添加early ioremap支持 (#492)

* 使用early io remap来映射早期的vesa缓冲区
This commit is contained in:
LoGin 2024-01-18 00:09:36 +08:00 committed by GitHub
parent d8e29bffee
commit c75ef4e212
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 103 additions and 18 deletions

View File

@ -42,7 +42,7 @@ pub(super) struct MMDebugLogManager;
impl MMDebugLogManager { impl MMDebugLogManager {
/// 最大的内存分配器日志数量 /// 最大的内存分配器日志数量
pub const MAX_ALLOC_LOG_NUM: usize = 100000; pub const MAX_ALLOC_LOG_NUM: usize = 10000;
/// 记录内存分配器的日志 /// 记录内存分配器的日志
/// ///

View File

@ -38,6 +38,7 @@ use crate::{
}, },
include::bindings::bindings::{ include::bindings::bindings::{
multiboot2_get_Framebuffer_info, multiboot2_iter, multiboot_tag_framebuffer_info_t, multiboot2_get_Framebuffer_info, multiboot2_iter, multiboot_tag_framebuffer_info_t,
FRAME_BUFFER_MAPPING_OFFSET,
}, },
init::{boot_params, initcall::INITCALL_DEVICE}, init::{boot_params, initcall::INITCALL_DEVICE},
libs::{ libs::{
@ -650,7 +651,11 @@ pub fn vesafb_early_init() -> Result<VirtAddr, SystemError> {
boottime_screen_info.lfb_size = boottime_screen_info.lfb_size =
(width * height * ((fb_info.framebuffer_bpp as u32 + 7) / 8)) as usize; (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); boottime_screen_info.lfb_virt_base = Some(buf_vaddr);
let init_text = "Video driver to map.\n\0"; let init_text = "Video driver to map.\n\0";

View File

@ -3,9 +3,6 @@ use core::sync::atomic::{AtomicBool, Ordering};
use crate::{ use crate::{
arch::MMArch, arch::MMArch,
driver::tty::serial::serial8250::send_to_default_serial8250_port, 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, init::boot_params,
kinfo, kinfo,
libs::{ libs::{
@ -16,7 +13,7 @@ use crate::{
}, },
mm::{ mm::{
allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, page::PageFlags, allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, page::PageFlags,
MemoryManagementArch, VirtAddr, MemoryManagementArch,
}, },
time::timer::{Timer, TimerFunction}, time::timer::{Timer, TimerFunction},
}; };
@ -86,10 +83,11 @@ impl VideoRefreshManager {
*/ */
fn init_frame_buffer(&self) { fn init_frame_buffer(&self) {
kinfo!("Re-mapping VBE frame buffer..."); kinfo!("Re-mapping VBE frame buffer...");
let buf_vaddr = VirtAddr::new( let buf_vaddr = boot_params()
SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE as usize + FRAME_BUFFER_MAPPING_OFFSET as usize, .read_irqsave()
); .screen_info
boot_params().write_irqsave().screen_info.lfb_virt_base = Some(buf_vaddr); .lfb_virt_base
.unwrap();
let mut frame_buffer_info_guard = self.device_buffer.write(); let mut frame_buffer_info_guard = self.device_buffer.write();
if let ScmBuffer::DeviceBuffer(vaddr) = &mut (frame_buffer_info_guard).buf { if let ScmBuffer::DeviceBuffer(vaddr) = &mut (frame_buffer_info_guard).buf {

View File

@ -1,15 +1,20 @@
//! 该文件用于系统启动早期,内存管理器初始化之前,提供一些简单的内存映射功能 //! 该文件用于系统启动早期,内存管理器初始化之前,提供一些简单的内存映射功能
//! //!
//! 这里假设在内核引导文件中已经填写了前100M的页表其中前50M是真实映射到内存的后面的仅仅创建了页表表项全部为0。
//! 因此这里映射内存不需要任何动态分配。
//!
//! 映射关系为: //! 映射关系为:
//! //!
//! 虚拟地址 0-100M与虚拟地址 0x8000_0000_0000 - 0x8000_0640_0000 之间具有重映射关系。 //! 虚拟地址 0-100M与虚拟地址 0x8000_0000_0000 - 0x8000_0640_0000 之间具有重映射关系。
//! 也就是说他们的第二级页表在最顶级页表中占用了第0和第256个页表项。 //! 也就是说他们的第二级页表在最顶级页表中占用了第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 core::marker::PhantomData;
use super::{ use super::{
@ -18,6 +23,74 @@ use super::{
PageTableKind, VirtAddr, 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> { struct PseudoAllocator<MMA> {
phantom: PhantomData<MMA>, phantom: PhantomData<MMA>,
@ -33,17 +106,26 @@ impl<MMA: MemoryManagementArch> PseudoAllocator<MMA> {
/// 为NoInitAllocator实现FrameAllocator /// 为NoInitAllocator实现FrameAllocator
impl<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> { impl<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> {
unsafe fn allocate(&mut self, _count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
panic!("NoInitAllocator can't allocate page frame"); 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) { unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount) {
panic!("NoInitAllocator can't free page frame"); 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: 获取内存区域页帧的使用情况 /// @brief: 获取内存区域页帧的使用情况
/// @param self /// @param self
/// @return 页帧的使用情况 /// @return 页帧的使用情况
unsafe fn usage(&self) -> PageFrameUsage { unsafe fn usage(&self) -> PageFrameUsage {
// 暂时不支持
panic!("NoInitAllocator can't get page frame usage"); panic!("NoInitAllocator can't get page frame usage");
} }
} }