170a4e555SLoGin use x86::msr::{ 270a4e555SLoGin rdmsr, wrmsr, IA32_APIC_BASE, IA32_X2APIC_APICID, IA32_X2APIC_EOI, IA32_X2APIC_SIVR, 370a4e555SLoGin IA32_X2APIC_VERSION, 470a4e555SLoGin }; 570a4e555SLoGin 670a4e555SLoGin use crate::{kdebug, kinfo}; 770a4e555SLoGin 8*e2841179SLoGin use super::{hw_irq::ApicId, LVTRegister, LocalAPIC, LVT}; 970a4e555SLoGin 1070a4e555SLoGin #[derive(Debug)] 1170a4e555SLoGin pub struct X2Apic; 1270a4e555SLoGin 1370a4e555SLoGin impl LocalAPIC for X2Apic { 1470a4e555SLoGin /// @brief 判断处理器是否支持x2APIC 1570a4e555SLoGin fn support() -> bool { 1670a4e555SLoGin return x86::cpuid::CpuId::new() 1770a4e555SLoGin .get_feature_info() 1870a4e555SLoGin .expect("Get cpu feature info failed.") 1970a4e555SLoGin .has_x2apic(); 2070a4e555SLoGin } 2170a4e555SLoGin /// @return true -> the function works 2270a4e555SLoGin fn init_current_cpu(&mut self) -> bool { 2370a4e555SLoGin unsafe { 2470a4e555SLoGin // 设置 x2APIC 使能位 2570a4e555SLoGin wrmsr( 2670a4e555SLoGin IA32_APIC_BASE.into(), 2770a4e555SLoGin rdmsr(IA32_APIC_BASE.into()) | 1 << 10, 2870a4e555SLoGin ); 2970a4e555SLoGin 3070a4e555SLoGin assert!( 3170a4e555SLoGin (rdmsr(IA32_APIC_BASE.into()) & 0xc00) == 0xc00, 3270a4e555SLoGin "x2APIC enable failed." 3370a4e555SLoGin ); 3470a4e555SLoGin 3570a4e555SLoGin // 设置Spurious-Interrupt Vector Register 3670a4e555SLoGin { 3770a4e555SLoGin let val = if self.support_eoi_broadcast_suppression() { 3870a4e555SLoGin (1 << 12) | (1 << 8) 3970a4e555SLoGin } else { 4070a4e555SLoGin 1 << 8 4170a4e555SLoGin }; 4270a4e555SLoGin 4370a4e555SLoGin wrmsr(IA32_X2APIC_SIVR.into(), val); 4470a4e555SLoGin 4570a4e555SLoGin assert!( 4670a4e555SLoGin (rdmsr(IA32_X2APIC_SIVR.into()) & 0x100) == 0x100, 4770a4e555SLoGin "x2APIC software enable failed." 4870a4e555SLoGin ); 4970a4e555SLoGin kinfo!("x2APIC software enabled."); 5070a4e555SLoGin 5170a4e555SLoGin if self.support_eoi_broadcast_suppression() { 5270a4e555SLoGin assert!( 5370a4e555SLoGin (rdmsr(IA32_X2APIC_SIVR.into()) & 0x1000) == 0x1000, 5470a4e555SLoGin "x2APIC EOI broadcast suppression enable failed." 5570a4e555SLoGin ); 5670a4e555SLoGin kinfo!("x2APIC EOI broadcast suppression enabled."); 5770a4e555SLoGin } 5870a4e555SLoGin } 5970a4e555SLoGin kdebug!("x2apic: to mask all lvt"); 6070a4e555SLoGin self.mask_all_lvt(); 6170a4e555SLoGin kdebug!("x2apic: all lvt masked"); 6270a4e555SLoGin } 6370a4e555SLoGin true 6470a4e555SLoGin } 6570a4e555SLoGin 6670a4e555SLoGin /// 发送 EOI (End Of Interrupt) 6770a4e555SLoGin fn send_eoi(&self) { 6870a4e555SLoGin unsafe { 6970a4e555SLoGin wrmsr(IA32_X2APIC_EOI.into(), 0); 7070a4e555SLoGin } 7170a4e555SLoGin } 7270a4e555SLoGin 7370a4e555SLoGin /// 获取 x2APIC 版本 7470a4e555SLoGin fn version(&self) -> u8 { 7570a4e555SLoGin unsafe { (rdmsr(IA32_X2APIC_VERSION.into()) & 0xff) as u8 } 7670a4e555SLoGin } 7770a4e555SLoGin 7870a4e555SLoGin fn support_eoi_broadcast_suppression(&self) -> bool { 7970a4e555SLoGin unsafe { ((rdmsr(IA32_X2APIC_VERSION.into()) >> 24) & 1) == 1 } 8070a4e555SLoGin } 8170a4e555SLoGin 8270a4e555SLoGin fn max_lvt_entry(&self) -> u8 { 8370a4e555SLoGin unsafe { ((rdmsr(IA32_X2APIC_VERSION.into()) >> 16) & 0xff) as u8 + 1 } 8470a4e555SLoGin } 8570a4e555SLoGin 8670a4e555SLoGin /// 获取 x2APIC 的 APIC ID 87*e2841179SLoGin fn id(&self) -> ApicId { 88*e2841179SLoGin unsafe { ApicId::new(rdmsr(IA32_X2APIC_APICID.into()) as u32) } 8970a4e555SLoGin } 9070a4e555SLoGin 9170a4e555SLoGin /// 设置 Local Vector Table (LVT) 寄存器 9270a4e555SLoGin fn set_lvt(&mut self, lvt: LVT) { 9370a4e555SLoGin unsafe { 9470a4e555SLoGin wrmsr(lvt.register().into(), lvt.data as u64); 9570a4e555SLoGin } 9670a4e555SLoGin } 9770a4e555SLoGin 9870a4e555SLoGin fn read_lvt(&self, reg: LVTRegister) -> LVT { 9970a4e555SLoGin unsafe { LVT::new(reg, (rdmsr(reg.into()) & 0xffff_ffff) as u32).unwrap() } 10070a4e555SLoGin } 10170a4e555SLoGin 10270a4e555SLoGin fn mask_all_lvt(&mut self) { 10370a4e555SLoGin // self.set_lvt(LVT::new(LVTRegister::CMCI, LVT::MASKED).unwrap()); 10470a4e555SLoGin let cpuid = raw_cpuid::CpuId::new(); 10570a4e555SLoGin // cpuid.get_performance_monitoring_info(); 10670a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::Timer, LVT::MASKED).unwrap()); 10770a4e555SLoGin 10870a4e555SLoGin if cpuid.get_thermal_power_info().is_some() { 10970a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::Thermal, LVT::MASKED).unwrap()); 11070a4e555SLoGin } 11170a4e555SLoGin 11270a4e555SLoGin if cpuid.get_performance_monitoring_info().is_some() { 11370a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::PerformanceMonitor, LVT::MASKED).unwrap()); 11470a4e555SLoGin } 11570a4e555SLoGin 11670a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::LINT0, LVT::MASKED).unwrap()); 11770a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::LINT1, LVT::MASKED).unwrap()); 11870a4e555SLoGin 11970a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::ErrorReg, LVT::MASKED).unwrap()); 12070a4e555SLoGin } 12170a4e555SLoGin 12270a4e555SLoGin fn write_icr(&self, icr: x86::apic::Icr) { 12370a4e555SLoGin unsafe { wrmsr(0x830, ((icr.upper() as u64) << 32) | icr.lower() as u64) }; 12470a4e555SLoGin } 12570a4e555SLoGin } 126