Browse Source

初始化riscv的内存管理模块,并且设置保留内存 (#506)

LoGin 1 year ago
parent
commit
453452cc02

+ 9 - 2
kernel/src/arch/riscv64/init/mod.rs

@@ -7,7 +7,7 @@ use crate::{
     driver::{firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver},
     init::{boot_params, init_before_mem_init},
     kdebug, kinfo,
-    mm::{PhysAddr, VirtAddr},
+    mm::{init::mm_init, memblock::mem_block_manager, PhysAddr, VirtAddr},
     print, println,
 };
 
@@ -49,12 +49,19 @@ 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();
 
+    for x in mem_block_manager().to_iter() {
+        kdebug!("before efi: {x:?}");
+    }
+
     efi_init();
 
+    open_firmware_fdt_driver().early_init_fdt_scan_reserved_mem();
+
+    mm_init();
     loop {}
     unreachable()
 }

+ 178 - 4
kernel/src/arch/riscv64/mm/init.rs

@@ -1,13 +1,34 @@
+use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
+
+use system_error::SystemError;
+
 use crate::{
-    arch::mm::{KERNEL_BEGIN_PA, KERNEL_BEGIN_VA, KERNEL_END_PA, KERNEL_END_VA},
-    kdebug,
-    mm::{PhysAddr, VirtAddr},
+    arch::{
+        mm::{
+            kernel_page_flags, INNER_ALLOCATOR, KERNEL_BEGIN_PA, KERNEL_BEGIN_VA, KERNEL_END_PA,
+            KERNEL_END_VA,
+        },
+        MMArch,
+    },
+    driver::firmware::efi::efi_manager,
+    kdebug, kinfo,
+    libs::lib_ui::screen_manager::scm_disable_put_to_window,
+    mm::{
+        allocator::{buddy::BuddyAllocator, bump::BumpAllocator, page_frame::FrameAllocator},
+        kernel_mapper::KernelMapper,
+        memblock::mem_block_manager,
+        page::PageEntry,
+        MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
+    },
 };
 
+use super::RiscV64MMArch;
+
+pub(super) static mut INITIAL_PGTABLE_VALUE: PhysAddr = PhysAddr::new(0);
+
 #[inline(never)]
 pub fn mm_early_init() {
     unsafe { init_kernel_addr() };
-    // unsafe { map_initial_page_table_linearly() };
 }
 
 unsafe fn init_kernel_addr() {
@@ -43,3 +64,156 @@ unsafe fn init_kernel_addr() {
     "
     );
 }
+
+pub(super) unsafe fn riscv_mm_init() -> Result<(), SystemError> {
+    mem_block_manager()
+        .reserve_block(KERNEL_BEGIN_PA, KERNEL_END_PA - KERNEL_BEGIN_PA)
+        .expect("Failed to reserve kernel memory");
+
+    let mut bump_allocator = BumpAllocator::<RiscV64MMArch>::new(0);
+    let _old_page_table = MMArch::table(PageTableKind::Kernel);
+    let new_page_table: PhysAddr;
+
+    // 使用bump分配器,把所有的内存页都映射到页表
+    {
+        kdebug!("to create new page table");
+        // 用bump allocator创建新的页表
+        let mut mapper: crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>> =
+            crate::mm::page::PageMapper::<MMArch, _>::create(
+                PageTableKind::Kernel,
+                &mut bump_allocator,
+            )
+            .expect("Failed to create page mapper");
+        new_page_table = mapper.table().phys();
+        kdebug!("PageMapper created");
+
+        // 取消最开始时候,在head.S中指定的映射(暂时不刷新TLB)
+        {
+            let table = mapper.table();
+            let empty_entry = PageEntry::<MMArch>::from_usize(0);
+            for i in 0..MMArch::PAGE_ENTRY_NUM {
+                table
+                    .set_entry(i, empty_entry)
+                    .expect("Failed to empty page table entry");
+            }
+        }
+        kdebug!("Successfully emptied page table");
+
+        let total_num = mem_block_manager().total_initial_memory_regions();
+        for i in 0..total_num {
+            let area = mem_block_manager().get_initial_memory_region(i).unwrap();
+            // kdebug!("area: base={:?}, size={:#x}, end={:?}", area.base, area.size, area.base + area.size);
+            for i in 0..((area.size + MMArch::PAGE_SIZE - 1) / MMArch::PAGE_SIZE) {
+                let paddr = area.base.add(i * MMArch::PAGE_SIZE);
+                let vaddr = unsafe { MMArch::phys_2_virt(paddr) }.unwrap();
+                let flags = kernel_page_flags::<MMArch>(vaddr).set_execute(true);
+
+                let flusher = mapper
+                    .map_phys(vaddr, paddr, flags)
+                    .expect("Failed to map frame");
+                // 暂时不刷新TLB
+                flusher.ignore();
+            }
+        }
+
+        // 添加低地址的映射(在smp完成初始化之前,需要使用低地址的映射.初始化之后需要取消这一段映射)
+        LowAddressRemapping::remap_at_low_address(&mut mapper);
+    }
+
+    unsafe {
+        INITIAL_PGTABLE_VALUE = new_page_table;
+    }
+    kdebug!(
+        "After mapping all physical memory, DragonOS used: {} KB",
+        bump_allocator.usage().used().bytes() / 1024
+    );
+
+    // 初始化buddy_allocator
+    let buddy_allocator = unsafe { BuddyAllocator::<MMArch>::new(bump_allocator).unwrap() };
+    // 设置全局的页帧分配器
+    unsafe { set_inner_allocator(buddy_allocator) };
+    kinfo!("Successfully initialized buddy allocator");
+    // 关闭显示输出
+    scm_disable_put_to_window();
+
+    // make the new page table current
+    {
+        let mut binding = INNER_ALLOCATOR.lock();
+        let mut allocator_guard = binding.as_mut().unwrap();
+        kdebug!("To enable new page table.");
+        compiler_fence(Ordering::SeqCst);
+        let mapper = crate::mm::page::PageMapper::<MMArch, _>::new(
+            PageTableKind::Kernel,
+            new_page_table,
+            &mut allocator_guard,
+        );
+        compiler_fence(Ordering::SeqCst);
+        mapper.make_current();
+        compiler_fence(Ordering::SeqCst);
+        // kdebug!("New page table enabled");
+    }
+    kdebug!("Successfully enabled new page table");
+    kinfo!("riscv mm init done");
+
+    return Ok(());
+}
+
+unsafe fn set_inner_allocator(allocator: BuddyAllocator<MMArch>) {
+    static FLAG: AtomicBool = AtomicBool::new(false);
+    if FLAG
+        .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
+        .is_err()
+    {
+        panic!("Cannot set inner allocator twice!");
+    }
+    *INNER_ALLOCATOR.lock() = Some(allocator);
+}
+
+/// 低地址重映射的管理器
+///
+/// 低地址重映射的管理器,在smp初始化完成之前,需要使用低地址的映射,因此需要在smp初始化完成之后,取消这一段映射
+pub struct LowAddressRemapping;
+
+impl LowAddressRemapping {
+    pub unsafe fn remap_at_low_address(
+        mapper: &mut crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>>,
+    ) {
+        let info = efi_manager().kernel_load_info().unwrap();
+        let base = PhysAddr::new(info.paddr as usize);
+        let size = info.size as usize;
+
+        for i in 0..(size / MMArch::PAGE_SIZE) {
+            let paddr = PhysAddr::new(base.data() + i * MMArch::PAGE_SIZE);
+            let vaddr = VirtAddr::new(base.data() + i * MMArch::PAGE_SIZE);
+            let flags = kernel_page_flags::<MMArch>(vaddr).set_execute(true);
+
+            let flusher = mapper
+                .map_phys(vaddr, paddr, flags)
+                .expect("Failed to map frame");
+            // 暂时不刷新TLB
+            flusher.ignore();
+        }
+    }
+
+    /// 取消低地址的映射
+    pub unsafe fn unmap_at_low_address(flush: bool) {
+        let mut mapper = KernelMapper::lock();
+        assert!(mapper.as_mut().is_some());
+
+        let info = efi_manager().kernel_load_info().unwrap();
+        let base = PhysAddr::new(info.paddr as usize);
+        let size = info.size as usize;
+
+        for i in 0..(size / MMArch::PAGE_SIZE) {
+            let vaddr = VirtAddr::new(base.data() + i * MMArch::PAGE_SIZE);
+            let (_, _, flusher) = mapper
+                .as_mut()
+                .unwrap()
+                .unmap_phys(vaddr, true)
+                .expect("Failed to unmap frame");
+            if flush == false {
+                flusher.ignore();
+            }
+        }
+    }
+}

