Browse Source

riscv: copy-thread (#696)

LoGin 11 months ago
parent
commit
e8eab1ac82

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

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

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

+ 33 - 5
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<KernelThreadCreateInfo>,
         clone_flags: CloneFlags,
     ) -> Result<Pid, SystemError> {
-        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);
     }
 }
 

+ 60 - 7
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::<TrapFrame>();
+        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,