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