riscv64: 映射uefi systemtable,并完善了riscv64页表填写的部分内容 (#498)

* 从fdt的chosen段获取几个需要的字段

* merge patch-early-ioremap

* feature: 增加early io remap的fixmap功能

允许在内存管理初始化之前,使用fixmap功能,映射一些物理内存,并记录.

* riscv64: 映射uefi systemtable,并完善了riscv64页表填写的部分内容

* 更新仓库网址
This commit is contained in:
LoGin 2024-01-21 15:38:12 +08:00 committed by GitHub
parent 3e3c6316aa
commit 7a29d4fcbc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 894 additions and 91 deletions

View File

@ -46,6 +46,9 @@ system_error = { path = "crates/system_error" }
unified-init = { path = "crates/unified-init" }
virtio-drivers = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/virtio-drivers.git", rev = "f1d1cbb" }
fdt = "0.1.5"
uefi = { version = "0.26.0", features = ["alloc"] }
uefi-raw = "0.5.0"
# target为x86_64时使用下面的依赖
[target.'cfg(target_arch = "x86_64")'.dependencies]
@ -56,7 +59,7 @@ x86_64 = "0.14.10"
# target为riscv64时使用下面的依赖
[target.'cfg(target_arch = "riscv64")'.dependencies]
riscv = { version = "0.11.0", features = [ "s-mode" ] }
# 构建时依赖项

View File

@ -12,7 +12,7 @@ crc = { path = "../crc" }
# 一个无锁MPSC队列
[dependencies.thingbuf]
git = "https://git.mirrors.dragonos.org/DragonOS-Community/thingbuf.git"
git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/thingbuf.git"
rev = "2dded730c3"
default-features = false
features = ["alloc", "static"]

View File

@ -7,6 +7,6 @@ edition = "2021"
[dependencies]
kdepends = { path = "../kdepends" }
num-traits = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false }
num-traits = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false }
num = { version = "0.4.0", default-features = false }
num-derive = "0.3"

View File

@ -17,9 +17,9 @@ ifeq ($(UNWIND_ENABLE), yes)
CFLAGS_UNWIND = -funwind-tables
ifeq ($(ARCH), x86_64)
LDFLAGS_UNWIND = --eh-frame-hdr
endif
RUSTFLAGS_UNWIND = -Cforce-unwind-tables -Clink-arg=-Wl,eh_frame.ld
endif
endif
RUSTFLAGS = $(RUSTFLAGS_UNWIND)

View File

