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