Browse Source

riscv: 完成UEFI初始化,能正确设置memblock的信息 (#501)

* riscv: 完成UEFI初始化,能正确设置memblock的信息

* sbi增加reset功能

* 把虚拟CPU修改为sifive-u54,使qemu能更正确地模拟硬件行为

* 修复内存页面映射未设置“DIRTY”、”ACCESSED“、”GLOBAL“位,导致真机page fault的问题
LoGin 1 year ago
parent
commit
9284987850

+ 39 - 16
kernel/src/arch/riscv64/asm/head.S

@@ -17,9 +17,9 @@
 #define SR_VS 0x00000600
 #define SR_FS_VS	(SR_FS | SR_VS) /* Vector and Floating-Point Unit */
 
-#define SATP_MODE_39 0x8000000000000000UL
-#define SATP_MODE_48 0x9000000000000000UL
-#define SATP_MODE_57 0xa000000000000000UL
+#define SATP_MODE_39 0x8000000000000000ULL
+#define SATP_MODE_48 0x9000000000000000ULL
+#define SATP_MODE_57 0xa000000000000000ULL
 
 #define PAGE_OFFSET 0xffffffc000000000
 #define KERNEL_LINK_OFFSET 0x1000000
@@ -84,7 +84,6 @@ ENTRY(_start)
 	call initial_map_1g_identical
 
 __init_set_pgtable_loop_end:
-	
 	call __initial_reloacate_enable_mmu
 
 .option push
@@ -119,6 +118,7 @@ __initial_reloacate_enable_mmu:
 	// 计算起始物理地址与内核高虚拟地址的偏移量
 	la t0, __initial_start_load_paddr
 	ld t0, 0(t0)
+
 	
 	li t1, KERNEL_VIRT_START
 	sub t1, t1, t0
@@ -128,18 +128,27 @@ __initial_reloacate_enable_mmu:
 
 	/* Point stvec to virtual address of intruction after satp write */
 	/* Set trap vector to spin forever to help debug */
-	la a2, __initial_Lsecondary_park
+	la a2, 1f
 	add a2, a2, t1
 	csrw CSR_TVEC, a2
-	
 	// enable MMU
 	la a2, __initial_pgtable
 	srli a2, a2, 12
 	la a0, __initial_satp_mode
 	ld a0, 0(a0)
 	or a2, a2, a0
+
+
 	sfence.vma
 	csrw satp, a2
+	
+1:
+	la a0, __initial_Lsecondary_park
+	add a0, a0, t1
+	csrw CSR_TVEC, a0
+
+	csrw satp, a2
+	sfence.vma
 
 	ret
 
@@ -165,7 +174,7 @@ initial_map_256M_phys_addr:
 	and t2, t2, t1
 
 	// 计算L0页表项的索引
-	srl t2, t2, 30
+	srli t2, t2, 30
 	andi t2, t2, 511
 	
 	
@@ -220,7 +229,7 @@ __initial_set_l1_pgtable_loop:
 	li t1, 0x3FFFFFFFFFFFFF
 	and t3, t3, t1 // t3 = t3 & 0x3FFFFFFFFFFFFF
 	slli t3, t3, 10 // t3 = t3 << 10
-	ori t3, t3, 0xf // 设置L1页表项属性,R/W/X/V = 1
+	ori t3, t3, 0xEF // 设置L1页表项属性,set R/W/X/V/A/D/G = 1
 	// 设置L1页表项的值
 	sd t3, 0(t0)
 
@@ -262,41 +271,55 @@ initial_map_1g_identical:
 	// 计算起始物理地址,存放在t0中
 	and t0, t0, a0
 
-	
+
 	// 把起始虚拟地址存储到t2中
 	mv t2, a1
 	// 按照1g对齐
 	li t1, -0x40000000
 	and t2, t2, t1
+
 	
 	// 右移30位,得到L0页表项的索引
-	srl t2, t2, 30
+	srli t2, t2, 30
 	// 与511进行与运算,得到L0页表项的索引
 	andi t2, t2, 511
 	
 
 	// 填写页表项
-	// li t2, 0xf // 页表项属性, R/W/X/V = 1
 	la t4, __initial_pgtable
 	slli t3, t2, 3 // t3 = t2 * 8
 	add t4, t4, t3 // t4 = t4 + t3
 
+
 	mv t3, t0
 	srli t3, t3, 12 // t3 = t0 >> 12 (page frame number)
 	slli t3, t3, 10 // t3 = t3 << 10 
-	ori t3, t3, 0xf // set R/W/X/V = 1
-	// 设置t0地址在L0页表中的值
+	ori t3, t3, 0xEF // set R/W/X/V/A/D/G = 1
+
+	// 计算delta的pfn
+	li t2, 0x40000000
+	srli t2, t2, 12
+	// 把delta pfn移位到页表项的第10位的位置
+	slli t2, t2, 10
+	li t1, 2
+
+__loop_set_8g:
+
+	
 	sd t3, 0(t4)
 
 	// 增加 t4 的值
 	addi t4, t4, 8
-	// 增加 t3 的值(1G)
-	li t2, 0x40000000
+	// 增加1G的pfn	
 	add t3, t3, t2
-	sd t3, 0(t4)
+	
+	
+	addi t1, t1, -1
+	bnez t1, __loop_set_8g
 
 	ret
 
+
 // 用于清空页表的空间
 // 参数:
 //   a0: page table address

+ 1 - 0
kernel/src/arch/riscv64/driver/sbi/mod.rs

@@ -5,6 +5,7 @@ use self::legacy::console_putchar;
 /// Some code takes from `https://github.com/repnop/sbi.git`
 mod ecall;
 pub mod legacy;
+pub mod reset;
 
 /// Error codes returned by SBI calls
 ///

+ 85 - 0
kernel/src/arch/riscv64/driver/sbi/reset.rs

@@ -0,0 +1,85 @@
+#![allow(dead_code)]
+use super::{ecall::ecall2, SbiError};
+
+/// System reset extension ID
+pub const EXTENSION_ID: usize = 0x53525354;
+
+/// The type of reset to perform
+#[derive(Debug, Clone, Copy)]
+pub enum ResetType {
+    /// Shutdown the system
+    Shutdown,
+    /// Power off all hardware and perform a cold boot
+    ColdReboot,
+    /// Reset processors and some hardware
+    WarmReboot,
+    /// Platform specific reset type. The variant value is a value within the
+    /// range `0x00000000..=0x0FFFFFFF`. A value outside of that range will be
+    /// clamped to the maximum possible valid value for this reset type.
+    PlatformSpecific(u32),
+}
+
+impl ResetType {
+    fn to_u32(self) -> u32 {
+        match self {
+            ResetType::Shutdown => 0,
+            ResetType::ColdReboot => 1,
+            ResetType::WarmReboot => 2,
+            ResetType::PlatformSpecific(n) => n.min(0x0FFFFFFF) + 0xF0000000,
+        }
+    }
+}
+
+/// The reason for performing the reset
+#[derive(Debug, Clone, Copy)]
+pub enum ResetReason {
+    /// No reason for reset
+    NoReason,
+    /// System failure
+    SystemFailure,
+    /// SBI implementation specific reset reason. The variant value is a value
+    /// within the range `0x00000000..=0x0FFFFFFF`. A value outside of that
+    /// range will be clamped to the maximum possible valid value for this reset
+    /// reason type.
+    SbiSpecific(u32),
+    /// Platform specific reset reason. The variant value is a value within the
+    /// range `0x00000000..=0x0FFFFFFF`. A value outside of that range will be
+    /// clamped to the maximum possible valid value for this reset reason type.
+    PlatformSpecific(u32),
+}
+
+impl ResetReason {
+    fn to_u32(self) -> u32 {
+        match self {
+            ResetReason::NoReason => 0,
+            ResetReason::SystemFailure => 1,
+            ResetReason::SbiSpecific(n) => n.min(0x0FFFFFFF) + 0xE0000000,
+            ResetReason::PlatformSpecific(n) => n.min(0x0FFFFFFF) + 0xF0000000,
+        }
+    }
+}
+
+/// Attempt to reset the system in the provided method, with a reason for the
+/// reset.
+///
+/// ### Possible errors
+///
+/// [`SbiError::NotSupported`]: The [`ResetType`] is valid but not implemented.
+///
+/// [`SbiError::Failed`]: The system reset request failed for an unknown reason.
+pub fn system_reset(
+    kind: ResetType,
+    reason: ResetReason,
+) -> Result<core::convert::Infallible, SbiError> {
+    match unsafe {
+        ecall2(
+            kind.to_u32() as usize,
+            reason.to_u32() as usize,
+            EXTENSION_ID,
+            0,
+        )
+    } {
+        Ok(_) => unreachable!("SBI returned `Ok` after a system reset call"),
+        Err(e) => Err(e),
+    }
+}

+ 5 - 14
kernel/src/arch/riscv64/init/mod.rs

@@ -3,14 +3,11 @@ use core::intrinsics::unreachable;
 use fdt::node::FdtNode;
 
 use crate::{
-    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,
-    },
+    arch::mm::init::mm_early_init,
+    driver::{firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver},
     init::{boot_params, init_before_mem_init},
     kdebug, kinfo,
-    mm::{MemoryManagementArch, PhysAddr, VirtAddr},
+    mm::{PhysAddr, VirtAddr},
     print, println,
 };
 
