1 use core::sync::atomic::AtomicU32; 2 3 use alloc::{sync::Arc, vec::Vec}; 4 use system_error::SystemError; 5 6 use crate::{ 7 arch::CurrentSMPArch, 8 libs::cpumask::CpuMask, 9 mm::percpu::{PerCpu, PerCpuVar}, 10 process::{ProcessControlBlock, ProcessManager}, 11 sched::completion::Completion, 12 }; 13 14 use super::{core::smp_get_processor_id, SMPArch}; 15 16 int_like!(ProcessorId, AtomicProcessorId, u32, AtomicU32); 17 18 impl ProcessorId { 19 pub const INVALID: ProcessorId = ProcessorId::new(u32::MAX); 20 } 21 22 static mut SMP_CPU_MANAGER: Option<SmpCpuManager> = None; 23 24 #[inline] 25 pub fn smp_cpu_manager() -> &'static SmpCpuManager { 26 unsafe { SMP_CPU_MANAGER.as_ref().unwrap() } 27 } 28 29 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] 30 pub enum CpuHpState { 31 /// 启动阈值 32 ThresholdBringUp = 0, 33 34 /// 该CPU是离线的 35 Offline, 36 37 /// 该CPU是在线的 38 Online, 39 } 40 41 /// Per-Cpu Cpu的热插拔状态 42 pub struct CpuHpCpuState { 43 /// 当前状态 44 state: CpuHpState, 45 /// 目标状态 46 target_state: CpuHpState, 47 /// 指向热插拔的线程的PCB 48 thread: Option<Arc<ProcessControlBlock>>, 49 50 /// 当前是否为启动流程 51 bringup: bool, 52 /// 启动完成的信号 53 comp_done_up: Completion, 54 } 55 56 impl CpuHpCpuState { 57 const fn new() -> Self { 58 Self { 59 state: CpuHpState::Offline, 60 target_state: CpuHpState::Offline, 61 thread: None, 62 bringup: false, 63 comp_done_up: Completion::new(), 64 } 65 } 66 67 pub const fn thread(&self) -> &Option<Arc<ProcessControlBlock>> { 68 &self.thread 69 } 70 } 71 72 pub struct SmpCpuManager { 73 /// 可用的CPU 74 possible_cpus: CpuMask, 75 /// 出现的CPU 76 present_cpus: CpuMask, 77 /// 出现在系统中的CPU的数量 78 present_cnt: AtomicU32, 79 /// 可用的CPU的数量 80 possible_cnt: AtomicU32, 81 /// CPU的状态 82 cpuhp_state: PerCpuVar<CpuHpCpuState>, 83 } 84 85 impl SmpCpuManager { 86 fn new() -> Self { 87 let possible_cpus = CpuMask::new(); 88 let present_cpus = CpuMask::new(); 89 let mut data = Vec::with_capacity(PerCpu::MAX_CPU_NUM as usize); 90 for i in 0..PerCpu::MAX_CPU_NUM { 91 let mut hpstate = CpuHpCpuState::new(); 92 hpstate.thread = Some(ProcessManager::idle_pcb()[i as usize].clone()); 93 data.push(hpstate); 94 } 95 let cpuhp_state = PerCpuVar::new(data).unwrap(); 96 97 Self { 98 possible_cpus, 99 present_cpus, 100 cpuhp_state, 101 present_cnt: AtomicU32::new(0), 102 possible_cnt: AtomicU32::new(0), 103 } 104 } 105 106 /// 设置可用的CPU 107 /// 108 /// # Safety 109 /// 110 /// - 该函数不会检查CPU的有效性,调用者需要保证CPU的有效性。 111 /// - 由于possible_cpus是一个全局变量,且为了性能考虑,并不会加锁 112 /// 访问,因此该函数只能在初始化阶段调用。 113 pub unsafe fn set_possible_cpu(&self, cpu: ProcessorId, value: bool) { 114 // 强制获取mut引用,因为该函数只能在初始化阶段调用 115 let p = (self as *const Self as *mut Self).as_mut().unwrap(); 116 117 if let Some(prev) = p.possible_cpus.set(cpu, value) { 118 if prev != value { 119 if value { 120 p.possible_cnt 121 .fetch_add(1, core::sync::atomic::Ordering::SeqCst); 122 } else { 123 p.possible_cnt 124 .fetch_sub(1, core::sync::atomic::Ordering::SeqCst); 125 } 126 } 127 } 128 } 129 130 /// 获取可用的CPU 131 pub fn possible_cpus(&self) -> &CpuMask { 132 &self.possible_cpus 133 } 134 135 #[allow(dead_code)] 136 pub fn possible_cpus_count(&self) -> u32 { 137 self.possible_cnt.load(core::sync::atomic::Ordering::SeqCst) 138 } 139 140 pub fn present_cpus_count(&self) -> u32 { 141 self.present_cnt.load(core::sync::atomic::Ordering::SeqCst) 142 } 143 144 pub unsafe fn set_present_cpu(&self, cpu: ProcessorId, value: bool) { 145 // 强制获取mut引用,因为该函数只能在初始化阶段调用 146 let p = (self as *const Self as *mut Self).as_mut().unwrap(); 147 148 if let Some(prev) = p.present_cpus.set(cpu, value) { 149 if prev != value { 150 if value { 151 p.present_cnt 152 .fetch_add(1, core::sync::atomic::Ordering::SeqCst); 153 } else { 154 p.present_cnt 155 .fetch_sub(1, core::sync::atomic::Ordering::SeqCst); 156 } 157 } 158 } 159 } 160 161 /// 获取CPU的状态 162 pub fn cpuhp_state(&self, cpu_id: ProcessorId) -> &CpuHpCpuState { 163 unsafe { self.cpuhp_state.force_get(cpu_id) } 164 } 165 166 fn cpuhp_state_mut(&self, cpu_id: ProcessorId) -> &mut CpuHpCpuState { 167 unsafe { self.cpuhp_state.force_get_mut(cpu_id) } 168 } 169 170 /// 设置CPU的状态, 返回旧的状态 171 pub unsafe fn set_cpuhp_state( 172 &self, 173 cpu_id: ProcessorId, 174 target_state: CpuHpState, 175 ) -> CpuHpState { 176 let p = self.cpuhp_state.force_get_mut(cpu_id); 177 let old_state = p.state; 178 179 let bringup = target_state > p.state; 180 p.target_state = target_state; 181 p.bringup = bringup; 182 183 return old_state; 184 } 185 186 pub fn set_online_cpu(&self, cpu_id: ProcessorId) { 187 unsafe { self.set_cpuhp_state(cpu_id, CpuHpState::Online) }; 188 } 189 190 /// 获取出现在系统中的CPU 191 #[allow(dead_code)] 192 pub fn present_cpus(&self) -> &CpuMask { 193 &self.present_cpus 194 } 195 196 /// 启动bsp以外的CPU 197 pub(super) fn bringup_nonboot_cpus(&self) { 198 for cpu_id in self.present_cpus().iter_cpu() { 199 if cpu_id == smp_get_processor_id() { 200 continue; 201 } 202 203 kdebug!("Bring up CPU {}", cpu_id.data()); 204 205 if let Err(e) = self.cpu_up(cpu_id, CpuHpState::Online) { 206 kerror!("Failed to bring up CPU {}: {:?}", cpu_id.data(), e); 207 } 208 } 209 210 kinfo!("All non-boot CPUs have been brought up"); 211 } 212 213 fn cpu_up(&self, cpu_id: ProcessorId, target_state: CpuHpState) -> Result<(), SystemError> { 214 if !self.possible_cpus().get(cpu_id).unwrap_or(false) { 215 return Err(SystemError::EINVAL); 216 } 217 218 let cpu_state = self.cpuhp_state(cpu_id).state; 219 kdebug!( 220 "cpu_up: cpu_id: {}, cpu_state: {:?}, target_state: {:?}", 221 cpu_id.data(), 222 cpu_state, 223 target_state 224 ); 225 // 如果CPU的状态已经达到或者超过目标状态,则直接返回 226 if cpu_state >= target_state { 227 return Ok(()); 228 } 229 230 unsafe { self.set_cpuhp_state(cpu_id, target_state) }; 231 let cpu_state = self.cpuhp_state(cpu_id).state; 232 if cpu_state > CpuHpState::ThresholdBringUp { 233 self.cpuhp_kick_ap(cpu_id, target_state)?; 234 } 235 236 return Ok(()); 237 } 238 239 fn cpuhp_kick_ap( 240 &self, 241 cpu_id: ProcessorId, 242 target_state: CpuHpState, 243 ) -> Result<(), SystemError> { 244 let prev_state = unsafe { self.set_cpuhp_state(cpu_id, target_state) }; 245 let hpstate = self.cpuhp_state_mut(cpu_id); 246 if let Err(e) = self.do_cpuhp_kick_ap(hpstate) { 247 self.cpuhp_reset_state(hpstate, prev_state); 248 self.do_cpuhp_kick_ap(hpstate).ok(); 249 250 return Err(e); 251 } 252 253 return Ok(()); 254 } 255 256 fn do_cpuhp_kick_ap(&self, cpu_state: &mut CpuHpCpuState) -> Result<(), SystemError> { 257 let pcb = cpu_state.thread.as_ref().ok_or(SystemError::EINVAL)?; 258 let cpu_id = pcb.sched_info().on_cpu().ok_or(SystemError::EINVAL)?; 259 260 // todo: 等待CPU启动完成 261 262 ProcessManager::wakeup(cpu_state.thread.as_ref().unwrap())?; 263 CurrentSMPArch::start_cpu(cpu_id, cpu_state)?; 264 assert_eq!(ProcessManager::current_pcb().preempt_count(), 0); 265 self.wait_for_ap_thread(cpu_state, cpu_state.bringup); 266 267 return Ok(()); 268 } 269 270 fn wait_for_ap_thread(&self, cpu_state: &mut CpuHpCpuState, bringup: bool) { 271 if bringup { 272 cpu_state.comp_done_up.wait_for_completion().ok(); 273 } else { 274 todo!("wait_for_ap_thread") 275 } 276 } 277 278 /// 完成AP的启动 279 pub fn complete_ap_thread(&self, bringup: bool) { 280 let cpu_id = smp_get_processor_id(); 281 let cpu_state = self.cpuhp_state_mut(cpu_id); 282 if bringup { 283 cpu_state.comp_done_up.complete(); 284 } else { 285 todo!("complete_ap_thread") 286 } 287 } 288 289 fn cpuhp_reset_state(&self, st: &mut CpuHpCpuState, prev_state: CpuHpState) { 290 let bringup = !st.bringup; 291 st.target_state = prev_state; 292 293 st.bringup = bringup; 294 } 295 } 296 297 pub fn smp_cpu_manager_init(boot_cpu: ProcessorId) { 298 unsafe { 299 SMP_CPU_MANAGER = Some(SmpCpuManager::new()); 300 } 301 302 unsafe { smp_cpu_manager().set_possible_cpu(boot_cpu, true) }; 303 304 SmpCpuManager::arch_init(boot_cpu); 305 } 306