diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index bed290b01..4ea5e6bb0 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -65,7 +65,7 @@ x86_64 = "=0.14.10" # target为riscv64时,使用下面的依赖 [target.'cfg(target_arch = "riscv64")'.dependencies] -riscv = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/riscv.git", revision = "cc4d3ea82a", features = [ "s-mode" ] } +riscv = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/riscv.git", rev = "4241a97", features = [ "s-mode" ] } sbi-rt = { version = "=0.0.3", features = ["legacy"] } diff --git a/kernel/src/arch/riscv64/driver/of.rs b/kernel/src/arch/riscv64/driver/of.rs index 9d21f69c8..f41793310 100644 --- a/kernel/src/arch/riscv64/driver/of.rs +++ b/kernel/src/arch/riscv64/driver/of.rs @@ -3,6 +3,7 @@ use system_error::SystemError; use crate::{ driver::open_firmware::fdt::OpenFirmwareFdtDriver, init::boot_params, + kdebug, libs::align::page_align_up, mm::{mmio_buddy::mmio_pool, MemoryManagementArch, PhysAddr}, }; @@ -28,6 +29,7 @@ impl OpenFirmwareFdtDriver { // drop the boot params guard in order to avoid deadlock drop(bp_guard); + kdebug!("map_fdt: map fdt to {:?}, size: {}", map_paddr, map_size); mmio_guard.map_phys(map_paddr, map_size)?; let mut bp_guard = boot_params().write(); let vaddr = mmio_guard.vaddr() + offset; diff --git a/kernel/src/arch/riscv64/init/mod.rs b/kernel/src/arch/riscv64/init/mod.rs index 078ac21ac..e69b95fed 100644 --- a/kernel/src/arch/riscv64/init/mod.rs +++ b/kernel/src/arch/riscv64/init/mod.rs @@ -112,7 +112,7 @@ pub fn early_setup_arch() -> Result<(), SystemError> { arch_boot_params_guard.arch.fdt_paddr = fdt_paddr; arch_boot_params_guard.arch.fdt_size = fdt.total_size(); arch_boot_params_guard.arch.boot_hartid = ProcessorId::new(hartid); - + kdebug!("fdt_paddr: {:?}, fdt_size: {}", fdt_paddr, fdt.total_size()); drop(arch_boot_params_guard); kinfo!( diff --git a/kernel/src/arch/riscv64/interrupt/entry.rs b/kernel/src/arch/riscv64/interrupt/entry.rs index c8eb4e8c6..7693a92d5 100644 --- a/kernel/src/arch/riscv64/interrupt/entry.rs +++ b/kernel/src/arch/riscv64/interrupt/entry.rs @@ -160,7 +160,8 @@ unsafe extern "C" fn _save_context() -> ! { off_cause = const offset_of!(TrapFrame, cause), off_tp = const offset_of!(TrapFrame, tp), off_epc = const offset_of!(TrapFrame, epc), - sr_sum_and_fsvs = const (SR_FS_VS | SR_SUM), + sr_sum_and_fsvs = const (0), // 暂时在内核中不禁用FPU和Vector,以及不禁用用户内存访问 + // sr_sum_and_fsvs = const (SR_FS_VS | SR_SUM), csr_status = const CSR_SSTATUS, csr_epc = const CSR_SEPC, csr_tval = const CSR_STVAL, diff --git a/kernel/src/arch/riscv64/interrupt/handle.rs b/kernel/src/arch/riscv64/interrupt/handle.rs index 3e7a5c25d..891c57de9 100644 --- a/kernel/src/arch/riscv64/interrupt/handle.rs +++ b/kernel/src/arch/riscv64/interrupt/handle.rs @@ -48,10 +48,6 @@ fn riscv64_do_interrupt(trap_frame: &mut TrapFrame) { /// 处理异常 fn riscv64_do_exception(trap_frame: &mut TrapFrame) { - kdebug!( - "riscv64_do_exception: from_user: {}", - trap_frame.is_from_user() - ); let code = trap_frame.cause.code(); if code < EXCEPTION_HANDLERS.len() { @@ -153,8 +149,16 @@ fn do_trap_user_env_call(trap_frame: &mut TrapFrame) -> Result<(), SystemError> // 9-11 reserved /// 处理指令页错误异常 #12 -fn do_trap_insn_page_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> { - kerror!("riscv64_do_irq: do_insn_page_fault"); +fn do_trap_insn_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError> { + let vaddr = trap_frame.badaddr; + let cause = trap_frame.cause; + let epc = trap_frame.epc; + kerror!( + "riscv64_do_irq: do_insn_page_fault vaddr: {:#x}, cause: {:?} epc: {:#x}", + vaddr, + cause, + epc + ); loop { spin_loop(); } @@ -179,8 +183,13 @@ fn do_trap_load_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError // 14 reserved /// 处理页存储错误异常 #15 -fn do_trap_store_page_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> { - kerror!("riscv64_do_irq: do_trap_store_page_fault"); +fn do_trap_store_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError> { + kerror!( + "riscv64_do_irq: do_trap_store_page_fault: epc: {:#x}, vaddr={:#x}, cause={:?}", + trap_frame.epc, + trap_frame.badaddr, + trap_frame.cause + ); loop { spin_loop(); } diff --git a/kernel/src/arch/riscv64/mm/init.rs b/kernel/src/arch/riscv64/mm/init.rs index 2de82aa94..79a5fade2 100644 --- a/kernel/src/arch/riscv64/mm/init.rs +++ b/kernel/src/arch/riscv64/mm/init.rs @@ -69,6 +69,8 @@ pub(super) unsafe fn riscv_mm_init() -> Result<(), SystemError> { mem_block_manager() .reserve_block(KERNEL_BEGIN_PA, KERNEL_END_PA - KERNEL_BEGIN_PA) .expect("Failed to reserve kernel memory"); + // 开启S-mode User Memory Access,允许内核访问用户空间 + riscv::register::sstatus::set_sum(); let mut bump_allocator = BumpAllocator::::new(0); let _old_page_table = MMArch::table(PageTableKind::Kernel); @@ -76,7 +78,7 @@ pub(super) unsafe fn riscv_mm_init() -> Result<(), SystemError> { // 使用bump分配器,把所有的内存页都映射到页表 { - kdebug!("to create new page table"); + // kdebug!("to create new page table"); // 用bump allocator创建新的页表 let mut mapper: crate::mm::page::PageMapper> = crate::mm::page::PageMapper::::create( @@ -85,7 +87,7 @@ pub(super) unsafe fn riscv_mm_init() -> Result<(), SystemError> { ) .expect("Failed to create page mapper"); new_page_table = mapper.table().phys(); - kdebug!("PageMapper created"); + // kdebug!("PageMapper created"); // 取消最开始时候,在head.S中指定的映射(暂时不刷新TLB) { diff --git a/kernel/src/arch/riscv64/mm/mod.rs b/kernel/src/arch/riscv64/mm/mod.rs index ad148cf46..0e5c419c4 100644 --- a/kernel/src/arch/riscv64/mm/mod.rs +++ b/kernel/src/arch/riscv64/mm/mod.rs @@ -105,7 +105,9 @@ impl MemoryManagementArch for RiscV64MMArch { const ENTRY_FLAG_PRESENT: usize = 1 << 0; - const ENTRY_FLAG_READONLY: usize = 0; + const ENTRY_FLAG_READONLY: usize = (1 << 1); + + const ENTRY_FLAG_WRITEABLE: usize = (1 << 2); const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1); @@ -176,6 +178,7 @@ impl MemoryManagementArch for RiscV64MMArch { let ppn = PhysPageFrame::new(table).ppn(); riscv::asm::sfence_vma_all(); satp::set(satp::Mode::Sv39, 0, ppn); + riscv::asm::sfence_vma_all(); } fn virt_is_valid(virt: VirtAddr) -> bool { diff --git a/kernel/src/arch/riscv64/process/idle.rs b/kernel/src/arch/riscv64/process/idle.rs index c2a27e725..e374087fe 100644 --- a/kernel/src/arch/riscv64/process/idle.rs +++ b/kernel/src/arch/riscv64/process/idle.rs @@ -15,7 +15,7 @@ impl ProcessManager { spin_loop(); } - kdebug!("idle loop"); + // kdebug!("idle loop"); } } } diff --git a/kernel/src/arch/riscv64/process/kthread.rs b/kernel/src/arch/riscv64/process/kthread.rs index f7d5e7f8b..610c8acd4 100644 --- a/kernel/src/arch/riscv64/process/kthread.rs +++ b/kernel/src/arch/riscv64/process/kthread.rs @@ -35,6 +35,7 @@ impl KernelThreadMechanism { // 使能中断 frame.status.update_sie(true); frame.status.update_spp(SPP::Supervisor); + frame.status.update_sum(true); frame.ra = kernel_thread_bootstrap_stage1 as usize; diff --git a/kernel/src/arch/riscv64/process/mod.rs b/kernel/src/arch/riscv64/process/mod.rs index 7648e753c..33a885629 100644 --- a/kernel/src/arch/riscv64/process/mod.rs +++ b/kernel/src/arch/riscv64/process/mod.rs @@ -28,6 +28,7 @@ use crate::{ PROCESS_SWITCH_RESULT, }, smp::cpu::ProcessorId, + syscall::Syscall, }; use super::{ @@ -53,7 +54,64 @@ static BSP_IDLE_STACK_SPACE: InitProcUnion = InitProcUnion { }; pub unsafe fn arch_switch_to_user(path: String, argv: Vec, envp: Vec) -> ! { - unimplemented!("RiscV64 arch_switch_to_user") + // 以下代码不能发生中断 + CurrentIrqArch::interrupt_disable(); + + let current_pcb = ProcessManager::current_pcb(); + let trap_frame_vaddr = VirtAddr::new( + current_pcb.kernel_stack().stack_max_address().data() - core::mem::size_of::(), + ); + let new_pc = VirtAddr::new(ret_from_exception as usize); + + let mut arch_guard = current_pcb.arch_info_irqsave(); + arch_guard.ksp = trap_frame_vaddr.data(); + + arch_guard.ra = new_pc.data(); + drop(arch_guard); + + // 删除kthread的标志 + current_pcb.flags().remove(ProcessFlags::KTHREAD); + current_pcb.worker_private().take(); + + *current_pcb.sched_info().sched_policy.write_irqsave() = crate::sched::SchedPolicy::CFS; + + let mut trap_frame = TrapFrame::new(); + + compiler_fence(Ordering::SeqCst); + Syscall::do_execve(path, argv, envp, &mut trap_frame).unwrap_or_else(|e| { + panic!( + "arch_switch_to_user(): pid: {pid:?}, Failed to execve: , error: {e:?}", + pid = current_pcb.pid(), + e = e + ); + }); + compiler_fence(Ordering::SeqCst); + + // 重要!在这里之后,一定要保证上面的引用计数变量、动态申请的变量、锁的守卫都被drop了,否则可能导致内存安全问题! + + drop(current_pcb); + + *(trap_frame_vaddr.data() as *mut TrapFrame) = trap_frame; + + compiler_fence(Ordering::SeqCst); + ready_to_switch_to_user(trap_frame_vaddr.data(), new_pc.data()); +} + +#[naked] +unsafe extern "C" fn ready_to_switch_to_user(trap_frame: usize, new_pc: usize) -> ! { + asm!( + concat!( + " + // 设置trap frame + mv sp, a0 + // 设置返回地址 + + jr a1 + + " + ), + options(noreturn) + ); } impl ProcessManager { @@ -98,6 +156,7 @@ impl ProcessManager { let current_arch_guard = current_pcb.arch_info_irqsave(); // 拷贝浮点寄存器的状态 new_arch_guard.fp_state = current_arch_guard.fp_state; + new_arch_guard.sstatus = current_arch_guard.sstatus; drop(current_arch_guard); @@ -128,11 +187,11 @@ impl ProcessManager { /// 参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/include/asm/switch_to.h#76 pub unsafe fn switch_process(prev: Arc, next: Arc) { assert!(!CurrentIrqArch::is_irq_enabled()); - kdebug!( - "riscv switch process: prev: {:?}, next: {:?}", - prev.pid(), - next.pid() - ); + // kdebug!( + // "riscv switch process: prev: {:?}, next: {:?}", + // prev.pid(), + // next.pid() + // ); Self::switch_process_fpu(&prev, &next); Self::switch_local_context(&prev, &next); @@ -144,6 +203,8 @@ impl ProcessManager { drop(next_addr_space); compiler_fence(Ordering::SeqCst); + // kdebug!("current sum={}, prev sum={}, next_sum={}", riscv::register::sstatus::read().sum(), prev.arch_info_irqsave().sstatus.sum(), next.arch_info_irqsave().sstatus.sum()); + // 获取arch info的锁,并强制泄露其守卫(切换上下文后,在switch_finish_hook中会释放锁) let next_arch = SpinLockGuard::leak(next.arch_info_irqsave()) as *mut ArchPCBInfo; let prev_arch = SpinLockGuard::leak(prev.arch_info_irqsave()) as *mut ArchPCBInfo; @@ -153,7 +214,7 @@ impl ProcessManager { ProcessManager::current_pcb().preempt_enable(); PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev); PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next); - kdebug!("riscv switch process: before to inner"); + // kdebug!("riscv switch process: before to inner"); compiler_fence(Ordering::SeqCst); // 正式切换上下文 switch_to_inner(prev_arch, next_arch); @@ -206,8 +267,8 @@ unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBI addi sp , sp, -8 sd a1, 0(sp) - csrr a0, sstatus - sd a0, {off_sstatus}(a1) + csrr a1, sstatus + sd a1, {off_sstatus}(a0) ld a1, 0(sp) addi sp, sp, 8 @@ -271,13 +332,12 @@ unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBI /// 在切换上下文完成后的钩子函数(必须在这里加一个跳转函数,否则会出现relocation truncated to fit: R_RISCV_JAL错误) unsafe extern "C" fn before_switch_finish_hook() { let pcb = ProcessManager::current_pcb(); - kdebug!( - "before_switch_finish_hook, pid: {:?}, name: {:?}", - pcb.pid(), - pcb.basic().name() - ); + // kdebug!( + // "before_switch_finish_hook, pid: {:?}, name: {:?}", + // pcb.pid(), + // pcb.basic().name() + // ); switch_finish_hook(); - kdebug!("after switch_finish_hook"); } impl ProcessControlBlock { @@ -344,6 +404,8 @@ impl ArchPCBInfo { /// /// 返回一个新的ArchPCBInfo pub fn new(kstack: &KernelStack) -> Self { + let mut sstatus = Sstatus::from(0); + sstatus.update_sum(true); Self { ra: 0, ksp: kstack.stack_max_address().data(), @@ -359,7 +421,7 @@ impl ArchPCBInfo { s9: 0, s10: 0, s11: 0, - sstatus: Sstatus::from(0), + sstatus, fp_state: FpDExtState::new(), local_context: LocalContext::new(ProcessorId::new(0)), } diff --git a/kernel/src/arch/riscv64/process/syscall.rs b/kernel/src/arch/riscv64/process/syscall.rs index 8478842cb..ae1e63f3a 100644 --- a/kernel/src/arch/riscv64/process/syscall.rs +++ b/kernel/src/arch/riscv64/process/syscall.rs @@ -1,7 +1,18 @@ use alloc::{string::String, vec::Vec}; +use riscv::register::sstatus::{Sstatus, FS, SPP}; use system_error::SystemError; -use crate::{arch::interrupt::TrapFrame, syscall::Syscall}; +use crate::{ + arch::{interrupt::TrapFrame, CurrentIrqArch}, + exception::InterruptArch, + kdebug, + mm::ucontext::AddressSpace, + process::{ + exec::{load_binary_file, ExecParam, ExecParamFlags}, + ProcessManager, + }, + syscall::Syscall, +}; impl Syscall { pub fn do_execve( @@ -10,7 +21,95 @@ impl Syscall { envp: Vec, regs: &mut TrapFrame, ) -> Result<(), SystemError> { - unimplemented!("Syscall::do_execve") + // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。 + let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; + let pcb = ProcessManager::current_pcb(); + // crate::kdebug!( + // "pid: {:?} do_execve: path: {:?}, argv: {:?}, envp: {:?}\n", + // pcb.pid(), + // path, + // argv, + // envp + // ); + + let mut basic_info = pcb.basic_mut(); + // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free) + let old_address_space = basic_info.user_vm(); + + // 在pcb中原来的用户地址空间 + unsafe { + basic_info.set_user_vm(None); + } + // 创建新的地址空间并设置为当前地址空间 + let address_space = AddressSpace::new(true).expect("Failed to create new address space"); + unsafe { + basic_info.set_user_vm(Some(address_space.clone())); + } + + // to avoid deadlock + drop(basic_info); + + assert!( + AddressSpace::is_current(&address_space), + "Failed to set address space" + ); + // kdebug!("Switch to new address space"); + + // 切换到新的用户地址空间 + unsafe { address_space.read().user_mapper.utable.make_current() }; + + drop(old_address_space); + drop(irq_guard); + // kdebug!("to load binary file"); + let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC)?; + + // 加载可执行文件 + let load_result = load_binary_file(&mut param) + .unwrap_or_else(|e| panic!("Failed to load binary file: {:?}, path: {:?}", e, path)); + // kdebug!("load binary file done"); + // kdebug!("argv: {:?}, envp: {:?}", argv, envp); + param.init_info_mut().args = argv; + param.init_info_mut().envs = envp; + + // 把proc_init_info写到用户栈上 + let mut ustack_message = unsafe { + address_space + .write() + .user_stack_mut() + .expect("No user stack found") + .clone_info_only() + }; + let (user_sp, argv_ptr) = unsafe { + param + .init_info() + .push_at( + // address_space + // .write() + // .user_stack_mut() + // .expect("No user stack found"), + &mut ustack_message, + ) + .expect("Failed to push proc_init_info to user stack") + }; + address_space.write().user_stack = Some(ustack_message); + + // kdebug!("write proc_init_info to user stack done"); + + regs.a0 = param.init_info().args.len(); + regs.a1 = argv_ptr.data(); + + // 设置系统调用返回时的寄存器状态 + regs.sp = user_sp.data(); + + regs.epc = load_result.entry_point().data(); + regs.status.update_spp(SPP::User); + regs.status.update_fs(FS::Clean); + regs.status.update_sie(true); + regs.status.update_sum(true); + + drop(param); + + return Ok(()); } /// ## 用于控制和查询与体系结构相关的进程特定选项 diff --git a/kernel/src/arch/riscv64/syscall/mod.rs b/kernel/src/arch/riscv64/syscall/mod.rs index cf3c2c2b2..7316ff0b5 100644 --- a/kernel/src/arch/riscv64/syscall/mod.rs +++ b/kernel/src/arch/riscv64/syscall/mod.rs @@ -2,7 +2,7 @@ pub mod nr; use system_error::SystemError; -use crate::{exception::InterruptArch, process::ProcessManager, syscall::Syscall}; +use crate::{exception::InterruptArch, kdebug, process::ProcessManager, syscall::Syscall}; use super::{interrupt::TrapFrame, CurrentIrqArch}; @@ -29,6 +29,7 @@ macro_rules! syscall_return { } pub(super) fn syscall_handler(syscall_num: usize, frame: &mut TrapFrame) -> () { + // kdebug!("syscall_handler: syscall_num: {}", syscall_num); unsafe { CurrentIrqArch::interrupt_enable(); } diff --git a/kernel/src/arch/riscv64/time.rs b/kernel/src/arch/riscv64/time.rs index ea2e91d76..d6be314a8 100644 --- a/kernel/src/arch/riscv64/time.rs +++ b/kernel/src/arch/riscv64/time.rs @@ -1,6 +1,6 @@ use crate::{ driver::open_firmware::fdt::open_firmware_fdt_driver, - kinfo, + kdebug, kinfo, time::{clocksource::HZ, TimeArch}, }; pub struct RiscV64TimeArch; @@ -14,10 +14,12 @@ static mut TIME_FREQ: usize = 0; /// /// todo: 支持从acpi中获取 fn init_time_freq() { + kdebug!("init_time_freq: init"); let fdt = open_firmware_fdt_driver().fdt_ref(); if fdt.is_err() { panic!("init_time_freq: failed to get fdt"); } + kdebug!("init_time_freq: get fdt"); let fdt = fdt.unwrap(); let cpu_node = fdt.find_node("/cpus"); if cpu_node.is_none() { diff --git a/kernel/src/arch/x86_64/mm/mod.rs b/kernel/src/arch/x86_64/mm/mod.rs index 7d5457584..bfc491eff 100644 --- a/kernel/src/arch/x86_64/mm/mod.rs +++ b/kernel/src/arch/x86_64/mm/mod.rs @@ -94,6 +94,7 @@ impl MemoryManagementArch for X86_64MMArch { const ENTRY_FLAG_READONLY: usize = 0; + const ENTRY_FLAG_WRITEABLE: usize = 1 << 1; const ENTRY_FLAG_READWRITE: usize = 1 << 1; const ENTRY_FLAG_USER: usize = 1 << 2; diff --git a/kernel/src/driver/Makefile b/kernel/src/driver/Makefile index d7ea67fce..c8e9e35f1 100644 --- a/kernel/src/driver/Makefile +++ b/kernel/src/driver/Makefile @@ -1,7 +1,7 @@ CFLAGS += -I . -kernel_driver_subdirs:=acpi disk multiboot2 timers +kernel_driver_subdirs:=acpi multiboot2 ECHO: @echo "$@" diff --git a/kernel/src/driver/clocksource/timer_riscv.rs b/kernel/src/driver/clocksource/timer_riscv.rs index e21d73708..cb0fd5458 100644 --- a/kernel/src/driver/clocksource/timer_riscv.rs +++ b/kernel/src/driver/clocksource/timer_riscv.rs @@ -34,11 +34,11 @@ impl RiscVSbiTimer { fn handle_irq(trap_frame: &mut TrapFrame) -> Result<(), SystemError> { // 更新下一次中断时间 - kdebug!( - "riscv_sbi_timer: handle_irq: cpu_id: {}, time: {}", - smp_get_processor_id().data(), - CurrentTimeArch::get_cycles() as u64 - ); + // kdebug!( + // "riscv_sbi_timer: handle_irq: cpu_id: {}, time: {}", + // smp_get_processor_id().data(), + // CurrentTimeArch::get_cycles() as u64 + // ); sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64 + unsafe { INTERVAL_CNT } as u64); ProcessManager::update_process_times(trap_frame.is_from_user()); Ok(()) diff --git a/kernel/src/driver/disk/Makefile b/kernel/src/driver/disk/Makefile deleted file mode 100644 index f85134716..000000000 --- a/kernel/src/driver/disk/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -SRC = $(wildcard *.c) -OBJ = $(SRC:.c=.o) -CFLAGS += -I . - -.PHONY: all - -all: $(OBJ) - -%.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ \ No newline at end of file diff --git a/kernel/src/driver/firmware/efi/esrt.rs b/kernel/src/driver/firmware/efi/esrt.rs new file mode 100644 index 000000000..6fd955764 --- /dev/null +++ b/kernel/src/driver/firmware/efi/esrt.rs @@ -0,0 +1,13 @@ +//! 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/esrt.c#1 + +use super::efi_manager; + +#[inline(never)] +pub(super) fn efi_esrt_init() { + if !efi_manager().esrt_table_exists() { + return; + } + + // todo: 参考linux 的 `efi_esrt_init`来实现 + todo!("efi_esrt_init") +} diff --git a/kernel/src/driver/firmware/efi/guid.rs b/kernel/src/driver/firmware/efi/guid.rs index 753c085f9..ad9b4daa4 100644 --- a/kernel/src/driver/firmware/efi/guid.rs +++ b/kernel/src/driver/firmware/efi/guid.rs @@ -29,6 +29,15 @@ pub static EFI_MEMRESERVE_TABLE_GUID: Guid = Guid::new( 0xf0, [0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2], ); + +pub static EFI_SYSTEM_RESOURCE_TABLE_GUID: Guid = Guid::new( + unsafe { mem::transmute_copy(&0xb122a263u32) }, + unsafe { mem::transmute_copy(&0x3661u32) }, + unsafe { mem::transmute_copy(&0x4f68u32) }, + 0x99, + 0x29, + [0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80], +); /// 表示内核被加载到的地址的信息。 /// /// 对应 `DRAGONSTUB_EFI_PAYLOAD_EFI_GUID` diff --git a/kernel/src/driver/firmware/efi/init.rs b/kernel/src/driver/firmware/efi/init.rs index 67443f725..c425a8872 100644 --- a/kernel/src/driver/firmware/efi/init.rs +++ b/kernel/src/driver/firmware/efi/init.rs @@ -5,7 +5,10 @@ use uefi_raw::table::boot::{MemoryAttribute, MemoryType}; use crate::{ arch::MMArch, - driver::{firmware::efi::EFIInitFlags, open_firmware::fdt::open_firmware_fdt_driver}, + driver::{ + firmware::efi::{esrt::efi_esrt_init, EFIInitFlags}, + open_firmware::fdt::open_firmware_fdt_driver, + }, libs::align::{page_align_down, page_align_up}, mm::{ allocator::page_frame::PhysPageFrame, early_ioremap::EarlyIoRemap, @@ -66,6 +69,11 @@ pub fn efi_init() { // todo: 模仿Linux的行为,做好接下来的几步工作: // 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/efi-init.c#217 + // todo: early_init_dt_check_for_usable_mem_range + + efi_find_mirror(); + efi_esrt_init(); + // 保留mmap table的内存 let base = page_align_down(data_from_fdt.mmap_base.unwrap() as usize); let offset = data_from_fdt.mmap_base.unwrap() as usize - base; @@ -78,7 +86,7 @@ pub fn efi_init() { .expect("Failed to reserve memory for EFI mmap table"); // 保留内核的内存 - if let Some(info) = efi_manager().inner.read().dragonstub_load_info { + if let Some(info) = efi_manager().inner_read().dragonstub_load_info { mem_block_manager() .reserve_block( PhysAddr::new(info.paddr as usize), @@ -92,6 +100,31 @@ pub fn efi_init() { kinfo!("UEFI init done!"); } +fn efi_find_mirror() { + let efi_guard = efi_manager().inner_read(); + let mut total_size = 0; + let mut mirror_size = 0; + for md in efi_guard.mmap.iter() { + let start = PhysAddr::new(md.phys_start as usize); + let size = (md.page_count << (MMArch::PAGE_SHIFT as u64)) as usize; + + if md.att.contains(MemoryAttribute::MORE_RELIABLE) { + mem_block_manager().mark_mirror(start, size).unwrap(); + mirror_size += size; + } + + total_size += size; + } + + if mirror_size > 0 { + kinfo!( + "Memory: {}M/{}M mirrored memory", + mirror_size >> 20, + total_size >> 20 + ); + } +} + #[inline(never)] fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> { // 定义错误处理函数 @@ -142,7 +175,7 @@ fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> { let st_ref = unsafe { st_ptr.as_ref().unwrap() }; let runtime_service_paddr = efi_vaddr_2_paddr(st_ref.runtime_services as usize); - let mut inner_write_guard = efi_manager().inner.write(); + let mut inner_write_guard = efi_manager().inner_write(); inner_write_guard.runtime_paddr = Some(runtime_service_paddr); inner_write_guard.runtime_service_version = Some(st_ref.header.revision); @@ -189,7 +222,7 @@ fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> { /// /// 在进入该函数前,请不要持有`efi_manager().inner`的写锁 fn efi_vaddr_2_paddr(efi_vaddr: usize) -> PhysAddr { - let guard = efi_manager().inner.read(); + let guard = efi_manager().inner_read(); let mmap = &guard.mmap; let efi_vaddr: u64 = efi_vaddr as u64; @@ -236,6 +269,11 @@ fn reserve_memory_regions() { if md.is_memory() { open_firmware_fdt_driver().early_init_dt_add_memory(phys_start as u64, size as u64); if !md.is_usable_memory() { + // kdebug!( + // "Marking non-usable memory as nomap: {:#x}-{:#x}", + // phys_start, + // phys_start + size + // ); mem_block_manager() .mark_nomap(PhysAddr::new(phys_start), size) .unwrap(); diff --git a/kernel/src/driver/firmware/efi/mod.rs b/kernel/src/driver/firmware/efi/mod.rs index e8c5c824b..a07d4df26 100644 --- a/kernel/src/driver/firmware/efi/mod.rs +++ b/kernel/src/driver/firmware/efi/mod.rs @@ -1,9 +1,13 @@ use system_error::SystemError; -use crate::{libs::rwlock::RwLock, mm::PhysAddr}; +use crate::{ + libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, + mm::PhysAddr, +}; use self::{guid::DragonStubPayloadEFI, memmap::EFIMemoryMapInfo}; +pub mod esrt; mod fdt; pub mod guid; pub mod init; @@ -39,6 +43,8 @@ struct InnerEFIManager { pub memory_attribute_table_paddr: Option, /// uefi 内存保留表的物理地址 pub memreserve_table_paddr: Option, + /// uefi esrt表的物理地址 + pub esrt_table_paddr: Option, } impl EFIManager { @@ -52,6 +58,7 @@ impl EFIManager { dragonstub_load_info: None, memory_attribute_table_paddr: None, memreserve_table_paddr: None, + esrt_table_paddr: None, }), } } @@ -97,6 +104,19 @@ impl EFIManager { return Ok(()); } + + fn inner_read(&self) -> RwLockReadGuard { + self.inner.read() + } + + fn inner_write(&self) -> RwLockWriteGuard { + self.inner.write() + } + + /// 是否存在ESRT表 + fn esrt_table_exists(&self) -> bool { + self.inner_read().esrt_table_paddr.is_some() + } } // 在Rust中,我们使用枚举和bitflags来表示这些宏 diff --git a/kernel/src/driver/firmware/efi/tables.rs b/kernel/src/driver/firmware/efi/tables.rs index 7076c9acd..bab605005 100644 --- a/kernel/src/driver/firmware/efi/tables.rs +++ b/kernel/src/driver/firmware/efi/tables.rs @@ -20,7 +20,9 @@ use crate::{ }; use super::{ - guid::{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, EFI_MEMRESERVE_TABLE_GUID}, + guid::{ + EFI_MEMORY_ATTRIBUTES_TABLE_GUID, EFI_MEMRESERVE_TABLE_GUID, EFI_SYSTEM_RESOURCE_TABLE_GUID, + }, EFIManager, }; @@ -29,6 +31,7 @@ static TABLE_PARSERS: &[&TableMatcher] = &[ &TableMatcher::new(&MatchTableDragonStubPayloadEFI), &TableMatcher::new(&MatchTableMemoryAttributes), &TableMatcher::new(&MatchTableMemReserve), + &TableMatcher::new(&MatchTableEsrt), ]; impl EFIManager { @@ -99,7 +102,7 @@ impl EFIManager { } // 如果存在mem reserve table - if let Some(mem_reserve) = efi_manager().inner.read().memreserve_table_paddr { + if let Some(mem_reserve) = efi_manager().inner_read().memreserve_table_paddr { let mut prev_paddr = mem_reserve; while !prev_paddr.is_null() { let vaddr = EarlyIoRemap::map_not_aligned(prev_paddr, MMArch::PAGE_SIZE, true) @@ -283,7 +286,7 @@ impl MatchTable for MatchTableDragonStubPayloadEFI { let vendor_table_vaddr = vendor_table_vaddr.unwrap(); let data = unsafe { *(vendor_table_vaddr.data() as *const DragonStubPayloadEFI) }; - efi_manager().inner.write().dragonstub_load_info = Some(data); + efi_manager().inner_write().dragonstub_load_info = Some(data); return Ok(()); } @@ -349,6 +352,33 @@ impl MatchTable for MatchTableMemReserve { } } +struct MatchTableEsrt; + +impl MatchTable for MatchTableEsrt { + fn name(&self) -> &'static str { + "ESRT" + } + + fn guid(&self) -> &'static uefi_raw::Guid { + &EFI_SYSTEM_RESOURCE_TABLE_GUID + } + + fn map_size(&self) -> usize { + 0 + } + + fn post_process( + &self, + _vendor_table_vaddr: Option, + table_raw: &ConfigurationTable, + ) -> Result<(), SystemError> { + efi_manager().inner.write_irqsave().esrt_table_paddr = + Some(PhysAddr::new(table_raw.vendor_table as usize)); + kdebug!("esrt_table_paddr: {:#x}", table_raw.vendor_table as usize); + return Ok(()); + } +} + /// 用于匹配配置表的匹配器 struct TableMatcher { table: &'static dyn MatchTable, diff --git a/kernel/src/driver/irqchip/riscv_intc.rs b/kernel/src/driver/irqchip/riscv_intc.rs index 9b9ac903f..67a061e5b 100644 --- a/kernel/src/driver/irqchip/riscv_intc.rs +++ b/kernel/src/driver/irqchip/riscv_intc.rs @@ -162,7 +162,7 @@ pub unsafe fn riscv_intc_init() -> Result<(), SystemError> { /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-riscv-intc.c#23 pub fn riscv_intc_irq(trap_frame: &mut TrapFrame) { let hwirq = HardwareIrqNumber::new(trap_frame.cause.code() as u32); - kdebug!("riscv64_do_irq: interrupt {hwirq:?}"); + // kdebug!("riscv64_do_irq: interrupt {hwirq:?}"); GenericIrqHandler::handle_domain_irq(riscv_intc_domain().clone().unwrap(), hwirq, trap_frame) .ok(); if hwirq.data() == RiscVSbiTimer::TIMER_IRQ.data() { diff --git a/kernel/src/driver/timers/Makefile b/kernel/src/driver/timers/Makefile deleted file mode 100644 index 6487a3748..000000000 --- a/kernel/src/driver/timers/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -all: - -CFLAGS += -I . - -#HPET.o: HPET/HPET.c -# $(CC) $(CFLAGS) -c HPET/HPET.c -o HPET/HPET.o diff --git a/kernel/src/init/initial_kthread.rs b/kernel/src/init/initial_kthread.rs index b883cc2ca..7b4b20b0d 100644 --- a/kernel/src/init/initial_kthread.rs +++ b/kernel/src/init/initial_kthread.rs @@ -61,8 +61,9 @@ fn kenrel_init_freeable() -> Result<(), SystemError> { /// 切换到用户态 fn switch_to_user() { - let path = String::from("/bin/dragonreach"); - let argv = vec![String::from("/bin/dragonreach")]; + const INIT_PROGRAM: &str = "/bin/dragonreach"; + let path = String::from(INIT_PROGRAM); + let argv = vec![path.clone()]; let envp = vec![String::from("PATH=/")]; unsafe { arch_switch_to_user(path, argv, envp) }; diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 71a7a4ff5..b26a7ca71 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -145,5 +145,6 @@ pub fn panic(info: &PanicInfo) -> ! { } println!("Current PCB:\n\t{:?}", (ProcessManager::current_pcb())); + ProcessManager::exit(usize::MAX); } diff --git a/kernel/src/libs/elf.rs b/kernel/src/libs/elf.rs index 7469814c2..73b6f9330 100644 --- a/kernel/src/libs/elf.rs +++ b/kernel/src/libs/elf.rs @@ -18,7 +18,7 @@ use crate::{ arch::{CurrentElfArch, MMArch}, driver::base::block::SeekFrom, filesystem::vfs::file::File, - kerror, + kdebug, kerror, libs::align::page_align_up, mm::{ allocator::page_frame::{PageFrameCount, VirtPageFrame}, @@ -123,7 +123,7 @@ impl ElfLoader { ) -> Result<(), ExecError> { let start = self.elf_page_start(start); let end = self.elf_page_align_up(end); - + // kdebug!("set_elf_brk: start={:?}, end={:?}", start, end); if end > start { let r = user_vm_guard.map_anonymous( start, @@ -133,6 +133,7 @@ impl ElfLoader { false, true, ); + // kdebug!("set_elf_brk: map_anonymous: r={:?}", r); if r.is_err() { kerror!("set_elf_brk: map_anonymous failed, err={:?}", r); return Err(ExecError::OutOfMemory); @@ -254,18 +255,14 @@ impl ElfLoader { if total_size != 0 { let total_size = self.elf_page_align_up(VirtAddr::new(total_size)).data(); - // kdebug!("total_size={}", total_size); - map_addr = user_vm_guard .map_anonymous(addr_to_map, total_size, tmp_prot, *map_flags, false, true) .map_err(map_err_handler)? .virt_address(); - // kdebug!("map ok: addr_to_map={:?}", addr_to_map); let to_unmap = map_addr + map_size; let to_unmap_size = total_size - map_size; - // kdebug!("to_unmap={:?}, to_unmap_size={}", to_unmap, to_unmap_size); user_vm_guard.munmap( VirtPageFrame::new(to_unmap), PageFrameCount::from_bytes(to_unmap_size).unwrap(), @@ -554,6 +551,7 @@ impl BinaryLoader for ElfLoader { if seg.p_type != PT_INTERP { continue; } + // 接下来处理这个 .interpreter 段以及动态链接器 // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#881 @@ -582,8 +580,6 @@ impl BinaryLoader for ElfLoader { } Self::parse_gnu_property()?; - // kdebug!("loadable_sections = {:?}", loadable_sections); - let mut elf_brk = VirtAddr::new(0); let mut elf_bss = VirtAddr::new(0); let mut start_code: Option = None; @@ -606,6 +602,7 @@ impl BinaryLoader for ElfLoader { let loadable_sections = phdr_table .into_iter() .filter(|seg| seg.p_type == elf::abi::PT_LOAD); + for seg_to_load in loadable_sections { min_address = min( min_address, @@ -632,11 +629,11 @@ impl BinaryLoader for ElfLoader { for seg_to_load in loadable_sections { // kdebug!("seg_to_load = {:?}", seg_to_load); if unlikely(elf_brk > elf_bss) { - // kdebug!( - // "to set brk, elf_brk = {:?}, elf_bss = {:?}", - // elf_brk, - // elf_bss - // ); + kdebug!( + "to set brk, elf_brk = {:?}, elf_bss = {:?}", + elf_brk, + elf_bss + ); self.set_elf_brk( &mut user_vm, elf_bss + load_bias, @@ -695,7 +692,7 @@ impl BinaryLoader for ElfLoader { } // 加载这个段到用户空间 - + // kdebug!("to load elf segment"); let e = self .load_elf_segment( &mut user_vm, @@ -706,10 +703,13 @@ impl BinaryLoader for ElfLoader { &elf_map_flags, total_size, ) - .map_err(|e| match e { - SystemError::EFAULT => ExecError::BadAddress(None), - SystemError::ENOMEM => ExecError::OutOfMemory, - _ => ExecError::Other(format!("load_elf_segment failed: {:?}", e)), + .map_err(|e| { + kerror!("load_elf_segment failed: {:?}", e); + match e { + SystemError::EFAULT => ExecError::BadAddress(None), + SystemError::ENOMEM => ExecError::OutOfMemory, + _ => ExecError::Other(format!("load_elf_segment failed: {:?}", e)), + } })?; // 如果地址不对,那么就报错 diff --git a/kernel/src/mm/allocator/page_frame.rs b/kernel/src/mm/allocator/page_frame.rs index 1e20ee310..75a79529f 100644 --- a/kernel/src/mm/allocator/page_frame.rs +++ b/kernel/src/mm/allocator/page_frame.rs @@ -21,7 +21,7 @@ pub struct PhysPageFrame { impl PhysPageFrame { pub fn new(paddr: PhysAddr) -> Self { return Self { - number: paddr.data() / MMArch::PAGE_SIZE, + number: paddr.data() >> MMArch::PAGE_SHIFT, }; } diff --git a/kernel/src/mm/kernel_mapper.rs b/kernel/src/mm/kernel_mapper.rs index 532cfe72d..02436189d 100644 --- a/kernel/src/mm/kernel_mapper.rs +++ b/kernel/src/mm/kernel_mapper.rs @@ -113,7 +113,6 @@ impl KernelMapper { let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE); // kdebug!("kernel mapper: map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}"); - for _ in 0..count.data() { let flusher = self.mapper.map_phys(vaddr, paddr, flags).unwrap(); diff --git a/kernel/src/mm/memblock.rs b/kernel/src/mm/memblock.rs index ff75c7110..4ecbee529 100644 --- a/kernel/src/mm/memblock.rs +++ b/kernel/src/mm/memblock.rs @@ -352,6 +352,11 @@ impl MemBlockManager { return self.set_or_clear_flags(base, size, true, MemoryAreaAttr::NOMAP); } + /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/mm/memblock.c?fi=memblock_mark_mirror#940 + pub fn mark_mirror(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> { + return self.set_or_clear_flags(base, size, true, MemoryAreaAttr::MIRROR); + } + fn set_or_clear_flags( &self, mut base: PhysAddr, diff --git a/kernel/src/mm/mod.rs b/kernel/src/mm/mod.rs index b37ba5a6e..49e61fcd1 100644 --- a/kernel/src/mm/mod.rs +++ b/kernel/src/mm/mod.rs @@ -447,6 +447,8 @@ pub trait MemoryManagementArch: Clone + Copy + Debug { const ENTRY_FLAG_PRESENT: usize; /// 页表项为read only时的值 const ENTRY_FLAG_READONLY: usize; + /// 页表项的write bit + const ENTRY_FLAG_WRITEABLE: usize; /// 页表项为可读写状态的值 const ENTRY_FLAG_READWRITE: usize; /// 页面项标记页面为user page的值 diff --git a/kernel/src/mm/page.rs b/kernel/src/mm/page.rs index b13f18111..fb8f806b3 100644 --- a/kernel/src/mm/page.rs +++ b/kernel/src/mm/page.rs @@ -3,7 +3,7 @@ use core::{ marker::PhantomData, mem, ops::Add, - sync::atomic::{compiler_fence, Ordering}, + sync::atomic::{compiler_fence, fence, Ordering}, }; use alloc::sync::Arc; @@ -530,9 +530,18 @@ impl PageFlags { Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE) } }; - if user { - r.set_user(true) - } else { + + #[cfg(target_arch = "x86_64")] + { + if user { + r.set_user(true) + } else { + r + } + } + + #[cfg(target_arch = "riscv64")] + { r } }; @@ -607,7 +616,9 @@ impl PageFlags { if value { return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true); } else { - return self.update_flags(Arch::ENTRY_FLAG_READONLY, true); + return self + .update_flags(Arch::ENTRY_FLAG_READONLY, true) + .update_flags(Arch::ENTRY_FLAG_WRITEABLE, false); } } } @@ -724,13 +735,25 @@ impl PageFlags { /// MMIO内存的页表项标志 #[inline(always)] pub fn mmio_flags() -> Self { - return Self::new() - .set_user(false) - .set_write(true) - .set_execute(true) - .set_page_cache_disable(true) - .set_page_write_through(true) - .set_page_global(true); + #[cfg(target_arch = "x86_64")] + { + Self::new() + .set_user(false) + .set_write(true) + .set_execute(true) + .set_page_cache_disable(true) + .set_page_write_through(true) + .set_page_global(true) + } + + #[cfg(target_arch = "riscv64")] + { + Self::new() + .set_user(false) + .set_write(true) + .set_execute(true) + .set_page_global(true) + } } } @@ -873,6 +896,7 @@ impl PageMapper { let mut table = self.table(); loop { let i = table.index_of(virt)?; + assert!(i < Arch::PAGE_ENTRY_NUM); if table.level() == 0 { compiler_fence(Ordering::SeqCst); @@ -891,13 +915,11 @@ impl PageMapper { // 清空这个页帧 MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE); - + fence(Ordering::SeqCst); // 设置页表项的flags let flags: PageFlags = PageFlags::new_page_table(virt.kind() == PageTableKind::User); - // kdebug!("Flags: {:?}", flags); - // 把新分配的页表映射到当前页表 table.set_entry(i, PageEntry::new(frame, flags)); diff --git a/kernel/src/process/exec.rs b/kernel/src/process/exec.rs index 943a8b1e2..91b7ac27d 100644 --- a/kernel/src/process/exec.rs +++ b/kernel/src/process/exec.rs @@ -188,7 +188,7 @@ pub fn load_binary_file(param: &mut ExecParam) -> Result