From f75cb0f8ed754d94c3b2924519b785db3321c1d9 Mon Sep 17 00:00:00 2001 From: LoGin Date: Sat, 27 Apr 2024 15:35:24 +0800 Subject: [PATCH] =?UTF-8?q?refactor(process):=20=E8=B0=83=E6=95=B4arch=5Fs?= =?UTF-8?q?witch=5Fto=5Fuser=E5=87=BD=E6=95=B0=EF=BC=8C=E6=8A=8Ariscv?= =?UTF-8?q?=E5=92=8Cx86=5F64=E7=9A=84=E5=85=B1=E7=94=A8=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E6=8A=BD=E5=8F=96=E5=87=BA=E6=9D=A5=E3=80=82=20(#773)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(process): Extract common logic for riscv and x86_64 in arch_switch_to_user to run_init_process 调整arch_switch_to_user函数,把riscv和x86_64的共用逻辑抽取出来。写成run_init_process函数,并且能够尝试运行多个不同的init程序,直到某个运行成功 --- kernel/src/arch/riscv64/mm/mod.rs | 4 +- kernel/src/arch/riscv64/process/idle.rs | 4 +- kernel/src/arch/riscv64/process/mod.rs | 22 ++------ kernel/src/arch/riscv64/process/syscall.rs | 6 +-- kernel/src/arch/riscv64/syscall/mod.rs | 2 +- kernel/src/arch/x86_64/process/mod.rs | 29 ++--------- kernel/src/arch/x86_64/process/syscall.rs | 3 +- kernel/src/arch/x86_64/syscall/mod.rs | 14 ----- kernel/src/init/initial_kthread.rs | 60 ++++++++++++++++++---- 9 files changed, 65 insertions(+), 79 deletions(-) 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(()) }