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::{ 9e2841179SLoGin 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; 25e2841179SLoGin pub mod hw_irq; 2670a4e555SLoGin pub mod ioapic; 27e2841179SLoGin 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 68e2841179SLoGin 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 121*b5b571e0SLoGin impl From<LVTRegister> for u32 { 122*b5b571e0SLoGin fn from(val: LVTRegister) -> Self { 123*b5b571e0SLoGin val 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) { 457*b5b571e0SLoGin if let Some(xapic) = current_xapic_instance().borrow_mut().as_mut() { 45870a4e555SLoGin xapic.write(reg, value); 459*b5b571e0SLoGin } 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(); 486e2841179SLoGin if cpu_id.data() == 0 { 48770a4e555SLoGin unsafe { 48870a4e555SLoGin self.mask8259a(); 48970a4e555SLoGin } 49070a4e555SLoGin } 491e2841179SLoGin kinfo!("Initializing apic for cpu {:?}", cpu_id); 49270a4e555SLoGin if X2Apic::support() && X2Apic.init_current_cpu() { 493e2841179SLoGin if cpu_id.data() == 0 { 49470a4e555SLoGin LOCAL_APIC_ENABLE_TYPE.store(LocalApicEnableType::X2Apic, Ordering::SeqCst); 49570a4e555SLoGin } 496e2841179SLoGin kinfo!("x2APIC initialized for cpu {:?}", cpu_id); 49770a4e555SLoGin } else { 49870a4e555SLoGin kinfo!("x2APIC not supported or failed to initialize, fallback to xAPIC."); 499e2841179SLoGin 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 517e2841179SLoGin kinfo!("xAPIC initialized for cpu {:?}", cpu_id); 51870a4e555SLoGin } 519e2841179SLoGin 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(); 527*b5b571e0SLoGin } else if let Some(xapic) = current_xapic_instance().borrow().as_ref() { 52870a4e555SLoGin xapic.send_eoi(); 52970a4e555SLoGin } 53070a4e555SLoGin } 53170a4e555SLoGin 53270a4e555SLoGin fn version(&self) -> u8 { 53370a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 53470a4e555SLoGin return X2Apic.version(); 53570a4e555SLoGin } else { 53670a4e555SLoGin return current_xapic_instance() 53770a4e555SLoGin .borrow() 53870a4e555SLoGin .as_ref() 53970a4e555SLoGin .map(|xapic| xapic.version()) 54070a4e555SLoGin .unwrap_or(0); 54170a4e555SLoGin } 54270a4e555SLoGin } 54370a4e555SLoGin 54470a4e555SLoGin fn support_eoi_broadcast_suppression(&self) -> bool { 54570a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 54670a4e555SLoGin return X2Apic.support_eoi_broadcast_suppression(); 54770a4e555SLoGin } else { 54870a4e555SLoGin return current_xapic_instance() 54970a4e555SLoGin .borrow() 55070a4e555SLoGin .as_ref() 55170a4e555SLoGin .map(|xapic| xapic.support_eoi_broadcast_suppression()) 55270a4e555SLoGin .unwrap_or(false); 55370a4e555SLoGin } 55470a4e555SLoGin } 55570a4e555SLoGin 55670a4e555SLoGin fn max_lvt_entry(&self) -> u8 { 55770a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 55870a4e555SLoGin return X2Apic.max_lvt_entry(); 55970a4e555SLoGin } else { 56070a4e555SLoGin return current_xapic_instance() 56170a4e555SLoGin .borrow() 56270a4e555SLoGin .as_ref() 56370a4e555SLoGin .map(|xapic| xapic.max_lvt_entry()) 56470a4e555SLoGin .unwrap_or(0); 56570a4e555SLoGin } 56670a4e555SLoGin } 56770a4e555SLoGin 568e2841179SLoGin fn id(&self) -> ApicId { 56970a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 57070a4e555SLoGin return X2Apic.id(); 57170a4e555SLoGin } else { 57270a4e555SLoGin return current_xapic_instance() 57370a4e555SLoGin .borrow() 57470a4e555SLoGin .as_ref() 57570a4e555SLoGin .map(|xapic| xapic.id()) 576e2841179SLoGin .unwrap_or(ApicId::new(0)); 57770a4e555SLoGin } 57870a4e555SLoGin } 57970a4e555SLoGin 58070a4e555SLoGin fn set_lvt(&mut self, lvt: LVT) { 58170a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 58270a4e555SLoGin X2Apic.set_lvt(lvt); 583*b5b571e0SLoGin } else if let Some(xapic) = current_xapic_instance().borrow_mut().as_mut() { 58470a4e555SLoGin xapic.set_lvt(lvt); 58570a4e555SLoGin } 58670a4e555SLoGin } 58770a4e555SLoGin 58870a4e555SLoGin fn read_lvt(&self, reg: LVTRegister) -> LVT { 58970a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 59070a4e555SLoGin return X2Apic.read_lvt(reg); 59170a4e555SLoGin } else { 59270a4e555SLoGin return current_xapic_instance() 59370a4e555SLoGin .borrow() 59470a4e555SLoGin .as_ref() 59570a4e555SLoGin .map(|xapic| xapic.read_lvt(reg)) 59670a4e555SLoGin .expect("xapic instance not initialized."); 59770a4e555SLoGin } 59870a4e555SLoGin } 59970a4e555SLoGin 60070a4e555SLoGin fn mask_all_lvt(&mut self) { 60170a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 60270a4e555SLoGin X2Apic.mask_all_lvt(); 603*b5b571e0SLoGin } else if let Some(xapic) = current_xapic_instance().borrow_mut().as_mut() { 60470a4e555SLoGin xapic.mask_all_lvt(); 60570a4e555SLoGin } 60670a4e555SLoGin } 60770a4e555SLoGin 60870a4e555SLoGin fn write_icr(&self, icr: Icr) { 60970a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 61070a4e555SLoGin X2Apic.write_icr(icr); 611*b5b571e0SLoGin } else if let Some(xapic) = current_xapic_instance().borrow().as_ref() { 61270a4e555SLoGin xapic.write_icr(icr); 61370a4e555SLoGin } 61470a4e555SLoGin } 61570a4e555SLoGin } 616