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