diff --git a/kernel/src/arch/riscv64/mm/mod.rs b/kernel/src/arch/riscv64/mm/mod.rs index 4a907ca5..abf05f3d 100644 --- a/kernel/src/arch/riscv64/mm/mod.rs +++ b/kernel/src/arch/riscv64/mm/mod.rs @@ -19,7 +19,7 @@ use crate::{ smp::cpu::ProcessorId, }; -use self::init::riscv_mm_init; +use self::init::{riscv_mm_init, INITIAL_PGTABLE_VALUE}; pub mod bump; pub(super) mod init; @@ -185,7 +185,7 @@ impl MemoryManagementArch for RiscV64MMArch { } fn initial_page_table() -> PhysAddr { - todo!() + unsafe { INITIAL_PGTABLE_VALUE } } fn setup_new_usermapper() -> Result { diff --git a/kernel/src/arch/riscv64/process/idle.rs b/kernel/src/arch/riscv64/process/idle.rs index e374087f..196a709e 100644 --- a/kernel/src/arch/riscv64/process/idle.rs +++ b/kernel/src/arch/riscv64/process/idle.rs @@ -1,8 +1,6 @@ use core::hint::spin_loop; -use crate::{ - arch::CurrentIrqArch, exception::InterruptArch, kBUG, kdebug, process::ProcessManager, -}; +use crate::{arch::CurrentIrqArch, exception::InterruptArch, kBUG, process::ProcessManager}; impl ProcessManager { /// 每个核的idle进程 diff --git a/kernel/src/arch/riscv64/process/mod.rs b/kernel/src/arch/riscv64/process/mod.rs index 33a88562..460fd016 100644 --- a/kernel/src/arch/riscv64/process/mod.rs +++ b/kernel/src/arch/riscv64/process/mod.rs @@ -19,7 +19,7 @@ use crate::{ CurrentIrqArch, }, exception::InterruptArch, - kdebug, kerror, + kerror, libs::spinlock::SpinLockGuard, mm::VirtAddr, process::{ @@ -53,7 +53,7 @@ static BSP_IDLE_STACK_SPACE: InitProcUnion = InitProcUnion { idle_stack: [0; 32768], }; -pub unsafe fn arch_switch_to_user(path: String, argv: Vec, envp: Vec) -> ! { +pub unsafe fn arch_switch_to_user(trap_frame: TrapFrame) -> ! { // 以下代码不能发生中断 CurrentIrqArch::interrupt_disable(); @@ -69,28 +69,12 @@ pub unsafe fn arch_switch_to_user(path: String, argv: Vec, envp: Vec ! { asm!("ret", options(noreturn)); } -pub unsafe fn arch_switch_to_user(path: String, argv: Vec, envp: Vec) -> ! { +pub unsafe fn arch_switch_to_user(trap_frame: TrapFrame) -> ! { // 以下代码不能发生中断 CurrentIrqArch::interrupt_disable(); @@ -520,7 +516,6 @@ pub unsafe fn arch_switch_to_user(path: String, argv: Vec, envp: Vec(), ); // kdebug!("trap_frame_vaddr: {:?}", trap_frame_vaddr); - let new_rip = VirtAddr::new(ret_from_intr as usize); assert!( (x86::current::registers::rsp() as usize) < trap_frame_vaddr.data(), @@ -531,6 +526,7 @@ pub unsafe fn arch_switch_to_user(path: String, argv: Vec, envp: Vec, envp: Vec Result<(), SystemError> { return Ok(()); } -/// 执行第一个用户进程的函数(只应该被调用一次) -/// -/// 当进程管理重构完成后,这个函数应该被删除。调整为别的函数。 -#[no_mangle] -pub extern "C" fn rs_exec_init_process(frame: &mut TrapFrame) -> usize { - let path = String::from("/bin/shell.elf"); - let argv = vec![String::from("/bin/shell.elf")]; - let envp = vec![String::from("PATH=/bin")]; - let r = Syscall::do_execve(path, argv, envp, frame); - // kdebug!("rs_exec_init_process: r: {:?}\n", r); - return r.map(|_| 0).unwrap_or_else(|e| e.to_posix_errno() as usize); -} - /// syscall指令初始化函数 pub(super) unsafe fn init_syscall_64() { let mut efer = x86::msr::rdmsr(x86::msr::IA32_EFER); diff --git a/kernel/src/init/initial_kthread.rs b/kernel/src/init/initial_kthread.rs index 7b4b20b0..c13fe2a4 100644 --- a/kernel/src/init/initial_kthread.rs +++ b/kernel/src/init/initial_kthread.rs @@ -1,16 +1,19 @@ //! 这个文件内放置初始内核线程的代码。 -use alloc::string::String; +use core::sync::atomic::{compiler_fence, Ordering}; + +use alloc::string::{String, ToString}; use system_error::SystemError; use crate::{ - arch::process::arch_switch_to_user, + arch::{interrupt::TrapFrame, process::arch_switch_to_user}, driver::{net::e1000e::e1000e::e1000e_init, virtio::virtio::virtio_probe}, filesystem::vfs::core::mount_root_fs, kdebug, kerror, net::net_core::net_init, - process::{kthread::KernelThreadMechanism, stdio::stdio_init}, + process::{kthread::KernelThreadMechanism, stdio::stdio_init, ProcessFlags, ProcessManager}, smp::smp_init, + syscall::Syscall, }; use super::initcall::do_initcalls; @@ -21,8 +24,6 @@ pub fn initial_kernel_thread() -> i32 { }); switch_to_user(); - - unreachable!(); } fn kernel_init() -> Result<(), SystemError> { @@ -60,11 +61,52 @@ fn kenrel_init_freeable() -> Result<(), SystemError> { } /// 切换到用户态 -fn switch_to_user() { - const INIT_PROGRAM: &str = "/bin/dragonreach"; - let path = String::from(INIT_PROGRAM); +#[inline(never)] +fn switch_to_user() -> ! { + let current_pcb = ProcessManager::current_pcb(); + + // 删除kthread的标志 + current_pcb.flags().remove(ProcessFlags::KTHREAD); + current_pcb.worker_private().take(); + + *current_pcb.sched_info().sched_policy.write_irqsave() = crate::sched::SchedPolicy::CFS; + drop(current_pcb); + + let mut trap_frame = TrapFrame::new(); + // 逐个尝试运行init进程 + + if try_to_run_init_process("/bin/dragonreach", &mut trap_frame).is_err() + && try_to_run_init_process("/bin/init", &mut trap_frame).is_err() + && try_to_run_init_process("/bin/sh", &mut trap_frame).is_err() + { + panic!("Failed to run init process: No working init found."); + } + + // 需要确保执行到这里之后,上面所有的资源都已经释放(比如arc之类的) + + unsafe { arch_switch_to_user(trap_frame) }; +} + +fn try_to_run_init_process(path: &str, trap_frame: &mut TrapFrame) -> Result<(), SystemError> { + if let Err(e) = run_init_process(path.to_string(), trap_frame) { + if e != SystemError::ENOENT { + kerror!( + "Failed to run init process: {path} exists but couldn't execute it (error {:?})", + e + ); + } + return Err(e); + } + + Ok(()) +} + +fn run_init_process(path: String, trap_frame: &mut TrapFrame) -> Result<(), SystemError> { let argv = vec![path.clone()]; let envp = vec![String::from("PATH=/")]; - unsafe { arch_switch_to_user(path, argv, envp) }; + compiler_fence(Ordering::SeqCst); + Syscall::do_execve(path, argv, envp, trap_frame)?; + + Ok(()) }