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