xref: /DragonOS/kernel/src/arch/riscv64/cpu.rs (revision 70f159a3988eab656ea1d2b204fde87948526ecf)
1 use alloc::vec::Vec;
2 use sbi_rt::HartMask;
3 
4 use crate::{
5     init::boot_params,
6     kdebug,
7     mm::percpu::{PerCpu, PerCpuVar},
8     smp::cpu::{ProcessorId, SmpCpuManager},
9 };
10 
11 /// 栈对齐
12 pub(super) const STACK_ALIGN: usize = 16;
13 
14 /// RISC-V的XLEN,也就是寄存器的位宽
15 pub const RISCV_XLEN: usize = core::mem::size_of::<usize>() * 8;
16 
17 /// 获取当前cpu的id
18 #[inline]
19 pub fn current_cpu_id() -> ProcessorId {
20     let ptr: *const LocalContext = riscv::register::tp::read() as *const LocalContext;
21 
22     if core::intrinsics::unlikely(ptr.is_null()) {
23         return boot_params().read_irqsave().arch.boot_hartid;
24     }
25 
26     unsafe { (*ptr).current_cpu() }
27 }
28 impl Into<HartMask> for ProcessorId {
29     fn into(self) -> HartMask {
30         let base = self.data() as usize / RISCV_XLEN;
31         let offset = self.data() as usize & (RISCV_XLEN - 1);
32         HartMask::from_mask_base(offset, base)
33     }
34 }
35 /// 重置cpu
36 pub unsafe fn cpu_reset() -> ! {
37     sbi_rt::system_reset(sbi_rt::WarmReboot, sbi_rt::NoReason);
38     unimplemented!("RiscV64 reset failed, manual override expected ...")
39 }
40 
41 static mut LOCAL_CONTEXT: Option<PerCpuVar<LocalContext>> = None;
42 
43 #[inline(always)]
44 pub(super) fn local_context() -> &'static PerCpuVar<LocalContext> {
45     unsafe { LOCAL_CONTEXT.as_ref().unwrap() }
46 }
47 
48 /// Per cpu的上下文数据
49 ///
50 /// 每个CPU的tp寄存器指向这个结构体
51 ///
52 /// 注意:
53 ///
54 /// - 从用户态进入内核态时,会从sscratch寄存器加载这个结构体的地址到tp寄存器,并把sscratch寄存器清零
55 /// - 从内核态进入用户态时,会将tp寄存器的值保存到sscratch寄存器
56 #[derive(Debug)]
57 pub(super) struct LocalContext {
58     /// 当前cpu的id
59     pub current_cpu: ProcessorId,
60     // 当前进程的内核栈指针(暂存,当进入中断处理程序的时候需要保存到pcb,进程切换的时候需要重新设置这个值)
61     pub kernel_sp: usize,
62     // 当前进程的用户栈指针(暂存,当进入中断处理程序的时候需要保存到pcb,进程切换的时候需要重新设置这个值)
63     pub user_sp: usize,
64 }
65 
66 impl LocalContext {
67     fn new(cpu: ProcessorId) -> Self {
68         Self {
69             current_cpu: cpu,
70             kernel_sp: 0,
71             user_sp: 0,
72         }
73     }
74     pub fn current_cpu(&self) -> ProcessorId {
75         self.current_cpu
76     }
77 
78     pub fn set_current_cpu(&mut self, cpu: ProcessorId) {
79         self.current_cpu = cpu;
80     }
81 
82     pub fn kernel_sp(&self) -> usize {
83         self.kernel_sp
84     }
85 
86     pub fn set_kernel_sp(&mut self, sp: usize) {
87         self.kernel_sp = sp;
88     }
89 
90     pub fn user_sp(&self) -> usize {
91         self.user_sp
92     }
93 
94     pub fn set_user_sp(&mut self, sp: usize) {
95         self.user_sp = sp;
96     }
97 
98     fn sync_to_cpu(&self) {
99         let ptr = self as *const Self as usize;
100         riscv::register::sscratch::write(0);
101 
102         // 写入tp寄存器
103         riscv::register::tp::write(ptr);
104     }
105 }
106 
107 /// 初始化本地上下文
108 #[inline(never)]
109 pub(super) fn init_local_context() {
110     let mut data = Vec::new();
111 
112     for i in 0..PerCpu::MAX_CPU_NUM {
113         data.push(LocalContext::new(ProcessorId::new(i)));
114     }
115     let ctx = PerCpuVar::new(data).unwrap();
116 
117     unsafe {
118         LOCAL_CONTEXT = Some(ctx);
119     }
120 
121     let hartid = boot_params().read().arch.boot_hartid;
122 
123     let ctx = unsafe { local_context().force_get(hartid) };
124     ctx.sync_to_cpu();
125 }
126 
127 impl SmpCpuManager {
128     pub fn arch_init(boot_cpu: ProcessorId) {
129         // todo: 读取所有可用的CPU
130     }
131 }
132