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