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