diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 02af0d2d..1effba09 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -46,6 +46,9 @@ system_error = { path = "crates/system_error" } unified-init = { path = "crates/unified-init" } virtio-drivers = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/virtio-drivers.git", rev = "f1d1cbb" } fdt = "0.1.5" +uefi = { version = "0.26.0", features = ["alloc"] } +uefi-raw = "0.5.0" + # target为x86_64时,使用下面的依赖 [target.'cfg(target_arch = "x86_64")'.dependencies] @@ -56,7 +59,7 @@ x86_64 = "0.14.10" # target为riscv64时,使用下面的依赖 [target.'cfg(target_arch = "riscv64")'.dependencies] - +riscv = { version = "0.11.0", features = [ "s-mode" ] } # 构建时依赖项 diff --git a/kernel/crates/kdepends/Cargo.toml b/kernel/crates/kdepends/Cargo.toml index 25062aad..cde833db 100644 --- a/kernel/crates/kdepends/Cargo.toml +++ b/kernel/crates/kdepends/Cargo.toml @@ -12,7 +12,7 @@ crc = { path = "../crc" } # 一个无锁MPSC队列 [dependencies.thingbuf] -git = "https://git.mirrors.dragonos.org/DragonOS-Community/thingbuf.git" +git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/thingbuf.git" rev = "2dded730c3" default-features = false features = ["alloc", "static"] diff --git a/kernel/crates/system_error/Cargo.toml b/kernel/crates/system_error/Cargo.toml index b280b36d..ccca15c6 100644 --- a/kernel/crates/system_error/Cargo.toml +++ b/kernel/crates/system_error/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" [dependencies] kdepends = { path = "../kdepends" } -num-traits = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false } +num-traits = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false } num = { version = "0.4.0", default-features = false } num-derive = "0.3" \ No newline at end of file diff --git a/kernel/src/Makefile b/kernel/src/Makefile index fb7be7e9..ca7aa8a3 100644 --- a/kernel/src/Makefile +++ b/kernel/src/Makefile @@ -17,9 +17,9 @@ ifeq ($(UNWIND_ENABLE), yes) CFLAGS_UNWIND = -funwind-tables ifeq ($(ARCH), x86_64) LDFLAGS_UNWIND = --eh-frame-hdr -endif RUSTFLAGS_UNWIND = -Cforce-unwind-tables -Clink-arg=-Wl,eh_frame.ld endif +endif RUSTFLAGS = $(RUSTFLAGS_UNWIND) diff --git a/kernel/src/arch/riscv64/asm/head.S b/kernel/src/arch/riscv64/asm/head.S index e70ac0ba..5bdd75f9 100644 --- a/kernel/src/arch/riscv64/asm/head.S +++ b/kernel/src/arch/riscv64/asm/head.S @@ -92,7 +92,7 @@ __init_set_pgtable_loop_end: la a0, BSP_IDLE_STACK_SPACE mv sp, a0 - li t0, 32768 + li t0, 32752 // 预留16字节防止越界 add sp, sp, t0 .option pop /* @@ -330,6 +330,7 @@ __initial_hartid_ptr: .quad 0 // _start标签在启动时被加载到的物理地址 +.global __initial_start_load_paddr __initial_start_load_paddr: .quad 0 @@ -344,9 +345,11 @@ __initial_satp_mode: // 初始页表的空间(sv39模式的L0页表) .section .initial_pgtable_section +.global __initial_pgtable __initial_pgtable: .skip 4096 +.global __initial_l1_pgtable __initial_l1_pgtable: .skip 8192 diff --git a/kernel/src/arch/riscv64/driver/sbi/legacy.rs b/kernel/src/arch/riscv64/driver/sbi/legacy.rs index 0384db97..eda07dad 100644 --- a/kernel/src/arch/riscv64/driver/sbi/legacy.rs +++ b/kernel/src/arch/riscv64/driver/sbi/legacy.rs @@ -1,7 +1,5 @@ -use crate::{ - arch::driver::sbi::ecall::{ecall0, ecall1}, - mm::VirtAddr, -}; +#![allow(dead_code)] +use crate::{arch::driver::sbi::ecall::ecall1, mm::VirtAddr}; use core::arch::asm; /// `sbi_set_timer` extension ID diff --git a/kernel/src/arch/riscv64/init/mod.rs b/kernel/src/arch/riscv64/init/mod.rs index 5117e725..fd253813 100644 --- a/kernel/src/arch/riscv64/init/mod.rs +++ b/kernel/src/arch/riscv64/init/mod.rs @@ -3,10 +3,14 @@ use core::intrinsics::unreachable; use fdt::node::FdtNode; use crate::{ - driver::open_firmware::fdt::open_firmware_fdt_driver, + arch::{mm::init::mm_early_init, MMArch}, + driver::{ + firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver, + tty::serial::serial8250::send_to_default_serial8250_port, + }, init::{boot_params, init_before_mem_init}, - kinfo, - mm::{PhysAddr, VirtAddr}, + kdebug, kinfo, + mm::{MemoryManagementArch, PhysAddr, VirtAddr}, print, println, }; @@ -14,18 +18,36 @@ use crate::{ pub struct ArchBootParams { /// 启动时的fdt物理地址 pub fdt_paddr: PhysAddr, + pub fdt_vaddr: Option, } impl ArchBootParams { pub const DEFAULT: Self = ArchBootParams { fdt_paddr: PhysAddr::new(0), + fdt_vaddr: None, }; + + pub fn arch_fdt(&self) -> VirtAddr { + // 如果fdt_vaddr为None,则说明还没有进行内核虚拟地址空间的映射,此时返回物理地址 + if self.fdt_vaddr.is_none() { + return VirtAddr::new(self.fdt_paddr.data()); + } + self.fdt_vaddr.unwrap() + } } #[no_mangle] unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! { let fdt_paddr = PhysAddr::new(fdt_paddr); + init_before_mem_init(); + extern "C" { + fn BSP_IDLE_STACK_SPACE(); + } + kdebug!("BSP_IDLE_STACK_SPACE={:#x}", BSP_IDLE_STACK_SPACE as u64); + kdebug!("PAGE_ADDRESS_SIZE={}", MMArch::PAGE_ADDRESS_SIZE); + kdebug!("PAGE_ADDRESS_SHIFT={}", MMArch::PAGE_ADDRESS_SHIFT); + boot_params().write().arch.fdt_paddr = fdt_paddr; kinfo!( "DragonOS kernel is running on hart {}, fdt address:{:?}", @@ -33,15 +55,20 @@ unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! { fdt_paddr ); + mm_early_init(); + let fdt = fdt::Fdt::from_ptr(fdt_paddr.data() as *const u8).expect("Failed to parse fdt!"); print_node(fdt.find_node("/").unwrap(), 0); parse_dtb(); + efi_init(); + loop {} unreachable() } +#[inline(never)] fn print_node(node: FdtNode<'_, '_>, n_spaces: usize) { (0..n_spaces).for_each(|_| print!(" ")); println!("{}/", node.name); @@ -56,15 +83,13 @@ fn print_node(node: FdtNode<'_, '_>, n_spaces: usize) { } /// 解析fdt,获取内核启动参数 +#[inline(never)] unsafe fn parse_dtb() { let fdt_paddr = boot_params().read().arch.fdt_paddr; if fdt_paddr.is_null() { panic!("Failed to get fdt address!"); } - open_firmware_fdt_driver() - .set_fdt_vaddr(VirtAddr::new(fdt_paddr.data())) - .unwrap(); open_firmware_fdt_driver() .early_scan_device_tree() .expect("Failed to scan device tree at boottime."); diff --git a/kernel/src/arch/riscv64/interrupt/mod.rs b/kernel/src/arch/riscv64/interrupt/mod.rs index 5c18a310..ae1dbf62 100644 --- a/kernel/src/arch/riscv64/interrupt/mod.rs +++ b/kernel/src/arch/riscv64/interrupt/mod.rs @@ -6,23 +6,29 @@ pub struct RiscV64InterruptArch; impl InterruptArch for RiscV64InterruptArch { unsafe fn interrupt_enable() { - unimplemented!("RiscV64InterruptArch::interrupt_enable") + riscv::interrupt::enable(); } unsafe fn interrupt_disable() { - unimplemented!("RiscV64InterruptArch::interrupt_disable") + riscv::interrupt::disable(); } fn is_irq_enabled() -> bool { - unimplemented!("RiscV64InterruptArch::is_irq_enabled") + riscv::register::sstatus::read().sie() } unsafe fn save_and_disable_irq() -> IrqFlagsGuard { - unimplemented!("RiscV64InterruptArch::save_and_disable_irq") + let sie = riscv::register::sstatus::read().sie(); + IrqFlagsGuard::new(IrqFlags::new(sie.into())) } unsafe fn restore_irq(flags: IrqFlags) { - unimplemented!("RiscV64InterruptArch::restore_irq") + let sie: bool = flags.flags() != 0; + if sie { + riscv::register::sstatus::set_sie(); + } else { + riscv::register::sstatus::clear_sie(); + } } } diff --git a/kernel/src/arch/riscv64/link.ld b/kernel/src/arch/riscv64/link.ld index 99dcffd4..5d628f39 100644 --- a/kernel/src/arch/riscv64/link.ld +++ b/kernel/src/arch/riscv64/link.ld @@ -76,6 +76,8 @@ SECTIONS _bss = .; *(.bss) *(.bss.*) + *(.sbss) + *(.sbss.*) _ebss = .; } diff --git a/kernel/src/arch/riscv64/mm/init.rs b/kernel/src/arch/riscv64/mm/init.rs index 3d7b8ace..77245783 100644 --- a/kernel/src/arch/riscv64/mm/init.rs +++ b/kernel/src/arch/riscv64/mm/init.rs @@ -1,3 +1,55 @@ -use virtio_drivers::PhysAddr; +use system_error::SystemError; -pub fn setup_vm(dtb_paddr: PhysAddr) {} +use crate::{ + arch::{ + mm::{KERNEL_BEGIN_PA, KERNEL_BEGIN_VA, KERNEL_END_PA, KERNEL_END_VA}, + MMArch, + }, + kdebug, + mm::{ + allocator::page_frame::PageFrameCount, + no_init::{pseudo_map_phys, EARLY_IOREMAP_PAGES}, + page::{PageEntry, PageMapper, PageTable}, + MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, + }, +}; + +#[inline(never)] +pub fn mm_early_init() { + unsafe { init_kernel_addr() }; + // unsafe { map_initial_page_table_linearly() }; +} + +unsafe fn init_kernel_addr() { + extern "C" { + /// 内核起始label + fn boot_text_start_pa(); + /// 内核结束位置的label + fn _end(); + + fn _start(); + + /// 内核start标签被加载到的物理地址 + fn __initial_start_load_paddr(); + } + let initial_start_load_pa = *(__initial_start_load_paddr as usize as *const usize); + let offset = _start as usize - boot_text_start_pa as usize; + let start_pa = initial_start_load_pa - offset; + + let offset2 = _end as usize - boot_text_start_pa as usize; + let end_pa = start_pa + offset2; + + KERNEL_BEGIN_PA = PhysAddr::new(start_pa); + KERNEL_END_PA = PhysAddr::new(end_pa); + + KERNEL_BEGIN_VA = VirtAddr::new(boot_text_start_pa as usize); + KERNEL_END_VA = VirtAddr::new(_end as usize); + + kdebug!( + "init_kernel_addr: \n\tKERNEL_BEGIN_PA: {KERNEL_BEGIN_PA:?} + \tKERNEL_END_PA: {KERNEL_END_PA:?} + \tKERNEL_BEGIN_VA: {KERNEL_BEGIN_VA:?} + \tKERNEL_END_VA: {KERNEL_END_VA:?} + " + ); +} diff --git a/kernel/src/arch/riscv64/mm/mod.rs b/kernel/src/arch/riscv64/mm/mod.rs index aec63b7a..5f5d48d2 100644 --- a/kernel/src/arch/riscv64/mm/mod.rs +++ b/kernel/src/arch/riscv64/mm/mod.rs @@ -1,9 +1,13 @@ +use riscv::register::satp; use system_error::SystemError; -use crate::mm::{ - allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage}, - page::PageFlags, - MemoryManagementArch, PhysAddr, VirtAddr, +use crate::{ + kdebug, + mm::{ + allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame}, + page::PageFlags, + MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, + }, }; pub mod bump; @@ -11,6 +15,15 @@ pub(super) mod init; pub type PageMapper = crate::mm::page::PageMapper; +/// 内核起始物理地址 +pub(self) static mut KERNEL_BEGIN_PA: PhysAddr = PhysAddr::new(0); +/// 内核结束的物理地址 +pub(self) static mut KERNEL_END_PA: PhysAddr = PhysAddr::new(0); +/// 内核起始虚拟地址 +pub(self) static mut KERNEL_BEGIN_VA: VirtAddr = VirtAddr::new(0); +/// 内核结束虚拟地址 +pub(self) static mut KERNEL_END_VA: VirtAddr = VirtAddr::new(0); + /// RiscV64的内存管理架构结构体(sv39) #[derive(Debug, Clone, Copy, Hash)] pub struct RiscV64MMArch; @@ -62,24 +75,34 @@ impl MemoryManagementArch for RiscV64MMArch { todo!() } - unsafe fn invalidate_page(address: crate::mm::VirtAddr) { - todo!() + unsafe fn invalidate_page(address: VirtAddr) { + riscv::asm::sfence_vma(0, address.data()); } unsafe fn invalidate_all() { - todo!() + riscv::asm::sfence_vma_all(); } - unsafe fn table(table_kind: crate::mm::PageTableKind) -> crate::mm::PhysAddr { - todo!() + unsafe fn table(_table_kind: PageTableKind) -> PhysAddr { + // phys page number + let ppn = riscv::register::satp::read().ppn(); + + let paddr = PhysPageFrame::from_ppn(ppn).phys_address(); + + kdebug!("table(): {paddr:?}, ppn: {ppn}"); + + return paddr; } - unsafe fn set_table(table_kind: crate::mm::PageTableKind, table: crate::mm::PhysAddr) { - todo!() + unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) { + let ppn = PhysPageFrame::new(table).ppn(); + kdebug!("set_table(): {table:?}, ppn:{ppn}"); + riscv::asm::sfence_vma_all(); + satp::set(satp::Mode::Sv39, 0, ppn); } fn virt_is_valid(virt: crate::mm::VirtAddr) -> bool { - todo!() + virt.is_canonical() } fn initial_page_table() -> crate::mm::PhysAddr { @@ -89,6 +112,56 @@ impl MemoryManagementArch for RiscV64MMArch { fn setup_new_usermapper() -> Result { todo!() } + + unsafe fn phys_2_virt(phys: PhysAddr) -> Option { + // riscv的内核文件所占用的空间,由于重定位而导致不满足线性偏移量的关系 + // 因此这里需要特殊处理 + if phys >= KERNEL_BEGIN_PA && phys < KERNEL_END_PA { + let r = KERNEL_BEGIN_VA + (phys - KERNEL_BEGIN_PA); + return Some(r); + } + + if let Some(vaddr) = phys.data().checked_add(Self::PHYS_OFFSET) { + return Some(VirtAddr::new(vaddr)); + } else { + return None; + } + } + + unsafe fn virt_2_phys(virt: VirtAddr) -> Option { + if virt >= KERNEL_BEGIN_VA && virt < KERNEL_END_VA { + let r = KERNEL_BEGIN_PA + (virt - KERNEL_BEGIN_VA); + kdebug!("virt_2_phys: kernel address: virt = {virt:?}, paddr = {r:?}"); + return Some(r); + } + + if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) { + let r = PhysAddr::new(paddr); + kdebug!("virt_2_phys: non-kernel address: virt = {virt:?}, paddr = {r:?}"); + return Some(r); + } else { + return None; + } + } + + fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize { + let ppn = PhysPageFrame::new(paddr).ppn(); + let r = ((ppn & ((1 << 44) - 1)) << 10) | page_flags; + + kdebug!("make entry: r={r:#x}"); + return r; + } +} + +impl VirtAddr { + /// 判断虚拟地址是否合法 + #[inline(always)] + pub fn is_canonical(self) -> bool { + let x = self.data() & RiscV64MMArch::PHYS_OFFSET; + // 如果x为0,说明虚拟地址的高位为0,是合法的用户地址 + // 如果x为PHYS_OFFSET,说明虚拟地址的高位全为1,是合法的内核地址 + return x == 0 || x == RiscV64MMArch::PHYS_OFFSET; + } } /// 获取内核地址默认的页面标志 diff --git a/kernel/src/arch/x86_64/mm/mod.rs b/kernel/src/arch/x86_64/mm/mod.rs index ab50834a..618a0d34 100644 --- a/kernel/src/arch/x86_64/mm/mod.rs +++ b/kernel/src/arch/x86_64/mm/mod.rs @@ -284,6 +284,11 @@ impl MemoryManagementArch for X86_64MMArch { return None; } } + + #[inline(always)] + fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize { + return paddr.data() | page_flags; + } } impl X86_64MMArch { @@ -334,8 +339,6 @@ impl X86_64MMArch { } total_mem_size += mb2_mem_info[i].len as usize; - // PHYS_MEMORY_AREAS[areas_count].base = PhysAddr::new(mb2_mem_info[i].addr as usize); - // PHYS_MEMORY_AREAS[areas_count].size = mb2_mem_info[i].len as usize; mem_block_manager() .add_block( @@ -450,7 +453,7 @@ unsafe fn allocator_init() { // 取消最开始时候,在head.S中指定的映射(暂时不刷新TLB) { let table = mapper.table(); - let empty_entry = PageEntry::::new(0); + let empty_entry = PageEntry::::from_usize(0); for i in 0..MMArch::PAGE_ENTRY_NUM { table .set_entry(i, empty_entry) diff --git a/kernel/src/driver/firmware/efi/fdt.rs b/kernel/src/driver/firmware/efi/fdt.rs new file mode 100644 index 00000000..a286af89 --- /dev/null +++ b/kernel/src/driver/firmware/efi/fdt.rs @@ -0,0 +1,189 @@ +//! 与UEFI相关的fdt操作 + +use core::fmt::Debug; + +use fdt::Fdt; +use system_error::SystemError; + +use crate::init::boot_params; + +use super::EFIManager; + +// 由于代码涉及转换,因此这里每个的大小都是8字节 +#[derive(Default)] +pub struct EFIFdtParams { + // systable + pub systable: Option, + // mmap_base + pub mmap_base: Option, + // mmap_size + pub mmap_size: Option, + // mmap_desc_size + pub mmap_desc_size: Option, + // mmap_desc_version + pub mmap_desc_version: Option, +} + +impl Debug for EFIFdtParams { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + // 十六进制输出 + f.debug_struct("EFIFdtParams") + .field("systable", &format_args!("{:#x?}", self.systable)) + .field("mmap_base", &format_args!("{:#x?}", self.mmap_base)) + .field("mmap_size", &format_args!("{:#x?}", self.mmap_size)) + .field( + "mmap_desc_size", + &format_args!("{:#x?}", self.mmap_desc_size), + ) + .field( + "mmap_desc_version", + &format_args!("{:#x?}", self.mmap_desc_version), + ) + .finish() + } +} + +/// 要从FDT中获取的属性 +#[derive(Debug, Clone, Copy)] +enum FdtPropType { + SystemTable, + MMBase, + MMSize, + DescSize, + DescVersion, +} + +impl FdtPropType { + /// 获取属性对应的fdt属性名 + fn prop_name(&self) -> &'static str { + self.clone().into() + } +} + +impl Into<&'static str> for FdtPropType { + fn into(self) -> &'static str { + match self { + FdtPropType::SystemTable => "linux,uefi-system-table", + FdtPropType::MMBase => "linux,uefi-mmap-start", + FdtPropType::MMSize => "linux,uefi-mmap-size", + FdtPropType::DescSize => "linux,uefi-mmap-desc-size", + FdtPropType::DescVersion => "linux,uefi-mmap-desc-ver", + } + } +} + +impl TryFrom<&str> for FdtPropType { + type Error = SystemError; + + fn try_from(value: &str) -> Result { + match value { + "linux,uefi-system-table" => Ok(FdtPropType::SystemTable), + "linux,uefi-mmap-start" => Ok(FdtPropType::MMBase), + "linux,uefi-mmap-size" => Ok(FdtPropType::MMSize), + "linux,uefi-mmap-desc-size" => Ok(FdtPropType::DescSize), + "linux,uefi-mmap-desc-ver" => Ok(FdtPropType::DescVersion), + _ => Err(SystemError::EINVAL), + } + } +} + +struct ParamToRead { + /// FDT节点路径 + path: &'static str, + /// 当前节点下要读取的属性 + properties: &'static [FdtPropType], +} + +static PARAM_TO_READ: &[ParamToRead] = &[ParamToRead { + path: "/chosen", + properties: &[ + FdtPropType::SystemTable, + FdtPropType::MMBase, + FdtPropType::MMSize, + FdtPropType::DescSize, + FdtPropType::DescVersion, + ], +}]; + +impl EFIManager { + pub(super) fn get_fdt_params(&self) -> Result { + let fdt = unsafe { + Fdt::from_ptr( + boot_params() + .read() + .fdt() + .ok_or(SystemError::ENODEV)? + .data() as *const u8, + ) + } + .map_err(|e| { + kerror!("failed to parse fdt, err={:?}", e); + SystemError::EINVAL + })?; + + let mut ret = EFIFdtParams::default(); + + for param in PARAM_TO_READ { + let node = fdt.find_node(param.path); + if node.is_none() { + continue; + } + let node = node.unwrap(); + + for prop in param.properties { + let prop = node.property(prop.prop_name()); + if prop.is_none() { + continue; + } + let prop = prop.unwrap(); + let prop_type = FdtPropType::try_from(prop.name); + if prop_type.is_err() { + continue; + } + + let prop_type = prop_type.unwrap(); + + self.do_get_fdt_prop(prop_type, &prop, &mut ret) + .unwrap_or_else(|e| { + kerror!("Failed to get fdt prop: {prop_type:?}, error: {e:?}"); + }) + } + } + + return Ok(ret); + } + + fn do_get_fdt_prop( + &self, + prop_type: FdtPropType, + prop: &fdt::node::NodeProperty<'_>, + target: &mut EFIFdtParams, + ) -> Result<(), SystemError> { + let val: u64; + if prop.value.len() == 4 { + val = u32::from_be_bytes(prop.value[0..4].try_into().unwrap()) as u64; + } else { + val = u64::from_be_bytes(prop.value[0..8].try_into().unwrap()); + } + + match prop_type { + FdtPropType::SystemTable => { + target.systable = Some(val); + } + FdtPropType::MMBase => { + target.mmap_base = Some(val); + } + FdtPropType::MMSize => { + target.mmap_size = Some(val); + } + FdtPropType::DescSize => { + target.mmap_desc_size = Some(val); + } + FdtPropType::DescVersion => { + target.mmap_desc_version = Some(val); + } + } + + return Ok(()); + } +} diff --git a/kernel/src/driver/firmware/efi/init.rs b/kernel/src/driver/firmware/efi/init.rs new file mode 100644 index 00000000..1efdb525 --- /dev/null +++ b/kernel/src/driver/firmware/efi/init.rs @@ -0,0 +1,129 @@ +use core::{intrinsics::unlikely, mem::size_of}; + +use system_error::SystemError; + +use crate::{ + driver::firmware::efi::EFIInitFlags, + libs::align::page_align_down, + mm::{early_ioremap::EarlyIoRemap, PhysAddr, VirtAddr}, +}; + +use super::efi_manager; + +#[allow(dead_code)] +#[inline(never)] +pub fn efi_init() { + let data_from_fdt = efi_manager() + .get_fdt_params() + .expect("Failed to get fdt params"); + + if data_from_fdt.systable.is_none() { + kerror!("Failed to get systable from fdt"); + return; + } + + kdebug!("to map memory table"); + + // 映射mmap table + if efi_manager().memmap_init_early(&data_from_fdt).is_err() { + // 如果我们通过UEFI进行引导, + // 那么 UEFI memory map 就是我们拥有的关于内存的唯一描述, + // 所以如果我们无法访问它,那么继续进行下去就没有什么意义了 + + kerror!("Failed to initialize early memory map"); + loop {} + } + // kdebug!("NNNN"); + // kwarn!("BBBB, e:{:?}", SystemError::EINVAL); + + let desc_version = efi_manager().desc_version(); + + if unlikely(desc_version != 1) { + kwarn!("Unexpected EFI memory map version: {}", desc_version); + } + + // todo: 映射table,初始化runtime services + + let r = uefi_init(PhysAddr::new(data_from_fdt.systable.unwrap() as usize)); + + if let Err(r) = r { + kerror!("Failed to initialize UEFI: {:?}", r); + } + + loop {} +} + +#[inline(never)] +fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> { + // 定义错误处理函数 + + // 错误处理:取消systable的映射 + let err_unmap_systable = |st_vaddr: VirtAddr| { + EarlyIoRemap::unmap(st_vaddr) + .map_err(|e| { + kerror!("Failed to unmap system table: {e:?}"); + }) + .ok(); + }; + + // 映射system table + + let st_size = size_of::(); + kdebug!("system table: {system_table:?}, size: {st_size}"); + let st_map_phy_base = PhysAddr::new(page_align_down(system_table.data())); + + let st_map_offset = system_table.data() - st_map_phy_base.data(); + let st_map_size = st_size + st_map_offset; + let (st_vaddr, _st_map_size) = + EarlyIoRemap::map(st_map_phy_base, st_map_size, true).map_err(|e| { + kwarn!("Unable to map EFI system table, e:{e:?}"); + e + })?; + + let st_vaddr = st_vaddr + st_map_offset; + + efi_manager() + .inner + .write() + .init_flags + .set(EFIInitFlags::BOOT, true); + + efi_manager() + .inner + .write() + .init_flags + .set(EFIInitFlags::EFI_64BIT, true); + + kdebug!("to parse EFI system table: p: {st_vaddr:?}"); + + if st_vaddr.is_null() { + return Err(SystemError::EINVAL); + } + + // 解析system table + let st_ptr = st_vaddr.data() as *const uefi_raw::table::system::SystemTable; + efi_manager() + .check_system_table_header(unsafe { &st_ptr.as_ref().unwrap().header }, 2) + .map_err(|e| { + err_unmap_systable(st_vaddr); + e + })?; + + kdebug!("parse ok!"); + let mut inner_write_guard = efi_manager().inner.write(); + let st_ref = unsafe { st_ptr.as_ref().unwrap() }; + inner_write_guard.runtime_paddr = Some(PhysAddr::new(st_ref.runtime_services as usize)); + inner_write_guard.runtime_service_version = Some(st_ref.header.revision); + + kdebug!( + "runtime service paddr: {:?}", + inner_write_guard.runtime_paddr.unwrap() + ); + kdebug!( + "runtime service version: {}", + inner_write_guard.runtime_service_version.unwrap() + ); + + unimplemented!("report header"); + // return Ok(()); +} diff --git a/kernel/src/driver/firmware/efi/memmap.rs b/kernel/src/driver/firmware/efi/memmap.rs new file mode 100644 index 00000000..86f305ae --- /dev/null +++ b/kernel/src/driver/firmware/efi/memmap.rs @@ -0,0 +1,100 @@ +use system_error::SystemError; + +use crate::{ + driver::firmware::efi::EFIInitFlags, + libs::align::page_align_down, + mm::{early_ioremap::EarlyIoRemap, PhysAddr, VirtAddr}, +}; + +use super::{fdt::EFIFdtParams, EFIManager}; + +#[derive(Debug)] +pub struct EFIMemoryMapInfo { + /// EFI Memory Map的物理地址 + pub(super) paddr: Option, + /// EFI Memory Map的虚拟地址 + pub(super) vaddr: Option, + /// EFI Memory Map的大小 + pub(super) size: usize, + /// 映射的描述信息的数量 + pub(super) nr_map: usize, + /// EFI Memory Map的描述信息的大小 + pub(super) desc_size: usize, + /// EFI Memory Map的描述信息的版本 + pub(super) desc_version: usize, +} + +impl EFIMemoryMapInfo { + pub const DEFAULT: Self = EFIMemoryMapInfo { + paddr: None, + vaddr: None, + size: 0, + nr_map: 0, + desc_size: 0, + desc_version: 0, + }; + + /// 获取EFI Memory Map的虚拟的结束地址 + #[allow(dead_code)] + pub fn map_end_vaddr(&self) -> Option { + return self.vaddr.map(|v| v + self.size); + } +} + +impl EFIManager { + /// Map the EFI memory map data structure + /// + /// 进入当前函数前,不应持有efi_manager.inner的锁 + #[inline(never)] + pub(super) fn memmap_init_early(&self, data: &EFIFdtParams) -> Result<(), SystemError> { + return self.do_efi_memmap_init(data, true); + } + + /// 映射 EFI memory map + /// + /// 该函数在内核启动过程中使用 + /// + /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/memmap.c?fi=efi_memmap_init_early#104 + #[inline(never)] + fn do_efi_memmap_init(&self, data: &EFIFdtParams, early: bool) -> Result<(), SystemError> { + let paddr = data.mmap_base.expect("mmap_base is not set"); + let paddr = PhysAddr::new(paddr as usize); + kdebug!("do_efi_memmap_init: paddr={paddr:?}"); + let mut inner_guard = self.inner.write(); + if early { + let offset = paddr.data() - page_align_down(paddr.data()); + let map_size = data.mmap_size.unwrap() as usize + offset; + + kdebug!("do_efi_memmap_init: map_size={map_size:#x}"); + // 映射内存 + let mut vaddr = EarlyIoRemap::map( + PhysAddr::new(page_align_down(paddr.data())), + map_size, + false, + ) + .map(|(vaddr, _)| vaddr)?; + + vaddr += offset; + + inner_guard.mmap.vaddr = Some(vaddr); + } else { + unimplemented!("efi_memmap_init_late") + } + + if inner_guard.mmap.vaddr.is_none() { + kerror!("Cannot map the EFI memory map!"); + return Err(SystemError::ENOMEM); + } + + inner_guard.mmap.paddr = Some(paddr); + inner_guard.mmap.size = data.mmap_size.unwrap() as usize; + inner_guard.mmap.nr_map = + data.mmap_size.unwrap() as usize / data.mmap_desc_size.unwrap() as usize; + inner_guard.mmap.desc_size = data.mmap_desc_size.unwrap() as usize; + inner_guard.mmap.desc_version = data.mmap_desc_version.unwrap() as usize; + + inner_guard.init_flags.set(EFIInitFlags::MEMMAP, true); + + return Ok(()); + } +} diff --git a/kernel/src/driver/firmware/efi/mod.rs b/kernel/src/driver/firmware/efi/mod.rs new file mode 100644 index 00000000..86a91e6e --- /dev/null +++ b/kernel/src/driver/firmware/efi/mod.rs @@ -0,0 +1,115 @@ +use system_error::SystemError; + +use crate::{libs::rwlock::RwLock, mm::PhysAddr}; + +use self::memmap::EFIMemoryMapInfo; + +mod fdt; +pub mod init; +pub mod memmap; + +static EFI_MANAGER: EFIManager = EFIManager::new(); + +/// EFI管理器 +/// +/// 数据成员可参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/efi.h#620 +#[derive(Debug)] +pub struct EFIManager { + inner: RwLock, +} + +#[inline(always)] +pub fn efi_manager() -> &'static EFIManager { + &EFI_MANAGER +} + +#[derive(Debug)] +struct InnerEFIManager { + pub mmap: EFIMemoryMapInfo, + /// EFI模块启动时状态的标识 + pub init_flags: EFIInitFlags, + /// runtime services的物理地址 + pub runtime_paddr: Option, + /// runtime services的版本号 + pub runtime_service_version: Option, +} + +impl EFIManager { + const fn new() -> Self { + EFIManager { + inner: RwLock::new(InnerEFIManager { + mmap: EFIMemoryMapInfo::DEFAULT, + init_flags: EFIInitFlags::empty(), + runtime_paddr: None, + runtime_service_version: None, + }), + } + } + + pub fn desc_version(&self) -> usize { + return self.inner.read().mmap.desc_version; + } + + /// 检查是否为有效的system table表头 + /// + /// ## 参数 + /// + /// - header: system table表头 + /// - min_major: 最小的major版本号。如果不满足,则会输出Warning,并返回Ok + /// + /// ## 返回 + /// + /// - Ok(()): 检查通过 + /// - Err(SystemError::EINVAL): header无效 + pub fn check_system_table_header( + &self, + header: &uefi_raw::table::Header, + min_major: u16, + ) -> Result<(), SystemError> { + if header.signature != uefi_raw::table::system::SystemTable::SIGNATURE { + kerror!("System table signature mismatch!"); + return Err(SystemError::EINVAL); + } + + if header.revision.major() < min_major { + kwarn!( + "System table version: {:?}, expected {}.00 or greater!", + header.revision, + min_major + ); + } + + return Ok(()); + } +} + +// 在Rust中,我们使用枚举和bitflags来表示这些宏 +bitflags! { + pub struct EFIInitFlags: u32 { + /// 当前使用EFI启动 + const BOOT = 1 << 0; + /// 是否可以使用EFI配置表 + const CONFIG_TABLES = 1 << 1; + /// 是否可以使用运行时服务 + const RUNTIME_SERVICES = 1 << 2; + /// 是否可以使用EFI内存映射 + const MEMMAP = 1 << 3; + /// 固件是否为64位 + const EFI_64BIT = 1 << 4; + /// 访问是否通过虚拟化接口 + const PARAVIRT = 1 << 5; + /// 第一架构特定位 + const ARCH_1 = 1 << 6; + /// 打印附加运行时调试信息 + const DBG = 1 << 7; + /// 是否可以在运行时数据区域映射非可执行 + const NX_PE_DATA = 1 << 8; + /// 固件是否发布了一个EFI_MEMORY_ATTRIBUTES表 + const MEM_ATTR = 1 << 9; + /// 内核是否配置为忽略软保留 + const MEM_NO_SOFT_RESERVE = 1 << 10; + /// 是否可以使用EFI引导服务内存段 + const PRESERVE_BS_REGIONS = 1 << 11; + + } +} diff --git a/kernel/src/driver/firmware/mod.rs b/kernel/src/driver/firmware/mod.rs new file mode 100644 index 00000000..c03d4128 --- /dev/null +++ b/kernel/src/driver/firmware/mod.rs @@ -0,0 +1 @@ +pub mod efi; diff --git a/kernel/src/driver/mod.rs b/kernel/src/driver/mod.rs index 0c8c9aac..0a8a5608 100644 --- a/kernel/src/driver/mod.rs +++ b/kernel/src/driver/mod.rs @@ -1,6 +1,7 @@ pub mod acpi; pub mod base; pub mod disk; +pub mod firmware; pub mod input; pub mod keyboard; pub mod net; diff --git a/kernel/src/driver/open_firmware/fdt.rs b/kernel/src/driver/open_firmware/fdt.rs index 7ec6027f..e95fc9ee 100644 --- a/kernel/src/driver/open_firmware/fdt.rs +++ b/kernel/src/driver/open_firmware/fdt.rs @@ -10,7 +10,7 @@ use crate::{ libs::{align::page_align_down, rwlock::RwLock}, mm::{ memblock::{mem_block_manager, MemBlockManager}, - MemoryManagementArch, PhysAddr, VirtAddr, + MemoryManagementArch, PhysAddr, }, }; @@ -42,13 +42,11 @@ impl FdtGlobalData { } } -static mut FDT_VADDR: Option = None; - pub struct OpenFirmwareFdtDriver; impl OpenFirmwareFdtDriver { pub fn early_scan_device_tree(&self) -> Result<(), SystemError> { - let fdt_vaddr = unsafe { FDT_VADDR.ok_or(SystemError::EINVAL)? }; + let fdt_vaddr = boot_params().read().fdt().unwrap(); let fdt = unsafe { fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| { kerror!("failed to parse fdt, err={:?}", e); @@ -281,20 +279,4 @@ impl OpenFirmwareFdtDriver { return false; } - - pub unsafe fn set_fdt_vaddr(&self, vaddr: VirtAddr) -> Result<(), SystemError> { - if vaddr.is_null() { - return Err(SystemError::EINVAL); - } - fdt::Fdt::from_ptr(vaddr.as_ptr()).map_err(|e| { - kerror!("failed to parse fdt, err={:?}", e); - SystemError::EINVAL - })?; - - unsafe { - FDT_VADDR = Some(vaddr); - } - - Ok(()) - } } diff --git a/kernel/src/driver/video/fbdev/mod.rs b/kernel/src/driver/video/fbdev/mod.rs index 44ea30c2..714c63d7 100644 --- a/kernel/src/driver/video/fbdev/mod.rs +++ b/kernel/src/driver/video/fbdev/mod.rs @@ -1,2 +1,3 @@ pub mod base; +#[cfg(target_arch = "x86_64")] pub mod vesafb; diff --git a/kernel/src/init/mod.rs b/kernel/src/init/mod.rs index a2a65bfa..c2109892 100644 --- a/kernel/src/init/mod.rs +++ b/kernel/src/init/mod.rs @@ -7,6 +7,7 @@ use crate::{ video::{fbdev::base::BootTimeScreenInfo, VideoRefreshManager}, }, libs::{lib_ui::screen_manager::scm_init, rwlock::RwLock}, + mm::VirtAddr, }; mod c_adapter; @@ -27,6 +28,7 @@ fn init_intertrait() { } /// 在内存管理初始化之前,执行的初始化 +#[inline(never)] pub fn init_before_mem_init() { tty_early_init().expect("tty early init failed"); let video_ok = unsafe { VideoRefreshManager::video_init().is_ok() }; @@ -99,4 +101,14 @@ impl BootParams { self.boot_command_line[pos + len] = 0; } + + /// 获取FDT的物理地址 + #[allow(dead_code)] + pub fn fdt(&self) -> Option { + #[cfg(target_arch = "riscv64")] + return Some(self.arch.arch_fdt()); + + #[cfg(target_arch = "x86_64")] + return None; + } } diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 36070872..8a47c2bb 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -74,6 +74,8 @@ extern crate intertrait; extern crate x86; extern crate klog_types; +extern crate uefi; +extern crate uefi_raw; use crate::mm::allocator::kernel_allocator::KernelAllocator; diff --git a/kernel/src/mm/allocator/page_frame.rs b/kernel/src/mm/allocator/page_frame.rs index db8ba699..576cdaf8 100644 --- a/kernel/src/mm/allocator/page_frame.rs +++ b/kernel/src/mm/allocator/page_frame.rs @@ -23,6 +23,16 @@ impl PhysPageFrame { }; } + /// 从物理页号创建PhysPageFrame结构体 + pub fn from_ppn(ppn: usize) -> Self { + return Self { number: ppn }; + } + + /// 获取当前页对应的物理页号 + pub fn ppn(&self) -> usize { + return self.number; + } + /// @brief 获取当前页对应的物理地址 pub fn phys_address(&self) -> PhysAddr { return PhysAddr::new(self.number * MMArch::PAGE_SIZE); @@ -87,6 +97,12 @@ impl VirtPageFrame { }; } + /// 从虚拟页号创建PhysPageFrame结构体 + #[allow(dead_code)] + pub fn from_vpn(vpn: usize) -> Self { + return Self { number: vpn }; + } + /// 获取当前虚拟页对应的虚拟地址 pub fn virt_address(&self) -> VirtAddr { return VirtAddr::new(self.number * MMArch::PAGE_SIZE); diff --git a/kernel/src/mm/early_ioremap.rs b/kernel/src/mm/early_ioremap.rs index 5acbc444..1b579a63 100644 --- a/kernel/src/mm/early_ioremap.rs +++ b/kernel/src/mm/early_ioremap.rs @@ -3,7 +3,7 @@ use system_error::SystemError; use crate::{ arch::MMArch, libs::{align::page_align_up, spinlock::SpinLock}, - mm::no_init::{pseudo_map_phys, pseudo_unmap_phys}, + mm::no_init::{pseudo_map_phys, pseudo_map_phys_ro, pseudo_unmap_phys}, }; use super::{allocator::page_frame::PageFrameCount, MemoryManagementArch, PhysAddr, VirtAddr}; @@ -34,6 +34,7 @@ impl EarlyIoRemap { /// /// - phys: 物理内存地址(需要按页对齐) /// - size: 映射的内存大小 + /// - read_only: 映射区与是否只读 /// /// ## 返回值 /// @@ -41,11 +42,17 @@ impl EarlyIoRemap { /// - Err(SystemError::ENOMEM): 可用的slot不足 /// - Err(SystemError::EINVAL): 传入的物理地址没有对齐 #[allow(dead_code)] - pub fn map(phys: PhysAddr, size: usize) -> Result<(VirtAddr, usize), SystemError> { + pub fn map( + phys: PhysAddr, + size: usize, + read_only: bool, + ) -> Result<(VirtAddr, usize), SystemError> { if phys.check_aligned(MMArch::PAGE_SIZE) == false { return Err(SystemError::EINVAL); } + // kdebug!("Early io remap:{phys:?}, size:{size}"); + let mut slot_guard = SLOTS.lock(); let slot_count = PageFrameCount::from_bytes(page_align_up(size)) @@ -72,8 +79,17 @@ impl EarlyIoRemap { let start_slot = start_slot.ok_or(SystemError::ENOMEM)?; let vaddr = Self::idx_to_virt(start_slot); + + // kdebug!("start_slot:{start_slot}, vaddr: {vaddr:?}, slot_count: {slot_count:?}"); + let page_count = PageFrameCount::new(slot_count); // 执行映射 - unsafe { pseudo_map_phys(vaddr, phys, PageFrameCount::new(slot_count)) } + if read_only { + unsafe { pseudo_map_phys_ro(vaddr, phys, page_count) } + } else { + unsafe { pseudo_map_phys(vaddr, phys, page_count) } + } + + // kdebug!("map ok"); // 更新slot信息 let map_size = slot_count * MMArch::PAGE_SIZE; @@ -141,7 +157,7 @@ impl EarlyIoRemap { *slot = Slot::DEFAULT; } - todo!() + return Ok(()); } /// 把slot下标转换为这个slot对应的虚拟地址 diff --git a/kernel/src/mm/mod.rs b/kernel/src/mm/mod.rs index 531f88f9..be32aaab 100644 --- a/kernel/src/mm/mod.rs +++ b/kernel/src/mm/mod.rs @@ -76,7 +76,8 @@ pub enum PageTableKind { User, /// 内核页表 Kernel, - /// 内存虚拟化中使用的EPT + /// x86内存虚拟化中使用的EPT + #[cfg(target_arch = "x86_64")] EPT, } @@ -511,6 +512,20 @@ pub trait MemoryManagementArch: Clone + Copy + Debug { /// 初始化新的usermapper,为用户进程创建页表 fn setup_new_usermapper() -> Result; + + /// 创建页表项 + /// + /// 这是一个低阶api,用于根据物理地址以及指定好的pageflags,创建页表项 + /// + /// ## 参数 + /// + /// - `paddr` 物理地址 + /// - `page_flags` 页表项的flags + /// + /// ## 返回值 + /// + /// 页表项的值 + fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize; } /// @brief 虚拟地址范围 diff --git a/kernel/src/mm/no_init.rs b/kernel/src/mm/no_init.rs index 111346d1..be115bcc 100644 --- a/kernel/src/mm/no_init.rs +++ b/kernel/src/mm/no_init.rs @@ -24,7 +24,8 @@ use super::{ }; /// 用于存储重映射页表的位图和页面 -static EARLY_IOREMAP_PAGES: SpinLock = SpinLock::new(EarlyIoRemapPages::new()); +pub static EARLY_IOREMAP_PAGES: SpinLock = + SpinLock::new(EarlyIoRemapPages::new()); /// 早期重映射使用的页表 #[repr(C)] @@ -42,7 +43,7 @@ impl EarlyRemapPage { } #[repr(C)] -struct EarlyIoRemapPages { +pub struct EarlyIoRemapPages { pages: [EarlyRemapPage; Self::EARLY_REMAP_PAGES_NUM], bmp: StaticBitmap<{ Self::EARLY_REMAP_PAGES_NUM }>, } @@ -110,12 +111,14 @@ impl FrameAllocator for PseudoAllocator { assert!(count.data() == 1); let vaddr = EARLY_IOREMAP_PAGES.lock_irqsave().allocate_page()?; let paddr = MMA::virt_2_phys(vaddr)?; + kdebug!("allocate page: vaddr={:?}, paddr={:?}", vaddr, paddr); return Some((paddr, count)); } unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount) { assert_eq!(count.data(), 1); assert!(address.check_aligned(MMA::PAGE_SIZE)); + kdebug!("free page: paddr={:?}", address); let vaddr = MMA::phys_2_virt(address); if let Some(vaddr) = vaddr { EARLY_IOREMAP_PAGES.lock_irqsave().free_page(vaddr); @@ -139,6 +142,27 @@ impl FrameAllocator for PseudoAllocator { /// 并且,内核引导文件必须以4K页为粒度,填写了前100M的内存映射关系。(具体以本文件开头的注释为准) #[inline(never)] pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) { + let flags: PageFlags = PageFlags::new().set_write(true).set_execute(true); + + pseudo_map_phys_with_flags(vaddr, paddr, count, flags); +} + +/// Use pseudo mapper to map physical memory to virtual memory +/// with READ_ONLY and EXECUTE flags. +#[inline(never)] +pub unsafe fn pseudo_map_phys_ro(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) { + let flags: PageFlags = PageFlags::new().set_write(false).set_execute(true); + + pseudo_map_phys_with_flags(vaddr, paddr, count, flags); +} + +#[inline(never)] +pub unsafe fn pseudo_map_phys_with_flags( + vaddr: VirtAddr, + paddr: PhysAddr, + count: PageFrameCount, + flags: PageFlags, +) { assert!(vaddr.check_aligned(MMArch::PAGE_SIZE)); assert!(paddr.check_aligned(MMArch::PAGE_SIZE)); @@ -150,12 +174,11 @@ pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrame &mut pseudo_allocator, ); - let flags: PageFlags = PageFlags::new().set_write(true).set_execute(true); - for i in 0..count.data() { let vaddr = vaddr + i * MMArch::PAGE_SIZE; let paddr = paddr + i * MMArch::PAGE_SIZE; - let flusher = mapper.map_phys(vaddr, paddr, flags).unwrap(); + let flusher: crate::mm::page::PageFlush = + mapper.map_phys(vaddr, paddr, flags).unwrap(); flusher.ignore(); } diff --git a/kernel/src/mm/page.rs b/kernel/src/mm/page.rs index 551eec74..d7c86714 100644 --- a/kernel/src/mm/page.rs +++ b/kernel/src/mm/page.rs @@ -102,7 +102,7 @@ impl PageTable { /// 获取当前页表的第i个页表项 pub unsafe fn entry(&self, i: usize) -> Option> { let entry_virt = self.entry_virt(i)?; - return Some(PageEntry::new(Arch::read::(entry_virt))); + return Some(PageEntry::from_usize(Arch::read::(entry_virt))); } /// 设置当前页表的第i个页表项 @@ -178,7 +178,14 @@ impl Debug for PageEntry { impl PageEntry { #[inline(always)] - pub fn new(data: usize) -> Self { + pub fn new(paddr: PhysAddr, flags: PageFlags) -> Self { + Self { + data: MMArch::make_entry(paddr, flags.data()), + phantom: PhantomData, + } + } + #[inline(always)] + pub fn from_usize(data: usize) -> Self { Self { data, phantom: PhantomData, @@ -198,7 +205,18 @@ impl PageEntry { /// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址 #[inline(always)] pub fn address(&self) -> Result { - let paddr = PhysAddr::new(self.data & Arch::PAGE_ADDRESS_MASK); + let paddr: PhysAddr = { + #[cfg(target_arch = "x86_64")] + { + PhysAddr::new(self.data & Arch::PAGE_ADDRESS_MASK) + } + + #[cfg(target_arch = "riscv64")] + { + let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 44) - 1); + super::allocator::page_frame::PhysPageFrame::from_ppn(ppn).phys_address() + } + }; if self.present() { Ok(paddr) @@ -290,7 +308,18 @@ impl PageFlags { #[inline(always)] pub fn new_page_table(user: bool) -> Self { return unsafe { - let r = Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE); + let r = { + #[cfg(target_arch = "x86_64")] + { + Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE) + } + + #[cfg(target_arch = "riscv64")] + { + // riscv64指向下一级页表的页表项,不应设置R/W/X权限位 + Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE) + } + }; if user { r.set_user(true) } else { @@ -355,10 +384,22 @@ impl PageFlags { #[must_use] #[inline(always)] pub fn set_write(self, value: bool) -> Self { - // 有的架构同时具有可写和不可写的标志位,因此需要同时更新 - return self - .update_flags(Arch::ENTRY_FLAG_READONLY, !value) - .update_flags(Arch::ENTRY_FLAG_READWRITE, value); + #[cfg(target_arch = "x86_64")] + { + // 有的架构同时具有可写和不可写的标志位,因此需要同时更新 + return self + .update_flags(Arch::ENTRY_FLAG_READONLY, !value) + .update_flags(Arch::ENTRY_FLAG_READWRITE, value); + } + + #[cfg(target_arch = "riscv64")] + { + if value { + return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true); + } else { + return self.update_flags(Arch::ENTRY_FLAG_READONLY, true); + } + } } /// 当前页表项是否可写 @@ -569,12 +610,13 @@ impl PageMapper { ); return None; } + let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK)); // TODO: 验证flags是否合法 // 创建页表项 - let entry = PageEntry::new(phys.data() | flags.data()); + let entry = PageEntry::new(phys, flags); let mut table = self.table(); loop { let i = table.index_of(virt)?; @@ -585,8 +627,9 @@ impl PageMapper { if table.entry_mapped(i)? == true { kwarn!("Page {:?} already mapped", virt); } - // kdebug!("Mapping {:?} to {:?}, i = {i}, entry={:?}, flags={:?}", virt, phys, entry, flags); + compiler_fence(Ordering::SeqCst); + table.set_entry(i, entry); compiler_fence(Ordering::SeqCst); return Some(PageFlush::new(virt)); @@ -596,27 +639,20 @@ impl PageMapper { table = next_table; // kdebug!("Mapping {:?} to next level table...", virt); } else { - // kdebug!("Allocating next level table for {:?}..., i={i}", virt); // 分配下一级页表 let frame = self.frame_allocator.allocate_one()?; + // 清空这个页帧 MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE); // 设置页表项的flags - // let flags = Arch::ENTRY_FLAG_READWRITE - // | Arch::ENTRY_FLAG_DEFAULT_TABLE - // | if virt.kind() == PageTableKind::User { - // Arch::ENTRY_FLAG_USER - // } else { - // 0 - // }; - let flags: PageFlags = + let flags: PageFlags = PageFlags::new_page_table(virt.kind() == PageTableKind::User); // kdebug!("Flags: {:?}", flags); // 把新分配的页表映射到当前页表 - table.set_entry(i, PageEntry::new(frame.data() | flags.data())); + table.set_entry(i, PageEntry::new(frame, flags)); // 获取新分配的页表 table = table.next_level_table(i)?; @@ -765,7 +801,7 @@ unsafe fn unmap_phys_inner( // 如果当前是最后一级页表,直接取消页面映射 if table.level() == 0 { let entry = table.entry(i)?; - table.set_entry(i, PageEntry::new(0)); + table.set_entry(i, PageEntry::from_usize(0)); return Some((entry.address().ok()?, entry.flags())); } @@ -784,7 +820,7 @@ unsafe fn unmap_phys_inner( .any(|e| e.present()); if !x { // 如果没有,就取消子页表的映射 - table.set_entry(i, PageEntry::new(0)); + table.set_entry(i, PageEntry::from_usize(0)); // 释放子页表 allocator.free_one(subtable.phys()); } diff --git a/kernel/submodules/DragonStub b/kernel/submodules/DragonStub index 7fc3806d..773f7fd3 160000 --- a/kernel/submodules/DragonStub +++ b/kernel/submodules/DragonStub @@ -1 +1 @@ -Subproject commit 7fc3806da73be059540a79b6fdddf8049be250f3 +Subproject commit 773f7fd31fb85ce22f0fc442fd2c13a8d0602a8c diff --git a/tools/debugging/logmonitor/Cargo.toml b/tools/debugging/logmonitor/Cargo.toml index d2b6d585..080fd01f 100644 --- a/tools/debugging/logmonitor/Cargo.toml +++ b/tools/debugging/logmonitor/Cargo.toml @@ -12,6 +12,6 @@ ratatui = "0.24.0" clap = { version = "4.4.7", features = ["color", "error-context", "help", "std", "suggestions", "usage", "derive"] } rand = "0.8.5" goblin = "0.7.1" -simple_logger = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/rust-simple_logger.git", "rev" = "36ab404868" } +simple_logger = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/rust-simple_logger.git", "rev" = "36ab404868" } log = "0.4.20" lazy_static = "1.4.0"