初始化riscv的内存管理模块,并且设置保留内存 (#506)

This commit is contained in:
LoGin 2024-02-04 14:35:18 +08:00 committed by GitHub
parent a02ce654cf
commit 453452cc02
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 1018 additions and 186 deletions

View File

@ -7,7 +7,7 @@ use crate::{
driver::{firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver}, driver::{firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver},
init::{boot_params, init_before_mem_init}, init::{boot_params, init_before_mem_init},
kdebug, kinfo, kdebug, kinfo,
mm::{PhysAddr, VirtAddr}, mm::{init::mm_init, memblock::mem_block_manager, PhysAddr, VirtAddr},
print, println, print, println,
}; };
@ -49,12 +49,19 @@ unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
mm_early_init(); mm_early_init();
let fdt = fdt::Fdt::from_ptr(fdt_paddr.data() as *const u8).expect("Failed to parse fdt!"); 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(); parse_dtb();
for x in mem_block_manager().to_iter() {
kdebug!("before efi: {x:?}");
}
efi_init(); efi_init();
open_firmware_fdt_driver().early_init_fdt_scan_reserved_mem();
mm_init();
loop {} loop {}
unreachable() unreachable()
} }

View File

@ -1,13 +1,34 @@
use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
use system_error::SystemError;
use crate::{ use crate::{
arch::mm::{KERNEL_BEGIN_PA, KERNEL_BEGIN_VA, KERNEL_END_PA, KERNEL_END_VA}, arch::{
kdebug, mm::{
mm::{PhysAddr, VirtAddr}, 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)] #[inline(never)]
pub fn mm_early_init() { pub fn mm_early_init() {
unsafe { init_kernel_addr() }; unsafe { init_kernel_addr() };
// unsafe { map_initial_page_table_linearly() };
} }
unsafe fn init_kernel_addr() { 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();
}
}
}
}

View File

