1e2841179SLoGin use core::sync::atomic::AtomicU32; 2e2841179SLoGin 38cb2e9b3SLoGin use alloc::{sync::Arc, vec::Vec}; 48cb2e9b3SLoGin use system_error::SystemError; 5338f6903SLoGin 68cb2e9b3SLoGin use crate::{ 78cb2e9b3SLoGin arch::CurrentSMPArch, 88cb2e9b3SLoGin libs::cpumask::CpuMask, 98cb2e9b3SLoGin mm::percpu::{PerCpu, PerCpuVar}, 108cb2e9b3SLoGin process::{ProcessControlBlock, ProcessManager}, 118cb2e9b3SLoGin sched::completion::Completion, 128cb2e9b3SLoGin }; 138cb2e9b3SLoGin 148cb2e9b3SLoGin use super::{core::smp_get_processor_id, SMPArch}; 15e2841179SLoGin 16e2841179SLoGin int_like!(ProcessorId, AtomicProcessorId, u32, AtomicU32); 17e2841179SLoGin 18e2841179SLoGin impl ProcessorId { 19e2841179SLoGin pub const INVALID: ProcessorId = ProcessorId::new(u32::MAX); 20e2841179SLoGin } 21338f6903SLoGin 22338f6903SLoGin static mut SMP_CPU_MANAGER: Option<SmpCpuManager> = None; 23338f6903SLoGin 24338f6903SLoGin #[inline] 25338f6903SLoGin pub fn smp_cpu_manager() -> &'static SmpCpuManager { 26338f6903SLoGin unsafe { SMP_CPU_MANAGER.as_ref().unwrap() } 27338f6903SLoGin } 28338f6903SLoGin 298cb2e9b3SLoGin #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] 308cb2e9b3SLoGin pub enum CpuHpState { 318cb2e9b3SLoGin /// 启动阈值 328cb2e9b3SLoGin ThresholdBringUp = 0, 338cb2e9b3SLoGin 348cb2e9b3SLoGin /// 该CPU是离线的 358cb2e9b3SLoGin Offline, 368cb2e9b3SLoGin 378cb2e9b3SLoGin /// 该CPU是在线的 388cb2e9b3SLoGin Online, 398cb2e9b3SLoGin } 408cb2e9b3SLoGin 418cb2e9b3SLoGin /// Per-Cpu Cpu的热插拔状态 428cb2e9b3SLoGin pub struct CpuHpCpuState { 438cb2e9b3SLoGin /// 当前状态 448cb2e9b3SLoGin state: CpuHpState, 458cb2e9b3SLoGin /// 目标状态 468cb2e9b3SLoGin target_state: CpuHpState, 478cb2e9b3SLoGin /// 指向热插拔的线程的PCB 488cb2e9b3SLoGin thread: Option<Arc<ProcessControlBlock>>, 498cb2e9b3SLoGin 508cb2e9b3SLoGin /// 当前是否为启动流程 518cb2e9b3SLoGin bringup: bool, 528cb2e9b3SLoGin /// 启动完成的信号 538cb2e9b3SLoGin comp_done_up: Completion, 548cb2e9b3SLoGin } 558cb2e9b3SLoGin 568cb2e9b3SLoGin impl CpuHpCpuState { 578cb2e9b3SLoGin const fn new() -> Self { 588cb2e9b3SLoGin Self { 598cb2e9b3SLoGin state: CpuHpState::Offline, 608cb2e9b3SLoGin target_state: CpuHpState::Offline, 618cb2e9b3SLoGin thread: None, 628cb2e9b3SLoGin bringup: false, 638cb2e9b3SLoGin comp_done_up: Completion::new(), 648cb2e9b3SLoGin } 658cb2e9b3SLoGin } 668cb2e9b3SLoGin 678cb2e9b3SLoGin pub const fn thread(&self) -> &Option<Arc<ProcessControlBlock>> { 688cb2e9b3SLoGin &self.thread 698cb2e9b3SLoGin } 708cb2e9b3SLoGin } 718cb2e9b3SLoGin 72338f6903SLoGin pub struct SmpCpuManager { 738cb2e9b3SLoGin /// 可用的CPU 74338f6903SLoGin possible_cpus: CpuMask, 758cb2e9b3SLoGin /// 出现的CPU 768cb2e9b3SLoGin present_cpus: CpuMask, 778cb2e9b3SLoGin /// 出现在系统中的CPU的数量 788cb2e9b3SLoGin present_cnt: AtomicU32, 798cb2e9b3SLoGin /// 可用的CPU的数量 808cb2e9b3SLoGin possible_cnt: AtomicU32, 818cb2e9b3SLoGin /// CPU的状态 828cb2e9b3SLoGin cpuhp_state: PerCpuVar<CpuHpCpuState>, 83338f6903SLoGin } 84338f6903SLoGin 85338f6903SLoGin impl SmpCpuManager { 86338f6903SLoGin fn new() -> Self { 87338f6903SLoGin let possible_cpus = CpuMask::new(); 888cb2e9b3SLoGin let present_cpus = CpuMask::new(); 898cb2e9b3SLoGin let mut data = Vec::with_capacity(PerCpu::MAX_CPU_NUM as usize); 908cb2e9b3SLoGin for i in 0..PerCpu::MAX_CPU_NUM { 918cb2e9b3SLoGin let mut hpstate = CpuHpCpuState::new(); 928cb2e9b3SLoGin hpstate.thread = Some(ProcessManager::idle_pcb()[i as usize].clone()); 938cb2e9b3SLoGin data.push(hpstate); 948cb2e9b3SLoGin } 958cb2e9b3SLoGin let cpuhp_state = PerCpuVar::new(data).unwrap(); 968cb2e9b3SLoGin 978cb2e9b3SLoGin Self { 988cb2e9b3SLoGin possible_cpus, 998cb2e9b3SLoGin present_cpus, 1008cb2e9b3SLoGin cpuhp_state, 1018cb2e9b3SLoGin present_cnt: AtomicU32::new(0), 1028cb2e9b3SLoGin possible_cnt: AtomicU32::new(0), 1038cb2e9b3SLoGin } 104338f6903SLoGin } 105338f6903SLoGin 106338f6903SLoGin /// 设置可用的CPU 107338f6903SLoGin /// 108338f6903SLoGin /// # Safety 109338f6903SLoGin /// 110338f6903SLoGin /// - 该函数不会检查CPU的有效性,调用者需要保证CPU的有效性。 111338f6903SLoGin /// - 由于possible_cpus是一个全局变量,且为了性能考虑,并不会加锁 112338f6903SLoGin /// 访问,因此该函数只能在初始化阶段调用。 113338f6903SLoGin pub unsafe fn set_possible_cpu(&self, cpu: ProcessorId, value: bool) { 114338f6903SLoGin // 强制获取mut引用,因为该函数只能在初始化阶段调用 115338f6903SLoGin let p = (self as *const Self as *mut Self).as_mut().unwrap(); 116338f6903SLoGin 1178cb2e9b3SLoGin if let Some(prev) = p.possible_cpus.set(cpu, value) { 1188cb2e9b3SLoGin if prev != value { 1198cb2e9b3SLoGin if value { 1208cb2e9b3SLoGin p.possible_cnt 1218cb2e9b3SLoGin .fetch_add(1, core::sync::atomic::Ordering::SeqCst); 1228cb2e9b3SLoGin } else { 1238cb2e9b3SLoGin p.possible_cnt 1248cb2e9b3SLoGin .fetch_sub(1, core::sync::atomic::Ordering::SeqCst); 1258cb2e9b3SLoGin } 1268cb2e9b3SLoGin } 1278cb2e9b3SLoGin } 128338f6903SLoGin } 129338f6903SLoGin 130338f6903SLoGin /// 获取可用的CPU 131338f6903SLoGin pub fn possible_cpus(&self) -> &CpuMask { 132338f6903SLoGin &self.possible_cpus 133338f6903SLoGin } 1348cb2e9b3SLoGin 1358cb2e9b3SLoGin #[allow(dead_code)] 1368cb2e9b3SLoGin pub fn possible_cpus_count(&self) -> u32 { 1378cb2e9b3SLoGin self.possible_cnt.load(core::sync::atomic::Ordering::SeqCst) 1388cb2e9b3SLoGin } 1398cb2e9b3SLoGin 1408cb2e9b3SLoGin pub fn present_cpus_count(&self) -> u32 { 1418cb2e9b3SLoGin self.present_cnt.load(core::sync::atomic::Ordering::SeqCst) 1428cb2e9b3SLoGin } 1438cb2e9b3SLoGin 1448cb2e9b3SLoGin pub unsafe fn set_present_cpu(&self, cpu: ProcessorId, value: bool) { 1458cb2e9b3SLoGin // 强制获取mut引用,因为该函数只能在初始化阶段调用 1468cb2e9b3SLoGin let p = (self as *const Self as *mut Self).as_mut().unwrap(); 1478cb2e9b3SLoGin 1488cb2e9b3SLoGin if let Some(prev) = p.present_cpus.set(cpu, value) { 1498cb2e9b3SLoGin if prev != value { 1508cb2e9b3SLoGin if value { 1518cb2e9b3SLoGin p.present_cnt 1528cb2e9b3SLoGin .fetch_add(1, core::sync::atomic::Ordering::SeqCst); 1538cb2e9b3SLoGin } else { 1548cb2e9b3SLoGin p.present_cnt 1558cb2e9b3SLoGin .fetch_sub(1, core::sync::atomic::Ordering::SeqCst); 1568cb2e9b3SLoGin } 1578cb2e9b3SLoGin } 1588cb2e9b3SLoGin } 1598cb2e9b3SLoGin } 1608cb2e9b3SLoGin 1618cb2e9b3SLoGin /// 获取CPU的状态 1628cb2e9b3SLoGin pub fn cpuhp_state(&self, cpu_id: ProcessorId) -> &CpuHpCpuState { 1638cb2e9b3SLoGin unsafe { self.cpuhp_state.force_get(cpu_id) } 1648cb2e9b3SLoGin } 1658cb2e9b3SLoGin 166b5b571e0SLoGin #[allow(clippy::mut_from_ref)] 1678cb2e9b3SLoGin fn cpuhp_state_mut(&self, cpu_id: ProcessorId) -> &mut CpuHpCpuState { 1688cb2e9b3SLoGin unsafe { self.cpuhp_state.force_get_mut(cpu_id) } 1698cb2e9b3SLoGin } 1708cb2e9b3SLoGin 1718cb2e9b3SLoGin /// 设置CPU的状态, 返回旧的状态 1728cb2e9b3SLoGin pub unsafe fn set_cpuhp_state( 1738cb2e9b3SLoGin &self, 1748cb2e9b3SLoGin cpu_id: ProcessorId, 1758cb2e9b3SLoGin target_state: CpuHpState, 1768cb2e9b3SLoGin ) -> CpuHpState { 1778cb2e9b3SLoGin let p = self.cpuhp_state.force_get_mut(cpu_id); 1788cb2e9b3SLoGin let old_state = p.state; 1798cb2e9b3SLoGin 1808cb2e9b3SLoGin let bringup = target_state > p.state; 1818cb2e9b3SLoGin p.target_state = target_state; 1828cb2e9b3SLoGin p.bringup = bringup; 1838cb2e9b3SLoGin 1848cb2e9b3SLoGin return old_state; 1858cb2e9b3SLoGin } 1868cb2e9b3SLoGin 1878cb2e9b3SLoGin pub fn set_online_cpu(&self, cpu_id: ProcessorId) { 1888cb2e9b3SLoGin unsafe { self.set_cpuhp_state(cpu_id, CpuHpState::Online) }; 1898cb2e9b3SLoGin } 1908cb2e9b3SLoGin 1918cb2e9b3SLoGin /// 获取出现在系统中的CPU 1928cb2e9b3SLoGin #[allow(dead_code)] 1938cb2e9b3SLoGin pub fn present_cpus(&self) -> &CpuMask { 1948cb2e9b3SLoGin &self.present_cpus 1958cb2e9b3SLoGin } 1968cb2e9b3SLoGin 1978cb2e9b3SLoGin /// 启动bsp以外的CPU 1988cb2e9b3SLoGin pub(super) fn bringup_nonboot_cpus(&self) { 1998cb2e9b3SLoGin for cpu_id in self.present_cpus().iter_cpu() { 2008cb2e9b3SLoGin if cpu_id == smp_get_processor_id() { 2018cb2e9b3SLoGin continue; 2028cb2e9b3SLoGin } 2038cb2e9b3SLoGin 2048cb2e9b3SLoGin kdebug!("Bring up CPU {}", cpu_id.data()); 2058cb2e9b3SLoGin 2068cb2e9b3SLoGin if let Err(e) = self.cpu_up(cpu_id, CpuHpState::Online) { 2078cb2e9b3SLoGin kerror!("Failed to bring up CPU {}: {:?}", cpu_id.data(), e); 2088cb2e9b3SLoGin } 2098cb2e9b3SLoGin } 2108cb2e9b3SLoGin 2118cb2e9b3SLoGin kinfo!("All non-boot CPUs have been brought up"); 2128cb2e9b3SLoGin } 2138cb2e9b3SLoGin 2148cb2e9b3SLoGin fn cpu_up(&self, cpu_id: ProcessorId, target_state: CpuHpState) -> Result<(), SystemError> { 2158cb2e9b3SLoGin if !self.possible_cpus().get(cpu_id).unwrap_or(false) { 2168cb2e9b3SLoGin return Err(SystemError::EINVAL); 2178cb2e9b3SLoGin } 2188cb2e9b3SLoGin 2198cb2e9b3SLoGin let cpu_state = self.cpuhp_state(cpu_id).state; 2208cb2e9b3SLoGin kdebug!( 2218cb2e9b3SLoGin "cpu_up: cpu_id: {}, cpu_state: {:?}, target_state: {:?}", 2228cb2e9b3SLoGin cpu_id.data(), 2238cb2e9b3SLoGin cpu_state, 2248cb2e9b3SLoGin target_state 2258cb2e9b3SLoGin ); 2268cb2e9b3SLoGin // 如果CPU的状态已经达到或者超过目标状态,则直接返回 2278cb2e9b3SLoGin if cpu_state >= target_state { 2288cb2e9b3SLoGin return Ok(()); 2298cb2e9b3SLoGin } 2308cb2e9b3SLoGin 2318cb2e9b3SLoGin unsafe { self.set_cpuhp_state(cpu_id, target_state) }; 2328cb2e9b3SLoGin let cpu_state = self.cpuhp_state(cpu_id).state; 2338cb2e9b3SLoGin if cpu_state > CpuHpState::ThresholdBringUp { 2348cb2e9b3SLoGin self.cpuhp_kick_ap(cpu_id, target_state)?; 2358cb2e9b3SLoGin } 2368cb2e9b3SLoGin 2378cb2e9b3SLoGin return Ok(()); 2388cb2e9b3SLoGin } 2398cb2e9b3SLoGin 2408cb2e9b3SLoGin fn cpuhp_kick_ap( 2418cb2e9b3SLoGin &self, 2428cb2e9b3SLoGin cpu_id: ProcessorId, 2438cb2e9b3SLoGin target_state: CpuHpState, 2448cb2e9b3SLoGin ) -> Result<(), SystemError> { 2458cb2e9b3SLoGin let prev_state = unsafe { self.set_cpuhp_state(cpu_id, target_state) }; 2468cb2e9b3SLoGin let hpstate = self.cpuhp_state_mut(cpu_id); 2478cb2e9b3SLoGin if let Err(e) = self.do_cpuhp_kick_ap(hpstate) { 2488cb2e9b3SLoGin self.cpuhp_reset_state(hpstate, prev_state); 2498cb2e9b3SLoGin self.do_cpuhp_kick_ap(hpstate).ok(); 2508cb2e9b3SLoGin 2518cb2e9b3SLoGin return Err(e); 2528cb2e9b3SLoGin } 2538cb2e9b3SLoGin 2548cb2e9b3SLoGin return Ok(()); 2558cb2e9b3SLoGin } 2568cb2e9b3SLoGin 2578cb2e9b3SLoGin fn do_cpuhp_kick_ap(&self, cpu_state: &mut CpuHpCpuState) -> Result<(), SystemError> { 2588cb2e9b3SLoGin let pcb = cpu_state.thread.as_ref().ok_or(SystemError::EINVAL)?; 2598cb2e9b3SLoGin let cpu_id = pcb.sched_info().on_cpu().ok_or(SystemError::EINVAL)?; 2608cb2e9b3SLoGin 2618cb2e9b3SLoGin // todo: 等待CPU启动完成 2628cb2e9b3SLoGin 2638cb2e9b3SLoGin ProcessManager::wakeup(cpu_state.thread.as_ref().unwrap())?; 264*3959e94dS曾俊 2658cb2e9b3SLoGin CurrentSMPArch::start_cpu(cpu_id, cpu_state)?; 2668cb2e9b3SLoGin assert_eq!(ProcessManager::current_pcb().preempt_count(), 0); 2678cb2e9b3SLoGin self.wait_for_ap_thread(cpu_state, cpu_state.bringup); 2688cb2e9b3SLoGin 2698cb2e9b3SLoGin return Ok(()); 2708cb2e9b3SLoGin } 2718cb2e9b3SLoGin 2728cb2e9b3SLoGin fn wait_for_ap_thread(&self, cpu_state: &mut CpuHpCpuState, bringup: bool) { 2738cb2e9b3SLoGin if bringup { 274*3959e94dS曾俊 cpu_state 275*3959e94dS曾俊 .comp_done_up 276*3959e94dS曾俊 .wait_for_completion() 277*3959e94dS曾俊 .expect("failed to wait ap thread"); 2788cb2e9b3SLoGin } else { 2798cb2e9b3SLoGin todo!("wait_for_ap_thread") 2808cb2e9b3SLoGin } 2818cb2e9b3SLoGin } 2828cb2e9b3SLoGin 2838cb2e9b3SLoGin /// 完成AP的启动 2848cb2e9b3SLoGin pub fn complete_ap_thread(&self, bringup: bool) { 2858cb2e9b3SLoGin let cpu_id = smp_get_processor_id(); 2868cb2e9b3SLoGin let cpu_state = self.cpuhp_state_mut(cpu_id); 2878cb2e9b3SLoGin if bringup { 2888cb2e9b3SLoGin cpu_state.comp_done_up.complete(); 2898cb2e9b3SLoGin } else { 2908cb2e9b3SLoGin todo!("complete_ap_thread") 2918cb2e9b3SLoGin } 2928cb2e9b3SLoGin } 2938cb2e9b3SLoGin 2948cb2e9b3SLoGin fn cpuhp_reset_state(&self, st: &mut CpuHpCpuState, prev_state: CpuHpState) { 2958cb2e9b3SLoGin let bringup = !st.bringup; 2968cb2e9b3SLoGin st.target_state = prev_state; 2978cb2e9b3SLoGin 2988cb2e9b3SLoGin st.bringup = bringup; 2998cb2e9b3SLoGin } 300338f6903SLoGin } 301338f6903SLoGin 302338f6903SLoGin pub fn smp_cpu_manager_init(boot_cpu: ProcessorId) { 303338f6903SLoGin unsafe { 304338f6903SLoGin SMP_CPU_MANAGER = Some(SmpCpuManager::new()); 305338f6903SLoGin } 306338f6903SLoGin 307338f6903SLoGin unsafe { smp_cpu_manager().set_possible_cpu(boot_cpu, true) }; 308338f6903SLoGin 309338f6903SLoGin SmpCpuManager::arch_init(boot_cpu); 310338f6903SLoGin } 311