xref: /DragonOS/kernel/src/arch/riscv64/cpu.rs (revision 338f6903262c5031abad3c8e361813355a27fcdb)
1 use alloc::vec::Vec;
2 
3 use crate::{
4     init::boot_params,
5     kdebug,
6     mm::percpu::{PerCpu, PerCpuVar},
7     smp::cpu::{ProcessorId, SmpCpuManager},
8 };
9 
10 /// 获取当前cpu的id
11 #[inline]
12 pub fn current_cpu_id() -> ProcessorId {
13     let ptr: *const LocalContext = riscv::register::sscratch::read() as *const LocalContext;
14 
15     if core::intrinsics::unlikely(ptr.is_null()) {
16         return boot_params().read_irqsave().arch.boot_hartid;
17     }
18 
19     unsafe { (*ptr).current_cpu() }
20 }
21 
22 /// 重置cpu
23 pub unsafe fn cpu_reset() -> ! {
24     sbi_rt::system_reset(sbi_rt::WarmReboot, sbi_rt::NoReason);
25     unimplemented!("RiscV64 reset failed, manual override expected ...")
26 }
27 
28 static mut LOCAL_CONTEXT: Option<PerCpuVar<LocalContext>> = None;
29 
30 #[inline(always)]
31 pub(super) fn local_context() -> &'static PerCpuVar<LocalContext> {
32     unsafe { LOCAL_CONTEXT.as_ref().unwrap() }
33 }
34 
35 /// Per cpu的上下文数据
36 ///
37 /// 每个CPU的sscratch寄存器指向这个结构体
38 #[derive(Debug)]
39 pub(super) struct LocalContext {
40     /// 当前cpu的id
41     current_cpu: ProcessorId,
42 }
43 
44 impl LocalContext {
45     fn new(cpu: ProcessorId) -> Self {
46         Self { current_cpu: cpu }
47     }
48     pub fn current_cpu(&self) -> ProcessorId {
49         self.current_cpu
50     }
51 
52     pub fn set_current_cpu(&mut self, cpu: ProcessorId) {
53         self.current_cpu = cpu;
54     }
55 
56     fn sync_to_cpu(&self) {
57         let ptr = self as *const Self as usize;
58         riscv::register::sscratch::write(ptr);
59     }
60 }
61 
62 /// 初始化本地上下文
63 #[inline(never)]
64 pub(super) fn init_local_context() {
65     kdebug!("init_local_context");
66     let mut data = Vec::new();
67 
68     for i in 0..PerCpu::MAX_CPU_NUM {
69         data.push(LocalContext::new(ProcessorId::new(i)));
70     }
71     let ctx = PerCpuVar::new(data).unwrap();
72 
73     unsafe {
74         LOCAL_CONTEXT = Some(ctx);
75     }
76 
77     let hartid = boot_params().read().arch.boot_hartid;
78 
79     let ctx = unsafe { local_context().force_get(hartid) };
80     ctx.sync_to_cpu();
81 }
82 
83 impl SmpCpuManager {
84     pub fn arch_init(boot_cpu: ProcessorId) {
85         // todo: 读取所有可用的CPU
86     }
87 }
88