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] 18 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 { 28 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 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)] 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 impl LocalContext { 66 pub fn new(cpu: ProcessorId) -> Self { 67 Self { 68 current_cpu: cpu, 69 kernel_sp: 0, 70 user_sp: 0, 71 } 72 } 73 pub fn current_cpu(&self) -> ProcessorId { 74 self.current_cpu 75 } 76 77 pub fn set_current_cpu(&mut self, cpu: ProcessorId) { 78 self.current_cpu = cpu; 79 } 80 81 pub fn kernel_sp(&self) -> usize { 82 self.kernel_sp 83 } 84 85 pub fn set_kernel_sp(&mut self, sp: usize) { 86 self.kernel_sp = sp; 87 } 88 89 pub fn user_sp(&self) -> usize { 90 self.user_sp 91 } 92 93 pub fn set_user_sp(&mut self, sp: usize) { 94 self.user_sp = sp; 95 } 96 97 fn sync_to_cpu(&self) { 98 let ptr = self as *const Self as usize; 99 riscv::register::sscratch::write(0); 100 101 // 写入tp寄存器 102 riscv::register::tp::write(ptr); 103 } 104 105 pub fn restore(&mut self, from: &LocalContext) { 106 // 不恢复cpu id 107 108 self.kernel_sp = from.kernel_sp; 109 self.user_sp = from.user_sp; 110 } 111 } 112 113 /// 初始化本地上下文 114 #[inline(never)] 115 pub(super) fn init_local_context() { 116 let mut data = Vec::new(); 117 118 for i in 0..PerCpu::MAX_CPU_NUM { 119 data.push(LocalContext::new(ProcessorId::new(i))); 120 } 121 let ctx = PerCpuVar::new(data).unwrap(); 122 123 unsafe { 124 LOCAL_CONTEXT = Some(ctx); 125 } 126 127 let hartid = boot_params().read().arch.boot_hartid; 128 129 let ctx = unsafe { local_context().force_get(hartid) }; 130 ctx.sync_to_cpu(); 131 } 132 133 impl SmpCpuManager { 134 pub fn arch_init(boot_cpu: ProcessorId) { 135 // todo: 读取所有可用的CPU 136 } 137 } 138