1 use core::{ 2 cell::RefCell, 3 hint::spin_loop, 4 ptr::{read_volatile, write_volatile}, 5 }; 6 7 use log::{debug, error, info}; 8 9 use crate::{ 10 mm::{ 11 mmio_buddy::{mmio_pool, MMIOSpaceGuard}, 12 percpu::PerCpu, 13 PhysAddr, VirtAddr, 14 }, 15 smp::core::smp_get_processor_id, 16 }; 17 18 use super::{hw_irq::ApicId, LVTRegister, LocalAPIC, LVT}; 19 20 /// per-cpu的xAPIC的MMIO空间起始地址 21 static mut XAPIC_INSTANCES: [RefCell<Option<XApic>>; PerCpu::MAX_CPU_NUM as usize] = 22 [const { RefCell::new(None) }; PerCpu::MAX_CPU_NUM as usize]; 23 24 #[inline(always)] 25 pub(super) fn current_xapic_instance() -> &'static RefCell<Option<XApic>> { 26 unsafe { &XAPIC_INSTANCES.as_ref()[smp_get_processor_id().data() as usize] } 27 } 28 29 /// TODO:统一变量 30 /// @brief local APIC 寄存器地址偏移量 31 #[derive(Debug)] 32 #[allow(dead_code)] 33 #[allow(non_camel_case_types)] 34 #[repr(u32)] 35 pub enum XApicOffset { 36 // 定义各个寄存器的地址偏移量 37 LOCAL_APIC_OFFSET_Local_APIC_ID = 0x20, 38 LOCAL_APIC_OFFSET_Local_APIC_Version = 0x30, 39 LOCAL_APIC_OFFSET_Local_APIC_TPR = 0x80, 40 LOCAL_APIC_OFFSET_Local_APIC_APR = 0x90, 41 LOCAL_APIC_OFFSET_Local_APIC_PPR = 0xa0, 42 LOCAL_APIC_OFFSET_Local_APIC_EOI = 0xb0, 43 LOCAL_APIC_OFFSET_Local_APIC_RRD = 0xc0, 44 LOCAL_APIC_OFFSET_Local_APIC_LDR = 0xd0, 45 LOCAL_APIC_OFFSET_Local_APIC_DFR = 0xe0, 46 LOCAL_APIC_OFFSET_Local_APIC_SVR = 0xf0, 47 48 LOCAL_APIC_OFFSET_Local_APIC_ISR_31_0 = 0x100, // In-Service Register 49 LOCAL_APIC_OFFSET_Local_APIC_ISR_63_32 = 0x110, 50 LOCAL_APIC_OFFSET_Local_APIC_ISR_95_64 = 0x120, 51 LOCAL_APIC_OFFSET_Local_APIC_ISR_127_96 = 0x130, 52 LOCAL_APIC_OFFSET_Local_APIC_ISR_159_128 = 0x140, 53 LOCAL_APIC_OFFSET_Local_APIC_ISR_191_160 = 0x150, 54 LOCAL_APIC_OFFSET_Local_APIC_ISR_223_192 = 0x160, 55 LOCAL_APIC_OFFSET_Local_APIC_ISR_255_224 = 0x170, 56 57 LOCAL_APIC_OFFSET_Local_APIC_TMR_31_0 = 0x180, // Trigger Mode Register 58 LOCAL_APIC_OFFSET_Local_APIC_TMR_63_32 = 0x190, 59 LOCAL_APIC_OFFSET_Local_APIC_TMR_95_64 = 0x1a0, 60 LOCAL_APIC_OFFSET_Local_APIC_TMR_127_96 = 0x1b0, 61 LOCAL_APIC_OFFSET_Local_APIC_TMR_159_128 = 0x1c0, 62 LOCAL_APIC_OFFSET_Local_APIC_TMR_191_160 = 0x1d0, 63 LOCAL_APIC_OFFSET_Local_APIC_TMR_223_192 = 0x1e0, 64 LOCAL_APIC_OFFSET_Local_APIC_TMR_255_224 = 0x1f0, 65 66 LOCAL_APIC_OFFSET_Local_APIC_IRR_31_0 = 0x200, // Interrupt Request Register 67 LOCAL_APIC_OFFSET_Local_APIC_IRR_63_32 = 0x210, 68 LOCAL_APIC_OFFSET_Local_APIC_IRR_95_64 = 0x220, 69 LOCAL_APIC_OFFSET_Local_APIC_IRR_127_96 = 0x230, 70 LOCAL_APIC_OFFSET_Local_APIC_IRR_159_128 = 0x240, 71 LOCAL_APIC_OFFSET_Local_APIC_IRR_191_160 = 0x250, 72 LOCAL_APIC_OFFSET_Local_APIC_IRR_223_192 = 0x260, 73 LOCAL_APIC_OFFSET_Local_APIC_IRR_255_224 = 0x270, 74 75 LOCAL_APIC_OFFSET_Local_APIC_ESR = 0x280, // Error Status Register 76 77 LOCAL_APIC_OFFSET_Local_APIC_LVT_CMCI = 0x2f0, // Corrected Machine Check Interrupt Register 78 79 LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0 = 0x300, // Interrupt Command Register 80 LOCAL_APIC_OFFSET_Local_APIC_ICR_63_32 = 0x310, 81 82 LOCAL_APIC_OFFSET_Local_APIC_LVT_TIMER = 0x320, 83 LOCAL_APIC_OFFSET_Local_APIC_LVT_THERMAL = 0x330, 84 LOCAL_APIC_OFFSET_Local_APIC_LVT_PERFORMANCE_MONITOR = 0x340, 85 LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT0 = 0x350, 86 LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT1 = 0x360, 87 LOCAL_APIC_OFFSET_Local_APIC_LVT_ERROR = 0x370, 88 // 初始计数寄存器(定时器专用) 89 LOCAL_APIC_OFFSET_Local_APIC_INITIAL_COUNT_REG = 0x380, 90 // 当前计数寄存器(定时器专用) 91 LOCAL_APIC_OFFSET_Local_APIC_CURRENT_COUNT_REG = 0x390, 92 LOCAL_APIC_OFFSET_Local_APIC_CLKDIV = 0x3e0, 93 } 94 95 impl From<XApicOffset> for u32 { 96 fn from(val: XApicOffset) -> Self { 97 val as u32 98 } 99 } 100 101 impl From<LVTRegister> for XApicOffset { 102 fn from(lvt: LVTRegister) -> Self { 103 match lvt { 104 LVTRegister::Timer => XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_TIMER, 105 LVTRegister::Thermal => XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_THERMAL, 106 LVTRegister::PerformanceMonitor => { 107 XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_PERFORMANCE_MONITOR 108 } 109 LVTRegister::LINT0 => XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT0, 110 LVTRegister::LINT1 => XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT1, 111 LVTRegister::ErrorReg => XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_ERROR, 112 LVTRegister::CMCI => XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_CMCI, 113 } 114 } 115 } 116 117 #[derive(Debug)] 118 #[allow(dead_code)] 119 pub struct XApic { 120 /// 当前xAPIC的寄存器映射的虚拟地址。注意,每个CPU都有自己的xAPIC,所以这个地址是每个CPU都不一样的。 121 apic_vaddr: VirtAddr, 122 /// `apic_vaddr`与映射的空间起始位置之间的偏移量 123 offset: usize, 124 map_guard: MMIOSpaceGuard, 125 xapic_base: PhysAddr, 126 } 127 128 impl XApic { 129 /// 读取指定寄存器的值 130 #[allow(dead_code)] 131 pub unsafe fn read(&self, reg: XApicOffset) -> u32 { 132 read_volatile((self.apic_vaddr.data() + reg as usize) as *const u32) 133 } 134 135 /// 将指定的值写入寄存器 136 #[allow(dead_code)] 137 pub unsafe fn write(&self, reg: XApicOffset, value: u32) { 138 write_volatile( 139 (self.apic_vaddr.data() + (reg as u32) as usize) as *mut u32, 140 value, 141 ); 142 self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ID); // 等待写操作完成,通过读取进行同步 143 } 144 } 145 146 impl XApic { 147 /// 创建新的XAPIC实例 148 /// 149 /// ## 参数 150 /// 151 /// - `xapic_base` - 当前核心的xAPIC的寄存器的物理地址 152 pub unsafe fn new(xapic_base: PhysAddr) -> Self { 153 let offset = xapic_base.data() & 0xffff; 154 let paddr = PhysAddr::new(xapic_base.data() & !0xffff); 155 let g = mmio_pool() 156 .create_mmio(4096) 157 .expect("Fail to create MMIO for XAPIC"); 158 g.map_phys(paddr, 4096).expect("Fail to map MMIO for XAPIC"); 159 let addr = g.vaddr() + offset; 160 161 debug!( 162 "XAPIC: {:#x} -> {:#x}, offset={offset}", 163 xapic_base.data(), 164 addr.data() 165 ); 166 167 let r = Self { 168 apic_vaddr: addr, 169 offset, 170 map_guard: g, 171 xapic_base, 172 }; 173 174 return r; 175 } 176 } 177 178 #[allow(dead_code)] 179 const X1: u32 = 0x0000000B; // 将除数设置为1,即不除频率 180 #[allow(dead_code)] 181 const PERIODIC: u32 = 0x00020000; // 周期性模式 182 #[allow(dead_code)] 183 const ENABLE: u32 = 0x00000100; // 单元使能 184 #[allow(dead_code)] 185 const MASKED: u32 = 0x00010000; // 中断屏蔽 186 const LEVEL: u32 = 0x00008000; // 电平触发 187 const BCAST: u32 = 0x00080000; // 发送到所有APIC,包括自己 188 const DELIVS: u32 = 0x00001000; // 传递状态 189 const INIT: u32 = 0x00000500; // INIT/RESET 190 191 //中断请求 192 #[allow(dead_code)] 193 const T_IRQ0: u32 = 32; // IRQ 0 对应于 T_IRQ 中断 194 #[allow(dead_code)] 195 const IRQ_TIMER: u32 = 0; 196 #[allow(dead_code)] 197 const IRQ_KBD: u32 = 1; 198 #[allow(dead_code)] 199 const IRQ_COM1: u32 = 4; 200 #[allow(dead_code)] 201 const IRQ_IDE: u32 = 14; 202 #[allow(dead_code)] 203 const IRQ_ERROR: u32 = 19; 204 #[allow(dead_code)] 205 const IRQ_SPURIOUS: u32 = 31; 206 207 impl LocalAPIC for XApic { 208 /// @brief 判断处理器是否支持apic 209 fn support() -> bool { 210 return x86::cpuid::CpuId::new() 211 .get_feature_info() 212 .expect("Fail to get CPU feature.") 213 .has_apic(); 214 } 215 216 /// @return true -> 函数运行成功 217 fn init_current_cpu(&mut self) -> bool { 218 unsafe { 219 // enable xapic 220 x86::msr::wrmsr(x86::msr::APIC_BASE, (self.xapic_base.data() | 0x800) as u64); 221 let val = x86::msr::rdmsr(x86::msr::APIC_BASE); 222 if val & 0x800 != 0x800 { 223 error!("xAPIC enable failed: APIC_BASE & 0x800 != 0x800"); 224 return false; 225 } 226 // 设置 Spurious Interrupt Vector Register 227 let val = self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_SVR); 228 229 self.write(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_SVR, val | ENABLE); 230 231 let val = self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_SVR); 232 if val & ENABLE == 0 { 233 error!("xAPIC software enable failed."); 234 235 return false; 236 } else { 237 info!("xAPIC software enabled."); 238 } 239 240 if val & 0x1000 != 0 { 241 info!("xAPIC EOI broadcast suppression enabled."); 242 } 243 244 self.mask_all_lvt(); 245 246 // 清除错误状态寄存器(需要连续写入两次) 247 self.write(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ESR, 0); 248 self.write(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ESR, 0); 249 250 // 确认任何未完成的中断 251 self.write(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_EOI, 0); 252 253 // 发送 Init Level De-Assert 信号以同步仲裁ID 254 self.write(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_63_32, 0); 255 self.write( 256 XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0, 257 BCAST | INIT | LEVEL, 258 ); 259 while self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0) & DELIVS != 0 { 260 spin_loop(); 261 } 262 } 263 264 true 265 } 266 267 /// 发送 EOI(End Of Interrupt) 268 fn send_eoi(&self) { 269 unsafe { 270 let s = self as *const Self as *mut Self; 271 (*s).write(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_EOI, 0); 272 } 273 } 274 275 /// 获取版本号 276 fn version(&self) -> u8 { 277 unsafe { (self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_Version) & 0xff) as u8 } 278 } 279 280 fn support_eoi_broadcast_suppression(&self) -> bool { 281 unsafe { ((self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_Version) >> 24) & 1) == 1 } 282 } 283 284 fn max_lvt_entry(&self) -> u8 { 285 unsafe { 286 ((self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_Version) >> 16) & 0xff) as u8 + 1 287 } 288 } 289 290 /// 获取ID 291 fn id(&self) -> ApicId { 292 unsafe { ApicId::new(self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ID) >> 24) } 293 } 294 295 /// 设置LVT寄存器的值 296 fn set_lvt(&mut self, lvt: LVT) { 297 unsafe { 298 self.write(lvt.register().into(), lvt.data); 299 } 300 } 301 302 fn read_lvt(&self, reg: LVTRegister) -> LVT { 303 unsafe { 304 LVT::new( 305 reg, 306 self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_TIMER), 307 ) 308 .unwrap() 309 } 310 } 311 312 fn mask_all_lvt(&mut self) { 313 // self.set_lvt(LVT::new(LVTRegister::CMCI, LVT::MASKED).unwrap()); 314 self.set_lvt(LVT::new(LVTRegister::Timer, LVT::MASKED).unwrap()); 315 self.set_lvt(LVT::new(LVTRegister::Thermal, LVT::MASKED).unwrap()); 316 self.set_lvt(LVT::new(LVTRegister::PerformanceMonitor, LVT::MASKED).unwrap()); 317 self.set_lvt(LVT::new(LVTRegister::LINT0, LVT::MASKED).unwrap()); 318 self.set_lvt(LVT::new(LVTRegister::LINT1, LVT::MASKED).unwrap()); 319 self.set_lvt(LVT::new(LVTRegister::ErrorReg, LVT::MASKED).unwrap()); 320 } 321 322 fn write_icr(&self, icr: x86::apic::Icr) { 323 unsafe { 324 // Wait for any previous send to finish 325 while self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0) & DELIVS != 0 { 326 spin_loop(); 327 } 328 329 self.write( 330 XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_63_32, 331 icr.upper(), 332 ); 333 self.write( 334 XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0, 335 icr.lower(), 336 ); 337 338 // Wait for send to finish 339 while self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0) & DELIVS != 0 { 340 spin_loop(); 341 } 342 } 343 } 344 } 345