@@ -39,14 +36,8 @@ impl ArchBootParams {
 #[no_mangle]
 unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
     let fdt_paddr = PhysAddr::new(fdt_paddr);
-
+    // system_reset(sbi::reset::ResetType::Shutdown, sbi::reset::ResetReason::NoReason);
     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!(
@@ -58,7 +49,7 @@ unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
     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);
+    // print_node(fdt.find_node("/").unwrap(), 0);
 
     parse_dtb();
 

+ 2 - 12
kernel/src/arch/riscv64/mm/init.rs

@@ -1,17 +1,7 @@
-use system_error::SystemError;
-
 use crate::{
-    arch::{
-        mm::{KERNEL_BEGIN_PA, KERNEL_BEGIN_VA, KERNEL_END_PA, KERNEL_END_VA},
-        MMArch,
-    },
+    arch::mm::{KERNEL_BEGIN_PA, KERNEL_BEGIN_VA, KERNEL_END_PA, KERNEL_END_VA},
     kdebug,
-    mm::{
-        allocator::page_frame::PageFrameCount,
-        no_init::{pseudo_map_phys, EARLY_IOREMAP_PAGES},
-        page::{PageEntry, PageMapper, PageTable},
-        MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
-    },
+    mm::{PhysAddr, VirtAddr},
 };
 
 #[inline(never)]

+ 15 - 16
kernel/src/arch/riscv64/mm/mod.rs

@@ -1,13 +1,10 @@
 use riscv::register::satp;
 use system_error::SystemError;
 
-use crate::{
-    kdebug,
-    mm::{
-        allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
-        page::PageFlags,
-        MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
-    },
+use crate::mm::{
+    allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
+    page::PageFlags,
+    MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
 };
 
 pub mod bump;
@@ -28,6 +25,9 @@ pub(self) static mut KERNEL_END_VA: VirtAddr = VirtAddr::new(0);
 #[derive(Debug, Clone, Copy, Hash)]
 pub struct RiscV64MMArch;
 
+impl RiscV64MMArch {
+    pub const ENTRY_FLAG_GLOBAL: usize = 1 << 5;
+}
 impl MemoryManagementArch for RiscV64MMArch {
     const PAGE_SHIFT: usize = 12;
 
@@ -38,13 +38,17 @@ impl MemoryManagementArch for RiscV64MMArch {
 
     const ENTRY_ADDRESS_SHIFT: usize = 39;
 
-    const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT;
+    const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT
+        | Self::ENTRY_FLAG_READWRITE
+        | Self::ENTRY_FLAG_DIRTY
+        | Self::ENTRY_FLAG_ACCESSED
+        | Self::ENTRY_FLAG_GLOBAL;
 
     const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT;
 
     const ENTRY_FLAG_PRESENT: usize = 1 << 0;
 
-    const ENTRY_FLAG_READONLY: usize = 1 << 1;
+    const ENTRY_FLAG_READONLY: usize = 0;
 
     const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1);
 
@@ -57,6 +61,8 @@ impl MemoryManagementArch for RiscV64MMArch {
     const ENTRY_FLAG_NO_EXEC: usize = 0;
 
     const ENTRY_FLAG_EXEC: usize = (1 << 3);
+    const ENTRY_FLAG_ACCESSED: usize = (1 << 6);
+    const ENTRY_FLAG_DIRTY: usize = (1 << 7);
 
     const PHYS_OFFSET: usize = 0xffff_ffc0_0000_0000;
 
@@ -89,14 +95,11 @@ impl MemoryManagementArch for RiscV64MMArch {
 
         let paddr = PhysPageFrame::from_ppn(ppn).phys_address();
 
-        kdebug!("table(): {paddr:?}, ppn: {ppn}");
-
         return paddr;
     }
 
     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);
     }
@@ -131,13 +134,11 @@ impl MemoryManagementArch for RiscV64MMArch {
     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;
@@ -147,8 +148,6 @@ impl MemoryManagementArch for RiscV64MMArch {
     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;
     }
 }

+ 8 - 4
kernel/src/arch/x86_64/mm/bump.rs

@@ -1,8 +1,9 @@
 use crate::{
     libs::align::{page_align_down, page_align_up},
     mm::{
-        allocator::bump::BumpAllocator, memblock::mem_block_manager, MemoryManagementArch,
-        PhysAddr, PhysMemoryArea, VirtAddr,
+        allocator::bump::BumpAllocator,
+        memblock::{mem_block_manager, MemoryAreaAttr},
+        MemoryManagementArch, PhysAddr, PhysMemoryArea, VirtAddr,
     },
 };
 
@@ -41,8 +42,11 @@ impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
                 continue;
             }
 
-            ret_areas[res_count] =
-                PhysMemoryArea::new(PhysAddr::new(new_start), new_end - new_start);
+            ret_areas[res_count] = PhysMemoryArea::new(
+                PhysAddr::new(new_start),
+                new_end - new_start,
+                MemoryAreaAttr::empty(),
+            );
 
             res_count += 1;
         }

