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