1*70a4e555SLoGin use core::sync::atomic::Ordering; 2*70a4e555SLoGin 3*70a4e555SLoGin use atomic_enum::atomic_enum; 4*70a4e555SLoGin use x86::{apic::Icr, msr::IA32_APIC_BASE}; 5*70a4e555SLoGin 6*70a4e555SLoGin use crate::{ 7*70a4e555SLoGin arch::{ 8*70a4e555SLoGin driver::apic::{ioapic::ioapic_init, x2apic::X2Apic, xapic::XApic}, 9*70a4e555SLoGin io::PortIOArch, 10*70a4e555SLoGin CurrentPortIOArch, 11*70a4e555SLoGin }, 12*70a4e555SLoGin kdebug, kinfo, 13*70a4e555SLoGin mm::PhysAddr, 14*70a4e555SLoGin smp::core::smp_get_processor_id, 15*70a4e555SLoGin syscall::SystemError, 16*70a4e555SLoGin }; 17*70a4e555SLoGin 18*70a4e555SLoGin use self::{ 19*70a4e555SLoGin apic_timer::LocalApicTimerMode, 20*70a4e555SLoGin xapic::{current_xapic_instance, XApicOffset}, 21*70a4e555SLoGin }; 22*70a4e555SLoGin 23*70a4e555SLoGin pub mod apic_timer; 24*70a4e555SLoGin mod c_adapter; 25*70a4e555SLoGin pub mod ioapic; 26*70a4e555SLoGin pub mod x2apic; 27*70a4e555SLoGin pub mod xapic; 28*70a4e555SLoGin 29*70a4e555SLoGin /// 当前启用的APIC类型 30*70a4e555SLoGin #[atomic_enum] 31*70a4e555SLoGin #[derive(PartialEq, Eq)] 32*70a4e555SLoGin pub enum LocalApicEnableType { 33*70a4e555SLoGin XApic, 34*70a4e555SLoGin X2Apic, 35*70a4e555SLoGin } 36*70a4e555SLoGin 37*70a4e555SLoGin static LOCAL_APIC_ENABLE_TYPE: AtomicLocalApicEnableType = 38*70a4e555SLoGin AtomicLocalApicEnableType::new(LocalApicEnableType::XApic); 39*70a4e555SLoGin 40*70a4e555SLoGin pub trait LocalAPIC { 41*70a4e555SLoGin /// @brief 判断当前处理器是否支持这个类型的apic 42*70a4e555SLoGin /// 43*70a4e555SLoGin /// @return true 当前处理器支持这个类型的apic 44*70a4e555SLoGin /// @return false 当前处理器不支持这个类型的apic 45*70a4e555SLoGin fn support() -> bool; 46*70a4e555SLoGin 47*70a4e555SLoGin /// @brief 为当前处理器初始化local apic 48*70a4e555SLoGin /// 49*70a4e555SLoGin /// @return true 初始化成功 50*70a4e555SLoGin /// @return false 初始化失败 51*70a4e555SLoGin fn init_current_cpu(&mut self) -> bool; 52*70a4e555SLoGin 53*70a4e555SLoGin /// @brief 发送EOI信号(End of interrupt) 54*70a4e555SLoGin fn send_eoi(&self); 55*70a4e555SLoGin 56*70a4e555SLoGin /// @brief 获取APIC版本号 57*70a4e555SLoGin fn version(&self) -> u8; 58*70a4e555SLoGin 59*70a4e555SLoGin /// @brief 判断当前处理器是否支持EOI广播抑制 60*70a4e555SLoGin fn support_eoi_broadcast_suppression(&self) -> bool; 61*70a4e555SLoGin 62*70a4e555SLoGin /// 获取最多支持的LVT寄存器数量 63*70a4e555SLoGin fn max_lvt_entry(&self) -> u8; 64*70a4e555SLoGin 65*70a4e555SLoGin /// @brief 获取当前处理器的APIC ID 66*70a4e555SLoGin fn id(&self) -> u32; 67*70a4e555SLoGin 68*70a4e555SLoGin /// @brief 设置LVT寄存器 69*70a4e555SLoGin /// 70*70a4e555SLoGin /// @param register 寄存器 71*70a4e555SLoGin /// @param lvt 要被设置成的值 72*70a4e555SLoGin fn set_lvt(&mut self, lvt: LVT); 73*70a4e555SLoGin 74*70a4e555SLoGin /// 读取LVT寄存器 75*70a4e555SLoGin fn read_lvt(&self, reg: LVTRegister) -> LVT; 76*70a4e555SLoGin 77*70a4e555SLoGin fn mask_all_lvt(&mut self); 78*70a4e555SLoGin 79*70a4e555SLoGin /// 写入ICR寄存器 80*70a4e555SLoGin fn write_icr(&self, icr: Icr); 81*70a4e555SLoGin } 82*70a4e555SLoGin 83*70a4e555SLoGin /// @brief 所有LVT寄存器的枚举类型 84*70a4e555SLoGin #[allow(dead_code)] 85*70a4e555SLoGin #[repr(u32)] 86*70a4e555SLoGin #[derive(Debug, Clone, Copy)] 87*70a4e555SLoGin pub enum LVTRegister { 88*70a4e555SLoGin /// CMCI寄存器 89*70a4e555SLoGin /// 90*70a4e555SLoGin /// 如果支持CMCI功能,那么,当修正的机器错误超过阈值时,Local APIC通过CMCI寄存器的配置, 91*70a4e555SLoGin /// 向处理器核心投递中断消息 92*70a4e555SLoGin CMCI = 0x82f, 93*70a4e555SLoGin /// 定时器寄存器 94*70a4e555SLoGin /// 95*70a4e555SLoGin /// 当APIC定时器产生中断信号时,Local APIC通过定时器寄存器的设置,向处理器投递中断消息 96*70a4e555SLoGin Timer = 0x832, 97*70a4e555SLoGin /// 温度传感器寄存器 98*70a4e555SLoGin /// 99*70a4e555SLoGin /// 当处理器内部的温度传感器产生中断请求信号时,Local APIC会通过温度传感器寄存器的设置, 100*70a4e555SLoGin /// 向处理器投递中断消息。 101*70a4e555SLoGin Thermal = 0x833, 102*70a4e555SLoGin /// 性能监控计数器寄存器 103*70a4e555SLoGin /// 104*70a4e555SLoGin /// 当性能检测计数器寄存器溢出,产生中断请求时,Local APIC将会根据这个寄存器的配置, 105*70a4e555SLoGin /// 向处理器投递中断消息 106*70a4e555SLoGin PerformanceMonitor = 0x834, 107*70a4e555SLoGin /// 当处理器的LINT0引脚接收到中断请求信号时,Local APIC会根据这个寄存器的配置, 108*70a4e555SLoGin /// 向处理器投递中断消息 109*70a4e555SLoGin LINT0 = 0x835, 110*70a4e555SLoGin /// 当处理器的LINT0引脚接收到中断请求信号时,Local APIC会根据这个寄存器的配置, 111*70a4e555SLoGin /// 向处理器投递中断消息 112*70a4e555SLoGin LINT1 = 0x836, 113*70a4e555SLoGin /// 错误寄存器 114*70a4e555SLoGin /// 115*70a4e555SLoGin /// 当APIC检测到内部错误而产生中断请求信号时,它将会通过错误寄存器的设置,向处理器投递中断消息 116*70a4e555SLoGin ErrorReg = 0x837, 117*70a4e555SLoGin } 118*70a4e555SLoGin 119*70a4e555SLoGin impl Into<u32> for LVTRegister { 120*70a4e555SLoGin fn into(self) -> u32 { 121*70a4e555SLoGin self as u32 122*70a4e555SLoGin } 123*70a4e555SLoGin } 124*70a4e555SLoGin 125*70a4e555SLoGin #[derive(Debug)] 126*70a4e555SLoGin pub struct LVT { 127*70a4e555SLoGin register: LVTRegister, 128*70a4e555SLoGin data: u32, 129*70a4e555SLoGin } 130*70a4e555SLoGin 131*70a4e555SLoGin impl LVT { 132*70a4e555SLoGin /// 当第16位为1时,表示屏蔽中断 133*70a4e555SLoGin pub const MASKED: u32 = 1 << 16; 134*70a4e555SLoGin 135*70a4e555SLoGin pub fn new(register: LVTRegister, data: u32) -> Option<Self> { 136*70a4e555SLoGin // vector: u8, mode: DeliveryMode, status: DeliveryStatus 137*70a4e555SLoGin let mut result = Self { register, data: 0 }; 138*70a4e555SLoGin result.set_vector((data & 0xFF) as u8); 139*70a4e555SLoGin match result.register { 140*70a4e555SLoGin LVTRegister::Timer | LVTRegister::ErrorReg => {} 141*70a4e555SLoGin _ => { 142*70a4e555SLoGin result 143*70a4e555SLoGin .set_delivery_mode(DeliveryMode::try_from(((data >> 8) & 0b111) as u8).ok()?) 144*70a4e555SLoGin .ok()?; 145*70a4e555SLoGin } 146*70a4e555SLoGin } 147*70a4e555SLoGin 148*70a4e555SLoGin if let LVTRegister::LINT0 | LVTRegister::LINT1 = result.register { 149*70a4e555SLoGin result.set_interrupt_input_pin_polarity((data & (1 << 13)) == 0); 150*70a4e555SLoGin 151*70a4e555SLoGin if data & (1 << 15) != 0 { 152*70a4e555SLoGin result.set_trigger_mode(TriggerMode::Level).ok()?; 153*70a4e555SLoGin } else { 154*70a4e555SLoGin result.set_trigger_mode(TriggerMode::Edge).ok()?; 155*70a4e555SLoGin } 156*70a4e555SLoGin } 157*70a4e555SLoGin result.set_mask((data & (1 << 16)) != 0); 158*70a4e555SLoGin 159*70a4e555SLoGin if let LVTRegister::Timer = result.register { 160*70a4e555SLoGin result 161*70a4e555SLoGin .set_timer_mode(LocalApicTimerMode::try_from(((data >> 17) & 0b11) as u8).ok()?) 162*70a4e555SLoGin .ok()?; 163*70a4e555SLoGin } 164*70a4e555SLoGin 165*70a4e555SLoGin return Some(result); 166*70a4e555SLoGin } 167*70a4e555SLoGin 168*70a4e555SLoGin /// 获取LVT寄存器的原始值 169*70a4e555SLoGin #[allow(dead_code)] 170*70a4e555SLoGin pub fn data(&self) -> u32 { 171*70a4e555SLoGin return self.data; 172*70a4e555SLoGin } 173*70a4e555SLoGin 174*70a4e555SLoGin pub fn register(&self) -> LVTRegister { 175*70a4e555SLoGin return self.register; 176*70a4e555SLoGin } 177*70a4e555SLoGin 178*70a4e555SLoGin pub fn set_vector(&mut self, vector: u8) { 179*70a4e555SLoGin self.data &= !((1 << 8) - 1); 180*70a4e555SLoGin self.data |= vector as u32; 181*70a4e555SLoGin } 182*70a4e555SLoGin 183*70a4e555SLoGin /// 获取中断向量号 184*70a4e555SLoGin #[allow(dead_code)] 185*70a4e555SLoGin pub fn vector(&self) -> u8 { 186*70a4e555SLoGin return (self.data & 0xFF) as u8; 187*70a4e555SLoGin } 188*70a4e555SLoGin 189*70a4e555SLoGin /// 设置中断投递模式 190*70a4e555SLoGin /// 191*70a4e555SLoGin /// Timer、ErrorReg寄存器不支持这个功能 192*70a4e555SLoGin /// 193*70a4e555SLoGin /// ## 参数 194*70a4e555SLoGin /// 195*70a4e555SLoGin /// - `mode`:投递模式 196*70a4e555SLoGin pub fn set_delivery_mode(&mut self, mode: DeliveryMode) -> Result<(), SystemError> { 197*70a4e555SLoGin match self.register { 198*70a4e555SLoGin LVTRegister::Timer | LVTRegister::ErrorReg => { 199*70a4e555SLoGin return Err(SystemError::EINVAL); 200*70a4e555SLoGin } 201*70a4e555SLoGin _ => {} 202*70a4e555SLoGin } 203*70a4e555SLoGin 204*70a4e555SLoGin self.data &= 0xFFFF_F8FF; 205*70a4e555SLoGin self.data |= ((mode as u32) & 0x7) << 8; 206*70a4e555SLoGin return Ok(()); 207*70a4e555SLoGin } 208*70a4e555SLoGin 209*70a4e555SLoGin /// 获取中断投递模式 210*70a4e555SLoGin /// Timer、ErrorReg寄存器不支持这个功能 211*70a4e555SLoGin #[allow(dead_code)] 212*70a4e555SLoGin pub fn delivery_mode(&self) -> Option<DeliveryMode> { 213*70a4e555SLoGin if let LVTRegister::Timer | LVTRegister::ErrorReg = self.register { 214*70a4e555SLoGin return None; 215*70a4e555SLoGin } 216*70a4e555SLoGin return DeliveryMode::try_from(((self.data >> 8) & 0b111) as u8).ok(); 217*70a4e555SLoGin } 218*70a4e555SLoGin 219*70a4e555SLoGin /// Get the delivery status of the interrupt 220*70a4e555SLoGin #[allow(dead_code)] 221*70a4e555SLoGin pub fn delivery_status(&self) -> DeliveryStatus { 222*70a4e555SLoGin return DeliveryStatus::from(self.data); 223*70a4e555SLoGin } 224*70a4e555SLoGin 225*70a4e555SLoGin /// 设置中断输入引脚的极性 226*70a4e555SLoGin /// 227*70a4e555SLoGin /// ## 参数 228*70a4e555SLoGin /// 229*70a4e555SLoGin /// - `high`:true表示高电平有效,false表示低电平有效 230*70a4e555SLoGin pub fn set_interrupt_input_pin_polarity(&mut self, high: bool) { 231*70a4e555SLoGin self.data &= 0xFFFF_DFFF; 232*70a4e555SLoGin // 0表示高电平有效,1表示低电平有效 233*70a4e555SLoGin if !high { 234*70a4e555SLoGin self.data |= 1 << 13; 235*70a4e555SLoGin } 236*70a4e555SLoGin } 237*70a4e555SLoGin 238*70a4e555SLoGin /// 获取中断输入引脚的极性 239*70a4e555SLoGin /// 240*70a4e555SLoGin /// true表示高电平有效,false表示低电平有效 241*70a4e555SLoGin #[allow(dead_code)] 242*70a4e555SLoGin pub fn interrupt_input_pin_polarity(&self) -> bool { 243*70a4e555SLoGin return (self.data & (1 << 13)) == 0; 244*70a4e555SLoGin } 245*70a4e555SLoGin 246*70a4e555SLoGin /// 设置中断输入引脚的触发模式 247*70a4e555SLoGin /// 248*70a4e555SLoGin /// 只有LINT0和LINT1寄存器支持这个功能 249*70a4e555SLoGin /// 250*70a4e555SLoGin /// ## 参数 251*70a4e555SLoGin /// 252*70a4e555SLoGin /// - `trigger_mode`:触发模式 253*70a4e555SLoGin pub fn set_trigger_mode(&mut self, trigger_mode: TriggerMode) -> Result<(), SystemError> { 254*70a4e555SLoGin match self.register { 255*70a4e555SLoGin LVTRegister::LINT0 | LVTRegister::LINT1 => { 256*70a4e555SLoGin self.data &= 0xFFFF_7FFF; 257*70a4e555SLoGin if trigger_mode == TriggerMode::Level { 258*70a4e555SLoGin self.data |= 1 << 15; 259*70a4e555SLoGin } 260*70a4e555SLoGin return Ok(()); 261*70a4e555SLoGin } 262*70a4e555SLoGin _ => { 263*70a4e555SLoGin return Err(SystemError::EINVAL); 264*70a4e555SLoGin } 265*70a4e555SLoGin } 266*70a4e555SLoGin } 267*70a4e555SLoGin 268*70a4e555SLoGin /// 获取中断输入引脚的触发模式 269*70a4e555SLoGin /// 270*70a4e555SLoGin /// 只有LINT0和LINT1寄存器支持这个功能 271*70a4e555SLoGin #[allow(dead_code)] 272*70a4e555SLoGin pub fn trigger_mode(&self) -> Option<TriggerMode> { 273*70a4e555SLoGin match self.register { 274*70a4e555SLoGin LVTRegister::LINT0 | LVTRegister::LINT1 => { 275*70a4e555SLoGin if self.data & (1 << 15) != 0 { 276*70a4e555SLoGin return Some(TriggerMode::Level); 277*70a4e555SLoGin } else { 278*70a4e555SLoGin return Some(TriggerMode::Edge); 279*70a4e555SLoGin } 280*70a4e555SLoGin } 281*70a4e555SLoGin _ => { 282*70a4e555SLoGin return None; 283*70a4e555SLoGin } 284*70a4e555SLoGin } 285*70a4e555SLoGin } 286*70a4e555SLoGin 287*70a4e555SLoGin /// 设置是否屏蔽中断 288*70a4e555SLoGin /// 289*70a4e555SLoGin /// ## 参数 290*70a4e555SLoGin /// 291*70a4e555SLoGin /// - `mask`:true表示屏蔽中断,false表示不屏蔽中断 292*70a4e555SLoGin pub fn set_mask(&mut self, mask: bool) { 293*70a4e555SLoGin self.data &= 0xFFFE_FFFF; 294*70a4e555SLoGin if mask { 295*70a4e555SLoGin self.data |= 1 << 16; 296*70a4e555SLoGin } 297*70a4e555SLoGin } 298*70a4e555SLoGin 299*70a4e555SLoGin /// Check if the interrupt is masked 300*70a4e555SLoGin /// 301*70a4e555SLoGin /// true表示屏蔽中断,false表示不屏蔽中断 302*70a4e555SLoGin #[allow(dead_code)] 303*70a4e555SLoGin pub fn mask(&self) -> bool { 304*70a4e555SLoGin return (self.data & (1 << 16)) != 0; 305*70a4e555SLoGin } 306*70a4e555SLoGin 307*70a4e555SLoGin /// 设置定时器模式 308*70a4e555SLoGin pub fn set_timer_mode(&mut self, mode: LocalApicTimerMode) -> Result<(), SystemError> { 309*70a4e555SLoGin match self.register { 310*70a4e555SLoGin LVTRegister::Timer => { 311*70a4e555SLoGin self.data &= 0xFFF9_FFFF; 312*70a4e555SLoGin match mode { 313*70a4e555SLoGin LocalApicTimerMode::Oneshot => { 314*70a4e555SLoGin self.data |= 0b00 << 17; 315*70a4e555SLoGin } 316*70a4e555SLoGin LocalApicTimerMode::Periodic => { 317*70a4e555SLoGin self.data |= 0b01 << 17; 318*70a4e555SLoGin } 319*70a4e555SLoGin LocalApicTimerMode::Deadline => { 320*70a4e555SLoGin self.data |= 0b10 << 17; 321*70a4e555SLoGin } 322*70a4e555SLoGin } 323*70a4e555SLoGin return Ok(()); 324*70a4e555SLoGin } 325*70a4e555SLoGin _ => { 326*70a4e555SLoGin return Err(SystemError::EINVAL); 327*70a4e555SLoGin } 328*70a4e555SLoGin } 329*70a4e555SLoGin } 330*70a4e555SLoGin 331*70a4e555SLoGin /// 获取定时器模式 332*70a4e555SLoGin #[allow(dead_code)] 333*70a4e555SLoGin pub fn timer_mode(&self) -> Option<LocalApicTimerMode> { 334*70a4e555SLoGin if let LVTRegister::Timer = self.register { 335*70a4e555SLoGin let mode = (self.data >> 17) & 0b11; 336*70a4e555SLoGin match mode { 337*70a4e555SLoGin 0b00 => { 338*70a4e555SLoGin return Some(LocalApicTimerMode::Oneshot); 339*70a4e555SLoGin } 340*70a4e555SLoGin 0b01 => { 341*70a4e555SLoGin return Some(LocalApicTimerMode::Periodic); 342*70a4e555SLoGin } 343*70a4e555SLoGin 0b10 => { 344*70a4e555SLoGin return Some(LocalApicTimerMode::Deadline); 345*70a4e555SLoGin } 346*70a4e555SLoGin _ => { 347*70a4e555SLoGin return None; 348*70a4e555SLoGin } 349*70a4e555SLoGin } 350*70a4e555SLoGin } 351*70a4e555SLoGin return None; 352*70a4e555SLoGin } 353*70a4e555SLoGin } 354*70a4e555SLoGin 355*70a4e555SLoGin /// @brief 356*70a4e555SLoGin #[allow(dead_code)] 357*70a4e555SLoGin #[derive(Debug, PartialEq)] 358*70a4e555SLoGin pub enum DeliveryMode { 359*70a4e555SLoGin /// 由LVT寄存器的向量号区域指定中断向量号 360*70a4e555SLoGin Fixed = 0b000, 361*70a4e555SLoGin /// 通过处理器的SMI信号线,向处理器投递SMI中断请求。 362*70a4e555SLoGin /// 由于兼容性的原因,使用此投递模式时,LVT的中断向量号区域必须设置为0。 363*70a4e555SLoGin SMI = 0b010, 364*70a4e555SLoGin /// 向处理器投递不可屏蔽中断,并忽略向量号区域 365*70a4e555SLoGin NMI = 0b100, 366*70a4e555SLoGin /// 向处理器投递INIT中断请求,处理器会执行初始化的过程。 367*70a4e555SLoGin /// 由于兼容性的原因,使用此投递模式时,LVT的中断向量号区域必须设置为0。 368*70a4e555SLoGin /// CMCI、温度传感器、性能监控计数器等寄存器均不支持INIT投递模式 369*70a4e555SLoGin INIT = 0b101, 370*70a4e555SLoGin 371*70a4e555SLoGin /// 向目标处理器投递Start-Up IPI。 372*70a4e555SLoGin /// 373*70a4e555SLoGin /// 这个向量通常由多核引导模块调用(请参阅Intel开发手册Volume3 Section 8.4, 374*70a4e555SLoGin /// Multiple-Processor (MP) Initialization)。 375*70a4e555SLoGin /// 如果源APIC无法投递这个IPI,它不会自动重发。如果Start-Up IPI未成功投递, 376*70a4e555SLoGin /// 则交由软件决定是否在必要时重新投递SIPI 377*70a4e555SLoGin StartUp = 0b110, 378*70a4e555SLoGin 379*70a4e555SLoGin /// ExtINT模式可以将类8259A中断控制器产生的中断请求投递到处理器,并接收类 380*70a4e555SLoGin /// 8259A中断控制器提供的中断向量号。 381*70a4e555SLoGin /// CMCI、温度传感器、性能监控计数器等寄存器均不支持ExtINT投递模式 382*70a4e555SLoGin ExtINT = 0b111, 383*70a4e555SLoGin } 384*70a4e555SLoGin 385*70a4e555SLoGin impl TryFrom<u8> for DeliveryMode { 386*70a4e555SLoGin type Error = SystemError; 387*70a4e555SLoGin 388*70a4e555SLoGin fn try_from(value: u8) -> Result<Self, Self::Error> { 389*70a4e555SLoGin match value { 390*70a4e555SLoGin 0b000 => { 391*70a4e555SLoGin return Ok(DeliveryMode::Fixed); 392*70a4e555SLoGin } 393*70a4e555SLoGin 0b010 => { 394*70a4e555SLoGin return Ok(DeliveryMode::SMI); 395*70a4e555SLoGin } 396*70a4e555SLoGin 0b100 => { 397*70a4e555SLoGin return Ok(DeliveryMode::NMI); 398*70a4e555SLoGin } 399*70a4e555SLoGin 0b101 => { 400*70a4e555SLoGin return Ok(DeliveryMode::INIT); 401*70a4e555SLoGin } 402*70a4e555SLoGin 0b110 => { 403*70a4e555SLoGin return Ok(DeliveryMode::StartUp); 404*70a4e555SLoGin } 405*70a4e555SLoGin 0b111 => { 406*70a4e555SLoGin return Ok(DeliveryMode::ExtINT); 407*70a4e555SLoGin } 408*70a4e555SLoGin _ => { 409*70a4e555SLoGin return Err(SystemError::EINVAL); 410*70a4e555SLoGin } 411*70a4e555SLoGin } 412*70a4e555SLoGin } 413*70a4e555SLoGin } 414*70a4e555SLoGin 415*70a4e555SLoGin /// @brief 投递状态 416*70a4e555SLoGin #[derive(Debug)] 417*70a4e555SLoGin #[allow(dead_code)] 418*70a4e555SLoGin pub enum DeliveryStatus { 419*70a4e555SLoGin /// 空闲态。 420*70a4e555SLoGin /// 此状态表明,当前中断源未产生中断,或者产生的中断已经投递到处理器,并被处理器处理。 421*70a4e555SLoGin Idle = 0, 422*70a4e555SLoGin /// 发送挂起状态。 423*70a4e555SLoGin /// 此状态表明,中断源产生的请求已经投递至处理器,但尚未被处理器处理。 424*70a4e555SLoGin SendPending = 1, 425*70a4e555SLoGin } 426*70a4e555SLoGin 427*70a4e555SLoGin impl DeliveryStatus { 428*70a4e555SLoGin pub fn from(data: u32) -> Self { 429*70a4e555SLoGin if data & (1 << 12) == 0 { 430*70a4e555SLoGin return DeliveryStatus::Idle; 431*70a4e555SLoGin } else { 432*70a4e555SLoGin return DeliveryStatus::SendPending; 433*70a4e555SLoGin } 434*70a4e555SLoGin } 435*70a4e555SLoGin } 436*70a4e555SLoGin 437*70a4e555SLoGin /// IPI Trigger Mode 438*70a4e555SLoGin #[derive(Debug, Eq, PartialEq)] 439*70a4e555SLoGin #[repr(u64)] 440*70a4e555SLoGin pub enum TriggerMode { 441*70a4e555SLoGin Edge = 0, 442*70a4e555SLoGin Level = 1, 443*70a4e555SLoGin } 444*70a4e555SLoGin 445*70a4e555SLoGin #[derive(Debug)] 446*70a4e555SLoGin pub struct CurrentApic; 447*70a4e555SLoGin 448*70a4e555SLoGin impl CurrentApic { 449*70a4e555SLoGin /// x2apic是否启用 450*70a4e555SLoGin pub fn x2apic_enabled(&self) -> bool { 451*70a4e555SLoGin return LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic; 452*70a4e555SLoGin } 453*70a4e555SLoGin 454*70a4e555SLoGin pub(self) unsafe fn write_xapic_register(&self, reg: XApicOffset, value: u32) { 455*70a4e555SLoGin current_xapic_instance().borrow_mut().as_mut().map(|xapic| { 456*70a4e555SLoGin xapic.write(reg, value); 457*70a4e555SLoGin }); 458*70a4e555SLoGin } 459*70a4e555SLoGin 460*70a4e555SLoGin /// 屏蔽类8259A芯片 461*70a4e555SLoGin unsafe fn mask8259a(&self) { 462*70a4e555SLoGin CurrentPortIOArch::out8(0x21, 0xff); 463*70a4e555SLoGin CurrentPortIOArch::out8(0xa1, 0xff); 464*70a4e555SLoGin 465*70a4e555SLoGin // 写入8259A pic的EOI位 466*70a4e555SLoGin CurrentPortIOArch::out8(0x20, 0x20); 467*70a4e555SLoGin CurrentPortIOArch::out8(0xa0, 0x20); 468*70a4e555SLoGin 469*70a4e555SLoGin kdebug!("8259A Masked."); 470*70a4e555SLoGin 471*70a4e555SLoGin // enable IMCR 472*70a4e555SLoGin CurrentPortIOArch::out8(0x22, 0x70); 473*70a4e555SLoGin CurrentPortIOArch::out8(0x23, 0x01); 474*70a4e555SLoGin } 475*70a4e555SLoGin } 476*70a4e555SLoGin 477*70a4e555SLoGin impl LocalAPIC for CurrentApic { 478*70a4e555SLoGin fn support() -> bool { 479*70a4e555SLoGin true 480*70a4e555SLoGin } 481*70a4e555SLoGin 482*70a4e555SLoGin fn init_current_cpu(&mut self) -> bool { 483*70a4e555SLoGin let cpu_id = smp_get_processor_id(); 484*70a4e555SLoGin if cpu_id == 0 { 485*70a4e555SLoGin unsafe { 486*70a4e555SLoGin self.mask8259a(); 487*70a4e555SLoGin } 488*70a4e555SLoGin } 489*70a4e555SLoGin kinfo!("Initializing apic for cpu {}", cpu_id); 490*70a4e555SLoGin if X2Apic::support() && X2Apic.init_current_cpu() { 491*70a4e555SLoGin if cpu_id == 0 { 492*70a4e555SLoGin LOCAL_APIC_ENABLE_TYPE.store(LocalApicEnableType::X2Apic, Ordering::SeqCst); 493*70a4e555SLoGin } 494*70a4e555SLoGin kinfo!("x2APIC initialized for cpu {}", cpu_id); 495*70a4e555SLoGin } else { 496*70a4e555SLoGin kinfo!("x2APIC not supported or failed to initialize, fallback to xAPIC."); 497*70a4e555SLoGin if cpu_id == 0 { 498*70a4e555SLoGin LOCAL_APIC_ENABLE_TYPE.store(LocalApicEnableType::XApic, Ordering::SeqCst); 499*70a4e555SLoGin } 500*70a4e555SLoGin let apic_base = 501*70a4e555SLoGin PhysAddr::new(unsafe { x86::msr::rdmsr(IA32_APIC_BASE) as usize & 0xFFFF_0000 }); 502*70a4e555SLoGin let xapic_instance = unsafe { XApic::new(apic_base) }; 503*70a4e555SLoGin 504*70a4e555SLoGin let mut cur = current_xapic_instance().borrow_mut(); 505*70a4e555SLoGin if cur.is_none() { 506*70a4e555SLoGin *cur = Some(xapic_instance); 507*70a4e555SLoGin } else { 508*70a4e555SLoGin panic!("xapic instance already initialized."); 509*70a4e555SLoGin } 510*70a4e555SLoGin 511*70a4e555SLoGin if let Some(xapic) = cur.as_mut() { 512*70a4e555SLoGin xapic.init_current_cpu(); 513*70a4e555SLoGin } 514*70a4e555SLoGin 515*70a4e555SLoGin kinfo!("xAPIC initialized for cpu {}", cpu_id); 516*70a4e555SLoGin } 517*70a4e555SLoGin if cpu_id == 0 { 518*70a4e555SLoGin ioapic_init(); 519*70a4e555SLoGin } 520*70a4e555SLoGin kinfo!("Apic initialized."); 521*70a4e555SLoGin return true; 522*70a4e555SLoGin } 523*70a4e555SLoGin 524*70a4e555SLoGin fn send_eoi(&self) { 525*70a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 526*70a4e555SLoGin X2Apic.send_eoi(); 527*70a4e555SLoGin } else { 528*70a4e555SLoGin current_xapic_instance().borrow().as_ref().map(|xapic| { 529*70a4e555SLoGin xapic.send_eoi(); 530*70a4e555SLoGin }); 531*70a4e555SLoGin } 532*70a4e555SLoGin } 533*70a4e555SLoGin 534*70a4e555SLoGin fn version(&self) -> u8 { 535*70a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 536*70a4e555SLoGin return X2Apic.version(); 537*70a4e555SLoGin } else { 538*70a4e555SLoGin return current_xapic_instance() 539*70a4e555SLoGin .borrow() 540*70a4e555SLoGin .as_ref() 541*70a4e555SLoGin .map(|xapic| xapic.version()) 542*70a4e555SLoGin .unwrap_or(0); 543*70a4e555SLoGin } 544*70a4e555SLoGin } 545*70a4e555SLoGin 546*70a4e555SLoGin fn support_eoi_broadcast_suppression(&self) -> bool { 547*70a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 548*70a4e555SLoGin return X2Apic.support_eoi_broadcast_suppression(); 549*70a4e555SLoGin } else { 550*70a4e555SLoGin return current_xapic_instance() 551*70a4e555SLoGin .borrow() 552*70a4e555SLoGin .as_ref() 553*70a4e555SLoGin .map(|xapic| xapic.support_eoi_broadcast_suppression()) 554*70a4e555SLoGin .unwrap_or(false); 555*70a4e555SLoGin } 556*70a4e555SLoGin } 557*70a4e555SLoGin 558*70a4e555SLoGin fn max_lvt_entry(&self) -> u8 { 559*70a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 560*70a4e555SLoGin return X2Apic.max_lvt_entry(); 561*70a4e555SLoGin } else { 562*70a4e555SLoGin return current_xapic_instance() 563*70a4e555SLoGin .borrow() 564*70a4e555SLoGin .as_ref() 565*70a4e555SLoGin .map(|xapic| xapic.max_lvt_entry()) 566*70a4e555SLoGin .unwrap_or(0); 567*70a4e555SLoGin } 568*70a4e555SLoGin } 569*70a4e555SLoGin 570*70a4e555SLoGin fn id(&self) -> u32 { 571*70a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 572*70a4e555SLoGin return X2Apic.id(); 573*70a4e555SLoGin } else { 574*70a4e555SLoGin return current_xapic_instance() 575*70a4e555SLoGin .borrow() 576*70a4e555SLoGin .as_ref() 577*70a4e555SLoGin .map(|xapic| xapic.id()) 578*70a4e555SLoGin .unwrap_or(0); 579*70a4e555SLoGin } 580*70a4e555SLoGin } 581*70a4e555SLoGin 582*70a4e555SLoGin fn set_lvt(&mut self, lvt: LVT) { 583*70a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 584*70a4e555SLoGin X2Apic.set_lvt(lvt); 585*70a4e555SLoGin } else { 586*70a4e555SLoGin current_xapic_instance().borrow_mut().as_mut().map(|xapic| { 587*70a4e555SLoGin xapic.set_lvt(lvt); 588*70a4e555SLoGin }); 589*70a4e555SLoGin } 590*70a4e555SLoGin } 591*70a4e555SLoGin 592*70a4e555SLoGin fn read_lvt(&self, reg: LVTRegister) -> LVT { 593*70a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 594*70a4e555SLoGin return X2Apic.read_lvt(reg); 595*70a4e555SLoGin } else { 596*70a4e555SLoGin return current_xapic_instance() 597*70a4e555SLoGin .borrow() 598*70a4e555SLoGin .as_ref() 599*70a4e555SLoGin .map(|xapic| xapic.read_lvt(reg)) 600*70a4e555SLoGin .expect("xapic instance not initialized."); 601*70a4e555SLoGin } 602*70a4e555SLoGin } 603*70a4e555SLoGin 604*70a4e555SLoGin fn mask_all_lvt(&mut self) { 605*70a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 606*70a4e555SLoGin X2Apic.mask_all_lvt(); 607*70a4e555SLoGin } else { 608*70a4e555SLoGin current_xapic_instance().borrow_mut().as_mut().map(|xapic| { 609*70a4e555SLoGin xapic.mask_all_lvt(); 610*70a4e555SLoGin }); 611*70a4e555SLoGin } 612*70a4e555SLoGin } 613*70a4e555SLoGin 614*70a4e555SLoGin fn write_icr(&self, icr: Icr) { 615*70a4e555SLoGin if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { 616*70a4e555SLoGin X2Apic.write_icr(icr); 617*70a4e555SLoGin } else { 618*70a4e555SLoGin current_xapic_instance().borrow().as_ref().map(|xapic| { 619*70a4e555SLoGin xapic.write_icr(icr); 620*70a4e555SLoGin }); 621*70a4e555SLoGin } 622*70a4e555SLoGin } 623*70a4e555SLoGin } 624