xref: /DragonOS/kernel/src/arch/riscv64/process/mod.rs (revision f049d1af01da7b92f312245ed411b22475b76065)
1 use alloc::{
2     string::String,
3     sync::{Arc, Weak},
4     vec::Vec,
5 };
6 use core::{
7     arch::asm,
8     intrinsics::unlikely,
9     mem::ManuallyDrop,
10     sync::atomic::{compiler_fence, Ordering},
11 };
12 use kdepends::memoffset::offset_of;
13 use system_error::SystemError;
14 
15 use crate::{
16     arch::{
17         interrupt::entry::ret_from_exception, process::kthread::kernel_thread_bootstrap_stage1,
18         CurrentIrqArch,
19     },
20     exception::InterruptArch,
21     kdebug, kerror,
22     libs::spinlock::SpinLockGuard,
23     mm::VirtAddr,
24     process::{
25         fork::{CloneFlags, KernelCloneArgs},
26         switch_finish_hook, KernelStack, ProcessControlBlock, ProcessFlags, ProcessManager,
27         PROCESS_SWITCH_RESULT,
28     },
29     smp::cpu::ProcessorId,
30 };
31 
32 use super::{
33     cpu::{local_context, LocalContext},
34     interrupt::TrapFrame,
35 };
36 
37 pub mod idle;
38 pub mod kthread;
39 pub mod syscall;
40 
41 #[allow(dead_code)]
42 #[repr(align(32768))]
43 union InitProcUnion {
44     /// 用于存放idle进程的内核栈
45     idle_stack: [u8; 32768],
46 }
47 
48 #[link_section = ".data.init_proc_union"]
49 #[no_mangle]
50 static BSP_IDLE_STACK_SPACE: InitProcUnion = InitProcUnion {
51     idle_stack: [0; 32768],
52 };
53 
54 pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<String>) -> ! {
55     unimplemented!("RiscV64 arch_switch_to_user")
56 }
57 
58 impl ProcessManager {
59     pub fn arch_init() {
60         // do nothing
61     }
62 
63     /// fork的过程中复制线程
64     ///
65     /// 由于这个过程与具体的架构相关,所以放在这里
66     pub fn copy_thread(
67         current_pcb: &Arc<ProcessControlBlock>,
68         new_pcb: &Arc<ProcessControlBlock>,
69         clone_args: KernelCloneArgs,
70         current_trapframe: &TrapFrame,
71     ) -> Result<(), SystemError> {
72         let clone_flags = clone_args.flags;
73         let mut child_trapframe = *current_trapframe;
74 
75         // 子进程的返回值为0
76         child_trapframe.set_return_value(0);
77 
78         // 设置子进程的栈基址(开始执行中断返回流程时的栈基址)
79         let mut new_arch_guard = unsafe { new_pcb.arch_info() };
80         let kernel_stack_guard = new_pcb.kernel_stack();
81         let trap_frame_vaddr: VirtAddr =
82             kernel_stack_guard.stack_max_address() - core::mem::size_of::<TrapFrame>();
83         new_arch_guard.set_stack(trap_frame_vaddr);
84 
85         // 拷贝栈帧
86         unsafe {
87             let usp = clone_args.stack;
88             if usp != 0 {
89                 child_trapframe.sp = usp;
90             }
91             let trap_frame_ptr = trap_frame_vaddr.data() as *mut TrapFrame;
92             *trap_frame_ptr = child_trapframe;
93         }
94 
95         // copy arch info
96 
97         let current_arch_guard = current_pcb.arch_info_irqsave();
98         // 拷贝浮点寄存器的状态
99         new_arch_guard.fp_state = current_arch_guard.fp_state;
100 
101         drop(current_arch_guard);
102 
103         // 设置返回地址(子进程开始执行的指令地址)
104         if new_pcb.flags().contains(ProcessFlags::KTHREAD) {
105             let kthread_bootstrap_stage1_func_addr = kernel_thread_bootstrap_stage1 as usize;
106             new_arch_guard.ra = kthread_bootstrap_stage1_func_addr;
107         } else {
108             new_arch_guard.ra = ret_from_exception as usize;
109         }
110 
111         // 设置tls
112         if clone_flags.contains(CloneFlags::CLONE_SETTLS) {
113             drop(new_arch_guard);
114             todo!("set tls");
115         }
116 
117         return Ok(());
118     }
119 
120     /// 切换进程
121     ///
122     /// ## 参数
123     ///
124     /// - `prev`:上一个进程的pcb
125     /// - `next`:下一个进程的pcb
126     ///
127     /// 参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/include/asm/switch_to.h#76
128     pub unsafe fn switch_process(prev: Arc<ProcessControlBlock>, next: Arc<ProcessControlBlock>) {
129         assert!(!CurrentIrqArch::is_irq_enabled());
130         kdebug!(
131             "riscv switch process: prev: {:?}, next: {:?}",
132             prev.pid(),
133             next.pid()
134         );
135         Self::switch_process_fpu(&prev, &next);
136         kdebug!("riscv switch process: after switch_process_fpu");
137         Self::switch_local_context(&prev, &next);
138         kdebug!("riscv switch process: after switch_local_context");
139 
140         // 切换地址空间
141         let next_addr_space = next.basic().user_vm().as_ref().unwrap().clone();
142         compiler_fence(Ordering::SeqCst);
143 
144         next_addr_space.read().user_mapper.utable.make_current();
145         kdebug!("riscv switch process: after switch addr space");
146         drop(next_addr_space);
147         compiler_fence(Ordering::SeqCst);
148 
149         // 获取arch info的锁,并强制泄露其守卫(切换上下文后,在switch_finish_hook中会释放锁)
150         let next_arch = SpinLockGuard::leak(next.arch_info_irqsave()) as *mut ArchPCBInfo;
151         let prev_arch = SpinLockGuard::leak(prev.arch_info_irqsave()) as *mut ArchPCBInfo;
152 
153         // 恢复当前的 preempt count*2
154         ProcessManager::current_pcb().preempt_enable();
155         ProcessManager::current_pcb().preempt_enable();
156         PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev);
157         PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next);
158         kdebug!("riscv switch process: before to inner");
159         compiler_fence(Ordering::SeqCst);
160         // 正式切换上下文
161         switch_to_inner(prev_arch, next_arch);
162     }
163 
164     fn switch_process_fpu(prev: &Arc<ProcessControlBlock>, next: &Arc<ProcessControlBlock>) {
165         let prev_regs = unsafe { Self::task_trapframe(prev) };
166         let next_regs = unsafe { Self::task_trapframe(next) };
167         if unlikely(prev_regs.status.sd()) {
168             prev.arch_info_irqsave().fp_state.save(prev_regs);
169         }
170         next.arch_info_irqsave().fp_state.restore(next_regs);
171     }
172 
173     fn switch_local_context(prev: &Arc<ProcessControlBlock>, next: &Arc<ProcessControlBlock>) {
174         prev.arch_info_irqsave().local_context = *local_context().get();
175         local_context()
176             .get_mut()
177             .restore(&next.arch_info_irqsave().local_context);
178     }
179 
180     unsafe fn task_trapframe(task: &Arc<ProcessControlBlock>) -> &mut TrapFrame {
181         let mut sp = task.kernel_stack().stack_max_address().data();
182         sp -= core::mem::size_of::<TrapFrame>();
183         return (sp as *mut TrapFrame).as_mut().unwrap();
184     }
185 }
186 
187 /// 切换上下文
188 ///
189 /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/kernel/entry.S#233
190 #[naked]
191 unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBInfo) {
192     core::arch::asm!(concat!(
193         "
194             sd ra, {off_ra}(a0)
195             sd sp, {off_sp}(a0)
196             sd s0, {off_s0}(a0)
197             sd s1, {off_s1}(a0)
198             sd s2, {off_s2}(a0)
199             sd s3, {off_s3}(a0)
200             sd s4, {off_s4}(a0)
201             sd s5, {off_s5}(a0)
202             sd s6, {off_s6}(a0)
203             sd s7, {off_s7}(a0)
204             sd s8, {off_s8}(a0)
205             sd s9, {off_s9}(a0)
206             sd s10, {off_s10}(a0)
207             sd s11, {off_s11}(a0)
208 
209 
210             ld sp, {off_sp}(a1)
211             ld s0, {off_s0}(a1)
212             ld s1, {off_s1}(a1)
213             ld s2, {off_s2}(a1)
214             ld s3, {off_s3}(a1)
215             ld s4, {off_s4}(a1)
216             ld s5, {off_s5}(a1)
217             ld s6, {off_s6}(a1)
218             ld s7, {off_s7}(a1)
219             ld s8, {off_s8}(a1)
220             ld s9, {off_s9}(a1)
221             ld s10, {off_s10}(a1)
222             ld s11, {off_s11}(a1)
223 
224             // 将ra设置为标签1,并跳转到before_switch_finish_hook
225             la ra, 1f
226             j {before_switch_finish_hook}
227 
228             1:
229             ld sp, {off_sp}(a1)
230             ld ra, {off_ra}(a1)
231             ret
232 
233         "
234     ),
235     off_ra = const(offset_of!(ArchPCBInfo, ra)),
236     off_sp = const(offset_of!(ArchPCBInfo, ksp)),
237     off_s0 = const(offset_of!(ArchPCBInfo, s0)),
238     off_s1 = const(offset_of!(ArchPCBInfo, s1)),
239     off_s2 = const(offset_of!(ArchPCBInfo, s2)),
240     off_s3 = const(offset_of!(ArchPCBInfo, s3)),
241     off_s4 = const(offset_of!(ArchPCBInfo, s4)),
242     off_s5 = const(offset_of!(ArchPCBInfo, s5)),
243     off_s6 = const(offset_of!(ArchPCBInfo, s6)),
244     off_s7 = const(offset_of!(ArchPCBInfo, s7)),
245     off_s8 = const(offset_of!(ArchPCBInfo, s8)),
246     off_s9 = const(offset_of!(ArchPCBInfo, s9)),
247     off_s10 = const(offset_of!(ArchPCBInfo, s10)),
248     off_s11 = const(offset_of!(ArchPCBInfo, s11)),
249     before_switch_finish_hook = sym before_switch_finish_hook,
250     options(noreturn));
251 }
252 
253 /// 在切换上下文完成后的钩子函数(必须在这里加一个跳转函数,否则会出现relocation truncated to fit: R_RISCV_JAL错误)
254 unsafe extern "C" fn before_switch_finish_hook() {
255     let pcb = ProcessManager::current_pcb();
256     kdebug!(
257         "before_switch_finish_hook, pid: {:?}, name: {:?}",
258         pcb.pid(),
259         pcb.basic().name()
260     );
261     switch_finish_hook();
262     kdebug!("after switch_finish_hook");
263 }
264 
265 impl ProcessControlBlock {
266     /// 获取当前进程的pcb
267     pub fn arch_current_pcb() -> Arc<Self> {
268         // 获取栈指针
269         let mut sp: usize;
270         unsafe { asm!("mv {}, sp", lateout(reg) sp, options(nostack)) };
271         let ptr = VirtAddr::new(sp);
272 
273         let stack_base = VirtAddr::new(ptr.data() & (!(KernelStack::ALIGN - 1)));
274 
275         // 从内核栈的最低地址处取出pcb的地址
276         let p = stack_base.data() as *const *const ProcessControlBlock;
277         if core::intrinsics::unlikely((unsafe { *p }).is_null()) {
278             kerror!("p={:p}", p);
279             panic!("current_pcb is null");
280         }
281         unsafe {
282             // 为了防止内核栈的pcb weak 指针被释放,这里需要将其包装一下
283             let weak_wrapper: ManuallyDrop<Weak<ProcessControlBlock>> =
284                 ManuallyDrop::new(Weak::from_raw(*p));
285 
286             let new_arc: Arc<ProcessControlBlock> = weak_wrapper.upgrade().unwrap();
287             return new_arc;
288         }
289     }
290 }
291 
292 /// PCB中与架构相关的信息
293 #[derive(Debug, Clone, Copy)]
294 #[allow(dead_code)]
295 #[repr(C)]
296 pub struct ArchPCBInfo {
297     ra: usize,
298     ksp: usize,
299     s0: usize,
300     s1: usize,
301     s2: usize,
302     s3: usize,
303     s4: usize,
304     s5: usize,
305     s6: usize,
306     s7: usize,
307     s8: usize,
308     s9: usize,
309     s10: usize,
310     s11: usize,
311 
312     fp_state: FpDExtState,
313     local_context: LocalContext,
314 }
315 
316 #[allow(dead_code)]
317 impl ArchPCBInfo {
318     /// 创建一个新的ArchPCBInfo
319     ///
320     /// ## 参数
321     ///
322     /// - `kstack`:内核栈的引用
323     ///
324     /// ## 返回值
325     ///
326     /// 返回一个新的ArchPCBInfo
327     pub fn new(kstack: &KernelStack) -> Self {
328         Self {
329             ra: 0,
330             ksp: kstack.stack_max_address().data(),
331             s0: 0,
332             s1: 0,
333             s2: 0,
334             s3: 0,
335             s4: 0,
336             s5: 0,
337             s6: 0,
338             s7: 0,
339             s8: 0,
340             s9: 0,
341             s10: 0,
342             s11: 0,
343             fp_state: FpDExtState::new(),
344             local_context: LocalContext::new(ProcessorId::new(0)),
345         }
346     }
347     // ### 从另一个ArchPCBInfo处clone,但是保留部分字段不变
348     pub fn clone_from(&mut self, from: &Self) {
349         *self = from.clone();
350     }
351 
352     pub fn set_stack(&mut self, stack: VirtAddr) {
353         self.ksp = stack.data();
354     }
355 }
356 
357 #[repr(C)]
358 #[derive(Debug, Clone, Copy)]
359 struct FpDExtState {
360     f: [u64; 32],
361     fcsr: u32,
362 }
363 
364 impl FpDExtState {
365     /// 创建一个新的FpState
366     const fn new() -> Self {
367         Self {
368             f: [0; 32],
369             fcsr: 0,
370         }
371     }
372 
373     fn save(&mut self, regs: &mut TrapFrame) {
374         if regs.status.fs() == riscv::register::sstatus::FS::Dirty {
375             self.do_save();
376             self.do_clean(regs);
377         }
378     }
379 
380     fn restore(&mut self, regs: &mut TrapFrame) {
381         if regs.status.fs() != riscv::register::sstatus::FS::Off {
382             self.do_restore();
383             self.do_clean(regs);
384         }
385     }
386 
387     fn do_clean(&mut self, regs: &mut TrapFrame) {
388         regs.status.update_fs(riscv::register::sstatus::FS::Clean);
389     }
390 
391     fn do_save(&mut self) {
392         compiler_fence(Ordering::SeqCst);
393         unsafe {
394             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Initial);
395             asm!("frcsr {0}", lateout(reg) self.fcsr);
396             asm!(concat!(
397                     "
398                 // 为原来的a0寄存器的值在堆栈上分配空间
399                 addi sp, sp, -8
400                 sd a0, 0(sp)
401                 mv a0, {0}
402 
403                 fsd f0, 0(a0)
404                 fsd f1, 8(a0)
405                 fsd f2, 16(a0)
406                 fsd f3, 24(a0)
407                 fsd f4, 32(a0)
408                 fsd f5, 40(a0)
409                 fsd f6, 48(a0)
410                 fsd f7, 56(a0)
411                 fsd f8, 64(a0)
412                 fsd f9, 72(a0)
413                 fsd f10, 80(a0)
414                 fsd f11, 88(a0)
415                 fsd f12, 96(a0)
416                 fsd f13, 104(a0)
417                 fsd f14, 112(a0)
418                 fsd f15, 120(a0)
419                 fsd f16, 128(a0)
420                 fsd f17, 136(a0)
421                 fsd f18, 144(a0)
422                 fsd f19, 152(a0)
423                 fsd f20, 160(a0)
424                 fsd f21, 168(a0)
425                 fsd f22, 176(a0)
426                 fsd f23, 184(a0)
427                 fsd f24, 192(a0)
428                 fsd f25, 200(a0)
429                 fsd f26, 208(a0)
430                 fsd f27, 216(a0)
431                 fsd f28, 224(a0)
432                 fsd f29, 232(a0)
433                 fsd f30, 240(a0)
434                 fsd f31, 248(a0)
435 
436                 // 恢复a0寄存器的值
437                 ld a0, 0(sp)
438                 addi sp, sp, 8
439                 "
440                 ),
441                 in (reg) &self.f as *const _,
442             );
443             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off);
444         }
445 
446         compiler_fence(Ordering::SeqCst);
447     }
448 
449     fn do_restore(&mut self) {
450         compiler_fence(Ordering::SeqCst);
451         let fcsr = self.fcsr;
452         unsafe {
453             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Initial);
454             compiler_fence(Ordering::SeqCst);
455             asm!(concat!(
456                     "
457             // 为原来的a0寄存器的值在堆栈上分配空间
458             addi sp, sp, -8
459             sd a0, 0(sp)
460             mv a0, {0}
461 
462             fld f0, 0(a0)
463             fld f1, 8(a0)
464             fld f2, 16(a0)
465             fld f3, 24(a0)
466             fld f4, 32(a0)
467             fld f5, 40(a0)
468             fld f6, 48(a0)
469             fld f7, 56(a0)
470             fld f8, 64(a0)
471             fld f9, 72(a0)
472             fld f10, 80(a0)
473             fld f11, 88(a0)
474             fld f12, 96(a0)
475             fld f13, 104(a0)
476             fld f14, 112(a0)
477             fld f15, 120(a0)
478             fld f16, 128(a0)
479             fld f17, 136(a0)
480             fld f18, 144(a0)
481             fld f19, 152(a0)
482             fld f20, 160(a0)
483             fld f21, 168(a0)
484             fld f22, 176(a0)
485             fld f23, 184(a0)
486             fld f24, 192(a0)
487             fld f25, 200(a0)
488             fld f26, 208(a0)
489             fld f27, 216(a0)
490             fld f28, 224(a0)
491             fld f29, 232(a0)
492             fld f30, 240(a0)
493             fld f31, 248(a0)
494 
495             // 恢复a0寄存器的值
496             ld a0, 0(sp)
497             addi sp, sp, 8
498             "
499                 ),
500                 in (reg) &self.f as *const _,
501             );
502             compiler_fence(Ordering::SeqCst);
503             asm!("fscsr {0}", in(reg) fcsr);
504             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off);
505         }
506         compiler_fence(Ordering::SeqCst);
507     }
508 }
509