+ 36 - 11
kernel/src/arch/riscv64/mm/mod.rs

@@ -1,12 +1,21 @@
 use riscv::register::satp;
 use system_error::SystemError;
 
-use crate::mm::{
-    allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
-    page::PageFlags,
-    MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
+use crate::{
+    arch::MMArch,
+    libs::spinlock::SpinLock,
+    mm::{
+        allocator::{
+            buddy::BuddyAllocator,
+            page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
+        },
+        page::PageFlags,
+        MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
+    },
 };
 
+use self::init::riscv_mm_init;
+
 pub mod bump;
 pub(super) mod init;
 
@@ -21,6 +30,8 @@ pub(self) static mut KERNEL_BEGIN_VA: VirtAddr = VirtAddr::new(0);
 /// 内核结束虚拟地址
 pub(self) static mut KERNEL_END_VA: VirtAddr = VirtAddr::new(0);
 
+pub(self) static INNER_ALLOCATOR: SpinLock<Option<BuddyAllocator<MMArch>>> = SpinLock::new(None);
+
 /// RiscV64的内存管理架构结构体(sv39)
 #[derive(Debug, Clone, Copy, Hash)]
 pub struct RiscV64MMArch;
@@ -65,6 +76,7 @@ impl MemoryManagementArch for RiscV64MMArch {
     const ENTRY_FLAG_DIRTY: usize = (1 << 7);
 
     const PHYS_OFFSET: usize = 0xffff_ffc0_0000_0000;
+    const KERNEL_LINK_OFFSET: usize = 0x1000000;
 
     const USER_END_VADDR: crate::mm::VirtAddr = VirtAddr::new(0x0000_003f_ffff_ffff);
 
@@ -77,8 +89,9 @@ impl MemoryManagementArch for RiscV64MMArch {
     /// 设置1MB的fixmap空间
     const FIXMAP_SIZE: usize = 256 * 4096;
 
+    #[inline(never)]
     unsafe fn init() {
-        todo!()
+        riscv_mm_init().expect("init kernel memory management architecture failed");
     }
 
     unsafe fn invalidate_page(address: VirtAddr) {
@@ -147,7 +160,7 @@ 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;
+        let r = ((ppn & ((1 << 54) - 1)) << 10) | page_flags;
         return r;
     }
 }
@@ -164,8 +177,10 @@ impl VirtAddr {
 }
 
 /// 获取内核地址默认的页面标志
-pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(virt: VirtAddr) -> PageFlags<A> {
-    unimplemented!("riscv64::kernel_page_flags")
+pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> {
+    PageFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE)
+        .set_user(false)
+        .set_execute(true)
 }
 
 /// 全局的页帧分配器
@@ -174,15 +189,25 @@ pub struct LockedFrameAllocator;
 
 impl FrameAllocator for LockedFrameAllocator {
     unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
-        unimplemented!("RiscV64 LockedFrameAllocator::allocate")
+        if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
+            return allocator.allocate(count);
+        } else {
+            return None;
+        }
     }
 
     unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) {
         assert!(count.data().is_power_of_two());
-        unimplemented!("RiscV64 LockedFrameAllocator::free")
+        if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
+            return allocator.free(address, count);
+        }
     }
 
     unsafe fn usage(&self) -> PageFrameUsage {
-        unimplemented!("RiscV64 LockedFrameAllocator::usage")
+        if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
+            return allocator.usage();
+        } else {
+            panic!("usage error");
+        }
     }
 }

+ 1 - 1
kernel/src/arch/riscv64/time.rs

@@ -3,6 +3,6 @@ pub struct RiscV64TimeArch;
 
 impl TimeArch for RiscV64TimeArch {
     fn get_cycles() -> usize {
-        unimplemented!("Riscv64TimeArch::get_cycles")
+        riscv::register::cycle::read()
     }
 }

+ 12 - 41
kernel/src/arch/x86_64/mm/mod.rs

@@ -8,19 +8,16 @@ use x86::time::rdtsc;
 use x86_64::registers::model_specific::EferFlags;
 
 use crate::driver::tty::serial::serial8250::send_to_default_serial8250_port;
-use crate::filesystem::procfs::kmsg::kmsg_init;
 use crate::include::bindings::bindings::{
     multiboot2_get_load_base, multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t,
     multiboot_tag_load_base_addr_t,
 };
 use crate::libs::align::page_align_up;
 use crate::libs::lib_ui::screen_manager::scm_disable_put_to_window;
-use crate::libs::printk::PrintkWriter;
 use crate::libs::spinlock::SpinLock;
 
 use crate::mm::allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage};
 use crate::mm::memblock::mem_block_manager;
