xref: /DragonOS/kernel/src/smp/cpu/mod.rs (revision 1f4877a4c512eb5ad232436128a0c52287b39aaa)
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