xref: /DragonOS/kernel/src/arch/riscv64/process/mod.rs (revision f0c87a897fe813b7f06bf5a9e93c43ad9519dafd)
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         KernelStack, ProcessControlBlock, ProcessFlags, ProcessManager, PROCESS_SWITCH_RESULT,
27     },
28     smp::cpu::ProcessorId,
29     syscall::Syscall,
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,并跳转到{switch_finish_hook}
217             la ra, 1f
218             j {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     switch_finish_hook = sym crate::process::switch_finish_hook,
242     options(noreturn));
243 }
244 
245 impl ProcessControlBlock {
246     /// 获取当前进程的pcb
247     pub fn arch_current_pcb() -> Arc<Self> {
248         // 获取栈指针
249         let mut sp: usize;
250         unsafe { asm!("mv {}, sp", lateout(reg) sp, options(nostack)) };
251         let ptr = VirtAddr::new(sp);
252 
253         let stack_base = VirtAddr::new(ptr.data() & (!(KernelStack::ALIGN - 1)));
254 
255         // 从内核栈的最低地址处取出pcb的地址
256         let p = stack_base.data() as *const *const ProcessControlBlock;
257         if core::intrinsics::unlikely((unsafe { *p }).is_null()) {
258             kerror!("p={:p}", p);
259             panic!("current_pcb is null");
260         }
261         unsafe {
262             // 为了防止内核栈的pcb weak 指针被释放,这里需要将其包装一下
263             let weak_wrapper: ManuallyDrop<Weak<ProcessControlBlock>> =
264                 ManuallyDrop::new(Weak::from_raw(*p));
265 
266             let new_arc: Arc<ProcessControlBlock> = weak_wrapper.upgrade().unwrap();
267             return new_arc;
268         }
269     }
270 }
271 
272 /// PCB中与架构相关的信息
273 #[derive(Debug, Clone, Copy)]
274 #[allow(dead_code)]
275 #[repr(C)]
276 pub struct ArchPCBInfo {
277     ra: usize,
278     ksp: usize,
279     s0: usize,
280     s1: usize,
281     s2: usize,
282     s3: usize,
283     s4: usize,
284     s5: usize,
285     s6: usize,
286     s7: usize,
287     s8: usize,
288     s9: usize,
289     s10: usize,
290     s11: usize,
291 
292     fp_state: FpDExtState,
293     local_context: LocalContext,
294 }
295 
296 #[allow(dead_code)]
297 impl ArchPCBInfo {
298     /// 创建一个新的ArchPCBInfo
299     ///
300     /// ## 参数
301     ///
302     /// - `kstack`:内核栈的引用
303     ///
304     /// ## 返回值
305     ///
306     /// 返回一个新的ArchPCBInfo
307     pub fn new(kstack: &KernelStack) -> Self {
308         Self {
309             ra: 0,
310             ksp: kstack.stack_max_address().data(),
311             s0: 0,
312             s1: 0,
313             s2: 0,
314             s3: 0,
315             s4: 0,
316             s5: 0,
317             s6: 0,
318             s7: 0,
319             s8: 0,
320             s9: 0,
321             s10: 0,
322             s11: 0,
323             fp_state: FpDExtState::new(),
324             local_context: LocalContext::new(ProcessorId::new(0)),
325         }
326     }
327     // ### 从另一个ArchPCBInfo处clone,但是保留部分字段不变
328     pub fn clone_from(&mut self, from: &Self) {
329         *self = from.clone();
330     }
331 
332     pub fn set_stack(&mut self, stack: VirtAddr) {
333         self.ksp = stack.data();
334     }
335 }
336 
337 #[repr(C)]
338 #[derive(Debug, Clone, Copy)]
339 struct FpDExtState {
340     f: [u64; 32],
341     fcsr: u32,
342 }
343 
344 impl FpDExtState {
345     /// 创建一个新的FpState
346     const fn new() -> Self {
347         Self {
348             f: [0; 32],
349             fcsr: 0,
350         }
351     }
352 
353     fn save(&mut self, regs: &mut TrapFrame) {
354         if regs.status.fs() == riscv::register::sstatus::FS::Dirty {
355             self.do_save();
356             self.do_clean(regs);
357         }
358     }
359 
360     fn restore(&mut self, regs: &mut TrapFrame) {
361         if regs.status.fs() != riscv::register::sstatus::FS::Off {
362             self.do_restore();
363             self.do_clean(regs);
364         }
365     }
366 
367     fn do_clean(&mut self, regs: &mut TrapFrame) {
368         regs.status.update_fs(riscv::register::sstatus::FS::Clean);
369     }
370 
371     fn do_save(&mut self) {
372         compiler_fence(Ordering::SeqCst);
373         unsafe {
374             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Initial);
375             asm!("frcsr {0}", lateout(reg) self.fcsr);
376             asm!(concat!(
377                     "
378                 fsd f0, {0}
379                 fsd f1, {1}
380                 fsd f2, {2}
381                 fsd f3, {3}
382                 fsd f4, {4}
383                 fsd f5, {5}
384                 fsd f6, {6}
385                 fsd f7, {7}
386                 fsd f8, {8}
387                 fsd f9, {9}
388                 fsd f10, {10}
389                 fsd f11, {11}
390                 fsd f12, {12}
391                 fsd f13, {13}
392                 fsd f14, {14}
393                 fsd f15, {15}
394                 fsd f16, {16}
395                 fsd f17, {17}
396                 fsd f18, {18}
397                 fsd f19, {19}
398                 fsd f20, {20}
399                 fsd f21, {21}
400                 fsd f22, {22}
401                 fsd f23, {23}
402                 fsd f24, {24}
403                 fsd f25, {25}
404                 fsd f26, {26}
405                 fsd f27, {27}
406                 fsd f28, {28}
407                 fsd f29, {29}
408                 fsd f30, {30}
409                 fsd f31, {31}
410                 "
411                 ),
412                 lateout(reg) self.f[0],
413                 lateout(reg) self.f[1],
414                 lateout(reg) self.f[2],
415                 lateout(reg) self.f[3],
416                 lateout(reg) self.f[4],
417                 lateout(reg) self.f[5],
418                 lateout(reg) self.f[6],
419                 lateout(reg) self.f[7],
420                 lateout(reg) self.f[8],
421                 lateout(reg) self.f[9],
422                 lateout(reg) self.f[10],
423                 lateout(reg) self.f[11],
424                 lateout(reg) self.f[12],
425                 lateout(reg) self.f[13],
426                 lateout(reg) self.f[14],
427                 lateout(reg) self.f[15],
428                 lateout(reg) self.f[16],
429                 lateout(reg) self.f[17],
430                 lateout(reg) self.f[18],
431                 lateout(reg) self.f[19],
432                 lateout(reg) self.f[20],
433                 lateout(reg) self.f[21],
434                 lateout(reg) self.f[22],
435                 lateout(reg) self.f[23],
436                 lateout(reg) self.f[24],
437                 lateout(reg) self.f[25],
438                 lateout(reg) self.f[26],
439                 lateout(reg) self.f[27],
440                 lateout(reg) self.f[28],
441                 lateout(reg) self.f[29],
442                 lateout(reg) self.f[30],
443                 lateout(reg) self.f[31],
444 
445             );
446             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off);
447         }
448 
449         compiler_fence(Ordering::SeqCst);
450     }
451 
452     fn do_restore(&mut self) {
453         compiler_fence(Ordering::SeqCst);
454         let fcsr = self.fcsr;
455         unsafe {
456             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Initial);
457             compiler_fence(Ordering::SeqCst);
458             asm!(concat!(
459                     "
460                 fld f0, {0}
461                 fld f1, {1}
462                 fld f2, {2}
463                 fld f3, {3}
464                 fld f4, {4}
465                 fld f5, {5}
466                 fld f6, {6}
467                 fld f7, {7}
468                 fld f8, {8}
469                 fld f9, {9}
470                 fld f10, {10}
471                 fld f11, {11}
472                 fld f12, {12}
473                 fld f13, {13}
474                 fld f14, {14}
475                 fld f15, {15}
476                 fld f16, {16}
477                 fld f17, {17}
478                 fld f18, {18}
479                 fld f19, {19}
480                 fld f20, {20}
481                 fld f21, {21}
482                 fld f22, {22}
483                 fld f23, {23}
484                 fld f24, {24}
485                 fld f25, {25}
486                 fld f26, {26}
487                 fld f27, {27}
488                 fld f28, {28}
489                 fld f29, {29}
490                 fld f30, {30}
491                 fld f31, {31}
492                 "
493                 ),
494                 in(reg) self.f[0],
495                 in(reg) self.f[1],
496                 in(reg) self.f[2],
497                 in(reg) self.f[3],
498                 in(reg) self.f[4],
499                 in(reg) self.f[5],
500                 in(reg) self.f[6],
501                 in(reg) self.f[7],
502                 in(reg) self.f[8],
503                 in(reg) self.f[9],
504                 in(reg) self.f[10],
505                 in(reg) self.f[11],
506                 in(reg) self.f[12],
507                 in(reg) self.f[13],
508                 in(reg) self.f[14],
509                 in(reg) self.f[15],
510                 in(reg) self.f[16],
511                 in(reg) self.f[17],
512                 in(reg) self.f[18],
513                 in(reg) self.f[19],
514                 in(reg) self.f[20],
515                 in(reg) self.f[21],
516                 in(reg) self.f[22],
517                 in(reg) self.f[23],
518                 in(reg) self.f[24],
519                 in(reg) self.f[25],
520                 in(reg) self.f[26],
521                 in(reg) self.f[27],
522                 in(reg) self.f[28],
523                 in(reg) self.f[29],
524                 in(reg) self.f[30],
525                 in(reg) self.f[31],
526             );
527             compiler_fence(Ordering::SeqCst);
528             asm!("fscsr {0}", in(reg) fcsr);
529             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off);
530         }
531         compiler_fence(Ordering::SeqCst);
532     }
533 }
534