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