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 #[allow(dead_code)] 68 pub const fn thread(&self) -> &Option<Arc<ProcessControlBlock>> { 69 &self.thread 70 } 71 } 72 73 pub struct SmpCpuManager { 74 /// 可用的CPU 75 possible_cpus: CpuMask, 76 /// 出现的CPU 77 present_cpus: CpuMask, 78 /// 出现在系统中的CPU的数量 79 present_cnt: AtomicU32, 80 /// 可用的CPU的数量 81 possible_cnt: AtomicU32, 82 /// CPU的状态 83 cpuhp_state: PerCpuVar<CpuHpCpuState>, 84 } 85 86 impl SmpCpuManager { 87 fn new() -> Self { 88 let possible_cpus = CpuMask::new(); 89 let present_cpus = CpuMask::new(); 90 let mut data = Vec::with_capacity(PerCpu::MAX_CPU_NUM as usize); 91 for i in 0..PerCpu::MAX_CPU_NUM { 92 let mut hpstate = CpuHpCpuState::new(); 93 hpstate.thread = Some(ProcessManager::idle_pcb()[i as usize].clone()); 94 data.push(hpstate); 95 } 96 let cpuhp_state = PerCpuVar::new(data).unwrap(); 97 98 Self { 99 possible_cpus, 100 present_cpus, 101 cpuhp_state, 102 present_cnt: AtomicU32::new(0), 103 possible_cnt: AtomicU32::new(0), 104 } 105 } 106 107 /// 设置可用的CPU 108 /// 109 /// # Safety 110 /// 111 /// - 该函数不会检查CPU的有效性,调用者需要保证CPU的有效性。 112 /// - 由于possible_cpus是一个全局变量,且为了性能考虑,并不会加锁 113 /// 访问,因此该函数只能在初始化阶段调用。 114 pub unsafe fn set_possible_cpu(&self, cpu: ProcessorId, value: bool) { 115 // 强制获取mut引用,因为该函数只能在初始化阶段调用 116 let p = (self as *const Self as *mut Self).as_mut().unwrap(); 117 118 if let Some(prev) = p.possible_cpus.set(cpu, value) { 119 if prev != value { 120 if value { 121 p.possible_cnt 122 .fetch_add(1, core::sync::atomic::Ordering::SeqCst); 123 } else { 124 p.possible_cnt 125 .fetch_sub(1, core::sync::atomic::Ordering::SeqCst); 126 } 127 } 128 } 129 } 130 131 /// 获取可用的CPU 132 pub fn possible_cpus(&self) -> &CpuMask { 133 &self.possible_cpus 134 } 135 136 #[allow(dead_code)] 137 pub fn possible_cpus_count(&self) -> u32 { 138 self.possible_cnt.load(core::sync::atomic::Ordering::SeqCst) 139 } 140 141 pub fn present_cpus_count(&self) -> u32 { 142 self.present_cnt.load(core::sync::atomic::Ordering::SeqCst) 143 } 144 145 pub unsafe fn set_present_cpu(&self, cpu: ProcessorId, value: bool) { 146 // 强制获取mut引用,因为该函数只能在初始化阶段调用 147 let p = (self as *const Self as *mut Self).as_mut().unwrap(); 148 149 if let Some(prev) = p.present_cpus.set(cpu, value) { 150 if prev != value { 151 if value { 152 p.present_cnt 153 .fetch_add(1, core::sync::atomic::Ordering::SeqCst); 154 } else { 155 p.present_cnt 156 .fetch_sub(1, core::sync::atomic::Ordering::SeqCst); 157 } 158 } 159 } 160 } 161 162 /// 获取CPU的状态 163 pub fn cpuhp_state(&self, cpu_id: ProcessorId) -> &CpuHpCpuState { 164 unsafe { self.cpuhp_state.force_get(cpu_id) } 165 } 166 167 #[allow(clippy::mut_from_ref)] 168 fn cpuhp_state_mut(&self, cpu_id: ProcessorId) -> &mut CpuHpCpuState { 169 unsafe { self.cpuhp_state.force_get_mut(cpu_id) } 170 } 171 172 /// 设置CPU的状态, 返回旧的状态 173 pub unsafe fn set_cpuhp_state( 174 &self, 175 cpu_id: ProcessorId, 176 target_state: CpuHpState, 177 ) -> CpuHpState { 178 let p = self.cpuhp_state.force_get_mut(cpu_id); 179 let old_state = p.state; 180 181 let bringup = target_state > p.state; 182 p.target_state = target_state; 183 p.bringup = bringup; 184 185 return old_state; 186 } 187 188 pub fn set_online_cpu(&self, cpu_id: ProcessorId) { 189 unsafe { self.set_cpuhp_state(cpu_id, CpuHpState::Online) }; 190 } 191 192 /// 获取出现在系统中的CPU 193 #[allow(dead_code)] 194 pub fn present_cpus(&self) -> &CpuMask { 195 &self.present_cpus 196 } 197 198 /// 启动bsp以外的CPU 199 pub(super) fn bringup_nonboot_cpus(&self) { 200 for cpu_id in self.present_cpus().iter_cpu() { 201 if cpu_id == smp_get_processor_id() { 202 continue; 203 } 204 205 kdebug!("Bring up CPU {}", cpu_id.data()); 206 207 if let Err(e) = self.cpu_up(cpu_id, CpuHpState::Online) { 208 kerror!("Failed to bring up CPU {}: {:?}", cpu_id.data(), e); 209 } 210 } 211 212 kinfo!("All non-boot CPUs have been brought up"); 213 } 214 215 fn cpu_up(&self, cpu_id: ProcessorId, target_state: CpuHpState) -> Result<(), SystemError> { 216 if !self.possible_cpus().get(cpu_id).unwrap_or(false) { 217 return Err(SystemError::EINVAL); 218 } 219 220 let cpu_state = self.cpuhp_state(cpu_id).state; 221 kdebug!( 222 "cpu_up: cpu_id: {}, cpu_state: {:?}, target_state: {:?}", 223 cpu_id.data(), 224 cpu_state, 225 target_state 226 ); 227 // 如果CPU的状态已经达到或者超过目标状态,则直接返回 228 if cpu_state >= target_state { 229 return Ok(()); 230 } 231 232 unsafe { self.set_cpuhp_state(cpu_id, target_state) }; 233 let cpu_state = self.cpuhp_state(cpu_id).state; 234 if cpu_state > CpuHpState::ThresholdBringUp { 235 self.cpuhp_kick_ap(cpu_id, target_state)?; 236 } 237 238 return Ok(()); 239 } 240 241 fn cpuhp_kick_ap( 242 &self, 243 cpu_id: ProcessorId, 244 target_state: CpuHpState, 245 ) -> Result<(), SystemError> { 246 let prev_state = unsafe { self.set_cpuhp_state(cpu_id, target_state) }; 247 let hpstate = self.cpuhp_state_mut(cpu_id); 248 if let Err(e) = self.do_cpuhp_kick_ap(hpstate) { 249 self.cpuhp_reset_state(hpstate, prev_state); 250 self.do_cpuhp_kick_ap(hpstate).ok(); 251 252 return Err(e); 253 } 254 255 return Ok(()); 256 } 257 258 fn do_cpuhp_kick_ap(&self, cpu_state: &mut CpuHpCpuState) -> Result<(), SystemError> { 259 let pcb = cpu_state.thread.as_ref().ok_or(SystemError::EINVAL)?; 260 let cpu_id = pcb.sched_info().on_cpu().ok_or(SystemError::EINVAL)?; 261 262 // todo: 等待CPU启动完成 263 264 ProcessManager::wakeup(cpu_state.thread.as_ref().unwrap())?; 265 266 CurrentSMPArch::start_cpu(cpu_id, cpu_state)?; 267 assert_eq!(ProcessManager::current_pcb().preempt_count(), 0); 268 self.wait_for_ap_thread(cpu_state, cpu_state.bringup); 269 270 return Ok(()); 271 } 272 273 fn wait_for_ap_thread(&self, cpu_state: &mut CpuHpCpuState, bringup: bool) { 274 if bringup { 275 cpu_state 276 .comp_done_up 277 .wait_for_completion() 278 .expect("failed to wait ap thread"); 279 } else { 280 todo!("wait_for_ap_thread") 281 } 282 } 283 284 /// 完成AP的启动 285 pub fn complete_ap_thread(&self, bringup: bool) { 286 let cpu_id = smp_get_processor_id(); 287 let cpu_state = self.cpuhp_state_mut(cpu_id); 288 if bringup { 289 cpu_state.comp_done_up.complete(); 290 } else { 291 todo!("complete_ap_thread") 292 } 293 } 294 295 fn cpuhp_reset_state(&self, st: &mut CpuHpCpuState, prev_state: CpuHpState) { 296 let bringup = !st.bringup; 297 st.target_state = prev_state; 298 299 st.bringup = bringup; 300 } 301 } 302 303 pub fn smp_cpu_manager_init(boot_cpu: ProcessorId) { 304 unsafe { 305 SMP_CPU_MANAGER = Some(SmpCpuManager::new()); 306 } 307 308 unsafe { smp_cpu_manager().set_possible_cpu(boot_cpu, true) }; 309 unsafe { smp_cpu_manager().set_present_cpu(boot_cpu, true) }; 310 311 SmpCpuManager::arch_init(boot_cpu); 312 } 313