-use crate::mm::mmio_buddy::mmio_init;
 use crate::{
     arch::MMArch,
     mm::allocator::{buddy::BuddyAllocator, bump::BumpAllocator},
@@ -34,7 +31,7 @@ use system_error::SystemError;
 
 use core::arch::asm;
 use core::ffi::c_void;
-use core::fmt::{Debug, Write};
+use core::fmt::Debug;
 use core::mem::{self};
 
 use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
@@ -114,6 +111,7 @@ impl MemoryManagementArch for X86_64MMArch {
     /// 物理地址与虚拟地址的偏移量
     /// 0xffff_8000_0000_0000
     const PHYS_OFFSET: usize = Self::PAGE_NEGATIVE_MASK + (Self::PAGE_ADDRESS_SIZE >> 1);
+    const KERNEL_LINK_OFFSET: usize = 0x100000;
 
     // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/include/asm/page_64_types.h#75
     const USER_END_VADDR: VirtAddr =
@@ -154,7 +152,14 @@ impl MemoryManagementArch for X86_64MMArch {
         // 初始化物理内存区域(从multiboot2中获取)
         Self::init_memory_area_from_multiboot2().expect("init memory area failed");
 
-        send_to_default_serial8250_port("x86 64 init end\n\0".as_bytes());
+        kdebug!("bootstrap info: {:?}", unsafe { BOOTSTRAP_MM_INFO });
+        kdebug!("phys[0]=virt[0x{:x}]", unsafe {
+            MMArch::phys_2_virt(PhysAddr::new(0)).unwrap().data()
+        });
+
+        // 初始化内存管理器
+        unsafe { allocator_init() };
+        send_to_default_serial8250_port("x86 64 init done\n\0".as_bytes());
     }
 
     /// @brief 刷新TLB中,关于指定虚拟地址的条目
@@ -399,36 +404,6 @@ impl VirtAddr {
     }
 }
 
-/// @brief 初始化内存管理模块
-pub fn mm_init() {
-    send_to_default_serial8250_port("mm_init\n\0".as_bytes());
-    PrintkWriter
-        .write_fmt(format_args!("mm_init() called\n"))
-        .unwrap();
-    // printk_color!(GREEN, BLACK, "mm_init() called\n");
-    static _CALL_ONCE: AtomicBool = AtomicBool::new(false);
-    if _CALL_ONCE
-        .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
-        .is_err()
-    {
-        send_to_default_serial8250_port("mm_init err\n\0".as_bytes());
-        panic!("mm_init() can only be called once");
-    }
-
-    unsafe { X86_64MMArch::init() };
-    kdebug!("bootstrap info: {:?}", unsafe { BOOTSTRAP_MM_INFO });
-    kdebug!("phys[0]=virt[0x{:x}]", unsafe {
-        MMArch::phys_2_virt(PhysAddr::new(0)).unwrap().data()
-    });
-
-    // 初始化内存管理器
-    unsafe { allocator_init() };
-    // enable mmio
-    mmio_init();
-    // enable KMSG
-    kmsg_init();
-}
-
 unsafe fn allocator_init() {
     let virt_offset = BOOTSTRAP_MM_INFO.unwrap().start_brk;
     let phy_offset =
@@ -681,8 +656,8 @@ unsafe fn set_inner_allocator(allocator: BuddyAllocator<MMArch>) {
 pub struct LowAddressRemapping;
 
 impl LowAddressRemapping {
-    // 映射32M
-    const REMAP_SIZE: usize = 32 * 1024 * 1024;
+    // 映射64M
+    const REMAP_SIZE: usize = 64 * 1024 * 1024;
 
     pub unsafe fn remap_at_low_address(
         mapper: &mut crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>>,
@@ -717,7 +692,3 @@ impl LowAddressRemapping {
         }
     }
 }
-#[no_mangle]
-pub extern "C" fn rs_mm_init() {
-    mm_init();
-}

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

@@ -12,6 +12,23 @@ pub static DRAGONSTUB_EFI_PAYLOAD_EFI_GUID: Guid = Guid::new(
     [0xbc, 0xef, 0x98, 0x12, 0x00, 0x31],
 );
 
+pub static EFI_MEMORY_ATTRIBUTES_TABLE_GUID: Guid = Guid::new(
+    unsafe { mem::transmute_copy(&0xdcfa911du32) },
+    unsafe { mem::transmute_copy(&0x26ebu32) },
+    unsafe { mem::transmute_copy(&0x469fu32) },
+    0xa2,
+    0x20,
+    [0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20],
+);
+
+pub static EFI_MEMRESERVE_TABLE_GUID: Guid = Guid::new(
+    unsafe { mem::transmute_copy(&0x888eb0c6u32) },
+    unsafe { mem::transmute_copy(&0x8edeu32) },
+    unsafe { mem::transmute_copy(&0x4ff5u32) },
+    0xa8,
+    0xf0,
+    [0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2],
+);
 /// 表示内核被加载到的地址的信息。
 ///
 /// 对应 `DRAGONSTUB_EFI_PAYLOAD_EFI_GUID`

+ 12 - 1
kernel/src/driver/firmware/efi/init.rs

@@ -75,6 +75,16 @@ pub fn efi_init() {
         )
         .expect("Failed to reserve memory for EFI mmap table");
 
+    // 保留内核的内存
+    if let Some(info) = efi_manager().inner.read().dragonstub_load_info.clone() {
+        mem_block_manager()
+            .reserve_block(
+                PhysAddr::new(info.paddr as usize),
+                page_align_up(info.size as usize),
+            )
+            .expect("Failed to reserve kernel itself memory");
+    }
+
     // todo: Initialize screen info
 
     kinfo!("UEFI init done!");
@@ -212,7 +222,7 @@ fn reserve_memory_regions() {
     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,
+            (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())
@@ -220,6 +230,7 @@ fn reserve_memory_regions() {
         let phys_start = page_align_down(md.phys_start as usize);
         let size = (page_count << (MMArch::PAGE_SHIFT as u64)) as usize;
 
+        // kdebug!("Reserve memory region: {:#x}-{:#x}({:#x}), is_memory: {}, is_usable_memory:{}, type: {:?}, att: {:?}", phys_start, phys_start + size, page_count, md.is_memory(), md.is_usable_memory(), md.ty, md.att);
         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() {

+ 12 - 0
kernel/src/driver/firmware/efi/mod.rs

@@ -35,6 +35,10 @@ struct InnerEFIManager {
     /// runtime services的版本号
     pub runtime_service_version: Option<uefi_raw::table::Revision>,
     pub dragonstub_load_info: Option<DragonStubPayloadEFI>,
+    /// uefi 内存属性表的物理地址
+    pub memory_attribute_table_paddr: Option<PhysAddr>,
+    /// uefi 内存保留表的物理地址
+    pub memreserve_table_paddr: Option<PhysAddr>,
 }
 
 impl EFIManager {
@@ -46,6 +50,8 @@ impl EFIManager {
                 runtime_paddr: None,
                 runtime_service_version: None,
                 dragonstub_load_info: None,
+                memory_attribute_table_paddr: None,
+                memreserve_table_paddr: None,
             }),
         }
     }
@@ -54,6 +60,12 @@ impl EFIManager {
         return self.inner.read().mmap.desc_version;
     }
 
+    /// 内核加载的地址、大小的信息
+    #[allow(dead_code)]
+    pub fn kernel_load_info(&self) -> Option<DragonStubPayloadEFI> {
+        return self.inner.read().dragonstub_load_info;
+    }
+
     /// 检查是否为有效的system table表头
     ///
     /// ## 参数

+ 263 - 20
kernel/src/driver/firmware/efi/tables.rs

@@ -8,14 +8,28 @@ use uefi_raw::table::{
 };
 
 use crate::{
+    arch::MMArch,
     driver::firmware::efi::{
         efi_manager,
         guid::{DragonStubPayloadEFI, DRAGONSTUB_EFI_PAYLOAD_EFI_GUID},
     },
-    mm::{early_ioremap::EarlyIoRemap, PhysAddr},
+    mm::{
+        early_ioremap::EarlyIoRemap, memblock::mem_block_manager, MemoryManagementArch, PhysAddr,
+        VirtAddr,
+    },
+};
+
+use super::{
+    guid::{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, EFI_MEMRESERVE_TABLE_GUID},
+    EFIManager,
 };
 
-use super::EFIManager;
+/// 所有的要解析的表格的解析器
+static TABLE_PARSERS: &'static [&'static TableMatcher] = &[
+    &TableMatcher::new(&MatchTableDragonStubPayloadEFI),
+    &TableMatcher::new(&MatchTableMemoryAttributes),
+    &TableMatcher::new(&MatchTableMemReserve),
+];
 
 impl EFIManager {
     /// 显示EFI系统表头的信息
@@ -64,25 +78,81 @@ impl EFIManager {
     /// 解析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 mut flag = false;
+            'parser_loop: for parser in TABLE_PARSERS {
+                if let Some(r) = parser.match_table(table) {
+                    // 有匹配结果
+                    if let Err(e) = r {
+                        kwarn!(
+                            "Failed to parse cfg table: '{}', err: {e:?}",
+                            parser.table.name()
+                        );
+                    }
+                    flag = true;
+                    break 'parser_loop;
+                }
+            }
 
-                let data = unsafe { *(vaddr.data() as *const DragonStubPayloadEFI) };
+            if !flag {
+                kwarn!("Cannot find parser for guid: {:?}", table.vendor_guid);
+            }
+        }
+
+        // 如果存在mem reserve table
+        if let Some(mem_reserve) = efi_manager().inner.read().memreserve_table_paddr {
+            let mut prev_paddr = mem_reserve;
+            while !prev_paddr.is_null() {
+                let vaddr = EarlyIoRemap::map_not_aligned(prev_paddr, MMArch::PAGE_SIZE, true)
+                    .map_err(|e| {
+                        kerror!(
+                            "Failed to map UEFI memreserve table, paddr: {prev_paddr:?}, err: {e:?}"
+                        );
+
+                        SystemError::ENOMEM
+                    })?;
 
-                efi_manager().inner.write().dragonstub_load_info = Some(data);
+                let p = unsafe {
+                    (vaddr.data() as *const LinuxEFIMemReserveTable)
+                        .as_ref()
+                        .unwrap()
+                };
 
+                // reserve the entry itself
+                let psize: usize = p.size.try_into().unwrap();
+                mem_block_manager()
+                    .reserve_block(
+                        prev_paddr,
+                        size_of::<LinuxEFIMemReserveTable>()
+                            + size_of::<LinuxEFIMemReserveEntry>() * psize,
+                    )
+                    .map_err(|e| {
+                        kerror!("Failed to reserve block, paddr: {prev_paddr:?}, err: {e:?}");
+                        EarlyIoRemap::unmap(vaddr).unwrap();
+                        e
+                    })?;
+
+                let entries = unsafe {
+                    core::slice::from_raw_parts(
+                        (vaddr.data() as *const LinuxEFIMemReserveTable).add(1)
+                            as *const LinuxEFIMemReserveEntry,
+                        p.count as usize,
+                    )
+                };
+                // reserve the entries
+                for entry in entries {
+                    mem_block_manager()
+                        .reserve_block(PhysAddr::new(entry.base), entry.size)
+                        .map_err(|e| {
+                            kerror!("Failed to reserve block, paddr: {prev_paddr:?}, err: {e:?}");
+                            EarlyIoRemap::unmap(vaddr).unwrap();
+                            e
+                        })?;
+                }
+
+                prev_paddr = p.next_paddr;
                 EarlyIoRemap::unmap(vaddr).unwrap();
             }
         }
-
         return Ok(());
     }
 }
@@ -111,11 +181,10 @@ impl MemoryDescriptor {
     /// 当前内存描述符是否表示真实的内存
     #[inline]
     pub fn is_memory(&self) -> bool {
-        if self.att.contains(
-            MemoryAttribute::WRITE_BACK
-                | MemoryAttribute::WRITE_THROUGH
-                | MemoryAttribute::WRITE_COMBINE,
-        ) {
+        if self.att.contains(MemoryAttribute::WRITE_BACK)
+            || self.att.contains(MemoryAttribute::WRITE_THROUGH)
+            || self.att.contains(MemoryAttribute::WRITE_COMBINE)
+        {
             return true;
         }
 
@@ -165,3 +234,177 @@ impl Default for MemoryDescriptor {
         }
     }
 }
+
+trait MatchTable: Send + Sync {
+    /// 配置表名(仅用于日志显示)
+    fn name(&self) -> &'static str;
+
+    /// 当前table的guid
+    fn guid(&self) -> &'static uefi_raw::Guid;
+
+    /// 匹配阶段时,匹配器要映射vendor_table的大小。
+    ///
+    /// 如果为0,则不映射
+    fn map_size(&self) -> usize;
+
+    /// 当表格被映射后,调用这个函数
+    ///
+    /// ## 锁
+    ///
+    /// 进入该函数前,不得持有efi_manager().inner的任何锁
+    fn post_process(
+        &self,
+        vendor_table_vaddr: Option<VirtAddr>,
+        table_raw: &ConfigurationTable,
+    ) -> Result<(), SystemError>;
+}
+
+/// `DRAGONSTUB_EFI_PAYLOAD_EFI_GUID` 的匹配器
+struct MatchTableDragonStubPayloadEFI;
+
+impl MatchTable for MatchTableDragonStubPayloadEFI {
+    fn name(&self) -> &'static str {
+        "DragonStub Payload"
+    }
+
+    fn guid(&self) -> &'static uefi_raw::Guid {
+        &DRAGONSTUB_EFI_PAYLOAD_EFI_GUID
+    }
+
+    fn map_size(&self) -> usize {
+        core::mem::size_of::<DragonStubPayloadEFI>()
+    }
+
+    fn post_process(
+        &self,
+        vendor_table_vaddr: Option<VirtAddr>,
+        _table_raw: &ConfigurationTable,
+    ) -> Result<(), SystemError> {
+        let vendor_table_vaddr = vendor_table_vaddr.unwrap();
+        let data = unsafe { *(vendor_table_vaddr.data() as *const DragonStubPayloadEFI) };
+
+        efi_manager().inner.write().dragonstub_load_info = Some(data);
+
+        return Ok(());
+    }
+}
+
+struct MatchTableMemoryAttributes;
+
+impl MatchTable for MatchTableMemoryAttributes {
+    fn name(&self) -> &'static str {
+        "MemAttr"
+    }
+
+    fn guid(&self) -> &'static uefi_raw::Guid {
+        &EFI_MEMORY_ATTRIBUTES_TABLE_GUID
+    }
+
+    fn map_size(&self) -> usize {
+        // 不映射
+        0
+    }
+
+    fn post_process(
+        &self,
+        _vendor_table_vaddr: Option<VirtAddr>,
+        table_raw: &ConfigurationTable,
+    ) -> Result<(), SystemError> {
+        efi_manager()
+            .inner
+            .write_irqsave()
+            .memory_attribute_table_paddr = Some(PhysAddr::new(table_raw.vendor_table as usize));
+        return Ok(());
+    }
+}
+
+struct MatchTableMemReserve;
+
+impl MatchTable for MatchTableMemReserve {
+    fn name(&self) -> &'static str {
+        "MemReserve"
+    }
+
+    fn guid(&self) -> &'static uefi_raw::Guid {
+        &EFI_MEMRESERVE_TABLE_GUID
+    }
+
+    fn map_size(&self) -> usize {
+        // 不映射
+        0
+    }
+
+    fn post_process(
+        &self,
+        _vendor_table_vaddr: Option<VirtAddr>,
+        table_raw: &ConfigurationTable,
+    ) -> Result<(), SystemError> {
+        efi_manager().inner.write_irqsave().memreserve_table_paddr =
+            Some(PhysAddr::new(table_raw.vendor_table as usize));
+        kdebug!(
+            "memreserve_table_paddr: {:#x}",
+            table_raw.vendor_table as usize
+        );
+        return Ok(());
+    }
+}
+
+/// 用于匹配配置表的匹配器
+struct TableMatcher {
+    table: &'static dyn MatchTable,
+}
+
+impl TableMatcher {
+    const fn new(table: &'static dyn MatchTable) -> Self {
+        Self { table }
+    }
+
+    /// 判断配置表与当前匹配器是否匹配
+    #[inline(never)]
+    fn match_table(&self, table: &ConfigurationTable) -> Option<Result<(), SystemError>> {
+        if table.vendor_guid.equivalent(self.table.guid()) == false {
+            return None;
+        }
+
+        let table_map_size = self.table.map_size();
+        let vendor_table_vaddr: Option<VirtAddr>;
+        if table_map_size > 0 {
+            let table_paddr: PhysAddr = PhysAddr::new(table.vendor_table as usize);
+            let vaddr = EarlyIoRemap::map_not_aligned(table_paddr, table_map_size, true);
+
+            if let Err(e) = vaddr {
+                return Some(Err(e));
+            }
+
+            vendor_table_vaddr = Some(vaddr.unwrap());
+        } else {
+            vendor_table_vaddr = None;
+        }
+
+        let r = self.table.post_process(vendor_table_vaddr, table);
+
+        if let Some(vaddr) = vendor_table_vaddr {
+            EarlyIoRemap::unmap(vaddr).unwrap();
+        }
+        return Some(r);
+    }
+}
+
+#[repr(C)]
+#[derive(Debug)]
+struct LinuxEFIMemReserveTable {
+    /// allocated size of the array
+    size: i32,
+    /// number of entries used
+    count: i32,
+    /// pa of next struct instance
+    next_paddr: PhysAddr,
+    entry: [LinuxEFIMemReserveEntry; 0],
+}
+
+#[repr(C)]
+#[derive(Debug)]
+struct LinuxEFIMemReserveEntry {
+    base: usize,
+    size: usize,
+}