@ -1,12 +1,21 @@
use riscv::register::satp; use riscv::register::satp;
use system_error::SystemError; use system_error::SystemError;
use crate::mm::{ use crate::{
allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame}, arch::MMArch,
page::PageFlags, libs::spinlock::SpinLock,
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, 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 mod bump;
pub(super) mod init; 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 mut KERNEL_END_VA: VirtAddr = VirtAddr::new(0);
pub(self) static INNER_ALLOCATOR: SpinLock<Option<BuddyAllocator<MMArch>>> = SpinLock::new(None);
/// RiscV64的内存管理架构结构体(sv39) /// RiscV64的内存管理架构结构体(sv39)
#[derive(Debug, Clone, Copy, Hash)] #[derive(Debug, Clone, Copy, Hash)]
pub struct RiscV64MMArch; pub struct RiscV64MMArch;
@ -65,6 +76,7 @@ impl MemoryManagementArch for RiscV64MMArch {
const ENTRY_FLAG_DIRTY: usize = (1 << 7); const ENTRY_FLAG_DIRTY: usize = (1 << 7);
const PHYS_OFFSET: usize = 0xffff_ffc0_0000_0000; 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); const USER_END_VADDR: crate::mm::VirtAddr = VirtAddr::new(0x0000_003f_ffff_ffff);
@ -77,8 +89,9 @@ impl MemoryManagementArch for RiscV64MMArch {
/// 设置1MB的fixmap空间 /// 设置1MB的fixmap空间
const FIXMAP_SIZE: usize = 256 * 4096; const FIXMAP_SIZE: usize = 256 * 4096;
#[inline(never)]
unsafe fn init() { unsafe fn init() {
todo!() riscv_mm_init().expect("init kernel memory management architecture failed");
} }
unsafe fn invalidate_page(address: VirtAddr) { unsafe fn invalidate_page(address: VirtAddr) {
@ -147,7 +160,7 @@ impl MemoryManagementArch for RiscV64MMArch {
fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize { fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize {
let ppn = PhysPageFrame::new(paddr).ppn(); 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; return r;
} }
} }
@ -164,8 +177,10 @@ impl VirtAddr {
} }
/// 获取内核地址默认的页面标志 /// 获取内核地址默认的页面标志
pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(virt: VirtAddr) -> PageFlags<A> { pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> {
unimplemented!("riscv64::kernel_page_flags") 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 { impl FrameAllocator for LockedFrameAllocator {
unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { 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) { unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) {
assert!(count.data().is_power_of_two()); 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 { 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");
}
} }
} }

View File

@ -3,6 +3,6 @@ pub struct RiscV64TimeArch;
impl TimeArch for RiscV64TimeArch { impl TimeArch for RiscV64TimeArch {
fn get_cycles() -> usize { fn get_cycles() -> usize {
unimplemented!("Riscv64TimeArch::get_cycles") riscv::register::cycle::read()
} }
} }

View File

@ -8,19 +8,16 @@ use x86::time::rdtsc;
use x86_64::registers::model_specific::EferFlags; use x86_64::registers::model_specific::EferFlags;
use crate::driver::tty::serial::serial8250::send_to_default_serial8250_port; use crate::driver::tty::serial::serial8250::send_to_default_serial8250_port;
use crate::filesystem::procfs::kmsg::kmsg_init;
use crate::include::bindings::bindings::{ use crate::include::bindings::bindings::{
multiboot2_get_load_base, multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t, multiboot2_get_load_base, multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t,
multiboot_tag_load_base_addr_t, multiboot_tag_load_base_addr_t,
}; };
use crate::libs::align::page_align_up; use crate::libs::align::page_align_up;
use crate::libs::lib_ui::screen_manager::scm_disable_put_to_window; use crate::libs::lib_ui::screen_manager::scm_disable_put_to_window;
use crate::libs::printk::PrintkWriter;
use crate::libs::spinlock::SpinLock; use crate::libs::spinlock::SpinLock;
use crate::mm::allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage}; use crate::mm::allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage};
use crate::mm::memblock::mem_block_manager; use crate::mm::memblock::mem_block_manager;
use crate::mm::mmio_buddy::mmio_init;
use crate::{ use crate::{
arch::MMArch, arch::MMArch,
mm::allocator::{buddy::BuddyAllocator, bump::BumpAllocator}, mm::allocator::{buddy::BuddyAllocator, bump::BumpAllocator},
@ -34,7 +31,7 @@ use system_error::SystemError;
use core::arch::asm; use core::arch::asm;
use core::ffi::c_void; use core::ffi::c_void;
use core::fmt::{Debug, Write}; use core::fmt::Debug;
use core::mem::{self}; use core::mem::{self};
use core::sync::atomic::{compiler_fence, AtomicBool, Ordering}; use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
@ -114,6 +111,7 @@ impl MemoryManagementArch for X86_64MMArch {
/// 物理地址与虚拟地址的偏移量 /// 物理地址与虚拟地址的偏移量
/// 0xffff_8000_0000_0000 /// 0xffff_8000_0000_0000
const PHYS_OFFSET: usize = Self::PAGE_NEGATIVE_MASK + (Self::PAGE_ADDRESS_SIZE >> 1); 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 // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/include/asm/page_64_types.h#75
const USER_END_VADDR: VirtAddr = const USER_END_VADDR: VirtAddr =
@ -154,7 +152,14 @@ impl MemoryManagementArch for X86_64MMArch {
// 初始化物理内存区域(从multiboot2中获取) // 初始化物理内存区域(从multiboot2中获取)
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()); 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中关于指定虚拟地址的条目 /// @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() { unsafe fn allocator_init() {
let virt_offset = BOOTSTRAP_MM_INFO.unwrap().start_brk; let virt_offset = BOOTSTRAP_MM_INFO.unwrap().start_brk;
let phy_offset = let phy_offset =
@ -681,8 +656,8 @@ unsafe fn set_inner_allocator(allocator: BuddyAllocator<MMArch>) {
pub struct LowAddressRemapping; pub struct LowAddressRemapping;
impl LowAddressRemapping { impl LowAddressRemapping {
// 映射32M // 映射64M
const REMAP_SIZE: usize = 32 * 1024 * 1024; const REMAP_SIZE: usize = 64 * 1024 * 1024;
pub unsafe fn remap_at_low_address( pub unsafe fn remap_at_low_address(
mapper: &mut crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>>, 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();
}

View File

@ -12,6 +12,23 @@ pub static DRAGONSTUB_EFI_PAYLOAD_EFI_GUID: Guid = Guid::new(
[0xbc, 0xef, 0x98, 0x12, 0x00, 0x31], [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` /// 对应 `DRAGONSTUB_EFI_PAYLOAD_EFI_GUID`

View File

@ -75,6 +75,16 @@ pub fn efi_init() {
) )
.expect("Failed to reserve memory for EFI mmap table"); .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 // todo: Initialize screen info
kinfo!("UEFI init done!"); kinfo!("UEFI init done!");
@ -212,7 +222,7 @@ fn reserve_memory_regions() {
let inner_guard = efi_manager().inner.read_irqsave(); let inner_guard = efi_manager().inner.read_irqsave();
for md in inner_guard.mmap.iter() { for md in inner_guard.mmap.iter() {
let page_count = (PhysPageFrame::new(PhysAddr::new(page_align_up( 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() .ppn()
- PhysPageFrame::new(PhysAddr::new(page_align_down(md.phys_start 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 phys_start = page_align_down(md.phys_start as usize);
let size = (page_count << (MMArch::PAGE_SHIFT as u64)) 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() { if md.is_memory() {
open_firmware_fdt_driver().early_init_dt_add_memory(phys_start as u64, size as u64); open_firmware_fdt_driver().early_init_dt_add_memory(phys_start as u64, size as u64);
if !md.is_usable_memory() { if !md.is_usable_memory() {

View File

@ -35,6 +35,10 @@ struct InnerEFIManager {
/// runtime services的版本号 /// runtime services的版本号
pub runtime_service_version: Option<uefi_raw::table::Revision>, pub runtime_service_version: Option<uefi_raw::table::Revision>,
pub dragonstub_load_info: Option<DragonStubPayloadEFI>, pub dragonstub_load_info: Option<DragonStubPayloadEFI>,
/// uefi 内存属性表的物理地址
pub memory_attribute_table_paddr: Option<PhysAddr>,
/// uefi 内存保留表的物理地址
pub memreserve_table_paddr: Option<PhysAddr>,
} }
impl EFIManager { impl EFIManager {
@ -46,6 +50,8 @@ impl EFIManager {
runtime_paddr: None, runtime_paddr: None,
runtime_service_version: None, runtime_service_version: None,
dragonstub_load_info: 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; 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表头 /// 检查是否为有效的system table表头
/// ///
/// ## 参数 /// ## 参数

View File

@ -8,14 +8,28 @@ use uefi_raw::table::{
}; };
use crate::{ use crate::{
arch::MMArch,
driver::firmware::efi::{ driver::firmware::efi::{
efi_manager, efi_manager,
guid::{DragonStubPayloadEFI, DRAGONSTUB_EFI_PAYLOAD_EFI_GUID}, 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 { impl EFIManager {
/// 显示EFI系统表头的信息 /// 显示EFI系统表头的信息
@ -64,25 +78,81 @@ impl EFIManager {
/// 解析EFI config table /// 解析EFI config table
pub fn parse_config_tables(&self, tables: &[ConfigurationTable]) -> Result<(), SystemError> { pub fn parse_config_tables(&self, tables: &[ConfigurationTable]) -> Result<(), SystemError> {
for table in tables { for table in tables {
if table let mut flag = false;
.vendor_guid 'parser_loop: for parser in TABLE_PARSERS {
.equivalent(&DRAGONSTUB_EFI_PAYLOAD_EFI_GUID) if let Some(r) = parser.match_table(table) {
{ // 有匹配结果
let table_paddr: PhysAddr = PhysAddr::new(table.vendor_table as usize); if let Err(e) = r {
let vaddr = EarlyIoRemap::map_not_aligned( kwarn!(
table_paddr, "Failed to parse cfg table: '{}', err: {e:?}",
size_of::<DragonStubPayloadEFI>(), parser.table.name()
true, );
)?; }
flag = true;
break 'parser_loop;
}
}
let data = unsafe { *(vaddr.data() as *const DragonStubPayloadEFI) }; if !flag {
kwarn!("Cannot find parser for guid: {:?}", table.vendor_guid);
efi_manager().inner.write().dragonstub_load_info = Some(data);
EarlyIoRemap::unmap(vaddr).unwrap();
} }
} }
// 如果存在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(()); return Ok(());
} }
} }
@ -111,11 +181,10 @@ impl MemoryDescriptor {
/// 当前内存描述符是否表示真实的内存 /// 当前内存描述符是否表示真实的内存
#[inline] #[inline]
pub fn is_memory(&self) -> bool { pub fn is_memory(&self) -> bool {
if self.att.contains( if self.att.contains(MemoryAttribute::WRITE_BACK)
MemoryAttribute::WRITE_BACK || self.att.contains(MemoryAttribute::WRITE_THROUGH)
| MemoryAttribute::WRITE_THROUGH || self.att.contains(MemoryAttribute::WRITE_COMBINE)
| MemoryAttribute::WRITE_COMBINE, {
) {
return true; 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,
}

View File

@ -1,10 +1,16 @@
use core::mem::size_of;
use fdt::{ use fdt::{
node::{FdtNode, NodeProperty}, node::{FdtNode, NodeProperty},
Fdt, Fdt,
}; };
use system_error::SystemError; 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)] #[inline(always)]
pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver { pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver {
@ -72,13 +78,13 @@ impl OpenFirmwareFdtDriver {
if let Some(prop) = node.property("#size-cells") { if let Some(prop) = node.property("#size-cells") {
guard.root_size_cells = prop.as_usize().unwrap() as u32; 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") { if let Some(prop) = node.property("#address-cells") {
guard.root_addr_cells = prop.as_usize().unwrap() as u32; 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(()); return Ok(());
@ -151,41 +157,10 @@ impl OpenFirmwareFdtDriver {
let total_elements_in_reg = reg.value.len() / ((addr_cells + size_cells) * 4); let total_elements_in_reg = reg.value.len() / ((addr_cells + size_cells) * 4);
for i in 0..total_elements_in_reg { for i in 0..total_elements_in_reg {
let mut base_index = i * (addr_cells + size_cells); let 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 { let (base, base_index) = read_cell(reg.value, base_index, addr_cells);
1 => { let (size, _) = read_cell(reg.value, base_index, size_cells);
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 { if size == 0 {
continue; continue;
@ -258,20 +233,21 @@ impl OpenFirmwareFdtDriver {
size -= MemBlockManager::MIN_MEMBLOCK_ADDR.data() - base; size -= MemBlockManager::MIN_MEMBLOCK_ADDR.data() - base;
base = MemBlockManager::MIN_MEMBLOCK_ADDR.data(); 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 { fn is_device_avaliable(&self, node: &FdtNode) -> bool {
let status = node.property("status"); let status = node.property("status");
if status.is_none() { if status.is_none() {
@ -287,4 +263,189 @@ impl OpenFirmwareFdtDriver {
return false; 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");
}
}
} }

View File

@ -1,3 +1,5 @@
use core::sync::atomic::{compiler_fence, Ordering};
use super::log::{LogLevel, LogMessage}; use super::log::{LogLevel, LogMessage};
use crate::libs::spinlock::SpinLock; use crate::libs::spinlock::SpinLock;
@ -16,8 +18,13 @@ pub static mut KMSG: Option<SpinLock<Kmsg>> = None;
/// 初始化KMSG /// 初始化KMSG
pub fn kmsg_init() { pub fn kmsg_init() {
kinfo!("kmsg_init");
let kmsg = SpinLock::new(Kmsg::new()); let kmsg = SpinLock::new(Kmsg::new());
compiler_fence(Ordering::SeqCst);
unsafe { KMSG = Some(kmsg) }; unsafe { KMSG = Some(kmsg) };
compiler_fence(Ordering::SeqCst);
kinfo!("kmsg_init done");
} }
/// 日志 /// 日志

View File

@ -7,7 +7,7 @@ use crate::{
video::{fbdev::base::BootTimeScreenInfo, VideoRefreshManager}, video::{fbdev::base::BootTimeScreenInfo, VideoRefreshManager},
}, },
libs::{lib_ui::screen_manager::scm_init, rwlock::RwLock}, libs::{lib_ui::screen_manager::scm_init, rwlock::RwLock},
mm::VirtAddr, mm::{PhysAddr, VirtAddr},
}; };
mod c_adapter; mod c_adapter;
@ -102,7 +102,7 @@ impl BootParams {
self.boot_command_line[pos + len] = 0; self.boot_command_line[pos + len] = 0;
} }
/// 获取FDT的物理地址 /// 获取FDT的虚拟地址
#[allow(dead_code)] #[allow(dead_code)]
pub fn fdt(&self) -> Option<VirtAddr> { pub fn fdt(&self) -> Option<VirtAddr> {
#[cfg(target_arch = "riscv64")] #[cfg(target_arch = "riscv64")]
@ -111,4 +111,14 @@ impl BootParams {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
return None; 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;
}
} }

View File

@ -116,9 +116,10 @@ pub struct Logger;
impl Logger { impl Logger {
pub fn log(&self, log_level: usize, message: fmt::Arguments) { 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 timestamp: TimeSpec = TimeSpec::now();
let log_level = LogLevel::from(log_level.clone()); let log_level = LogLevel::from(log_level.clone());
let log_message = LogMessage::new(timestamp, log_level, message.to_string()); let log_message = LogMessage::new(timestamp, log_level, message.to_string());
unsafe { KMSG.as_ref().unwrap().lock_irqsave().push(log_message) }; unsafe { KMSG.as_ref().unwrap().lock_irqsave().push(log_message) };

View File

@ -110,13 +110,16 @@ impl<A: MemoryManagementArch> BuddyAllocator<A> {
let remain_areas = &res_areas[0..]; 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 { for area in remain_areas {
let mut paddr = (area.area_base_aligned() + offset_in_remain_area).data(); let mut paddr = (area.area_base_aligned() + offset_in_remain_area).data();
let mut remain_pages = let mut remain_pages =
PageFrameCount::from_bytes(area.area_end_aligned().data() - paddr).unwrap(); 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; total_pages_to_buddy += remain_pages;
if offset_in_remain_area != 0 { if offset_in_remain_area != 0 {

View File

@ -3,7 +3,14 @@
/// @FilePath: /DragonOS/kernel/src/mm/allocator/bump.rs /// @FilePath: /DragonOS/kernel/src/mm/allocator/bump.rs
/// @Description: bump allocator线性分配器 /// @Description: bump allocator线性分配器
use super::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage}; 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; use core::marker::PhantomData;
/// 线性分配器 /// 线性分配器
@ -41,44 +48,47 @@ impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
pub fn remain_areas(&self, result_area: &mut [PhysMemoryArea]) -> Option<usize> { pub fn remain_areas(&self, result_area: &mut [PhysMemoryArea]) -> Option<usize> {
let mut offset = self.offset(); let mut offset = self.offset();
let iter = mem_block_manager().to_iter_available();
let mut ret_offset_aligned = 0; let mut ret_offset_aligned = 0;
let mut res_cnt = 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 { for area in iter {
let area = mem_block_manager().get_initial_memory_region(i).unwrap(); if found_start == false {
// 将area的base地址与PAGE_SIZE对齐对齐时向上取整 // 将area的base地址与PAGE_SIZE对齐对齐时向上取整
// let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT); // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
let area_base = area.area_base_aligned().data(); let area_base = area.area_base_aligned().data();
// 将area的末尾地址与PAGE_SIZE对齐对齐时向下取整 // 将area的末尾地址与PAGE_SIZE对齐对齐时向下取整
// let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT); // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
let area_end = area.area_end_aligned().data(); let area_end = area.area_end_aligned().data();
// 如果offset大于area_end说明当前的物理内存区域已经分配完了需要跳到下一个物理内存区域 // 如果offset大于area_end说明当前的物理内存区域已经分配完了需要跳到下一个物理内存区域
if offset >= area_end { if offset >= area_end {
continue; continue;
} }
// 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧将offset设置为area_base // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧将offset设置为area_base
if offset < area_base { if offset < area_base {
offset = area_base; offset = area_base;
} else if offset < area_end { } else if offset < area_end {
// 将offset对齐到PAGE_SIZE // 将offset对齐到PAGE_SIZE
offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1); offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1);
} }
// found // found
if offset + 1 * MMA::PAGE_SIZE <= area_end { if offset + 1 * MMA::PAGE_SIZE <= area_end {
for j in i..total_num { ret_offset_aligned = offset - area.area_base_aligned().data();
let aj = mem_block_manager().get_initial_memory_region(j).unwrap(); found_start = true;
if aj.area_base_aligned() < aj.area_end_aligned() { }
result_area[res_cnt] = aj; }
res_cnt += 1;
} 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); 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> { 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)> { unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
let mut offset = self.offset(); let mut offset = self.offset();
let iter = mem_block_manager().to_iter(); let iter = mem_block_manager().to_iter_available();
// 遍历所有的物理内存区域 // 遍历所有的物理内存区域
for area in iter { for area in iter {
@ -128,7 +160,9 @@ impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
// 将offset增加至分配后的内存 // 将offset增加至分配后的内存
self.offset = offset + count.data() * MMA::PAGE_SIZE; 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; return None;
@ -144,7 +178,7 @@ impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
unsafe fn usage(&self) -> PageFrameUsage { unsafe fn usage(&self) -> PageFrameUsage {
let mut total = 0; let mut total = 0;
let mut used = 0; let mut used = 0;
let iter = mem_block_manager().to_iter(); let iter = mem_block_manager().to_iter_available();
for area in iter { for area in iter {
// 将area的base地址与PAGE_SIZE对齐对其时向上取整 // 将area的base地址与PAGE_SIZE对齐对其时向上取整
let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT); let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);

View File

@ -56,7 +56,7 @@ impl KernelAllocator {
} }
} }
/// 为内核SLAB分配器实现LocalAlloc的trait /// 为内核分配器实现LocalAlloc的trait
impl LocalAlloc for KernelAllocator { impl LocalAlloc for KernelAllocator {
unsafe fn local_alloc(&self, layout: Layout) -> *mut u8 { unsafe fn local_alloc(&self, layout: Layout) -> *mut u8 {
return self return self
@ -84,7 +84,7 @@ impl LocalAlloc for KernelAllocator {
/// 为内核slab分配器实现GlobalAlloc特性 /// 为内核slab分配器实现GlobalAlloc特性
unsafe impl GlobalAlloc for KernelAllocator { unsafe impl GlobalAlloc for KernelAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 { unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let r = self.local_alloc(layout); let r = self.local_alloc_zeroed(layout);
mm_debug_log( mm_debug_log(
klog_types::AllocatorLogType::Alloc(AllocLogItem::new( klog_types::AllocatorLogType::Alloc(AllocLogItem::new(
layout.clone(), layout.clone(),

View File

@ -78,7 +78,8 @@ impl Iterator for PhysPageFrameIter {
if unlikely(self.current == self.end) { if unlikely(self.current == self.end) {
return None; return None;
} }
let current = self.current.next(); let current: PhysPageFrame = self.current;
self.current = self.current.next_by(1);
return Some(current); return Some(current);
} }
} }

View File

@ -14,8 +14,9 @@ use crate::{
}; };
use super::{ use super::{
allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, mmio_buddy::mmio_pool, allocator::page_frame::PageFrameCount, init::mm_init, kernel_mapper::KernelMapper,
no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr, mmio_buddy::mmio_pool, no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch,
PhysAddr, VirtAddr,
}; };
lazy_static! { 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) .release_mmio(VirtAddr::new(vaddr as usize), length as usize)
.unwrap_or_else(|err| err.to_posix_errno()); .unwrap_or_else(|err| err.to_posix_errno());
} }
#[no_mangle]
unsafe extern "C" fn rs_mm_init() {
mm_init();
}

View File

@ -179,7 +179,6 @@ impl EarlyIoRemap {
let count = PageFrameCount::from_bytes(slot_guard[idx].size as usize).unwrap(); let count = PageFrameCount::from_bytes(slot_guard[idx].size as usize).unwrap();
// 取消映射 // 取消映射
unsafe { pseudo_unmap_phys(vaddr, count) }; unsafe { pseudo_unmap_phys(vaddr, count) };
for i in 0..count.data() { for i in 0..count.data() {

61
kernel/src/mm/init.rs Normal file
View 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)
}

View File

@ -2,7 +2,10 @@ use core::intrinsics::unlikely;
use system_error::SystemError; 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}; use super::{PhysAddr, PhysMemoryArea};
@ -50,7 +53,8 @@ impl MemBlockManager {
/// 如果添加的区域与已有区域有重叠,会将重叠的区域合并 /// 如果添加的区域与已有区域有重叠,会将重叠的区域合并
#[allow(dead_code)] #[allow(dead_code)]
pub fn add_block(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> { 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( fn set_or_clear_flags(
&self, &self,
base: PhysAddr, mut base: PhysAddr,
size: usize, mut size: usize,
set: bool, set: bool,
flags: MemoryAreaAttr, flags: MemoryAreaAttr,
) -> Result<(), SystemError> { ) -> 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 mut inner = self.inner.lock();
let (start_index, end_index) = self.isolate_range(&mut inner, base, size)?; let (start_index, end_index) = self.isolate_range(&mut inner, base, size)?;
for i in start_index..end_index { for i in start_index..end_index {
@ -375,10 +383,68 @@ impl MemBlockManager {
return self.set_or_clear_flags(base, size, true, MemoryAreaAttr::RESERVED); 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 { pub fn to_iter(&self) -> MemBlockIter {
let inner = self.inner.lock(); 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> { pub struct MemBlockIter<'a> {
inner: SpinLockGuard<'a, InnerMemBlockManager>, inner: SpinLockGuard<'a, InnerMemBlockManager>,
index: usize, index: usize,
usable_only: bool,
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -421,6 +488,22 @@ impl<'a> Iterator for MemBlockIter<'a> {
type Item = PhysMemoryArea; type Item = PhysMemoryArea;
fn next(&mut self) -> Option<Self::Item> { 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 { if self.index >= self.inner.initial_memory_regions_num {
return None; return None;
} }

View File

@ -51,6 +51,7 @@ pub struct MmioBuddyMemPool {
} }
impl MmioBuddyMemPool { impl MmioBuddyMemPool {
#[inline(never)]
fn new() -> Self { fn new() -> Self {
let mut free_regions: [MaybeUninit<SpinLock<MmioFreeRegionList>>; let mut free_regions: [MaybeUninit<SpinLock<MmioFreeRegionList>>;
MMIO_BUDDY_REGION_COUNT as usize] = unsafe { MaybeUninit::uninit().assume_init() }; MMIO_BUDDY_REGION_COUNT as usize] = unsafe { MaybeUninit::uninit().assume_init() };

View File

@ -22,6 +22,7 @@ use self::{
pub mod allocator; pub mod allocator;
pub mod c_adapter; pub mod c_adapter;
pub mod early_ioremap; pub mod early_ioremap;
pub mod init;
pub mod kernel_mapper; pub mod kernel_mapper;
pub mod memblock; pub mod memblock;
pub mod mmio_buddy; pub mod mmio_buddy;
@ -407,6 +408,11 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
/// 虚拟地址与物理地址的偏移量 /// 虚拟地址与物理地址的偏移量
const PHYS_OFFSET: usize; 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; const PAGE_SIZE: usize = 1 << Self::PAGE_SHIFT;
/// 通过这个mask获取地址的页内偏移量 /// 通过这个mask获取地址的页内偏移量

View File

@ -141,7 +141,7 @@ impl<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> {
/// 并且内核引导文件必须以4K页为粒度填写了前100M的内存映射关系。具体以本文件开头的注释为准 /// 并且内核引导文件必须以4K页为粒度填写了前100M的内存映射关系。具体以本文件开头的注释为准
#[inline(never)] #[inline(never)]
pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) { 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); pseudo_map_phys_with_flags(vaddr, paddr, count, flags);
} }
@ -192,7 +192,6 @@ pub unsafe fn pseudo_map_phys_with_flags(
#[inline(never)] #[inline(never)]
pub unsafe fn pseudo_unmap_phys(vaddr: VirtAddr, count: PageFrameCount) { pub unsafe fn pseudo_unmap_phys(vaddr: VirtAddr, count: PageFrameCount) {
assert!(vaddr.check_aligned(MMArch::PAGE_SIZE)); assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
assert!(count.data() == 1);
let mut pseudo_allocator = PseudoAllocator::<MMArch>::new(); let mut pseudo_allocator = PseudoAllocator::<MMArch>::new();

View File

@ -213,7 +213,7 @@ impl<Arch: MemoryManagementArch> PageEntry<Arch> {
#[cfg(target_arch = "riscv64")] #[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() super::allocator::page_frame::PhysPageFrame::from_ppn(ppn).phys_address()
} }
}; };

View File

@ -76,7 +76,7 @@ impl TimeSpec {
#[cfg(target_arch = "riscv64")] #[cfg(target_arch = "riscv64")]
{ {
unimplemented!("TimeSpec::now()") return TimeSpec::new(0, 0);
} }
} }
} }