mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-20 10:06:31 +00:00
feat: 添加对内核引导协议的抽象 (#913)
* 添加multiboot header * head.S传参增加bootloader类型 * feat: 添加引导加载协议的抽象,并为multiboot2实现这个抽象. * 把framebuffer的映射地址改为从early ioremap和mmio pool分配 * riscv64能运行
This commit is contained in:
@ -6,15 +6,13 @@ pub mod pkru;
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec::Vec;
|
||||
use hashbrown::HashSet;
|
||||
use log::{debug, info, warn};
|
||||
use log::{debug, info};
|
||||
use x86::time::rdtsc;
|
||||
use x86_64::registers::model_specific::EferFlags;
|
||||
|
||||
use crate::driver::serial::serial8250::send_to_default_serial8250_port;
|
||||
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::init::boot::boot_callbacks;
|
||||
use crate::libs::align::page_align_up;
|
||||
use crate::libs::lib_ui::screen_manager::scm_disable_put_to_window;
|
||||
use crate::libs::spinlock::SpinLock;
|
||||
@ -34,9 +32,7 @@ use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, VmFlags
|
||||
use system_error::SystemError;
|
||||
|
||||
use core::arch::asm;
|
||||
use core::ffi::c_void;
|
||||
use core::fmt::Debug;
|
||||
use core::mem::{self};
|
||||
|
||||
use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
|
||||
|
||||
@ -63,6 +59,12 @@ pub struct X86_64MMBootstrapInfo {
|
||||
|
||||
pub(super) static mut BOOTSTRAP_MM_INFO: Option<X86_64MMBootstrapInfo> = None;
|
||||
|
||||
pub(super) fn x86_64_set_kernel_load_base_paddr(paddr: PhysAddr) {
|
||||
unsafe {
|
||||
BOOTSTRAP_MM_INFO.as_mut().unwrap().kernel_load_base_paddr = paddr.data();
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief X86_64的内存管理架构结构体
|
||||
#[derive(Debug, Clone, Copy, Hash)]
|
||||
pub struct X86_64MMArch;
|
||||
@ -125,8 +127,8 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
const USER_STACK_START: VirtAddr = VirtAddr::new(0x6ffff0a00000);
|
||||
|
||||
const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffffb00000000000);
|
||||
/// 设置FIXMAP区域大小为1M
|
||||
const FIXMAP_SIZE: usize = 256 * 4096;
|
||||
/// 设置FIXMAP区域大小为16M
|
||||
const FIXMAP_SIZE: usize = 256 * 4096 * 16;
|
||||
|
||||
const MMIO_BASE: VirtAddr = VirtAddr::new(0xffffa10000000000);
|
||||
const MMIO_SIZE: usize = 1 << PAGE_1G_SHIFT;
|
||||
@ -142,10 +144,9 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
}
|
||||
|
||||
Self::init_xd_rsvd();
|
||||
let load_base_paddr = Self::get_load_base_paddr();
|
||||
|
||||
let bootstrap_info = X86_64MMBootstrapInfo {
|
||||
kernel_load_base_paddr: load_base_paddr.data(),
|
||||
kernel_load_base_paddr: 0,
|
||||
kernel_code_start: _text as usize,
|
||||
kernel_code_end: _etext as usize,
|
||||
kernel_data_end: _edata as usize,
|
||||
@ -157,8 +158,10 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
BOOTSTRAP_MM_INFO = Some(bootstrap_info);
|
||||
}
|
||||
|
||||
// 初始化物理内存区域(从multiboot2中获取)
|
||||
Self::init_memory_area_from_multiboot2().expect("init memory area failed");
|
||||
// 初始化物理内存区域
|
||||
boot_callbacks()
|
||||
.early_init_memory_blocks()
|
||||
.expect("init memory area failed");
|
||||
|
||||
debug!("bootstrap info: {:?}", unsafe { BOOTSTRAP_MM_INFO });
|
||||
debug!("phys[0]=virt[0x{:x}]", unsafe {
|
||||
@ -168,7 +171,7 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
// 初始化内存管理器
|
||||
unsafe { allocator_init() };
|
||||
|
||||
send_to_default_serial8250_port("x86 64 init done\n\0".as_bytes());
|
||||
send_to_default_serial8250_port("x86 64 mm init done\n\0".as_bytes());
|
||||
}
|
||||
|
||||
/// @brief 刷新TLB中,关于指定虚拟地址的条目
|
||||
@ -416,73 +419,6 @@ const fn protection_map() -> [EntryFlags<MMArch>; 16] {
|
||||
}
|
||||
|
||||
impl X86_64MMArch {
|
||||
unsafe fn get_load_base_paddr() -> PhysAddr {
|
||||
let mut mb2_lb_info: [multiboot_tag_load_base_addr_t; 512] = mem::zeroed();
|
||||
send_to_default_serial8250_port("get_load_base_paddr begin\n\0".as_bytes());
|
||||
|
||||
let mut mb2_count: u32 = 0;
|
||||
multiboot2_iter(
|
||||
Some(multiboot2_get_load_base),
|
||||
&mut mb2_lb_info as *mut [multiboot_tag_load_base_addr_t; 512] as usize as *mut c_void,
|
||||
&mut mb2_count,
|
||||
);
|
||||
|
||||
if mb2_count == 0 {
|
||||
send_to_default_serial8250_port(
|
||||
"get_load_base_paddr mb2_count == 0, default to 1MB\n\0".as_bytes(),
|
||||
);
|
||||
return PhysAddr::new(0x100000);
|
||||
}
|
||||
|
||||
let phys = mb2_lb_info[0].load_base_addr as usize;
|
||||
|
||||
return PhysAddr::new(phys);
|
||||
}
|
||||
unsafe fn init_memory_area_from_multiboot2() -> Result<usize, SystemError> {
|
||||
// 这个数组用来存放内存区域的信息(从C获取)
|
||||
let mut mb2_mem_info: [multiboot_mmap_entry_t; 512] = mem::zeroed();
|
||||
send_to_default_serial8250_port("init_memory_area_from_multiboot2 begin\n\0".as_bytes());
|
||||
|
||||
let mut mb2_count: u32 = 0;
|
||||
multiboot2_iter(
|
||||
Some(multiboot2_get_memory),
|
||||
&mut mb2_mem_info as *mut [multiboot_mmap_entry_t; 512] as usize as *mut c_void,
|
||||
&mut mb2_count,
|
||||
);
|
||||
send_to_default_serial8250_port("init_memory_area_from_multiboot2 2\n\0".as_bytes());
|
||||
|
||||
let mb2_count = mb2_count as usize;
|
||||
let mut areas_count = 0usize;
|
||||
let mut total_mem_size = 0usize;
|
||||
for info_entry in mb2_mem_info.iter().take(mb2_count) {
|
||||
// Only use the memory area if its type is 1 (RAM)
|
||||
if info_entry.type_ == 1 {
|
||||
// Skip the memory area if its len is 0
|
||||
if info_entry.len == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
total_mem_size += info_entry.len as usize;
|
||||
|
||||
mem_block_manager()
|
||||
.add_block(
|
||||
PhysAddr::new(info_entry.addr as usize),
|
||||
info_entry.len as usize,
|
||||
)
|
||||
.unwrap_or_else(|e| {
|
||||
warn!(
|
||||
"Failed to add memory block: base={:#x}, size={:#x}, error={:?}",
|
||||
info_entry.addr, info_entry.len, e
|
||||
);
|
||||
});
|
||||
areas_count += 1;
|
||||
}
|
||||
}
|
||||
send_to_default_serial8250_port("init_memory_area_from_multiboot2 end\n\0".as_bytes());
|
||||
info!("Total memory size: {} MB, total areas from multiboot2: {mb2_count}, valid areas: {areas_count}", total_mem_size / 1024 / 1024);
|
||||
return Ok(areas_count);
|
||||
}
|
||||
|
||||
fn init_xd_rsvd() {
|
||||
// 读取ia32-EFER寄存器的值
|
||||
let efer: EferFlags = x86_64::registers::model_specific::Efer::read();
|
||||
|
Reference in New Issue
Block a user