xref: /DragonOS/kernel/src/arch/riscv64/process/mod.rs (revision dfe53cf087ef4c7b6db63d992906b062dc63e93f)
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::CurrentIrqArch,
17     exception::InterruptArch,
18     kerror,
19     libs::spinlock::SpinLockGuard,
20     mm::VirtAddr,
21     process::{
22         fork::KernelCloneArgs, KernelStack, ProcessControlBlock, ProcessManager,
23         PROCESS_SWITCH_RESULT,
24     },
25     smp::cpu::ProcessorId,
26 };
27 
28 use super::{
29     cpu::{local_context, LocalContext},
30     interrupt::TrapFrame,
31 };
32 
33 pub mod idle;
34 pub mod kthread;
35 pub mod syscall;
36 
37 #[allow(dead_code)]
38 #[repr(align(32768))]
39 union InitProcUnion {
40     /// 用于存放idle进程的内核栈
41     idle_stack: [u8; 32768],
42 }
43 
44 #[link_section = ".data.init_proc_union"]
45 #[no_mangle]
46 static BSP_IDLE_STACK_SPACE: InitProcUnion = InitProcUnion {
47     idle_stack: [0; 32768],
48 };
49 
50 pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<String>) -> ! {
51     unimplemented!("RiscV64 arch_switch_to_user")
52 }
53 
54 impl ProcessManager {
55     pub fn arch_init() {
56         // do nothing
57     }
58 
59     /// fork的过程中复制线程
60     ///
61     /// 由于这个过程与具体的架构相关,所以放在这里
62     pub fn copy_thread(
63         current_pcb: &Arc<ProcessControlBlock>,
64         new_pcb: &Arc<ProcessControlBlock>,
65         clone_args: KernelCloneArgs,
66         current_trapframe: &TrapFrame,
67     ) -> Result<(), SystemError> {
68         unimplemented!("ProcessManager::copy_thread")
69     }
70 
71     /// 切换进程
72     ///
73     /// ## 参数
74     ///
75     /// - `prev`:上一个进程的pcb
76     /// - `next`:下一个进程的pcb
77     ///
78     /// 参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/include/asm/switch_to.h#76
79     pub unsafe fn switch_process(prev: Arc<ProcessControlBlock>, next: Arc<ProcessControlBlock>) {
80         assert!(!CurrentIrqArch::is_irq_enabled());
81         Self::switch_process_fpu(&prev, &next);
82         Self::switch_local_context(&prev, &next);
83 
84         // 切换地址空间
85         let next_addr_space = next.basic().user_vm().as_ref().unwrap().clone();
86         compiler_fence(Ordering::SeqCst);
87 
88         next_addr_space.read().user_mapper.utable.make_current();
89         drop(next_addr_space);
90         compiler_fence(Ordering::SeqCst);
91 
92         // 获取arch info的锁,并强制泄露其守卫(切换上下文后,在switch_finish_hook中会释放锁)
93         let next_arch = SpinLockGuard::leak(next.arch_info_irqsave()) as *mut ArchPCBInfo;
94         let prev_arch = SpinLockGuard::leak(prev.arch_info_irqsave()) as *mut ArchPCBInfo;
95 
96         // 恢复当前的 preempt count*2
97         ProcessManager::current_pcb().preempt_enable();
98         ProcessManager::current_pcb().preempt_enable();
99         PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev);
100         PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next);
101         // kdebug!("switch tss ok");
102         compiler_fence(Ordering::SeqCst);
103         // 正式切换上下文
104         switch_to_inner(prev_arch, next_arch);
105     }
106 
107     fn switch_process_fpu(prev: &Arc<ProcessControlBlock>, next: &Arc<ProcessControlBlock>) {
108         let prev_regs = unsafe { Self::task_trapframe(prev) };
109         let next_regs = unsafe { Self::task_trapframe(next) };
110         if unlikely(prev_regs.status.sd()) {
111             prev.arch_info_irqsave().fp_state.save(prev_regs);
112         }
113         next.arch_info_irqsave().fp_state.restore(next_regs);
114     }
115 
116     fn switch_local_context(prev: &Arc<ProcessControlBlock>, next: &Arc<ProcessControlBlock>) {
117         prev.arch_info_irqsave().local_context = *local_context().get();
118         local_context()
119             .get_mut()
120             .restore(&next.arch_info_irqsave().local_context);
121     }
122 
123     unsafe fn task_trapframe(task: &Arc<ProcessControlBlock>) -> &mut TrapFrame {
124         let mut sp = task.kernel_stack().stack_max_address().data();
125         sp -= core::mem::size_of::<TrapFrame>();
126         return (sp as *mut TrapFrame).as_mut().unwrap();
127     }
128 }
129 
130 /// 切换上下文
131 ///
132 /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/kernel/entry.S#233
133 #[naked]
134 unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBInfo) {
135     core::arch::asm!(concat!(
136         "
137             sd ra, {off_ra}(a0)
138             sd sp, {off_sp}(a0)
139             sd s0, {off_s0}(a0)
140             sd s1, {off_s1}(a0)
141             sd s2, {off_s2}(a0)
142             sd s3, {off_s3}(a0)
143             sd s4, {off_s4}(a0)
144             sd s5, {off_s5}(a0)
145             sd s6, {off_s6}(a0)
146             sd s7, {off_s7}(a0)
147             sd s8, {off_s8}(a0)
148             sd s9, {off_s9}(a0)
149             sd s10, {off_s10}(a0)
150             sd s11, {off_s11}(a0)
151 
152 
153             ld sp, {off_sp}(a1)
154             ld s0, {off_s0}(a1)
155             ld s1, {off_s1}(a1)
156             ld s2, {off_s2}(a1)
157             ld s3, {off_s3}(a1)
158             ld s4, {off_s4}(a1)
159             ld s5, {off_s5}(a1)
160             ld s6, {off_s6}(a1)
161             ld s7, {off_s7}(a1)
162             ld s8, {off_s8}(a1)
163             ld s9, {off_s9}(a1)
164             ld s10, {off_s10}(a1)
165             ld s11, {off_s11}(a1)
166 
167             // 将ra设置为标签1,并跳转到{switch_finish_hook}
168             la ra, 1f
169             j {switch_finish_hook}
170 
171             1:
172             ld sp, {off_sp}(a1)
173             ld ra, {off_ra}(a1)
174             ret
175 
176         "
177     ),
178     off_ra = const(offset_of!(ArchPCBInfo, ra)),
179     off_sp = const(offset_of!(ArchPCBInfo, ksp)),
180     off_s0 = const(offset_of!(ArchPCBInfo, s0)),
181     off_s1 = const(offset_of!(ArchPCBInfo, s1)),
182     off_s2 = const(offset_of!(ArchPCBInfo, s2)),
183     off_s3 = const(offset_of!(ArchPCBInfo, s3)),
184     off_s4 = const(offset_of!(ArchPCBInfo, s4)),
185     off_s5 = const(offset_of!(ArchPCBInfo, s5)),
186     off_s6 = const(offset_of!(ArchPCBInfo, s6)),
187     off_s7 = const(offset_of!(ArchPCBInfo, s7)),
188     off_s8 = const(offset_of!(ArchPCBInfo, s8)),
189     off_s9 = const(offset_of!(ArchPCBInfo, s9)),
190     off_s10 = const(offset_of!(ArchPCBInfo, s10)),
191     off_s11 = const(offset_of!(ArchPCBInfo, s11)),
192     switch_finish_hook = sym crate::process::switch_finish_hook,
193     options(noreturn));
194 }
195 
196 impl ProcessControlBlock {
197     /// 获取当前进程的pcb
198     pub fn arch_current_pcb() -> Arc<Self> {
199         // 获取栈指针
200         let mut sp: usize;
201         unsafe { asm!("mv {}, sp", lateout(reg) sp, options(nostack)) };
202         let ptr = VirtAddr::new(sp);
203 
204         let stack_base = VirtAddr::new(ptr.data() & (!(KernelStack::ALIGN - 1)));
205 
206         // 从内核栈的最低地址处取出pcb的地址
207         let p = stack_base.data() as *const *const ProcessControlBlock;
208         if core::intrinsics::unlikely((unsafe { *p }).is_null()) {
209             kerror!("p={:p}", p);
210             panic!("current_pcb is null");
211         }
212         unsafe {
213             // 为了防止内核栈的pcb weak 指针被释放,这里需要将其包装一下
214             let weak_wrapper: ManuallyDrop<Weak<ProcessControlBlock>> =
215                 ManuallyDrop::new(Weak::from_raw(*p));
216 
217             let new_arc: Arc<ProcessControlBlock> = weak_wrapper.upgrade().unwrap();
218             return new_arc;
219         }
220     }
221 }
222 
223 /// PCB中与架构相关的信息
224 #[derive(Debug)]
225 #[allow(dead_code)]
226 #[repr(C)]
227 pub struct ArchPCBInfo {
228     ra: usize,
229     ksp: usize,
230     s0: usize,
231     s1: usize,
232     s2: usize,
233     s3: usize,
234     s4: usize,
235     s5: usize,
236     s6: usize,
237     s7: usize,
238     s8: usize,
239     s9: usize,
240     s10: usize,
241     s11: usize,
242 
243     fp_state: FpDExtState,
244     local_context: LocalContext,
245 }
246 
247 #[allow(dead_code)]
248 impl ArchPCBInfo {
249     /// 创建一个新的ArchPCBInfo
250     ///
251     /// ## 参数
252     ///
253     /// - `kstack`:内核栈的引用
254     ///
255     /// ## 返回值
256     ///
257     /// 返回一个新的ArchPCBInfo
258     pub fn new(kstack: &KernelStack) -> Self {
259         Self {
260             ra: 0,
261             ksp: kstack.stack_max_address().data(),
262             s0: 0,
263             s1: 0,
264             s2: 0,
265             s3: 0,
266             s4: 0,
267             s5: 0,
268             s6: 0,
269             s7: 0,
270             s8: 0,
271             s9: 0,
272             s10: 0,
273             s11: 0,
274             fp_state: FpDExtState::new(),
275             local_context: LocalContext::new(ProcessorId::new(0)),
276         }
277     }
278     // ### 从另一个ArchPCBInfo处clone,但是保留部分字段不变
279     pub fn clone_from(&mut self, from: &Self) {
280         unimplemented!("ArchPCBInfo::clone_from")
281     }
282 }
283 
284 #[repr(C)]
285 #[derive(Debug)]
286 struct FpDExtState {
287     f: [u64; 32],
288     fcsr: u32,
289 }
290 
291 impl FpDExtState {
292     /// 创建一个新的FpState
293     const fn new() -> Self {
294         Self {
295             f: [0; 32],
296             fcsr: 0,
297         }
298     }
299 
300     fn save(&mut self, regs: &mut TrapFrame) {
301         if regs.status.fs() == riscv::register::sstatus::FS::Dirty {
302             self.do_save();
303             self.do_clean(regs);
304         }
305     }
306 
307     fn restore(&mut self, regs: &mut TrapFrame) {
308         if regs.status.fs() != riscv::register::sstatus::FS::Off {
309             self.do_restore();
310             self.do_clean(regs);
311         }
312     }
313 
314     fn do_clean(&mut self, regs: &mut TrapFrame) {
315         regs.status.update_fs(riscv::register::sstatus::FS::Clean);
316     }
317 
318     fn do_save(&mut self) {
319         compiler_fence(Ordering::SeqCst);
320         unsafe {
321             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Initial);
322             asm!("frcsr {0}", lateout(reg) self.fcsr);
323             asm!(concat!(
324                     "
325                 fsd f0, {0}
326                 fsd f1, {1}
327                 fsd f2, {2}
328                 fsd f3, {3}
329                 fsd f4, {4}
330                 fsd f5, {5}
331                 fsd f6, {6}
332                 fsd f7, {7}
333                 fsd f8, {8}
334                 fsd f9, {9}
335                 fsd f10, {10}
336                 fsd f11, {11}
337                 fsd f12, {12}
338                 fsd f13, {13}
339                 fsd f14, {14}
340                 fsd f15, {15}
341                 fsd f16, {16}
342                 fsd f17, {17}
343                 fsd f18, {18}
344                 fsd f19, {19}
345                 fsd f20, {20}
346                 fsd f21, {21}
347                 fsd f22, {22}
348                 fsd f23, {23}
349                 fsd f24, {24}
350                 fsd f25, {25}
351                 fsd f26, {26}
352                 fsd f27, {27}
353                 fsd f28, {28}
354                 fsd f29, {29}
355                 fsd f30, {30}
356                 fsd f31, {31}
357                 "
358                 ),
359                 lateout(reg) self.f[0],
360                 lateout(reg) self.f[1],
361                 lateout(reg) self.f[2],
362                 lateout(reg) self.f[3],
363                 lateout(reg) self.f[4],
364                 lateout(reg) self.f[5],
365                 lateout(reg) self.f[6],
366                 lateout(reg) self.f[7],
367                 lateout(reg) self.f[8],
368                 lateout(reg) self.f[9],
369                 lateout(reg) self.f[10],
370                 lateout(reg) self.f[11],
371                 lateout(reg) self.f[12],
372                 lateout(reg) self.f[13],
373                 lateout(reg) self.f[14],
374                 lateout(reg) self.f[15],
375                 lateout(reg) self.f[16],
376                 lateout(reg) self.f[17],
377                 lateout(reg) self.f[18],
378                 lateout(reg) self.f[19],
379                 lateout(reg) self.f[20],
380                 lateout(reg) self.f[21],
381                 lateout(reg) self.f[22],
382                 lateout(reg) self.f[23],
383                 lateout(reg) self.f[24],
384                 lateout(reg) self.f[25],
385                 lateout(reg) self.f[26],
386                 lateout(reg) self.f[27],
387                 lateout(reg) self.f[28],
388                 lateout(reg) self.f[29],
389                 lateout(reg) self.f[30],
390                 lateout(reg) self.f[31],
391 
392             );
393             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off);
394         }
395 
396         compiler_fence(Ordering::SeqCst);
397     }
398 
399     fn do_restore(&mut self) {
400         compiler_fence(Ordering::SeqCst);
401         let fcsr = self.fcsr;
402         unsafe {
403             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Initial);
404             compiler_fence(Ordering::SeqCst);
405             asm!(concat!(
406                     "
407                 fld f0, {0}
408                 fld f1, {1}
409                 fld f2, {2}
410                 fld f3, {3}
411                 fld f4, {4}
412                 fld f5, {5}
413                 fld f6, {6}
414                 fld f7, {7}
415                 fld f8, {8}
416                 fld f9, {9}
417                 fld f10, {10}
418                 fld f11, {11}
419                 fld f12, {12}
420                 fld f13, {13}
421                 fld f14, {14}
422                 fld f15, {15}
423                 fld f16, {16}
424                 fld f17, {17}
425                 fld f18, {18}
426                 fld f19, {19}
427                 fld f20, {20}
428                 fld f21, {21}
429                 fld f22, {22}
430                 fld f23, {23}
431                 fld f24, {24}
432                 fld f25, {25}
433                 fld f26, {26}
434                 fld f27, {27}
435                 fld f28, {28}
436                 fld f29, {29}
437                 fld f30, {30}
438                 fld f31, {31}
439                 "
440                 ),
441                 in(reg) self.f[0],
442                 in(reg) self.f[1],
443                 in(reg) self.f[2],
444                 in(reg) self.f[3],
445                 in(reg) self.f[4],
446                 in(reg) self.f[5],
447                 in(reg) self.f[6],
448                 in(reg) self.f[7],
449                 in(reg) self.f[8],
450                 in(reg) self.f[9],
451                 in(reg) self.f[10],
452                 in(reg) self.f[11],
453                 in(reg) self.f[12],
454                 in(reg) self.f[13],
455                 in(reg) self.f[14],
456                 in(reg) self.f[15],
457                 in(reg) self.f[16],
458                 in(reg) self.f[17],
459                 in(reg) self.f[18],
460                 in(reg) self.f[19],
461                 in(reg) self.f[20],
462                 in(reg) self.f[21],
463                 in(reg) self.f[22],
464                 in(reg) self.f[23],
465                 in(reg) self.f[24],
466                 in(reg) self.f[25],
467                 in(reg) self.f[26],
468                 in(reg) self.f[27],
469                 in(reg) self.f[28],
470                 in(reg) self.f[29],
471                 in(reg) self.f[30],
472                 in(reg) self.f[31],
473             );
474             compiler_fence(Ordering::SeqCst);
475             asm!("fscsr {0}", in(reg) fcsr);
476             riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off);
477         }
478         compiler_fence(Ordering::SeqCst);
479     }
480 }
481