mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
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:
parent
3e3c6316aa
commit
7a29d4fcbc
@ -46,6 +46,9 @@ system_error = { path = "crates/system_error" }
|
|||||||
unified-init = { path = "crates/unified-init" }
|
unified-init = { path = "crates/unified-init" }
|
||||||
virtio-drivers = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/virtio-drivers.git", rev = "f1d1cbb" }
|
virtio-drivers = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/virtio-drivers.git", rev = "f1d1cbb" }
|
||||||
fdt = "0.1.5"
|
fdt = "0.1.5"
|
||||||
|
uefi = { version = "0.26.0", features = ["alloc"] }
|
||||||
|
uefi-raw = "0.5.0"
|
||||||
|
|
||||||
|
|
||||||
# target为x86_64时,使用下面的依赖
|
# target为x86_64时,使用下面的依赖
|
||||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||||
@ -56,7 +59,7 @@ x86_64 = "0.14.10"
|
|||||||
|
|
||||||
# target为riscv64时,使用下面的依赖
|
# target为riscv64时,使用下面的依赖
|
||||||
[target.'cfg(target_arch = "riscv64")'.dependencies]
|
[target.'cfg(target_arch = "riscv64")'.dependencies]
|
||||||
|
riscv = { version = "0.11.0", features = [ "s-mode" ] }
|
||||||
|
|
||||||
|
|
||||||
# 构建时依赖项
|
# 构建时依赖项
|
||||||
|
@ -12,7 +12,7 @@ crc = { path = "../crc" }
|
|||||||
|
|
||||||
# 一个无锁MPSC队列
|
# 一个无锁MPSC队列
|
||||||
[dependencies.thingbuf]
|
[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"
|
rev = "2dded730c3"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["alloc", "static"]
|
features = ["alloc", "static"]
|
||||||
|
@ -7,6 +7,6 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
kdepends = { path = "../kdepends" }
|
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 = { version = "0.4.0", default-features = false }
|
||||||
num-derive = "0.3"
|
num-derive = "0.3"
|
@ -17,9 +17,9 @@ ifeq ($(UNWIND_ENABLE), yes)
|
|||||||
CFLAGS_UNWIND = -funwind-tables
|
CFLAGS_UNWIND = -funwind-tables
|
||||||
ifeq ($(ARCH), x86_64)
|
ifeq ($(ARCH), x86_64)
|
||||||
LDFLAGS_UNWIND = --eh-frame-hdr
|
LDFLAGS_UNWIND = --eh-frame-hdr
|
||||||
endif
|
|
||||||
RUSTFLAGS_UNWIND = -Cforce-unwind-tables -Clink-arg=-Wl,eh_frame.ld
|
RUSTFLAGS_UNWIND = -Cforce-unwind-tables -Clink-arg=-Wl,eh_frame.ld
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
RUSTFLAGS = $(RUSTFLAGS_UNWIND)
|
RUSTFLAGS = $(RUSTFLAGS_UNWIND)
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ __init_set_pgtable_loop_end:
|
|||||||
|
|
||||||
la a0, BSP_IDLE_STACK_SPACE
|
la a0, BSP_IDLE_STACK_SPACE
|
||||||
mv sp, a0
|
mv sp, a0
|
||||||
li t0, 32768
|
li t0, 32752 // 预留16字节防止越界
|
||||||
add sp, sp, t0
|
add sp, sp, t0
|
||||||
.option pop
|
.option pop
|
||||||
/*
|
/*
|
||||||
@ -330,6 +330,7 @@ __initial_hartid_ptr:
|
|||||||
.quad 0
|
.quad 0
|
||||||
|
|
||||||
// _start标签在启动时被加载到的物理地址
|
// _start标签在启动时被加载到的物理地址
|
||||||
|
.global __initial_start_load_paddr
|
||||||
__initial_start_load_paddr:
|
__initial_start_load_paddr:
|
||||||
.quad 0
|
.quad 0
|
||||||
|
|
||||||
@ -344,9 +345,11 @@ __initial_satp_mode:
|
|||||||
|
|
||||||
// 初始页表的空间(sv39模式的L0页表)
|
// 初始页表的空间(sv39模式的L0页表)
|
||||||
.section .initial_pgtable_section
|
.section .initial_pgtable_section
|
||||||
|
.global __initial_pgtable
|
||||||
__initial_pgtable:
|
__initial_pgtable:
|
||||||
.skip 4096
|
.skip 4096
|
||||||
|
|
||||||
|
.global __initial_l1_pgtable
|
||||||
__initial_l1_pgtable:
|
__initial_l1_pgtable:
|
||||||
.skip 8192
|
.skip 8192
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
use crate::{
|
#![allow(dead_code)]
|
||||||
arch::driver::sbi::ecall::{ecall0, ecall1},
|
use crate::{arch::driver::sbi::ecall::ecall1, mm::VirtAddr};
|
||||||
mm::VirtAddr,
|
|
||||||
};
|
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
|
|
||||||
/// `sbi_set_timer` extension ID
|
/// `sbi_set_timer` extension ID
|
||||||
|
@ -3,10 +3,14 @@ use core::intrinsics::unreachable;
|
|||||||
use fdt::node::FdtNode;
|
use fdt::node::FdtNode;
|
||||||
|
|
||||||
use crate::{
|
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},
|
init::{boot_params, init_before_mem_init},
|
||||||
kinfo,
|
kdebug, kinfo,
|
||||||
mm::{PhysAddr, VirtAddr},
|
mm::{MemoryManagementArch, PhysAddr, VirtAddr},
|
||||||
print, println,
|
print, println,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -14,18 +18,36 @@ use crate::{
|
|||||||
pub struct ArchBootParams {
|
pub struct ArchBootParams {
|
||||||
/// 启动时的fdt物理地址
|
/// 启动时的fdt物理地址
|
||||||
pub fdt_paddr: PhysAddr,
|
pub fdt_paddr: PhysAddr,
|
||||||
|
pub fdt_vaddr: Option<VirtAddr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArchBootParams {
|
impl ArchBootParams {
|
||||||
pub const DEFAULT: Self = ArchBootParams {
|
pub const DEFAULT: Self = ArchBootParams {
|
||||||
fdt_paddr: PhysAddr::new(0),
|
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]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
|
unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
|
||||||
let fdt_paddr = PhysAddr::new(fdt_paddr);
|
let fdt_paddr = PhysAddr::new(fdt_paddr);
|
||||||
|
|
||||||
init_before_mem_init();
|
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;
|
boot_params().write().arch.fdt_paddr = fdt_paddr;
|
||||||
kinfo!(
|
kinfo!(
|
||||||
"DragonOS kernel is running on hart {}, fdt address:{:?}",
|
"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
|
fdt_paddr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
efi_init();
|
||||||
|
|
||||||
loop {}
|
loop {}
|
||||||
unreachable()
|
unreachable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
fn print_node(node: FdtNode<'_, '_>, n_spaces: usize) {
|
fn print_node(node: FdtNode<'_, '_>, n_spaces: usize) {
|
||||||
(0..n_spaces).for_each(|_| print!(" "));
|
(0..n_spaces).for_each(|_| print!(" "));
|
||||||
println!("{}/", node.name);
|
println!("{}/", node.name);
|
||||||
@ -56,15 +83,13 @@ fn print_node(node: FdtNode<'_, '_>, n_spaces: usize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 解析fdt,获取内核启动参数
|
/// 解析fdt,获取内核启动参数
|
||||||
|
#[inline(never)]
|
||||||
unsafe fn parse_dtb() {
|
unsafe fn parse_dtb() {
|
||||||
let fdt_paddr = boot_params().read().arch.fdt_paddr;
|
let fdt_paddr = boot_params().read().arch.fdt_paddr;
|
||||||
if fdt_paddr.is_null() {
|
if fdt_paddr.is_null() {
|
||||||
panic!("Failed to get fdt address!");
|
panic!("Failed to get fdt address!");
|
||||||
}
|
}
|
||||||
|
|
||||||
open_firmware_fdt_driver()
|
|
||||||
.set_fdt_vaddr(VirtAddr::new(fdt_paddr.data()))
|
|
||||||
.unwrap();
|
|
||||||
open_firmware_fdt_driver()
|
open_firmware_fdt_driver()
|
||||||
.early_scan_device_tree()
|
.early_scan_device_tree()
|
||||||
.expect("Failed to scan device tree at boottime.");
|
.expect("Failed to scan device tree at boottime.");
|
||||||
|
@ -6,23 +6,29 @@ pub struct RiscV64InterruptArch;
|
|||||||
|
|
||||||
impl InterruptArch for RiscV64InterruptArch {
|
impl InterruptArch for RiscV64InterruptArch {
|
||||||
unsafe fn interrupt_enable() {
|
unsafe fn interrupt_enable() {
|
||||||
unimplemented!("RiscV64InterruptArch::interrupt_enable")
|
riscv::interrupt::enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn interrupt_disable() {
|
unsafe fn interrupt_disable() {
|
||||||
unimplemented!("RiscV64InterruptArch::interrupt_disable")
|
riscv::interrupt::disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_irq_enabled() -> bool {
|
fn is_irq_enabled() -> bool {
|
||||||
unimplemented!("RiscV64InterruptArch::is_irq_enabled")
|
riscv::register::sstatus::read().sie()
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn save_and_disable_irq() -> IrqFlagsGuard {
|
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) {
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +76,8 @@ SECTIONS
|
|||||||
_bss = .;
|
_bss = .;
|
||||||
*(.bss)
|
*(.bss)
|
||||||
*(.bss.*)
|
*(.bss.*)
|
||||||
|
*(.sbss)
|
||||||
|
*(.sbss.*)
|
||||||
_ebss = .;
|
_ebss = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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:?}
|
||||||
|
"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
|
use riscv::register::satp;
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::mm::{
|
use crate::{
|
||||||
allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage},
|
kdebug,
|
||||||
|
mm::{
|
||||||
|
allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
|
||||||
page::PageFlags,
|
page::PageFlags,
|
||||||
MemoryManagementArch, PhysAddr, VirtAddr,
|
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod bump;
|
pub mod bump;
|
||||||
@ -11,6 +15,15 @@ pub(super) mod init;
|
|||||||
|
|
||||||
pub type PageMapper = crate::mm::page::PageMapper<RiscV64MMArch, LockedFrameAllocator>;
|
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)
|
/// RiscV64的内存管理架构结构体(sv39)
|
||||||
#[derive(Debug, Clone, Copy, Hash)]
|
#[derive(Debug, Clone, Copy, Hash)]
|
||||||
pub struct RiscV64MMArch;
|
pub struct RiscV64MMArch;
|
||||||
@ -62,24 +75,34 @@ impl MemoryManagementArch for RiscV64MMArch {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn invalidate_page(address: crate::mm::VirtAddr) {
|
unsafe fn invalidate_page(address: VirtAddr) {
|
||||||
todo!()
|
riscv::asm::sfence_vma(0, address.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn invalidate_all() {
|
unsafe fn invalidate_all() {
|
||||||
todo!()
|
riscv::asm::sfence_vma_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn table(table_kind: crate::mm::PageTableKind) -> crate::mm::PhysAddr {
|
unsafe fn table(_table_kind: PageTableKind) -> PhysAddr {
|
||||||
todo!()
|
// 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) {
|
unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) {
|
||||||
todo!()
|
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 {
|
fn virt_is_valid(virt: crate::mm::VirtAddr) -> bool {
|
||||||
todo!()
|
virt.is_canonical()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initial_page_table() -> crate::mm::PhysAddr {
|
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> {
|
fn setup_new_usermapper() -> Result<crate::mm::ucontext::UserMapper, SystemError> {
|
||||||
todo!()
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取内核地址默认的页面标志
|
/// 获取内核地址默认的页面标志
|
||||||
|
@ -284,6 +284,11 @@ impl MemoryManagementArch for X86_64MMArch {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize {
|
||||||
|
return paddr.data() | page_flags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl X86_64MMArch {
|
impl X86_64MMArch {
|
||||||
@ -334,8 +339,6 @@ impl X86_64MMArch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
total_mem_size += mb2_mem_info[i].len as usize;
|
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()
|
mem_block_manager()
|
||||||
.add_block(
|
.add_block(
|
||||||
@ -450,7 +453,7 @@ unsafe fn allocator_init() {
|
|||||||
// 取消最开始时候,在head.S中指定的映射(暂时不刷新TLB)
|
// 取消最开始时候,在head.S中指定的映射(暂时不刷新TLB)
|
||||||
{
|
{
|
||||||
let table = mapper.table();
|
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 {
|
for i in 0..MMArch::PAGE_ENTRY_NUM {
|
||||||
table
|
table
|
||||||
.set_entry(i, empty_entry)
|
.set_entry(i, empty_entry)
|
||||||
|
189
kernel/src/driver/firmware/efi/fdt.rs
Normal file
189
kernel/src/driver/firmware/efi/fdt.rs
Normal 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(());
|
||||||
|
}
|
||||||
|
}
|
129
kernel/src/driver/firmware/efi/init.rs
Normal file
129
kernel/src/driver/firmware/efi/init.rs
Normal 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(());
|
||||||
|
}
|
100
kernel/src/driver/firmware/efi/memmap.rs
Normal file
100
kernel/src/driver/firmware/efi/memmap.rs
Normal 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(());
|
||||||
|
}
|
||||||
|
}
|
115
kernel/src/driver/firmware/efi/mod.rs
Normal file
115
kernel/src/driver/firmware/efi/mod.rs
Normal 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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
1
kernel/src/driver/firmware/mod.rs
Normal file
1
kernel/src/driver/firmware/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod efi;
|
@ -1,6 +1,7 @@
|
|||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
pub mod base;
|
pub mod base;
|
||||||
pub mod disk;
|
pub mod disk;
|
||||||
|
pub mod firmware;
|
||||||
pub mod input;
|
pub mod input;
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
pub mod net;
|
pub mod net;
|
||||||
|
@ -10,7 +10,7 @@ use crate::{
|
|||||||
libs::{align::page_align_down, rwlock::RwLock},
|
libs::{align::page_align_down, rwlock::RwLock},
|
||||||
mm::{
|
mm::{
|
||||||
memblock::{mem_block_manager, MemBlockManager},
|
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;
|
pub struct OpenFirmwareFdtDriver;
|
||||||
|
|
||||||
impl OpenFirmwareFdtDriver {
|
impl OpenFirmwareFdtDriver {
|
||||||
pub fn early_scan_device_tree(&self) -> Result<(), SystemError> {
|
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 {
|
let fdt = unsafe {
|
||||||
fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| {
|
fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| {
|
||||||
kerror!("failed to parse fdt, err={:?}", e);
|
kerror!("failed to parse fdt, err={:?}", e);
|
||||||
@ -281,20 +279,4 @@ impl OpenFirmwareFdtDriver {
|
|||||||
|
|
||||||
return false;
|
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(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
pub mod base;
|
pub mod base;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub mod vesafb;
|
pub mod vesafb;
|
||||||
|
@ -7,6 +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,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod c_adapter;
|
mod c_adapter;
|
||||||
@ -27,6 +28,7 @@ fn init_intertrait() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 在内存管理初始化之前,执行的初始化
|
/// 在内存管理初始化之前,执行的初始化
|
||||||
|
#[inline(never)]
|
||||||
pub fn init_before_mem_init() {
|
pub fn init_before_mem_init() {
|
||||||
tty_early_init().expect("tty early init failed");
|
tty_early_init().expect("tty early init failed");
|
||||||
let video_ok = unsafe { VideoRefreshManager::video_init().is_ok() };
|
let video_ok = unsafe { VideoRefreshManager::video_init().is_ok() };
|
||||||
@ -99,4 +101,14 @@ impl BootParams {
|
|||||||
|
|
||||||
self.boot_command_line[pos + len] = 0;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,8 @@ extern crate intertrait;
|
|||||||
extern crate x86;
|
extern crate x86;
|
||||||
|
|
||||||
extern crate klog_types;
|
extern crate klog_types;
|
||||||
|
extern crate uefi;
|
||||||
|
extern crate uefi_raw;
|
||||||
|
|
||||||
use crate::mm::allocator::kernel_allocator::KernelAllocator;
|
use crate::mm::allocator::kernel_allocator::KernelAllocator;
|
||||||
|
|
||||||
|
@ -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 获取当前页对应的物理地址
|
/// @brief 获取当前页对应的物理地址
|
||||||
pub fn phys_address(&self) -> PhysAddr {
|
pub fn phys_address(&self) -> PhysAddr {
|
||||||
return PhysAddr::new(self.number * MMArch::PAGE_SIZE);
|
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 {
|
pub fn virt_address(&self) -> VirtAddr {
|
||||||
return VirtAddr::new(self.number * MMArch::PAGE_SIZE);
|
return VirtAddr::new(self.number * MMArch::PAGE_SIZE);
|
||||||
|
@ -3,7 +3,7 @@ use system_error::SystemError;
|
|||||||
use crate::{
|
use crate::{
|
||||||
arch::MMArch,
|
arch::MMArch,
|
||||||
libs::{align::page_align_up, spinlock::SpinLock},
|
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};
|
use super::{allocator::page_frame::PageFrameCount, MemoryManagementArch, PhysAddr, VirtAddr};
|
||||||
@ -34,6 +34,7 @@ impl EarlyIoRemap {
|
|||||||
///
|
///
|
||||||
/// - phys: 物理内存地址(需要按页对齐)
|
/// - phys: 物理内存地址(需要按页对齐)
|
||||||
/// - size: 映射的内存大小
|
/// - size: 映射的内存大小
|
||||||
|
/// - read_only: 映射区与是否只读
|
||||||
///
|
///
|
||||||
/// ## 返回值
|
/// ## 返回值
|
||||||
///
|
///
|
||||||
@ -41,11 +42,17 @@ impl EarlyIoRemap {
|
|||||||
/// - Err(SystemError::ENOMEM): 可用的slot不足
|
/// - Err(SystemError::ENOMEM): 可用的slot不足
|
||||||
/// - Err(SystemError::EINVAL): 传入的物理地址没有对齐
|
/// - Err(SystemError::EINVAL): 传入的物理地址没有对齐
|
||||||
#[allow(dead_code)]
|
#[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 {
|
if phys.check_aligned(MMArch::PAGE_SIZE) == false {
|
||||||
return Err(SystemError::EINVAL);
|
return Err(SystemError::EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// kdebug!("Early io remap:{phys:?}, size:{size}");
|
||||||
|
|
||||||
let mut slot_guard = SLOTS.lock();
|
let mut slot_guard = SLOTS.lock();
|
||||||
|
|
||||||
let slot_count = PageFrameCount::from_bytes(page_align_up(size))
|
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 start_slot = start_slot.ok_or(SystemError::ENOMEM)?;
|
||||||
let vaddr = Self::idx_to_virt(start_slot);
|
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信息
|
// 更新slot信息
|
||||||
let map_size = slot_count * MMArch::PAGE_SIZE;
|
let map_size = slot_count * MMArch::PAGE_SIZE;
|
||||||
@ -141,7 +157,7 @@ impl EarlyIoRemap {
|
|||||||
*slot = Slot::DEFAULT;
|
*slot = Slot::DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
todo!()
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 把slot下标转换为这个slot对应的虚拟地址
|
/// 把slot下标转换为这个slot对应的虚拟地址
|
||||||
|
@ -76,7 +76,8 @@ pub enum PageTableKind {
|
|||||||
User,
|
User,
|
||||||
/// 内核页表
|
/// 内核页表
|
||||||
Kernel,
|
Kernel,
|
||||||
/// 内存虚拟化中使用的EPT
|
/// x86内存虚拟化中使用的EPT
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
EPT,
|
EPT,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,6 +512,20 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
|
|||||||
|
|
||||||
/// 初始化新的usermapper,为用户进程创建页表
|
/// 初始化新的usermapper,为用户进程创建页表
|
||||||
fn setup_new_usermapper() -> Result<UserMapper, SystemError>;
|
fn setup_new_usermapper() -> Result<UserMapper, SystemError>;
|
||||||
|
|
||||||
|
/// 创建页表项
|
||||||
|
///
|
||||||
|
/// 这是一个低阶api,用于根据物理地址以及指定好的pageflags,创建页表项
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `paddr` 物理地址
|
||||||
|
/// - `page_flags` 页表项的flags
|
||||||
|
///
|
||||||
|
/// ## 返回值
|
||||||
|
///
|
||||||
|
/// 页表项的值
|
||||||
|
fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 虚拟地址范围
|
/// @brief 虚拟地址范围
|
||||||
|
@ -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)]
|
#[repr(C)]
|
||||||
@ -42,7 +43,7 @@ impl EarlyRemapPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct EarlyIoRemapPages {
|
pub struct EarlyIoRemapPages {
|
||||||
pages: [EarlyRemapPage; Self::EARLY_REMAP_PAGES_NUM],
|
pages: [EarlyRemapPage; Self::EARLY_REMAP_PAGES_NUM],
|
||||||
bmp: StaticBitmap<{ 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);
|
assert!(count.data() == 1);
|
||||||
let vaddr = EARLY_IOREMAP_PAGES.lock_irqsave().allocate_page()?;
|
let vaddr = EARLY_IOREMAP_PAGES.lock_irqsave().allocate_page()?;
|
||||||
let paddr = MMA::virt_2_phys(vaddr)?;
|
let paddr = MMA::virt_2_phys(vaddr)?;
|
||||||
|
kdebug!("allocate page: vaddr={:?}, paddr={:?}", vaddr, paddr);
|
||||||
return Some((paddr, count));
|
return Some((paddr, count));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount) {
|
unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount) {
|
||||||
assert_eq!(count.data(), 1);
|
assert_eq!(count.data(), 1);
|
||||||
assert!(address.check_aligned(MMA::PAGE_SIZE));
|
assert!(address.check_aligned(MMA::PAGE_SIZE));
|
||||||
|
kdebug!("free page: paddr={:?}", address);
|
||||||
let vaddr = MMA::phys_2_virt(address);
|
let vaddr = MMA::phys_2_virt(address);
|
||||||
if let Some(vaddr) = vaddr {
|
if let Some(vaddr) = vaddr {
|
||||||
EARLY_IOREMAP_PAGES.lock_irqsave().free_page(vaddr);
|
EARLY_IOREMAP_PAGES.lock_irqsave().free_page(vaddr);
|
||||||
@ -139,6 +142,27 @@ 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);
|
||||||
|
|
||||||
|
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!(vaddr.check_aligned(MMArch::PAGE_SIZE));
|
||||||
assert!(paddr.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,
|
&mut pseudo_allocator,
|
||||||
);
|
);
|
||||||
|
|
||||||
let flags: PageFlags<MMArch> = PageFlags::new().set_write(true).set_execute(true);
|
|
||||||
|
|
||||||
for i in 0..count.data() {
|
for i in 0..count.data() {
|
||||||
let vaddr = vaddr + i * MMArch::PAGE_SIZE;
|
let vaddr = vaddr + i * MMArch::PAGE_SIZE;
|
||||||
let paddr = paddr + 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();
|
flusher.ignore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ impl<Arch: MemoryManagementArch> PageTable<Arch> {
|
|||||||
/// 获取当前页表的第i个页表项
|
/// 获取当前页表的第i个页表项
|
||||||
pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<Arch>> {
|
pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<Arch>> {
|
||||||
let entry_virt = self.entry_virt(i)?;
|
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个页表项
|
/// 设置当前页表的第i个页表项
|
||||||
@ -178,7 +178,14 @@ impl<Arch> Debug for PageEntry<Arch> {
|
|||||||
|
|
||||||
impl<Arch: MemoryManagementArch> PageEntry<Arch> {
|
impl<Arch: MemoryManagementArch> PageEntry<Arch> {
|
||||||
#[inline(always)]
|
#[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 {
|
Self {
|
||||||
data,
|
data,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
@ -198,7 +205,18 @@ impl<Arch: MemoryManagementArch> PageEntry<Arch> {
|
|||||||
/// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址
|
/// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn address(&self) -> Result<PhysAddr, PhysAddr> {
|
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() {
|
if self.present() {
|
||||||
Ok(paddr)
|
Ok(paddr)
|
||||||
@ -290,7 +308,18 @@ impl<Arch: MemoryManagementArch> PageFlags<Arch> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn new_page_table(user: bool) -> Self {
|
pub fn new_page_table(user: bool) -> Self {
|
||||||
return unsafe {
|
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 {
|
if user {
|
||||||
r.set_user(true)
|
r.set_user(true)
|
||||||
} else {
|
} else {
|
||||||
@ -355,12 +384,24 @@ impl<Arch: MemoryManagementArch> PageFlags<Arch> {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_write(self, value: bool) -> Self {
|
pub fn set_write(self, value: bool) -> Self {
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
{
|
||||||
// 有的架构同时具有可写和不可写的标志位,因此需要同时更新
|
// 有的架构同时具有可写和不可写的标志位,因此需要同时更新
|
||||||
return self
|
return self
|
||||||
.update_flags(Arch::ENTRY_FLAG_READONLY, !value)
|
.update_flags(Arch::ENTRY_FLAG_READONLY, !value)
|
||||||
.update_flags(Arch::ENTRY_FLAG_READWRITE, 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)]
|
#[inline(always)]
|
||||||
pub fn has_write(&self) -> bool {
|
pub fn has_write(&self) -> bool {
|
||||||
@ -569,12 +610,13 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
|||||||
);
|
);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK));
|
let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK));
|
||||||
|
|
||||||
// TODO: 验证flags是否合法
|
// TODO: 验证flags是否合法
|
||||||
|
|
||||||
// 创建页表项
|
// 创建页表项
|
||||||
let entry = PageEntry::new(phys.data() | flags.data());
|
let entry = PageEntry::new(phys, flags);
|
||||||
let mut table = self.table();
|
let mut table = self.table();
|
||||||
loop {
|
loop {
|
||||||
let i = table.index_of(virt)?;
|
let i = table.index_of(virt)?;
|
||||||
@ -585,8 +627,9 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
|||||||
if table.entry_mapped(i)? == true {
|
if table.entry_mapped(i)? == true {
|
||||||
kwarn!("Page {:?} already mapped", virt);
|
kwarn!("Page {:?} already mapped", virt);
|
||||||
}
|
}
|
||||||
// kdebug!("Mapping {:?} to {:?}, i = {i}, entry={:?}, flags={:?}", virt, phys, entry, flags);
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
table.set_entry(i, entry);
|
table.set_entry(i, entry);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
return Some(PageFlush::new(virt));
|
return Some(PageFlush::new(virt));
|
||||||
@ -596,27 +639,20 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
|||||||
table = next_table;
|
table = next_table;
|
||||||
// kdebug!("Mapping {:?} to next level table...", virt);
|
// kdebug!("Mapping {:?} to next level table...", virt);
|
||||||
} else {
|
} else {
|
||||||
// kdebug!("Allocating next level table for {:?}..., i={i}", virt);
|
|
||||||
// 分配下一级页表
|
// 分配下一级页表
|
||||||
let frame = self.frame_allocator.allocate_one()?;
|
let frame = self.frame_allocator.allocate_one()?;
|
||||||
|
|
||||||
// 清空这个页帧
|
// 清空这个页帧
|
||||||
MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
|
MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
|
||||||
|
|
||||||
// 设置页表项的flags
|
// 设置页表项的flags
|
||||||
// let flags = Arch::ENTRY_FLAG_READWRITE
|
let flags: PageFlags<Arch> =
|
||||||
// | Arch::ENTRY_FLAG_DEFAULT_TABLE
|
|
||||||
// | if virt.kind() == PageTableKind::User {
|
|
||||||
// Arch::ENTRY_FLAG_USER
|
|
||||||
// } else {
|
|
||||||
// 0
|
|
||||||
// };
|
|
||||||
let flags: PageFlags<MMArch> =
|
|
||||||
PageFlags::new_page_table(virt.kind() == PageTableKind::User);
|
PageFlags::new_page_table(virt.kind() == PageTableKind::User);
|
||||||
|
|
||||||
// kdebug!("Flags: {:?}", flags);
|
// 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)?;
|
table = table.next_level_table(i)?;
|
||||||
@ -765,7 +801,7 @@ unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>(
|
|||||||
// 如果当前是最后一级页表,直接取消页面映射
|
// 如果当前是最后一级页表,直接取消页面映射
|
||||||
if table.level() == 0 {
|
if table.level() == 0 {
|
||||||
let entry = table.entry(i)?;
|
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()));
|
return Some((entry.address().ok()?, entry.flags()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,7 +820,7 @@ unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>(
|
|||||||
.any(|e| e.present());
|
.any(|e| e.present());
|
||||||
if !x {
|
if !x {
|
||||||
// 如果没有,就取消子页表的映射
|
// 如果没有,就取消子页表的映射
|
||||||
table.set_entry(i, PageEntry::new(0));
|
table.set_entry(i, PageEntry::from_usize(0));
|
||||||
// 释放子页表
|
// 释放子页表
|
||||||
allocator.free_one(subtable.phys());
|
allocator.free_one(subtable.phys());
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 7fc3806da73be059540a79b6fdddf8049be250f3
|
Subproject commit 773f7fd31fb85ce22f0fc442fd2c13a8d0602a8c
|
@ -12,6 +12,6 @@ ratatui = "0.24.0"
|
|||||||
clap = { version = "4.4.7", features = ["color", "error-context", "help", "std", "suggestions", "usage", "derive"] }
|
clap = { version = "4.4.7", features = ["color", "error-context", "help", "std", "suggestions", "usage", "derive"] }
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
goblin = "0.7.1"
|
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"
|
log = "0.4.20"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user