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
137 #[allow(dead_code)]
possible_cpus_count(&self) -> u32138 pub fn possible_cpus_count(&self) -> u32 {
139 self.possible_cnt.load(core::sync::atomic::Ordering::SeqCst)
140 }
141
present_cpus_count(&self) -> u32142 pub fn present_cpus_count(&self) -> u32 {
143 self.present_cnt.load(core::sync::atomic::Ordering::SeqCst)
144 }
145
set_present_cpu(&self, cpu: ProcessorId, value: bool)146 pub unsafe fn set_present_cpu(&self, cpu: ProcessorId, value: bool) {
147 // 强制获取mut引用,因为该函数只能在初始化阶段调用
148 let p = (self as *const Self as *mut Self).as_mut().unwrap();
149
150 if let Some(prev) = p.present_cpus.set(cpu, value) {
151 if prev != value {
152 if value {
153 p.present_cnt
154 .fetch_add(1, core::sync::atomic::Ordering::SeqCst);
155 } else {
156 p.present_cnt
157 .fetch_sub(1, core::sync::atomic::Ordering::SeqCst);
158 }
159 }
160 }
161 }
162
163 /// 获取CPU的状态
cpuhp_state(&self, cpu_id: ProcessorId) -> &CpuHpCpuState164 pub fn cpuhp_state(&self, cpu_id: ProcessorId) -> &CpuHpCpuState {
165 unsafe { self.cpuhp_state.force_get(cpu_id) }
166 }
167
168 #[allow(clippy::mut_from_ref)]
cpuhp_state_mut(&self, cpu_id: ProcessorId) -> &mut CpuHpCpuState169 fn cpuhp_state_mut(&self, cpu_id: ProcessorId) -> &mut CpuHpCpuState {
170 unsafe { self.cpuhp_state.force_get_mut(cpu_id) }
171 }
172
173 /// 设置CPU的状态, 返回旧的状态
set_cpuhp_state( &self, cpu_id: ProcessorId, target_state: CpuHpState, ) -> CpuHpState174 pub unsafe fn set_cpuhp_state(
175 &self,
176 cpu_id: ProcessorId,
177 target_state: CpuHpState,
178 ) -> CpuHpState {
179 let p = self.cpuhp_state.force_get_mut(cpu_id);
180 let old_state = p.state;
181
182 let bringup = target_state > p.state;
183 p.target_state = target_state;
184 p.bringup = bringup;
185
186 return old_state;
187 }
188
set_online_cpu(&self, cpu_id: ProcessorId)189 pub fn set_online_cpu(&self, cpu_id: ProcessorId) {
190 unsafe { self.set_cpuhp_state(cpu_id, CpuHpState::Online) };
191 }
192
193 /// 获取出现在系统中的CPU
194 #[allow(dead_code)]
present_cpus(&self) -> &CpuMask195 pub fn present_cpus(&self) -> &CpuMask {
196 &self.present_cpus
197 }
198
199 /// 启动bsp以外的CPU
bringup_nonboot_cpus(&self)200 pub(super) fn bringup_nonboot_cpus(&self) {
201 for cpu_id in self.present_cpus().iter_cpu() {
202 if cpu_id == smp_get_processor_id() {
203 continue;
204 }
205
206 debug!("Bring up CPU {}", cpu_id.data());
207
208 if let Err(e) = self.cpu_up(cpu_id, CpuHpState::Online) {
209 error!("Failed to bring up CPU {}: {:?}", cpu_id.data(), e);
210 }
211 }
212
213 info!("All non-boot CPUs have been brought up");
214 }
215
cpu_up(&self, cpu_id: ProcessorId, target_state: CpuHpState) -> Result<(), SystemError>216 fn cpu_up(&self, cpu_id: ProcessorId, target_state: CpuHpState) -> Result<(), SystemError> {
217 if !self.possible_cpus().get(cpu_id).unwrap_or(false) {
218 return Err(SystemError::EINVAL);
219 }
220
221 let cpu_state = self.cpuhp_state(cpu_id).state;
222 debug!(
223 "cpu_up: cpu_id: {}, cpu_state: {:?}, target_state: {:?}",
224 cpu_id.data(),
225 cpu_state,
226 target_state
227 );
228 // 如果CPU的状态已经达到或者超过目标状态,则直接返回
229 if cpu_state >= target_state {
230 return Ok(());
231 }
232
233 unsafe { self.set_cpuhp_state(cpu_id, target_state) };
234 let cpu_state = self.cpuhp_state(cpu_id).state;
235 if cpu_state > CpuHpState::ThresholdBringUp {
236 self.cpuhp_kick_ap(cpu_id, target_state)?;
237 }
238
239 return Ok(());
240 }
241
cpuhp_kick_ap( &self, cpu_id: ProcessorId, target_state: CpuHpState, ) -> Result<(), SystemError>242 fn cpuhp_kick_ap(
243 &self,
244 cpu_id: ProcessorId,
245 target_state: CpuHpState,
246 ) -> Result<(), SystemError> {
247 let prev_state = unsafe { self.set_cpuhp_state(cpu_id, target_state) };
248 let hpstate = self.cpuhp_state_mut(cpu_id);
249 if let Err(e) = self.do_cpuhp_kick_ap(hpstate) {
250 self.cpuhp_reset_state(hpstate, prev_state);
251 self.do_cpuhp_kick_ap(hpstate).ok();
252
253 return Err(e);
254 }
255
256 return Ok(());
257 }
258
do_cpuhp_kick_ap(&self, cpu_state: &mut CpuHpCpuState) -> Result<(), SystemError>259 fn do_cpuhp_kick_ap(&self, cpu_state: &mut CpuHpCpuState) -> Result<(), SystemError> {
260 let pcb = cpu_state.thread.as_ref().ok_or(SystemError::EINVAL)?;
261 let cpu_id = pcb.sched_info().on_cpu().ok_or(SystemError::EINVAL)?;
262
263 // todo: 等待CPU启动完成
264
265 ProcessManager::wakeup(cpu_state.thread.as_ref().unwrap())?;
266
267 CurrentSMPArch::start_cpu(cpu_id, cpu_state)?;
268 assert_eq!(ProcessManager::current_pcb().preempt_count(), 0);
269 self.wait_for_ap_thread(cpu_state, cpu_state.bringup);
270
271 return Ok(());
272 }
273
wait_for_ap_thread(&self, cpu_state: &mut CpuHpCpuState, bringup: bool)274 fn wait_for_ap_thread(&self, cpu_state: &mut CpuHpCpuState, bringup: bool) {
275 if bringup {
276 cpu_state
277 .comp_done_up
278 .wait_for_completion()
279 .expect("failed to wait ap thread");
280 } else {
281 todo!("wait_for_ap_thread")
282 }
283 }
284
285 /// 完成AP的启动
complete_ap_thread(&self, bringup: bool)286 pub fn complete_ap_thread(&self, bringup: bool) {
287 let cpu_id = smp_get_processor_id();
288 let cpu_state = self.cpuhp_state_mut(cpu_id);
289 if bringup {
290 cpu_state.comp_done_up.complete();
291 } else {
292 todo!("complete_ap_thread")
293 }
294 }
295
cpuhp_reset_state(&self, st: &mut CpuHpCpuState, prev_state: CpuHpState)296 fn cpuhp_reset_state(&self, st: &mut CpuHpCpuState, prev_state: CpuHpState) {
297 let bringup = !st.bringup;
298 st.target_state = prev_state;
299
300 st.bringup = bringup;
301 }
302 }
303
smp_cpu_manager_init(boot_cpu: ProcessorId)304 pub fn smp_cpu_manager_init(boot_cpu: ProcessorId) {
305 unsafe {
306 SMP_CPU_MANAGER = Some(SmpCpuManager::new());
307 }
308
309 unsafe { smp_cpu_manager().set_possible_cpu(boot_cpu, true) };
310 unsafe { smp_cpu_manager().set_present_cpu(boot_cpu, true) };
311
312 SmpCpuManager::arch_init(boot_cpu);
313 }
314