xref: /DragonOS/kernel/src/arch/riscv64/cpu.rs (revision 9b96c5b547c337502db7ec820312f119f95eece1)
1338f6903SLoGin use alloc::vec::Vec;
270f159a3SLoGin use sbi_rt::HartMask;
3338f6903SLoGin 
4338f6903SLoGin use crate::{
5338f6903SLoGin     init::boot_params,
6338f6903SLoGin     kdebug,
7338f6903SLoGin     mm::percpu::{PerCpu, PerCpuVar},
8338f6903SLoGin     smp::cpu::{ProcessorId, SmpCpuManager},
9338f6903SLoGin };
10e2841179SLoGin 
115c4224e5SLoGin /// 栈对齐
125c4224e5SLoGin pub(super) const STACK_ALIGN: usize = 16;
135c4224e5SLoGin 
1470f159a3SLoGin /// RISC-V的XLEN,也就是寄存器的位宽
1570f159a3SLoGin pub const RISCV_XLEN: usize = core::mem::size_of::<usize>() * 8;
1670f159a3SLoGin 
174fda81ceSLoGin /// 获取当前cpu的id
184fda81ceSLoGin #[inline]
19e2841179SLoGin pub fn current_cpu_id() -> ProcessorId {
205c4224e5SLoGin     let ptr: *const LocalContext = riscv::register::tp::read() as *const LocalContext;
21338f6903SLoGin 
22338f6903SLoGin     if core::intrinsics::unlikely(ptr.is_null()) {
23338f6903SLoGin         return boot_params().read_irqsave().arch.boot_hartid;
24338f6903SLoGin     }
25338f6903SLoGin 
26338f6903SLoGin     unsafe { (*ptr).current_cpu() }
274fda81ceSLoGin }
2870f159a3SLoGin impl Into<HartMask> for ProcessorId {
2970f159a3SLoGin     fn into(self) -> HartMask {
3070f159a3SLoGin         let base = self.data() as usize / RISCV_XLEN;
3170f159a3SLoGin         let offset = self.data() as usize & (RISCV_XLEN - 1);
3270f159a3SLoGin         HartMask::from_mask_base(offset, base)
3370f159a3SLoGin     }
3470f159a3SLoGin }
354fda81ceSLoGin /// 重置cpu
364fda81ceSLoGin pub unsafe fn cpu_reset() -> ! {
37d14e28a8SLuo Jia / Zhouqi Jiang     sbi_rt::system_reset(sbi_rt::WarmReboot, sbi_rt::NoReason);
38d14e28a8SLuo Jia / Zhouqi Jiang     unimplemented!("RiscV64 reset failed, manual override expected ...")
394fda81ceSLoGin }
40338f6903SLoGin 
41338f6903SLoGin static mut LOCAL_CONTEXT: Option<PerCpuVar<LocalContext>> = None;
42338f6903SLoGin 
43338f6903SLoGin #[inline(always)]
44338f6903SLoGin pub(super) fn local_context() -> &'static PerCpuVar<LocalContext> {
45338f6903SLoGin     unsafe { LOCAL_CONTEXT.as_ref().unwrap() }
46338f6903SLoGin }
47338f6903SLoGin 
48338f6903SLoGin /// Per cpu的上下文数据
49338f6903SLoGin ///
505c4224e5SLoGin /// 每个CPU的tp寄存器指向这个结构体
515c4224e5SLoGin ///
525c4224e5SLoGin /// 注意:
535c4224e5SLoGin ///
545c4224e5SLoGin /// - 从用户态进入内核态时,会从sscratch寄存器加载这个结构体的地址到tp寄存器,并把sscratch寄存器清零
555c4224e5SLoGin /// - 从内核态进入用户态时,会将tp寄存器的值保存到sscratch寄存器
56*9b96c5b5SLoGin #[derive(Debug, Clone, Copy)]
57338f6903SLoGin pub(super) struct LocalContext {
58338f6903SLoGin     /// 当前cpu的id
595c4224e5SLoGin     pub current_cpu: ProcessorId,
605c4224e5SLoGin     // 当前进程的内核栈指针(暂存,当进入中断处理程序的时候需要保存到pcb,进程切换的时候需要重新设置这个值)
615c4224e5SLoGin     pub kernel_sp: usize,
625c4224e5SLoGin     // 当前进程的用户栈指针(暂存,当进入中断处理程序的时候需要保存到pcb,进程切换的时候需要重新设置这个值)
635c4224e5SLoGin     pub user_sp: usize,
64338f6903SLoGin }
65338f6903SLoGin 
66338f6903SLoGin impl LocalContext {
67*9b96c5b5SLoGin     pub fn new(cpu: ProcessorId) -> Self {
685c4224e5SLoGin         Self {
695c4224e5SLoGin             current_cpu: cpu,
705c4224e5SLoGin             kernel_sp: 0,
715c4224e5SLoGin             user_sp: 0,
725c4224e5SLoGin         }
73338f6903SLoGin     }
74338f6903SLoGin     pub fn current_cpu(&self) -> ProcessorId {
75338f6903SLoGin         self.current_cpu
76338f6903SLoGin     }
77338f6903SLoGin 
78338f6903SLoGin     pub fn set_current_cpu(&mut self, cpu: ProcessorId) {
79338f6903SLoGin         self.current_cpu = cpu;
80338f6903SLoGin     }
81338f6903SLoGin 
825c4224e5SLoGin     pub fn kernel_sp(&self) -> usize {
835c4224e5SLoGin         self.kernel_sp
845c4224e5SLoGin     }
855c4224e5SLoGin 
865c4224e5SLoGin     pub fn set_kernel_sp(&mut self, sp: usize) {
875c4224e5SLoGin         self.kernel_sp = sp;
885c4224e5SLoGin     }
895c4224e5SLoGin 
905c4224e5SLoGin     pub fn user_sp(&self) -> usize {
915c4224e5SLoGin         self.user_sp
925c4224e5SLoGin     }
935c4224e5SLoGin 
945c4224e5SLoGin     pub fn set_user_sp(&mut self, sp: usize) {
955c4224e5SLoGin         self.user_sp = sp;
965c4224e5SLoGin     }
975c4224e5SLoGin 
98338f6903SLoGin     fn sync_to_cpu(&self) {
99338f6903SLoGin         let ptr = self as *const Self as usize;
1005c4224e5SLoGin         riscv::register::sscratch::write(0);
1015c4224e5SLoGin 
1025c4224e5SLoGin         // 写入tp寄存器
1035c4224e5SLoGin         riscv::register::tp::write(ptr);
104338f6903SLoGin     }
105*9b96c5b5SLoGin 
106*9b96c5b5SLoGin     pub fn restore(&mut self, from: &LocalContext) {
107*9b96c5b5SLoGin         // 不恢复cpu id
108*9b96c5b5SLoGin 
109*9b96c5b5SLoGin         self.kernel_sp = from.kernel_sp;
110*9b96c5b5SLoGin         self.user_sp = from.user_sp;
111*9b96c5b5SLoGin     }
112338f6903SLoGin }
113338f6903SLoGin 
114338f6903SLoGin /// 初始化本地上下文
115338f6903SLoGin #[inline(never)]
116338f6903SLoGin pub(super) fn init_local_context() {
117338f6903SLoGin     let mut data = Vec::new();
118338f6903SLoGin 
119338f6903SLoGin     for i in 0..PerCpu::MAX_CPU_NUM {
120338f6903SLoGin         data.push(LocalContext::new(ProcessorId::new(i)));
121338f6903SLoGin     }
122338f6903SLoGin     let ctx = PerCpuVar::new(data).unwrap();
123338f6903SLoGin 
124338f6903SLoGin     unsafe {
125338f6903SLoGin         LOCAL_CONTEXT = Some(ctx);
126338f6903SLoGin     }
127338f6903SLoGin 
128338f6903SLoGin     let hartid = boot_params().read().arch.boot_hartid;
129338f6903SLoGin 
130338f6903SLoGin     let ctx = unsafe { local_context().force_get(hartid) };
131338f6903SLoGin     ctx.sync_to_cpu();
132338f6903SLoGin }
133338f6903SLoGin 
134338f6903SLoGin impl SmpCpuManager {
135338f6903SLoGin     pub fn arch_init(boot_cpu: ProcessorId) {
136338f6903SLoGin         // todo: 读取所有可用的CPU
137338f6903SLoGin     }
138338f6903SLoGin }
139