mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 07:06:47 +00:00
初始化riscv的内存管理模块,并且设置保留内存 (#506)
This commit is contained in:
parent
a02ce654cf
commit
453452cc02
@ -7,7 +7,7 @@ use crate::{
|
||||
driver::{firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver},
|
||||
init::{boot_params, init_before_mem_init},
|
||||
kdebug, kinfo,
|
||||
mm::{PhysAddr, VirtAddr},
|
||||
mm::{init::mm_init, memblock::mem_block_manager, PhysAddr, VirtAddr},
|
||||
print, println,
|
||||
};
|
||||
|
||||
@ -49,12 +49,19 @@ unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
|
||||
mm_early_init();
|
||||
|
||||
let fdt = fdt::Fdt::from_ptr(fdt_paddr.data() as *const u8).expect("Failed to parse fdt!");
|
||||
// print_node(fdt.find_node("/").unwrap(), 0);
|
||||
print_node(fdt.find_node("/").unwrap(), 0);
|
||||
|
||||
parse_dtb();
|
||||
|
||||
for x in mem_block_manager().to_iter() {
|
||||
kdebug!("before efi: {x:?}");
|
||||
}
|
||||
|
||||
efi_init();
|
||||
|
||||
open_firmware_fdt_driver().early_init_fdt_scan_reserved_mem();
|
||||
|
||||
mm_init();
|
||||
loop {}
|
||||
unreachable()
|
||||
}
|
||||
|
@ -1,13 +1,34 @@
|
||||
use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
|
||||
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
arch::mm::{KERNEL_BEGIN_PA, KERNEL_BEGIN_VA, KERNEL_END_PA, KERNEL_END_VA},
|
||||
kdebug,
|
||||
mm::{PhysAddr, VirtAddr},
|
||||
arch::{
|
||||
mm::{
|
||||
kernel_page_flags, INNER_ALLOCATOR, KERNEL_BEGIN_PA, KERNEL_BEGIN_VA, KERNEL_END_PA,
|
||||
KERNEL_END_VA,
|
||||
},
|
||||
MMArch,
|
||||
},
|
||||
driver::firmware::efi::efi_manager,
|
||||
kdebug, kinfo,
|
||||
libs::lib_ui::screen_manager::scm_disable_put_to_window,
|
||||
mm::{
|
||||
allocator::{buddy::BuddyAllocator, bump::BumpAllocator, page_frame::FrameAllocator},
|
||||
kernel_mapper::KernelMapper,
|
||||
memblock::mem_block_manager,
|
||||
page::PageEntry,
|
||||
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
|
||||
},
|
||||
};
|
||||
|
||||
use super::RiscV64MMArch;
|
||||
|
||||
pub(super) static mut INITIAL_PGTABLE_VALUE: PhysAddr = PhysAddr::new(0);
|
||||
|
||||
#[inline(never)]
|
||||
pub fn mm_early_init() {
|
||||
unsafe { init_kernel_addr() };
|
||||
// unsafe { map_initial_page_table_linearly() };
|
||||
}
|
||||
|
||||
unsafe fn init_kernel_addr() {
|
||||
@ -43,3 +64,156 @@ unsafe fn init_kernel_addr() {
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) unsafe fn riscv_mm_init() -> Result<(), SystemError> {
|
||||
mem_block_manager()
|
||||
.reserve_block(KERNEL_BEGIN_PA, KERNEL_END_PA - KERNEL_BEGIN_PA)
|
||||
.expect("Failed to reserve kernel memory");
|
||||
|
||||
let mut bump_allocator = BumpAllocator::<RiscV64MMArch>::new(0);
|
||||
let _old_page_table = MMArch::table(PageTableKind::Kernel);
|
||||
let new_page_table: PhysAddr;
|
||||
|
||||
// 使用bump分配器,把所有的内存页都映射到页表
|
||||
{
|
||||
kdebug!("to create new page table");
|
||||
// 用bump allocator创建新的页表
|
||||
let mut mapper: crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>> =
|
||||
crate::mm::page::PageMapper::<MMArch, _>::create(
|
||||
PageTableKind::Kernel,
|
||||
&mut bump_allocator,
|
||||
)
|
||||
.expect("Failed to create page mapper");
|
||||
new_page_table = mapper.table().phys();
|
||||
kdebug!("PageMapper created");
|
||||
|
||||
// 取消最开始时候,在head.S中指定的映射(暂时不刷新TLB)
|
||||
{
|
||||
let table = mapper.table();
|
||||
let empty_entry = PageEntry::<MMArch>::from_usize(0);
|
||||
for i in 0..MMArch::PAGE_ENTRY_NUM {
|
||||
table
|
||||
.set_entry(i, empty_entry)
|
||||
.expect("Failed to empty page table entry");
|
||||
}
|
||||
}
|
||||
kdebug!("Successfully emptied page table");
|
||||
|
||||
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);
|
||||
let vaddr = unsafe { MMArch::phys_2_virt(paddr) }.unwrap();
|
||||
let flags = kernel_page_flags::<MMArch>(vaddr).set_execute(true);
|
||||
|
||||
let flusher = mapper
|
||||
.map_phys(vaddr, paddr, flags)
|
||||
.expect("Failed to map frame");
|
||||
// 暂时不刷新TLB
|
||||
flusher.ignore();
|
||||
}
|
||||
}
|
||||
|
||||
// 添加低地址的映射(在smp完成初始化之前,需要使用低地址的映射.初始化之后需要取消这一段映射)
|
||||
LowAddressRemapping::remap_at_low_address(&mut mapper);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
INITIAL_PGTABLE_VALUE = new_page_table;
|
||||
}
|
||||
kdebug!(
|
||||
"After mapping all physical memory, DragonOS used: {} KB",
|
||||
bump_allocator.usage().used().bytes() / 1024
|
||||
);
|
||||
|
||||
// 初始化buddy_allocator
|
||||
let buddy_allocator = unsafe { BuddyAllocator::<MMArch>::new(bump_allocator).unwrap() };
|
||||
// 设置全局的页帧分配器
|
||||
unsafe { set_inner_allocator(buddy_allocator) };
|
||||
kinfo!("Successfully initialized buddy allocator");
|
||||
// 关闭显示输出
|
||||
scm_disable_put_to_window();
|
||||
|
||||
// make the new page table current
|
||||
{
|
||||
let mut binding = INNER_ALLOCATOR.lock();
|
||||
let mut allocator_guard = binding.as_mut().unwrap();
|
||||
kdebug!("To enable new page table.");
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
let mapper = crate::mm::page::PageMapper::<MMArch, _>::new(
|
||||
PageTableKind::Kernel,
|
||||
new_page_table,
|
||||
&mut allocator_guard,
|
||||
);
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
mapper.make_current();
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
// kdebug!("New page table enabled");
|
||||
}
|
||||
kdebug!("Successfully enabled new page table");
|
||||
kinfo!("riscv mm init done");
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
unsafe fn set_inner_allocator(allocator: BuddyAllocator<MMArch>) {
|
||||
static FLAG: AtomicBool = AtomicBool::new(false);
|
||||
if FLAG
|
||||
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
|
||||
.is_err()
|
||||
{
|
||||
panic!("Cannot set inner allocator twice!");
|
||||
}
|
||||
*INNER_ALLOCATOR.lock() = Some(allocator);
|
||||
}
|
||||
|
||||
/// 低地址重映射的管理器
|
||||
///
|
||||
/// 低地址重映射的管理器,在smp初始化完成之前,需要使用低地址的映射,因此需要在smp初始化完成之后,取消这一段映射
|
||||
pub struct LowAddressRemapping;
|
||||
|
||||
impl LowAddressRemapping {
|
||||
pub unsafe fn remap_at_low_address(
|
||||
mapper: &mut crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>>,
|
||||
) {
|
||||
let info = efi_manager().kernel_load_info().unwrap();
|
||||
let base = PhysAddr::new(info.paddr as usize);
|
||||
let size = info.size as usize;
|
||||
|
||||
for i in 0..(size / MMArch::PAGE_SIZE) {
|
||||
let paddr = PhysAddr::new(base.data() + i * MMArch::PAGE_SIZE);
|
||||
let vaddr = VirtAddr::new(base.data() + i * MMArch::PAGE_SIZE);
|
||||
let flags = kernel_page_flags::<MMArch>(vaddr).set_execute(true);
|
||||
|
||||
let flusher = mapper
|
||||
.map_phys(vaddr, paddr, flags)
|
||||
.expect("Failed to map frame");
|
||||
// 暂时不刷新TLB
|
||||
flusher.ignore();
|
||||
}
|
||||
}
|
||||
|
||||
/// 取消低地址的映射
|
||||
pub unsafe fn unmap_at_low_address(flush: bool) {
|
||||
let mut mapper = KernelMapper::lock();
|
||||
assert!(mapper.as_mut().is_some());
|
||||
|
||||
let info = efi_manager().kernel_load_info().unwrap();
|
||||
let base = PhysAddr::new(info.paddr as usize);
|
||||
let size = info.size as usize;
|
||||
|
||||
for i in 0..(size / MMArch::PAGE_SIZE) {
|
||||
let vaddr = VirtAddr::new(base.data() + i * MMArch::PAGE_SIZE);
|
||||
let (_, _, flusher) = mapper
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.unmap_phys(vaddr, true)
|
||||
.expect("Failed to unmap frame");
|
||||
if flush == false {
|
||||
flusher.ignore();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,21 @@
|
||||
use riscv::register::satp;
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::mm::{
|
||||
allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
|
||||
page::PageFlags,
|
||||
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
|
||||
use crate::{
|
||||
arch::MMArch,
|
||||
libs::spinlock::SpinLock,
|
||||
mm::{
|
||||
allocator::{
|
||||
buddy::BuddyAllocator,
|
||||
page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
|
||||
},
|
||||
page::PageFlags,
|
||||
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
|
||||
},
|
||||
};
|
||||
|
||||
use self::init::riscv_mm_init;
|
||||
|
||||
pub mod bump;
|
||||
pub(super) mod init;
|
||||
|
||||
@ -21,6 +30,8 @@ pub(self) static mut KERNEL_BEGIN_VA: VirtAddr = VirtAddr::new(0);
|
||||
/// 内核结束虚拟地址
|
||||
pub(self) static mut KERNEL_END_VA: VirtAddr = VirtAddr::new(0);
|
||||
|
||||
pub(self) static INNER_ALLOCATOR: SpinLock<Option<BuddyAllocator<MMArch>>> = SpinLock::new(None);
|
||||
|
||||
/// RiscV64的内存管理架构结构体(sv39)
|
||||
#[derive(Debug, Clone, Copy, Hash)]
|
||||
pub struct RiscV64MMArch;
|
||||
@ -65,6 +76,7 @@ impl MemoryManagementArch for RiscV64MMArch {
|
||||
const ENTRY_FLAG_DIRTY: usize = (1 << 7);
|
||||
|
||||
const PHYS_OFFSET: usize = 0xffff_ffc0_0000_0000;
|
||||
const KERNEL_LINK_OFFSET: usize = 0x1000000;
|
||||
|
||||
const USER_END_VADDR: crate::mm::VirtAddr = VirtAddr::new(0x0000_003f_ffff_ffff);
|
||||
|
||||
@ -77,8 +89,9 @@ impl MemoryManagementArch for RiscV64MMArch {
|
||||
/// 设置1MB的fixmap空间
|
||||
const FIXMAP_SIZE: usize = 256 * 4096;
|
||||
|
||||
#[inline(never)]
|
||||
unsafe fn init() {
|
||||
todo!()
|
||||
riscv_mm_init().expect("init kernel memory management architecture failed");
|
||||
}
|
||||
|
||||
unsafe fn invalidate_page(address: VirtAddr) {
|
||||
@ -147,7 +160,7 @@ impl MemoryManagementArch for RiscV64MMArch {
|
||||
|
||||
fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize {
|
||||
let ppn = PhysPageFrame::new(paddr).ppn();
|
||||
let r = ((ppn & ((1 << 44) - 1)) << 10) | page_flags;
|
||||
let r = ((ppn & ((1 << 54) - 1)) << 10) | page_flags;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@ -164,8 +177,10 @@ impl VirtAddr {
|
||||
}
|
||||
|
||||
/// 获取内核地址默认的页面标志
|
||||
pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(virt: VirtAddr) -> PageFlags<A> {
|
||||
unimplemented!("riscv64::kernel_page_flags")
|
||||
pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> {
|
||||
PageFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE)
|
||||
.set_user(false)
|
||||
.set_execute(true)
|
||||
}
|
||||
|
||||
/// 全局的页帧分配器
|
||||
@ -174,15 +189,25 @@ pub struct LockedFrameAllocator;
|
||||
|
||||
impl FrameAllocator for LockedFrameAllocator {
|
||||
unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
|
||||
unimplemented!("RiscV64 LockedFrameAllocator::allocate")
|
||||
if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
|
||||
return allocator.allocate(count);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) {
|
||||
assert!(count.data().is_power_of_two());
|
||||
unimplemented!("RiscV64 LockedFrameAllocator::free")
|
||||
if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
|
||||
return allocator.free(address, count);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn usage(&self) -> PageFrameUsage {
|
||||
unimplemented!("RiscV64 LockedFrameAllocator::usage")
|
||||
if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
|
||||
return allocator.usage();
|
||||
} else {
|
||||
panic!("usage error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,6 @@ pub struct RiscV64TimeArch;
|
||||
|
||||
impl TimeArch for RiscV64TimeArch {
|
||||
fn get_cycles() -> usize {
|
||||
unimplemented!("Riscv64TimeArch::get_cycles")
|
||||
riscv::register::cycle::read()
|
||||
}
|
||||
}
|
||||
|
@ -8,19 +8,16 @@ use x86::time::rdtsc;
|
||||
use x86_64::registers::model_specific::EferFlags;
|
||||
|
||||
use crate::driver::tty::serial::serial8250::send_to_default_serial8250_port;
|
||||
use crate::filesystem::procfs::kmsg::kmsg_init;
|
||||
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::libs::align::page_align_up;
|
||||
use crate::libs::lib_ui::screen_manager::scm_disable_put_to_window;
|
||||
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,
|
||||
mm::allocator::{buddy::BuddyAllocator, bump::BumpAllocator},
|
||||
@ -34,7 +31,7 @@ use system_error::SystemError;
|
||||
|
||||
use core::arch::asm;
|
||||
use core::ffi::c_void;
|
||||
use core::fmt::{Debug, Write};
|
||||
use core::fmt::Debug;
|
||||
use core::mem::{self};
|
||||
|
||||
use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
|
||||
@ -114,6 +111,7 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
/// 物理地址与虚拟地址的偏移量
|
||||
/// 0xffff_8000_0000_0000
|
||||
const PHYS_OFFSET: usize = Self::PAGE_NEGATIVE_MASK + (Self::PAGE_ADDRESS_SIZE >> 1);
|
||||
const KERNEL_LINK_OFFSET: usize = 0x100000;
|
||||
|
||||
// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/include/asm/page_64_types.h#75
|
||||
const USER_END_VADDR: VirtAddr =
|
||||
@ -154,7 +152,14 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
// 初始化物理内存区域(从multiboot2中获取)
|
||||
Self::init_memory_area_from_multiboot2().expect("init memory area failed");
|
||||
|
||||
send_to_default_serial8250_port("x86 64 init end\n\0".as_bytes());
|
||||
kdebug!("bootstrap info: {:?}", unsafe { BOOTSTRAP_MM_INFO });
|
||||
kdebug!("phys[0]=virt[0x{:x}]", unsafe {
|
||||
MMArch::phys_2_virt(PhysAddr::new(0)).unwrap().data()
|
||||
});
|
||||
|
||||
// 初始化内存管理器
|
||||
unsafe { allocator_init() };
|
||||
send_to_default_serial8250_port("x86 64 init done\n\0".as_bytes());
|
||||
}
|
||||
|
||||
/// @brief 刷新TLB中,关于指定虚拟地址的条目
|
||||
@ -399,36 +404,6 @@ impl VirtAddr {
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 初始化内存管理模块
|
||||
pub fn mm_init() {
|
||||
send_to_default_serial8250_port("mm_init\n\0".as_bytes());
|
||||
PrintkWriter
|
||||
.write_fmt(format_args!("mm_init() called\n"))
|
||||
.unwrap();
|
||||
// printk_color!(GREEN, BLACK, "mm_init() called\n");
|
||||
static _CALL_ONCE: AtomicBool = AtomicBool::new(false);
|
||||
if _CALL_ONCE
|
||||
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
|
||||
.is_err()
|
||||
{
|
||||
send_to_default_serial8250_port("mm_init err\n\0".as_bytes());
|
||||
panic!("mm_init() can only be called once");
|
||||
}
|
||||
|
||||
unsafe { X86_64MMArch::init() };
|
||||
kdebug!("bootstrap info: {:?}", unsafe { BOOTSTRAP_MM_INFO });
|
||||
kdebug!("phys[0]=virt[0x{:x}]", unsafe {
|
||||
MMArch::phys_2_virt(PhysAddr::new(0)).unwrap().data()
|
||||
});
|
||||
|
||||
// 初始化内存管理器
|
||||
unsafe { allocator_init() };
|
||||
// enable mmio
|
||||
mmio_init();
|
||||
// enable KMSG
|
||||
kmsg_init();
|
||||
}
|
||||
|
||||
unsafe fn allocator_init() {
|
||||
let virt_offset = BOOTSTRAP_MM_INFO.unwrap().start_brk;
|
||||
let phy_offset =
|
||||
@ -681,8 +656,8 @@ unsafe fn set_inner_allocator(allocator: BuddyAllocator<MMArch>) {
|
||||
pub struct LowAddressRemapping;
|
||||
|
||||
impl LowAddressRemapping {
|
||||
// 映射32M
|
||||
const REMAP_SIZE: usize = 32 * 1024 * 1024;
|
||||
// 映射64M
|
||||
const REMAP_SIZE: usize = 64 * 1024 * 1024;
|
||||
|
||||
pub unsafe fn remap_at_low_address(
|
||||
mapper: &mut crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>>,
|
||||
@ -717,7 +692,3 @@ impl LowAddressRemapping {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rs_mm_init() {
|
||||
mm_init();
|
||||
}
|
||||
|
@ -12,6 +12,23 @@ pub static DRAGONSTUB_EFI_PAYLOAD_EFI_GUID: Guid = Guid::new(
|
||||
[0xbc, 0xef, 0x98, 0x12, 0x00, 0x31],
|
||||
);
|
||||
|
||||
pub static EFI_MEMORY_ATTRIBUTES_TABLE_GUID: Guid = Guid::new(
|
||||
unsafe { mem::transmute_copy(&0xdcfa911du32) },
|
||||
unsafe { mem::transmute_copy(&0x26ebu32) },
|
||||
unsafe { mem::transmute_copy(&0x469fu32) },
|
||||
0xa2,
|
||||
0x20,
|
||||
[0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20],
|
||||
);
|
||||
|
||||
pub static EFI_MEMRESERVE_TABLE_GUID: Guid = Guid::new(
|
||||
unsafe { mem::transmute_copy(&0x888eb0c6u32) },
|
||||
unsafe { mem::transmute_copy(&0x8edeu32) },
|
||||
unsafe { mem::transmute_copy(&0x4ff5u32) },
|
||||
0xa8,
|
||||
0xf0,
|
||||
[0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2],
|
||||
);
|
||||
/// 表示内核被加载到的地址的信息。
|
||||
///
|
||||
/// 对应 `DRAGONSTUB_EFI_PAYLOAD_EFI_GUID`
|
||||
|
@ -75,6 +75,16 @@ pub fn efi_init() {
|
||||
)
|
||||
.expect("Failed to reserve memory for EFI mmap table");
|
||||
|
||||
// 保留内核的内存
|
||||
if let Some(info) = efi_manager().inner.read().dragonstub_load_info.clone() {
|
||||
mem_block_manager()
|
||||
.reserve_block(
|
||||
PhysAddr::new(info.paddr as usize),
|
||||
page_align_up(info.size as usize),
|
||||
)
|
||||
.expect("Failed to reserve kernel itself memory");
|
||||
}
|
||||
|
||||
// todo: Initialize screen info
|
||||
|
||||
kinfo!("UEFI init done!");
|
||||
@ -212,7 +222,7 @@ fn reserve_memory_regions() {
|
||||
let inner_guard = efi_manager().inner.read_irqsave();
|
||||
for md in inner_guard.mmap.iter() {
|
||||
let page_count = (PhysPageFrame::new(PhysAddr::new(page_align_up(
|
||||
(md.phys_start + md.page_count << (MMArch::PAGE_SHIFT as u64)) as usize,
|
||||
(md.phys_start + (md.page_count << (MMArch::PAGE_SHIFT as u64))) as usize,
|
||||
)))
|
||||
.ppn()
|
||||
- PhysPageFrame::new(PhysAddr::new(page_align_down(md.phys_start as usize))).ppn())
|
||||
@ -220,6 +230,7 @@ fn reserve_memory_regions() {
|
||||
let phys_start = page_align_down(md.phys_start as usize);
|
||||
let size = (page_count << (MMArch::PAGE_SHIFT as u64)) as usize;
|
||||
|
||||
// kdebug!("Reserve memory region: {:#x}-{:#x}({:#x}), is_memory: {}, is_usable_memory:{}, type: {:?}, att: {:?}", phys_start, phys_start + size, page_count, md.is_memory(), md.is_usable_memory(), md.ty, md.att);
|
||||
if md.is_memory() {
|
||||
open_firmware_fdt_driver().early_init_dt_add_memory(phys_start as u64, size as u64);
|
||||
if !md.is_usable_memory() {
|
||||
|
@ -35,6 +35,10 @@ struct InnerEFIManager {
|
||||
/// runtime services的版本号
|
||||
pub runtime_service_version: Option<uefi_raw::table::Revision>,
|
||||
pub dragonstub_load_info: Option<DragonStubPayloadEFI>,
|
||||
/// uefi 内存属性表的物理地址
|
||||
pub memory_attribute_table_paddr: Option<PhysAddr>,
|
||||
/// uefi 内存保留表的物理地址
|
||||
pub memreserve_table_paddr: Option<PhysAddr>,
|
||||
}
|
||||
|
||||
impl EFIManager {
|
||||
@ -46,6 +50,8 @@ impl EFIManager {
|
||||
runtime_paddr: None,
|
||||
runtime_service_version: None,
|
||||
dragonstub_load_info: None,
|
||||
memory_attribute_table_paddr: None,
|
||||
memreserve_table_paddr: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -54,6 +60,12 @@ impl EFIManager {
|
||||
return self.inner.read().mmap.desc_version;
|
||||
}
|
||||
|
||||
/// 内核加载的地址、大小的信息
|
||||
#[allow(dead_code)]
|
||||
pub fn kernel_load_info(&self) -> Option<DragonStubPayloadEFI> {
|
||||
return self.inner.read().dragonstub_load_info;
|
||||
}
|
||||
|
||||
/// 检查是否为有效的system table表头
|
||||
///
|
||||
/// ## 参数
|
||||
|
@ -8,14 +8,28 @@ use uefi_raw::table::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
arch::MMArch,
|
||||
driver::firmware::efi::{
|
||||
efi_manager,
|
||||
guid::{DragonStubPayloadEFI, DRAGONSTUB_EFI_PAYLOAD_EFI_GUID},
|
||||
},
|
||||
mm::{early_ioremap::EarlyIoRemap, PhysAddr},
|
||||
mm::{
|
||||
early_ioremap::EarlyIoRemap, memblock::mem_block_manager, MemoryManagementArch, PhysAddr,
|
||||
VirtAddr,
|
||||
},
|
||||
};
|
||||
|
||||
use super::EFIManager;
|
||||
use super::{
|
||||
guid::{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, EFI_MEMRESERVE_TABLE_GUID},
|
||||
EFIManager,
|
||||
};
|
||||
|
||||
/// 所有的要解析的表格的解析器
|
||||
static TABLE_PARSERS: &'static [&'static TableMatcher] = &[
|
||||
&TableMatcher::new(&MatchTableDragonStubPayloadEFI),
|
||||
&TableMatcher::new(&MatchTableMemoryAttributes),
|
||||
&TableMatcher::new(&MatchTableMemReserve),
|
||||
];
|
||||
|
||||
impl EFIManager {
|
||||
/// 显示EFI系统表头的信息
|
||||
@ -64,25 +78,81 @@ impl EFIManager {
|
||||
/// 解析EFI config table
|
||||
pub fn parse_config_tables(&self, tables: &[ConfigurationTable]) -> Result<(), SystemError> {
|
||||
for table in tables {
|
||||
if table
|
||||
.vendor_guid
|
||||
.equivalent(&DRAGONSTUB_EFI_PAYLOAD_EFI_GUID)
|
||||
{
|
||||
let table_paddr: PhysAddr = PhysAddr::new(table.vendor_table as usize);
|
||||
let vaddr = EarlyIoRemap::map_not_aligned(
|
||||
table_paddr,
|
||||
size_of::<DragonStubPayloadEFI>(),
|
||||
true,
|
||||
)?;
|
||||
let mut flag = false;
|
||||
'parser_loop: for parser in TABLE_PARSERS {
|
||||
if let Some(r) = parser.match_table(table) {
|
||||
// 有匹配结果
|
||||
if let Err(e) = r {
|
||||
kwarn!(
|
||||
"Failed to parse cfg table: '{}', err: {e:?}",
|
||||
parser.table.name()
|
||||
);
|
||||
}
|
||||
flag = true;
|
||||
break 'parser_loop;
|
||||
}
|
||||
}
|
||||
|
||||
let data = unsafe { *(vaddr.data() as *const DragonStubPayloadEFI) };
|
||||
|
||||
efi_manager().inner.write().dragonstub_load_info = Some(data);
|
||||
|
||||
EarlyIoRemap::unmap(vaddr).unwrap();
|
||||
if !flag {
|
||||
kwarn!("Cannot find parser for guid: {:?}", table.vendor_guid);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果存在mem reserve table
|
||||
if let Some(mem_reserve) = efi_manager().inner.read().memreserve_table_paddr {
|
||||
let mut prev_paddr = mem_reserve;
|
||||
while !prev_paddr.is_null() {
|
||||
let vaddr = EarlyIoRemap::map_not_aligned(prev_paddr, MMArch::PAGE_SIZE, true)
|
||||
.map_err(|e| {
|
||||
kerror!(
|
||||
"Failed to map UEFI memreserve table, paddr: {prev_paddr:?}, err: {e:?}"
|
||||
);
|
||||
|
||||
SystemError::ENOMEM
|
||||
})?;
|
||||
|
||||
let p = unsafe {
|
||||
(vaddr.data() as *const LinuxEFIMemReserveTable)
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
// reserve the entry itself
|
||||
let psize: usize = p.size.try_into().unwrap();
|
||||
mem_block_manager()
|
||||
.reserve_block(
|
||||
prev_paddr,
|
||||
size_of::<LinuxEFIMemReserveTable>()
|
||||
+ size_of::<LinuxEFIMemReserveEntry>() * psize,
|
||||
)
|
||||
.map_err(|e| {
|
||||
kerror!("Failed to reserve block, paddr: {prev_paddr:?}, err: {e:?}");
|
||||
EarlyIoRemap::unmap(vaddr).unwrap();
|
||||
e
|
||||
})?;
|
||||
|
||||
let entries = unsafe {
|
||||
core::slice::from_raw_parts(
|
||||
(vaddr.data() as *const LinuxEFIMemReserveTable).add(1)
|
||||
as *const LinuxEFIMemReserveEntry,
|
||||
p.count as usize,
|
||||
)
|
||||
};
|
||||
// reserve the entries
|
||||
for entry in entries {
|
||||
mem_block_manager()
|
||||
.reserve_block(PhysAddr::new(entry.base), entry.size)
|
||||
.map_err(|e| {
|
||||
kerror!("Failed to reserve block, paddr: {prev_paddr:?}, err: {e:?}");
|
||||
EarlyIoRemap::unmap(vaddr).unwrap();
|
||||
e
|
||||
})?;
|
||||
}
|
||||
|
||||
prev_paddr = p.next_paddr;
|
||||
EarlyIoRemap::unmap(vaddr).unwrap();
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@ -111,11 +181,10 @@ impl MemoryDescriptor {
|
||||
/// 当前内存描述符是否表示真实的内存
|
||||
#[inline]
|
||||
pub fn is_memory(&self) -> bool {
|
||||
if self.att.contains(
|
||||
MemoryAttribute::WRITE_BACK
|
||||
| MemoryAttribute::WRITE_THROUGH
|
||||
| MemoryAttribute::WRITE_COMBINE,
|
||||
) {
|
||||
if self.att.contains(MemoryAttribute::WRITE_BACK)
|
||||
|| self.att.contains(MemoryAttribute::WRITE_THROUGH)
|
||||
|| self.att.contains(MemoryAttribute::WRITE_COMBINE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -165,3 +234,177 @@ impl Default for MemoryDescriptor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait MatchTable: Send + Sync {
|
||||
/// 配置表名(仅用于日志显示)
|
||||
fn name(&self) -> &'static str;
|
||||
|
||||
/// 当前table的guid
|
||||
fn guid(&self) -> &'static uefi_raw::Guid;
|
||||
|
||||
/// 匹配阶段时,匹配器要映射vendor_table的大小。
|
||||
///
|
||||
/// 如果为0,则不映射
|
||||
fn map_size(&self) -> usize;
|
||||
|
||||
/// 当表格被映射后,调用这个函数
|
||||
///
|
||||
/// ## 锁
|
||||
///
|
||||
/// 进入该函数前,不得持有efi_manager().inner的任何锁
|
||||
fn post_process(
|
||||
&self,
|
||||
vendor_table_vaddr: Option<VirtAddr>,
|
||||
table_raw: &ConfigurationTable,
|
||||
) -> Result<(), SystemError>;
|
||||
}
|
||||
|
||||
/// `DRAGONSTUB_EFI_PAYLOAD_EFI_GUID` 的匹配器
|
||||
struct MatchTableDragonStubPayloadEFI;
|
||||
|
||||
impl MatchTable for MatchTableDragonStubPayloadEFI {
|
||||
fn name(&self) -> &'static str {
|
||||
"DragonStub Payload"
|
||||
}
|
||||
|
||||
fn guid(&self) -> &'static uefi_raw::Guid {
|
||||
&DRAGONSTUB_EFI_PAYLOAD_EFI_GUID
|
||||
}
|
||||
|
||||
fn map_size(&self) -> usize {
|
||||
core::mem::size_of::<DragonStubPayloadEFI>()
|
||||
}
|
||||
|
||||
fn post_process(
|
||||
&self,
|
||||
vendor_table_vaddr: Option<VirtAddr>,
|
||||
_table_raw: &ConfigurationTable,
|
||||
) -> Result<(), SystemError> {
|
||||
let vendor_table_vaddr = vendor_table_vaddr.unwrap();
|
||||
let data = unsafe { *(vendor_table_vaddr.data() as *const DragonStubPayloadEFI) };
|
||||
|
||||
efi_manager().inner.write().dragonstub_load_info = Some(data);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
struct MatchTableMemoryAttributes;
|
||||
|
||||
impl MatchTable for MatchTableMemoryAttributes {
|
||||
fn name(&self) -> &'static str {
|
||||
"MemAttr"
|
||||
}
|
||||
|
||||
fn guid(&self) -> &'static uefi_raw::Guid {
|
||||
&EFI_MEMORY_ATTRIBUTES_TABLE_GUID
|
||||
}
|
||||
|
||||
fn map_size(&self) -> usize {
|
||||
// 不映射
|
||||
0
|
||||
}
|
||||
|
||||
fn post_process(
|
||||
&self,
|
||||
_vendor_table_vaddr: Option<VirtAddr>,
|
||||
table_raw: &ConfigurationTable,
|
||||
) -> Result<(), SystemError> {
|
||||
efi_manager()
|
||||
.inner
|
||||
.write_irqsave()
|
||||
.memory_attribute_table_paddr = Some(PhysAddr::new(table_raw.vendor_table as usize));
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
struct MatchTableMemReserve;
|
||||
|
||||
impl MatchTable for MatchTableMemReserve {
|
||||
fn name(&self) -> &'static str {
|
||||
"MemReserve"
|
||||
}
|
||||
|
||||
fn guid(&self) -> &'static uefi_raw::Guid {
|
||||
&EFI_MEMRESERVE_TABLE_GUID
|
||||
}
|
||||
|
||||
fn map_size(&self) -> usize {
|
||||
// 不映射
|
||||
0
|
||||
}
|
||||
|
||||
fn post_process(
|
||||
&self,
|
||||
_vendor_table_vaddr: Option<VirtAddr>,
|
||||
table_raw: &ConfigurationTable,
|
||||
) -> Result<(), SystemError> {
|
||||
efi_manager().inner.write_irqsave().memreserve_table_paddr =
|
||||
Some(PhysAddr::new(table_raw.vendor_table as usize));
|
||||
kdebug!(
|
||||
"memreserve_table_paddr: {:#x}",
|
||||
table_raw.vendor_table as usize
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
/// 用于匹配配置表的匹配器
|
||||
struct TableMatcher {
|
||||
table: &'static dyn MatchTable,
|
||||
}
|
||||
|
||||
impl TableMatcher {
|
||||
const fn new(table: &'static dyn MatchTable) -> Self {
|
||||
Self { table }
|
||||
}
|
||||
|
||||
/// 判断配置表与当前匹配器是否匹配
|
||||
#[inline(never)]
|
||||
fn match_table(&self, table: &ConfigurationTable) -> Option<Result<(), SystemError>> {
|
||||
if table.vendor_guid.equivalent(self.table.guid()) == false {
|
||||
return None;
|
||||
}
|
||||
|
||||
let table_map_size = self.table.map_size();
|
||||
let vendor_table_vaddr: Option<VirtAddr>;
|
||||
if table_map_size > 0 {
|
||||
let table_paddr: PhysAddr = PhysAddr::new(table.vendor_table as usize);
|
||||
let vaddr = EarlyIoRemap::map_not_aligned(table_paddr, table_map_size, true);
|
||||
|
||||
if let Err(e) = vaddr {
|
||||
return Some(Err(e));
|
||||
}
|
||||
|
||||
vendor_table_vaddr = Some(vaddr.unwrap());
|
||||
} else {
|
||||
vendor_table_vaddr = None;
|
||||
}
|
||||
|
||||
let r = self.table.post_process(vendor_table_vaddr, table);
|
||||
|
||||
if let Some(vaddr) = vendor_table_vaddr {
|
||||
EarlyIoRemap::unmap(vaddr).unwrap();
|
||||
}
|
||||
return Some(r);
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
struct LinuxEFIMemReserveTable {
|
||||
/// allocated size of the array
|
||||
size: i32,
|
||||
/// number of entries used
|
||||
count: i32,
|
||||
/// pa of next struct instance
|
||||
next_paddr: PhysAddr,
|
||||
entry: [LinuxEFIMemReserveEntry; 0],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
struct LinuxEFIMemReserveEntry {
|
||||
base: usize,
|
||||
size: usize,
|
||||
}
|
||||
|
@ -1,10 +1,16 @@
|
||||
use core::mem::size_of;
|
||||
|
||||
use fdt::{
|
||||
node::{FdtNode, NodeProperty},
|
||||
Fdt,
|
||||
};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{init::boot_params, libs::rwlock::RwLock};
|
||||
use crate::{
|
||||
init::boot_params,
|
||||
libs::rwlock::RwLock,
|
||||
mm::{memblock::mem_block_manager, PhysAddr},
|
||||
};
|
||||
|
||||
#[inline(always)]
|
||||
pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver {
|
||||
@ -72,13 +78,13 @@ impl OpenFirmwareFdtDriver {
|
||||
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);
|
||||
// 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);
|
||||
// kdebug!("fdt_root_addr_cells={}", guard.root_addr_cells);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
@ -151,41 +157,10 @@ impl OpenFirmwareFdtDriver {
|
||||
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;
|
||||
let base_index = i * (addr_cells + size_cells);
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
let (base, base_index) = read_cell(reg.value, base_index, addr_cells);
|
||||
let (size, _) = read_cell(reg.value, base_index, size_cells);
|
||||
|
||||
if size == 0 {
|
||||
continue;
|
||||
@ -258,20 +233,21 @@ impl OpenFirmwareFdtDriver {
|
||||
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
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
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() {
|
||||
@ -287,4 +263,189 @@ impl OpenFirmwareFdtDriver {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// 在UEFI初始化后,扫描FDT中的`/reserved-memory`节点,设置保留的内存
|
||||
///
|
||||
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/of/fdt.c#634
|
||||
pub fn early_init_fdt_scan_reserved_mem(&self) {
|
||||
let vaddr = boot_params().read().fdt();
|
||||
if vaddr.is_none() {
|
||||
return;
|
||||
}
|
||||
let vaddr = vaddr.unwrap();
|
||||
let fdt = unsafe { Fdt::from_ptr(vaddr.data() as *const u8) };
|
||||
if fdt.is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
let fdt = fdt.unwrap();
|
||||
self.early_reserve_fdt_itself(&fdt);
|
||||
|
||||
let reserved_mem_nodes = fdt.memory_reservations();
|
||||
|
||||
for node in reserved_mem_nodes {
|
||||
if node.size() != 0 {
|
||||
let address = PhysAddr::new(node.address() as usize);
|
||||
let size = node.size();
|
||||
kdebug!("Reserve memory: {:?}-{:?}", address, address + size);
|
||||
mem_block_manager().reserve_block(address, size).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
self.fdt_scan_reserved_mem(&fdt)
|
||||
.expect("Failed to scan reserved memory");
|
||||
}
|
||||
|
||||
/// 保留fdt自身的内存空间
|
||||
|
||||
fn early_reserve_fdt_itself(&self, fdt: &Fdt) {
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
{
|
||||
use crate::libs::align::{page_align_down, page_align_up};
|
||||
|
||||
let fdt_paddr = boot_params().read().arch.fdt_paddr;
|
||||
let rsvd_start = PhysAddr::new(page_align_down(fdt_paddr.data()));
|
||||
let rsvd_size = page_align_up(fdt_paddr.data() - rsvd_start.data() + fdt.total_size());
|
||||
mem_block_manager()
|
||||
.reserve_block(rsvd_start, rsvd_size)
|
||||
.expect("Failed to reserve memory for fdt");
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
let _ = fdt;
|
||||
}
|
||||
}
|
||||
|
||||
fn fdt_scan_reserved_mem(&self, fdt: &Fdt) -> Result<(), SystemError> {
|
||||
let node = fdt
|
||||
.find_node("/reserved-memory")
|
||||
.ok_or(SystemError::ENODEV)?;
|
||||
|
||||
for child in node.children() {
|
||||
if !self.is_device_avaliable(&child) {
|
||||
continue;
|
||||
}
|
||||
|
||||
reserved_mem_reserve_reg(&child).ok();
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn early_init_dt_reserve_memory(
|
||||
&self,
|
||||
base: PhysAddr,
|
||||
size: usize,
|
||||
nomap: bool,
|
||||
) -> Result<(), SystemError> {
|
||||
if nomap {
|
||||
if mem_block_manager().is_overlapped(base, size)
|
||||
&& mem_block_manager().is_overlapped_with_reserved(base, size)
|
||||
{
|
||||
// 如果内存已经被其他区域预留(即已经被映射),我们不应该允许它被标记为`nomap`,
|
||||
// 但是不需要担心如果该区域不是内存(即不会被映射)的情况。
|
||||
return Err(SystemError::EBUSY);
|
||||
}
|
||||
|
||||
return mem_block_manager().mark_nomap(base, size);
|
||||
}
|
||||
|
||||
return mem_block_manager().reserve_block(base, size);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn reserved_mem_reserve_reg(node: &FdtNode<'_, '_>) -> Result<(), SystemError> {
|
||||
let global_data_guard: crate::libs::rwlock::RwLockReadGuard<'_, FdtGlobalData> =
|
||||
FDT_GLOBAL_DATA.read();
|
||||
let t_len = ((global_data_guard.root_addr_cells + global_data_guard.root_size_cells) as usize)
|
||||
* size_of::<u32>();
|
||||
drop(global_data_guard);
|
||||
|
||||
let reg = node.property("reg").ok_or(SystemError::ENOENT)?;
|
||||
|
||||
let mut reg_size = reg.value.len();
|
||||
if reg_size > 0 && reg_size % t_len != 0 {
|
||||
kerror!(
|
||||
"Reserved memory: invalid reg property in '{}', skipping node.",
|
||||
node.name
|
||||
);
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
// 每个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 nomap = node.property("no-map").is_some();
|
||||
|
||||
let mut base_index = 0;
|
||||
|
||||
while reg_size >= t_len {
|
||||
let (base, bi) = read_cell(reg.value, base_index, addr_cells);
|
||||
base_index = bi;
|
||||
let (size, bi) = read_cell(reg.value, base_index, size_cells);
|
||||
base_index = bi;
|
||||
|
||||
if size > 0
|
||||
&& open_firmware_fdt_driver()
|
||||
.early_init_dt_reserve_memory(PhysAddr::new(base as usize), size as usize, nomap)
|
||||
.is_ok()
|
||||
{
|
||||
kdebug!(
|
||||
"Reserved memory: base={:#x}, size={:#x}, nomap={}",
|
||||
base,
|
||||
size,
|
||||
nomap
|
||||
);
|
||||
} else {
|
||||
kerror!(
|
||||
"Failed to reserve memory: base={:#x}, size={:#x}, nomap={}",
|
||||
base,
|
||||
size,
|
||||
nomap
|
||||
);
|
||||
}
|
||||
|
||||
reg_size -= t_len;
|
||||
|
||||
// todo: linux这里保存了节点,但是我感觉现在还用不着。
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 从FDT的`reg`属性中读取指定数量的cell,作为一个小端u64返回
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `reg_value`:`reg`属性数组的引用
|
||||
/// - `base_index`:起始索引
|
||||
/// - `cells`:要读取的cell数量,必须是1或2
|
||||
///
|
||||
/// ## 返回值
|
||||
///
|
||||
/// (value, next_base_index)
|
||||
fn read_cell(reg_value: &[u8], base_index: usize, cells: usize) -> (u64, usize) {
|
||||
let next_base_index = base_index + cells * 4;
|
||||
match cells {
|
||||
1 => {
|
||||
return (
|
||||
u32::from_be_bytes(reg_value[base_index..base_index + 4].try_into().unwrap())
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
next_base_index,
|
||||
);
|
||||
}
|
||||
|
||||
2 => {
|
||||
return (
|
||||
u64::from_be_bytes(reg_value[base_index..base_index + 8].try_into().unwrap()),
|
||||
next_base_index,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
panic!("cells must be 1 or 2");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
|
||||
use super::log::{LogLevel, LogMessage};
|
||||
|
||||
use crate::libs::spinlock::SpinLock;
|
||||
@ -16,8 +18,13 @@ pub static mut KMSG: Option<SpinLock<Kmsg>> = None;
|
||||
|
||||
/// 初始化KMSG
|
||||
pub fn kmsg_init() {
|
||||
kinfo!("kmsg_init");
|
||||
let kmsg = SpinLock::new(Kmsg::new());
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
unsafe { KMSG = Some(kmsg) };
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
kinfo!("kmsg_init done");
|
||||
}
|
||||
|
||||
/// 日志
|
||||
|
@ -7,7 +7,7 @@ use crate::{
|
||||
video::{fbdev::base::BootTimeScreenInfo, VideoRefreshManager},
|
||||
},
|
||||
libs::{lib_ui::screen_manager::scm_init, rwlock::RwLock},
|
||||
mm::VirtAddr,
|
||||
mm::{PhysAddr, VirtAddr},
|
||||
};
|
||||
|
||||
mod c_adapter;
|
||||
@ -102,7 +102,7 @@ impl BootParams {
|
||||
self.boot_command_line[pos + len] = 0;
|
||||
}
|
||||
|
||||
/// 获取FDT的物理地址
|
||||
/// 获取FDT的虚拟地址
|
||||
#[allow(dead_code)]
|
||||
pub fn fdt(&self) -> Option<VirtAddr> {
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
@ -111,4 +111,14 @@ impl BootParams {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
return None;
|
||||
}
|
||||
|
||||
/// 获取FDT的物理地址
|
||||
#[allow(dead_code)]
|
||||
pub fn fdt_paddr(&self) -> Option<PhysAddr> {
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
return Some(self.arch.fdt_paddr);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
@ -116,9 +116,10 @@ pub struct Logger;
|
||||
|
||||
impl Logger {
|
||||
pub fn log(&self, log_level: usize, message: fmt::Arguments) {
|
||||
if unsafe { !KMSG.is_none() } {
|
||||
if unsafe { KMSG.is_some() } {
|
||||
let timestamp: TimeSpec = TimeSpec::now();
|
||||
let log_level = LogLevel::from(log_level.clone());
|
||||
|
||||
let log_message = LogMessage::new(timestamp, log_level, message.to_string());
|
||||
|
||||
unsafe { KMSG.as_ref().unwrap().lock_irqsave().push(log_message) };
|
||||
|
@ -110,13 +110,16 @@ impl<A: MemoryManagementArch> BuddyAllocator<A> {
|
||||
|
||||
let remain_areas = &res_areas[0..];
|
||||
|
||||
kdebug!("Remain areas: {:?}", &remain_areas[0..10]);
|
||||
kdebug!("offset_in_remain_area: {:?}", offset_in_remain_area);
|
||||
|
||||
for area in remain_areas {
|
||||
let mut paddr = (area.area_base_aligned() + offset_in_remain_area).data();
|
||||
let mut remain_pages =
|
||||
PageFrameCount::from_bytes(area.area_end_aligned().data() - paddr).unwrap();
|
||||
|
||||
if remain_pages.data() == 0 {
|
||||
continue;
|
||||
}
|
||||
kdebug!("area: {area:?}, paddr: {paddr:#x}, remain_pages: {remain_pages:?}");
|
||||
|
||||
total_pages_to_buddy += remain_pages;
|
||||
|
||||
if offset_in_remain_area != 0 {
|
||||
|
@ -3,7 +3,14 @@
|
||||
/// @FilePath: /DragonOS/kernel/src/mm/allocator/bump.rs
|
||||
/// @Description: bump allocator线性分配器
|
||||
use super::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage};
|
||||
use crate::mm::{memblock::mem_block_manager, MemoryManagementArch, PhysAddr, PhysMemoryArea};
|
||||
use crate::mm::{
|
||||
allocator::page_frame::{PhysPageFrame, PhysPageFrameIter},
|
||||
init::{mm_init_status, MMInitStatus},
|
||||
memblock::mem_block_manager,
|
||||
no_init::pseudo_map_phys,
|
||||
page::PageMapper,
|
||||
MemoryManagementArch, PageTableKind, PhysAddr, PhysMemoryArea,
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// 线性分配器
|
||||
@ -41,44 +48,47 @@ impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
|
||||
pub fn remain_areas(&self, result_area: &mut [PhysMemoryArea]) -> Option<usize> {
|
||||
let mut offset = self.offset();
|
||||
|
||||
let iter = mem_block_manager().to_iter_available();
|
||||
|
||||
let mut ret_offset_aligned = 0;
|
||||
|
||||
let mut res_cnt = 0;
|
||||
|
||||
let total_num = mem_block_manager().total_initial_memory_regions();
|
||||
let mut found_start = false;
|
||||
// 遍历所有的物理内存区域
|
||||
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();
|
||||
// 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整
|
||||
// let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
|
||||
let area_end = area.area_end_aligned().data();
|
||||
for area in iter {
|
||||
if found_start == false {
|
||||
// 将area的base地址与PAGE_SIZE对齐,对齐时向上取整
|
||||
// let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
|
||||
let area_base = area.area_base_aligned().data();
|
||||
// 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整
|
||||
// let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
|
||||
let area_end = area.area_end_aligned().data();
|
||||
|
||||
// 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域
|
||||
if offset >= area_end {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base
|
||||
if offset < area_base {
|
||||
offset = area_base;
|
||||
} else if offset < area_end {
|
||||
// 将offset对齐到PAGE_SIZE
|
||||
offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1);
|
||||
}
|
||||
// found
|
||||
if offset + 1 * MMA::PAGE_SIZE <= area_end {
|
||||
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;
|
||||
}
|
||||
// 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域
|
||||
if offset >= area_end {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base
|
||||
if offset < area_base {
|
||||
offset = area_base;
|
||||
} else if offset < area_end {
|
||||
// 将offset对齐到PAGE_SIZE
|
||||
offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1);
|
||||
}
|
||||
// found
|
||||
if offset + 1 * MMA::PAGE_SIZE <= area_end {
|
||||
ret_offset_aligned = offset - area.area_base_aligned().data();
|
||||
found_start = true;
|
||||
}
|
||||
}
|
||||
|
||||
if found_start {
|
||||
if area.area_base_aligned() < area.area_end_aligned() {
|
||||
result_area[res_cnt] = area;
|
||||
res_cnt += 1;
|
||||
}
|
||||
ret_offset_aligned = offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,6 +99,28 @@ impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
|
||||
return Some(ret_offset_aligned);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
unsafe fn ensure_early_mapping(&self, start_paddr: PhysAddr, count: PageFrameCount) {
|
||||
// 确保在内存管理未被初始化时,这地址已经被映射了
|
||||
if mm_init_status() != MMInitStatus::Initialized {
|
||||
// 映射涉及的页
|
||||
|
||||
let iter = PhysPageFrameIter::new(
|
||||
PhysPageFrame::new(start_paddr),
|
||||
PhysPageFrame::new(start_paddr + count.bytes()),
|
||||
);
|
||||
let mapper =
|
||||
PageMapper::<MMA, _>::current(PageTableKind::Kernel, BumpAllocator::<MMA>::new(0));
|
||||
|
||||
for p in iter {
|
||||
if let None = mapper.translate(MMA::phys_2_virt(p.phys_address()).unwrap()) {
|
||||
let vaddr = MMA::phys_2_virt(p.phys_address()).unwrap();
|
||||
pseudo_map_phys(vaddr, p.phys_address(), PageFrameCount::new(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
|
||||
@ -99,7 +131,7 @@ impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
|
||||
unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
|
||||
let mut offset = self.offset();
|
||||
|
||||
let iter = mem_block_manager().to_iter();
|
||||
let iter = mem_block_manager().to_iter_available();
|
||||
|
||||
// 遍历所有的物理内存区域
|
||||
for area in iter {
|
||||
@ -128,7 +160,9 @@ impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
|
||||
// 将offset增加至分配后的内存
|
||||
self.offset = offset + count.data() * MMA::PAGE_SIZE;
|
||||
|
||||
return Some((PhysAddr(res_page_phys), count));
|
||||
let r = (PhysAddr(res_page_phys), count);
|
||||
self.ensure_early_mapping(r.0, r.1);
|
||||
return Some(r);
|
||||
}
|
||||
}
|
||||
return None;
|
||||
@ -144,7 +178,7 @@ impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
|
||||
unsafe fn usage(&self) -> PageFrameUsage {
|
||||
let mut total = 0;
|
||||
let mut used = 0;
|
||||
let iter = mem_block_manager().to_iter();
|
||||
let iter = mem_block_manager().to_iter_available();
|
||||
for area in iter {
|
||||
// 将area的base地址与PAGE_SIZE对齐,对其时向上取整
|
||||
let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
|
||||
|
@ -56,7 +56,7 @@ impl KernelAllocator {
|
||||
}
|
||||
}
|
||||
|
||||
/// 为内核SLAB分配器实现LocalAlloc的trait
|
||||
/// 为内核分配器实现LocalAlloc的trait
|
||||
impl LocalAlloc for KernelAllocator {
|
||||
unsafe fn local_alloc(&self, layout: Layout) -> *mut u8 {
|
||||
return self
|
||||
@ -84,7 +84,7 @@ impl LocalAlloc for KernelAllocator {
|
||||
/// 为内核slab分配器实现GlobalAlloc特性
|
||||
unsafe impl GlobalAlloc for KernelAllocator {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
let r = self.local_alloc(layout);
|
||||
let r = self.local_alloc_zeroed(layout);
|
||||
mm_debug_log(
|
||||
klog_types::AllocatorLogType::Alloc(AllocLogItem::new(
|
||||
layout.clone(),
|
||||
|
@ -78,7 +78,8 @@ impl Iterator for PhysPageFrameIter {
|
||||
if unlikely(self.current == self.end) {
|
||||
return None;
|
||||
}
|
||||
let current = self.current.next();
|
||||
let current: PhysPageFrame = self.current;
|
||||
self.current = self.current.next_by(1);
|
||||
return Some(current);
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,9 @@ use crate::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, mmio_buddy::mmio_pool,
|
||||
no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
|
||||
allocator::page_frame::PageFrameCount, init::mm_init, kernel_mapper::KernelMapper,
|
||||
mmio_buddy::mmio_pool, no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch,
|
||||
PhysAddr, VirtAddr,
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
@ -165,3 +166,8 @@ pub unsafe extern "C" fn rs_mmio_release(vaddr: u64, length: u64) -> i32 {
|
||||
.release_mmio(VirtAddr::new(vaddr as usize), length as usize)
|
||||
.unwrap_or_else(|err| err.to_posix_errno());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rs_mm_init() {
|
||||
mm_init();
|
||||
}
|
||||
|
@ -179,7 +179,6 @@ impl EarlyIoRemap {
|
||||
let count = PageFrameCount::from_bytes(slot_guard[idx].size as usize).unwrap();
|
||||
|
||||
// 取消映射
|
||||
|
||||
unsafe { pseudo_unmap_phys(vaddr, count) };
|
||||
|
||||
for i in 0..count.data() {
|
||||
|
61
kernel/src/mm/init.rs
Normal file
61
kernel/src/mm/init.rs
Normal file
@ -0,0 +1,61 @@
|
||||
use core::{fmt::Write, sync::atomic::Ordering};
|
||||
|
||||
use crate::{
|
||||
arch::MMArch, driver::tty::serial::serial8250::send_to_default_serial8250_port,
|
||||
filesystem::procfs::kmsg::kmsg_init, libs::printk::PrintkWriter, mm::mmio_buddy::mmio_init,
|
||||
};
|
||||
|
||||
use super::MemoryManagementArch;
|
||||
|
||||
#[atomic_enum]
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum MMInitStatus {
|
||||
NotInit,
|
||||
Initializing,
|
||||
Initialized,
|
||||
}
|
||||
/// 内存管理的初始化状态
|
||||
static MM_INIT: AtomicMMInitStatus = AtomicMMInitStatus::new(MMInitStatus::NotInit);
|
||||
|
||||
pub unsafe fn mm_init() {
|
||||
send_to_default_serial8250_port("mm_init\n\0".as_bytes());
|
||||
PrintkWriter
|
||||
.write_fmt(format_args!("mm_init() called\n"))
|
||||
.unwrap();
|
||||
// printk_color!(GREEN, BLACK, "mm_init() called\n");
|
||||
|
||||
if MM_INIT
|
||||
.compare_exchange(
|
||||
MMInitStatus::NotInit,
|
||||
MMInitStatus::Initializing,
|
||||
Ordering::SeqCst,
|
||||
Ordering::SeqCst,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
send_to_default_serial8250_port("mm_init err\n\0".as_bytes());
|
||||
panic!("mm_init() can only be called once");
|
||||
}
|
||||
|
||||
MMArch::init();
|
||||
|
||||
// enable mmio
|
||||
mmio_init();
|
||||
// enable KMSG
|
||||
kmsg_init();
|
||||
|
||||
MM_INIT
|
||||
.compare_exchange(
|
||||
MMInitStatus::Initializing,
|
||||
MMInitStatus::Initialized,
|
||||
Ordering::SeqCst,
|
||||
Ordering::SeqCst,
|
||||
)
|
||||
.unwrap();
|
||||
kinfo!("mm init done.");
|
||||
}
|
||||
|
||||
/// 获取内存管理的初始化状态
|
||||
pub fn mm_init_status() -> MMInitStatus {
|
||||
MM_INIT.load(Ordering::SeqCst)
|
||||
}
|
@ -2,7 +2,10 @@ use core::intrinsics::unlikely;
|
||||
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
|
||||
use crate::libs::{
|
||||
align::{page_align_down, page_align_up},
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
};
|
||||
|
||||
use super::{PhysAddr, PhysMemoryArea};
|
||||
|
||||
@ -50,7 +53,8 @@ impl MemBlockManager {
|
||||
/// 如果添加的区域与已有区域有重叠,会将重叠的区域合并
|
||||
#[allow(dead_code)]
|
||||
pub fn add_block(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> {
|
||||
return self.add_range(base, size, MemoryAreaAttr::empty());
|
||||
let r = self.add_range(base, size, MemoryAreaAttr::empty());
|
||||
return r;
|
||||
}
|
||||
|
||||
/// 添加内存区域
|
||||
@ -350,11 +354,15 @@ impl MemBlockManager {
|
||||
|
||||
fn set_or_clear_flags(
|
||||
&self,
|
||||
base: PhysAddr,
|
||||
size: usize,
|
||||
mut base: PhysAddr,
|
||||
mut size: usize,
|
||||
set: bool,
|
||||
flags: MemoryAreaAttr,
|
||||
) -> Result<(), SystemError> {
|
||||
let rsvd_base = PhysAddr::new(page_align_down(base.data()));
|
||||
size = page_align_up((size as usize) + base.data() - rsvd_base.data());
|
||||
base = rsvd_base;
|
||||
|
||||
let mut inner = self.inner.lock();
|
||||
let (start_index, end_index) = self.isolate_range(&mut inner, base, size)?;
|
||||
for i in start_index..end_index {
|
||||
@ -375,10 +383,68 @@ impl MemBlockManager {
|
||||
return self.set_or_clear_flags(base, size, true, MemoryAreaAttr::RESERVED);
|
||||
}
|
||||
|
||||
/// 判断[base, base+size)与已有区域是否有重叠
|
||||
pub fn is_overlapped(&self, base: PhysAddr, size: usize) -> bool {
|
||||
let inner = self.inner.lock();
|
||||
return self.do_is_overlapped(base, size, false, &inner);
|
||||
}
|
||||
|
||||
/// 判断[base, base+size)与已有Reserved区域是否有重叠
|
||||
pub fn is_overlapped_with_reserved(&self, base: PhysAddr, size: usize) -> bool {
|
||||
let inner = self.inner.lock();
|
||||
return self.do_is_overlapped(base, size, true, &inner);
|
||||
}
|
||||
|
||||
fn do_is_overlapped(
|
||||
&self,
|
||||
base: PhysAddr,
|
||||
size: usize,
|
||||
require_reserved: bool,
|
||||
inner: &SpinLockGuard<'_, InnerMemBlockManager>,
|
||||
) -> bool {
|
||||
let mut res = false;
|
||||
for i in 0..inner.initial_memory_regions_num {
|
||||
if require_reserved
|
||||
&& !inner.initial_memory_regions[i]
|
||||
.flags
|
||||
.contains(MemoryAreaAttr::RESERVED)
|
||||
{
|
||||
// 忽略非保留区域
|
||||
continue;
|
||||
}
|
||||
|
||||
let range_base = inner.initial_memory_regions[i].base;
|
||||
let range_end = range_base + inner.initial_memory_regions[i].size;
|
||||
if (base >= range_base && base < range_end)
|
||||
|| (base + size > range_base && base + size <= range_end)
|
||||
|| (base <= range_base && base + size >= range_end)
|
||||
{
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// 生成迭代器
|
||||
pub fn to_iter(&self) -> MemBlockIter {
|
||||
let inner = self.inner.lock();
|
||||
return MemBlockIter { inner, index: 0 };
|
||||
return MemBlockIter {
|
||||
inner,
|
||||
index: 0,
|
||||
usable_only: false,
|
||||
};
|
||||
}
|
||||
|
||||
/// 生成迭代器,迭代所有可用的物理内存区域
|
||||
pub fn to_iter_available(&self) -> MemBlockIter {
|
||||
let inner = self.inner.lock();
|
||||
return MemBlockIter {
|
||||
inner,
|
||||
index: 0,
|
||||
usable_only: true,
|
||||
};
|
||||
}
|
||||
|
||||
/// 获取初始内存区域数量
|
||||
@ -397,6 +463,7 @@ impl MemBlockManager {
|
||||
pub struct MemBlockIter<'a> {
|
||||
inner: SpinLockGuard<'a, InnerMemBlockManager>,
|
||||
index: usize,
|
||||
usable_only: bool,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -421,6 +488,22 @@ impl<'a> Iterator for MemBlockIter<'a> {
|
||||
type Item = PhysMemoryArea;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while self.index < self.inner.initial_memory_regions_num {
|
||||
if self.usable_only {
|
||||
if self.inner.initial_memory_regions[self.index]
|
||||
.flags
|
||||
.is_empty()
|
||||
== false
|
||||
{
|
||||
self.index += 1;
|
||||
if self.index >= self.inner.initial_memory_regions_num {
|
||||
return None;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if self.index >= self.inner.initial_memory_regions_num {
|
||||
return None;
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ pub struct MmioBuddyMemPool {
|
||||
}
|
||||
|
||||
impl MmioBuddyMemPool {
|
||||
#[inline(never)]
|
||||
fn new() -> Self {
|
||||
let mut free_regions: [MaybeUninit<SpinLock<MmioFreeRegionList>>;
|
||||
MMIO_BUDDY_REGION_COUNT as usize] = unsafe { MaybeUninit::uninit().assume_init() };
|
||||
|
@ -22,6 +22,7 @@ use self::{
|
||||
pub mod allocator;
|
||||
pub mod c_adapter;
|
||||
pub mod early_ioremap;
|
||||
pub mod init;
|
||||
pub mod kernel_mapper;
|
||||
pub mod memblock;
|
||||
pub mod mmio_buddy;
|
||||
@ -407,6 +408,11 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
|
||||
/// 虚拟地址与物理地址的偏移量
|
||||
const PHYS_OFFSET: usize;
|
||||
|
||||
/// 内核在链接时被链接到的偏移量
|
||||
const KERNEL_LINK_OFFSET: usize;
|
||||
|
||||
const KERNEL_VIRT_START: usize = Self::PHYS_OFFSET + Self::KERNEL_LINK_OFFSET;
|
||||
|
||||
/// 每个页面的大小
|
||||
const PAGE_SIZE: usize = 1 << Self::PAGE_SHIFT;
|
||||
/// 通过这个mask,获取地址的页内偏移量
|
||||
|
@ -141,7 +141,7 @@ impl<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> {
|
||||
/// 并且,内核引导文件必须以4K页为粒度,填写了前100M的内存映射关系。(具体以本文件开头的注释为准)
|
||||
#[inline(never)]
|
||||
pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) {
|
||||
let flags: PageFlags<MMArch> = PageFlags::new().set_write(true).set_execute(true);
|
||||
let flags: PageFlags<MMArch> = PageFlags::new().set_write(true);
|
||||
|
||||
pseudo_map_phys_with_flags(vaddr, paddr, count, flags);
|
||||
}
|
||||
@ -192,7 +192,6 @@ pub unsafe fn pseudo_map_phys_with_flags(
|
||||
#[inline(never)]
|
||||
pub unsafe fn pseudo_unmap_phys(vaddr: VirtAddr, count: PageFrameCount) {
|
||||
assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
|
||||
assert!(count.data() == 1);
|
||||
|
||||
let mut pseudo_allocator = PseudoAllocator::<MMArch>::new();
|
||||
|
||||
|
@ -213,7 +213,7 @@ impl<Arch: MemoryManagementArch> PageEntry<Arch> {
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
{
|
||||
let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 44) - 1);
|
||||
let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 54) - 1);
|
||||
super::allocator::page_frame::PhysPageFrame::from_ppn(ppn).phys_address()
|
||||
}
|
||||
};
|
||||
|
@ -76,7 +76,7 @@ impl TimeSpec {
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
{
|
||||
unimplemented!("TimeSpec::now()")
|
||||
return TimeSpec::new(0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user