+ 3 - 0
kernel/src/arch/x86_64/mm/mod.rs

@@ -108,6 +108,9 @@ impl MemoryManagementArch for X86_64MMArch {
     /// x86_64不存在EXEC标志位,只有NO_EXEC(XD)标志位
     const ENTRY_FLAG_EXEC: usize = 0;
 
+    const ENTRY_FLAG_ACCESSED: usize = 0;
+    const ENTRY_FLAG_DIRTY: usize = 0;
+
     /// 物理地址与虚拟地址的偏移量
     /// 0xffff_8000_0000_0000
     const PHYS_OFFSET: usize = Self::PAGE_NEGATIVE_MASK + (Self::PAGE_ADDRESS_SIZE >> 1);

+ 35 - 0
kernel/src/driver/firmware/efi/guid.rs

@@ -0,0 +1,35 @@
+use core::{fmt, mem};
+
+use uefi_raw::Guid;
+
+/// 由DragonStub设置的,用于描述内核被放置在的地址的GUID
+pub static DRAGONSTUB_EFI_PAYLOAD_EFI_GUID: Guid = Guid::new(
+    unsafe { mem::transmute_copy(&0xddf1d47cu32) },
+    unsafe { mem::transmute_copy(&0x102cu32) },
+    unsafe { mem::transmute_copy(&0xaaf9u32) },
+    0xce,
+    0x34,
+    [0xbc, 0xef, 0x98, 0x12, 0x00, 0x31],
+);
+
+/// 表示内核被加载到的地址的信息。
+///
+/// 对应 `DRAGONSTUB_EFI_PAYLOAD_EFI_GUID`
+#[derive(Clone, Copy)]
+#[repr(C)]
+pub struct DragonStubPayloadEFI {
+    /// 内核文件被加载到的物理地址
+    pub paddr: u64,
+
+    /// 占用的空间的大小
+    pub size: u64,
+}
+
+impl fmt::Debug for DragonStubPayloadEFI {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("DragonStubPayloadEFI")
+            .field("paddr", &format_args!("0x{:x}", self.paddr))
+            .field("size", &self.size)
+            .finish()
+    }
+}

+ 145 - 35
kernel/src/driver/firmware/efi/init.rs

@@ -1,11 +1,16 @@
 use core::{intrinsics::unlikely, mem::size_of};
 
 use system_error::SystemError;
+use uefi_raw::table::boot::{MemoryAttribute, MemoryType};
 
 use crate::{
-    driver::firmware::efi::EFIInitFlags,
-    libs::align::page_align_down,
-    mm::{early_ioremap::EarlyIoRemap, PhysAddr, VirtAddr},
+    arch::MMArch,
+    driver::{firmware::efi::EFIInitFlags, open_firmware::fdt::open_firmware_fdt_driver},
+    libs::align::{page_align_down, page_align_up},
+    mm::{
+        allocator::page_frame::PhysPageFrame, early_ioremap::EarlyIoRemap,
+        memblock::mem_block_manager, MemoryManagementArch, PhysAddr, VirtAddr,
+    },
 };
 
 use super::efi_manager;
@@ -13,6 +18,7 @@ use super::efi_manager;
 #[allow(dead_code)]
 #[inline(never)]
 pub fn efi_init() {
+    kinfo!("Initializing efi...");
     let data_from_fdt = efi_manager()
         .get_fdt_params()
         .expect("Failed to get fdt params");
@@ -22,7 +28,7 @@ pub fn efi_init() {
         return;
     }
 
-    kdebug!("to map memory table");
+    // kdebug!("to map memory table");
 
     // 映射mmap table
     if efi_manager().memmap_init_early(&data_from_fdt).is_err() {
@@ -42,15 +48,36 @@ pub fn efi_init() {
         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);
+    if let Err(e) = r {
+        kerror!("Failed to initialize UEFI: {:?}", e);
+        efi_manager().efi_memmap_unmap();
+        return;
     }
 
-    loop {}
+    reserve_memory_regions();
+    // todo: 由于上面的`uefi_init`里面,按照UEFI的数据,初始化了内存块,
+    // 但是UEFI给的数据可能不全,这里Linux会再次从设备树检测可用内存,从而填补完全相应的内存信息
+
+    // 并且,Linux还对EFI BootService提供的Mokvar表进行了检测以及空间保留。
+
+    // todo: 模仿Linux的行为,做好接下来的几步工作:
+    // 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/efi-init.c#217
+
+    // 保留mmap table的内存
+    let base = page_align_down(data_from_fdt.mmap_base.unwrap() as usize);
+    let offset = data_from_fdt.mmap_base.unwrap() as usize - base;
+
+    mem_block_manager()
+        .reserve_block(
+            PhysAddr::new(base),
+            data_from_fdt.mmap_size.unwrap() as usize + offset,
+        )
+        .expect("Failed to reserve memory for EFI mmap table");
+
+    // todo: Initialize screen info
+
+    kinfo!("UEFI init done!");
 }
 
 #[inline(never)]
@@ -69,18 +96,11 @@ fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> {
     // 映射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;
+    let st_vaddr = EarlyIoRemap::map_not_aligned(system_table, st_size, true).map_err(|e| {
+        kwarn!("Unable to map EFI system table, e:{e:?}");
+        e
+    })?;
 
     efi_manager()
         .inner
@@ -94,8 +114,6 @@ fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> {
         .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);
     }
@@ -109,21 +127,113 @@ fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> {
             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));
