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::{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( 26 IA32_APIC_BASE.into(), 27 rdmsr(IA32_APIC_BASE.into()) | 1 << 10, 28 ); 29 30 assert!( 31 (rdmsr(IA32_APIC_BASE.into()) & 0xc00) == 0xc00, 32 "x2APIC enable failed." 33 ); 34 35 // 设置Spurious-Interrupt Vector Register 36 { 37 let val = if self.support_eoi_broadcast_suppression() { 38 (1 << 12) | (1 << 8) 39 } else { 40 1 << 8 41 }; 42 43 wrmsr(IA32_X2APIC_SIVR.into(), val); 44 45 assert!( 46 (rdmsr(IA32_X2APIC_SIVR.into()) & 0x100) == 0x100, 47 "x2APIC software enable failed." 48 ); 49 kinfo!("x2APIC software enabled."); 50 51 if self.support_eoi_broadcast_suppression() { 52 assert!( 53 (rdmsr(IA32_X2APIC_SIVR.into()) & 0x1000) == 0x1000, 54 "x2APIC EOI broadcast suppression enable failed." 55 ); 56 kinfo!("x2APIC EOI broadcast suppression enabled."); 57 } 58 } 59 kdebug!("x2apic: to mask all lvt"); 60 self.mask_all_lvt(); 61 kdebug!("x2apic: all lvt masked"); 62 } 63 true 64 } 65 66 /// 发送 EOI (End Of Interrupt) 67 fn send_eoi(&self) { 68 unsafe { 69 wrmsr(IA32_X2APIC_EOI.into(), 0); 70 } 71 } 72 73 /// 获取 x2APIC 版本 74 fn version(&self) -> u8 { 75 unsafe { (rdmsr(IA32_X2APIC_VERSION.into()) & 0xff) as u8 } 76 } 77 78 fn support_eoi_broadcast_suppression(&self) -> bool { 79 unsafe { ((rdmsr(IA32_X2APIC_VERSION.into()) >> 24) & 1) == 1 } 80 } 81 82 fn max_lvt_entry(&self) -> u8 { 83 unsafe { ((rdmsr(IA32_X2APIC_VERSION.into()) >> 16) & 0xff) as u8 + 1 } 84 } 85 86 /// 获取 x2APIC 的 APIC ID 87 fn id(&self) -> u32 { 88 unsafe { rdmsr(IA32_X2APIC_APICID.into()) as u32 } 89 } 90 91 /// 设置 Local Vector Table (LVT) 寄存器 92 fn set_lvt(&mut self, lvt: LVT) { 93 unsafe { 94 wrmsr(lvt.register().into(), lvt.data as u64); 95 } 96 } 97 98 fn read_lvt(&self, reg: LVTRegister) -> LVT { 99 unsafe { LVT::new(reg, (rdmsr(reg.into()) & 0xffff_ffff) as u32).unwrap() } 100 } 101 102 fn mask_all_lvt(&mut self) { 103 // self.set_lvt(LVT::new(LVTRegister::CMCI, LVT::MASKED).unwrap()); 104 let cpuid = raw_cpuid::CpuId::new(); 105 // cpuid.get_performance_monitoring_info(); 106 self.set_lvt(LVT::new(LVTRegister::Timer, LVT::MASKED).unwrap()); 107 108 if cpuid.get_thermal_power_info().is_some() { 109 self.set_lvt(LVT::new(LVTRegister::Thermal, LVT::MASKED).unwrap()); 110 } 111 112 if cpuid.get_performance_monitoring_info().is_some() { 113 self.set_lvt(LVT::new(LVTRegister::PerformanceMonitor, LVT::MASKED).unwrap()); 114 } 115 116 self.set_lvt(LVT::new(LVTRegister::LINT0, LVT::MASKED).unwrap()); 117 self.set_lvt(LVT::new(LVTRegister::LINT1, LVT::MASKED).unwrap()); 118 119 self.set_lvt(LVT::new(LVTRegister::ErrorReg, LVT::MASKED).unwrap()); 120 } 121 122 fn write_icr(&self, icr: x86::apic::Icr) { 123 unsafe { wrmsr(0x830, ((icr.upper() as u64) << 32) | icr.lower() as u64) }; 124 } 125 } 126