1 use core::sync::atomic::{fence, Ordering}; 2 3 use log::info; 4 use x86::msr::{ 5 rdmsr, wrmsr, IA32_APIC_BASE, IA32_X2APIC_APICID, IA32_X2APIC_EOI, IA32_X2APIC_SIVR, 6 IA32_X2APIC_VERSION, 7 }; 8 9 use super::{hw_irq::ApicId, LVTRegister, LocalAPIC, LVT}; 10 11 #[derive(Debug)] 12 pub struct X2Apic; 13 14 impl LocalAPIC for X2Apic { 15 /// @brief 判断处理器是否支持x2APIC 16 fn support() -> bool { 17 return x86::cpuid::CpuId::new() 18 .get_feature_info() 19 .expect("Get cpu feature info failed.") 20 .has_x2apic(); 21 } 22 /// @return true -> the function works 23 fn init_current_cpu(&mut self) -> bool { 24 unsafe { 25 // 设置 x2APIC 使能位 26 wrmsr(IA32_APIC_BASE, rdmsr(IA32_APIC_BASE) | 1 << 10); 27 28 assert!( 29 (rdmsr(IA32_APIC_BASE) & 0xc00) == 0xc00, 30 "x2APIC enable failed." 31 ); 32 33 // 设置Spurious-Interrupt Vector Register 34 { 35 let val = if self.support_eoi_broadcast_suppression() { 36 (1 << 12) | (1 << 8) 37 } else { 38 1 << 8 39 }; 40 41 wrmsr(IA32_X2APIC_SIVR, val); 42 43 assert!( 44 (rdmsr(IA32_X2APIC_SIVR) & 0x100) == 0x100, 45 "x2APIC software enable failed." 46 ); 47 info!("x2APIC software enabled."); 48 49 if self.support_eoi_broadcast_suppression() { 50 assert!( 51 (rdmsr(IA32_X2APIC_SIVR) & 0x1000) == 0x1000, 52 "x2APIC EOI broadcast suppression enable failed." 53 ); 54 info!("x2APIC EOI broadcast suppression enabled."); 55 } 56 } 57 // debug!("x2apic: to mask all lvt"); 58 self.mask_all_lvt(); 59 // debug!("x2apic: all lvt masked"); 60 } 61 true 62 } 63 64 /// 发送 EOI (End Of Interrupt) 65 fn send_eoi(&self) { 66 fence(Ordering::SeqCst); 67 unsafe { 68 wrmsr(IA32_X2APIC_EOI, 0); 69 } 70 71 fence(Ordering::SeqCst); 72 } 73 74 /// 获取 x2APIC 版本 75 fn version(&self) -> u8 { 76 unsafe { (rdmsr(IA32_X2APIC_VERSION) & 0xff) as u8 } 77 } 78 79 fn support_eoi_broadcast_suppression(&self) -> bool { 80 unsafe { ((rdmsr(IA32_X2APIC_VERSION) >> 24) & 1) == 1 } 81 } 82 83 fn max_lvt_entry(&self) -> u8 { 84 unsafe { ((rdmsr(IA32_X2APIC_VERSION) >> 16) & 0xff) as u8 + 1 } 85 } 86 87 /// 获取 x2APIC 的 APIC ID 88 fn id(&self) -> ApicId { 89 unsafe { ApicId::new(rdmsr(IA32_X2APIC_APICID) as u32) } 90 } 91 92 /// 设置 Local Vector Table (LVT) 寄存器 93 fn set_lvt(&mut self, lvt: LVT) { 94 unsafe { 95 wrmsr(lvt.register().into(), lvt.data as u64); 96 } 97 } 98 99 fn read_lvt(&self, reg: LVTRegister) -> LVT { 100 unsafe { LVT::new(reg, (rdmsr(reg.into()) & 0xffff_ffff) as u32).unwrap() } 101 } 102 103 fn mask_all_lvt(&mut self) { 104 // self.set_lvt(LVT::new(LVTRegister::CMCI, LVT::MASKED).unwrap()); 105 let cpuid = raw_cpuid::CpuId::new(); 106 // cpuid.get_performance_monitoring_info(); 107 self.set_lvt(LVT::new(LVTRegister::Timer, LVT::MASKED).unwrap()); 108 109 if cpuid.get_thermal_power_info().is_some() { 110 self.set_lvt(LVT::new(LVTRegister::Thermal, LVT::MASKED).unwrap()); 111 } 112 113 if cpuid.get_performance_monitoring_info().is_some() { 114 self.set_lvt(LVT::new(LVTRegister::PerformanceMonitor, LVT::MASKED).unwrap()); 115 } 116 117 self.set_lvt(LVT::new(LVTRegister::LINT0, LVT::MASKED).unwrap()); 118 self.set_lvt(LVT::new(LVTRegister::LINT1, LVT::MASKED).unwrap()); 119 120 self.set_lvt(LVT::new(LVTRegister::ErrorReg, LVT::MASKED).unwrap()); 121 } 122 123 fn write_icr(&self, icr: x86::apic::Icr) { 124 unsafe { wrmsr(0x830, ((icr.upper() as u64) << 32) | icr.lower() as u64) }; 125 } 126 } 127