瀏覽代碼

riscv64: 映射uefi systemtable,并完善了riscv64页表填写的部分内容 (#498)

* 从fdt的chosen段获取几个需要的字段

* merge patch-early-ioremap

* feature: 增加early io remap的fixmap功能

允许在内存管理初始化之前,使用fixmap功能,映射一些物理内存,并记录.

* riscv64: 映射uefi systemtable,并完善了riscv64页表填写的部分内容

* 更新仓库网址
LoGin 1 年之前
父節點
當前提交
7a29d4fcbc

+ 4 - 1
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" ] }
 
 
 # 构建时依赖项

+ 1 - 1
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"]

+ 1 - 1
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"

+ 1 - 1
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)
 

+ 4 - 1
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
 

+ 2 - 4
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

+ 31 - 6
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<VirtAddr>,
 }
 
 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.");

+ 11 - 5
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();
+        }
     }
 }
 

+ 2 - 0
kernel/src/arch/riscv64/link.ld

@@ -76,6 +76,8 @@ SECTIONS
 		_bss = .;
 		*(.bss)
 		*(.bss.*)
+		*(.sbss)
+		*(.sbss.*)
 		_ebss = .;
 	}
 

+ 54 - 2
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:?}
+    "
+    );
+}

+ 85 - 12
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<RiscV64MMArch, LockedFrameAllocator>;
 
+/// 内核起始物理地址
+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<crate::mm::ucontext::UserMapper, SystemError> {
         todo!()
     }
+
+    unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> {
+        // 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<PhysAddr> {
+        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;
+    }
 }
 
 /// 获取内核地址默认的页面标志

+ 6 - 3
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::<MMArch>::new(0);
+            let empty_entry = PageEntry::<MMArch>::from_usize(0);
             for i in 0..MMArch::PAGE_ENTRY_NUM {
                 table
                     .set_entry(i, empty_entry)

+ 189 - 0
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<u64>,
+    // mmap_base
+    pub mmap_base: Option<u64>,
+    // mmap_size
+    pub mmap_size: Option<u64>,
+    // mmap_desc_size
+    pub mmap_desc_size: Option<u64>,
+    // mmap_desc_version
+    pub mmap_desc_version: Option<u64>,
+}
+
+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<Self, Self::Error> {
+        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<EFIFdtParams, SystemError> {
+        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(());
+    }
+}

+ 129 - 0
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::<uefi_raw::table::system::SystemTable>();
+    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(());
+}

+ 100 - 0
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<PhysAddr>,
+    /// EFI Memory Map的虚拟地址
+    pub(super) vaddr: Option<VirtAddr>,
+    /// 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<VirtAddr> {
+        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(());
+    }
+}

+ 115 - 0
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<InnerEFIManager>,
+}
+
+#[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<PhysAddr>,
+    /// runtime services的版本号
+    pub runtime_service_version: Option<uefi_raw::table::Revision>,
+}
+
+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;
+
+    }
+}

+ 1 - 0
kernel/src/driver/firmware/mod.rs

@@ -0,0 +1 @@
+pub mod efi;

+ 1 - 0
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;

+ 2 - 20
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<VirtAddr> = 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(())
-    }
 }

+ 1 - 0
kernel/src/driver/video/fbdev/mod.rs

@@ -1,2 +1,3 @@
 pub mod base;
+#[cfg(target_arch = "x86_64")]
 pub mod vesafb;

+ 12 - 0
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<VirtAddr> {
+        #[cfg(target_arch = "riscv64")]
+        return Some(self.arch.arch_fdt());
+
+        #[cfg(target_arch = "x86_64")]
+        return None;
+    }
 }

+ 2 - 0
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;
 

+ 16 - 0
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);

+ 20 - 4
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对应的虚拟地址

+ 16 - 1
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<UserMapper, SystemError>;
+
+    /// 创建页表项
+    ///
+    /// 这是一个低阶api,用于根据物理地址以及指定好的pageflags,创建页表项
+    ///
+    /// ## 参数
+    ///
+    /// - `paddr` 物理地址
+    /// - `page_flags` 页表项的flags
+    ///
+    /// ## 返回值
+    ///
+    /// 页表项的值
+    fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize;
 }
 
 /// @brief 虚拟地址范围

+ 28 - 5
kernel/src/mm/no_init.rs

@@ -24,7 +24,8 @@ use super::{
 };
 
 /// 用于存储重映射页表的位图和页面
-static EARLY_IOREMAP_PAGES: SpinLock<EarlyIoRemapPages> = SpinLock::new(EarlyIoRemapPages::new());
+pub static EARLY_IOREMAP_PAGES: SpinLock<EarlyIoRemapPages> =
+    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<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> {
         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<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> {
 /// 并且,内核引导文件必须以4K页为粒度,填写了前100M的内存映射关系。(具体以本文件开头的注释为准)
 #[inline(never)]
 pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) {
+    let flags: PageFlags<MMArch> = 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<MMArch> = 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<MMArch>,
+) {
     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<MMArch> = 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<MMArch> =
+            mapper.map_phys(vaddr, paddr, flags).unwrap();
         flusher.ignore();
     }
 

+ 58 - 22
kernel/src/mm/page.rs

@@ -102,7 +102,7 @@ impl<Arch: MemoryManagementArch> PageTable<Arch> {
     /// 获取当前页表的第i个页表项
     pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<Arch>> {
         let entry_virt = self.entry_virt(i)?;
-        return Some(PageEntry::new(Arch::read::<usize>(entry_virt)));
+        return Some(PageEntry::from_usize(Arch::read::<usize>(entry_virt)));
     }
 
     /// 设置当前页表的第i个页表项
@@ -178,7 +178,14 @@ impl<Arch> Debug for PageEntry<Arch> {
 
 impl<Arch: MemoryManagementArch> PageEntry<Arch> {
     #[inline(always)]
-    pub fn new(data: usize) -> Self {
+    pub fn new(paddr: PhysAddr, flags: PageFlags<Arch>) -> 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<Arch: MemoryManagementArch> PageEntry<Arch> {
     /// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址
     #[inline(always)]
     pub fn address(&self) -> Result<PhysAddr, PhysAddr> {
-        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<Arch: MemoryManagementArch> PageFlags<Arch> {
     #[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<Arch: MemoryManagementArch> PageFlags<Arch> {
     #[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<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
             );
             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<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
                 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<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
                     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<MMArch> =
+                    let flags: PageFlags<Arch> =
                         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<Arch: MemoryManagementArch>(
     // 如果当前是最后一级页表,直接取消页面映射
     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<Arch: MemoryManagementArch>(
             .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());
         }

+ 1 - 1
kernel/submodules/DragonStub

@@ -1 +1 @@
-Subproject commit 7fc3806da73be059540a79b6fdddf8049be250f3
+Subproject commit 773f7fd31fb85ce22f0fc442fd2c13a8d0602a8c

+ 1 - 1
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"