xref: /DragonOS/kernel/src/arch/x86_64/smp/mod.rs (revision 7ae679ddd6481897a86523a52fad3b060254fa5b)
1 use core::{arch::asm, hint::spin_loop, sync::atomic::compiler_fence};
2 
3 use memoffset::offset_of;
4 
5 use crate::{
6     arch::process::table::TSSManager, exception::InterruptArch,
7     include::bindings::bindings::cpu_core_info, kdebug, process::ProcessManager,
8     smp::core::smp_get_processor_id,
9 };
10 
11 use super::CurrentIrqArch;
12 
13 extern "C" {
14     fn smp_ap_start_stage2();
15 }
16 
17 #[repr(C)]
18 struct ApStartStackInfo {
19     vaddr: usize,
20 }
21 
22 /// AP处理器启动时执行
23 #[no_mangle]
24 unsafe extern "C" fn smp_ap_start() -> ! {
25     CurrentIrqArch::interrupt_disable();
26     let vaddr = cpu_core_info[smp_get_processor_id() as usize].stack_start as usize;
27     compiler_fence(core::sync::atomic::Ordering::SeqCst);
28     let v = ApStartStackInfo { vaddr };
29     smp_init_switch_stack(&v);
30 }
31 
32 #[naked]
33 unsafe extern "sysv64" fn smp_init_switch_stack(st: &ApStartStackInfo) -> ! {
34     asm!(concat!("
35         mov rsp, [rdi + {off_rsp}]
36         mov rbp, [rdi + {off_rsp}]
37         jmp {stage1}
38     "),
39         off_rsp = const(offset_of!(ApStartStackInfo, vaddr)),
40         stage1 = sym smp_ap_start_stage1,
41     options(noreturn));
42 }
43 
44 unsafe extern "C" fn smp_ap_start_stage1() -> ! {
45     let id = smp_get_processor_id();
46     kdebug!("smp_ap_start_stage1: id: {}\n", id);
47     let current_idle = ProcessManager::idle_pcb()[smp_get_processor_id() as usize].clone();
48 
49     let tss = TSSManager::current_tss();
50 
51     tss.set_rsp(
52         x86::Ring::Ring0,
53         current_idle.kernel_stack().stack_max_address().data() as u64,
54     );
55     TSSManager::load_tr();
56 
57     smp_ap_start_stage2();
58     loop {
59         spin_loop();
60     }
61 }
62