Browse Source

添加early ioremap支持 (#492)

* 使用early io remap来映射早期的vesa缓冲区
LoGin 1 year ago
parent
commit
c75ef4e212

+ 1 - 1
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;
 
     /// 记录内存分配器的日志
     ///

+ 6 - 1
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<VirtAddr, SystemError> {
     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";

+ 6 - 8
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 {

+ 90 - 8
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<EarlyIoRemapPages> = 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<VirtAddr> {
+        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<MMA> {
     phantom: PhantomData<MMA>,
@@ -33,17 +106,26 @@ impl<MMA: MemoryManagementArch> PseudoAllocator<MMA> {
 
 /// 为NoInitAllocator实现FrameAllocator
 impl<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> {
-    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");
     }
 }