mod.rs 9.0 KB

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