xref: /DragonOS/kernel/src/arch/x86_64/driver/apic/x2apic.rs (revision 70a4e5550a9fb49b537092287c3ddc36448c5b78)
1*70a4e555SLoGin use x86::msr::{
2*70a4e555SLoGin     rdmsr, wrmsr, IA32_APIC_BASE, IA32_X2APIC_APICID, IA32_X2APIC_EOI, IA32_X2APIC_SIVR,
3*70a4e555SLoGin     IA32_X2APIC_VERSION,
4*70a4e555SLoGin };
5*70a4e555SLoGin 
6*70a4e555SLoGin use crate::{kdebug, kinfo};
7*70a4e555SLoGin 
8*70a4e555SLoGin use super::{LVTRegister, LocalAPIC, LVT};
9*70a4e555SLoGin 
10*70a4e555SLoGin #[derive(Debug)]
11*70a4e555SLoGin pub struct X2Apic;
12*70a4e555SLoGin 
13*70a4e555SLoGin impl LocalAPIC for X2Apic {
14*70a4e555SLoGin     /// @brief 判断处理器是否支持x2APIC
15*70a4e555SLoGin     fn support() -> bool {
16*70a4e555SLoGin         return x86::cpuid::CpuId::new()
17*70a4e555SLoGin             .get_feature_info()
18*70a4e555SLoGin             .expect("Get cpu feature info failed.")
19*70a4e555SLoGin             .has_x2apic();
20*70a4e555SLoGin     }
21*70a4e555SLoGin     /// @return true -> the function works
22*70a4e555SLoGin     fn init_current_cpu(&mut self) -> bool {
23*70a4e555SLoGin         unsafe {
24*70a4e555SLoGin             // 设置 x2APIC 使能位
25*70a4e555SLoGin             wrmsr(
26*70a4e555SLoGin                 IA32_APIC_BASE.into(),
27*70a4e555SLoGin                 rdmsr(IA32_APIC_BASE.into()) | 1 << 10,
28*70a4e555SLoGin             );
29*70a4e555SLoGin 
30*70a4e555SLoGin             assert!(
31*70a4e555SLoGin                 (rdmsr(IA32_APIC_BASE.into()) & 0xc00) == 0xc00,
32*70a4e555SLoGin                 "x2APIC enable failed."
33*70a4e555SLoGin             );
34*70a4e555SLoGin 
35*70a4e555SLoGin             // 设置Spurious-Interrupt Vector Register
36*70a4e555SLoGin             {
37*70a4e555SLoGin                 let val = if self.support_eoi_broadcast_suppression() {
38*70a4e555SLoGin                     (1 << 12) | (1 << 8)
39*70a4e555SLoGin                 } else {
40*70a4e555SLoGin                     1 << 8
41*70a4e555SLoGin                 };
42*70a4e555SLoGin 
43*70a4e555SLoGin                 wrmsr(IA32_X2APIC_SIVR.into(), val);
44*70a4e555SLoGin 
45*70a4e555SLoGin                 assert!(
46*70a4e555SLoGin                     (rdmsr(IA32_X2APIC_SIVR.into()) & 0x100) == 0x100,
47*70a4e555SLoGin                     "x2APIC software enable failed."
48*70a4e555SLoGin                 );
49*70a4e555SLoGin                 kinfo!("x2APIC software enabled.");
50*70a4e555SLoGin 
51*70a4e555SLoGin                 if self.support_eoi_broadcast_suppression() {
52*70a4e555SLoGin                     assert!(
53*70a4e555SLoGin                         (rdmsr(IA32_X2APIC_SIVR.into()) & 0x1000) == 0x1000,
54*70a4e555SLoGin                         "x2APIC EOI broadcast suppression enable failed."
55*70a4e555SLoGin                     );
56*70a4e555SLoGin                     kinfo!("x2APIC EOI broadcast suppression enabled.");
57*70a4e555SLoGin                 }
58*70a4e555SLoGin             }
59*70a4e555SLoGin             kdebug!("x2apic: to mask all lvt");
60*70a4e555SLoGin             self.mask_all_lvt();
61*70a4e555SLoGin             kdebug!("x2apic: all lvt masked");
62*70a4e555SLoGin         }
63*70a4e555SLoGin         true
64*70a4e555SLoGin     }
65*70a4e555SLoGin 
66*70a4e555SLoGin     /// 发送 EOI (End Of Interrupt)
67*70a4e555SLoGin     fn send_eoi(&self) {
68*70a4e555SLoGin         unsafe {
69*70a4e555SLoGin             wrmsr(IA32_X2APIC_EOI.into(), 0);
70*70a4e555SLoGin         }
71*70a4e555SLoGin     }
72*70a4e555SLoGin 
73*70a4e555SLoGin     /// 获取 x2APIC 版本
74*70a4e555SLoGin     fn version(&self) -> u8 {
75*70a4e555SLoGin         unsafe { (rdmsr(IA32_X2APIC_VERSION.into()) & 0xff) as u8 }
76*70a4e555SLoGin     }
77*70a4e555SLoGin 
78*70a4e555SLoGin     fn support_eoi_broadcast_suppression(&self) -> bool {
79*70a4e555SLoGin         unsafe { ((rdmsr(IA32_X2APIC_VERSION.into()) >> 24) & 1) == 1 }
80*70a4e555SLoGin     }
81*70a4e555SLoGin 
82*70a4e555SLoGin     fn max_lvt_entry(&self) -> u8 {
83*70a4e555SLoGin         unsafe { ((rdmsr(IA32_X2APIC_VERSION.into()) >> 16) & 0xff) as u8 + 1 }
84*70a4e555SLoGin     }
85*70a4e555SLoGin 
86*70a4e555SLoGin     /// 获取 x2APIC 的 APIC ID
87*70a4e555SLoGin     fn id(&self) -> u32 {
88*70a4e555SLoGin         unsafe { rdmsr(IA32_X2APIC_APICID.into()) as u32 }
89*70a4e555SLoGin     }
90*70a4e555SLoGin 
91*70a4e555SLoGin     /// 设置 Local Vector Table (LVT) 寄存器
92*70a4e555SLoGin     fn set_lvt(&mut self, lvt: LVT) {
93*70a4e555SLoGin         unsafe {
94*70a4e555SLoGin             wrmsr(lvt.register().into(), lvt.data as u64);
95*70a4e555SLoGin         }
96*70a4e555SLoGin     }
97*70a4e555SLoGin 
98*70a4e555SLoGin     fn read_lvt(&self, reg: LVTRegister) -> LVT {
99*70a4e555SLoGin         unsafe { LVT::new(reg, (rdmsr(reg.into()) & 0xffff_ffff) as u32).unwrap() }
100*70a4e555SLoGin     }
101*70a4e555SLoGin 
102*70a4e555SLoGin     fn mask_all_lvt(&mut self) {
103*70a4e555SLoGin         // self.set_lvt(LVT::new(LVTRegister::CMCI, LVT::MASKED).unwrap());
104*70a4e555SLoGin         let cpuid = raw_cpuid::CpuId::new();
105*70a4e555SLoGin         // cpuid.get_performance_monitoring_info();
106*70a4e555SLoGin         self.set_lvt(LVT::new(LVTRegister::Timer, LVT::MASKED).unwrap());
107*70a4e555SLoGin 
108*70a4e555SLoGin         if cpuid.get_thermal_power_info().is_some() {
109*70a4e555SLoGin             self.set_lvt(LVT::new(LVTRegister::Thermal, LVT::MASKED).unwrap());
110*70a4e555SLoGin         }
111*70a4e555SLoGin 
112*70a4e555SLoGin         if cpuid.get_performance_monitoring_info().is_some() {
113*70a4e555SLoGin             self.set_lvt(LVT::new(LVTRegister::PerformanceMonitor, LVT::MASKED).unwrap());
114*70a4e555SLoGin         }
115*70a4e555SLoGin 
116*70a4e555SLoGin         self.set_lvt(LVT::new(LVTRegister::LINT0, LVT::MASKED).unwrap());
117*70a4e555SLoGin         self.set_lvt(LVT::new(LVTRegister::LINT1, LVT::MASKED).unwrap());
118*70a4e555SLoGin 
119*70a4e555SLoGin         self.set_lvt(LVT::new(LVTRegister::ErrorReg, LVT::MASKED).unwrap());
120*70a4e555SLoGin     }
121*70a4e555SLoGin 
122*70a4e555SLoGin     fn write_icr(&self, icr: x86::apic::Icr) {
123*70a4e555SLoGin         unsafe { wrmsr(0x830, ((icr.upper() as u64) << 32) | icr.lower() as u64) };
124*70a4e555SLoGin     }
125*70a4e555SLoGin }
126