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