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