+ 210 - 49
kernel/src/driver/open_firmware/fdt.rs

@@ -1,10 +1,16 @@
+use core::mem::size_of;
+
 use fdt::{
     node::{FdtNode, NodeProperty},
     Fdt,
 };
 use system_error::SystemError;
 
-use crate::{init::boot_params, libs::rwlock::RwLock};
+use crate::{
+    init::boot_params,
+    libs::rwlock::RwLock,
+    mm::{memblock::mem_block_manager, PhysAddr},
+};
 
 #[inline(always)]
 pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver {
@@ -72,13 +78,13 @@ impl OpenFirmwareFdtDriver {
         if let Some(prop) = node.property("#size-cells") {
             guard.root_size_cells = prop.as_usize().unwrap() as u32;
 
-            kdebug!("fdt_root_size_cells={}", guard.root_size_cells);
+            // kdebug!("fdt_root_size_cells={}", guard.root_size_cells);
         }
 
         if let Some(prop) = node.property("#address-cells") {
             guard.root_addr_cells = prop.as_usize().unwrap() as u32;
 
-            kdebug!("fdt_root_addr_cells={}", guard.root_addr_cells);
+            // kdebug!("fdt_root_addr_cells={}", guard.root_addr_cells);
         }
 
         return Ok(());
@@ -151,41 +157,10 @@ impl OpenFirmwareFdtDriver {
             let total_elements_in_reg = reg.value.len() / ((addr_cells + size_cells) * 4);
 
             for i in 0..total_elements_in_reg {
-                let mut base_index = i * (addr_cells + size_cells);
-                let base: u64;
-                let size: u64;
-                match addr_cells {
-                    1 => {
-                        base = u32::from_be_bytes(
-                            reg.value[base_index..base_index + 4].try_into().unwrap(),
-                        ) as u64;
-                    }
-                    2 => {
-                        base = u64::from_be_bytes(
-                            reg.value[base_index..base_index + 8].try_into().unwrap(),
-                        );
-                    }
-                    _ => {
-                        panic!("addr_cells must be 1 or 2");
-                    }
-                }
-                base_index += addr_cells * 4;
-
-                match size_cells {
-                    1 => {
-                        size = u32::from_be_bytes(
-                            reg.value[base_index..base_index + 4].try_into().unwrap(),
-                        ) as u64;
-                    }
-                    2 => {
-                        size = u64::from_be_bytes(
-                            reg.value[base_index..base_index + 8].try_into().unwrap(),
-                        );
-                    }
-                    _ => {
-                        panic!("size_cells must be 1 or 2");
-                    }
-                }
+                let base_index = i * (addr_cells + size_cells);
+
+                let (base, base_index) = read_cell(reg.value, base_index, addr_cells);
+                let (size, _) = read_cell(reg.value, base_index, size_cells);
 
                 if size == 0 {
                     continue;
@@ -258,20 +233,21 @@ impl OpenFirmwareFdtDriver {
                 size -= MemBlockManager::MIN_MEMBLOCK_ADDR.data() - base;
                 base = MemBlockManager::MIN_MEMBLOCK_ADDR.data();
             }
-
-            mem_block_manager()
-                .add_block(PhysAddr::new(base), size)
-                .unwrap_or_else(|e| {
-                    panic!(
-                        "Failed to add memory block '{:#x}-{:#x}', err={:?}",
-                        base,
-                        base + size,
-                        e
-                    );
-                });
         }
+
+        mem_block_manager()
+            .add_block(PhysAddr::new(base), size)
+            .unwrap_or_else(|e| {
+                panic!(
+                    "Failed to add memory block '{:#x}-{:#x}', err={:?}",
+                    base,
+                    base + size,
+                    e
+                );
+            });
     }
 
+    /// 判断设备是否可用
     fn is_device_avaliable(&self, node: &FdtNode) -> bool {
         let status = node.property("status");
         if status.is_none() {
@@ -287,4 +263,189 @@ impl OpenFirmwareFdtDriver {
 
         return false;
     }
+
+    /// 在UEFI初始化后,扫描FDT中的`/reserved-memory`节点,设置保留的内存
+    ///
+    /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/of/fdt.c#634
+    pub fn early_init_fdt_scan_reserved_mem(&self) {
+        let vaddr = boot_params().read().fdt();
+        if vaddr.is_none() {
+            return;
+        }
+        let vaddr = vaddr.unwrap();
+        let fdt = unsafe { Fdt::from_ptr(vaddr.data() as *const u8) };
+        if fdt.is_err() {
+            return;
+        }
+
+        let fdt = fdt.unwrap();
+        self.early_reserve_fdt_itself(&fdt);
+
+        let reserved_mem_nodes = fdt.memory_reservations();
+
+        for node in reserved_mem_nodes {
+            if node.size() != 0 {
+                let address = PhysAddr::new(node.address() as usize);
+                let size = node.size();
+                kdebug!("Reserve memory: {:?}-{:?}", address, address + size);
+                mem_block_manager().reserve_block(address, size).unwrap();
+            }
+        }
+
+        self.fdt_scan_reserved_mem(&fdt)
+            .expect("Failed to scan reserved memory");
+    }
+
+    /// 保留fdt自身的内存空间
+
+    fn early_reserve_fdt_itself(&self, fdt: &Fdt) {
+        #[cfg(target_arch = "riscv64")]
+        {
+            use crate::libs::align::{page_align_down, page_align_up};
+
+            let fdt_paddr = boot_params().read().arch.fdt_paddr;
+            let rsvd_start = PhysAddr::new(page_align_down(fdt_paddr.data()));
+            let rsvd_size = page_align_up(fdt_paddr.data() - rsvd_start.data() + fdt.total_size());
+            mem_block_manager()
+                .reserve_block(rsvd_start, rsvd_size)
+                .expect("Failed to reserve memory for fdt");
+        }
+
+        #[cfg(target_arch = "x86_64")]
+        {
+            let _ = fdt;
+        }
+    }
+
+    fn fdt_scan_reserved_mem(&self, fdt: &Fdt) -> Result<(), SystemError> {
+        let node = fdt
+            .find_node("/reserved-memory")
+            .ok_or(SystemError::ENODEV)?;
+
+        for child in node.children() {
+            if !self.is_device_avaliable(&child) {
+                continue;
+            }
+
+            reserved_mem_reserve_reg(&child).ok();
+        }
+
+        return Ok(());
+    }
+
+    fn early_init_dt_reserve_memory(
+        &self,
+        base: PhysAddr,
+        size: usize,
+        nomap: bool,
+    ) -> Result<(), SystemError> {
+        if nomap {
+            if mem_block_manager().is_overlapped(base, size)
+                && mem_block_manager().is_overlapped_with_reserved(base, size)
+            {
+                // 如果内存已经被其他区域预留(即已经被映射),我们不应该允许它被标记为`nomap`,
+                // 但是不需要担心如果该区域不是内存(即不会被映射)的情况。
+                return Err(SystemError::EBUSY);
+            }
+
+            return mem_block_manager().mark_nomap(base, size);
+        }
+
+        return mem_block_manager().reserve_block(base, size);
+    }
+}
+
+#[allow(dead_code)]
+fn reserved_mem_reserve_reg(node: &FdtNode<'_, '_>) -> Result<(), SystemError> {
+    let global_data_guard: crate::libs::rwlock::RwLockReadGuard<'_, FdtGlobalData> =
+        FDT_GLOBAL_DATA.read();
+    let t_len = ((global_data_guard.root_addr_cells + global_data_guard.root_size_cells) as usize)
+        * size_of::<u32>();
+    drop(global_data_guard);
+
+    let reg = node.property("reg").ok_or(SystemError::ENOENT)?;
+
+    let mut reg_size = reg.value.len();
+    if reg_size > 0 && reg_size % t_len != 0 {
+        kerror!(
+            "Reserved memory: invalid reg property in '{}', skipping node.",
+            node.name
+        );
+        return Err(SystemError::EINVAL);
+    }
+    // 每个cell是4字节
+    let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize;
+    let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize;
+
+    let nomap = node.property("no-map").is_some();
+
+    let mut base_index = 0;
+
+    while reg_size >= t_len {
+        let (base, bi) = read_cell(reg.value, base_index, addr_cells);
+        base_index = bi;
+        let (size, bi) = read_cell(reg.value, base_index, size_cells);
+        base_index = bi;
+
+        if size > 0
+            && open_firmware_fdt_driver()
+                .early_init_dt_reserve_memory(PhysAddr::new(base as usize), size as usize, nomap)
+                .is_ok()
+        {
+            kdebug!(
+                "Reserved memory: base={:#x}, size={:#x}, nomap={}",
+                base,
+                size,
+                nomap
+            );
+        } else {
+            kerror!(
+                "Failed to reserve memory: base={:#x}, size={:#x}, nomap={}",
+                base,
+                size,
+                nomap
+            );
+        }
+
+        reg_size -= t_len;
+
+        // todo: linux这里保存了节点,但是我感觉现在还用不着。
+    }
+
+    return Ok(());
+}
+
+/// 从FDT的`reg`属性中读取指定数量的cell,作为一个小端u64返回
+///
+/// ## 参数
+///
+/// - `reg_value`:`reg`属性数组的引用
+/// - `base_index`:起始索引
+/// - `cells`:要读取的cell数量,必须是1或2
+///
+/// ## 返回值
+///
+/// (value, next_base_index)
+fn read_cell(reg_value: &[u8], base_index: usize, cells: usize) -> (u64, usize) {
+    let next_base_index = base_index + cells * 4;
+    match cells {
+        1 => {
+            return (
+                u32::from_be_bytes(reg_value[base_index..base_index + 4].try_into().unwrap())
+                    .try_into()
+                    .unwrap(),
+                next_base_index,
+            );
+        }
+
+        2 => {
+            return (
+                u64::from_be_bytes(reg_value[base_index..base_index + 8].try_into().unwrap()),
+                next_base_index,
+            );
+        }
+        _ => {
+            panic!("cells must be 1 or 2");
+        }
+    }
 }

+ 7 - 0
kernel/src/filesystem/procfs/kmsg.rs

@@ -1,3 +1,5 @@
+use core::sync::atomic::{compiler_fence, Ordering};
+
 use super::log::{LogLevel, LogMessage};
 
 use crate::libs::spinlock::SpinLock;
@@ -16,8 +18,13 @@ pub static mut KMSG: Option<SpinLock<Kmsg>> = None;
 
 /// 初始化KMSG
 pub fn kmsg_init() {
+    kinfo!("kmsg_init");
     let kmsg = SpinLock::new(Kmsg::new());
+
+    compiler_fence(Ordering::SeqCst);
     unsafe { KMSG = Some(kmsg) };
+    compiler_fence(Ordering::SeqCst);
+    kinfo!("kmsg_init done");
 }
 
 /// 日志

+ 12 - 2
kernel/src/init/mod.rs

@@ -7,7 +7,7 @@ use crate::{
         video::{fbdev::base::BootTimeScreenInfo, VideoRefreshManager},
     },
     libs::{lib_ui::screen_manager::scm_init, rwlock::RwLock},
-    mm::VirtAddr,
+    mm::{PhysAddr, VirtAddr},
 };
 
 mod c_adapter;
@@ -102,7 +102,7 @@ impl BootParams {
         self.boot_command_line[pos + len] = 0;
     }
 
-    /// 获取FDT的物理地址
+    /// 获取FDT的虚拟地址
     #[allow(dead_code)]
     pub fn fdt(&self) -> Option<VirtAddr> {
         #[cfg(target_arch = "riscv64")]
@@ -111,4 +111,14 @@ impl BootParams {
         #[cfg(target_arch = "x86_64")]
         return None;
     }
+
+    /// 获取FDT的物理地址
+    #[allow(dead_code)]
+    pub fn fdt_paddr(&self) -> Option<PhysAddr> {
+        #[cfg(target_arch = "riscv64")]
+        return Some(self.arch.fdt_paddr);
+
+        #[cfg(target_arch = "x86_64")]
+        return None;
+    }
 }

+ 2 - 1
kernel/src/libs/printk.rs

@@ -116,9 +116,10 @@ pub struct Logger;
 
 impl Logger {
     pub fn log(&self, log_level: usize, message: fmt::Arguments) {
-        if unsafe { !KMSG.is_none() } {
+        if unsafe { KMSG.is_some() } {
             let timestamp: TimeSpec = TimeSpec::now();
             let log_level = LogLevel::from(log_level.clone());
+
             let log_message = LogMessage::new(timestamp, log_level, message.to_string());
 
             unsafe { KMSG.as_ref().unwrap().lock_irqsave().push(log_message) };

+ 6 - 3
kernel/src/mm/allocator/buddy.rs

@@ -110,13 +110,16 @@ impl<A: MemoryManagementArch> BuddyAllocator<A> {
 
         let remain_areas = &res_areas[0..];
 
-        kdebug!("Remain areas: {:?}", &remain_areas[0..10]);
-        kdebug!("offset_in_remain_area: {:?}", offset_in_remain_area);
-
         for area in remain_areas {
             let mut paddr = (area.area_base_aligned() + offset_in_remain_area).data();
             let mut remain_pages =
                 PageFrameCount::from_bytes(area.area_end_aligned().data() - paddr).unwrap();
+
+            if remain_pages.data() == 0 {
+                continue;
+            }
+            kdebug!("area: {area:?}, paddr: {paddr:#x}, remain_pages: {remain_pages:?}");
+
             total_pages_to_buddy += remain_pages;
 
             if offset_in_remain_area != 0 {

+ 67 - 33
kernel/src/mm/allocator/bump.rs

@@ -3,7 +3,14 @@
 /// @FilePath: /DragonOS/kernel/src/mm/allocator/bump.rs
 /// @Description: bump allocator线性分配器
 use super::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage};
-use crate::mm::{memblock::mem_block_manager, MemoryManagementArch, PhysAddr, PhysMemoryArea};
+use crate::mm::{
+    allocator::page_frame::{PhysPageFrame, PhysPageFrameIter},
+    init::{mm_init_status, MMInitStatus},
+    memblock::mem_block_manager,
+    no_init::pseudo_map_phys,
+    page::PageMapper,
+    MemoryManagementArch, PageTableKind, PhysAddr, PhysMemoryArea,
+};
 use core::marker::PhantomData;
 
 /// 线性分配器
@@ -41,44 +48,47 @@ impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
     pub fn remain_areas(&self, result_area: &mut [PhysMemoryArea]) -> Option<usize> {
         let mut offset = self.offset();
 
+        let iter = mem_block_manager().to_iter_available();
+
         let mut ret_offset_aligned = 0;
 
         let mut res_cnt = 0;
 
-        let total_num = mem_block_manager().total_initial_memory_regions();
+        let mut found_start = false;
         // 遍历所有的物理内存区域
-        for i in 0..total_num {
-            let area = mem_block_manager().get_initial_memory_region(i).unwrap();
-            // 将area的base地址与PAGE_SIZE对齐,对齐时向上取整
-            // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
-            let area_base = area.area_base_aligned().data();
-            // 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整
-            // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
-            let area_end = area.area_end_aligned().data();
+        for area in iter {
+            if found_start == false {
+                // 将area的base地址与PAGE_SIZE对齐,对齐时向上取整
+                // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
+                let area_base = area.area_base_aligned().data();
+                // 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整
+                // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
+                let area_end = area.area_end_aligned().data();
+
+                // 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域
+                if offset >= area_end {
+                    continue;
+                }
 
-            // 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域
-            if offset >= area_end {
-                continue;
+                // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base
+                if offset < area_base {
+                    offset = area_base;
+                } else if offset < area_end {
+                    // 将offset对齐到PAGE_SIZE
+                    offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1);
+                }
+                // found
+                if offset + 1 * MMA::PAGE_SIZE <= area_end {
+                    ret_offset_aligned = offset - area.area_base_aligned().data();
+                    found_start = true;
+                }
             }
 
-            // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base
-            if offset < area_base {
-                offset = area_base;
-            } else if offset < area_end {
-                // 将offset对齐到PAGE_SIZE
-                offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1);
-            }
-            // found
-            if offset + 1 * MMA::PAGE_SIZE <= area_end {
-                for j in i..total_num {
-                    let aj = mem_block_manager().get_initial_memory_region(j).unwrap();
-                    if aj.area_base_aligned() < aj.area_end_aligned() {
-                        result_area[res_cnt] = aj;
-                        res_cnt += 1;
-                    }
+            if found_start {
+                if area.area_base_aligned() < area.area_end_aligned() {
+                    result_area[res_cnt] = area;
+                    res_cnt += 1;
                 }
-                ret_offset_aligned = offset;
-                break;
             }
         }
 
@@ -89,6 +99,28 @@ impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
             return Some(ret_offset_aligned);
         }
     }
+
+    #[inline(never)]
+    unsafe fn ensure_early_mapping(&self, start_paddr: PhysAddr, count: PageFrameCount) {
+        // 确保在内存管理未被初始化时,这地址已经被映射了
+        if mm_init_status() != MMInitStatus::Initialized {
+            // 映射涉及的页
+
+            let iter = PhysPageFrameIter::new(
+                PhysPageFrame::new(start_paddr),
+                PhysPageFrame::new(start_paddr + count.bytes()),
+            );
+            let mapper =
+                PageMapper::<MMA, _>::current(PageTableKind::Kernel, BumpAllocator::<MMA>::new(0));
+
+            for p in iter {
+                if let None = mapper.translate(MMA::phys_2_virt(p.phys_address()).unwrap()) {
+                    let vaddr = MMA::phys_2_virt(p.phys_address()).unwrap();
+                    pseudo_map_phys(vaddr, p.phys_address(), PageFrameCount::new(1));
+                }
+            }
+        }
+    }
 }
 
 impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
@@ -99,7 +131,7 @@ impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
     unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
         let mut offset = self.offset();
 
-        let iter = mem_block_manager().to_iter();
+        let iter = mem_block_manager().to_iter_available();
 
         // 遍历所有的物理内存区域
         for area in iter {
@@ -128,7 +160,9 @@ impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
                 // 将offset增加至分配后的内存
                 self.offset = offset + count.data() * MMA::PAGE_SIZE;
 
-                return Some((PhysAddr(res_page_phys), count));
+                let r = (PhysAddr(res_page_phys), count);
+                self.ensure_early_mapping(r.0, r.1);
+                return Some(r);
             }
         }
         return None;
@@ -144,7 +178,7 @@ impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
     unsafe fn usage(&self) -> PageFrameUsage {
         let mut total = 0;
         let mut used = 0;
-        let iter = mem_block_manager().to_iter();
+        let iter = mem_block_manager().to_iter_available();
         for area in iter {
             // 将area的base地址与PAGE_SIZE对齐,对其时向上取整
             let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);

+ 2 - 2
kernel/src/mm/allocator/kernel_allocator.rs

@@ -56,7 +56,7 @@ impl KernelAllocator {
     }
 }
 
-/// 为内核SLAB分配器实现LocalAlloc的trait
+/// 为内核分配器实现LocalAlloc的trait
 impl LocalAlloc for KernelAllocator {
     unsafe fn local_alloc(&self, layout: Layout) -> *mut u8 {
         return self
@@ -84,7 +84,7 @@ impl LocalAlloc for KernelAllocator {
 /// 为内核slab分配器实现GlobalAlloc特性
 unsafe impl GlobalAlloc for KernelAllocator {
     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
-        let r = self.local_alloc(layout);
+        let r = self.local_alloc_zeroed(layout);
         mm_debug_log(
             klog_types::AllocatorLogType::Alloc(AllocLogItem::new(
                 layout.clone(),

+ 2 - 1
kernel/src/mm/allocator/page_frame.rs

@@ -78,7 +78,8 @@ impl Iterator for PhysPageFrameIter {
         if unlikely(self.current == self.end) {
             return None;
         }
-        let current = self.current.next();
+        let current: PhysPageFrame = self.current;
+        self.current = self.current.next_by(1);
         return Some(current);
     }
 }

+ 8 - 2
kernel/src/mm/c_adapter.rs

@@ -14,8 +14,9 @@ use crate::{
 };
 
 use super::{
-    allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, mmio_buddy::mmio_pool,
-    no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
+    allocator::page_frame::PageFrameCount, init::mm_init, kernel_mapper::KernelMapper,
+    mmio_buddy::mmio_pool, no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch,
+    PhysAddr, VirtAddr,
 };
 
 lazy_static! {
@@ -165,3 +166,8 @@ pub unsafe extern "C" fn rs_mmio_release(vaddr: u64, length: u64) -> i32 {
         .release_mmio(VirtAddr::new(vaddr as usize), length as usize)
         .unwrap_or_else(|err| err.to_posix_errno());
 }
+
+#[no_mangle]
+unsafe extern "C" fn rs_mm_init() {
+    mm_init();
+}

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

@@ -179,7 +179,6 @@ impl EarlyIoRemap {
         let count = PageFrameCount::from_bytes(slot_guard[idx].size as usize).unwrap();
 
         // 取消映射
-
         unsafe { pseudo_unmap_phys(vaddr, count) };
 
         for i in 0..count.data() {

+ 61 - 0
kernel/src/mm/init.rs

@@ -0,0 +1,61 @@
+use core::{fmt::Write, sync::atomic::Ordering};
+
+use crate::{
+    arch::MMArch, driver::tty::serial::serial8250::send_to_default_serial8250_port,
+    filesystem::procfs::kmsg::kmsg_init, libs::printk::PrintkWriter, mm::mmio_buddy::mmio_init,
+};
+
+use super::MemoryManagementArch;
+
+#[atomic_enum]
+#[derive(PartialEq, Eq)]
+pub enum MMInitStatus {
+    NotInit,
+    Initializing,
+    Initialized,
+}
+/// 内存管理的初始化状态
+static MM_INIT: AtomicMMInitStatus = AtomicMMInitStatus::new(MMInitStatus::NotInit);
+
+pub unsafe fn mm_init() {
+    send_to_default_serial8250_port("mm_init\n\0".as_bytes());
+    PrintkWriter
+        .write_fmt(format_args!("mm_init() called\n"))
+        .unwrap();
+    // printk_color!(GREEN, BLACK, "mm_init() called\n");
+
+    if MM_INIT
+        .compare_exchange(
+            MMInitStatus::NotInit,
+            MMInitStatus::Initializing,
+            Ordering::SeqCst,
+            Ordering::SeqCst,
+        )
+        .is_err()
+    {
+        send_to_default_serial8250_port("mm_init err\n\0".as_bytes());
+        panic!("mm_init() can only be called once");
+    }
+
+    MMArch::init();
+
+    // enable mmio
+    mmio_init();
+    // enable KMSG
+    kmsg_init();
+
+    MM_INIT
+        .compare_exchange(
+            MMInitStatus::Initializing,
+            MMInitStatus::Initialized,
+            Ordering::SeqCst,
+            Ordering::SeqCst,
+        )
+        .unwrap();
+    kinfo!("mm init done.");
+}
+
+/// 获取内存管理的初始化状态
+pub fn mm_init_status() -> MMInitStatus {
+    MM_INIT.load(Ordering::SeqCst)
+}

+ 88 - 5
kernel/src/mm/memblock.rs

@@ -2,7 +2,10 @@ use core::intrinsics::unlikely;
 
 use system_error::SystemError;
 
-use crate::libs::spinlock::{SpinLock, SpinLockGuard};
+use crate::libs::{
+    align::{page_align_down, page_align_up},
+    spinlock::{SpinLock, SpinLockGuard},
+};
 
 use super::{PhysAddr, PhysMemoryArea};
 
@@ -50,7 +53,8 @@ impl MemBlockManager {
     /// 如果添加的区域与已有区域有重叠,会将重叠的区域合并
     #[allow(dead_code)]
     pub fn add_block(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> {
-        return self.add_range(base, size, MemoryAreaAttr::empty());
+        let r = self.add_range(base, size, MemoryAreaAttr::empty());
+        return r;
     }
 
     /// 添加内存区域
@@ -350,11 +354,15 @@ impl MemBlockManager {
 
     fn set_or_clear_flags(
         &self,
-        base: PhysAddr,
-        size: usize,
+        mut base: PhysAddr,
+        mut size: usize,
         set: bool,
         flags: MemoryAreaAttr,
     ) -> Result<(), SystemError> {
+        let rsvd_base = PhysAddr::new(page_align_down(base.data()));
+        size = page_align_up((size as usize) + base.data() - rsvd_base.data());
+        base = rsvd_base;
+
         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 {
@@ -375,10 +383,68 @@ impl MemBlockManager {
         return self.set_or_clear_flags(base, size, true, MemoryAreaAttr::RESERVED);
     }
 
+    /// 判断[base, base+size)与已有区域是否有重叠
+    pub fn is_overlapped(&self, base: PhysAddr, size: usize) -> bool {
+        let inner = self.inner.lock();
+        return self.do_is_overlapped(base, size, false, &inner);
+    }
+
+    /// 判断[base, base+size)与已有Reserved区域是否有重叠
+    pub fn is_overlapped_with_reserved(&self, base: PhysAddr, size: usize) -> bool {
+        let inner = self.inner.lock();
+        return self.do_is_overlapped(base, size, true, &inner);
+    }
+
+    fn do_is_overlapped(
+        &self,
+        base: PhysAddr,
+        size: usize,
+        require_reserved: bool,
+        inner: &SpinLockGuard<'_, InnerMemBlockManager>,
+    ) -> bool {
+        let mut res = false;
+        for i in 0..inner.initial_memory_regions_num {
+            if require_reserved
+                && !inner.initial_memory_regions[i]
+                    .flags
+                    .contains(MemoryAreaAttr::RESERVED)
+            {
+                // 忽略非保留区域
+                continue;
+            }
+
+            let range_base = inner.initial_memory_regions[i].base;
+            let range_end = range_base + inner.initial_memory_regions[i].size;
+            if (base >= range_base && base < range_end)
+                || (base + size > range_base && base + size <= range_end)
+                || (base <= range_base && base + size >= range_end)
+            {
+                res = true;
+                break;
+            }
+        }
+
+        return res;
+    }
+
     /// 生成迭代器
     pub fn to_iter(&self) -> MemBlockIter {
         let inner = self.inner.lock();
-        return MemBlockIter { inner, index: 0 };
+        return MemBlockIter {
+            inner,
+            index: 0,
+            usable_only: false,
+        };
+    }
+
+    /// 生成迭代器,迭代所有可用的物理内存区域
+    pub fn to_iter_available(&self) -> MemBlockIter {
+        let inner = self.inner.lock();
+        return MemBlockIter {
+            inner,
+            index: 0,
+            usable_only: true,
+        };
     }
 
     /// 获取初始内存区域数量
@@ -397,6 +463,7 @@ impl MemBlockManager {
 pub struct MemBlockIter<'a> {
     inner: SpinLockGuard<'a, InnerMemBlockManager>,
     index: usize,
+    usable_only: bool,
 }
 
 #[allow(dead_code)]
@@ -421,6 +488,22 @@ impl<'a> Iterator for MemBlockIter<'a> {
     type Item = PhysMemoryArea;
 
     fn next(&mut self) -> Option<Self::Item> {
+        while self.index < self.inner.initial_memory_regions_num {
+            if self.usable_only {
+                if self.inner.initial_memory_regions[self.index]
+                    .flags
+                    .is_empty()
+                    == false
+                {
+                    self.index += 1;
+                    if self.index >= self.inner.initial_memory_regions_num {
+                        return None;
+                    }
+                    continue;
+                }
+            }
+            break;
+        }
         if self.index >= self.inner.initial_memory_regions_num {
             return None;
         }

+ 1 - 0
kernel/src/mm/mmio_buddy.rs

@@ -51,6 +51,7 @@ pub struct MmioBuddyMemPool {
 }
 
 impl MmioBuddyMemPool {
+    #[inline(never)]
     fn new() -> Self {
         let mut free_regions: [MaybeUninit<SpinLock<MmioFreeRegionList>>;
             MMIO_BUDDY_REGION_COUNT as usize] = unsafe { MaybeUninit::uninit().assume_init() };

+ 6 - 0
kernel/src/mm/mod.rs

@@ -22,6 +22,7 @@ use self::{
 pub mod allocator;
 pub mod c_adapter;
 pub mod early_ioremap;
+pub mod init;
 pub mod kernel_mapper;
 pub mod memblock;
 pub mod mmio_buddy;
@@ -407,6 +408,11 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
     /// 虚拟地址与物理地址的偏移量
     const PHYS_OFFSET: usize;
 
+    /// 内核在链接时被链接到的偏移量
+    const KERNEL_LINK_OFFSET: usize;
+
+    const KERNEL_VIRT_START: usize = Self::PHYS_OFFSET + Self::KERNEL_LINK_OFFSET;
+
     /// 每个页面的大小
     const PAGE_SIZE: usize = 1 << Self::PAGE_SHIFT;
     /// 通过这个mask,获取地址的页内偏移量

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

@@ -141,7 +141,7 @@ 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);
+    let flags: PageFlags<MMArch> = PageFlags::new().set_write(true);
 
     pseudo_map_phys_with_flags(vaddr, paddr, count, flags);
 }
@@ -192,7 +192,6 @@ pub unsafe fn pseudo_map_phys_with_flags(
 #[inline(never)]
 pub unsafe fn pseudo_unmap_phys(vaddr: VirtAddr, count: PageFrameCount) {
     assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
-    assert!(count.data() == 1);
 
     let mut pseudo_allocator = PseudoAllocator::<MMArch>::new();
 

+ 1 - 1
kernel/src/mm/page.rs

@@ -213,7 +213,7 @@ impl<Arch: MemoryManagementArch> PageEntry<Arch> {
 
             #[cfg(target_arch = "riscv64")]
             {
-                let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 44) - 1);
+                let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 54) - 1);
                 super::allocator::page_frame::PhysPageFrame::from_ppn(ppn).phys_address()
             }
         };

+ 1 - 1
kernel/src/time/mod.rs

@@ -76,7 +76,7 @@ impl TimeSpec {
 
         #[cfg(target_arch = "riscv64")]
         {
-            unimplemented!("TimeSpec::now()")
+            return TimeSpec::new(0, 0);
         }
     }
 }