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