xref: /DragonOS/kernel/src/arch/riscv64/process/mod.rs (revision 4b0170bd6bb374d0e9699a0076cc23b976ad6db7)
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     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         Self::switch_process_fpu(&prev, &next);
131         Self::switch_local_context(&prev, &next);
132 
133         // 切换地址空间
134         let next_addr_space = next.basic().user_vm().as_ref().unwrap().clone();
135         compiler_fence(Ordering::SeqCst);
136 
137         next_addr_space.read().user_mapper.utable.make_current();
138         drop(next_addr_space);
139         compiler_fence(Ordering::SeqCst);
140 
141         // 获取arch info的锁,并强制泄露其守卫(切换上下文后,在switch_finish_hook中会释放锁)
142         let next_arch = SpinLockGuard::leak(next.arch_info_irqsave()) as *mut ArchPCBInfo;
143         let prev_arch = SpinLockGuard::leak(prev.arch_info_irqsave()) as *mut ArchPCBInfo;
144 
145         // 恢复当前的 preempt count*2
146         ProcessManager::current_pcb().preempt_enable();
147         ProcessManager::current_pcb().preempt_enable();
148         PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev);
149         PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next);
150         // kdebug!("switch tss ok");
151         compiler_fence(Ordering::SeqCst);
152         // 正式切换上下文
153         switch_to_inner(prev_arch, next_arch);
154     }
155 
156     fn switch_process_fpu(prev: &Arc<ProcessControlBlock>, next: &Arc<ProcessControlBlock>) {
157         let prev_regs = unsafe { Self::task_trapframe(prev) };
158         let next_regs = unsafe { Self::task_trapframe(next) };
159         if unlikely(prev_regs.status.sd()) {
160             prev.arch_info_irqsave().fp_state.save(prev_regs);
161         }
162         next.arch_info_irqsave().fp_state.restore(next_regs);
163     }
164 
165     fn switch_local_context(prev: &Arc<ProcessControlBlock>, next: &Arc<ProcessControlBlock>) {
166         prev.arch_info_irqsave().local_context = *local_context().get();
167         local_context()
168             .get_mut()
169             .restore(&next.arch_info_irqsave().local_context);
170     }
171 
172     unsafe fn task_trapframe(task: &Arc<ProcessControlBlock>) -> &mut TrapFrame {
173         let mut sp = task.kernel_stack().stack_max_address().data();
174         sp -= core::mem::size_of::<TrapFrame>();
175         return (sp as *mut TrapFrame).as_mut().unwrap();
176     }
177 }
178 
179 /// 切换上下文
180 ///
181 /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/kernel/entry.S#233
182 #[naked]
183 unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBInfo) {
184     core::arch::asm!(concat!(
185         "
186             sd ra, {off_ra}(a0)
187             sd sp, {off_sp}(a0)
188             sd s0, {off_s0}(a0)
189             sd s1, {off_s1}(a0)
190             sd s2, {off_s2}(a0)
191             sd s3, {off_s3}(a0)
192             sd s4, {off_s4}(a0)
193             sd s5, {off_s5}(a0)
194             sd s6, {off_s6}(a0)
195             sd s7, {off_s7}(a0)
196             sd s8, {off_s8}(a0)
197             sd s9, {off_s9}(a0)
198             sd s10, {off_s10}(a0)
199             sd s11, {off_s11}(a0)
200 
201 
202             ld sp, {off_sp}(a1)
203             ld s0, {off_s0}(a1)
204             ld s1, {off_s1}(a1)
205             ld s2, {off_s2}(a1)
206             ld s3, {off_s3}(a1)
207             ld s4, {off_s4}(a1)
208             ld s5, {off_s5}(a1)
209             ld s6, {off_s6}(a1)
210             ld s7, {off_s7}(a1)
211             ld s8, {off_s8}(a1)
212             ld s9, {off_s9}(a1)
213             ld s10, {off_s10}(a1)
214             ld s11, {off_s11}(a1)
215 
216             // 将ra设置为标签1,并跳转到before_switch_finish_hook
217             la ra, 1f
218             j {before_switch_finish_hook}
219 
220             1:
221             ld sp, {off_sp}(a1)
222             ld ra, {off_ra}(a1)
223             ret
224 
225         "
226     ),
227     off_ra = const(offset_of!(ArchPCBInfo, ra)),
228     off_sp = const(offset_of!(ArchPCBInfo, ksp)),
229     off_s0 = const(offset_of!(ArchPCBInfo, s0)),
230     off_s1 = const(offset_of!(ArchPCBInfo, s1)),
231     off_s2 = const(offset_of!(ArchPCBInfo, s2)),
232     off_s3 = const(offset_of!(ArchPCBInfo, s3)),
233     off_s4 = const(offset_of!(ArchPCBInfo, s4)),
234     off_s5 = const(offset_of!(ArchPCBInfo, s5)),
235     off_s6 = const(offset_of!(ArchPCBInfo, s6)),
236     off_s7 = const(offset_of!(ArchPCBInfo, s7)),
237     off_s8 = const(offset_of!(ArchPCBInfo, s8)),
238     off_s9 = const(offset_of!(ArchPCBInfo, s9)),
239     off_s10 = const(offset_of!(ArchPCBInfo, s10)),
240     off_s11 = const(offset_of!(ArchPCBInfo, s11)),
241     before_switch_finish_hook = sym before_switch_finish_hook,
242     options(noreturn));
243 }
244 
245 /// 在切换上下文完成后的钩子函数(必须在这里加一个跳转函数,否则会出现relocation truncated to fit: R_RISCV_JAL错误)
246 unsafe extern "C" fn before_switch_finish_hook() {
247     switch_finish_hook();
248 }
249 
250 impl ProcessControlBlock {
251     /// 获取当前进程的pcb
252     pub fn arch_current_pcb() -> Arc<Self> {
253         // 获取栈指针
254         let mut sp: usize;
255         unsafe { asm!("mv {}, sp", lateout(reg) sp, options(nostack)) };
256         let ptr = VirtAddr::new(sp);
257 
258         let stack_base = VirtAddr::new(ptr.data() & (!(KernelStack::ALIGN - 1)));
259 
260         // 从内核栈的最低地址处取出pcb的地址
261         let p = stack_base.data() as *const *const ProcessControlBlock;
262         if core::intrinsics::unlikely((unsafe { *p }).is_null()) {
263             kerror!("p={:p}", p);
264             panic!("current_pcb is null");
265         }
266         unsafe {
267             // 为了防止内核栈的pcb weak 指针被释放,这里需要将其包装一下
268             let weak_wrapper: ManuallyDrop<Weak<ProcessControlBlock>> =
269                 ManuallyDrop::new(Weak::from_raw(*p));
270 
271             let new_arc: Arc<ProcessControlBlock> = weak_wrapper.upgrade().unwrap();
272             return new_arc;
273         }
274     }
275 }
276 
277 /// PCB中与架构相关的信息
278 #[derive(Debug, Clone, Copy)]
279 #[allow(dead_code)]
280 #[repr(C)]
281 pub struct ArchPCBInfo {
282     ra: usize,
283     ksp: usize,
284     s0: usize,
285     s1: usize,
286     s2: usize,
287     s3: usize,
288     s4: usize,
289     s5: usize,
290     s6: usize,
291     s7: usize,
292     s8: usize,
293     s9: usize,
294     s10: usize,
295     s11: usize,
296 
297     fp_state: FpDExtState,
298     local_context: LocalContext,
299 }
300 
301 #[allow(dead_code)]
302 impl ArchPCBInfo {
303     /// 创建一个新的ArchPCBInfo
304     ///
305     /// ## 参数
306     ///
307     /// - `kstack`:内核栈的引用
308     ///
309     /// ## 返回值
310     ///
311     /// 返回一个新的ArchPCBInfo
312     pub fn new(kstack: &KernelStack) -> Self {
313         Self {
314             ra: 0,
315             ksp: kstack.stack_max_address().data(),
316             s0: 0,
317             s1: 0,
318             s2: 0,
319             s3: 0,
320             s4: 0,
321             s5: 0,
322             s6: 0,
323             s7: 0,
324             s8: 0,
325             s9: 0,
326             s10: 0,
327             s11: 0,
328             fp_state: FpDExtState::new(),
329             local_context: LocalContext::new(ProcessorId::new(0)),
330         }
331     }
332     // ### 从另一个ArchPCBInfo处clone,但是保留部分字段不变
333     pub fn clone_from(&mut self, from: &Self) {
334         *self = from.clone();
335     }
336 
337     pub fn set_stack(&mut self, stack: VirtAddr) {
338         self.ksp = stack.data();
339     }
340 }
341 
342 #[repr(C)]
343 #[derive(Debug, Clone, Copy)]
344 struct FpDExtState {
345     f: [u64; 32],
346     fcsr: u32,
347 }
348 
349 impl FpDExtState {
350     /// 创建一个新的FpState
351     const fn new() -> Self {
352         Self {
353             f: [0; 32],
354             fcsr: 0,
355         }
356     }
357 
358     fn save(&mut self, regs: &mut TrapFrame) {
359         if regs.status.fs() == riscv::register::sstatus::FS::Dirty {
360             self.do_save();
361             self.do_clean(regs);
362         }
363     }
364 
365     fn restore(&mut self, regs: &mut TrapFrame) {
366         if regs.status.fs() != riscv::register::sstatus::FS::Off {
367             self.do_restore();
368             self.do_clean(regs);
369         }
370     }
371 
372     fn do_clean(&mut self, regs: &mut TrapFrame) {
373         regs.status.update_fs(riscv::register::sstatus::FS::Clean);
374     }
375 
376     fn do_save(&mut self) {
377         compiler_fence(Ordering::SeqCst);
378         unsafe {
379             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Initial);
380             asm!("frcsr {0}", lateout(reg) self.fcsr);
381             asm!(concat!(
382                     "
383                 // 为原来的a0寄存器的值在堆栈上分配空间
384                 addi sp, sp, -8
385                 sd a0, 0(sp)
386                 mv a0, {0}
387 
388                 fsd f0, 0(a0)
389                 fsd f1, 8(a0)
390                 fsd f2, 16(a0)
391                 fsd f3, 24(a0)
392                 fsd f4, 32(a0)
393                 fsd f5, 40(a0)
394                 fsd f6, 48(a0)
395                 fsd f7, 56(a0)
396                 fsd f8, 64(a0)
397                 fsd f9, 72(a0)
398                 fsd f10, 80(a0)
399                 fsd f11, 88(a0)
400                 fsd f12, 96(a0)
401                 fsd f13, 104(a0)
402                 fsd f14, 112(a0)
403                 fsd f15, 120(a0)
404                 fsd f16, 128(a0)
405                 fsd f17, 136(a0)
406                 fsd f18, 144(a0)
407                 fsd f19, 152(a0)
408                 fsd f20, 160(a0)
409                 fsd f21, 168(a0)
410                 fsd f22, 176(a0)
411                 fsd f23, 184(a0)
412                 fsd f24, 192(a0)
413                 fsd f25, 200(a0)
414                 fsd f26, 208(a0)
415                 fsd f27, 216(a0)
416                 fsd f28, 224(a0)
417                 fsd f29, 232(a0)
418                 fsd f30, 240(a0)
419                 fsd f31, 248(a0)
420 
421                 // 恢复a0寄存器的值
422                 ld a0, 0(sp)
423                 addi sp, sp, 8
424                 "
425                 ),
426                 in (reg) &self.f as *const _,
427             );
428             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off);
429         }
430 
431         compiler_fence(Ordering::SeqCst);
432     }
433 
434     fn do_restore(&mut self) {
435         compiler_fence(Ordering::SeqCst);
436         let fcsr = self.fcsr;
437         unsafe {
438             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Initial);
439             compiler_fence(Ordering::SeqCst);
440             asm!(concat!(
441                     "
442             // 为原来的a0寄存器的值在堆栈上分配空间
443             addi sp, sp, -8
444             sd a0, 0(sp)
445             mv a0, {0}
446 
447             fld f0, 0(a0)
448             fld f1, 8(a0)
449             fld f2, 16(a0)
450             fld f3, 24(a0)
451             fld f4, 32(a0)
452             fld f5, 40(a0)
453             fld f6, 48(a0)
454             fld f7, 56(a0)
455             fld f8, 64(a0)
456             fld f9, 72(a0)
457             fld f10, 80(a0)
458             fld f11, 88(a0)
459             fld f12, 96(a0)
460             fld f13, 104(a0)
461             fld f14, 112(a0)
462             fld f15, 120(a0)
463             fld f16, 128(a0)
464             fld f17, 136(a0)
465             fld f18, 144(a0)
466             fld f19, 152(a0)
467             fld f20, 160(a0)
468             fld f21, 168(a0)
469             fld f22, 176(a0)
470             fld f23, 184(a0)
471             fld f24, 192(a0)
472             fld f25, 200(a0)
473             fld f26, 208(a0)
474             fld f27, 216(a0)
475             fld f28, 224(a0)
476             fld f29, 232(a0)
477             fld f30, 240(a0)
478             fld f31, 248(a0)
479 
480             // 恢复a0寄存器的值
481             ld a0, 0(sp)
482             addi sp, sp, 8
483             "
484                 ),
485                 in (reg) &self.f as *const _,
486             );
487             compiler_fence(Ordering::SeqCst);
488             asm!("fscsr {0}", in(reg) fcsr);
489             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off);
490         }
491         compiler_fence(Ordering::SeqCst);
492     }
493 }
494