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 #[allow(clippy::mut_from_ref)] 167 fn cpuhp_state_mut(&self, cpu_id: ProcessorId) -> &mut CpuHpCpuState { 168 unsafe { self.cpuhp_state.force_get_mut(cpu_id) } 169 } 170 171 /// 设置CPU的状态, 返回旧的状态 172 pub unsafe fn set_cpuhp_state( 173 &self, 174 cpu_id: ProcessorId, 175 target_state: CpuHpState, 176 ) -> CpuHpState { 177 let p = self.cpuhp_state.force_get_mut(cpu_id); 178 let old_state = p.state; 179 180 let bringup = target_state > p.state; 181 p.target_state = target_state; 182 p.bringup = bringup; 183 184 return old_state; 185 } 186 187 pub fn set_online_cpu(&self, cpu_id: ProcessorId) { 188 unsafe { self.set_cpuhp_state(cpu_id, CpuHpState::Online) }; 189 } 190 191 /// 获取出现在系统中的CPU 192 #[allow(dead_code)] 193 pub fn present_cpus(&self) -> &CpuMask { 194 &self.present_cpus 195 } 196 197 /// 启动bsp以外的CPU 198 pub(super) fn bringup_nonboot_cpus(&self) { 199 for cpu_id in self.present_cpus().iter_cpu() { 200 if cpu_id == smp_get_processor_id() { 201 continue; 202 } 203 204 kdebug!("Bring up CPU {}", cpu_id.data()); 205 206 if let Err(e) = self.cpu_up(cpu_id, CpuHpState::Online) { 207 kerror!("Failed to bring up CPU {}: {:?}", cpu_id.data(), e); 208 } 209 } 210 211 kinfo!("All non-boot CPUs have been brought up"); 212 } 213 214 fn cpu_up(&self, cpu_id: ProcessorId, target_state: CpuHpState) -> Result<(), SystemError> { 215 if !self.possible_cpus().get(cpu_id).unwrap_or(false) { 216 return Err(SystemError::EINVAL); 217 } 218 219 let cpu_state = self.cpuhp_state(cpu_id).state; 220 kdebug!( 221 "cpu_up: cpu_id: {}, cpu_state: {:?}, target_state: {:?}", 222 cpu_id.data(), 223 cpu_state, 224 target_state 225 ); 226 // 如果CPU的状态已经达到或者超过目标状态,则直接返回 227 if cpu_state >= target_state { 228 return Ok(()); 229 } 230 231 unsafe { self.set_cpuhp_state(cpu_id, target_state) }; 232 let cpu_state = self.cpuhp_state(cpu_id).state; 233 if cpu_state > CpuHpState::ThresholdBringUp { 234 self.cpuhp_kick_ap(cpu_id, target_state)?; 235 } 236 237 return Ok(()); 238 } 239 240 fn cpuhp_kick_ap( 241 &self, 242 cpu_id: ProcessorId, 243 target_state: CpuHpState, 244 ) -> Result<(), SystemError> { 245 let prev_state = unsafe { self.set_cpuhp_state(cpu_id, target_state) }; 246 let hpstate = self.cpuhp_state_mut(cpu_id); 247 if let Err(e) = self.do_cpuhp_kick_ap(hpstate) { 248 self.cpuhp_reset_state(hpstate, prev_state); 249 self.do_cpuhp_kick_ap(hpstate).ok(); 250 251 return Err(e); 252 } 253 254 return Ok(()); 255 } 256 257 fn do_cpuhp_kick_ap(&self, cpu_state: &mut CpuHpCpuState) -> Result<(), SystemError> { 258 let pcb = cpu_state.thread.as_ref().ok_or(SystemError::EINVAL)?; 259 let cpu_id = pcb.sched_info().on_cpu().ok_or(SystemError::EINVAL)?; 260 261 // todo: 等待CPU启动完成 262 263 ProcessManager::wakeup(cpu_state.thread.as_ref().unwrap())?; 264 265 CurrentSMPArch::start_cpu(cpu_id, cpu_state)?; 266 assert_eq!(ProcessManager::current_pcb().preempt_count(), 0); 267 self.wait_for_ap_thread(cpu_state, cpu_state.bringup); 268 269 return Ok(()); 270 } 271 272 fn wait_for_ap_thread(&self, cpu_state: &mut CpuHpCpuState, bringup: bool) { 273 if bringup { 274 cpu_state 275 .comp_done_up 276 .wait_for_completion() 277 .expect("failed to wait ap thread"); 278 } else { 279 todo!("wait_for_ap_thread") 280 } 281 } 282 283 /// 完成AP的启动 284 pub fn complete_ap_thread(&self, bringup: bool) { 285 let cpu_id = smp_get_processor_id(); 286 let cpu_state = self.cpuhp_state_mut(cpu_id); 287 if bringup { 288 cpu_state.comp_done_up.complete(); 289 } else { 290 todo!("complete_ap_thread") 291 } 292 } 293 294 fn cpuhp_reset_state(&self, st: &mut CpuHpCpuState, prev_state: CpuHpState) { 295 let bringup = !st.bringup; 296 st.target_state = prev_state; 297 298 st.bringup = bringup; 299 } 300 } 301 302 pub fn smp_cpu_manager_init(boot_cpu: ProcessorId) { 303 unsafe { 304 SMP_CPU_MANAGER = Some(SmpCpuManager::new()); 305 } 306 307 unsafe { smp_cpu_manager().set_possible_cpu(boot_cpu, true) }; 308 309 SmpCpuManager::arch_init(boot_cpu); 310 } 311