添加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 {
/// 最大的内存分配器日志数量
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::{
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";

View File

@ -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 {

View File

@ -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");
}
}