diff --git a/kernel/src/debug/klog/mm.rs b/kernel/src/debug/klog/mm.rs index f970e8d9..3a89fdcb 100644 --- a/kernel/src/debug/klog/mm.rs +++ b/kernel/src/debug/klog/mm.rs @@ -42,7 +42,7 @@ pub(super) struct MMDebugLogManager; impl MMDebugLogManager { /// 最大的内存分配器日志数量 - pub const MAX_ALLOC_LOG_NUM: usize = 100000; + pub const MAX_ALLOC_LOG_NUM: usize = 10000; /// 记录内存分配器的日志 /// diff --git a/kernel/src/driver/video/fbdev/vesafb.rs b/kernel/src/driver/video/fbdev/vesafb.rs index 232f34ab..c71d78dd 100644 --- a/kernel/src/driver/video/fbdev/vesafb.rs +++ b/kernel/src/driver/video/fbdev/vesafb.rs @@ -38,6 +38,7 @@ use crate::{ }, include::bindings::bindings::{ multiboot2_get_Framebuffer_info, multiboot2_iter, multiboot_tag_framebuffer_info_t, + FRAME_BUFFER_MAPPING_OFFSET, }, init::{boot_params, initcall::INITCALL_DEVICE}, libs::{ @@ -650,7 +651,11 @@ pub fn vesafb_early_init() -> Result { boottime_screen_info.lfb_size = (width * height * ((fb_info.framebuffer_bpp as u32 + 7) / 8)) as usize; - let buf_vaddr = VirtAddr::new(0xffff800003200000); + // let buf_vaddr = VirtAddr::new(0xffff800003200000); + let buf_vaddr = VirtAddr::new( + crate::include::bindings::bindings::SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE as usize + + FRAME_BUFFER_MAPPING_OFFSET as usize, + ); boottime_screen_info.lfb_virt_base = Some(buf_vaddr); let init_text = "Video driver to map.\n\0"; diff --git a/kernel/src/driver/video/mod.rs b/kernel/src/driver/video/mod.rs index 63f2a1a2..80f92992 100644 --- a/kernel/src/driver/video/mod.rs +++ b/kernel/src/driver/video/mod.rs @@ -3,9 +3,6 @@ use core::sync::atomic::{AtomicBool, Ordering}; use crate::{ arch::MMArch, driver::tty::serial::serial8250::send_to_default_serial8250_port, - include::bindings::bindings::{ - FRAME_BUFFER_MAPPING_OFFSET, SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE, - }, init::boot_params, kinfo, libs::{ @@ -16,7 +13,7 @@ use crate::{ }, mm::{ allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, page::PageFlags, - MemoryManagementArch, VirtAddr, + MemoryManagementArch, }, time::timer::{Timer, TimerFunction}, }; @@ -86,10 +83,11 @@ impl VideoRefreshManager { */ fn init_frame_buffer(&self) { kinfo!("Re-mapping VBE frame buffer..."); - let buf_vaddr = VirtAddr::new( - SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE as usize + FRAME_BUFFER_MAPPING_OFFSET as usize, - ); - boot_params().write_irqsave().screen_info.lfb_virt_base = Some(buf_vaddr); + let buf_vaddr = boot_params() + .read_irqsave() + .screen_info + .lfb_virt_base + .unwrap(); let mut frame_buffer_info_guard = self.device_buffer.write(); if let ScmBuffer::DeviceBuffer(vaddr) = &mut (frame_buffer_info_guard).buf { diff --git a/kernel/src/mm/no_init.rs b/kernel/src/mm/no_init.rs index b481e9f3..4c198e93 100644 --- a/kernel/src/mm/no_init.rs +++ b/kernel/src/mm/no_init.rs @@ -1,15 +1,20 @@ //! 该文件用于系统启动早期,内存管理器初始化之前,提供一些简单的内存映射功能 //! -//! 这里假设在内核引导文件中,已经填写了前100M的页表,其中,前50M是真实映射到内存的,后面的仅仅创建了页表,表项全部为0。 -//! 因此这里映射内存不需要任何动态分配。 -//! //! 映射关系为: //! //! 虚拟地址 0-100M与虚拟地址 0x8000_0000_0000 - 0x8000_0640_0000 之间具有重映射关系。 //! 也就是说,他们的第二级页表在最顶级页表中,占用了第0和第256个页表项。 //! +//! 对于x86: +//! 这里假设在内核引导文件中,已经填写了前100M的页表,其中,前50M是真实映射到内存的,后面的仅仅创建了页表,表项全部为0。 + +use bitmap::{traits::BitMapOps, StaticBitmap}; + +use crate::{ + libs::spinlock::SpinLock, + mm::{MMArch, MemoryManagementArch, PhysAddr}, +}; -use crate::mm::{MMArch, MemoryManagementArch, PhysAddr}; use core::marker::PhantomData; use super::{ @@ -18,6 +23,74 @@ use super::{ PageTableKind, VirtAddr, }; +/// 用于存储重映射页表的位图和页面 +static EARLY_IOREMAP_PAGES: SpinLock = SpinLock::new(EarlyIoRemapPages::new()); + +/// 早期重映射使用的页表 +#[repr(C)] +#[repr(align(4096))] +#[derive(Clone, Copy)] +struct EarlyRemapPage { + data: [u64; MMArch::PAGE_SIZE], +} + +impl EarlyRemapPage { + /// 清空数据 + fn zero(&mut self) { + self.data.fill(0); + } +} + +#[repr(C)] +struct EarlyIoRemapPages { + pages: [EarlyRemapPage; Self::EARLY_REMAP_PAGES_NUM], + bmp: StaticBitmap<{ Self::EARLY_REMAP_PAGES_NUM }>, +} + +impl EarlyIoRemapPages { + /// 预留的用于在内存管理初始化之前,映射内存所使用的页表数量 + pub const EARLY_REMAP_PAGES_NUM: usize = 256; + pub const fn new() -> Self { + Self { + pages: [EarlyRemapPage { + data: [0; MMArch::PAGE_SIZE], + }; Self::EARLY_REMAP_PAGES_NUM], + bmp: StaticBitmap::new(), + } + } + + /// 分配一个页面 + /// + /// 如果成功,返回虚拟地址 + /// + /// 如果失败,返回None + pub fn allocate_page(&mut self) -> Option { + if let Some(index) = self.bmp.first_false_index() { + self.bmp.set(index, true); + // 清空数据 + self.pages[index].zero(); + + let p = &self.pages[index] as *const EarlyRemapPage as usize; + let vaddr = VirtAddr::new(p); + assert!(vaddr.check_aligned(MMArch::PAGE_SIZE)); + return Some(vaddr); + } else { + return None; + } + } + + pub fn free_page(&mut self, addr: VirtAddr) { + // 判断地址是否合法 + let start_vaddr = &self.pages[0] as *const EarlyRemapPage as usize; + let offset = addr.data() - start_vaddr; + let index = offset / MMArch::PAGE_SIZE; + if index < Self::EARLY_REMAP_PAGES_NUM { + assert_eq!(self.bmp.get(index).unwrap(), true); + self.bmp.set(index, false); + } + } +} + /// 伪分配器 struct PseudoAllocator { phantom: PhantomData, @@ -33,17 +106,26 @@ impl PseudoAllocator { /// 为NoInitAllocator实现FrameAllocator impl FrameAllocator for PseudoAllocator { - unsafe fn allocate(&mut self, _count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { - panic!("NoInitAllocator can't allocate page frame"); + unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { + assert!(count.data() == 1); + let vaddr = EARLY_IOREMAP_PAGES.lock_irqsave().allocate_page()?; + let paddr = MMA::virt_2_phys(vaddr)?; + return Some((paddr, count)); } - unsafe fn free(&mut self, _address: PhysAddr, _count: PageFrameCount) { - panic!("NoInitAllocator can't free page frame"); + unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount) { + assert_eq!(count.data(), 1); + assert!(address.check_aligned(MMA::PAGE_SIZE)); + let vaddr = MMA::phys_2_virt(address); + if let Some(vaddr) = vaddr { + EARLY_IOREMAP_PAGES.lock_irqsave().free_page(vaddr); + } } /// @brief: 获取内存区域页帧的使用情况 /// @param self /// @return 页帧的使用情况 unsafe fn usage(&self) -> PageFrameUsage { + // 暂时不支持 panic!("NoInitAllocator can't get page frame usage"); } }