Browse Source

feat(riscv): riscv下能够运行hello world用户程序 (#770)

* feat(riscv): riscv下能够运行hello world用户程序
LoGin 10 months ago
parent
commit
471d65cf15

+ 1 - 1
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"] }
 
 

+ 2 - 0
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;

+ 1 - 1
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!(

+ 2 - 1
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,

+ 17 - 8
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();
     }

+ 4 - 2
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::<RiscV64MMArch>::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<MMArch, &mut BumpAllocator<MMArch>> =
             crate::mm::page::PageMapper::<MMArch, _>::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)
         {

+ 3 - 1
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);
 

+ 1 - 1
kernel/src/arch/riscv64/process/idle.rs

@@ -15,7 +15,7 @@ impl ProcessManager {
                 spin_loop();
             }
 
-            kdebug!("idle loop");
+            // kdebug!("idle loop");
         }
     }
 }

+ 1 - 0
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;
 

+ 78 - 16
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<String>, envp: Vec<String>) -> ! {
-    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::<TrapFrame>(),
+    );
+    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<ProcessControlBlock>, next: Arc<ProcessControlBlock>) {
         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)),
         }

+ 101 - 2
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<String>,
         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(());
     }
 
     /// ## 用于控制和查询与体系结构相关的进程特定选项

+ 2 - 1
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();
     }

+ 3 - 1
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() {

+ 1 - 0
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;

+ 1 - 1
kernel/src/driver/Makefile

@@ -1,7 +1,7 @@
 
 CFLAGS += -I .
 
-kernel_driver_subdirs:=acpi disk multiboot2 timers 
+kernel_driver_subdirs:=acpi multiboot2 
 
 ECHO:
 	@echo "$@"

+ 5 - 5
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(())

+ 0 - 10
kernel/src/driver/disk/Makefile

@@ -1,10 +0,0 @@
-SRC = $(wildcard *.c)
-OBJ = $(SRC:.c=.o)
-CFLAGS += -I .
-
-.PHONY: all
-
-all: $(OBJ)
-
-%.o: %.c
-	$(CC) $(CFLAGS) -c $< -o $@

+ 13 - 0
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")
+}

+ 9 - 0
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`

+ 42 - 4
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();

+ 21 - 1
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<PhysAddr>,
     /// uefi 内存保留表的物理地址
     pub memreserve_table_paddr: Option<PhysAddr>,
+    /// uefi esrt表的物理地址
+    pub esrt_table_paddr: Option<PhysAddr>,
 }
 
 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<InnerEFIManager> {
+        self.inner.read()
+    }
+
+    fn inner_write(&self) -> RwLockWriteGuard<InnerEFIManager> {
+        self.inner.write()
+    }
+
+    /// 是否存在ESRT表
+    fn esrt_table_exists(&self) -> bool {
+        self.inner_read().esrt_table_paddr.is_some()
+    }
 }
 
 // 在Rust中,我们使用枚举和bitflags来表示这些宏

+ 33 - 3
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<VirtAddr>,
+        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,

+ 1 - 1
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() {

+ 0 - 6
kernel/src/driver/timers/Makefile

@@ -1,6 +0,0 @@
-all: 
-
-CFLAGS += -I .
-
-#HPET.o: HPET/HPET.c
-#	$(CC) $(CFLAGS) -c HPET/HPET.c -o HPET/HPET.o

+ 3 - 2
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) };

+ 1 - 0
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);
 }

+ 12 - 12
kernel/src/libs/elf.rs

@@ -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<VirtAddr> = 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,
@@ -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)),
+                    }
                 })?;
 
             // 如果地址不对,那么就报错

+ 1 - 1
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,
         };
     }
 

+ 0 - 1
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();
 

+ 5 - 0
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,

+ 2 - 0
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的值

+ 35 - 14
kernel/src/mm/page.rs

@@ -530,9 +530,18 @@ impl<Arch: MemoryManagementArch> PageFlags<Arch> {
                     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<Arch: MemoryManagementArch> PageFlags<Arch> {
             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<Arch: MemoryManagementArch> PageFlags<Arch> {
     /// 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<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
         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,10 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
 
                     // 清空这个页帧
                     MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
-
                     // 设置页表项的flags
                     let flags: PageFlags<Arch> =
                         PageFlags::new_page_table(virt.kind() == PageTableKind::User);
 
-                    // kdebug!("Flags: {:?}", flags);
-
                     // 把新分配的页表映射到当前页表
                     table.set_entry(i, PageEntry::new(frame, flags));
 

+ 1 - 1
kernel/src/process/exec.rs

@@ -188,7 +188,7 @@ pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, Sys
         .load(param, &head_buf)
         .unwrap_or_else(|e| panic!("load_binary_file failed: error: {e:?}, param: {param:?}"));
 
-    // kdebug!("load_binary_file: load success");
+    // kdebug!("load_binary_file: load success: {result:?}");
     return Ok(result);
 }