From e8eab1ac824e1b1e638e50debb8326dfed4f05e5 Mon Sep 17 00:00:00 2001 From: LoGin Date: Fri, 5 Apr 2024 16:37:08 +0800 Subject: [PATCH] riscv: copy-thread (#696) --- kernel/Cargo.toml | 2 +- kernel/src/arch/riscv64/interrupt/entry.rs | 2 +- kernel/src/arch/riscv64/interrupt/mod.rs | 45 +++++++++++++++ kernel/src/arch/riscv64/process/kthread.rs | 38 ++++++++++-- kernel/src/arch/riscv64/process/mod.rs | 67 +++++++++++++++++++--- 5 files changed, 140 insertions(+), 14 deletions(-) diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 3a00ba65..941fe9f8 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -62,7 +62,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 = "01fc40d", features = [ "s-mode" ] } +riscv = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/riscv.git", revision = "bf771288c3", features = [ "s-mode" ] } sbi-rt = { version = "=0.0.3", features = ["legacy"] } diff --git a/kernel/src/arch/riscv64/interrupt/entry.rs b/kernel/src/arch/riscv64/interrupt/entry.rs index a5942c38..121f2ae2 100644 --- a/kernel/src/arch/riscv64/interrupt/entry.rs +++ b/kernel/src/arch/riscv64/interrupt/entry.rs @@ -242,7 +242,7 @@ unsafe extern "C" fn _save_context() -> ! { #[naked] #[no_mangle] -unsafe extern "C" fn ret_from_exception() -> ! { +pub unsafe extern "C" fn ret_from_exception() -> ! { asm!( concat!(" ld s0, {off_status}(sp) diff --git a/kernel/src/arch/riscv64/interrupt/mod.rs b/kernel/src/arch/riscv64/interrupt/mod.rs index e9a18572..8285cbce 100644 --- a/kernel/src/arch/riscv64/interrupt/mod.rs +++ b/kernel/src/arch/riscv64/interrupt/mod.rs @@ -111,4 +111,49 @@ impl TrapFrame { pub fn is_from_user(&self) -> bool { self.status.spp() == riscv::register::sstatus::SPP::User } + + pub fn new() -> Self { + Self { + epc: 0, + ra: 0, + sp: 0, + gp: 0, + tp: 0, + t0: 0, + t1: 0, + t2: 0, + s0: 0, + s1: 0, + a0: 0, + a1: 0, + a2: 0, + a3: 0, + a4: 0, + a5: 0, + a6: 0, + a7: 0, + s2: 0, + s3: 0, + s4: 0, + s5: 0, + s6: 0, + s7: 0, + s8: 0, + s9: 0, + s10: 0, + s11: 0, + t3: 0, + t4: 0, + t5: 0, + t6: 0, + status: unsafe { core::mem::zeroed() }, + badaddr: 0, + cause: unsafe { core::mem::zeroed() }, + origin_a0: 0, + } + } + + pub fn set_return_value(&mut self, value: usize) { + self.a0 = value; + } } diff --git a/kernel/src/arch/riscv64/process/kthread.rs b/kernel/src/arch/riscv64/process/kthread.rs index 4f833387..5f48092c 100644 --- a/kernel/src/arch/riscv64/process/kthread.rs +++ b/kernel/src/arch/riscv64/process/kthread.rs @@ -1,10 +1,14 @@ use alloc::sync::Arc; +use riscv::register::sstatus::SPP; use system_error::SystemError; -use crate::process::{ - fork::CloneFlags, - kthread::{KernelThreadCreateInfo, KernelThreadMechanism}, - Pid, +use crate::{ + arch::interrupt::TrapFrame, + process::{ + fork::CloneFlags, + kthread::{KernelThreadCreateInfo, KernelThreadMechanism}, + Pid, ProcessManager, + }, }; impl KernelThreadMechanism { @@ -13,11 +17,35 @@ impl KernelThreadMechanism { /// ## 返回值 /// /// 返回创建的内核线程的pid + #[inline(never)] pub fn __inner_create( info: &Arc, clone_flags: CloneFlags, ) -> Result { - unimplemented!("KernelThreadMechanism::__inner_create") + // WARNING: If create failed, we must drop the info manually or it will cause memory leak. (refcount will not decrease when create failed) + let create_info: *const KernelThreadCreateInfo = + KernelThreadCreateInfo::generate_unsafe_arc_ptr(info.clone()); + + let mut frame = TrapFrame::new(); + frame.a0 = create_info as usize; + + // 使能中断 + frame.status.update_sie(true); + frame.status.update_spp(SPP::Supervisor); + + frame.ra = kernel_thread_bootstrap_stage1 as usize; + + // fork失败的话,子线程不会执行。否则将导致内存安全问题。 + let pid = ProcessManager::fork(&frame, clone_flags).map_err(|e| { + unsafe { KernelThreadCreateInfo::parse_unsafe_arc_ptr(create_info) }; + e + })?; + + ProcessManager::find(pid) + .unwrap() + .set_name(info.name().clone()); + + return Ok(pid); } } diff --git a/kernel/src/arch/riscv64/process/mod.rs b/kernel/src/arch/riscv64/process/mod.rs index a62a17ef..56152895 100644 --- a/kernel/src/arch/riscv64/process/mod.rs +++ b/kernel/src/arch/riscv64/process/mod.rs @@ -13,16 +13,20 @@ use kdepends::memoffset::offset_of; use system_error::SystemError; use crate::{ - arch::CurrentIrqArch, + arch::{ + interrupt::entry::ret_from_exception, process::kthread::kernel_thread_bootstrap_stage1, + CurrentIrqArch, + }, exception::InterruptArch, kerror, libs::spinlock::SpinLockGuard, mm::VirtAddr, process::{ - fork::KernelCloneArgs, KernelStack, ProcessControlBlock, ProcessManager, - PROCESS_SWITCH_RESULT, + fork::{CloneFlags, KernelCloneArgs}, + KernelStack, ProcessControlBlock, ProcessFlags, ProcessManager, PROCESS_SWITCH_RESULT, }, smp::cpu::ProcessorId, + syscall::Syscall, }; use super::{ @@ -65,7 +69,52 @@ impl ProcessManager { clone_args: KernelCloneArgs, current_trapframe: &TrapFrame, ) -> Result<(), SystemError> { - unimplemented!("ProcessManager::copy_thread") + let clone_flags = clone_args.flags; + let mut child_trapframe = *current_trapframe; + + // 子进程的返回值为0 + child_trapframe.set_return_value(0); + + // 设置子进程的栈基址(开始执行中断返回流程时的栈基址) + let mut new_arch_guard = unsafe { new_pcb.arch_info() }; + let kernel_stack_guard = new_pcb.kernel_stack(); + let trap_frame_vaddr: VirtAddr = + kernel_stack_guard.stack_max_address() - core::mem::size_of::(); + new_arch_guard.set_stack(trap_frame_vaddr); + + // 拷贝栈帧 + unsafe { + let usp = clone_args.stack; + if usp != 0 { + child_trapframe.sp = usp; + } + let trap_frame_ptr = trap_frame_vaddr.data() as *mut TrapFrame; + *trap_frame_ptr = child_trapframe; + } + + // copy arch info + + let current_arch_guard = current_pcb.arch_info_irqsave(); + // 拷贝浮点寄存器的状态 + new_arch_guard.fp_state = current_arch_guard.fp_state; + + drop(current_arch_guard); + + // 设置返回地址(子进程开始执行的指令地址) + if new_pcb.flags().contains(ProcessFlags::KTHREAD) { + let kthread_bootstrap_stage1_func_addr = kernel_thread_bootstrap_stage1 as usize; + new_arch_guard.ra = kthread_bootstrap_stage1_func_addr; + } else { + new_arch_guard.ra = ret_from_exception as usize; + } + + // 设置tls + if clone_flags.contains(CloneFlags::CLONE_SETTLS) { + drop(new_arch_guard); + todo!("set tls"); + } + + return Ok(()); } /// 切换进程 @@ -221,7 +270,7 @@ impl ProcessControlBlock { } /// PCB中与架构相关的信息 -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] #[allow(dead_code)] #[repr(C)] pub struct ArchPCBInfo { @@ -277,12 +326,16 @@ impl ArchPCBInfo { } // ### 从另一个ArchPCBInfo处clone,但是保留部分字段不变 pub fn clone_from(&mut self, from: &Self) { - unimplemented!("ArchPCBInfo::clone_from") + *self = from.clone(); + } + + pub fn set_stack(&mut self, stack: VirtAddr) { + self.ksp = stack.data(); } } #[repr(C)] -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] struct FpDExtState { f: [u64; 32], fcsr: u32,