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