1use core::sync::atomic::{AtomicUsize, Ordering};
2
3use axconfig::{TASK_STACK_SIZE, plat::CPU_NUM};
4use axhal::mem::{VirtAddr, virt_to_phys};
5
6#[unsafe(link_section = ".bss.stack")]
7static mut SECONDARY_BOOT_STACK: [[u8; TASK_STACK_SIZE]; CPU_NUM - 1] =
8 [[0; TASK_STACK_SIZE]; CPU_NUM - 1];
9
10static ENTERED_CPUS: AtomicUsize = AtomicUsize::new(1);
11
12#[allow(clippy::absurd_extreme_comparisons)]
13pub fn start_secondary_cpus(primary_cpu_id: usize) {
14 let mut logic_cpu_id = 0;
15 for i in 0..CPU_NUM {
16 if i != primary_cpu_id && logic_cpu_id < CPU_NUM - 1 {
17 let stack_top = virt_to_phys(VirtAddr::from(unsafe {
18 SECONDARY_BOOT_STACK[logic_cpu_id].as_ptr_range().end as usize
19 }));
20
21 debug!("starting CPU {}...", i);
22 axhal::power::cpu_boot(i, stack_top.as_usize());
23 logic_cpu_id += 1;
24
25 while ENTERED_CPUS.load(Ordering::Acquire) <= logic_cpu_id {
26 core::hint::spin_loop();
27 }
28 }
29 }
30}
31
32#[axplat::secondary_main]
36pub fn rust_main_secondary(cpu_id: usize) -> ! {
37 axhal::init_percpu_secondary(cpu_id);
38 axhal::init_early_secondary(cpu_id);
39
40 ENTERED_CPUS.fetch_add(1, Ordering::Release);
41 info!("Secondary CPU {} started.", cpu_id);
42
43 #[cfg(feature = "paging")]
44 axmm::init_memory_management_secondary();
45
46 axhal::init_later_secondary(cpu_id);
47
48 #[cfg(feature = "multitask")]
49 axtask::init_scheduler_secondary();
50
51 info!("Secondary CPU {:x} init OK.", cpu_id);
52 super::INITED_CPUS.fetch_add(1, Ordering::Release);
53
54 while !super::is_init_ok() {
55 core::hint::spin_loop();
56 }
57
58 #[cfg(feature = "irq")]
59 axhal::asm::enable_irqs();
60
61 #[cfg(all(feature = "tls", not(feature = "multitask")))]
62 super::init_tls();
63
64 #[cfg(feature = "multitask")]
65 axtask::run_idle();
66 #[cfg(not(feature = "multitask"))]
67 loop {
68 axhal::asm::wait_for_irqs();
69 }
70}