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