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 8e2841179SLoGin 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 使能位 25*b5b571e0SLoGin wrmsr(IA32_APIC_BASE, rdmsr(IA32_APIC_BASE) | 1 << 10); 2670a4e555SLoGin 2770a4e555SLoGin assert!( 28*b5b571e0SLoGin (rdmsr(IA32_APIC_BASE) & 0xc00) == 0xc00, 2970a4e555SLoGin "x2APIC enable failed." 3070a4e555SLoGin ); 3170a4e555SLoGin 3270a4e555SLoGin // 设置Spurious-Interrupt Vector Register 3370a4e555SLoGin { 3470a4e555SLoGin let val = if self.support_eoi_broadcast_suppression() { 3570a4e555SLoGin (1 << 12) | (1 << 8) 3670a4e555SLoGin } else { 3770a4e555SLoGin 1 << 8 3870a4e555SLoGin }; 3970a4e555SLoGin 40*b5b571e0SLoGin wrmsr(IA32_X2APIC_SIVR, val); 4170a4e555SLoGin 4270a4e555SLoGin assert!( 43*b5b571e0SLoGin (rdmsr(IA32_X2APIC_SIVR) & 0x100) == 0x100, 4470a4e555SLoGin "x2APIC software enable failed." 4570a4e555SLoGin ); 4670a4e555SLoGin kinfo!("x2APIC software enabled."); 4770a4e555SLoGin 4870a4e555SLoGin if self.support_eoi_broadcast_suppression() { 4970a4e555SLoGin assert!( 50*b5b571e0SLoGin (rdmsr(IA32_X2APIC_SIVR) & 0x1000) == 0x1000, 5170a4e555SLoGin "x2APIC EOI broadcast suppression enable failed." 5270a4e555SLoGin ); 5370a4e555SLoGin kinfo!("x2APIC EOI broadcast suppression enabled."); 5470a4e555SLoGin } 5570a4e555SLoGin } 5670a4e555SLoGin kdebug!("x2apic: to mask all lvt"); 5770a4e555SLoGin self.mask_all_lvt(); 5870a4e555SLoGin kdebug!("x2apic: all lvt masked"); 5970a4e555SLoGin } 6070a4e555SLoGin true 6170a4e555SLoGin } 6270a4e555SLoGin 6370a4e555SLoGin /// 发送 EOI (End Of Interrupt) 6470a4e555SLoGin fn send_eoi(&self) { 6570a4e555SLoGin unsafe { 66*b5b571e0SLoGin wrmsr(IA32_X2APIC_EOI, 0); 6770a4e555SLoGin } 6870a4e555SLoGin } 6970a4e555SLoGin 7070a4e555SLoGin /// 获取 x2APIC 版本 7170a4e555SLoGin fn version(&self) -> u8 { 72*b5b571e0SLoGin unsafe { (rdmsr(IA32_X2APIC_VERSION) & 0xff) as u8 } 7370a4e555SLoGin } 7470a4e555SLoGin 7570a4e555SLoGin fn support_eoi_broadcast_suppression(&self) -> bool { 76*b5b571e0SLoGin unsafe { ((rdmsr(IA32_X2APIC_VERSION) >> 24) & 1) == 1 } 7770a4e555SLoGin } 7870a4e555SLoGin 7970a4e555SLoGin fn max_lvt_entry(&self) -> u8 { 80*b5b571e0SLoGin unsafe { ((rdmsr(IA32_X2APIC_VERSION) >> 16) & 0xff) as u8 + 1 } 8170a4e555SLoGin } 8270a4e555SLoGin 8370a4e555SLoGin /// 获取 x2APIC 的 APIC ID 84e2841179SLoGin fn id(&self) -> ApicId { 85*b5b571e0SLoGin unsafe { ApicId::new(rdmsr(IA32_X2APIC_APICID) as u32) } 8670a4e555SLoGin } 8770a4e555SLoGin 8870a4e555SLoGin /// 设置 Local Vector Table (LVT) 寄存器 8970a4e555SLoGin fn set_lvt(&mut self, lvt: LVT) { 9070a4e555SLoGin unsafe { 9170a4e555SLoGin wrmsr(lvt.register().into(), lvt.data as u64); 9270a4e555SLoGin } 9370a4e555SLoGin } 9470a4e555SLoGin 9570a4e555SLoGin fn read_lvt(&self, reg: LVTRegister) -> LVT { 9670a4e555SLoGin unsafe { LVT::new(reg, (rdmsr(reg.into()) & 0xffff_ffff) as u32).unwrap() } 9770a4e555SLoGin } 9870a4e555SLoGin 9970a4e555SLoGin fn mask_all_lvt(&mut self) { 10070a4e555SLoGin // self.set_lvt(LVT::new(LVTRegister::CMCI, LVT::MASKED).unwrap()); 10170a4e555SLoGin let cpuid = raw_cpuid::CpuId::new(); 10270a4e555SLoGin // cpuid.get_performance_monitoring_info(); 10370a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::Timer, LVT::MASKED).unwrap()); 10470a4e555SLoGin 10570a4e555SLoGin if cpuid.get_thermal_power_info().is_some() { 10670a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::Thermal, LVT::MASKED).unwrap()); 10770a4e555SLoGin } 10870a4e555SLoGin 10970a4e555SLoGin if cpuid.get_performance_monitoring_info().is_some() { 11070a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::PerformanceMonitor, LVT::MASKED).unwrap()); 11170a4e555SLoGin } 11270a4e555SLoGin 11370a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::LINT0, LVT::MASKED).unwrap()); 11470a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::LINT1, LVT::MASKED).unwrap()); 11570a4e555SLoGin 11670a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::ErrorReg, LVT::MASKED).unwrap()); 11770a4e555SLoGin } 11870a4e555SLoGin 11970a4e555SLoGin fn write_icr(&self, icr: x86::apic::Icr) { 12070a4e555SLoGin unsafe { wrmsr(0x830, ((icr.upper() as u64) << 32) | icr.lower() as u64) }; 12170a4e555SLoGin } 12270a4e555SLoGin } 123