+
+    let runtime_service_paddr = efi_vaddr_2_paddr(st_ref.runtime_services as usize);
+    let mut inner_write_guard = efi_manager().inner.write();
+    inner_write_guard.runtime_paddr = Some(runtime_service_paddr);
     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()
+    drop(inner_write_guard);
+    efi_manager().report_systable_header(
+        &st_ref.header,
+        efi_vaddr_2_paddr(st_ref.firmware_vendor as usize),
     );
 
-    unimplemented!("report header");
-    // return Ok(());
+    {
+        // 映射configuration table
+        let table_size = st_ref.number_of_configuration_table_entries
+            * size_of::<uefi_raw::table::configuration::ConfigurationTable>();
+        let config_table_vaddr = EarlyIoRemap::map_not_aligned(
+            efi_vaddr_2_paddr(st_ref.configuration_table as usize),
+            table_size,
+            true,
+        )
+        .map_err(|e| {
+            kwarn!("Unable to map EFI configuration table, e:{e:?}");
+            err_unmap_systable(st_vaddr);
+            e
+        })?;
+        let cfg_tables = unsafe {
+            core::slice::from_raw_parts(
+                config_table_vaddr.data()
+                    as *const uefi_raw::table::configuration::ConfigurationTable,
+                st_ref.number_of_configuration_table_entries,
+            )
+        };
+        // 解析configuration table
+        let r = efi_manager().parse_config_tables(cfg_tables);
+
+        EarlyIoRemap::unmap(config_table_vaddr).expect("Failed to unmap EFI config table");
+        return r;
+    }
+}
+
+/// 把EFI固件提供的虚拟地址转换为物理地址。
+///
+/// 因为在调用SetVirtualAddressMap()之后,`EFI SystemTable` 的一些数据成员会被虚拟重映射
+///
+/// ## 锁
+///
+/// 在进入该函数前,请不要持有`efi_manager().inner`的写锁
+fn efi_vaddr_2_paddr(efi_vaddr: usize) -> PhysAddr {
+    let guard = efi_manager().inner.read();
+    let mmap = &guard.mmap;
+
+    let efi_vaddr: u64 = efi_vaddr as u64;
+    for md in mmap.iter() {
+        if !md.att.contains(MemoryAttribute::RUNTIME) {
+            continue;
+        }
+
+        if md.virt_start == 0 {
+            // no virtual mapping has been installed by the DragonStub
+            break;
+        }
+
+        if md.virt_start <= efi_vaddr
+            && ((efi_vaddr - md.virt_start) < (md.page_count << (MMArch::PAGE_SHIFT as u64)))
+        {
+            return PhysAddr::new((md.phys_start + (efi_vaddr - md.virt_start)) as usize);
+        }
+    }
+
+    return PhysAddr::new(efi_vaddr as usize);
+}
+
+/// 根据UEFI提供的内存描述符的信息,填写内存区域信息
+fn reserve_memory_regions() {
+    // 忽略之前已经发现的任何内存块。因为之前发现的内存块来自平坦设备树,
+    // 但是UEFI有自己的内存映射表,我们以UEFI提供的为准
+    mem_block_manager()
+        .remove_block(PhysAddr::new(0), PhysAddr::MAX.data())
+        .expect("Failed to remove all memblocks!");
+
+    let inner_guard = efi_manager().inner.read_irqsave();
+    for md in inner_guard.mmap.iter() {
+        let page_count = (PhysPageFrame::new(PhysAddr::new(page_align_up(
+            (md.phys_start + md.page_count << (MMArch::PAGE_SHIFT as u64)) as usize,
+        )))
+        .ppn()
+            - PhysPageFrame::new(PhysAddr::new(page_align_down(md.phys_start as usize))).ppn())
+            as u64;
+        let phys_start = page_align_down(md.phys_start as usize);
+        let size = (page_count << (MMArch::PAGE_SHIFT as u64)) as usize;
+
+        if md.is_memory() {
+            open_firmware_fdt_driver().early_init_dt_add_memory(phys_start as u64, size as u64);
+            if !md.is_usable_memory() {
+                mem_block_manager()
+                    .mark_nomap(PhysAddr::new(phys_start), size)
+                    .unwrap();
+            }
+
+            //  keep ACPI reclaim memory intact for kexec etc.
+            if md.ty == MemoryType::ACPI_RECLAIM {
+                mem_block_manager()
+                    .reserve_block(PhysAddr::new(phys_start), size)
+                    .unwrap();
+            }
+        }
+    }
 }

+ 68 - 3
kernel/src/driver/firmware/efi/memmap.rs

