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