xref: /DragonOS/kernel/src/arch/x86_64/driver/apic/mod.rs (revision e28411791f090c421fe4b6fa5956fb1bd362a8d9)
170a4e555SLoGin use core::sync::atomic::Ordering;
270a4e555SLoGin 
370a4e555SLoGin use atomic_enum::atomic_enum;
491e9d4abSLoGin use system_error::SystemError;
570a4e555SLoGin use x86::{apic::Icr, msr::IA32_APIC_BASE};
670a4e555SLoGin 
770a4e555SLoGin use crate::{
870a4e555SLoGin     arch::{
9*e2841179SLoGin         driver::apic::{hw_irq::ApicId, x2apic::X2Apic, xapic::XApic},
1070a4e555SLoGin         io::PortIOArch,
1170a4e555SLoGin         CurrentPortIOArch,
1270a4e555SLoGin     },
1370a4e555SLoGin     kdebug, kinfo,
1470a4e555SLoGin     mm::PhysAddr,
1570a4e555SLoGin     smp::core::smp_get_processor_id,
1670a4e555SLoGin };
1770a4e555SLoGin 
1870a4e555SLoGin use self::{
1970a4e555SLoGin     apic_timer::LocalApicTimerMode,
2070a4e555SLoGin     xapic::{current_xapic_instance, XApicOffset},
2170a4e555SLoGin };
2270a4e555SLoGin 
2370a4e555SLoGin pub mod apic_timer;
2470a4e555SLoGin mod c_adapter;
25*e2841179SLoGin pub mod hw_irq;
2670a4e555SLoGin pub mod ioapic;
27*e2841179SLoGin pub mod lapic_vector;
2870a4e555SLoGin pub mod x2apic;
2970a4e555SLoGin pub mod xapic;
3070a4e555SLoGin 
3170a4e555SLoGin /// 当前启用的APIC类型
3270a4e555SLoGin #[atomic_enum]
3370a4e555SLoGin #[derive(PartialEq, Eq)]
3470a4e555SLoGin pub enum LocalApicEnableType {
3570a4e555SLoGin     XApic,
3670a4e555SLoGin     X2Apic,
3770a4e555SLoGin }
3870a4e555SLoGin 
3970a4e555SLoGin static LOCAL_APIC_ENABLE_TYPE: AtomicLocalApicEnableType =
4070a4e555SLoGin     AtomicLocalApicEnableType::new(LocalApicEnableType::XApic);
4170a4e555SLoGin 
4270a4e555SLoGin pub trait LocalAPIC {
4370a4e555SLoGin     /// @brief 判断当前处理器是否支持这个类型的apic
4470a4e555SLoGin     ///
4570a4e555SLoGin     /// @return true 当前处理器支持这个类型的apic
4670a4e555SLoGin     /// @return false 当前处理器不支持这个类型的apic
4770a4e555SLoGin     fn support() -> bool;
4870a4e555SLoGin 
4970a4e555SLoGin     /// @brief 为当前处理器初始化local apic
5070a4e555SLoGin     ///
5170a4e555SLoGin     /// @return true 初始化成功
5270a4e555SLoGin     /// @return false 初始化失败
5370a4e555SLoGin     fn init_current_cpu(&mut self) -> bool;
5470a4e555SLoGin 
5570a4e555SLoGin     /// @brief 发送EOI信号(End of interrupt)
5670a4e555SLoGin     fn send_eoi(&self);
5770a4e555SLoGin 
5870a4e555SLoGin     /// @brief 获取APIC版本号
5970a4e555SLoGin     fn version(&self) -> u8;
6070a4e555SLoGin 
6170a4e555SLoGin     /// @brief 判断当前处理器是否支持EOI广播抑制
6270a4e555SLoGin     fn support_eoi_broadcast_suppression(&self) -> bool;
6370a4e555SLoGin 
6470a4e555SLoGin     /// 获取最多支持的LVT寄存器数量
6570a4e555SLoGin     fn max_lvt_entry(&self) -> u8;
6670a4e555SLoGin 
6770a4e555SLoGin     /// @brief 获取当前处理器的APIC ID
68*e2841179SLoGin     fn id(&self) -> ApicId;
6970a4e555SLoGin 
7070a4e555SLoGin     /// @brief 设置LVT寄存器
7170a4e555SLoGin     ///
7270a4e555SLoGin     /// @param register 寄存器
7370a4e555SLoGin     /// @param lvt 要被设置成的值
7470a4e555SLoGin     fn set_lvt(&mut self, lvt: LVT);
7570a4e555SLoGin 
7670a4e555SLoGin     /// 读取LVT寄存器
7770a4e555SLoGin     fn read_lvt(&self, reg: LVTRegister) -> LVT;
7870a4e555SLoGin 
7970a4e555SLoGin     fn mask_all_lvt(&mut self);
8070a4e555SLoGin 
8170a4e555SLoGin     /// 写入ICR寄存器
8270a4e555SLoGin     fn write_icr(&self, icr: Icr);
8370a4e555SLoGin }
8470a4e555SLoGin 
8570a4e555SLoGin /// @brief 所有LVT寄存器的枚举类型
8670a4e555SLoGin #[allow(dead_code)]
8770a4e555SLoGin #[repr(u32)]
8870a4e555SLoGin #[derive(Debug, Clone, Copy)]
8970a4e555SLoGin pub enum LVTRegister {
9070a4e555SLoGin     /// CMCI寄存器
9170a4e555SLoGin     ///
9270a4e555SLoGin     /// 如果支持CMCI功能,那么,当修正的机器错误超过阈值时,Local APIC通过CMCI寄存器的配置,
9370a4e555SLoGin     /// 向处理器核心投递中断消息
9470a4e555SLoGin     CMCI = 0x82f,
9570a4e555SLoGin     /// 定时器寄存器
9670a4e555SLoGin     ///
9770a4e555SLoGin     /// 当APIC定时器产生中断信号时,Local APIC通过定时器寄存器的设置,向处理器投递中断消息
9870a4e555SLoGin     Timer = 0x832,
9970a4e555SLoGin     /// 温度传感器寄存器
10070a4e555SLoGin     ///
10170a4e555SLoGin     /// 当处理器内部的温度传感器产生中断请求信号时,Local APIC会通过温度传感器寄存器的设置,
10270a4e555SLoGin     /// 向处理器投递中断消息。
10370a4e555SLoGin     Thermal = 0x833,
10470a4e555SLoGin     /// 性能监控计数器寄存器
10570a4e555SLoGin     ///
10670a4e555SLoGin     /// 当性能检测计数器寄存器溢出,产生中断请求时,Local APIC将会根据这个寄存器的配置,
10770a4e555SLoGin     /// 向处理器投递中断消息
10870a4e555SLoGin     PerformanceMonitor = 0x834,
10970a4e555SLoGin     /// 当处理器的LINT0引脚接收到中断请求信号时,Local APIC会根据这个寄存器的配置,
11070a4e555SLoGin     /// 向处理器投递中断消息
11170a4e555SLoGin     LINT0 = 0x835,
11270a4e555SLoGin     /// 当处理器的LINT0引脚接收到中断请求信号时,Local APIC会根据这个寄存器的配置,
11370a4e555SLoGin     /// 向处理器投递中断消息
11470a4e555SLoGin     LINT1 = 0x836,
11570a4e555SLoGin     /// 错误寄存器
11670a4e555SLoGin     ///
11770a4e555SLoGin     /// 当APIC检测到内部错误而产生中断请求信号时,它将会通过错误寄存器的设置,向处理器投递中断消息
11870a4e555SLoGin     ErrorReg = 0x837,
11970a4e555SLoGin }
12070a4e555SLoGin 
12170a4e555SLoGin impl Into<u32> for LVTRegister {
12270a4e555SLoGin     fn into(self) -> u32 {
12370a4e555SLoGin         self as u32
12470a4e555SLoGin     }
12570a4e555SLoGin }
12670a4e555SLoGin 
12770a4e555SLoGin #[derive(Debug)]
12870a4e555SLoGin pub struct LVT {
12970a4e555SLoGin     register: LVTRegister,
13070a4e555SLoGin     data: u32,
13170a4e555SLoGin }
13270a4e555SLoGin 
13370a4e555SLoGin impl LVT {
13470a4e555SLoGin     /// 当第16位为1时,表示屏蔽中断
13570a4e555SLoGin     pub const MASKED: u32 = 1 << 16;
13670a4e555SLoGin 
13770a4e555SLoGin     pub fn new(register: LVTRegister, data: u32) -> Option<Self> {
13870a4e555SLoGin         // vector: u8, mode: DeliveryMode, status: DeliveryStatus
13970a4e555SLoGin         let mut result = Self { register, data: 0 };
14070a4e555SLoGin         result.set_vector((data & 0xFF) as u8);
14170a4e555SLoGin         match result.register {
14270a4e555SLoGin             LVTRegister::Timer | LVTRegister::ErrorReg => {}
14370a4e555SLoGin             _ => {
14470a4e555SLoGin                 result
14570a4e555SLoGin                     .set_delivery_mode(DeliveryMode::try_from(((data >> 8) & 0b111) as u8).ok()?)
14670a4e555SLoGin                     .ok()?;
14770a4e555SLoGin             }
14870a4e555SLoGin         }
14970a4e555SLoGin 
15070a4e555SLoGin         if let LVTRegister::LINT0 | LVTRegister::LINT1 = result.register {
15170a4e555SLoGin             result.set_interrupt_input_pin_polarity((data & (1 << 13)) == 0);
15270a4e555SLoGin 
15370a4e555SLoGin             if data & (1 << 15) != 0 {
15470a4e555SLoGin                 result.set_trigger_mode(TriggerMode::Level).ok()?;
15570a4e555SLoGin             } else {
15670a4e555SLoGin                 result.set_trigger_mode(TriggerMode::Edge).ok()?;
15770a4e555SLoGin             }
15870a4e555SLoGin         }
15970a4e555SLoGin         result.set_mask((data & (1 << 16)) != 0);
16070a4e555SLoGin 
16170a4e555SLoGin         if let LVTRegister::Timer = result.register {
16270a4e555SLoGin             result
16370a4e555SLoGin                 .set_timer_mode(LocalApicTimerMode::try_from(((data >> 17) & 0b11) as u8).ok()?)
16470a4e555SLoGin                 .ok()?;
16570a4e555SLoGin         }
16670a4e555SLoGin 
16770a4e555SLoGin         return Some(result);
16870a4e555SLoGin     }
16970a4e555SLoGin 
17070a4e555SLoGin     /// 获取LVT寄存器的原始值
17170a4e555SLoGin     #[allow(dead_code)]
17270a4e555SLoGin     pub fn data(&self) -> u32 {
17370a4e555SLoGin         return self.data;
17470a4e555SLoGin     }
17570a4e555SLoGin 
17670a4e555SLoGin     pub fn register(&self) -> LVTRegister {
17770a4e555SLoGin         return self.register;
17870a4e555SLoGin     }
17970a4e555SLoGin 
18070a4e555SLoGin     pub fn set_vector(&mut self, vector: u8) {
18170a4e555SLoGin         self.data &= !((1 << 8) - 1);
18270a4e555SLoGin         self.data |= vector as u32;
18370a4e555SLoGin     }
18470a4e555SLoGin 
18570a4e555SLoGin     /// 获取中断向量号
18670a4e555SLoGin     #[allow(dead_code)]
18770a4e555SLoGin     pub fn vector(&self) -> u8 {
18870a4e555SLoGin         return (self.data & 0xFF) as u8;
18970a4e555SLoGin     }
19070a4e555SLoGin 
19170a4e555SLoGin     /// 设置中断投递模式
19270a4e555SLoGin     ///
19370a4e555SLoGin     /// Timer、ErrorReg寄存器不支持这个功能
19470a4e555SLoGin     ///
19570a4e555SLoGin     /// ## 参数
19670a4e555SLoGin     ///
19770a4e555SLoGin     /// - `mode`:投递模式
19870a4e555SLoGin     pub fn set_delivery_mode(&mut self, mode: DeliveryMode) -> Result<(), SystemError> {
19970a4e555SLoGin         match self.register {
20070a4e555SLoGin             LVTRegister::Timer | LVTRegister::ErrorReg => {
20170a4e555SLoGin                 return Err(SystemError::EINVAL);
20270a4e555SLoGin             }
20370a4e555SLoGin             _ => {}
20470a4e555SLoGin         }
20570a4e555SLoGin 
20670a4e555SLoGin         self.data &= 0xFFFF_F8FF;
20770a4e555SLoGin         self.data |= ((mode as u32) & 0x7) << 8;
20870a4e555SLoGin         return Ok(());
20970a4e555SLoGin     }
21070a4e555SLoGin 
21170a4e555SLoGin     /// 获取中断投递模式
21270a4e555SLoGin     /// Timer、ErrorReg寄存器不支持这个功能
21370a4e555SLoGin     #[allow(dead_code)]
21470a4e555SLoGin     pub fn delivery_mode(&self) -> Option<DeliveryMode> {
21570a4e555SLoGin         if let LVTRegister::Timer | LVTRegister::ErrorReg = self.register {
21670a4e555SLoGin             return None;
21770a4e555SLoGin         }
21870a4e555SLoGin         return DeliveryMode::try_from(((self.data >> 8) & 0b111) as u8).ok();
21970a4e555SLoGin     }
22070a4e555SLoGin 
22170a4e555SLoGin     /// Get the delivery status of the interrupt
22270a4e555SLoGin     #[allow(dead_code)]
22370a4e555SLoGin     pub fn delivery_status(&self) -> DeliveryStatus {
22470a4e555SLoGin         return DeliveryStatus::from(self.data);
22570a4e555SLoGin     }
22670a4e555SLoGin 
22770a4e555SLoGin     /// 设置中断输入引脚的极性
22870a4e555SLoGin     ///
22970a4e555SLoGin     /// ## 参数
23070a4e555SLoGin     ///
23170a4e555SLoGin     /// - `high`:true表示高电平有效,false表示低电平有效
23270a4e555SLoGin     pub fn set_interrupt_input_pin_polarity(&mut self, high: bool) {
23370a4e555SLoGin         self.data &= 0xFFFF_DFFF;
23470a4e555SLoGin         // 0表示高电平有效,1表示低电平有效
23570a4e555SLoGin         if !high {
23670a4e555SLoGin             self.data |= 1 << 13;
23770a4e555SLoGin         }
23870a4e555SLoGin     }
23970a4e555SLoGin 
24070a4e555SLoGin     /// 获取中断输入引脚的极性
24170a4e555SLoGin     ///
24270a4e555SLoGin     /// true表示高电平有效,false表示低电平有效
24370a4e555SLoGin     #[allow(dead_code)]
24470a4e555SLoGin     pub fn interrupt_input_pin_polarity(&self) -> bool {
24570a4e555SLoGin         return (self.data & (1 << 13)) == 0;
24670a4e555SLoGin     }
24770a4e555SLoGin 
24870a4e555SLoGin     /// 设置中断输入引脚的触发模式
24970a4e555SLoGin     ///
25070a4e555SLoGin     /// 只有LINT0和LINT1寄存器支持这个功能
25170a4e555SLoGin     ///
25270a4e555SLoGin     /// ## 参数
25370a4e555SLoGin     ///
25470a4e555SLoGin     /// - `trigger_mode`:触发模式
25570a4e555SLoGin     pub fn set_trigger_mode(&mut self, trigger_mode: TriggerMode) -> Result<(), SystemError> {
25670a4e555SLoGin         match self.register {
25770a4e555SLoGin             LVTRegister::LINT0 | LVTRegister::LINT1 => {
25870a4e555SLoGin                 self.data &= 0xFFFF_7FFF;
25970a4e555SLoGin                 if trigger_mode == TriggerMode::Level {
26070a4e555SLoGin                     self.data |= 1 << 15;
26170a4e555SLoGin                 }
26270a4e555SLoGin                 return Ok(());
26370a4e555SLoGin             }
26470a4e555SLoGin             _ => {
26570a4e555SLoGin                 return Err(SystemError::EINVAL);
26670a4e555SLoGin             }
26770a4e555SLoGin         }
26870a4e555SLoGin     }
26970a4e555SLoGin 
27070a4e555SLoGin     /// 获取中断输入引脚的触发模式
27170a4e555SLoGin     ///
27270a4e555SLoGin     /// 只有LINT0和LINT1寄存器支持这个功能
27370a4e555SLoGin     #[allow(dead_code)]
27470a4e555SLoGin     pub fn trigger_mode(&self) -> Option<TriggerMode> {
27570a4e555SLoGin         match self.register {
27670a4e555SLoGin             LVTRegister::LINT0 | LVTRegister::LINT1 => {
27770a4e555SLoGin                 if self.data & (1 << 15) != 0 {
27870a4e555SLoGin                     return Some(TriggerMode::Level);
27970a4e555SLoGin                 } else {
28070a4e555SLoGin                     return Some(TriggerMode::Edge);
28170a4e555SLoGin                 }
28270a4e555SLoGin             }
28370a4e555SLoGin             _ => {
28470a4e555SLoGin                 return None;
28570a4e555SLoGin             }
28670a4e555SLoGin         }
28770a4e555SLoGin     }
28870a4e555SLoGin 
28970a4e555SLoGin     /// 设置是否屏蔽中断
29070a4e555SLoGin     ///
29170a4e555SLoGin     /// ## 参数
29270a4e555SLoGin     ///
29370a4e555SLoGin     /// - `mask`:true表示屏蔽中断,false表示不屏蔽中断
29470a4e555SLoGin     pub fn set_mask(&mut self, mask: bool) {
29570a4e555SLoGin         self.data &= 0xFFFE_FFFF;
29670a4e555SLoGin         if mask {
29770a4e555SLoGin             self.data |= 1 << 16;
29870a4e555SLoGin         }
29970a4e555SLoGin     }
30070a4e555SLoGin 
30170a4e555SLoGin     /// Check if the interrupt is masked
30270a4e555SLoGin     ///
30370a4e555SLoGin     /// true表示屏蔽中断,false表示不屏蔽中断
30470a4e555SLoGin     #[allow(dead_code)]
30570a4e555SLoGin     pub fn mask(&self) -> bool {
30670a4e555SLoGin         return (self.data & (1 << 16)) != 0;
30770a4e555SLoGin     }
30870a4e555SLoGin 
30970a4e555SLoGin     /// 设置定时器模式
31070a4e555SLoGin     pub fn set_timer_mode(&mut self, mode: LocalApicTimerMode) -> Result<(), SystemError> {
31170a4e555SLoGin         match self.register {
31270a4e555SLoGin             LVTRegister::Timer => {
31370a4e555SLoGin                 self.data &= 0xFFF9_FFFF;
31470a4e555SLoGin                 match mode {
31570a4e555SLoGin                     LocalApicTimerMode::Oneshot => {
31670a4e555SLoGin                         self.data |= 0b00 << 17;
31770a4e555SLoGin                     }
31870a4e555SLoGin                     LocalApicTimerMode::Periodic => {
31970a4e555SLoGin                         self.data |= 0b01 << 17;
32070a4e555SLoGin                     }
32170a4e555SLoGin                     LocalApicTimerMode::Deadline => {
32270a4e555SLoGin                         self.data |= 0b10 << 17;
32370a4e555SLoGin                     }
32470a4e555SLoGin                 }
32570a4e555SLoGin                 return Ok(());
32670a4e555SLoGin             }
32770a4e555SLoGin             _ => {
32870a4e555SLoGin                 return Err(SystemError::EINVAL);
32970a4e555SLoGin             }
33070a4e555SLoGin         }
33170a4e555SLoGin     }
33270a4e555SLoGin 
33370a4e555SLoGin     /// 获取定时器模式
33470a4e555SLoGin     #[allow(dead_code)]
33570a4e555SLoGin     pub fn timer_mode(&self) -> Option<LocalApicTimerMode> {
33670a4e555SLoGin         if let LVTRegister::Timer = self.register {
33770a4e555SLoGin             let mode = (self.data >> 17) & 0b11;
33870a4e555SLoGin             match mode {
33970a4e555SLoGin                 0b00 => {
34070a4e555SLoGin                     return Some(LocalApicTimerMode::Oneshot);
34170a4e555SLoGin                 }
34270a4e555SLoGin                 0b01 => {
34370a4e555SLoGin                     return Some(LocalApicTimerMode::Periodic);
34470a4e555SLoGin                 }
34570a4e555SLoGin                 0b10 => {
34670a4e555SLoGin                     return Some(LocalApicTimerMode::Deadline);
34770a4e555SLoGin                 }
34870a4e555SLoGin                 _ => {
34970a4e555SLoGin                     return None;
35070a4e555SLoGin                 }
35170a4e555SLoGin             }
35270a4e555SLoGin         }
35370a4e555SLoGin         return None;
35470a4e555SLoGin     }
35570a4e555SLoGin }
35670a4e555SLoGin 
35770a4e555SLoGin /// @brief
35870a4e555SLoGin #[allow(dead_code)]
35970a4e555SLoGin #[derive(Debug, PartialEq)]
36070a4e555SLoGin pub enum DeliveryMode {
36170a4e555SLoGin     /// 由LVT寄存器的向量号区域指定中断向量号
36270a4e555SLoGin     Fixed = 0b000,
36370a4e555SLoGin     /// 通过处理器的SMI信号线,向处理器投递SMI中断请求。
36470a4e555SLoGin     /// 由于兼容性的原因,使用此投递模式时,LVT的中断向量号区域必须设置为0。
36570a4e555SLoGin     SMI = 0b010,
36670a4e555SLoGin     /// 向处理器投递不可屏蔽中断,并忽略向量号区域
36770a4e555SLoGin     NMI = 0b100,
36870a4e555SLoGin     /// 向处理器投递INIT中断请求,处理器会执行初始化的过程。
36970a4e555SLoGin     /// 由于兼容性的原因,使用此投递模式时,LVT的中断向量号区域必须设置为0。
37070a4e555SLoGin     /// CMCI、温度传感器、性能监控计数器等寄存器均不支持INIT投递模式
37170a4e555SLoGin     INIT = 0b101,
37270a4e555SLoGin 
37370a4e555SLoGin     /// 向目标处理器投递Start-Up IPI。
37470a4e555SLoGin     ///
37570a4e555SLoGin     /// 这个向量通常由多核引导模块调用(请参阅Intel开发手册Volume3 Section 8.4,
37670a4e555SLoGin     /// Multiple-Processor (MP) Initialization)。
37770a4e555SLoGin     /// 如果源APIC无法投递这个IPI,它不会自动重发。如果Start-Up IPI未成功投递,
37870a4e555SLoGin     /// 则交由软件决定是否在必要时重新投递SIPI
37970a4e555SLoGin     StartUp = 0b110,
38070a4e555SLoGin 
38170a4e555SLoGin     /// ExtINT模式可以将类8259A中断控制器产生的中断请求投递到处理器,并接收类
38270a4e555SLoGin     /// 8259A中断控制器提供的中断向量号。
38370a4e555SLoGin     /// CMCI、温度传感器、性能监控计数器等寄存器均不支持ExtINT投递模式
38470a4e555SLoGin     ExtINT = 0b111,
38570a4e555SLoGin }
38670a4e555SLoGin 
38770a4e555SLoGin impl TryFrom<u8> for DeliveryMode {
38870a4e555SLoGin     type Error = SystemError;
38970a4e555SLoGin 
39070a4e555SLoGin     fn try_from(value: u8) -> Result<Self, Self::Error> {
39170a4e555SLoGin         match value {
39270a4e555SLoGin             0b000 => {
39370a4e555SLoGin                 return Ok(DeliveryMode::Fixed);
39470a4e555SLoGin             }
39570a4e555SLoGin             0b010 => {
39670a4e555SLoGin                 return Ok(DeliveryMode::SMI);
39770a4e555SLoGin             }
39870a4e555SLoGin             0b100 => {
39970a4e555SLoGin                 return Ok(DeliveryMode::NMI);
40070a4e555SLoGin             }
40170a4e555SLoGin             0b101 => {
40270a4e555SLoGin                 return Ok(DeliveryMode::INIT);
40370a4e555SLoGin             }
40470a4e555SLoGin             0b110 => {
40570a4e555SLoGin                 return Ok(DeliveryMode::StartUp);
40670a4e555SLoGin             }
40770a4e555SLoGin             0b111 => {
40870a4e555SLoGin                 return Ok(DeliveryMode::ExtINT);
40970a4e555SLoGin             }
41070a4e555SLoGin             _ => {
41170a4e555SLoGin                 return Err(SystemError::EINVAL);
41270a4e555SLoGin             }
41370a4e555SLoGin         }
41470a4e555SLoGin     }
41570a4e555SLoGin }
41670a4e555SLoGin 
41770a4e555SLoGin /// @brief 投递状态
41870a4e555SLoGin #[derive(Debug)]
41970a4e555SLoGin #[allow(dead_code)]
42070a4e555SLoGin pub enum DeliveryStatus {
42170a4e555SLoGin     /// 空闲态。
42270a4e555SLoGin     /// 此状态表明,当前中断源未产生中断,或者产生的中断已经投递到处理器,并被处理器处理。
42370a4e555SLoGin     Idle = 0,
42470a4e555SLoGin     /// 发送挂起状态。
42570a4e555SLoGin     /// 此状态表明,中断源产生的请求已经投递至处理器,但尚未被处理器处理。
42670a4e555SLoGin     SendPending = 1,
42770a4e555SLoGin }
42870a4e555SLoGin 
42970a4e555SLoGin impl DeliveryStatus {
43070a4e555SLoGin     pub fn from(data: u32) -> Self {
43170a4e555SLoGin         if data & (1 << 12) == 0 {
43270a4e555SLoGin             return DeliveryStatus::Idle;
43370a4e555SLoGin         } else {
43470a4e555SLoGin             return DeliveryStatus::SendPending;
43570a4e555SLoGin         }
43670a4e555SLoGin     }
43770a4e555SLoGin }
43870a4e555SLoGin 
43970a4e555SLoGin /// IPI Trigger Mode
44070a4e555SLoGin #[derive(Debug, Eq, PartialEq)]
44170a4e555SLoGin #[repr(u64)]
44270a4e555SLoGin pub enum TriggerMode {
44370a4e555SLoGin     Edge = 0,
44470a4e555SLoGin     Level = 1,
44570a4e555SLoGin }
44670a4e555SLoGin 
44770a4e555SLoGin #[derive(Debug)]
44870a4e555SLoGin pub struct CurrentApic;
44970a4e555SLoGin 
45070a4e555SLoGin impl CurrentApic {
45170a4e555SLoGin     /// x2apic是否启用
45270a4e555SLoGin     pub fn x2apic_enabled(&self) -> bool {
45370a4e555SLoGin         return LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic;
45470a4e555SLoGin     }
45570a4e555SLoGin 
45670a4e555SLoGin     pub(self) unsafe fn write_xapic_register(&self, reg: XApicOffset, value: u32) {
45770a4e555SLoGin         current_xapic_instance().borrow_mut().as_mut().map(|xapic| {
45870a4e555SLoGin             xapic.write(reg, value);
45970a4e555SLoGin         });
46070a4e555SLoGin     }
46170a4e555SLoGin 
46270a4e555SLoGin     /// 屏蔽类8259A芯片
46370a4e555SLoGin     unsafe fn mask8259a(&self) {
46470a4e555SLoGin         CurrentPortIOArch::out8(0x21, 0xff);
46570a4e555SLoGin         CurrentPortIOArch::out8(0xa1, 0xff);
46670a4e555SLoGin 
46770a4e555SLoGin         // 写入8259A pic的EOI位
46870a4e555SLoGin         CurrentPortIOArch::out8(0x20, 0x20);
46970a4e555SLoGin         CurrentPortIOArch::out8(0xa0, 0x20);
47070a4e555SLoGin 
47170a4e555SLoGin         kdebug!("8259A Masked.");
47270a4e555SLoGin 
47370a4e555SLoGin         // enable IMCR
47470a4e555SLoGin         CurrentPortIOArch::out8(0x22, 0x70);
47570a4e555SLoGin         CurrentPortIOArch::out8(0x23, 0x01);
47670a4e555SLoGin     }
47770a4e555SLoGin }
47870a4e555SLoGin 
47970a4e555SLoGin impl LocalAPIC for CurrentApic {
48070a4e555SLoGin     fn support() -> bool {
48170a4e555SLoGin         true
48270a4e555SLoGin     }
48370a4e555SLoGin 
48470a4e555SLoGin     fn init_current_cpu(&mut self) -> bool {
48570a4e555SLoGin         let cpu_id = smp_get_processor_id();
486*e2841179SLoGin         if cpu_id.data() == 0 {
48770a4e555SLoGin             unsafe {
48870a4e555SLoGin                 self.mask8259a();
48970a4e555SLoGin             }
49070a4e555SLoGin         }
491*e2841179SLoGin         kinfo!("Initializing apic for cpu {:?}", cpu_id);
49270a4e555SLoGin         if X2Apic::support() && X2Apic.init_current_cpu() {
493*e2841179SLoGin             if cpu_id.data() == 0 {
49470a4e555SLoGin                 LOCAL_APIC_ENABLE_TYPE.store(LocalApicEnableType::X2Apic, Ordering::SeqCst);
49570a4e555SLoGin             }
496*e2841179SLoGin             kinfo!("x2APIC initialized for cpu {:?}", cpu_id);
49770a4e555SLoGin         } else {
49870a4e555SLoGin             kinfo!("x2APIC not supported or failed to initialize, fallback to xAPIC.");
499*e2841179SLoGin             if cpu_id.data() == 0 {
50070a4e555SLoGin                 LOCAL_APIC_ENABLE_TYPE.store(LocalApicEnableType::XApic, Ordering::SeqCst);
50170a4e555SLoGin             }
50270a4e555SLoGin             let apic_base =
50370a4e555SLoGin                 PhysAddr::new(unsafe { x86::msr::rdmsr(IA32_APIC_BASE) as usize & 0xFFFF_0000 });
50470a4e555SLoGin             let xapic_instance = unsafe { XApic::new(apic_base) };
50570a4e555SLoGin 
50670a4e555SLoGin             let mut cur = current_xapic_instance().borrow_mut();
50770a4e555SLoGin             if cur.is_none() {
50870a4e555SLoGin                 *cur = Some(xapic_instance);
50970a4e555SLoGin             } else {
51070a4e555SLoGin                 panic!("xapic instance already initialized.");
51170a4e555SLoGin             }
51270a4e555SLoGin 
51370a4e555SLoGin             if let Some(xapic) = cur.as_mut() {
51470a4e555SLoGin                 xapic.init_current_cpu();
51570a4e555SLoGin             }
51670a4e555SLoGin 
517*e2841179SLoGin             kinfo!("xAPIC initialized for cpu {:?}", cpu_id);
51870a4e555SLoGin         }
519*e2841179SLoGin 
52070a4e555SLoGin         kinfo!("Apic initialized.");
52170a4e555SLoGin         return true;
52270a4e555SLoGin     }
52370a4e555SLoGin 
52470a4e555SLoGin     fn send_eoi(&self) {
52570a4e555SLoGin         if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
52670a4e555SLoGin             X2Apic.send_eoi();
52770a4e555SLoGin         } else {
52870a4e555SLoGin             current_xapic_instance().borrow().as_ref().map(|xapic| {
52970a4e555SLoGin                 xapic.send_eoi();
53070a4e555SLoGin             });
53170a4e555SLoGin         }
53270a4e555SLoGin     }
53370a4e555SLoGin 
53470a4e555SLoGin     fn version(&self) -> u8 {
53570a4e555SLoGin         if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
53670a4e555SLoGin             return X2Apic.version();
53770a4e555SLoGin         } else {
53870a4e555SLoGin             return current_xapic_instance()
53970a4e555SLoGin                 .borrow()
54070a4e555SLoGin                 .as_ref()
54170a4e555SLoGin                 .map(|xapic| xapic.version())
54270a4e555SLoGin                 .unwrap_or(0);
54370a4e555SLoGin         }
54470a4e555SLoGin     }
54570a4e555SLoGin 
54670a4e555SLoGin     fn support_eoi_broadcast_suppression(&self) -> bool {
54770a4e555SLoGin         if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
54870a4e555SLoGin             return X2Apic.support_eoi_broadcast_suppression();
54970a4e555SLoGin         } else {
55070a4e555SLoGin             return current_xapic_instance()
55170a4e555SLoGin                 .borrow()
55270a4e555SLoGin                 .as_ref()
55370a4e555SLoGin                 .map(|xapic| xapic.support_eoi_broadcast_suppression())
55470a4e555SLoGin                 .unwrap_or(false);
55570a4e555SLoGin         }
55670a4e555SLoGin     }
55770a4e555SLoGin 
55870a4e555SLoGin     fn max_lvt_entry(&self) -> u8 {
55970a4e555SLoGin         if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
56070a4e555SLoGin             return X2Apic.max_lvt_entry();
56170a4e555SLoGin         } else {
56270a4e555SLoGin             return current_xapic_instance()
56370a4e555SLoGin                 .borrow()
56470a4e555SLoGin                 .as_ref()
56570a4e555SLoGin                 .map(|xapic| xapic.max_lvt_entry())
56670a4e555SLoGin                 .unwrap_or(0);
56770a4e555SLoGin         }
56870a4e555SLoGin     }
56970a4e555SLoGin 
570*e2841179SLoGin     fn id(&self) -> ApicId {
57170a4e555SLoGin         if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
57270a4e555SLoGin             return X2Apic.id();
57370a4e555SLoGin         } else {
57470a4e555SLoGin             return current_xapic_instance()
57570a4e555SLoGin                 .borrow()
57670a4e555SLoGin                 .as_ref()
57770a4e555SLoGin                 .map(|xapic| xapic.id())
578*e2841179SLoGin                 .unwrap_or(ApicId::new(0));
57970a4e555SLoGin         }
58070a4e555SLoGin     }
58170a4e555SLoGin 
58270a4e555SLoGin     fn set_lvt(&mut self, lvt: LVT) {
58370a4e555SLoGin         if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
58470a4e555SLoGin             X2Apic.set_lvt(lvt);
58570a4e555SLoGin         } else {
58670a4e555SLoGin             current_xapic_instance().borrow_mut().as_mut().map(|xapic| {
58770a4e555SLoGin                 xapic.set_lvt(lvt);
58870a4e555SLoGin             });
58970a4e555SLoGin         }
59070a4e555SLoGin     }
59170a4e555SLoGin 
59270a4e555SLoGin     fn read_lvt(&self, reg: LVTRegister) -> LVT {
59370a4e555SLoGin         if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
59470a4e555SLoGin             return X2Apic.read_lvt(reg);
59570a4e555SLoGin         } else {
59670a4e555SLoGin             return current_xapic_instance()
59770a4e555SLoGin                 .borrow()
59870a4e555SLoGin                 .as_ref()
59970a4e555SLoGin                 .map(|xapic| xapic.read_lvt(reg))
60070a4e555SLoGin                 .expect("xapic instance not initialized.");
60170a4e555SLoGin         }
60270a4e555SLoGin     }
60370a4e555SLoGin 
60470a4e555SLoGin     fn mask_all_lvt(&mut self) {
60570a4e555SLoGin         if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
60670a4e555SLoGin             X2Apic.mask_all_lvt();
60770a4e555SLoGin         } else {
60870a4e555SLoGin             current_xapic_instance().borrow_mut().as_mut().map(|xapic| {
60970a4e555SLoGin                 xapic.mask_all_lvt();
61070a4e555SLoGin             });
61170a4e555SLoGin         }
61270a4e555SLoGin     }
61370a4e555SLoGin 
61470a4e555SLoGin     fn write_icr(&self, icr: Icr) {
61570a4e555SLoGin         if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
61670a4e555SLoGin             X2Apic.write_icr(icr);
61770a4e555SLoGin         } else {
61870a4e555SLoGin             current_xapic_instance().borrow().as_ref().map(|xapic| {
61970a4e555SLoGin                 xapic.write_icr(icr);
62070a4e555SLoGin             });
62170a4e555SLoGin         }
62270a4e555SLoGin     }
62370a4e555SLoGin }
624