mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
riscv: 解析dtb,获取可用内存空间并添加到memblock (#486)
This commit is contained in:
parent
02343d0b5b
commit
45626c859f
@ -44,6 +44,7 @@ smoltcp = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/smoltcp.g
|
||||
system_error = { path = "crates/system_error" }
|
||||
unified-init = { path = "crates/unified-init" }
|
||||
virtio-drivers = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/virtio-drivers.git", rev = "f1d1cbb" }
|
||||
fdt = "0.1.5"
|
||||
|
||||
# target为x86_64时,使用下面的依赖
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
@ -52,6 +53,11 @@ x86 = "0.52.0"
|
||||
x86_64 = "0.14.10"
|
||||
|
||||
|
||||
# target为riscv64时,使用下面的依赖
|
||||
[target.'cfg(target_arch = "riscv64")'.dependencies]
|
||||
|
||||
|
||||
|
||||
# 构建时依赖项
|
||||
[build-dependencies]
|
||||
kernel_build = { path = "../build-scripts/kernel_build" }
|
||||
|
@ -1,16 +1,71 @@
|
||||
use core::intrinsics::unreachable;
|
||||
|
||||
use crate::{init::init_before_mem_init, kinfo, mm::PhysAddr};
|
||||
use fdt::node::FdtNode;
|
||||
|
||||
use crate::{
|
||||
driver::open_firmware::fdt::open_firmware_fdt_driver,
|
||||
init::{boot_params, init_before_mem_init},
|
||||
kinfo,
|
||||
mm::{PhysAddr, VirtAddr},
|
||||
print, println,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ArchBootParams {
|
||||
/// 启动时的fdt物理地址
|
||||
pub fdt_paddr: PhysAddr,
|
||||
}
|
||||
|
||||
impl ArchBootParams {
|
||||
pub const DEFAULT: Self = ArchBootParams {
|
||||
fdt_paddr: PhysAddr::new(0),
|
||||
};
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
|
||||
let fdt_paddr = PhysAddr::new(fdt_paddr);
|
||||
init_before_mem_init();
|
||||
boot_params().write().arch.fdt_paddr = fdt_paddr;
|
||||
kinfo!(
|
||||
"DragonOS kernel is running on hart {}, fdt address:{:?}",
|
||||
hartid,
|
||||
fdt_paddr
|
||||
);
|
||||
|
||||
let fdt = fdt::Fdt::from_ptr(fdt_paddr.data() as *const u8).expect("Failed to parse fdt!");
|
||||
print_node(fdt.find_node("/").unwrap(), 0);
|
||||
|
||||
parse_dtb();
|
||||
|
||||
loop {}
|
||||
unreachable()
|
||||
}
|
||||
|
||||
fn print_node(node: FdtNode<'_, '_>, n_spaces: usize) {
|
||||
(0..n_spaces).for_each(|_| print!(" "));
|
||||
println!("{}/", node.name);
|
||||
node.properties().for_each(|p| {
|
||||
(0..n_spaces + 4).for_each(|_| print!(" "));
|
||||
println!("{}: {:?}", p.name, p.value);
|
||||
});
|
||||
|
||||
for child in node.children() {
|
||||
print_node(child, n_spaces + 4);
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析fdt,获取内核启动参数
|
||||
unsafe fn parse_dtb() {
|
||||
let fdt_paddr = boot_params().read().arch.fdt_paddr;
|
||||
if fdt_paddr.is_null() {
|
||||
panic!("Failed to get fdt address!");
|
||||
}
|
||||
|
||||
open_firmware_fdt_driver()
|
||||
.set_fdt_vaddr(VirtAddr::new(fdt_paddr.data()))
|
||||
.unwrap();
|
||||
open_firmware_fdt_driver()
|
||||
.early_scan_device_tree()
|
||||
.expect("Failed to scan device tree at boottime.");
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ impl MemoryManagementArch for RiscV64MMArch {
|
||||
|
||||
const USER_STACK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffa0_0000);
|
||||
|
||||
unsafe fn init() -> &'static [crate::mm::PhysMemoryArea] {
|
||||
unsafe fn init() {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
pub mod asm;
|
||||
pub mod cpu;
|
||||
pub mod driver;
|
||||
mod init;
|
||||
pub mod init;
|
||||
pub mod interrupt;
|
||||
pub mod ipc;
|
||||
mod kvm;
|
||||
|
6
kernel/src/arch/x86_64/init/mod.rs
Normal file
6
kernel/src/arch/x86_64/init/mod.rs
Normal file
@ -0,0 +1,6 @@
|
||||
#[derive(Debug)]
|
||||
pub struct ArchBootParams {}
|
||||
|
||||
impl ArchBootParams {
|
||||
pub const DEFAULT: Self = ArchBootParams {};
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
use crate::{
|
||||
kdebug,
|
||||
libs::align::{page_align_down, page_align_up},
|
||||
mm::{
|
||||
allocator::bump::BumpAllocator, MemoryManagementArch, PhysAddr, PhysMemoryArea, VirtAddr,
|
||||
allocator::bump::BumpAllocator, memblock::mem_block_manager, MemoryManagementArch,
|
||||
PhysAddr, PhysMemoryArea, VirtAddr,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{X86_64MMBootstrapInfo, BOOTSTRAP_MM_INFO, PHYS_MEMORY_AREAS};
|
||||
use super::{X86_64MMBootstrapInfo, BOOTSTRAP_MM_INFO};
|
||||
|
||||
impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
|
||||
pub unsafe fn arch_remain_areas(
|
||||
@ -23,7 +23,7 @@ impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
|
||||
let offset_end = page_align_down(kernel_code_start - 16384);
|
||||
|
||||
// 把内核代码前的空间加入到可用内存区域中
|
||||
for area in &PHYS_MEMORY_AREAS {
|
||||
for area in mem_block_manager().to_iter() {
|
||||
let area_base = area.area_base_aligned().data();
|
||||
let area_end = area.area_end_aligned().data();
|
||||
if area_base >= offset_end {
|
||||
@ -44,7 +44,6 @@ impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
|
||||
ret_areas[res_count] =
|
||||
PhysMemoryArea::new(PhysAddr::new(new_start), new_end - new_start);
|
||||
|
||||
kdebug!("new arch remain area: {:?}", ret_areas[res_count]);
|
||||
res_count += 1;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ use crate::libs::printk::PrintkWriter;
|
||||
use crate::libs::spinlock::SpinLock;
|
||||
|
||||
use crate::mm::allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage};
|
||||
use crate::mm::memblock::mem_block_manager;
|
||||
use crate::mm::mmio_buddy::mmio_init;
|
||||
use crate::{
|
||||
arch::MMArch,
|
||||
@ -26,8 +27,8 @@ use crate::{
|
||||
|
||||
use crate::mm::kernel_mapper::KernelMapper;
|
||||
use crate::mm::page::{PageEntry, PageFlags};
|
||||
use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, PhysMemoryArea, VirtAddr};
|
||||
use crate::{kdebug, kinfo};
|
||||
use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr};
|
||||
use crate::{kdebug, kinfo, kwarn};
|
||||
use system_error::SystemError;
|
||||
|
||||
use core::arch::asm;
|
||||
@ -43,12 +44,6 @@ use super::kvm::vmx::vmx_asm_wrapper::vmx_vmread;
|
||||
pub type PageMapper =
|
||||
crate::mm::page::PageMapper<crate::arch::x86_64::mm::X86_64MMArch, LockedFrameAllocator>;
|
||||
|
||||
/// @brief 用于存储物理内存区域的数组
|
||||
static mut PHYS_MEMORY_AREAS: [PhysMemoryArea; 512] = [PhysMemoryArea {
|
||||
base: PhysAddr::new(0),
|
||||
size: 0,
|
||||
}; 512];
|
||||
|
||||
/// 初始的CR3寄存器的值,用于内存管理初始化时,创建的第一个内核页表的位置
|
||||
static mut INITIAL_CR3_VALUE: PhysAddr = PhysAddr::new(0);
|
||||
|
||||
@ -121,7 +116,7 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
const USER_STACK_START: VirtAddr = VirtAddr::new(0x6ffff0a00000);
|
||||
|
||||
/// @brief 获取物理内存区域
|
||||
unsafe fn init() -> &'static [crate::mm::PhysMemoryArea] {
|
||||
unsafe fn init() {
|
||||
extern "C" {
|
||||
fn _text();
|
||||
fn _etext();
|
||||
@ -147,12 +142,9 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
}
|
||||
|
||||
// 初始化物理内存区域(从multiboot2中获取)
|
||||
let areas_count =
|
||||
Self::init_memory_area_from_multiboot2().expect("init memory area failed");
|
||||
Self::init_memory_area_from_multiboot2().expect("init memory area failed");
|
||||
|
||||
send_to_default_serial8250_port("x86 64 init end\n\0".as_bytes());
|
||||
|
||||
return &PHYS_MEMORY_AREAS[0..areas_count];
|
||||
}
|
||||
|
||||
/// @brief 刷新TLB中,关于指定虚拟地址的条目
|
||||
@ -336,9 +328,24 @@ impl X86_64MMArch {
|
||||
if mb2_mem_info[i].len == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
total_mem_size += mb2_mem_info[i].len as usize;
|
||||
PHYS_MEMORY_AREAS[areas_count].base = PhysAddr::new(mb2_mem_info[i].addr as usize);
|
||||
PHYS_MEMORY_AREAS[areas_count].size = mb2_mem_info[i].len as usize;
|
||||
// PHYS_MEMORY_AREAS[areas_count].base = PhysAddr::new(mb2_mem_info[i].addr as usize);
|
||||
// PHYS_MEMORY_AREAS[areas_count].size = mb2_mem_info[i].len as usize;
|
||||
|
||||
mem_block_manager()
|
||||
.add_block(
|
||||
PhysAddr::new(mb2_mem_info[i].addr as usize),
|
||||
mb2_mem_info[i].len as usize,
|
||||
)
|
||||
.unwrap_or_else(|e| {
|
||||
kwarn!(
|
||||
"Failed to add memory block: base={:#x}, size={:#x}, error={:?}",
|
||||
mb2_mem_info[i].addr,
|
||||
mb2_mem_info[i].len,
|
||||
e
|
||||
);
|
||||
});
|
||||
areas_count += 1;
|
||||
}
|
||||
}
|
||||
@ -412,9 +419,7 @@ unsafe fn allocator_init() {
|
||||
let phy_offset =
|
||||
unsafe { MMArch::virt_2_phys(VirtAddr::new(page_align_up(virt_offset))) }.unwrap();
|
||||
|
||||
kdebug!("PhysArea[0..10] = {:?}", &PHYS_MEMORY_AREAS[0..10]);
|
||||
let mut bump_allocator =
|
||||
BumpAllocator::<X86_64MMArch>::new(&PHYS_MEMORY_AREAS, phy_offset.data());
|
||||
let mut bump_allocator = BumpAllocator::<X86_64MMArch>::new(phy_offset.data());
|
||||
kdebug!(
|
||||
"BumpAllocator created, offset={:?}",
|
||||
bump_allocator.offset()
|
||||
@ -450,7 +455,9 @@ unsafe fn allocator_init() {
|
||||
}
|
||||
kdebug!("Successfully emptied page table");
|
||||
|
||||
for area in PHYS_MEMORY_AREAS.iter() {
|
||||
let total_num = mem_block_manager().total_initial_memory_regions();
|
||||
for i in 0..total_num {
|
||||
let area = mem_block_manager().get_initial_memory_region(i).unwrap();
|
||||
// kdebug!("area: base={:?}, size={:#x}, end={:?}", area.base, area.size, area.base + area.size);
|
||||
for i in 0..((area.size + MMArch::PAGE_SIZE - 1) / MMArch::PAGE_SIZE) {
|
||||
let paddr = area.base.add(i * MMArch::PAGE_SIZE);
|
||||
|
@ -5,6 +5,7 @@ mod c_adapter;
|
||||
pub mod cpu;
|
||||
pub mod driver;
|
||||
pub mod fpu;
|
||||
pub mod init;
|
||||
pub mod interrupt;
|
||||
pub mod ipc;
|
||||
pub mod kvm;
|
||||
|
@ -3,6 +3,7 @@ pub mod base;
|
||||
pub mod disk;
|
||||
pub mod keyboard;
|
||||
pub mod net;
|
||||
pub mod open_firmware;
|
||||
pub mod pci;
|
||||
pub mod timers;
|
||||
pub mod tty;
|
||||
|
300
kernel/src/driver/open_firmware/fdt.rs
Normal file
300
kernel/src/driver/open_firmware/fdt.rs
Normal file
@ -0,0 +1,300 @@
|
||||
use fdt::{
|
||||
node::{FdtNode, NodeProperty},
|
||||
Fdt,
|
||||
};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
arch::MMArch,
|
||||
init::boot_params,
|
||||
libs::{align::page_align_down, rwlock::RwLock},
|
||||
mm::{
|
||||
memblock::{mem_block_manager, MemBlockManager},
|
||||
MemoryManagementArch, PhysAddr, VirtAddr,
|
||||
},
|
||||
};
|
||||
|
||||
#[inline(always)]
|
||||
pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver {
|
||||
&OpenFirmwareFdtDriver
|
||||
}
|
||||
|
||||
static FDT_GLOBAL_DATA: RwLock<FdtGlobalData> = RwLock::new(FdtGlobalData::new());
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FdtGlobalData {
|
||||
/// FDT根节点下的`size-cells`属性值
|
||||
root_size_cells: u32,
|
||||
|
||||
/// FDT根节点下的`address-cells`属性值
|
||||
root_addr_cells: u32,
|
||||
|
||||
chosen_node_name: Option<&'static str>,
|
||||
}
|
||||
|
||||
impl FdtGlobalData {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
root_size_cells: 1,
|
||||
root_addr_cells: 1,
|
||||
chosen_node_name: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mut FDT_VADDR: Option<VirtAddr> = None;
|
||||
|
||||
pub struct OpenFirmwareFdtDriver;
|
||||
|
||||
impl OpenFirmwareFdtDriver {
|
||||
pub fn early_scan_device_tree(&self) -> Result<(), SystemError> {
|
||||
let fdt_vaddr = unsafe { FDT_VADDR.ok_or(SystemError::EINVAL)? };
|
||||
let fdt = unsafe {
|
||||
fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| {
|
||||
kerror!("failed to parse fdt, err={:?}", e);
|
||||
SystemError::EINVAL
|
||||
})
|
||||
}?;
|
||||
|
||||
self.early_init_scan_nodes(&fdt);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn early_init_scan_nodes(&self, fdt: &Fdt) {
|
||||
self.early_init_scan_root(fdt)
|
||||
.expect("Failed to scan fdt root node.");
|
||||
|
||||
self.early_init_scan_chosen(fdt).unwrap_or_else(|_| {
|
||||
kwarn!("No `chosen` node found");
|
||||
});
|
||||
|
||||
self.early_init_scan_memory(fdt);
|
||||
}
|
||||
|
||||
/// 扫描根节点
|
||||
fn early_init_scan_root(&self, fdt: &Fdt) -> Result<(), SystemError> {
|
||||
let node = fdt.find_node("/").ok_or(SystemError::ENODEV)?;
|
||||
|
||||
let mut guard = FDT_GLOBAL_DATA.write();
|
||||
|
||||
if let Some(prop) = node.property("#size-cells") {
|
||||
guard.root_size_cells = prop.as_usize().unwrap() as u32;
|
||||
|
||||
kdebug!("fdt_root_size_cells={}", guard.root_size_cells);
|
||||
}
|
||||
|
||||
if let Some(prop) = node.property("#address-cells") {
|
||||
guard.root_addr_cells = prop.as_usize().unwrap() as u32;
|
||||
|
||||
kdebug!("fdt_root_addr_cells={}", guard.root_addr_cells);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 扫描 `/chosen` 节点
|
||||
fn early_init_scan_chosen(&self, fdt: &Fdt) -> Result<(), SystemError> {
|
||||
const CHOSEN_NAME1: &'static str = "/chosen";
|
||||
let mut node = fdt.find_node(CHOSEN_NAME1);
|
||||
if node.is_none() {
|
||||
const CHOSEN_NAME2: &'static str = "/chosen@0";
|
||||
node = fdt.find_node(CHOSEN_NAME2);
|
||||
if node.is_some() {
|
||||
FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME2);
|
||||
}
|
||||
} else {
|
||||
FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME1);
|
||||
}
|
||||
|
||||
if let Some(node) = node {
|
||||
if let Some(prop) = node.property("bootargs") {
|
||||
let bootargs = prop.as_str().unwrap();
|
||||
|
||||
boot_params()
|
||||
.write()
|
||||
.boot_cmdline_append(bootargs.as_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: 拼接内核自定义的command line参数
|
||||
|
||||
kdebug!("Command line: {}", boot_params().read().boot_cmdline_str());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 扫描 `/memory` 节点
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `fdt`:FDT
|
||||
///
|
||||
/// ## 返回值
|
||||
///
|
||||
/// 如果扫描成功,找到可用内存,则返回`true`,否则返回`false`。
|
||||
fn early_init_scan_memory(&self, fdt: &Fdt) -> bool {
|
||||
let mut found_memory = false;
|
||||
for node in fdt.all_nodes() {
|
||||
let device_type: Option<NodeProperty<'_>> = node.property("device_type");
|
||||
if device_type.is_none() {
|
||||
continue;
|
||||
}
|
||||
let device_type = device_type.unwrap().as_str();
|
||||
if device_type.is_none() || device_type.unwrap() != "memory" {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !self.is_device_avaliable(&node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let reg = node.property("reg");
|
||||
if reg.is_none() {
|
||||
continue;
|
||||
}
|
||||
let reg = reg.unwrap();
|
||||
// 每个cell是4字节
|
||||
let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize;
|
||||
let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize;
|
||||
|
||||
let total_elements_in_reg = reg.value.len() / ((addr_cells + size_cells) * 4);
|
||||
|
||||
for i in 0..total_elements_in_reg {
|
||||
let mut base_index = i * (addr_cells + size_cells);
|
||||
let base: u64;
|
||||
let size: u64;
|
||||
match addr_cells {
|
||||
1 => {
|
||||
base = u32::from_be_bytes(
|
||||
reg.value[base_index..base_index + 4].try_into().unwrap(),
|
||||
) as u64;
|
||||
}
|
||||
2 => {
|
||||
base = u64::from_be_bytes(
|
||||
reg.value[base_index..base_index + 8].try_into().unwrap(),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
panic!("addr_cells must be 1 or 2");
|
||||
}
|
||||
}
|
||||
base_index += addr_cells * 4;
|
||||
|
||||
match size_cells {
|
||||
1 => {
|
||||
size = u32::from_be_bytes(
|
||||
reg.value[base_index..base_index + 4].try_into().unwrap(),
|
||||
) as u64;
|
||||
}
|
||||
2 => {
|
||||
size = u64::from_be_bytes(
|
||||
reg.value[base_index..base_index + 8].try_into().unwrap(),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
panic!("size_cells must be 1 or 2");
|
||||
}
|
||||
}
|
||||
|
||||
if size == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
kdebug!("Found memory: base={:#x}, size={:#x}", base, size);
|
||||
self.early_init_dt_add_memory(base, size);
|
||||
found_memory = true;
|
||||
}
|
||||
}
|
||||
|
||||
return found_memory;
|
||||
}
|
||||
|
||||
fn early_init_dt_add_memory(&self, base: u64, size: u64) {
|
||||
let mut base = base as usize;
|
||||
let mut size = size as usize;
|
||||
|
||||
if size < (MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK))) {
|
||||
kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size);
|
||||
}
|
||||
|
||||
if PhysAddr::new(base).check_aligned(MMArch::PAGE_SIZE) == false {
|
||||
size -= MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK));
|
||||
base = page_align_down(base);
|
||||
}
|
||||
|
||||
size = page_align_down(size);
|
||||
|
||||
if base > MemBlockManager::MAX_MEMBLOCK_ADDR.data() {
|
||||
kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size);
|
||||
}
|
||||
|
||||
if base + size - 1 > MemBlockManager::MAX_MEMBLOCK_ADDR.data() {
|
||||
kwarn!(
|
||||
"Ignoring memory range {:#x}-{:#x}",
|
||||
MemBlockManager::MAX_MEMBLOCK_ADDR.data() + 1,
|
||||
base + size
|
||||
);
|
||||
size = MemBlockManager::MAX_MEMBLOCK_ADDR.data() - base + 1;
|
||||
}
|
||||
|
||||
if base + size < MemBlockManager::MIN_MEMBLOCK_ADDR.data() {
|
||||
kwarn!("Ignoring memory range {:#x}-{:#x}", base, base + size);
|
||||
return;
|
||||
}
|
||||
|
||||
if base < MemBlockManager::MIN_MEMBLOCK_ADDR.data() {
|
||||
{
|
||||
kwarn!(
|
||||
"Ignoring memory range {:#x}-{:#x}",
|
||||
base,
|
||||
MemBlockManager::MIN_MEMBLOCK_ADDR.data()
|
||||
);
|
||||
size -= MemBlockManager::MIN_MEMBLOCK_ADDR.data() - base;
|
||||
base = MemBlockManager::MIN_MEMBLOCK_ADDR.data();
|
||||
}
|
||||
|
||||
mem_block_manager()
|
||||
.add_block(PhysAddr::new(base), size)
|
||||
.unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Failed to add memory block '{:#x}-{:#x}', err={:?}",
|
||||
base,
|
||||
base + size,
|
||||
e
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn is_device_avaliable(&self, node: &FdtNode) -> bool {
|
||||
let status = node.property("status");
|
||||
if status.is_none() {
|
||||
return true;
|
||||
}
|
||||
|
||||
let status = status.unwrap().as_str();
|
||||
if let Some(status) = status {
|
||||
if status == "okay" || status == "ok" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
pub unsafe fn set_fdt_vaddr(&self, vaddr: VirtAddr) -> Result<(), SystemError> {
|
||||
if vaddr.is_null() {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
fdt::Fdt::from_ptr(vaddr.as_ptr()).map_err(|e| {
|
||||
kerror!("failed to parse fdt, err={:?}", e);
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
|
||||
unsafe {
|
||||
FDT_VADDR = Some(vaddr);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
2
kernel/src/driver/open_firmware/mod.rs
Normal file
2
kernel/src/driver/open_firmware/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub mod fdt;
|
@ -1,4 +1,7 @@
|
||||
use core::cmp::min;
|
||||
|
||||
use crate::{
|
||||
arch::init::ArchBootParams,
|
||||
driver::{
|
||||
tty::init::tty_early_init,
|
||||
video::{fbdev::base::BootTimeScreenInfo, VideoRefreshManager},
|
||||
@ -33,14 +36,67 @@ pub fn init_before_mem_init() {
|
||||
#[derive(Debug)]
|
||||
pub struct BootParams {
|
||||
pub screen_info: BootTimeScreenInfo,
|
||||
pub arch: ArchBootParams,
|
||||
boot_command_line: [u8; Self::BOOT_COMMAND_LINE_SIZE],
|
||||
}
|
||||
|
||||
impl BootParams {
|
||||
const DEFAULT: Self = BootParams {
|
||||
screen_info: BootTimeScreenInfo::DEFAULT,
|
||||
arch: ArchBootParams::DEFAULT,
|
||||
boot_command_line: [0u8; Self::BOOT_COMMAND_LINE_SIZE],
|
||||
};
|
||||
|
||||
/// 开机命令行参数字符串最大大小
|
||||
pub const BOOT_COMMAND_LINE_SIZE: usize = 2048;
|
||||
|
||||
const fn new() -> Self {
|
||||
Self::DEFAULT
|
||||
}
|
||||
|
||||
/// 开机命令行参数(原始字节数组)
|
||||
#[allow(dead_code)]
|
||||
pub fn boot_cmdline(&self) -> &[u8] {
|
||||
&self.boot_command_line
|
||||
}
|
||||
|
||||
/// 开机命令行参数字符串
|
||||
pub fn boot_cmdline_str(&self) -> &str {
|
||||
core::str::from_utf8(self.boot_cmdline()).unwrap()
|
||||
}
|
||||
|
||||
/// 追加开机命令行参数
|
||||
///
|
||||
/// 如果开机命令行参数已经满了,则不会追加。
|
||||
/// 如果超过了最大长度,则截断。
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `data`:追加的数据
|
||||
pub fn boot_cmdline_append(&mut self, data: &[u8]) {
|
||||
if data.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut pos: Option<usize> = None;
|
||||
// 寻找结尾
|
||||
for (i, x) in self.boot_command_line.iter().enumerate() {
|
||||
if *x == 0 {
|
||||
pos = Some(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
let pos = pos.unwrap_or_else(|| self.boot_command_line.len() - 1) as isize;
|
||||
|
||||
let avail = self.boot_command_line.len() as isize - pos - 1;
|
||||
if avail <= 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let len = min(avail as usize, data.len());
|
||||
let pos = pos as usize;
|
||||
self.boot_command_line[pos..pos + len].copy_from_slice(&data[0..len]);
|
||||
|
||||
self.boot_command_line[pos + len] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,11 @@
|
||||
/// @FilePath: /DragonOS/kernel/src/mm/allocator/bump.rs
|
||||
/// @Description: bump allocator线性分配器
|
||||
use super::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage};
|
||||
use crate::mm::{MemoryManagementArch, PhysAddr, PhysMemoryArea};
|
||||
use crate::mm::{memblock::mem_block_manager, MemoryManagementArch, PhysAddr, PhysMemoryArea};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// 线性分配器
|
||||
pub struct BumpAllocator<MMA> {
|
||||
// 表示可用物理内存区域的数组。每个 PhysMemoryArea 结构体描述一个物理内存区域的起始地址和大小。
|
||||
areas: &'static [PhysMemoryArea],
|
||||
// 表示当前分配的物理内存的偏移量.
|
||||
offset: usize,
|
||||
// 一个占位类型,用于标记 A 类型在结构体中的存在。但是,它并不会占用任何内存空间,因为它的大小为 0。
|
||||
@ -22,17 +20,13 @@ impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
|
||||
/// @param Fareas 当前的内存区域
|
||||
/// @param offset 当前的偏移量
|
||||
/// @return 分配器本身
|
||||
pub fn new(areas: &'static [PhysMemoryArea], offset: usize) -> Self {
|
||||
pub fn new(offset: usize) -> Self {
|
||||
Self {
|
||||
areas,
|
||||
offset,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
// @brief 获取页帧使用情况
|
||||
pub fn areas(&self) -> &'static [PhysMemoryArea] {
|
||||
return self.areas;
|
||||
}
|
||||
|
||||
// @brief 获取当前分配的物理内存的偏移量
|
||||
pub fn offset(&self) -> usize {
|
||||
return self.offset;
|
||||
@ -51,9 +45,10 @@ impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
|
||||
|
||||
let mut res_cnt = 0;
|
||||
|
||||
let total_num = mem_block_manager().total_initial_memory_regions();
|
||||
// 遍历所有的物理内存区域
|
||||
for i in 0..self.areas().len() {
|
||||
let area = &self.areas()[i];
|
||||
for i in 0..total_num {
|
||||
let area = mem_block_manager().get_initial_memory_region(i).unwrap();
|
||||
// 将area的base地址与PAGE_SIZE对齐,对齐时向上取整
|
||||
// let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
|
||||
let area_base = area.area_base_aligned().data();
|
||||
@ -75,9 +70,10 @@ impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
|
||||
}
|
||||
// found
|
||||
if offset + 1 * MMA::PAGE_SIZE <= area_end {
|
||||
for j in i..self.areas().len() {
|
||||
if self.areas()[j].area_base_aligned() < self.areas()[j].area_end_aligned() {
|
||||
result_area[res_cnt] = self.areas()[j];
|
||||
for j in i..total_num {
|
||||
let aj = mem_block_manager().get_initial_memory_region(j).unwrap();
|
||||
if aj.area_base_aligned() < aj.area_end_aligned() {
|
||||
result_area[res_cnt] = aj;
|
||||
res_cnt += 1;
|
||||
}
|
||||
}
|
||||
@ -102,8 +98,11 @@ impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
|
||||
/// @return 分配后的物理地址
|
||||
unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
|
||||
let mut offset = self.offset();
|
||||
|
||||
let iter = mem_block_manager().to_iter();
|
||||
|
||||
// 遍历所有的物理内存区域
|
||||
for area in self.areas().iter() {
|
||||
for area in iter {
|
||||
// 将area的base地址与PAGE_SIZE对齐,对齐时向上取整
|
||||
// let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
|
||||
let area_base = area.area_base_aligned().data();
|
||||
@ -145,7 +144,8 @@ impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
|
||||
unsafe fn usage(&self) -> PageFrameUsage {
|
||||
let mut total = 0;
|
||||
let mut used = 0;
|
||||
for area in self.areas().iter() {
|
||||
let iter = mem_block_manager().to_iter();
|
||||
for area in iter {
|
||||
// 将area的base地址与PAGE_SIZE对齐,对其时向上取整
|
||||
let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
|
||||
// 将area的末尾地址与PAGE_SIZE对齐,对其时向下取整
|
||||
|
351
kernel/src/mm/memblock.rs
Normal file
351
kernel/src/mm/memblock.rs
Normal file
@ -0,0 +1,351 @@
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
|
||||
|
||||
use super::{PhysAddr, PhysMemoryArea};
|
||||
|
||||
pub const INITIAL_MEMORY_REGIONS_NUM: usize = 128;
|
||||
|
||||
/// 初始内存区域
|
||||
static MEM_BLOCK_MANAGER: MemBlockManager = MemBlockManager::new();
|
||||
|
||||
#[inline(always)]
|
||||
pub fn mem_block_manager() -> &'static MemBlockManager {
|
||||
&MEM_BLOCK_MANAGER
|
||||
}
|
||||
|
||||
/// 内存区域管理器
|
||||
#[derive(Debug)]
|
||||
pub struct MemBlockManager {
|
||||
inner: SpinLock<InnerMemBlockManager>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InnerMemBlockManager {
|
||||
/// 初始内存区域
|
||||
///
|
||||
/// 用于记录内核启动时的内存布局, 这些区域保持升序、不重叠
|
||||
initial_memory_regions: [PhysMemoryArea; INITIAL_MEMORY_REGIONS_NUM],
|
||||
initial_memory_regions_num: usize,
|
||||
}
|
||||
|
||||
impl MemBlockManager {
|
||||
#[allow(dead_code)]
|
||||
pub const MIN_MEMBLOCK_ADDR: PhysAddr = PhysAddr::new(0);
|
||||
#[allow(dead_code)]
|
||||
pub const MAX_MEMBLOCK_ADDR: PhysAddr = PhysAddr::new(usize::MAX);
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
inner: SpinLock::new(InnerMemBlockManager {
|
||||
initial_memory_regions: [PhysMemoryArea::DEFAULT; INITIAL_MEMORY_REGIONS_NUM],
|
||||
initial_memory_regions_num: 0,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/// 添加内存区域
|
||||
///
|
||||
/// 如果添加的区域与已有区域有重叠,会将重叠的区域合并
|
||||
#[allow(dead_code)]
|
||||
pub fn add_block(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> {
|
||||
if size == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
let mut inner = self.inner.lock();
|
||||
if inner.initial_memory_regions_num >= INITIAL_MEMORY_REGIONS_NUM {
|
||||
panic!("Too many memory regions!");
|
||||
}
|
||||
|
||||
let block = PhysMemoryArea::new(base, size);
|
||||
// 特判第一个区域
|
||||
if inner.initial_memory_regions_num == 0 {
|
||||
inner.initial_memory_regions[0] = block;
|
||||
inner.initial_memory_regions_num += 1;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// 先计算需要添加的区域数量
|
||||
let blocks_to_add = self
|
||||
.do_add_block(&mut inner, block, false)
|
||||
.expect("Failed to count blocks to add!");
|
||||
|
||||
if inner.initial_memory_regions_num + blocks_to_add > INITIAL_MEMORY_REGIONS_NUM {
|
||||
kerror!("Too many memory regions!");
|
||||
return Err(SystemError::ENOMEM);
|
||||
}
|
||||
|
||||
// 然后添加区域
|
||||
self.do_add_block(&mut inner, block, true)
|
||||
.expect("Failed to add block!");
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn do_add_block(
|
||||
&self,
|
||||
inner: &mut SpinLockGuard<'_, InnerMemBlockManager>,
|
||||
block: PhysMemoryArea,
|
||||
insert: bool,
|
||||
) -> Result<usize, SystemError> {
|
||||
let mut base = block.base;
|
||||
let end = block.base + block.size;
|
||||
let mut i = 0;
|
||||
let mut start_index = -1;
|
||||
let mut end_index = -1;
|
||||
|
||||
let mut num_to_add = 0;
|
||||
|
||||
while i < inner.initial_memory_regions_num {
|
||||
let range_base = inner.initial_memory_regions[i].base;
|
||||
let range_end =
|
||||
inner.initial_memory_regions[i].base + inner.initial_memory_regions[i].size;
|
||||
|
||||
if range_base >= end {
|
||||
break;
|
||||
}
|
||||
if range_end <= base {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 有重叠
|
||||
|
||||
if range_base > base {
|
||||
num_to_add += 1;
|
||||
if insert {
|
||||
if start_index == -1 {
|
||||
start_index = i as isize;
|
||||
}
|
||||
end_index = (i + 1) as isize;
|
||||
self.do_insert_area(inner, i, base, range_base - base);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
i += 1;
|
||||
base = core::cmp::min(range_end, end);
|
||||
}
|
||||
|
||||
if base < end {
|
||||
num_to_add += 1;
|
||||
if insert {
|
||||
if start_index == -1 {
|
||||
start_index = i as isize;
|
||||
}
|
||||
end_index = (i + 1) as isize;
|
||||
self.do_insert_area(inner, i, base, end - base);
|
||||
}
|
||||
}
|
||||
|
||||
if num_to_add == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
if insert {
|
||||
self.do_merge_blocks(inner, start_index, end_index);
|
||||
}
|
||||
return Ok(num_to_add);
|
||||
}
|
||||
|
||||
fn do_insert_area(
|
||||
&self,
|
||||
inner: &mut SpinLockGuard<'_, InnerMemBlockManager>,
|
||||
index: usize,
|
||||
base: PhysAddr,
|
||||
size: usize,
|
||||
) {
|
||||
let copy_elements = inner.initial_memory_regions_num - index;
|
||||
inner
|
||||
.initial_memory_regions
|
||||
.copy_within(index..index + copy_elements, index + 1);
|
||||
inner.initial_memory_regions[index] = PhysMemoryArea::new(base, size);
|
||||
inner.initial_memory_regions_num += 1;
|
||||
}
|
||||
|
||||
fn do_merge_blocks(
|
||||
&self,
|
||||
inner: &mut SpinLockGuard<'_, InnerMemBlockManager>,
|
||||
start_index: isize,
|
||||
mut end_index: isize,
|
||||
) {
|
||||
let mut i = 0;
|
||||
if start_index > 0 {
|
||||
i = start_index - 1;
|
||||
}
|
||||
end_index = core::cmp::min(end_index, inner.initial_memory_regions_num as isize - 1);
|
||||
|
||||
while i < end_index {
|
||||
{
|
||||
let next_base = inner.initial_memory_regions[(i + 1) as usize].base;
|
||||
let next_size = inner.initial_memory_regions[(i + 1) as usize].size;
|
||||
let this = &mut inner.initial_memory_regions[i as usize];
|
||||
|
||||
if this.base + this.size != next_base {
|
||||
// BUG_ON(this->base + this->size > next->base);
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
this.size += next_size;
|
||||
}
|
||||
// 移动后面的区域
|
||||
let copy_elements = inner.initial_memory_regions_num - (i + 2) as usize;
|
||||
inner.initial_memory_regions.copy_within(
|
||||
(i + 2) as usize..(i as usize + 2 + copy_elements),
|
||||
(i + 1) as usize,
|
||||
);
|
||||
|
||||
inner.initial_memory_regions_num -= 1;
|
||||
end_index -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// 移除内存区域
|
||||
///
|
||||
/// 如果移除的区域与已有区域有重叠,会将重叠的区域分割
|
||||
#[allow(dead_code)]
|
||||
pub fn remove_block(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> {
|
||||
if size == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
let mut inner = self.inner.lock();
|
||||
if inner.initial_memory_regions_num == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let (start_index, end_index) = self
|
||||
.isolate_range(&mut inner, base, size)
|
||||
.expect("Failed to isolate range!");
|
||||
|
||||
for i in (start_index..end_index).rev() {
|
||||
self.do_remove_region(&mut inner, i);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn do_remove_region(&self, inner: &mut SpinLockGuard<'_, InnerMemBlockManager>, index: usize) {
|
||||
let copy_elements = inner.initial_memory_regions_num - index - 1;
|
||||
inner
|
||||
.initial_memory_regions
|
||||
.copy_within(index + 1..index + 1 + copy_elements, index);
|
||||
|
||||
inner.initial_memory_regions_num -= 1;
|
||||
|
||||
if inner.initial_memory_regions_num == 0 {
|
||||
inner.initial_memory_regions[0].base = PhysAddr::new(0);
|
||||
inner.initial_memory_regions[0].size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fn isolate_range(
|
||||
&self,
|
||||
inner: &mut SpinLockGuard<'_, InnerMemBlockManager>,
|
||||
base: PhysAddr,
|
||||
size: usize,
|
||||
) -> Result<(usize, usize), SystemError> {
|
||||
let end = base + size;
|
||||
|
||||
let mut idx = 0;
|
||||
|
||||
let mut start_index = 0;
|
||||
let mut end_index = 0;
|
||||
|
||||
if size == 0 {
|
||||
return Ok((0, 0));
|
||||
}
|
||||
|
||||
while idx < inner.initial_memory_regions_num {
|
||||
let range_base = inner.initial_memory_regions[idx].base;
|
||||
let range_end = range_base + inner.initial_memory_regions[idx].size;
|
||||
|
||||
if range_base >= end {
|
||||
break;
|
||||
}
|
||||
if range_end <= base {
|
||||
idx = idx.checked_add(1).unwrap_or(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if range_base < base {
|
||||
// regions[idx] intersects from below
|
||||
inner.initial_memory_regions[idx].base = base;
|
||||
inner.initial_memory_regions[idx].size -= base - range_base;
|
||||
self.do_insert_area(inner, idx, range_base, base - range_base);
|
||||
} else if range_end > end {
|
||||
// regions[idx] intersects from above
|
||||
inner.initial_memory_regions[idx].base = end;
|
||||
inner.initial_memory_regions[idx].size -= end - range_base;
|
||||
|
||||
self.do_insert_area(inner, idx, range_base, end - range_base);
|
||||
if idx == 0 {
|
||||
idx = usize::MAX;
|
||||
} else {
|
||||
idx -= 1;
|
||||
}
|
||||
} else {
|
||||
// regions[idx] is inside the range, record it
|
||||
if end_index == 0 {
|
||||
start_index = idx;
|
||||
}
|
||||
end_index = idx + 1;
|
||||
}
|
||||
|
||||
idx = idx.checked_add(1).unwrap_or(0);
|
||||
}
|
||||
|
||||
return Ok((start_index, end_index));
|
||||
}
|
||||
|
||||
/// 生成迭代器
|
||||
pub fn to_iter(&self) -> MemBlockIter {
|
||||
let inner = self.inner.lock();
|
||||
return MemBlockIter { inner, index: 0 };
|
||||
}
|
||||
|
||||
/// 获取初始内存区域数量
|
||||
pub fn total_initial_memory_regions(&self) -> usize {
|
||||
let inner = self.inner.lock();
|
||||
return inner.initial_memory_regions_num;
|
||||
}
|
||||
|
||||
/// 根据索引获取初始内存区域
|
||||
pub fn get_initial_memory_region(&self, index: usize) -> Option<PhysMemoryArea> {
|
||||
let inner = self.inner.lock();
|
||||
return inner.initial_memory_regions.get(index).copied();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MemBlockIter<'a> {
|
||||
inner: SpinLockGuard<'a, InnerMemBlockManager>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<'a> MemBlockIter<'a> {
|
||||
/// 获取内存区域数量
|
||||
pub fn total_num(&self) -> usize {
|
||||
self.inner.initial_memory_regions_num
|
||||
}
|
||||
|
||||
/// 获取指定索引的内存区域
|
||||
pub fn get_area(&self, index: usize) -> &PhysMemoryArea {
|
||||
&self.inner.initial_memory_regions[index]
|
||||
}
|
||||
|
||||
/// 获取当前索引
|
||||
pub fn current_index(&self) -> usize {
|
||||
self.index
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for MemBlockIter<'a> {
|
||||
type Item = PhysMemoryArea;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.index >= self.inner.initial_memory_regions_num {
|
||||
return None;
|
||||
}
|
||||
let ret = self.inner.initial_memory_regions[self.index];
|
||||
self.index += 1;
|
||||
return Some(ret);
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ use self::{
|
||||
pub mod allocator;
|
||||
pub mod c_adapter;
|
||||
pub mod kernel_mapper;
|
||||
pub mod memblock;
|
||||
pub mod mmio_buddy;
|
||||
pub mod no_init;
|
||||
pub mod page;
|
||||
@ -331,6 +332,11 @@ pub struct PhysMemoryArea {
|
||||
}
|
||||
|
||||
impl PhysMemoryArea {
|
||||
pub const DEFAULT: Self = Self {
|
||||
base: PhysAddr::new(0),
|
||||
size: 0,
|
||||
};
|
||||
|
||||
pub fn new(base: PhysAddr, size: usize) -> Self {
|
||||
Self { base, size }
|
||||
}
|
||||
@ -350,10 +356,7 @@ impl PhysMemoryArea {
|
||||
|
||||
impl Default for PhysMemoryArea {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
base: PhysAddr::new(0),
|
||||
size: 0,
|
||||
}
|
||||
return Self::DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,8 +430,8 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
|
||||
const USER_STACK_START: VirtAddr;
|
||||
|
||||
/// @brief 用于初始化内存管理模块与架构相关的信息。
|
||||
/// 该函数应调用其他模块的接口,生成内存区域结构体,提供给BumpAllocator使用
|
||||
unsafe fn init() -> &'static [PhysMemoryArea];
|
||||
/// 该函数应调用其他模块的接口,把可用内存区域添加到memblock,提供给BumpAllocator使用
|
||||
unsafe fn init();
|
||||
|
||||
/// @brief 读取指定虚拟地址的值,并假设它是类型T的指针
|
||||
#[inline(always)]
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 5d9a3c158772e628967d96e442c7398fa9da576a
|
||||
Subproject commit 7fc3806da73be059540a79b6fdddf8049be250f3
|
Loading…
x
Reference in New Issue
Block a user