@@ -1,3 +1,5 @@
+use core::{intrinsics::unlikely, mem::size_of};
+
 use system_error::SystemError;
 
 use crate::{
@@ -6,7 +8,7 @@ use crate::{
     mm::{early_ioremap::EarlyIoRemap, PhysAddr, VirtAddr},
 };
 
-use super::{fdt::EFIFdtParams, EFIManager};
+use super::{fdt::EFIFdtParams, tables::MemoryDescriptor, EFIManager};
 
 #[derive(Debug)]
 pub struct EFIMemoryMapInfo {
@@ -22,6 +24,11 @@ pub struct EFIMemoryMapInfo {
     pub(super) desc_size: usize,
     /// EFI Memory Map的描述信息的版本
     pub(super) desc_version: usize,
+    /// 当前是否在内存管理已经完成初始化后,对该结构体进行操作
+    ///
+    /// true: 内存管理已经完成初始化
+    /// false: 内存管理还未完成初始化
+    pub(super) late: bool,
 }
 
 impl EFIMemoryMapInfo {
@@ -32,6 +39,7 @@ impl EFIMemoryMapInfo {
         nr_map: 0,
         desc_size: 0,
         desc_version: 0,
+        late: false,
     };
 
     /// 获取EFI Memory Map的虚拟的结束地址
@@ -39,6 +47,43 @@ impl EFIMemoryMapInfo {
     pub fn map_end_vaddr(&self) -> Option<VirtAddr> {
         return self.vaddr.map(|v| v + self.size);
     }
+
+    /// 迭代所有的内存描述符
+    pub fn iter(&self) -> EFIMemoryDescIter {
+        EFIMemoryDescIter::new(self)
+    }
+}
+
+/// UEFI 内存描述符的迭代器
+pub struct EFIMemoryDescIter<'a> {
+    inner: &'a EFIMemoryMapInfo,
+    offset: usize,
+}
+
+impl<'a> EFIMemoryDescIter<'a> {
+    fn new(inner: &'a EFIMemoryMapInfo) -> Self {
+        Self { inner, offset: 0 }
+    }
+}
+
+impl<'a> Iterator for EFIMemoryDescIter<'a> {
+    type Item = MemoryDescriptor;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.offset + size_of::<Self::Item>() > self.inner.size {
+            return None;
+        }
+
+        // 如果是空指针,返回None
+        if unlikely(self.inner.vaddr.unwrap_or(VirtAddr::new(0)).is_null()) {
+            return None;
+        }
+
+        let vaddr = self.inner.vaddr? + self.offset;
+        self.offset += size_of::<Self::Item>();
+        let res = unsafe { *(vaddr.data() as *const Self::Item) };
+        return Some(res);
+    }
 }
 
 impl EFIManager {
@@ -59,13 +104,14 @@ impl EFIManager {
     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}");
+            // kdebug!("do_efi_memmap_init: map_size={map_size:#x}");
+
             // 映射内存
             let mut vaddr = EarlyIoRemap::map(
                 PhysAddr::new(page_align_down(paddr.data())),
@@ -77,7 +123,9 @@ impl EFIManager {
             vaddr += offset;
 
             inner_guard.mmap.vaddr = Some(vaddr);
+            inner_guard.mmap.late = false;
         } else {
+            inner_guard.mmap.late = true;
             unimplemented!("efi_memmap_init_late")
         }
 
@@ -97,4 +145,21 @@ impl EFIManager {
 
         return Ok(());
     }
+
+    /// 清除EFI Memory Table在内存中的映射
+    pub fn efi_memmap_unmap(&self) {
+        let mut inner_guard = self.inner.write_irqsave();
+
+        // 没有启用memmap
+        if !inner_guard.init_flags.contains(EFIInitFlags::MEMMAP) {
+            return;
+        }
+
+        if !inner_guard.mmap.late {
+            EarlyIoRemap::unmap(inner_guard.mmap.vaddr.take().unwrap()).unwrap();
+        } else {
+            unimplemented!("efi_memmap_unmap");
+        }
+        inner_guard.init_flags.set(EFIInitFlags::MEMMAP, false);
+    }
 }

+ 5 - 1
kernel/src/driver/firmware/efi/mod.rs

@@ -2,11 +2,13 @@ use system_error::SystemError;
 
 use crate::{libs::rwlock::RwLock, mm::PhysAddr};
 
-use self::memmap::EFIMemoryMapInfo;
+use self::{guid::DragonStubPayloadEFI, memmap::EFIMemoryMapInfo};
 
 mod fdt;
+pub mod guid;
 pub mod init;
 pub mod memmap;
+pub mod tables;
 
 static EFI_MANAGER: EFIManager = EFIManager::new();
 
@@ -32,6 +34,7 @@ struct InnerEFIManager {
     pub runtime_paddr: Option<PhysAddr>,
     /// runtime services的版本号
     pub runtime_service_version: Option<uefi_raw::table::Revision>,
+    pub dragonstub_load_info: Option<DragonStubPayloadEFI>,
 }
 
 impl EFIManager {
@@ -42,6 +45,7 @@ impl EFIManager {
                 init_flags: EFIInitFlags::empty(),
                 runtime_paddr: None,
                 runtime_service_version: None,
+                dragonstub_load_info: None,
             }),
         }
     }

+ 167 - 0
kernel/src/driver/firmware/efi/tables.rs

