xref: /DragonOS/kernel/src/smp/cpu/mod.rs (revision 8cb2e9b344230227fe5f3ab3ebeb2522f1c5e289)
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     pub const fn thread(&self) -> &Option<Arc<ProcessControlBlock>> {
68         &self.thread
69     }
70 }
71 
72 pub struct SmpCpuManager {
73     /// 可用的CPU
74     possible_cpus: CpuMask,
75     /// 出现的CPU
76     present_cpus: CpuMask,
77     /// 出现在系统中的CPU的数量
78     present_cnt: AtomicU32,
79     /// 可用的CPU的数量
80     possible_cnt: AtomicU32,
81     /// CPU的状态
82     cpuhp_state: PerCpuVar<CpuHpCpuState>,
83 }
84 
85 impl SmpCpuManager {
86     fn new() -> Self {
87         let possible_cpus = CpuMask::new();
88         let present_cpus = CpuMask::new();
89         let mut data = Vec::with_capacity(PerCpu::MAX_CPU_NUM as usize);
90         for i in 0..PerCpu::MAX_CPU_NUM {
91             let mut hpstate = CpuHpCpuState::new();
92             hpstate.thread = Some(ProcessManager::idle_pcb()[i as usize].clone());
93             data.push(hpstate);
94         }
95         let cpuhp_state = PerCpuVar::new(data).unwrap();
96 
97         Self {
98             possible_cpus,
99             present_cpus,
100             cpuhp_state,
101             present_cnt: AtomicU32::new(0),
102             possible_cnt: AtomicU32::new(0),
103         }
104     }
105 
106     /// 设置可用的CPU
107     ///
108     /// # Safety
109     ///
110     /// - 该函数不会检查CPU的有效性,调用者需要保证CPU的有效性。
111     /// - 由于possible_cpus是一个全局变量,且为了性能考虑,并不会加锁
112     ///     访问,因此该函数只能在初始化阶段调用。
113     pub unsafe fn set_possible_cpu(&self, cpu: ProcessorId, value: bool) {
114         // 强制获取mut引用,因为该函数只能在初始化阶段调用
115         let p = (self as *const Self as *mut Self).as_mut().unwrap();
116 
117         if let Some(prev) = p.possible_cpus.set(cpu, value) {
118             if prev != value {
119                 if value {
120                     p.possible_cnt
121                         .fetch_add(1, core::sync::atomic::Ordering::SeqCst);
122                 } else {
123                     p.possible_cnt
124                         .fetch_sub(1, core::sync::atomic::Ordering::SeqCst);
125                 }
126             }
127         }
128     }
129 
130     /// 获取可用的CPU
131     pub fn possible_cpus(&self) -> &CpuMask {
132         &self.possible_cpus
133     }
134 
135     #[allow(dead_code)]
136     pub fn possible_cpus_count(&self) -> u32 {
137         self.possible_cnt.load(core::sync::atomic::Ordering::SeqCst)
138     }
139 
140     pub fn present_cpus_count(&self) -> u32 {
141         self.present_cnt.load(core::sync::atomic::Ordering::SeqCst)
142     }
143 
144     pub unsafe fn set_present_cpu(&self, cpu: ProcessorId, value: bool) {
145         // 强制获取mut引用,因为该函数只能在初始化阶段调用
146         let p = (self as *const Self as *mut Self).as_mut().unwrap();
147 
148         if let Some(prev) = p.present_cpus.set(cpu, value) {
149             if prev != value {
150                 if value {
151                     p.present_cnt
152                         .fetch_add(1, core::sync::atomic::Ordering::SeqCst);
153                 } else {
154                     p.present_cnt
155                         .fetch_sub(1, core::sync::atomic::Ordering::SeqCst);
156                 }
157             }
158         }
159     }
160 
161     /// 获取CPU的状态
162     pub fn cpuhp_state(&self, cpu_id: ProcessorId) -> &CpuHpCpuState {
163         unsafe { self.cpuhp_state.force_get(cpu_id) }
164     }
165 
166     fn cpuhp_state_mut(&self, cpu_id: ProcessorId) -> &mut CpuHpCpuState {
167         unsafe { self.cpuhp_state.force_get_mut(cpu_id) }
168     }
169 
170     /// 设置CPU的状态, 返回旧的状态
171     pub unsafe fn set_cpuhp_state(
172         &self,
173         cpu_id: ProcessorId,
174         target_state: CpuHpState,
175     ) -> CpuHpState {
176         let p = self.cpuhp_state.force_get_mut(cpu_id);
177         let old_state = p.state;
178 
179         let bringup = target_state > p.state;
180         p.target_state = target_state;
181         p.bringup = bringup;
182 
183         return old_state;
184     }
185 
186     pub fn set_online_cpu(&self, cpu_id: ProcessorId) {
187         unsafe { self.set_cpuhp_state(cpu_id, CpuHpState::Online) };
188     }
189 
190     /// 获取出现在系统中的CPU
191     #[allow(dead_code)]
192     pub fn present_cpus(&self) -> &CpuMask {
193         &self.present_cpus
194     }
195 
196     /// 启动bsp以外的CPU
197     pub(super) fn bringup_nonboot_cpus(&self) {
198         for cpu_id in self.present_cpus().iter_cpu() {
199             if cpu_id == smp_get_processor_id() {
200                 continue;
201             }
202 
203             kdebug!("Bring up CPU {}", cpu_id.data());
204 
205             if let Err(e) = self.cpu_up(cpu_id, CpuHpState::Online) {
206                 kerror!("Failed to bring up CPU {}: {:?}", cpu_id.data(), e);
207             }
208         }
209 
210         kinfo!("All non-boot CPUs have been brought up");
211     }
212 
213     fn cpu_up(&self, cpu_id: ProcessorId, target_state: CpuHpState) -> Result<(), SystemError> {
214         if !self.possible_cpus().get(cpu_id).unwrap_or(false) {
215             return Err(SystemError::EINVAL);
216         }
217 
218         let cpu_state = self.cpuhp_state(cpu_id).state;
219         kdebug!(
220             "cpu_up: cpu_id: {}, cpu_state: {:?}, target_state: {:?}",
221             cpu_id.data(),
222             cpu_state,
223             target_state
224         );
225         // 如果CPU的状态已经达到或者超过目标状态,则直接返回
226         if cpu_state >= target_state {
227             return Ok(());
228         }
229 
230         unsafe { self.set_cpuhp_state(cpu_id, target_state) };
231         let cpu_state = self.cpuhp_state(cpu_id).state;
232         if cpu_state > CpuHpState::ThresholdBringUp {
233             self.cpuhp_kick_ap(cpu_id, target_state)?;
234         }
235 
236         return Ok(());
237     }
238 
239     fn cpuhp_kick_ap(
240         &self,
241         cpu_id: ProcessorId,
242         target_state: CpuHpState,
243     ) -> Result<(), SystemError> {
244         let prev_state = unsafe { self.set_cpuhp_state(cpu_id, target_state) };
245         let hpstate = self.cpuhp_state_mut(cpu_id);
246         if let Err(e) = self.do_cpuhp_kick_ap(hpstate) {
247             self.cpuhp_reset_state(hpstate, prev_state);
248             self.do_cpuhp_kick_ap(hpstate).ok();
249 
250             return Err(e);
251         }
252 
253         return Ok(());
254     }
255 
256     fn do_cpuhp_kick_ap(&self, cpu_state: &mut CpuHpCpuState) -> Result<(), SystemError> {
257         let pcb = cpu_state.thread.as_ref().ok_or(SystemError::EINVAL)?;
258         let cpu_id = pcb.sched_info().on_cpu().ok_or(SystemError::EINVAL)?;
259 
260         // todo: 等待CPU启动完成
261 
262         ProcessManager::wakeup(cpu_state.thread.as_ref().unwrap())?;
263         CurrentSMPArch::start_cpu(cpu_id, cpu_state)?;
264         assert_eq!(ProcessManager::current_pcb().preempt_count(), 0);
265         self.wait_for_ap_thread(cpu_state, cpu_state.bringup);
266 
267         return Ok(());
268     }
269 
270     fn wait_for_ap_thread(&self, cpu_state: &mut CpuHpCpuState, bringup: bool) {
271         if bringup {
272             cpu_state.comp_done_up.wait_for_completion().ok();
273         } else {
274             todo!("wait_for_ap_thread")
275         }
276     }
277 
278     /// 完成AP的启动
279     pub fn complete_ap_thread(&self, bringup: bool) {
280         let cpu_id = smp_get_processor_id();
281         let cpu_state = self.cpuhp_state_mut(cpu_id);
282         if bringup {
283             cpu_state.comp_done_up.complete();
284         } else {
285             todo!("complete_ap_thread")
286         }
287     }
288 
289     fn cpuhp_reset_state(&self, st: &mut CpuHpCpuState, prev_state: CpuHpState) {
290         let bringup = !st.bringup;
291         st.target_state = prev_state;
292 
293         st.bringup = bringup;
294     }
295 }
296 
297 pub fn smp_cpu_manager_init(boot_cpu: ProcessorId) {
298     unsafe {
299         SMP_CPU_MANAGER = Some(SmpCpuManager::new());
300     }
301 
302     unsafe { smp_cpu_manager().set_possible_cpu(boot_cpu, true) };
303 
304     SmpCpuManager::arch_init(boot_cpu);
305 }
306