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