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