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