@@ -0,0 +1,167 @@
+use core::{ffi::CStr, mem::size_of};
+
+use hashbrown::Equivalent;
+use system_error::SystemError;
+use uefi_raw::table::{
+    boot::{MemoryAttribute, MemoryType},
+    configuration::ConfigurationTable,
+};
+
+use crate::{
+    driver::firmware::efi::{
+        efi_manager,
+        guid::{DragonStubPayloadEFI, DRAGONSTUB_EFI_PAYLOAD_EFI_GUID},
+    },
+    mm::{early_ioremap::EarlyIoRemap, PhysAddr},
+};
+
+use super::EFIManager;
+
+impl EFIManager {
+    /// 显示EFI系统表头的信息
+    ///
+    /// ## 参数
+    ///
+    /// - header: system table表头
+    /// - firmware_vendor: firmware vendor字符串的物理地址
+    #[inline(never)]
+    pub fn report_systable_header(
+        &self,
+        header: &uefi_raw::table::Header,
+        firmware_vendor: PhysAddr,
+    ) {
+        const TMPBUF_SIZE: usize = 100;
+
+        let mut tmp_buf = [0u8; TMPBUF_SIZE];
+
+        let fw_ptr =
+            EarlyIoRemap::map_not_aligned(firmware_vendor, TMPBUF_SIZE * size_of::<u16>(), true);
+        if let Ok(fw_ptr) = fw_ptr {
+            let slice =
+                unsafe { core::slice::from_raw_parts(fw_ptr.data() as *const u16, TMPBUF_SIZE) };
+            for i in 0..(TMPBUF_SIZE - 1) {
+                let val = slice[i];
+
+                if (val & 0xff) == 0 {
+                    break;
+                }
+                tmp_buf[i] = (val & 0xff) as u8;
+            }
+
+            EarlyIoRemap::unmap(fw_ptr).map_err(|e|{
+                kerror!("report systable header: failed to unmap systable header, fw_ptr: {fw_ptr:?}, err: {e:?}");
+                e
+            }).ok();
+        } else {
+            kwarn!("report systable header: failed to map systable header, err: {fw_ptr:?}");
+        }
+
+        let s = CStr::from_bytes_with_nul(&tmp_buf)
+            .unwrap_or_else(|_| CStr::from_bytes_with_nul(b"Unknown\0").unwrap());
+        kinfo!("EFI version: {:?}, vendor: {:?}", header.revision, s);
+    }
+
+    /// 解析EFI config table
+    pub fn parse_config_tables(&self, tables: &[ConfigurationTable]) -> Result<(), SystemError> {
+        for table in tables {
+            if table
+                .vendor_guid
+                .equivalent(&DRAGONSTUB_EFI_PAYLOAD_EFI_GUID)
+            {
+                let table_paddr: PhysAddr = PhysAddr::new(table.vendor_table as usize);
+                let vaddr = EarlyIoRemap::map_not_aligned(
+                    table_paddr,
+                    size_of::<DragonStubPayloadEFI>(),
+                    true,
+                )?;
+
+                let data = unsafe { *(vaddr.data() as *const DragonStubPayloadEFI) };
+
+                efi_manager().inner.write().dragonstub_load_info = Some(data);
+
+                EarlyIoRemap::unmap(vaddr).unwrap();
+            }
+        }
+
+        return Ok(());
+    }
+}
+
+/// A structure describing a region of memory.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[repr(C)]
+pub struct MemoryDescriptor {
+    /// Type of memory occupying this range.
+    pub ty: MemoryType,
+    /// Starting physical address.
+    pub phys_start: uefi_raw::PhysicalAddress,
+    /// Starting virtual address.
+    pub virt_start: uefi_raw::VirtualAddress,
+    /// Number of 4 KiB pages contained in this range.
+    pub page_count: u64,
+    /// The capability attributes of this memory range.
+    pub att: MemoryAttribute,
+}
+
+#[allow(dead_code)]
+impl MemoryDescriptor {
+    /// Memory descriptor version number.
+    pub const VERSION: u32 = 1;
+
+    /// 当前内存描述符是否表示真实的内存
+    #[inline]
+    pub fn is_memory(&self) -> bool {
+        if self.att.contains(
+            MemoryAttribute::WRITE_BACK
+                | MemoryAttribute::WRITE_THROUGH
+                | MemoryAttribute::WRITE_COMBINE,
+        ) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /// 判断当前内存描述符所表示的区域是否能被作为系统内存使用
+    ///
+    /// ## 返回
+    ///
+    /// - `true` - 可以
+    /// - `false` - 不可以
+    pub fn is_usable_memory(&self) -> bool {
+        match self.ty {
+            MemoryType::LOADER_CODE
+            | MemoryType::LOADER_DATA
+            | MemoryType::ACPI_RECLAIM
+            | MemoryType::BOOT_SERVICES_CODE
+            | MemoryType::BOOT_SERVICES_DATA
+            | MemoryType::CONVENTIONAL
+            | MemoryType::PERSISTENT_MEMORY => {
+                // SPECIAL_PURPOSE的内存是“软保留”的,这意味着它最初被留出,
+                // 但在启动后可以通过热插拔再次使用,或者分配给dax驱动程序。
+                if self.att.contains(MemoryAttribute::SPECIAL_PURPOSE) {
+                    return false;
+                }
+
+                // 根据规范,在调用ExitBootServices()之后,这些区域就不再被保留了。
+                // 然而,只有当它们可以被映射为WRITE_BACK缓存时,我们才能将它们用作系统内存
+                return self.att.contains(MemoryAttribute::WRITE_BACK);
+            }
+            _ => {
+                return false;
+            }
+        }
+    }
+}
+
+impl Default for MemoryDescriptor {
+    fn default() -> MemoryDescriptor {
+        MemoryDescriptor {
+            ty: MemoryType::RESERVED,
+            phys_start: 0,
+            virt_start: 0,
+            page_count: 0,
+            att: MemoryAttribute::empty(),
+        }
+    }
+}

+ 18 - 10
kernel/src/driver/open_firmware/fdt.rs

@@ -4,15 +4,7 @@ use fdt::{
 };
 use system_error::SystemError;
 
-use crate::{
-    arch::MMArch,
-    init::boot_params,
-    libs::{align::page_align_down, rwlock::RwLock},
-    mm::{
-        memblock::{mem_block_manager, MemBlockManager},
-        MemoryManagementArch, PhysAddr,
-    },
-};
+use crate::{init::boot_params, libs::rwlock::RwLock};
 
 #[inline(always)]
 pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver {
@@ -45,6 +37,7 @@ impl FdtGlobalData {
 pub struct OpenFirmwareFdtDriver;
 
 impl OpenFirmwareFdtDriver {
+    #[allow(dead_code)]
     pub fn early_scan_device_tree(&self) -> Result<(), SystemError> {
         let fdt_vaddr = boot_params().read().fdt().unwrap();
         let fdt = unsafe {
@@ -207,7 +200,22 @@ impl OpenFirmwareFdtDriver {
         return found_memory;
     }
 
-    fn early_init_dt_add_memory(&self, base: u64, size: u64) {
+    #[cfg(target_arch = "x86_64")]
+    pub fn early_init_dt_add_memory(&self, _base: u64, _size: u64) {
+        kBUG!("x86_64 should not call early_init_dt_add_memory");
+    }
+
+    #[cfg(not(target_arch = "x86_64"))]
+    pub fn early_init_dt_add_memory(&self, base: u64, size: u64) {
+        use crate::{
+            arch::MMArch,
+            libs::align::page_align_down,
+            mm::{
+                memblock::{mem_block_manager, MemBlockManager},
+                MemoryManagementArch, PhysAddr,
+            },
+        };
+
         let mut base = base as usize;
         let mut size = size as usize;
 

+ 1 - 1
kernel/src/driver/open_firmware/mod.rs

@@ -1,2 +1,2 @@
-#[cfg(target_arch = "riscv64")]
+// #[cfg(target_arch = "riscv64")]
 pub mod fdt;

+ 1 - 0
kernel/src/lib.rs

@@ -6,6 +6,7 @@
 #![feature(const_for)]
 #![feature(const_mut_refs)]
 #![feature(const_trait_impl)]
+#![feature(const_transmute_copy)]
 #![feature(const_refs_to_cell)]
 #![feature(core_intrinsics)]
 #![feature(c_void_variant)]

+ 32 - 1
kernel/src/mm/early_ioremap.rs

@@ -2,7 +2,10 @@ use system_error::SystemError;
 
 use crate::{
     arch::MMArch,
-    libs::{align::page_align_up, spinlock::SpinLock},
+    libs::{
+        align::{page_align_down, page_align_up},
+        spinlock::SpinLock,
+    },
     mm::no_init::{pseudo_map_phys, pseudo_map_phys_ro, pseudo_unmap_phys},
 };
 
@@ -24,6 +27,34 @@ pub struct EarlyIoRemap;
 impl EarlyIoRemap {
     const SLOT_CNT: usize = MMArch::FIXMAP_SIZE / MMArch::PAGE_SIZE;
 
+    /// 把物理内存映射到虚拟内存中(物理地址不要求对齐
+    ///
+    /// ## 参数
+    ///
+    /// - phys: 物理内存地址(不需要对齐)
+    /// - size: 映射的内存大小
+    /// - read_only: 映射区与是否只读
+    ///
+    /// ## 返回值
+    ///
+    /// - 成功: (phys对应的虚拟内存地址)
+    /// - Err(SystemError::ENOMEM): 可用的slot不足
+    #[allow(dead_code)]
+    pub fn map_not_aligned(
+        mut phys: PhysAddr,
+        mut size: usize,
+        read_only: bool,
+    ) -> Result<VirtAddr, SystemError> {
+        // kdebug!("map not aligned phys:{phys:?}, size:{size:?}, read_only:{read_only:?}");
+
+        let offset = phys.data() - page_align_down(phys.data());
+        size += offset;
+        phys -= offset;
+
+        let (map_vaddr, _) = Self::map(phys, size, read_only)?;
+        return Ok(map_vaddr + offset);
+    }
+
     /// 把物理内存映射到虚拟内存中
     ///
     /// ## 说明

+ 108 - 10
kernel/src/mm/memblock.rs

@@ -1,3 +1,5 @@
+use core::intrinsics::unlikely;
+
 use system_error::SystemError;
 
 use crate::libs::spinlock::{SpinLock, SpinLockGuard};
@@ -48,6 +50,18 @@ impl MemBlockManager {
     /// 如果添加的区域与已有区域有重叠,会将重叠的区域合并
     #[allow(dead_code)]
     pub fn add_block(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> {
+        return self.add_range(base, size, MemoryAreaAttr::empty());
+    }
+
+    /// 添加内存区域
+    ///
+    /// 如果添加的区域与已有区域有重叠,会将重叠的区域合并
+    fn add_range(
+        &self,
+        base: PhysAddr,
+        size: usize,
+        flags: MemoryAreaAttr,
+    ) -> Result<(), SystemError> {
         if size == 0 {
             return Ok(());
         }
@@ -56,7 +70,7 @@ impl MemBlockManager {
             panic!("Too many memory regions!");
         }
 
-        let block = PhysMemoryArea::new(base, size);
+        let block = PhysMemoryArea::new(base, size, MemoryAreaAttr::empty());
         // 特判第一个区域
         if inner.initial_memory_regions_num == 0 {
             inner.initial_memory_regions[0] = block;
@@ -66,7 +80,7 @@ impl MemBlockManager {
 
         // 先计算需要添加的区域数量
         let blocks_to_add = self
-            .do_add_block(&mut inner, block, false)
+            .do_add_block(&mut inner, block, false, flags)
             .expect("Failed to count blocks to add!");
 
         if inner.initial_memory_regions_num + blocks_to_add > INITIAL_MEMORY_REGIONS_NUM {
@@ -75,7 +89,7 @@ impl MemBlockManager {
         }
 
         // 然后添加区域
-        self.do_add_block(&mut inner, block, true)
+        self.do_add_block(&mut inner, block, true, flags)
             .expect("Failed to add block!");
 
         return Ok(());
@@ -86,6 +100,7 @@ impl MemBlockManager {
         inner: &mut SpinLockGuard<'_, InnerMemBlockManager>,
         block: PhysMemoryArea,
         insert: bool,
+        flags: MemoryAreaAttr,
     ) -> Result<usize, SystemError> {
         let mut base = block.base;
         let end = block.base + block.size;
@@ -117,7 +132,7 @@ impl MemBlockManager {
                         start_index = i as isize;
                     }
                     end_index = (i + 1) as isize;
-                    self.do_insert_area(inner, i, base, range_base - base);
+                    self.do_insert_area(inner, i, base, range_base - base, flags);
                     i += 1;
                 }
             }
@@ -133,7 +148,7 @@ impl MemBlockManager {
                     start_index = i as isize;
                 }
                 end_index = (i + 1) as isize;
-                self.do_insert_area(inner, i, base, end - base);
+                self.do_insert_area(inner, i, base, end - base, flags);
             }
         }
 
@@ -153,12 +168,13 @@ impl MemBlockManager {
         index: usize,
         base: PhysAddr,
         size: usize,
+        flags: MemoryAreaAttr,
     ) {
         let copy_elements = inner.initial_memory_regions_num - index;
         inner
             .initial_memory_regions
             .copy_within(index..index + copy_elements, index + 1);
-        inner.initial_memory_regions[index] = PhysMemoryArea::new(base, size);
+        inner.initial_memory_regions[index] = PhysMemoryArea::new(base, size, flags);
         inner.initial_memory_regions_num += 1;
     }
 
@@ -178,10 +194,13 @@ impl MemBlockManager {
             {
                 let next_base = inner.initial_memory_regions[(i + 1) as usize].base;
                 let next_size = inner.initial_memory_regions[(i + 1) as usize].size;
+                let next_flags = inner.initial_memory_regions[(i + 1) as usize].flags;
                 let this = &mut inner.initial_memory_regions[i as usize];
 
-                if this.base + this.size != next_base {
-                    // BUG_ON(this->base + this->size > next->base);
+                if this.base + this.size != next_base || this.flags != next_flags {
+                    if unlikely(this.base + this.size > next_base) {
+                        kBUG!("this->base + this->size > next->base");
+                    }
                     i += 1;
                     continue;
                 }
@@ -236,6 +255,15 @@ impl MemBlockManager {
         }
     }
 
+    /// 在一个内存块管理器中找到一个物理地址范围内的
+    /// 空闲块,并隔离出所需的内存大小
+    ///
+    /// ## 返回值
+    ///
+    /// - Ok((start_index, end_index)) 表示成功找到了一个连续的内存区域来满足所需的 size。这里:
+    ///     - start_index 是指定的起始内存区域的索引。
+    ///     - end_index 是指定的结束内存区域的索引,它实际上不包含在返回的连续区域中,但它标志着下一个可能的不连续区域的开始。
+    /// - Err(SystemError) 则表示没有找到足够的空间来满足请求的 size,可能是因为内存区域不足或存在其他系统错误
     fn isolate_range(
         &self,
         inner: &mut SpinLockGuard<'_, InnerMemBlockManager>,
@@ -269,13 +297,25 @@ impl MemBlockManager {
                 // regions[idx] intersects from below
                 inner.initial_memory_regions[idx].base = base;
                 inner.initial_memory_regions[idx].size -= base - range_base;
-                self.do_insert_area(inner, idx, range_base, base - range_base);
+                self.do_insert_area(
+                    inner,
+                    idx,
+                    range_base,
+                    base - range_base,
+                    inner.initial_memory_regions[idx].flags,
+                );
             } else if range_end > end {
                 // regions[idx] intersects from above
                 inner.initial_memory_regions[idx].base = end;
                 inner.initial_memory_regions[idx].size -= end - range_base;
 
-                self.do_insert_area(inner, idx, range_base, end - range_base);
+                self.do_insert_area(
+                    inner,
+                    idx,
+                    range_base,
+                    end - range_base,
+                    inner.initial_memory_regions[idx].flags,
+                );
                 if idx == 0 {
                     idx = usize::MAX;
                 } else {
@@ -295,6 +335,46 @@ impl MemBlockManager {
         return Ok((start_index, end_index));
     }
 
+    /// mark_nomap - 用`MemoryAreaAttr::NOMAP`标志标记内存区域
+    ///
+    /// ## 参数
+    ///
+    /// - base: 区域的物理基地址
+    /// - size: 区域的大小
+    ///
+    /// 使用`MemoryAreaAttr::NOMAP`标志标记的内存区域将不会被添加到物理内存的直接映射中。这些区域仍然会被内存映射所覆盖。内存映射中代表NOMAP内存帧的struct page将被PageReserved()。
+    /// 注意:如果被标记为`MemoryAreaAttr::NOMAP`的内存是从memblock分配的,调用者必须忽略该内存
+    pub fn mark_nomap(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> {
+        return self.set_or_clear_flags(base, size, true, MemoryAreaAttr::NOMAP);
+    }
+
+    fn set_or_clear_flags(
+        &self,
+        base: PhysAddr,
+        size: usize,
+        set: bool,
+        flags: MemoryAreaAttr,
+    ) -> Result<(), SystemError> {
+        let mut inner = self.inner.lock();
+        let (start_index, end_index) = self.isolate_range(&mut inner, base, size)?;
+        for i in start_index..end_index {
+            if set {
+                inner.initial_memory_regions[i].flags |= flags;
+            } else {
+                inner.initial_memory_regions[i].flags &= !flags;
+            }
+        }
+
+        let num = inner.initial_memory_regions_num as isize;
+        self.do_merge_blocks(&mut inner, 0, num);
+        return Ok(());
+    }
+
+    /// 标记内存区域为保留区域
+    pub fn reserve_block(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> {
+        return self.set_or_clear_flags(base, size, true, MemoryAreaAttr::RESERVED);
+    }
+
     /// 生成迭代器
     pub fn to_iter(&self) -> MemBlockIter {
         let inner = self.inner.lock();
@@ -349,3 +429,21 @@ impl<'a> Iterator for MemBlockIter<'a> {
         return Some(ret);
     }
 }
+
+bitflags! {
+    /// 内存区域属性
+    pub struct MemoryAreaAttr: u32 {
+        /// No special request
+        const NONE = 0x0;
+        /// Hotpluggable region
+        const HOTPLUG = (1 << 0);
+        /// Mirrored region
+        const MIRROR = (1 << 1);
+        /// do not add to kenrel direct mapping
+        const NOMAP = (1 << 2);
+        /// Always detected via a driver
+        const DRIVER_MANAGED = (1 << 3);
+        /// Memory is reserved
+        const RESERVED = (1 << 4);
+    }
+}

+ 13 - 2
kernel/src/mm/mod.rs

@@ -14,6 +14,7 @@ use core::{
 
 use self::{
     allocator::page_frame::{VirtPageFrame, VirtPageFrameIter},
+    memblock::MemoryAreaAttr,
     page::round_up_to_page_size,
     ucontext::{AddressSpace, UserMapper},
 };
@@ -87,6 +88,9 @@ pub enum PageTableKind {
 pub struct PhysAddr(usize);
 
 impl PhysAddr {
+    /// 最大物理地址
+    pub const MAX: Self = PhysAddr(usize::MAX);
+
     #[inline(always)]
     pub const fn new(address: usize) -> Self {
         Self(address)
@@ -331,16 +335,19 @@ pub struct PhysMemoryArea {
     pub base: PhysAddr,
     /// 该区域的物理内存大小
     pub size: usize,
+
+    pub flags: MemoryAreaAttr,
 }
 
 impl PhysMemoryArea {
     pub const DEFAULT: Self = Self {
         base: PhysAddr::new(0),
         size: 0,
+        flags: MemoryAreaAttr::empty(),
     };
 
-    pub fn new(base: PhysAddr, size: usize) -> Self {
-        Self { base, size }
+    pub fn new(base: PhysAddr, size: usize, flags: MemoryAreaAttr) -> Self {
+        Self { base, size, flags }
     }
 
     /// 返回向上页面对齐的区域起始物理地址
@@ -392,6 +399,10 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
     const ENTRY_FLAG_NO_EXEC: usize;
     /// 标记当前页面可执行的标志位(Execute enable)
     const ENTRY_FLAG_EXEC: usize;
+    /// 当该位为1时,标明这是一个脏页
+    const ENTRY_FLAG_DIRTY: usize;
+    /// 当该位为1时,代表这个页面被处理器访问过
+    const ENTRY_FLAG_ACCESSED: usize;
 
     /// 虚拟地址与物理地址的偏移量
     const PHYS_OFFSET: usize;

+ 1 - 2
kernel/src/mm/no_init.rs

@@ -111,14 +111,13 @@ 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);

+ 1 - 1
kernel/submodules/DragonStub

@@ -1 +1 @@
-Subproject commit 773f7fd31fb85ce22f0fc442fd2c13a8d0602a8c
+Subproject commit 8515606674058ca81cd1c0b99453e326875c5c0d

+ 1 - 2
tools/run-qemu.sh

@@ -87,8 +87,7 @@ if [ ${ARCH} == "i386" ] || [ ${ARCH} == "x86_64" ]; then
     QEMU_CPU_FEATURES+="-cpu IvyBridge,apic,x2apic,+fpu,check,+vmx,${allflags}"
     QEMU_RTC_CLOCK+=" -rtc clock=host,base=localtime"
 else
-    QEMU_MACHINE=" -machine virt,memory-backend=${QEMU_MEMORY_BACKEND} "
-
+    QEMU_MACHINE=" -machine virt,memory-backend=${QEMU_MEMORY_BACKEND} -cpu sifive-u54 "
 fi
 
 if [ ${ARCH} == "riscv64" ]; then