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