xref: /DragonOS/kernel/src/arch/x86_64/driver/apic/x2apic.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
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