xref: /DragonOS/kernel/src/arch/x86_64/driver/apic/xapic.rs (revision 7b32f5080f42bcbf7d2421013f3ea53c776a063c)
1 use core::{
2     cell::RefCell,
3     hint::spin_loop,
4     ptr::{read_volatile, write_volatile},
5 };
6 
7 use crate::{
8     kdebug, kerror, kinfo,
9     mm::{
10         mmio_buddy::{mmio_pool, MMIOSpaceGuard},
11         percpu::PerCpu,
12         PhysAddr, VirtAddr,
13     },
14     smp::core::smp_get_processor_id,
15 };
16 
17 use super::{LVTRegister, LocalAPIC, LVT};
18 
19 /// per-cpu的xAPIC的MMIO空间起始地址
20 static mut XAPIC_INSTANCES: [RefCell<Option<XApic>>; PerCpu::MAX_CPU_NUM] =
21     [const { RefCell::new(None) }; PerCpu::MAX_CPU_NUM];
22 
23 #[inline(always)]
24 pub(super) fn current_xapic_instance() -> &'static RefCell<Option<XApic>> {
25     unsafe { &XAPIC_INSTANCES.as_ref()[smp_get_processor_id() as usize] }
26 }
27 
28 /// TODO:统一变量
29 /// @brief local APIC 寄存器地址偏移量
30 #[derive(Debug)]
31 #[allow(dead_code)]
32 #[allow(non_camel_case_types)]
33 #[repr(u32)]
34 pub enum XApicOffset {
35     // 定义各个寄存器的地址偏移量
36     LOCAL_APIC_OFFSET_Local_APIC_ID = 0x20,
37     LOCAL_APIC_OFFSET_Local_APIC_Version = 0x30,
38     LOCAL_APIC_OFFSET_Local_APIC_TPR = 0x80,
39     LOCAL_APIC_OFFSET_Local_APIC_APR = 0x90,
40     LOCAL_APIC_OFFSET_Local_APIC_PPR = 0xa0,
41     LOCAL_APIC_OFFSET_Local_APIC_EOI = 0xb0,
42     LOCAL_APIC_OFFSET_Local_APIC_RRD = 0xc0,
43     LOCAL_APIC_OFFSET_Local_APIC_LDR = 0xd0,
44     LOCAL_APIC_OFFSET_Local_APIC_DFR = 0xe0,
45     LOCAL_APIC_OFFSET_Local_APIC_SVR = 0xf0,
46 
47     LOCAL_APIC_OFFSET_Local_APIC_ISR_31_0 = 0x100, // In-Service Register
48     LOCAL_APIC_OFFSET_Local_APIC_ISR_63_32 = 0x110,
49     LOCAL_APIC_OFFSET_Local_APIC_ISR_95_64 = 0x120,
50     LOCAL_APIC_OFFSET_Local_APIC_ISR_127_96 = 0x130,
51     LOCAL_APIC_OFFSET_Local_APIC_ISR_159_128 = 0x140,
52     LOCAL_APIC_OFFSET_Local_APIC_ISR_191_160 = 0x150,
53     LOCAL_APIC_OFFSET_Local_APIC_ISR_223_192 = 0x160,
54     LOCAL_APIC_OFFSET_Local_APIC_ISR_255_224 = 0x170,
55 
56     LOCAL_APIC_OFFSET_Local_APIC_TMR_31_0 = 0x180, // Trigger Mode Register
57     LOCAL_APIC_OFFSET_Local_APIC_TMR_63_32 = 0x190,
58     LOCAL_APIC_OFFSET_Local_APIC_TMR_95_64 = 0x1a0,
59     LOCAL_APIC_OFFSET_Local_APIC_TMR_127_96 = 0x1b0,
60     LOCAL_APIC_OFFSET_Local_APIC_TMR_159_128 = 0x1c0,
61     LOCAL_APIC_OFFSET_Local_APIC_TMR_191_160 = 0x1d0,
62     LOCAL_APIC_OFFSET_Local_APIC_TMR_223_192 = 0x1e0,
63     LOCAL_APIC_OFFSET_Local_APIC_TMR_255_224 = 0x1f0,
64 
65     LOCAL_APIC_OFFSET_Local_APIC_IRR_31_0 = 0x200, // Interrupt Request Register
66     LOCAL_APIC_OFFSET_Local_APIC_IRR_63_32 = 0x210,
67     LOCAL_APIC_OFFSET_Local_APIC_IRR_95_64 = 0x220,
68     LOCAL_APIC_OFFSET_Local_APIC_IRR_127_96 = 0x230,
69     LOCAL_APIC_OFFSET_Local_APIC_IRR_159_128 = 0x240,
70     LOCAL_APIC_OFFSET_Local_APIC_IRR_191_160 = 0x250,
71     LOCAL_APIC_OFFSET_Local_APIC_IRR_223_192 = 0x260,
72     LOCAL_APIC_OFFSET_Local_APIC_IRR_255_224 = 0x270,
73 
74     LOCAL_APIC_OFFSET_Local_APIC_ESR = 0x280, // Error Status Register
75 
76     LOCAL_APIC_OFFSET_Local_APIC_LVT_CMCI = 0x2f0, // Corrected Machine Check Interrupt Register
77 
78     LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0 = 0x300, // Interrupt Command Register
79     LOCAL_APIC_OFFSET_Local_APIC_ICR_63_32 = 0x310,
80 
81     LOCAL_APIC_OFFSET_Local_APIC_LVT_TIMER = 0x320,
82     LOCAL_APIC_OFFSET_Local_APIC_LVT_THERMAL = 0x330,
83     LOCAL_APIC_OFFSET_Local_APIC_LVT_PERFORMANCE_MONITOR = 0x340,
84     LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT0 = 0x350,
85     LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT1 = 0x360,
86     LOCAL_APIC_OFFSET_Local_APIC_LVT_ERROR = 0x370,
87     // 初始计数寄存器(定时器专用)
88     LOCAL_APIC_OFFSET_Local_APIC_INITIAL_COUNT_REG = 0x380,
89     // 当前计数寄存器(定时器专用)
90     LOCAL_APIC_OFFSET_Local_APIC_CURRENT_COUNT_REG = 0x390,
91     LOCAL_APIC_OFFSET_Local_APIC_CLKDIV = 0x3e0,
92 }
93 
94 impl Into<u32> for XApicOffset {
95     fn into(self) -> u32 {
96         self as u32
97     }
98 }
99 
100 impl From<LVTRegister> for XApicOffset {
101     fn from(lvt: LVTRegister) -> Self {
102         match lvt {
103             LVTRegister::Timer => XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_TIMER,
104             LVTRegister::Thermal => XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_THERMAL,
105             LVTRegister::PerformanceMonitor => {
106                 XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_PERFORMANCE_MONITOR
107             }
108             LVTRegister::LINT0 => XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT0,
109             LVTRegister::LINT1 => XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT1,
110             LVTRegister::ErrorReg => XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_ERROR,
111             LVTRegister::CMCI => XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_CMCI,
112         }
113     }
114 }
115 
116 #[derive(Debug)]
117 #[allow(dead_code)]
118 pub struct XApic {
119     /// 当前xAPIC的寄存器映射的虚拟地址。注意,每个CPU都有自己的xAPIC,所以这个地址是每个CPU都不一样的。
120     apic_vaddr: VirtAddr,
121     /// `apic_vaddr`与映射的空间起始位置之间的偏移量
122     offset: usize,
123     map_guard: MMIOSpaceGuard,
124     xapic_base: PhysAddr,
125 }
126 
127 impl XApic {
128     /// 读取指定寄存器的值
129     #[allow(dead_code)]
130     pub unsafe fn read(&self, reg: XApicOffset) -> u32 {
131         read_volatile((self.apic_vaddr.data() + reg as usize) as *const u32)
132     }
133 
134     /// 将指定的值写入寄存器
135     #[allow(dead_code)]
136     pub unsafe fn write(&self, reg: XApicOffset, value: u32) {
137         write_volatile(
138             (self.apic_vaddr.data() + (reg as u32) as usize) as *mut u32,
139             value,
140         );
141         self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ID); // 等待写操作完成,通过读取进行同步
142     }
143 }
144 
145 impl XApic {
146     /// 创建新的XAPIC实例
147     ///
148     /// ## 参数
149     ///
150     /// - `xapic_base` - 当前核心的xAPIC的寄存器的物理地址
151     pub unsafe fn new(xapic_base: PhysAddr) -> Self {
152         let offset = xapic_base.data() & 0xffff;
153         let paddr = PhysAddr::new(xapic_base.data() & !0xffff);
154         let g = mmio_pool()
155             .create_mmio(4096)
156             .expect("Fail to create MMIO for XAPIC");
157         g.map_phys(paddr, 4096).expect("Fail to map MMIO for XAPIC");
158         let addr = g.vaddr() + offset;
159 
160         kdebug!(
161             "XAPIC: {:#x} -> {:#x}, offset={offset}",
162             xapic_base.data(),
163             addr.data()
164         );
165 
166         let r = Self {
167             apic_vaddr: addr,
168             offset,
169             map_guard: g,
170             xapic_base,
171         };
172 
173         return r;
174     }
175 }
176 
177 #[allow(dead_code)]
178 const X1: u32 = 0x0000000B; // 将除数设置为1,即不除频率
179 #[allow(dead_code)]
180 const PERIODIC: u32 = 0x00020000; // 周期性模式
181 #[allow(dead_code)]
182 const ENABLE: u32 = 0x00000100; // 单元使能
183 #[allow(dead_code)]
184 const MASKED: u32 = 0x00010000; // 中断屏蔽
185 const LEVEL: u32 = 0x00008000; // 电平触发
186 const BCAST: u32 = 0x00080000; // 发送到所有APIC,包括自己
187 const DELIVS: u32 = 0x00001000; // 传递状态
188 const INIT: u32 = 0x00000500; // INIT/RESET
189 
190 //中断请求
191 #[allow(dead_code)]
192 const T_IRQ0: u32 = 32; // IRQ 0 对应于 T_IRQ 中断
193 #[allow(dead_code)]
194 const IRQ_TIMER: u32 = 0;
195 #[allow(dead_code)]
196 const IRQ_KBD: u32 = 1;
197 #[allow(dead_code)]
198 const IRQ_COM1: u32 = 4;
199 #[allow(dead_code)]
200 const IRQ_IDE: u32 = 14;
201 #[allow(dead_code)]
202 const IRQ_ERROR: u32 = 19;
203 #[allow(dead_code)]
204 const IRQ_SPURIOUS: u32 = 31;
205 
206 impl LocalAPIC for XApic {
207     /// @brief 判断处理器是否支持apic
208     fn support() -> bool {
209         return x86::cpuid::CpuId::new()
210             .get_feature_info()
211             .expect("Fail to get CPU feature.")
212             .has_apic();
213     }
214 
215     /// @return true -> 函数运行成功
216     fn init_current_cpu(&mut self) -> bool {
217         unsafe {
218             // enable xapic
219             x86::msr::wrmsr(x86::msr::APIC_BASE, (self.xapic_base.data() | 0x800) as u64);
220             let val = x86::msr::rdmsr(x86::msr::APIC_BASE);
221             if val & 0x800 != 0x800 {
222                 kerror!("xAPIC enable failed: APIC_BASE & 0x800 != 0x800");
223                 return false;
224             }
225             // 设置 Spurious Interrupt Vector Register
226             let val = self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_SVR.into());
227 
228             self.write(
229                 XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_SVR.into(),
230                 val | ENABLE,
231             );
232 
233             let val = self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_SVR.into());
234             if val & ENABLE == 0 {
235                 kerror!("xAPIC software enable failed.");
236 
237                 return false;
238             } else {
239                 kinfo!("xAPIC software enabled.");
240             }
241 
242             if val & 0x1000 != 0 {
243                 kinfo!("xAPIC EOI broadcast suppression enabled.");
244             }
245 
246             self.mask_all_lvt();
247 
248             // 清除错误状态寄存器(需要连续写入两次)
249             self.write(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ESR.into(), 0);
250             self.write(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ESR.into(), 0);
251 
252             // 确认任何未完成的中断
253             self.write(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_EOI.into(), 0);
254 
255             // 发送 Init Level De-Assert 信号以同步仲裁ID
256             self.write(
257                 XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_63_32.into(),
258                 0,
259             );
260             self.write(
261                 XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0.into(),
262                 BCAST | INIT | LEVEL,
263             );
264             while self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0.into()) & DELIVS != 0
265             {
266                 spin_loop();
267             }
268         }
269 
270         true
271     }
272 
273     /// 发送 EOI(End Of Interrupt)
274     fn send_eoi(&self) {
275         unsafe {
276             let s = self as *const Self as *mut Self;
277             (*s).write(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_EOI.into(), 0);
278         }
279     }
280 
281     /// 获取版本号
282     fn version(&self) -> u8 {
283         unsafe {
284             (self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_Version.into()) & 0xff) as u8
285         }
286     }
287 
288     fn support_eoi_broadcast_suppression(&self) -> bool {
289         unsafe {
290             ((self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_Version.into()) >> 24) & 1) == 1
291         }
292     }
293 
294     fn max_lvt_entry(&self) -> u8 {
295         unsafe {
296             ((self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_Version.into()) >> 16) & 0xff)
297                 as u8
298                 + 1
299         }
300     }
301 
302     /// 获取ID
303     fn id(&self) -> u32 {
304         unsafe { self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ID.into()) >> 24 }
305     }
306 
307     /// 设置LVT寄存器的值
308     fn set_lvt(&mut self, lvt: LVT) {
309         unsafe {
310             self.write(lvt.register().into(), lvt.data);
311         }
312     }
313 
314     fn read_lvt(&self, reg: LVTRegister) -> LVT {
315         unsafe {
316             LVT::new(
317                 reg,
318                 self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_LVT_TIMER.into()),
319             )
320             .unwrap()
321         }
322     }
323 
324     fn mask_all_lvt(&mut self) {
325         // self.set_lvt(LVT::new(LVTRegister::CMCI, LVT::MASKED).unwrap());
326         self.set_lvt(LVT::new(LVTRegister::Timer, LVT::MASKED).unwrap());
327         self.set_lvt(LVT::new(LVTRegister::Thermal, LVT::MASKED).unwrap());
328         self.set_lvt(LVT::new(LVTRegister::PerformanceMonitor, LVT::MASKED).unwrap());
329         self.set_lvt(LVT::new(LVTRegister::LINT0, LVT::MASKED).unwrap());
330         self.set_lvt(LVT::new(LVTRegister::LINT1, LVT::MASKED).unwrap());
331         self.set_lvt(LVT::new(LVTRegister::ErrorReg, LVT::MASKED).unwrap());
332     }
333 
334     fn write_icr(&self, icr: x86::apic::Icr) {
335         unsafe {
336             // Wait for any previous send to finish
337             while self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0.into()) & DELIVS != 0
338             {
339                 spin_loop();
340             }
341 
342             self.write(
343                 XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_63_32.into(),
344                 icr.upper(),
345             );
346             self.write(
347                 XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0.into(),
348                 icr.lower(),
349             );
350 
351             // Wait for send to finish
352             while self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0.into()) & DELIVS != 0
353             {
354                 spin_loop();
355             }
356         }
357     }
358 }
359