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