1f0c87a89SGnoCiYeH use core::sync::atomic::{fence, Ordering}; 2f0c87a89SGnoCiYeH 3*2eab6dd7S曾俊 use log::info; 470a4e555SLoGin use x86::msr::{ 570a4e555SLoGin rdmsr, wrmsr, IA32_APIC_BASE, IA32_X2APIC_APICID, IA32_X2APIC_EOI, IA32_X2APIC_SIVR, 670a4e555SLoGin IA32_X2APIC_VERSION, 770a4e555SLoGin }; 870a4e555SLoGin 9e2841179SLoGin use super::{hw_irq::ApicId, LVTRegister, LocalAPIC, LVT}; 1070a4e555SLoGin 1170a4e555SLoGin #[derive(Debug)] 1270a4e555SLoGin pub struct X2Apic; 1370a4e555SLoGin 1470a4e555SLoGin impl LocalAPIC for X2Apic { 1570a4e555SLoGin /// @brief 判断处理器是否支持x2APIC support() -> bool1670a4e555SLoGin fn support() -> bool { 1770a4e555SLoGin return x86::cpuid::CpuId::new() 1870a4e555SLoGin .get_feature_info() 1970a4e555SLoGin .expect("Get cpu feature info failed.") 2070a4e555SLoGin .has_x2apic(); 2170a4e555SLoGin } 2270a4e555SLoGin /// @return true -> the function works init_current_cpu(&mut self) -> bool2370a4e555SLoGin fn init_current_cpu(&mut self) -> bool { 2470a4e555SLoGin unsafe { 2570a4e555SLoGin // 设置 x2APIC 使能位 26b5b571e0SLoGin wrmsr(IA32_APIC_BASE, rdmsr(IA32_APIC_BASE) | 1 << 10); 2770a4e555SLoGin 2870a4e555SLoGin assert!( 29b5b571e0SLoGin (rdmsr(IA32_APIC_BASE) & 0xc00) == 0xc00, 3070a4e555SLoGin "x2APIC enable failed." 3170a4e555SLoGin ); 3270a4e555SLoGin 3370a4e555SLoGin // 设置Spurious-Interrupt Vector Register 3470a4e555SLoGin { 3570a4e555SLoGin let val = if self.support_eoi_broadcast_suppression() { 3670a4e555SLoGin (1 << 12) | (1 << 8) 3770a4e555SLoGin } else { 3870a4e555SLoGin 1 << 8 3970a4e555SLoGin }; 4070a4e555SLoGin 41b5b571e0SLoGin wrmsr(IA32_X2APIC_SIVR, val); 4270a4e555SLoGin 4370a4e555SLoGin assert!( 44b5b571e0SLoGin (rdmsr(IA32_X2APIC_SIVR) & 0x100) == 0x100, 4570a4e555SLoGin "x2APIC software enable failed." 4670a4e555SLoGin ); 47*2eab6dd7S曾俊 info!("x2APIC software enabled."); 4870a4e555SLoGin 4970a4e555SLoGin if self.support_eoi_broadcast_suppression() { 5070a4e555SLoGin assert!( 51b5b571e0SLoGin (rdmsr(IA32_X2APIC_SIVR) & 0x1000) == 0x1000, 5270a4e555SLoGin "x2APIC EOI broadcast suppression enable failed." 5370a4e555SLoGin ); 54*2eab6dd7S曾俊 info!("x2APIC EOI broadcast suppression enabled."); 5570a4e555SLoGin } 5670a4e555SLoGin } 57*2eab6dd7S曾俊 // debug!("x2apic: to mask all lvt"); 5870a4e555SLoGin self.mask_all_lvt(); 59*2eab6dd7S曾俊 // debug!("x2apic: all lvt masked"); 6070a4e555SLoGin } 6170a4e555SLoGin true 6270a4e555SLoGin } 6370a4e555SLoGin 6470a4e555SLoGin /// 发送 EOI (End Of Interrupt) send_eoi(&self)6570a4e555SLoGin fn send_eoi(&self) { 66f0c87a89SGnoCiYeH fence(Ordering::SeqCst); 6770a4e555SLoGin unsafe { 68b5b571e0SLoGin wrmsr(IA32_X2APIC_EOI, 0); 6970a4e555SLoGin } 70f0c87a89SGnoCiYeH 71f0c87a89SGnoCiYeH fence(Ordering::SeqCst); 7270a4e555SLoGin } 7370a4e555SLoGin 7470a4e555SLoGin /// 获取 x2APIC 版本 version(&self) -> u87570a4e555SLoGin fn version(&self) -> u8 { 76b5b571e0SLoGin unsafe { (rdmsr(IA32_X2APIC_VERSION) & 0xff) as u8 } 7770a4e555SLoGin } 7870a4e555SLoGin support_eoi_broadcast_suppression(&self) -> bool7970a4e555SLoGin fn support_eoi_broadcast_suppression(&self) -> bool { 80b5b571e0SLoGin unsafe { ((rdmsr(IA32_X2APIC_VERSION) >> 24) & 1) == 1 } 8170a4e555SLoGin } 8270a4e555SLoGin max_lvt_entry(&self) -> u88370a4e555SLoGin fn max_lvt_entry(&self) -> u8 { 84b5b571e0SLoGin unsafe { ((rdmsr(IA32_X2APIC_VERSION) >> 16) & 0xff) as u8 + 1 } 8570a4e555SLoGin } 8670a4e555SLoGin 8770a4e555SLoGin /// 获取 x2APIC 的 APIC ID id(&self) -> ApicId88e2841179SLoGin fn id(&self) -> ApicId { 89b5b571e0SLoGin unsafe { ApicId::new(rdmsr(IA32_X2APIC_APICID) as u32) } 9070a4e555SLoGin } 9170a4e555SLoGin 9270a4e555SLoGin /// 设置 Local Vector Table (LVT) 寄存器 set_lvt(&mut self, lvt: LVT)9370a4e555SLoGin fn set_lvt(&mut self, lvt: LVT) { 9470a4e555SLoGin unsafe { 9570a4e555SLoGin wrmsr(lvt.register().into(), lvt.data as u64); 9670a4e555SLoGin } 9770a4e555SLoGin } 9870a4e555SLoGin read_lvt(&self, reg: LVTRegister) -> LVT9970a4e555SLoGin fn read_lvt(&self, reg: LVTRegister) -> LVT { 10070a4e555SLoGin unsafe { LVT::new(reg, (rdmsr(reg.into()) & 0xffff_ffff) as u32).unwrap() } 10170a4e555SLoGin } 10270a4e555SLoGin mask_all_lvt(&mut self)10370a4e555SLoGin fn mask_all_lvt(&mut self) { 10470a4e555SLoGin // self.set_lvt(LVT::new(LVTRegister::CMCI, LVT::MASKED).unwrap()); 10570a4e555SLoGin let cpuid = raw_cpuid::CpuId::new(); 10670a4e555SLoGin // cpuid.get_performance_monitoring_info(); 10770a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::Timer, LVT::MASKED).unwrap()); 10870a4e555SLoGin 10970a4e555SLoGin if cpuid.get_thermal_power_info().is_some() { 11070a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::Thermal, LVT::MASKED).unwrap()); 11170a4e555SLoGin } 11270a4e555SLoGin 11370a4e555SLoGin if cpuid.get_performance_monitoring_info().is_some() { 11470a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::PerformanceMonitor, LVT::MASKED).unwrap()); 11570a4e555SLoGin } 11670a4e555SLoGin 11770a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::LINT0, LVT::MASKED).unwrap()); 11870a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::LINT1, LVT::MASKED).unwrap()); 11970a4e555SLoGin 12070a4e555SLoGin self.set_lvt(LVT::new(LVTRegister::ErrorReg, LVT::MASKED).unwrap()); 12170a4e555SLoGin } 12270a4e555SLoGin write_icr(&self, icr: x86::apic::Icr)12370a4e555SLoGin fn write_icr(&self, icr: x86::apic::Icr) { 12470a4e555SLoGin unsafe { wrmsr(0x830, ((icr.upper() as u64) << 32) | icr.lower() as u64) }; 12570a4e555SLoGin } 12670a4e555SLoGin } 127