diff --git a/kernel/src/arch/riscv64/init/mod.rs b/kernel/src/arch/riscv64/init/mod.rs index 1c8edb6d..8951b465 100644 --- a/kernel/src/arch/riscv64/init/mod.rs +++ b/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() } diff --git a/kernel/src/arch/riscv64/mm/init.rs b/kernel/src/arch/riscv64/mm/init.rs index 62e81e6f..2de82aa9 100644 --- a/kernel/src/arch/riscv64/mm/init.rs +++ b/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::::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> = + crate::mm::page::PageMapper::::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::::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::(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::::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::::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) { + 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>, + ) { + 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::(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(); + } + } + } +} diff --git a/kernel/src/arch/riscv64/mm/mod.rs b/kernel/src/arch/riscv64/mm/mod.rs index 5afd5036..5adc2197 100644 --- a/kernel/src/arch/riscv64/mm/mod.rs +++ b/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>> = 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(virt: VirtAddr) -> PageFlags { - unimplemented!("riscv64::kernel_page_flags") +pub unsafe fn kernel_page_flags(_virt: VirtAddr) -> PageFlags { + 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"); + } } } diff --git a/kernel/src/arch/riscv64/time.rs b/kernel/src/arch/riscv64/time.rs index 75fa0b6d..248f003e 100644 --- a/kernel/src/arch/riscv64/time.rs +++ b/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() } } diff --git a/kernel/src/arch/x86_64/mm/mod.rs b/kernel/src/arch/x86_64/mm/mod.rs index cc2abeab..0d2f5e7c 100644 --- a/kernel/src/arch/x86_64/mm/mod.rs +++ b/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) { 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>, @@ -717,7 +692,3 @@ impl LowAddressRemapping { } } } -#[no_mangle] -pub extern "C" fn rs_mm_init() { - mm_init(); -} diff --git a/kernel/src/driver/firmware/efi/guid.rs b/kernel/src/driver/firmware/efi/guid.rs index 31334025..753c085f 100644 --- a/kernel/src/driver/firmware/efi/guid.rs +++ b/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` diff --git a/kernel/src/driver/firmware/efi/init.rs b/kernel/src/driver/firmware/efi/init.rs index d7727707..b37d9693 100644 --- a/kernel/src/driver/firmware/efi/init.rs +++ b/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() { diff --git a/kernel/src/driver/firmware/efi/mod.rs b/kernel/src/driver/firmware/efi/mod.rs index 23370ff2..e8c5c824 100644 --- a/kernel/src/driver/firmware/efi/mod.rs +++ b/kernel/src/driver/firmware/efi/mod.rs @@ -35,6 +35,10 @@ struct InnerEFIManager { /// runtime services的版本号 pub runtime_service_version: Option, pub dragonstub_load_info: Option, + /// uefi 内存属性表的物理地址 + pub memory_attribute_table_paddr: Option, + /// uefi 内存保留表的物理地址 + pub memreserve_table_paddr: Option, } 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 { + return self.inner.read().dragonstub_load_info; + } + /// 检查是否为有效的system table表头 /// /// ## 参数 diff --git a/kernel/src/driver/firmware/efi/tables.rs b/kernel/src/driver/firmware/efi/tables.rs index 8c00c2aa..82160977 100644 --- a/kernel/src/driver/firmware/efi/tables.rs +++ b/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::EFIManager; +use super::{ + guid::{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, EFI_MEMRESERVE_TABLE_GUID}, + 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::(), - 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) }; - - efi_manager().inner.write().dragonstub_load_info = Some(data); - - EarlyIoRemap::unmap(vaddr).unwrap(); + 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 + })?; + + 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::() + + size_of::() * 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, + 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::() + } + + fn post_process( + &self, + vendor_table_vaddr: Option, + _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, + 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, + 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> { + if table.vendor_guid.equivalent(self.table.guid()) == false { + return None; + } + + let table_map_size = self.table.map_size(); + let vendor_table_vaddr: Option; + 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, +} diff --git a/kernel/src/driver/open_firmware/fdt.rs b/kernel/src/driver/open_firmware/fdt.rs index db6de24a..59c9bb0f 100644 --- a/kernel/src/driver/open_firmware/fdt.rs +++ b/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; + let base_index = i * (addr_cells + size_cells); - 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, 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::(); + 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"); + } + } } diff --git a/kernel/src/filesystem/procfs/kmsg.rs b/kernel/src/filesystem/procfs/kmsg.rs index fe8101db..04612192 100644 --- a/kernel/src/filesystem/procfs/kmsg.rs +++ b/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> = 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"); } /// 日志 diff --git a/kernel/src/init/mod.rs b/kernel/src/init/mod.rs index c2109892..f5eba036 100644 --- a/kernel/src/init/mod.rs +++ b/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 { #[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 { + #[cfg(target_arch = "riscv64")] + return Some(self.arch.fdt_paddr); + + #[cfg(target_arch = "x86_64")] + return None; + } } diff --git a/kernel/src/libs/printk.rs b/kernel/src/libs/printk.rs index 138dc10c..071fd5ef 100644 --- a/kernel/src/libs/printk.rs +++ b/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) }; diff --git a/kernel/src/mm/allocator/buddy.rs b/kernel/src/mm/allocator/buddy.rs index 37550eb1..ab249b26 100644 --- a/kernel/src/mm/allocator/buddy.rs +++ b/kernel/src/mm/allocator/buddy.rs @@ -110,13 +110,16 @@ impl BuddyAllocator { 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 { diff --git a/kernel/src/mm/allocator/bump.rs b/kernel/src/mm/allocator/bump.rs index 8b2fbc20..f8df52b6 100644 --- a/kernel/src/mm/allocator/bump.rs +++ b/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 BumpAllocator { pub fn remain_areas(&self, result_area: &mut [PhysMemoryArea]) -> Option { 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_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; - } + // 如果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; + } + } + + 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 BumpAllocator { 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::::current(PageTableKind::Kernel, BumpAllocator::::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 FrameAllocator for BumpAllocator { @@ -99,7 +131,7 @@ impl FrameAllocator for BumpAllocator { 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 FrameAllocator for BumpAllocator { // 将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 FrameAllocator for BumpAllocator { 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); diff --git a/kernel/src/mm/allocator/kernel_allocator.rs b/kernel/src/mm/allocator/kernel_allocator.rs index 7fbe547d..b1bc31a0 100644 --- a/kernel/src/mm/allocator/kernel_allocator.rs +++ b/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(), diff --git a/kernel/src/mm/allocator/page_frame.rs b/kernel/src/mm/allocator/page_frame.rs index 576cdaf8..c4652af9 100644 --- a/kernel/src/mm/allocator/page_frame.rs +++ b/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); } } diff --git a/kernel/src/mm/c_adapter.rs b/kernel/src/mm/c_adapter.rs index 2fd534c9..4aa7b4c8 100644 --- a/kernel/src/mm/c_adapter.rs +++ b/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(); +} diff --git a/kernel/src/mm/early_ioremap.rs b/kernel/src/mm/early_ioremap.rs index 0bf652b1..3a25e284 100644 --- a/kernel/src/mm/early_ioremap.rs +++ b/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() { diff --git a/kernel/src/mm/init.rs b/kernel/src/mm/init.rs new file mode 100644 index 00000000..3b13f614 --- /dev/null +++ b/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) +} diff --git a/kernel/src/mm/memblock.rs b/kernel/src/mm/memblock.rs index ab68bb92..a36dc73d 100644 --- a/kernel/src/mm/memblock.rs +++ b/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 { + 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; } diff --git a/kernel/src/mm/mmio_buddy.rs b/kernel/src/mm/mmio_buddy.rs index 6aafb9f0..276b7c74 100644 --- a/kernel/src/mm/mmio_buddy.rs +++ b/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>; MMIO_BUDDY_REGION_COUNT as usize] = unsafe { MaybeUninit::uninit().assume_init() }; diff --git a/kernel/src/mm/mod.rs b/kernel/src/mm/mod.rs index 86c2b869..23229b11 100644 --- a/kernel/src/mm/mod.rs +++ b/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,获取地址的页内偏移量 diff --git a/kernel/src/mm/no_init.rs b/kernel/src/mm/no_init.rs index ce9fbef7..54c5ae77 100644 --- a/kernel/src/mm/no_init.rs +++ b/kernel/src/mm/no_init.rs @@ -141,7 +141,7 @@ impl FrameAllocator for PseudoAllocator { /// 并且,内核引导文件必须以4K页为粒度,填写了前100M的内存映射关系。(具体以本文件开头的注释为准) #[inline(never)] pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) { - let flags: PageFlags = PageFlags::new().set_write(true).set_execute(true); + let flags: PageFlags = 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::::new(); diff --git a/kernel/src/mm/page.rs b/kernel/src/mm/page.rs index d7c86714..f87adaa8 100644 --- a/kernel/src/mm/page.rs +++ b/kernel/src/mm/page.rs @@ -213,7 +213,7 @@ impl PageEntry { #[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() } }; diff --git a/kernel/src/time/mod.rs b/kernel/src/time/mod.rs index 8d20c800..9a0507ef 100644 --- a/kernel/src/time/mod.rs +++ b/kernel/src/time/mod.rs @@ -76,7 +76,7 @@ impl TimeSpec { #[cfg(target_arch = "riscv64")] { - unimplemented!("TimeSpec::now()") + return TimeSpec::new(0, 0); } } }