1 use core::{ 2 arch::asm, 3 hint::spin_loop, 4 sync::atomic::{compiler_fence, AtomicBool, Ordering}, 5 }; 6 7 use memoffset::offset_of; 8 9 use crate::{ 10 arch::process::table::TSSManager, exception::InterruptArch, 11 include::bindings::bindings::cpu_core_info, kdebug, libs::rwlock::RwLock, mm::percpu::PerCpu, 12 process::ProcessManager, smp::core::smp_get_processor_id, syscall::SystemError, 13 }; 14 15 use super::CurrentIrqArch; 16 17 extern "C" { 18 fn smp_ap_start_stage2(); 19 } 20 21 pub(super) static X86_64_SMP_MANAGER: X86_64SmpManager = X86_64SmpManager::new(); 22 23 #[repr(C)] 24 struct ApStartStackInfo { 25 vaddr: usize, 26 } 27 28 /// AP处理器启动时执行 29 #[no_mangle] 30 unsafe extern "C" fn smp_ap_start() -> ! { 31 CurrentIrqArch::interrupt_disable(); 32 let vaddr = cpu_core_info[smp_get_processor_id() as usize].stack_start as usize; 33 compiler_fence(core::sync::atomic::Ordering::SeqCst); 34 let v = ApStartStackInfo { vaddr }; 35 smp_init_switch_stack(&v); 36 } 37 38 #[naked] 39 unsafe extern "sysv64" fn smp_init_switch_stack(st: &ApStartStackInfo) -> ! { 40 asm!(concat!(" 41 mov rsp, [rdi + {off_rsp}] 42 mov rbp, [rdi + {off_rsp}] 43 jmp {stage1} 44 "), 45 off_rsp = const(offset_of!(ApStartStackInfo, vaddr)), 46 stage1 = sym smp_ap_start_stage1, 47 options(noreturn)); 48 } 49 50 unsafe extern "C" fn smp_ap_start_stage1() -> ! { 51 let id = smp_get_processor_id(); 52 kdebug!("smp_ap_start_stage1: id: {}\n", id); 53 let current_idle = ProcessManager::idle_pcb()[smp_get_processor_id() as usize].clone(); 54 55 let tss = TSSManager::current_tss(); 56 57 tss.set_rsp( 58 x86::Ring::Ring0, 59 current_idle.kernel_stack().stack_max_address().data() as u64, 60 ); 61 TSSManager::load_tr(); 62 63 smp_ap_start_stage2(); 64 loop { 65 spin_loop(); 66 } 67 } 68 69 /// 多核的数据 70 #[derive(Debug)] 71 pub struct SmpBootData { 72 initialized: AtomicBool, 73 cpu_count: usize, 74 /// CPU的物理ID(指的是Local APIC ID) 75 /// 76 /// 这里必须保证第0项的是bsp的物理ID 77 phys_id: [usize; PerCpu::MAX_CPU_NUM], 78 } 79 80 #[allow(dead_code)] 81 impl SmpBootData { 82 pub fn cpu_count(&self) -> usize { 83 self.cpu_count 84 } 85 86 /// 获取CPU的物理ID 87 pub fn phys_id(&self, cpu_id: usize) -> usize { 88 self.phys_id[cpu_id] 89 } 90 91 /// 获取BSP的物理ID 92 pub fn bsp_phys_id(&self) -> usize { 93 self.phys_id[0] 94 } 95 96 pub unsafe fn set_cpu_count(&self, cpu_count: usize) { 97 if self.initialized.load(Ordering::SeqCst) == false { 98 let p = self as *const SmpBootData as *mut SmpBootData; 99 (*p).cpu_count = cpu_count; 100 } 101 } 102 103 pub unsafe fn set_phys_id(&self, cpu_id: usize, phys_id: usize) { 104 if self.initialized.load(Ordering::SeqCst) == false { 105 let p = self as *const SmpBootData as *mut SmpBootData; 106 (*p).phys_id[cpu_id] = phys_id; 107 } 108 } 109 110 /// 标记boot data结构体已经初始化完成 111 pub fn mark_initialized(&self) { 112 self.initialized.store(true, Ordering::SeqCst); 113 } 114 } 115 116 pub(super) static SMP_BOOT_DATA: SmpBootData = SmpBootData { 117 initialized: AtomicBool::new(false), 118 cpu_count: 0, 119 phys_id: [0; PerCpu::MAX_CPU_NUM], 120 }; 121 122 #[allow(dead_code)] 123 #[derive(Debug)] 124 pub struct X86_64SmpManager { 125 ia64_cpu_to_sapicid: RwLock<[Option<usize>; PerCpu::MAX_CPU_NUM]>, 126 } 127 128 impl X86_64SmpManager { 129 pub const fn new() -> Self { 130 return Self { 131 ia64_cpu_to_sapicid: RwLock::new([None; PerCpu::MAX_CPU_NUM]), 132 }; 133 } 134 /// initialize the logical cpu number to APIC ID mapping 135 pub fn build_cpu_map(&self) -> Result<(), SystemError> { 136 // 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/arch/ia64/kernel/smpboot.c?fi=smp_build_cpu_map#496 137 // todo!("build_cpu_map") 138 return Ok(()); 139 } 140 } 141