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