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