1 use core::sync::atomic::AtomicU32;
2
3 use alloc::{sync::Arc, vec::Vec};
4 use log::{debug, error, info};
5 use system_error::SystemError;
6
7 use crate::{
8 arch::CurrentSMPArch,
9 libs::cpumask::CpuMask,
10 mm::percpu::{PerCpu, PerCpuVar},
11 process::{ProcessControlBlock, ProcessManager},
12 sched::completion::Completion,
13 };
14
15 use super::{core::smp_get_processor_id, SMPArch};
16
17 int_like!(ProcessorId, AtomicProcessorId, u32, AtomicU32);
18
19 impl ProcessorId {
20 pub const INVALID: ProcessorId = ProcessorId::new(u32::MAX);
21 }
22
23 static mut SMP_CPU_MANAGER: Option<SmpCpuManager> = None;
24
25 #[inline]
smp_cpu_manager() -> &'static SmpCpuManager26 pub fn smp_cpu_manager() -> &'static SmpCpuManager {
27 unsafe { SMP_CPU_MANAGER.as_ref().unwrap() }
28 }
29
30 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
31 pub enum CpuHpState {
32 /// 启动阈值
33 ThresholdBringUp = 0,
34
35 /// 该CPU是离线的
36 Offline,
37
38 /// 该CPU是在线的
39 Online,
40 }
41
42 /// Per-Cpu Cpu的热插拔状态
43 pub struct CpuHpCpuState {
44 /// 当前状态
45 state: CpuHpState,
46 /// 目标状态
47 target_state: CpuHpState,
48 /// 指向热插拔的线程的PCB
49 thread: Option<Arc<ProcessControlBlock>>,
50
51 /// 当前是否为启动流程
52 bringup: bool,
53 /// 启动完成的信号
54 comp_done_up: Completion,
55 }
56
57 impl CpuHpCpuState {
new() -> Self58 const fn new() -> Self {
59 Self {
60 state: CpuHpState::Offline,
61 target_state: CpuHpState::Offline,
62 thread: None,
63 bringup: false,
64 comp_done_up: Completion::new(),
65 }
66 }
67
68 #[allow(dead_code)]
thread(&self) -> &Option<Arc<ProcessControlBlock>>69 pub const fn thread(&self) -> &Option<Arc<ProcessControlBlock>> {
70 &self.thread
71 }
72 }
73
74 pub struct SmpCpuManager {
75 /// 可用的CPU
76 possible_cpus: CpuMask,
77 /// 出现的CPU
78 present_cpus: CpuMask,
79 /// 出现在系统中的CPU的数量
80 present_cnt: AtomicU32,
81 /// 可用的CPU的数量
82 possible_cnt: AtomicU32,
83 /// CPU的状态
84 cpuhp_state: PerCpuVar<CpuHpCpuState>,
85 }
86
87 impl SmpCpuManager {
new() -> Self88 fn new() -> Self {
89 let possible_cpus = CpuMask::new();
90 let present_cpus = CpuMask::new();
91 let mut data = Vec::with_capacity(PerCpu::MAX_CPU_NUM as usize);
92 for i in 0..PerCpu::MAX_CPU_NUM {
93 let mut hpstate = CpuHpCpuState::new();
94 hpstate.thread = Some(ProcessManager::idle_pcb()[i as usize].clone());
95 data.push(hpstate);
96 }
97 let cpuhp_state = PerCpuVar::new(data).unwrap();
98
99 Self {
100 possible_cpus,
101 present_cpus,
102 cpuhp_state,
103 present_cnt: AtomicU32::new(0),
104 possible_cnt: AtomicU32::new(0),
105 }
106 }
107
108 /// 设置可用的CPU
109 ///
110 /// # Safety
111 ///
112 /// - 该函数不会检查CPU的有效性,调用者需要保证CPU的有效性。
113 /// - 由于possible_cpus是一个全局变量,且为了性能考虑,并不会加锁
114 /// 访问,因此该函数只能在初始化阶段调用。
set_possible_cpu(&self, cpu: ProcessorId, value: bool)115 pub unsafe fn set_possible_cpu(&self, cpu: ProcessorId, value: bool) {
116 // 强制获取mut引用,因为该函数只能在初始化阶段调用
117 let p = (self as *const Self as *mut Self).as_mut().unwrap();
118
119 if let Some(prev) = p.possible_cpus.set(cpu, value) {
120 if prev != value {
121 if value {
122 p.possible_cnt
123 .fetch_add(1, core::sync::atomic::Ordering::SeqCst);
124 } else {
125 p.possible_cnt
126 .fetch_sub(1, core::sync::atomic::Ordering::SeqCst);
127 }
128 }
129 }
130 }
131
132 /// 获取可用的CPU
possible_cpus(&self) -> &CpuMask133 pub fn possible_cpus(&self) -> &CpuMask {
134 &self.possible_cpus
135 }
136
possible_cpus_count(&self) -> u32137 pub fn possible_cpus_count(&self) -> u32 {
138 self.possible_cnt.load(core::sync::atomic::Ordering::SeqCst)
139 }
140
present_cpus_count(&self) -> u32141 pub fn present_cpus_count(&self) -> u32 {
142 self.present_cnt.load(core::sync::atomic::Ordering::SeqCst)
143 }
144
set_present_cpu(&self, cpu: ProcessorId, value: bool)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的状态
cpuhp_state(&self, cpu_id: ProcessorId) -> &CpuHpCpuState163 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)]
cpuhp_state_mut(&self, cpu_id: ProcessorId) -> &mut CpuHpCpuState168 fn cpuhp_state_mut(&self, cpu_id: ProcessorId) -> &mut CpuHpCpuState {
169 unsafe { self.cpuhp_state.force_get_mut(cpu_id) }
170 }
171
172 /// 设置CPU的状态, 返回旧的状态
set_cpuhp_state( &self, cpu_id: ProcessorId, target_state: CpuHpState, ) -> CpuHpState173 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
set_online_cpu(&self, cpu_id: ProcessorId)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)]
present_cpus(&self) -> &CpuMask194 pub fn present_cpus(&self) -> &CpuMask {
195 &self.present_cpus
196 }
197
198 /// 启动bsp以外的CPU
bringup_nonboot_cpus(&self)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 debug!("Bring up CPU {}", cpu_id.data());
206
207 if let Err(e) = self.cpu_up(cpu_id, CpuHpState::Online) {
208 error!("Failed to bring up CPU {}: {:?}", cpu_id.data(), e);
209 }
210 }
211
212 info!("All non-boot CPUs have been brought up");
213 }
214
cpu_up(&self, cpu_id: ProcessorId, target_state: CpuHpState) -> Result<(), SystemError>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 debug!(
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
cpuhp_kick_ap( &self, cpu_id: ProcessorId, target_state: CpuHpState, ) -> Result<(), SystemError>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
do_cpuhp_kick_ap(&self, cpu_state: &mut CpuHpCpuState) -> Result<(), SystemError>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
wait_for_ap_thread(&self, cpu_state: &mut CpuHpCpuState, bringup: bool)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的启动
complete_ap_thread(&self, bringup: bool)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
cpuhp_reset_state(&self, st: &mut CpuHpCpuState, prev_state: CpuHpState)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
smp_cpu_manager_init(boot_cpu: ProcessorId)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