@ -92,7 +92,7 @@ __init_set_pgtable_loop_end:
la a0, BSP_IDLE_STACK_SPACE
mv sp, a0
li t0, 32768
li t0, 32752 // 16
add sp, sp, t0
.option pop
/*
@ -330,6 +330,7 @@ __initial_hartid_ptr:
.quad 0
// _start
.global __initial_start_load_paddr
__initial_start_load_paddr:
.quad 0
@ -344,9 +345,11 @@ __initial_satp_mode:
// sv39L0
.section .initial_pgtable_section
.global __initial_pgtable
__initial_pgtable:
.skip 4096
.global __initial_l1_pgtable
__initial_l1_pgtable:
.skip 8192

View File

@ -1,7 +1,5 @@
use crate::{
arch::driver::sbi::ecall::{ecall0, ecall1},
mm::VirtAddr,
};
#![allow(dead_code)]
use crate::{arch::driver::sbi::ecall::ecall1, mm::VirtAddr};
use core::arch::asm;
/// `sbi_set_timer` extension ID

View File

@ -3,10 +3,14 @@ use core::intrinsics::unreachable;
use fdt::node::FdtNode;
use crate::{
driver::open_firmware::fdt::open_firmware_fdt_driver,
arch::{mm::init::mm_early_init, MMArch},
driver::{
firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver,
tty::serial::serial8250::send_to_default_serial8250_port,
},
init::{boot_params, init_before_mem_init},
kinfo,
mm::{PhysAddr, VirtAddr},
kdebug, kinfo,
mm::{MemoryManagementArch, PhysAddr, VirtAddr},
print, println,
};
@ -14,18 +18,36 @@ use crate::{
pub struct ArchBootParams {
/// 启动时的fdt物理地址
pub fdt_paddr: PhysAddr,
pub fdt_vaddr: Option<VirtAddr>,
}
impl ArchBootParams {
pub const DEFAULT: Self = ArchBootParams {
fdt_paddr: PhysAddr::new(0),
fdt_vaddr: None,
};
pub fn arch_fdt(&self) -> VirtAddr {
// 如果fdt_vaddr为None则说明还没有进行内核虚拟地址空间的映射此时返回物理地址
if self.fdt_vaddr.is_none() {
return VirtAddr::new(self.fdt_paddr.data());
}
self.fdt_vaddr.unwrap()
}
}
#[no_mangle]
unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
let fdt_paddr = PhysAddr::new(fdt_paddr);
init_before_mem_init();
extern "C" {
fn BSP_IDLE_STACK_SPACE();
}
kdebug!("BSP_IDLE_STACK_SPACE={:#x}", BSP_IDLE_STACK_SPACE as u64);
kdebug!("PAGE_ADDRESS_SIZE={}", MMArch::PAGE_ADDRESS_SIZE);
kdebug!("PAGE_ADDRESS_SHIFT={}", MMArch::PAGE_ADDRESS_SHIFT);
boot_params().write().arch.fdt_paddr = fdt_paddr;
kinfo!(
"DragonOS kernel is running on hart {}, fdt address:{:?}",
@ -33,15 +55,20 @@ unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
fdt_paddr
);
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);
parse_dtb();
efi_init();
loop {}
unreachable()
}
#[inline(never)]
fn print_node(node: FdtNode<'_, '_>, n_spaces: usize) {
(0..n_spaces).for_each(|_| print!(" "));
println!("{}/", node.name);
@ -56,15 +83,13 @@ fn print_node(node: FdtNode<'_, '_>, n_spaces: usize) {
}
/// 解析fdt获取内核启动参数
#[inline(never)]
unsafe fn parse_dtb() {
let fdt_paddr = boot_params().read().arch.fdt_paddr;
if fdt_paddr.is_null() {
panic!("Failed to get fdt address!");
}
open_firmware_fdt_driver()
.set_fdt_vaddr(VirtAddr::new(fdt_paddr.data()))
.unwrap();
open_firmware_fdt_driver()
.early_scan_device_tree()
.expect("Failed to scan device tree at boottime.");

View File

@ -6,23 +6,29 @@ pub struct RiscV64InterruptArch;
impl InterruptArch for RiscV64InterruptArch {
unsafe fn interrupt_enable() {
unimplemented!("RiscV64InterruptArch::interrupt_enable")
riscv::interrupt::enable();
}
unsafe fn interrupt_disable() {
unimplemented!("RiscV64InterruptArch::interrupt_disable")
riscv::interrupt::disable();
}
fn is_irq_enabled() -> bool {
unimplemented!("RiscV64InterruptArch::is_irq_enabled")
riscv::register::sstatus::read().sie()
}
unsafe fn save_and_disable_irq() -> IrqFlagsGuard {
unimplemented!("RiscV64InterruptArch::save_and_disable_irq")
let sie = riscv::register::sstatus::read().sie();
IrqFlagsGuard::new(IrqFlags::new(sie.into()))
}
unsafe fn restore_irq(flags: IrqFlags) {
unimplemented!("RiscV64InterruptArch::restore_irq")
let sie: bool = flags.flags() != 0;
if sie {
riscv::register::sstatus::set_sie();
} else {
riscv::register::sstatus::clear_sie();
}
}
}

View File

@ -76,6 +76,8 @@ SECTIONS
_bss = .;
*(.bss)
*(.bss.*)
*(.sbss)
*(.sbss.*)
_ebss = .;
}

View File

@ -1,3 +1,55 @@
use virtio_drivers::PhysAddr;
use system_error::SystemError;
pub fn setup_vm(dtb_paddr: PhysAddr) {}
use crate::{
arch::{
mm::{KERNEL_BEGIN_PA, KERNEL_BEGIN_VA, KERNEL_END_PA, KERNEL_END_VA},
MMArch,
},
kdebug,
mm::{
allocator::page_frame::PageFrameCount,
no_init::{pseudo_map_phys, EARLY_IOREMAP_PAGES},
page::{PageEntry, PageMapper, PageTable},
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
},
};
#[inline(never)]
pub fn mm_early_init() {
unsafe { init_kernel_addr() };
// unsafe { map_initial_page_table_linearly() };
}
unsafe fn init_kernel_addr() {
extern "C" {
/// 内核起始label
fn boot_text_start_pa();
/// 内核结束位置的label
fn _end();
fn _start();
/// 内核start标签被加载到的物理地址
fn __initial_start_load_paddr();
}
let initial_start_load_pa = *(__initial_start_load_paddr as usize as *const usize);
let offset = _start as usize - boot_text_start_pa as usize;
let start_pa = initial_start_load_pa - offset;
let offset2 = _end as usize - boot_text_start_pa as usize;
let end_pa = start_pa + offset2;
KERNEL_BEGIN_PA = PhysAddr::new(start_pa);
KERNEL_END_PA = PhysAddr::new(end_pa);
KERNEL_BEGIN_VA = VirtAddr::new(boot_text_start_pa as usize);
KERNEL_END_VA = VirtAddr::new(_end as usize);
kdebug!(
"init_kernel_addr: \n\tKERNEL_BEGIN_PA: {KERNEL_BEGIN_PA:?}
\tKERNEL_END_PA: {KERNEL_END_PA:?}
\tKERNEL_BEGIN_VA: {KERNEL_BEGIN_VA:?}
\tKERNEL_END_VA: {KERNEL_END_VA:?}
"
);
}

View File

@ -1,9 +1,13 @@
use riscv::register::satp;
use system_error::SystemError;
use crate::mm::{
allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage},
use crate::{
kdebug,
mm::{
allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
page::PageFlags,
MemoryManagementArch, PhysAddr, VirtAddr,
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
},
};
pub mod bump;
@ -11,6 +15,15 @@ pub(super) mod init;
pub type PageMapper = crate::mm::page::PageMapper<RiscV64MMArch, LockedFrameAllocator>;
/// 内核起始物理地址
pub(self) static mut KERNEL_BEGIN_PA: PhysAddr = PhysAddr::new(0);
/// 内核结束的物理地址
pub(self) static mut KERNEL_END_PA: PhysAddr = PhysAddr::new(0);
/// 内核起始虚拟地址
pub(self) static mut KERNEL_BEGIN_VA: VirtAddr = VirtAddr::new(0);
/// 内核结束虚拟地址
pub(self) static mut KERNEL_END_VA: VirtAddr = VirtAddr::new(0);
/// RiscV64的内存管理架构结构体(sv39)
#[derive(Debug, Clone, Copy, Hash)]
pub struct RiscV64MMArch;
@ -62,24 +75,34 @@ impl MemoryManagementArch for RiscV64MMArch {
todo!()
}
unsafe fn invalidate_page(address: crate::mm::VirtAddr) {
todo!()
unsafe fn invalidate_page(address: VirtAddr) {
riscv::asm::sfence_vma(0, address.data());
}
unsafe fn invalidate_all() {
todo!()
riscv::asm::sfence_vma_all();
}
unsafe fn table(table_kind: crate::mm::PageTableKind) -> crate::mm::PhysAddr {
todo!()
unsafe fn table(_table_kind: PageTableKind) -> PhysAddr {
// phys page number
let ppn = riscv::register::satp::read().ppn();
let paddr = PhysPageFrame::from_ppn(ppn).phys_address();
kdebug!("table(): {paddr:?}, ppn: {ppn}");
return paddr;
}
unsafe fn set_table(table_kind: crate::mm::PageTableKind, table: crate::mm::PhysAddr) {
todo!()
unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) {
let ppn = PhysPageFrame::new(table).ppn();
kdebug!("set_table(): {table:?}, ppn:{ppn}");
riscv::asm::sfence_vma_all();
satp::set(satp::Mode::Sv39, 0, ppn);
}
fn virt_is_valid(virt: crate::mm::VirtAddr) -> bool {
todo!()
virt.is_canonical()
}
fn initial_page_table() -> crate::mm::PhysAddr {
@ -89,6 +112,56 @@ impl MemoryManagementArch for RiscV64MMArch {
fn setup_new_usermapper() -> Result<crate::mm::ucontext::UserMapper, SystemError> {
todo!()
}
unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> {
// riscv的内核文件所占用的空间由于重定位而导致不满足线性偏移量的关系
// 因此这里需要特殊处理
if phys >= KERNEL_BEGIN_PA && phys < KERNEL_END_PA {
let r = KERNEL_BEGIN_VA + (phys - KERNEL_BEGIN_PA);
return Some(r);
}
if let Some(vaddr) = phys.data().checked_add(Self::PHYS_OFFSET) {
return Some(VirtAddr::new(vaddr));
} else {
return None;
}
}
unsafe fn virt_2_phys(virt: VirtAddr) -> Option<PhysAddr> {
if virt >= KERNEL_BEGIN_VA && virt < KERNEL_END_VA {
let r = KERNEL_BEGIN_PA + (virt - KERNEL_BEGIN_VA);
kdebug!("virt_2_phys: kernel address: virt = {virt:?}, paddr = {r:?}");
return Some(r);
}
if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) {
let r = PhysAddr::new(paddr);
kdebug!("virt_2_phys: non-kernel address: virt = {virt:?}, paddr = {r:?}");
return Some(r);
} else {
return None;
}
}
fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize {
let ppn = PhysPageFrame::new(paddr).ppn();
let r = ((ppn & ((1 << 44) - 1)) << 10) | page_flags;
kdebug!("make entry: r={r:#x}");
return r;
}
}
impl VirtAddr {
/// 判断虚拟地址是否合法
#[inline(always)]
pub fn is_canonical(self) -> bool {
let x = self.data() & RiscV64MMArch::PHYS_OFFSET;
// 如果x为0说明虚拟地址的高位为0是合法的用户地址
// 如果x为PHYS_OFFSET说明虚拟地址的高位全为1是合法的内核地址
return x == 0 || x == RiscV64MMArch::PHYS_OFFSET;
}
}
/// 获取内核地址默认的页面标志

View File

@ -284,6 +284,11 @@ impl MemoryManagementArch for X86_64MMArch {
return None;
}
}
#[inline(always)]
fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize {
return paddr.data() | page_flags;
}
}
impl X86_64MMArch {
@ -334,8 +339,6 @@ impl X86_64MMArch {
}
total_mem_size += mb2_mem_info[i].len as usize;
// PHYS_MEMORY_AREAS[areas_count].base = PhysAddr::new(mb2_mem_info[i].addr as usize);
// PHYS_MEMORY_AREAS[areas_count].size = mb2_mem_info[i].len as usize;
mem_block_manager()
.add_block(
@ -450,7 +453,7 @@ unsafe fn allocator_init() {
// 取消最开始时候在head.S中指定的映射(暂时不刷新TLB)
{
let table = mapper.table();
let empty_entry = PageEntry::<MMArch>::new(0);
let empty_entry = PageEntry::<MMArch>::from_usize(0);
for i in 0..MMArch::PAGE_ENTRY_NUM {
table
.set_entry(i, empty_entry)

View File

@ -0,0 +1,189 @@
//! 与UEFI相关的fdt操作
use core::fmt::Debug;
use fdt::Fdt;
use system_error::SystemError;
use crate::init::boot_params;
use super::EFIManager;
// 由于代码涉及转换因此这里每个的大小都是8字节
#[derive(Default)]
pub struct EFIFdtParams {
// systable
pub systable: Option<u64>,
// mmap_base
pub mmap_base: Option<u64>,
// mmap_size
pub mmap_size: Option<u64>,
// mmap_desc_size
pub mmap_desc_size: Option<u64>,
// mmap_desc_version
pub mmap_desc_version: Option<u64>,
}
impl Debug for EFIFdtParams {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
// 十六进制输出
f.debug_struct("EFIFdtParams")
.field("systable", &format_args!("{:#x?}", self.systable))
.field("mmap_base", &format_args!("{:#x?}", self.mmap_base))
.field("mmap_size", &format_args!("{:#x?}", self.mmap_size))
.field(
"mmap_desc_size",
&format_args!("{:#x?}", self.mmap_desc_size),
)
.field(
"mmap_desc_version",
&format_args!("{:#x?}", self.mmap_desc_version),
)
.finish()
}
}
/// 要从FDT中获取的属性
#[derive(Debug, Clone, Copy)]
enum FdtPropType {
SystemTable,
MMBase,
MMSize,
DescSize,
DescVersion,
}
impl FdtPropType {
/// 获取属性对应的fdt属性名
fn prop_name(&self) -> &'static str {
self.clone().into()
}
}
impl Into<&'static str> for FdtPropType {
fn into(self) -> &'static str {
match self {
FdtPropType::SystemTable => "linux,uefi-system-table",
FdtPropType::MMBase => "linux,uefi-mmap-start",
FdtPropType::MMSize => "linux,uefi-mmap-size",
FdtPropType::DescSize => "linux,uefi-mmap-desc-size",
FdtPropType::DescVersion => "linux,uefi-mmap-desc-ver",
}
}
}
impl TryFrom<&str> for FdtPropType {
type Error = SystemError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value {
"linux,uefi-system-table" => Ok(FdtPropType::SystemTable),
"linux,uefi-mmap-start" => Ok(FdtPropType::MMBase),
"linux,uefi-mmap-size" => Ok(FdtPropType::MMSize),
"linux,uefi-mmap-desc-size" => Ok(FdtPropType::DescSize),
"linux,uefi-mmap-desc-ver" => Ok(FdtPropType::DescVersion),
_ => Err(SystemError::EINVAL),
}
}
}
struct ParamToRead {
/// FDT节点路径
path: &'static str,
/// 当前节点下要读取的属性
properties: &'static [FdtPropType],
}
static PARAM_TO_READ: &[ParamToRead] = &[ParamToRead {
path: "/chosen",
properties: &[
FdtPropType::SystemTable,
FdtPropType::MMBase,
FdtPropType::MMSize,
FdtPropType::DescSize,
FdtPropType::DescVersion,
],
}];
impl EFIManager {
pub(super) fn get_fdt_params(&self) -> Result<EFIFdtParams, SystemError> {
let fdt = unsafe {
Fdt::from_ptr(
boot_params()
.read()
.fdt()
.ok_or(SystemError::ENODEV)?
.data() as *const u8,
)
}
.map_err(|e| {
kerror!("failed to parse fdt, err={:?}", e);
SystemError::EINVAL
})?;
let mut ret = EFIFdtParams::default();
for param in PARAM_TO_READ {
let node = fdt.find_node(param.path);
if node.is_none() {
continue;
}
let node = node.unwrap();
for prop in param.properties {
let prop = node.property(prop.prop_name());
if prop.is_none() {
continue;
}
let prop = prop.unwrap();
let prop_type = FdtPropType::try_from(prop.name);
if prop_type.is_err() {
continue;
}
let prop_type = prop_type.unwrap();
self.do_get_fdt_prop(prop_type, &prop, &mut ret)
.unwrap_or_else(|e| {
kerror!("Failed to get fdt prop: {prop_type:?}, error: {e:?}");
})
}
}
return Ok(ret);
}
fn do_get_fdt_prop(
&self,
prop_type: FdtPropType,
prop: &fdt::node::NodeProperty<'_>,
target: &mut EFIFdtParams,
) -> Result<(), SystemError> {
let val: u64;
if prop.value.len() == 4 {
val = u32::from_be_bytes(prop.value[0..4].try_into().unwrap()) as u64;
} else {
val = u64::from_be_bytes(prop.value[0..8].try_into().unwrap());
}
match prop_type {
FdtPropType::SystemTable => {
target.systable = Some(val);
}
FdtPropType::MMBase => {
target.mmap_base = Some(val);
}
FdtPropType::MMSize => {
target.mmap_size = Some(val);
}
FdtPropType::DescSize => {
target.mmap_desc_size = Some(val);
}
FdtPropType::DescVersion => {
target.mmap_desc_version = Some(val);
}
}
return Ok(());
}
}

View File

@ -0,0 +1,129 @@
use core::{intrinsics::unlikely, mem::size_of};
use system_error::SystemError;
use crate::{
driver::firmware::efi::EFIInitFlags,
libs::align::page_align_down,
mm::{early_ioremap::EarlyIoRemap, PhysAddr, VirtAddr},
};
use super::efi_manager;
#[allow(dead_code)]
#[inline(never)]
pub fn efi_init() {
let data_from_fdt = efi_manager()
.get_fdt_params()
.expect("Failed to get fdt params");
if data_from_fdt.systable.is_none() {
kerror!("Failed to get systable from fdt");
return;
}
kdebug!("to map memory table");
// 映射mmap table
if efi_manager().memmap_init_early(&data_from_fdt).is_err() {
// 如果我们通过UEFI进行引导
// 那么 UEFI memory map 就是我们拥有的关于内存的唯一描述,
// 所以如果我们无法访问它,那么继续进行下去就没有什么意义了
kerror!("Failed to initialize early memory map");
loop {}
}
// kdebug!("NNNN");
// kwarn!("BBBB, e:{:?}", SystemError::EINVAL);
let desc_version = efi_manager().desc_version();
if unlikely(desc_version != 1) {
kwarn!("Unexpected EFI memory map version: {}", desc_version);
}
// todo: 映射table初始化runtime services
let r = uefi_init(PhysAddr::new(data_from_fdt.systable.unwrap() as usize));
if let Err(r) = r {
kerror!("Failed to initialize UEFI: {:?}", r);
}
loop {}
}
#[inline(never)]
fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> {
// 定义错误处理函数
// 错误处理取消systable的映射
let err_unmap_systable = |st_vaddr: VirtAddr| {
EarlyIoRemap::unmap(st_vaddr)
.map_err(|e| {
kerror!("Failed to unmap system table: {e:?}");
})
.ok();
};
// 映射system table
let st_size = size_of::<uefi_raw::table::system::SystemTable>();
kdebug!("system table: {system_table:?}, size: {st_size}");
let st_map_phy_base = PhysAddr::new(page_align_down(system_table.data()));
let st_map_offset = system_table.data() - st_map_phy_base.data();
let st_map_size = st_size + st_map_offset;
let (st_vaddr, _st_map_size) =
EarlyIoRemap::map(st_map_phy_base, st_map_size, true).map_err(|e| {
kwarn!("Unable to map EFI system table, e:{e:?}");
e
})?;
let st_vaddr = st_vaddr + st_map_offset;
efi_manager()
.inner
.write()
.init_flags
.set(EFIInitFlags::BOOT, true);
efi_manager()
.inner
.write()
.init_flags
.set(EFIInitFlags::EFI_64BIT, true);
kdebug!("to parse EFI system table: p: {st_vaddr:?}");
if st_vaddr.is_null() {
return Err(SystemError::EINVAL);
}
// 解析system table
let st_ptr = st_vaddr.data() as *const uefi_raw::table::system::SystemTable;
efi_manager()
.check_system_table_header(unsafe { &st_ptr.as_ref().unwrap().header }, 2)
.map_err(|e| {
err_unmap_systable(st_vaddr);
e
})?;
kdebug!("parse ok!");
let mut inner_write_guard = efi_manager().inner.write();
let st_ref = unsafe { st_ptr.as_ref().unwrap() };
inner_write_guard.runtime_paddr = Some(PhysAddr::new(st_ref.runtime_services as usize));
inner_write_guard.runtime_service_version = Some(st_ref.header.revision);
kdebug!(
"runtime service paddr: {:?}",
inner_write_guard.runtime_paddr.unwrap()
);
kdebug!(
"runtime service version: {}",
inner_write_guard.runtime_service_version.unwrap()
);
unimplemented!("report header");
// return Ok(());
}

View File

@ -0,0 +1,100 @@
use system_error::SystemError;
use crate::{
driver::firmware::efi::EFIInitFlags,
libs::align::page_align_down,
mm::{early_ioremap::EarlyIoRemap, PhysAddr, VirtAddr},
};
use super::{fdt::EFIFdtParams, EFIManager};
#[derive(Debug)]
pub struct EFIMemoryMapInfo {
/// EFI Memory Map的物理地址
pub(super) paddr: Option<PhysAddr>,
/// EFI Memory Map的虚拟地址
pub(super) vaddr: Option<VirtAddr>,
/// EFI Memory Map的大小
pub(super) size: usize,
/// 映射的描述信息的数量
pub(super) nr_map: usize,
/// EFI Memory Map的描述信息的大小
pub(super) desc_size: usize,
/// EFI Memory Map的描述信息的版本
pub(super) desc_version: usize,
}
impl EFIMemoryMapInfo {
pub const DEFAULT: Self = EFIMemoryMapInfo {
paddr: None,
vaddr: None,
size: 0,
nr_map: 0,
desc_size: 0,
desc_version: 0,
};
/// 获取EFI Memory Map的虚拟的结束地址
#[allow(dead_code)]
pub fn map_end_vaddr(&self) -> Option<VirtAddr> {
return self.vaddr.map(|v| v + self.size);
}
}
impl EFIManager {
/// Map the EFI memory map data structure
///
/// 进入当前函数前不应持有efi_manager.inner的锁
#[inline(never)]
pub(super) fn memmap_init_early(&self, data: &EFIFdtParams) -> Result<(), SystemError> {
return self.do_efi_memmap_init(data, true);
}
/// 映射 EFI memory map
///
/// 该函数在内核启动过程中使用
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/memmap.c?fi=efi_memmap_init_early#104
#[inline(never)]
fn do_efi_memmap_init(&self, data: &EFIFdtParams, early: bool) -> Result<(), SystemError> {
let paddr = data.mmap_base.expect("mmap_base is not set");
let paddr = PhysAddr::new(paddr as usize);
kdebug!("do_efi_memmap_init: paddr={paddr:?}");
let mut inner_guard = self.inner.write();
if early {
let offset = paddr.data() - page_align_down(paddr.data());
let map_size = data.mmap_size.unwrap() as usize + offset;
kdebug!("do_efi_memmap_init: map_size={map_size:#x}");
// 映射内存
let mut vaddr = EarlyIoRemap::map(
PhysAddr::new(page_align_down(paddr.data())),
map_size,
false,
)
.map(|(vaddr, _)| vaddr)?;
vaddr += offset;
inner_guard.mmap.vaddr = Some(vaddr);
} else {
unimplemented!("efi_memmap_init_late")
}
if inner_guard.mmap.vaddr.is_none() {
kerror!("Cannot map the EFI memory map!");
return Err(SystemError::ENOMEM);
}
inner_guard.mmap.paddr = Some(paddr);
inner_guard.mmap.size = data.mmap_size.unwrap() as usize;
inner_guard.mmap.nr_map =
data.mmap_size.unwrap() as usize / data.mmap_desc_size.unwrap() as usize;
inner_guard.mmap.desc_size = data.mmap_desc_size.unwrap() as usize;
inner_guard.mmap.desc_version = data.mmap_desc_version.unwrap() as usize;
inner_guard.init_flags.set(EFIInitFlags::MEMMAP, true);
return Ok(());
}
}

View File

@ -0,0 +1,115 @@
use system_error::SystemError;
use crate::{libs::rwlock::RwLock, mm::PhysAddr};
use self::memmap::EFIMemoryMapInfo;
mod fdt;
pub mod init;
pub mod memmap;
static EFI_MANAGER: EFIManager = EFIManager::new();
/// EFI管理器
///
/// 数据成员可参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/efi.h#620
#[derive(Debug)]
pub struct EFIManager {
inner: RwLock<InnerEFIManager>,
}
#[inline(always)]
pub fn efi_manager() -> &'static EFIManager {
&EFI_MANAGER
}
#[derive(Debug)]
struct InnerEFIManager {
pub mmap: EFIMemoryMapInfo,
/// EFI模块启动时状态的标识
pub init_flags: EFIInitFlags,
/// runtime services的物理地址
pub runtime_paddr: Option<PhysAddr>,
/// runtime services的版本号
pub runtime_service_version: Option<uefi_raw::table::Revision>,
}
impl EFIManager {
const fn new() -> Self {
EFIManager {
inner: RwLock::new(InnerEFIManager {
mmap: EFIMemoryMapInfo::DEFAULT,
init_flags: EFIInitFlags::empty(),
runtime_paddr: None,
runtime_service_version: None,
}),
}
}
pub fn desc_version(&self) -> usize {
return self.inner.read().mmap.desc_version;
}
/// 检查是否为有效的system table表头
///
/// ## 参数
///
/// - header: system table表头
/// - min_major: 最小的major版本号。如果不满足则会输出Warning并返回Ok
///
/// ## 返回
///
/// - Ok(()): 检查通过
/// - Err(SystemError::EINVAL): header无效
pub fn check_system_table_header(
&self,
header: &uefi_raw::table::Header,
min_major: u16,
) -> Result<(), SystemError> {
if header.signature != uefi_raw::table::system::SystemTable::SIGNATURE {
kerror!("System table signature mismatch!");
return Err(SystemError::EINVAL);
}
if header.revision.major() < min_major {
kwarn!(
"System table version: {:?}, expected {}.00 or greater!",
header.revision,
min_major
);
}
return Ok(());
}
}
// 在Rust中我们使用枚举和bitflags来表示这些宏
bitflags! {
pub struct EFIInitFlags: u32 {
/// 当前使用EFI启动
const BOOT = 1 << 0;
/// 是否可以使用EFI配置表
const CONFIG_TABLES = 1 << 1;
/// 是否可以使用运行时服务
const RUNTIME_SERVICES = 1 << 2;
/// 是否可以使用EFI内存映射
const MEMMAP = 1 << 3;
/// 固件是否为64位
const EFI_64BIT = 1 << 4;
/// 访问是否通过虚拟化接口
const PARAVIRT = 1 << 5;
/// 第一架构特定位
const ARCH_1 = 1 << 6;
/// 打印附加运行时调试信息
const DBG = 1 << 7;
/// 是否可以在运行时数据区域映射非可执行
const NX_PE_DATA = 1 << 8;
/// 固件是否发布了一个EFI_MEMORY_ATTRIBUTES表
const MEM_ATTR = 1 << 9;
/// 内核是否配置为忽略软保留
const MEM_NO_SOFT_RESERVE = 1 << 10;
/// 是否可以使用EFI引导服务内存段
const PRESERVE_BS_REGIONS = 1 << 11;
}
}

View File

@ -0,0 +1 @@
pub mod efi;

View File

@ -1,6 +1,7 @@
pub mod acpi;
pub mod base;
pub mod disk;
pub mod firmware;
pub mod input;
pub mod keyboard;
pub mod net;

View File

@ -10,7 +10,7 @@ use crate::{
libs::{align::page_align_down, rwlock::RwLock},
mm::{
memblock::{mem_block_manager, MemBlockManager},
MemoryManagementArch, PhysAddr, VirtAddr,
MemoryManagementArch, PhysAddr,
},
};
@ -42,13 +42,11 @@ impl FdtGlobalData {
}
}
static mut FDT_VADDR: Option<VirtAddr> = None;
pub struct OpenFirmwareFdtDriver;
impl OpenFirmwareFdtDriver {
pub fn early_scan_device_tree(&self) -> Result<(), SystemError> {
let fdt_vaddr = unsafe { FDT_VADDR.ok_or(SystemError::EINVAL)? };
let fdt_vaddr = boot_params().read().fdt().unwrap();
let fdt = unsafe {
fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| {
kerror!("failed to parse fdt, err={:?}", e);
@ -281,20 +279,4 @@ impl OpenFirmwareFdtDriver {
return false;
}
pub unsafe fn set_fdt_vaddr(&self, vaddr: VirtAddr) -> Result<(), SystemError> {
if vaddr.is_null() {
return Err(SystemError::EINVAL);
}
fdt::Fdt::from_ptr(vaddr.as_ptr()).map_err(|e| {
kerror!("failed to parse fdt, err={:?}", e);
SystemError::EINVAL
})?;
unsafe {
FDT_VADDR = Some(vaddr);
}
Ok(())
}
}

View File

@ -1,2 +1,3 @@
pub mod base;
#[cfg(target_arch = "x86_64")]
pub mod vesafb;

View File

@ -7,6 +7,7 @@ use crate::{
video::{fbdev::base::BootTimeScreenInfo, VideoRefreshManager},
},
libs::{lib_ui::screen_manager::scm_init, rwlock::RwLock},
mm::VirtAddr,
};
mod c_adapter;
@ -27,6 +28,7 @@ fn init_intertrait() {
}
/// 在内存管理初始化之前,执行的初始化
#[inline(never)]
pub fn init_before_mem_init() {
tty_early_init().expect("tty early init failed");
let video_ok = unsafe { VideoRefreshManager::video_init().is_ok() };
@ -99,4 +101,14 @@ impl BootParams {
self.boot_command_line[pos + len] = 0;
}
/// 获取FDT的物理地址
#[allow(dead_code)]
pub fn fdt(&self) -> Option<VirtAddr> {
#[cfg(target_arch = "riscv64")]
return Some(self.arch.arch_fdt());
#[cfg(target_arch = "x86_64")]
return None;
}
}

View File

@ -74,6 +74,8 @@ extern crate intertrait;
extern crate x86;
extern crate klog_types;
extern crate uefi;
extern crate uefi_raw;
use crate::mm::allocator::kernel_allocator::KernelAllocator;

View File

@ -23,6 +23,16 @@ impl PhysPageFrame {
};
}
/// 从物理页号创建PhysPageFrame结构体
pub fn from_ppn(ppn: usize) -> Self {
return Self { number: ppn };
}
/// 获取当前页对应的物理页号
pub fn ppn(&self) -> usize {
return self.number;
}
/// @brief 获取当前页对应的物理地址
pub fn phys_address(&self) -> PhysAddr {
return PhysAddr::new(self.number * MMArch::PAGE_SIZE);
@ -87,6 +97,12 @@ impl VirtPageFrame {
};
}
/// 从虚拟页号创建PhysPageFrame结构体
#[allow(dead_code)]
pub fn from_vpn(vpn: usize) -> Self {
return Self { number: vpn };
}
/// 获取当前虚拟页对应的虚拟地址
pub fn virt_address(&self) -> VirtAddr {
return VirtAddr::new(self.number * MMArch::PAGE_SIZE);

View File

@ -3,7 +3,7 @@ use system_error::SystemError;
use crate::{
arch::MMArch,
libs::{align::page_align_up, spinlock::SpinLock},
mm::no_init::{pseudo_map_phys, pseudo_unmap_phys},
mm::no_init::{pseudo_map_phys, pseudo_map_phys_ro, pseudo_unmap_phys},
};
use super::{allocator::page_frame::PageFrameCount, MemoryManagementArch, PhysAddr, VirtAddr};
@ -34,6 +34,7 @@ impl EarlyIoRemap {
///
/// - phys: 物理内存地址(需要按页对齐)
/// - size: 映射的内存大小
/// - read_only: 映射区与是否只读
///
/// ## 返回值
///
@ -41,11 +42,17 @@ impl EarlyIoRemap {
/// - Err(SystemError::ENOMEM): 可用的slot不足
/// - Err(SystemError::EINVAL): 传入的物理地址没有对齐
#[allow(dead_code)]
pub fn map(phys: PhysAddr, size: usize) -> Result<(VirtAddr, usize), SystemError> {
pub fn map(
phys: PhysAddr,
size: usize,
read_only: bool,
) -> Result<(VirtAddr, usize), SystemError> {
if phys.check_aligned(MMArch::PAGE_SIZE) == false {
return Err(SystemError::EINVAL);
}
// kdebug!("Early io remap:{phys:?}, size:{size}");
let mut slot_guard = SLOTS.lock();
let slot_count = PageFrameCount::from_bytes(page_align_up(size))
@ -72,8 +79,17 @@ impl EarlyIoRemap {
let start_slot = start_slot.ok_or(SystemError::ENOMEM)?;
let vaddr = Self::idx_to_virt(start_slot);
// kdebug!("start_slot:{start_slot}, vaddr: {vaddr:?}, slot_count: {slot_count:?}");
let page_count = PageFrameCount::new(slot_count);
// 执行映射
unsafe { pseudo_map_phys(vaddr, phys, PageFrameCount::new(slot_count)) }
if read_only {
unsafe { pseudo_map_phys_ro(vaddr, phys, page_count) }
} else {
unsafe { pseudo_map_phys(vaddr, phys, page_count) }
}
// kdebug!("map ok");
// 更新slot信息
let map_size = slot_count * MMArch::PAGE_SIZE;
@ -141,7 +157,7 @@ impl EarlyIoRemap {
*slot = Slot::DEFAULT;
}
todo!()
return Ok(());
}
/// 把slot下标转换为这个slot对应的虚拟地址

View File

@ -76,7 +76,8 @@ pub enum PageTableKind {
User,
/// 内核页表
Kernel,
/// 内存虚拟化中使用的EPT
/// x86内存虚拟化中使用的EPT
#[cfg(target_arch = "x86_64")]
EPT,
}
@ -511,6 +512,20 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
/// 初始化新的usermapper为用户进程创建页表
fn setup_new_usermapper() -> Result<UserMapper, SystemError>;
/// 创建页表项
///
/// 这是一个低阶api用于根据物理地址以及指定好的pageflags创建页表项
///
/// ## 参数
///
/// - `paddr` 物理地址
/// - `page_flags` 页表项的flags
///
/// ## 返回值
///
/// 页表项的值
fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize;
}
/// @brief 虚拟地址范围

View File

@ -24,7 +24,8 @@ use super::{
};
/// 用于存储重映射页表的位图和页面
static EARLY_IOREMAP_PAGES: SpinLock<EarlyIoRemapPages> = SpinLock::new(EarlyIoRemapPages::new());
pub static EARLY_IOREMAP_PAGES: SpinLock<EarlyIoRemapPages> =
SpinLock::new(EarlyIoRemapPages::new());
/// 早期重映射使用的页表
#[repr(C)]
@ -42,7 +43,7 @@ impl EarlyRemapPage {
}
#[repr(C)]
struct EarlyIoRemapPages {
pub struct EarlyIoRemapPages {
pages: [EarlyRemapPage; Self::EARLY_REMAP_PAGES_NUM],
bmp: StaticBitmap<{ Self::EARLY_REMAP_PAGES_NUM }>,
}
@ -110,12 +111,14 @@ impl<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> {
assert!(count.data() == 1);
let vaddr = EARLY_IOREMAP_PAGES.lock_irqsave().allocate_page()?;
let paddr = MMA::virt_2_phys(vaddr)?;
kdebug!("allocate page: vaddr={:?}, paddr={:?}", vaddr, paddr);
return Some((paddr, count));
}
unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount) {
assert_eq!(count.data(), 1);
assert!(address.check_aligned(MMA::PAGE_SIZE));
kdebug!("free page: paddr={:?}", address);
let vaddr = MMA::phys_2_virt(address);
if let Some(vaddr) = vaddr {
EARLY_IOREMAP_PAGES.lock_irqsave().free_page(vaddr);
@ -139,6 +142,27 @@ 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);
pseudo_map_phys_with_flags(vaddr, paddr, count, flags);
}
/// Use pseudo mapper to map physical memory to virtual memory
/// with READ_ONLY and EXECUTE flags.
#[inline(never)]
pub unsafe fn pseudo_map_phys_ro(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) {
let flags: PageFlags<MMArch> = PageFlags::new().set_write(false).set_execute(true);
pseudo_map_phys_with_flags(vaddr, paddr, count, flags);
}
#[inline(never)]
pub unsafe fn pseudo_map_phys_with_flags(
vaddr: VirtAddr,
paddr: PhysAddr,
count: PageFrameCount,
flags: PageFlags<MMArch>,
) {
assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
assert!(paddr.check_aligned(MMArch::PAGE_SIZE));
@ -150,12 +174,11 @@ pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrame
&mut pseudo_allocator,
);
let flags: PageFlags<MMArch> = PageFlags::new().set_write(true).set_execute(true);
for i in 0..count.data() {
let vaddr = vaddr + i * MMArch::PAGE_SIZE;
let paddr = paddr + i * MMArch::PAGE_SIZE;
let flusher = mapper.map_phys(vaddr, paddr, flags).unwrap();
let flusher: crate::mm::page::PageFlush<MMArch> =
mapper.map_phys(vaddr, paddr, flags).unwrap();
flusher.ignore();
}

View File

@ -102,7 +102,7 @@ impl<Arch: MemoryManagementArch> PageTable<Arch> {
/// 获取当前页表的第i个页表项
pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<Arch>> {
let entry_virt = self.entry_virt(i)?;
return Some(PageEntry::new(Arch::read::<usize>(entry_virt)));
return Some(PageEntry::from_usize(Arch::read::<usize>(entry_virt)));
}
/// 设置当前页表的第i个页表项
@ -178,7 +178,14 @@ impl<Arch> Debug for PageEntry<Arch> {
impl<Arch: MemoryManagementArch> PageEntry<Arch> {
#[inline(always)]
pub fn new(data: usize) -> Self {
pub fn new(paddr: PhysAddr, flags: PageFlags<Arch>) -> Self {
Self {
data: MMArch::make_entry(paddr, flags.data()),
phantom: PhantomData,
}
}
#[inline(always)]
pub fn from_usize(data: usize) -> Self {
Self {
data,
phantom: PhantomData,
@ -198,7 +205,18 @@ impl<Arch: MemoryManagementArch> PageEntry<Arch> {
/// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址
#[inline(always)]
pub fn address(&self) -> Result<PhysAddr, PhysAddr> {
let paddr = PhysAddr::new(self.data & Arch::PAGE_ADDRESS_MASK);
let paddr: PhysAddr = {
#[cfg(target_arch = "x86_64")]
{
PhysAddr::new(self.data & Arch::PAGE_ADDRESS_MASK)
}
#[cfg(target_arch = "riscv64")]
{
let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 44) - 1);
super::allocator::page_frame::PhysPageFrame::from_ppn(ppn).phys_address()
}
};
if self.present() {
Ok(paddr)
@ -290,7 +308,18 @@ impl<Arch: MemoryManagementArch> PageFlags<Arch> {
#[inline(always)]
pub fn new_page_table(user: bool) -> Self {
return unsafe {
let r = Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE);
let r = {
#[cfg(target_arch = "x86_64")]
{
Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE)
}
#[cfg(target_arch = "riscv64")]
{
// riscv64指向下一级页表的页表项不应设置R/W/X权限位
Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE)
}
};
if user {
r.set_user(true)
} else {
@ -355,12 +384,24 @@ impl<Arch: MemoryManagementArch> PageFlags<Arch> {
#[must_use]
#[inline(always)]
pub fn set_write(self, value: bool) -> Self {
#[cfg(target_arch = "x86_64")]
{
// 有的架构同时具有可写和不可写的标志位,因此需要同时更新
return self
.update_flags(Arch::ENTRY_FLAG_READONLY, !value)
.update_flags(Arch::ENTRY_FLAG_READWRITE, value);
}
#[cfg(target_arch = "riscv64")]
{
if value {
return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true);
} else {
return self.update_flags(Arch::ENTRY_FLAG_READONLY, true);
}
}
}
/// 当前页表项是否可写
#[inline(always)]
pub fn has_write(&self) -> bool {
@ -569,12 +610,13 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
);
return None;
}
let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK));
// TODO 验证flags是否合法
// 创建页表项
let entry = PageEntry::new(phys.data() | flags.data());
let entry = PageEntry::new(phys, flags);
let mut table = self.table();
loop {
let i = table.index_of(virt)?;
@ -585,8 +627,9 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
if table.entry_mapped(i)? == true {
kwarn!("Page {:?} already mapped", virt);
}
// kdebug!("Mapping {:?} to {:?}, i = {i}, entry={:?}, flags={:?}", virt, phys, entry, flags);
compiler_fence(Ordering::SeqCst);
table.set_entry(i, entry);
compiler_fence(Ordering::SeqCst);
return Some(PageFlush::new(virt));
@ -596,27 +639,20 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
table = next_table;
// kdebug!("Mapping {:?} to next level table...", virt);
} else {
// kdebug!("Allocating next level table for {:?}..., i={i}", virt);
// 分配下一级页表
let frame = self.frame_allocator.allocate_one()?;
// 清空这个页帧
MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
// 设置页表项的flags
// let flags = Arch::ENTRY_FLAG_READWRITE
// | Arch::ENTRY_FLAG_DEFAULT_TABLE
// | if virt.kind() == PageTableKind::User {
// Arch::ENTRY_FLAG_USER
// } else {
// 0
// };
let flags: PageFlags<MMArch> =
let flags: PageFlags<Arch> =
PageFlags::new_page_table(virt.kind() == PageTableKind::User);
// kdebug!("Flags: {:?}", flags);
// 把新分配的页表映射到当前页表
table.set_entry(i, PageEntry::new(frame.data() | flags.data()));
table.set_entry(i, PageEntry::new(frame, flags));
// 获取新分配的页表
table = table.next_level_table(i)?;
@ -765,7 +801,7 @@ unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>(
// 如果当前是最后一级页表,直接取消页面映射
if table.level() == 0 {
let entry = table.entry(i)?;
table.set_entry(i, PageEntry::new(0));
table.set_entry(i, PageEntry::from_usize(0));
return Some((entry.address().ok()?, entry.flags()));
}
@ -784,7 +820,7 @@ unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>(
.any(|e| e.present());
if !x {
// 如果没有,就取消子页表的映射
table.set_entry(i, PageEntry::new(0));
table.set_entry(i, PageEntry::from_usize(0));
// 释放子页表
allocator.free_one(subtable.phys());
}

@ -1 +1 @@
Subproject commit 7fc3806da73be059540a79b6fdddf8049be250f3
Subproject commit 773f7fd31fb85ce22f0fc442fd2c13a8d0602a8c

View File

@ -12,6 +12,6 @@ ratatui = "0.24.0"
clap = { version = "4.4.7", features = ["color", "error-context", "help", "std", "suggestions", "usage", "derive"] }
rand = "0.8.5"
goblin = "0.7.1"
simple_logger = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/rust-simple_logger.git", "rev" = "36ab404868" }
simple_logger = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/rust-simple_logger.git", "rev" = "36ab404868" }
log = "0.4.20"
lazy_static = "1.4.0"