1 use core::ptr::NonNull; 2 3 use acpi::madt::Madt; 4 use alloc::sync::Arc; 5 use bit_field::BitField; 6 use bitflags::bitflags; 7 use log::{debug, info}; 8 use system_error::SystemError; 9 10 use crate::{ 11 driver::acpi::acpi_manager, 12 exception::{ 13 handle::{edge_irq_handler, fast_eoi_irq_handler}, 14 irqchip::{IrqChip, IrqChipData, IrqChipFlags, IrqChipSetMaskResult, IrqChipState}, 15 irqdata::{IrqData, IrqLineStatus}, 16 irqdesc::{irq_desc_manager, IrqDesc, IrqFlowHandler}, 17 manage::irq_manager, 18 IrqNumber, 19 }, 20 libs::{ 21 cpumask::CpuMask, 22 once::Once, 23 spinlock::{SpinLock, SpinLockGuard}, 24 volatile::{volwrite, Volatile}, 25 }, 26 mm::{ 27 mmio_buddy::{mmio_pool, MMIOSpaceGuard}, 28 PhysAddr, 29 }, 30 }; 31 32 use super::{CurrentApic, LocalAPIC}; 33 34 static mut __IOAPIC: Option<SpinLock<IoApic>> = None; 35 static mut IOAPIC_IR_CHIP: Option<Arc<IoApicChip>> = None; 36 37 #[allow(non_snake_case)] 38 fn IOAPIC() -> &'static SpinLock<IoApic> { 39 unsafe { __IOAPIC.as_ref().unwrap() } 40 } 41 42 #[inline(always)] 43 pub(super) fn ioapic_ir_chip() -> Arc<dyn IrqChip> { 44 unsafe { IOAPIC_IR_CHIP.as_ref().unwrap().clone() } 45 } 46 47 #[allow(dead_code)] 48 pub struct IoApic { 49 reg: *mut u32, 50 data: *mut u32, 51 virt_eoi: *mut u32, 52 phys_base: PhysAddr, 53 mmio_guard: MMIOSpaceGuard, 54 } 55 56 impl IoApic { 57 /// IO APIC的中断向量号从32开始 58 pub const VECTOR_BASE: u8 = 32; 59 60 /// Create a new IOAPIC. 61 /// 62 /// # Safety 63 /// 64 /// You must provide a valid address. 65 pub unsafe fn new() -> Self { 66 static INIT_STATE: Once = Once::new(); 67 assert!(!INIT_STATE.is_completed()); 68 69 let mut result: Option<IoApic> = None; 70 INIT_STATE.call_once(|| { 71 info!("Initializing ioapic..."); 72 73 // get ioapic base from acpi 74 75 let madt = acpi_manager() 76 .tables() 77 .unwrap() 78 .find_table::<Madt>() 79 .expect("IoApic::new(): failed to find MADT"); 80 81 let io_apic_paddr = madt 82 .entries() 83 .find(|x| { 84 if let acpi::madt::MadtEntry::IoApic(_x) = x { 85 return true; 86 } 87 return false; 88 }) 89 .and_then(|x| { 90 if let acpi::madt::MadtEntry::IoApic(x) = x { 91 Some(x.io_apic_address) 92 } else { 93 None 94 } 95 }) 96 .unwrap(); 97 98 let phys_base = PhysAddr::new(io_apic_paddr as usize); 99 100 let mmio_guard = mmio_pool() 101 .create_mmio(0x1000) 102 .expect("IoApic::new(): failed to create mmio"); 103 assert!( 104 mmio_guard.map_phys(phys_base, 0x1000).is_ok(), 105 "IoApic::new(): failed to map phys" 106 ); 107 debug!("Ioapic map ok"); 108 let reg = mmio_guard.vaddr(); 109 110 result = Some(IoApic { 111 reg: reg.data() as *mut u32, 112 data: (reg + 0x10).data() as *mut u32, 113 virt_eoi: (reg + 0x40).data() as *mut u32, 114 phys_base, 115 mmio_guard, 116 }); 117 debug!("IOAPIC: to mask all RTE"); 118 // 屏蔽所有的RTE 119 let res_mut = result.as_mut().unwrap(); 120 for i in 0..res_mut.supported_interrupts() { 121 res_mut.write_rte(i, 0x20 + i, RedirectionEntry::DISABLED, 0); 122 } 123 debug!("Ioapic init done"); 124 }); 125 126 assert!( 127 result.is_some(), 128 "Failed to init ioapic, maybe this is a double initialization bug?" 129 ); 130 return result.unwrap(); 131 } 132 133 /// Disable all interrupts. 134 #[allow(dead_code)] 135 pub fn disable_all(&mut self) { 136 // Mark all interrupts edge-triggered, active high, disabled, 137 // and not routed to any CPUs. 138 for i in 0..self.supported_interrupts() { 139 self.disable(i); 140 } 141 } 142 143 unsafe fn read(&mut self, reg: u8) -> u32 { 144 assert!(!(0x3..REG_TABLE).contains(®)); 145 self.reg.write_volatile(reg as u32); 146 self.data.read_volatile() 147 } 148 149 /// 直接写入REG_TABLE内的寄存器 150 /// 151 /// ## 参数 152 /// 153 /// * `reg` - 寄存器下标 154 /// * `data` - 寄存器数据 155 unsafe fn write(&mut self, reg: u8, data: u32) { 156 // 0x1 & 0x2 are read-only regs 157 assert!(!(0x1..REG_TABLE).contains(®)); 158 self.reg.write_volatile(reg as u32); 159 self.data.write_volatile(data); 160 } 161 162 fn write_rte(&mut self, rte_index: u8, vector: u8, flags: RedirectionEntry, dest: u8) { 163 unsafe { 164 self.write(REG_TABLE + 2 * rte_index, vector as u32 | flags.bits()); 165 self.write(REG_TABLE + 2 * rte_index + 1, (dest as u32) << 24); 166 } 167 } 168 169 /// 标记中断边沿触发、高电平有效、 170 /// 启用并路由到给定的 cpunum,即是是该 cpu 的 APIC ID(不是cpuid) 171 pub fn enable(&mut self, rte_index: u8) { 172 let mut val = unsafe { self.read(REG_TABLE + 2 * rte_index) }; 173 val &= !RedirectionEntry::DISABLED.bits(); 174 unsafe { self.write(REG_TABLE + 2 * rte_index, val) }; 175 } 176 177 pub fn disable(&mut self, rte_index: u8) { 178 let reg = REG_TABLE + 2 * rte_index; 179 let mut val = unsafe { self.read(reg) }; 180 val |= RedirectionEntry::DISABLED.bits(); 181 unsafe { self.write(reg, val) }; 182 } 183 184 /// 安装中断 185 /// 186 /// ## 参数 187 /// 188 /// * `rte_index` - RTE下标 189 /// * `vector` - 中断向量号 190 /// * `dest` - 目标CPU的APIC ID 191 /// * `level_triggered` - 是否为电平触发 192 /// * `active_high` - 是否为高电平有效 193 /// * `dest_logic` - 是否为逻辑模式 194 /// * `mask` - 是否屏蔽 195 #[allow(clippy::too_many_arguments)] 196 pub fn install( 197 &mut self, 198 rte_index: u8, 199 vector: u8, 200 dest: u8, 201 level_triggered: bool, 202 active_high: bool, 203 dest_logic: bool, 204 mut mask: bool, 205 ) -> Result<(), SystemError> { 206 // 重定向表从 REG_TABLE 开始,使用两个寄存器来配置每个中断。 207 // 一对中的第一个(低位)寄存器包含配置位。32bit 208 // 第二个(高)寄存器包含一个位掩码,告诉哪些 CPU 可以服务该中断。 209 // level_triggered:如果为真,表示中断触发方式为电平触发(level-triggered),则将RedirectionEntry::LEVEL标志位设置在flags中。 210 // active_high:如果为假,表示中断的极性为低电平有效(active-low),则将RedirectionEntry::ACTIVELOW标志位设置在flags中。 211 // dest_logic:如果为真,表示中断目标为逻辑模式(logical mode),则将RedirectionEntry::LOGICAL标志位设置在flags中。 212 // !(0x20..=0xef).contains(&vector):判断中断向量号(vector)是否在范围0x20到0xef之外,如果是,则表示中断无效,将mask标志位设置为真。 213 // mask:如果为真,表示中断被屏蔽(masked),将RedirectionEntry::DISABLED标志位设置在flags中。 214 let mut flags = RedirectionEntry::NONE; 215 if level_triggered { 216 flags |= RedirectionEntry::LEVEL; 217 } 218 if !active_high { 219 flags |= RedirectionEntry::ACTIVELOW; 220 } 221 if dest_logic { 222 flags |= RedirectionEntry::LOGICAL; 223 } 224 if !(0x20..=0xef).contains(&vector) { 225 mask = true; 226 } 227 if mask { 228 flags |= RedirectionEntry::DISABLED; 229 } 230 self.write_rte(rte_index, vector, flags, dest); 231 return Ok(()); 232 } 233 234 /// Get the vector number for the given IRQ. 235 #[allow(dead_code)] 236 pub fn irq_vector(&mut self, irq: u8) -> u8 { 237 unsafe { self.read(REG_TABLE + 2 * irq).get_bits(0..8) as u8 } 238 } 239 240 /// Set the vector number for the given IRQ. 241 #[allow(dead_code)] 242 pub fn set_irq_vector(&mut self, irq: u8, vector: u8) { 243 let mut old = unsafe { self.read(REG_TABLE + 2 * irq) }; 244 let old_vector = old.get_bits(0..8); 245 if !(0x20..=0xfe).contains(&old_vector) { 246 old |= RedirectionEntry::DISABLED.bits(); 247 } 248 unsafe { 249 self.write(REG_TABLE + 2 * irq, *old.set_bits(0..8, vector as u32)); 250 } 251 } 252 253 #[allow(dead_code)] 254 pub fn id(&mut self) -> u8 { 255 unsafe { self.read(REG_ID).get_bits(24..28) as u8 } 256 } 257 258 /// IO APIC Version 259 #[allow(dead_code)] 260 pub fn version(&mut self) -> u8 { 261 unsafe { self.read(REG_VER).get_bits(0..8) as u8 } 262 } 263 264 /// Number of supported interrupts by this IO APIC. 265 /// 266 /// Max Redirection Entry = "how many IRQs can this I/O APIC handle - 1" 267 /// The -1 is silly so we add one back to it. 268 pub fn supported_interrupts(&mut self) -> u8 { 269 unsafe { (self.read(REG_VER).get_bits(16..24) + 1) as u8 } 270 } 271 272 pub fn pending(&mut self, irq: u8) -> bool { 273 let rte_index = Self::vector_rte_index(irq); 274 let data = unsafe { self.read(REG_TABLE + 2 * rte_index) }; 275 data & (1 << 12) != 0 276 } 277 278 fn vector_rte_index(irq_num: u8) -> u8 { 279 assert!(irq_num >= Self::VECTOR_BASE); 280 irq_num - Self::VECTOR_BASE 281 } 282 283 /// 电平响应 284 #[allow(dead_code)] 285 fn level_ack(&mut self, irq_num: u8) { 286 #[repr(C)] 287 struct LevelAck { 288 virt_eoi: Volatile<u32>, 289 } 290 291 let p = NonNull::new(self.virt_eoi as *mut LevelAck).unwrap(); 292 293 unsafe { 294 volwrite!(p, virt_eoi, irq_num as u32); 295 } 296 } 297 } 298 299 /// Register index: ID 300 const REG_ID: u8 = 0x00; 301 /// 获取IO APIC Version 302 const REG_VER: u8 = 0x01; 303 /// Redirection table base 304 const REG_TABLE: u8 = 0x10; 305 306 bitflags! { 307 /// The redirection table starts at REG_TABLE and uses 308 /// two registers to configure each interrupt. 309 /// The first (low) register in a pair contains configuration bits. 310 /// The second (high) register contains a bitmask telling which 311 /// CPUs can serve that interrupt. 312 struct RedirectionEntry: u32 { 313 /// Interrupt disabled 314 const DISABLED = 0x00010000; 315 /// Level-triggered (vs edge-) 316 const LEVEL = 0x00008000; 317 /// Active low (vs high) 318 const ACTIVELOW = 0x00002000; 319 /// Destination is CPU id (vs APIC ID) 320 const LOGICAL = 0x00000800; 321 /// None 322 const NONE = 0x00000000; 323 } 324 } 325 326 #[derive(Debug)] 327 struct IoApicChipData { 328 inner: SpinLock<InnerIoApicChipData>, 329 } 330 331 impl IrqChipData for IoApicChipData { 332 fn as_any_ref(&self) -> &dyn core::any::Any { 333 self 334 } 335 } 336 337 impl IoApicChipData { 338 const fn default() -> Self { 339 Self::new(0, 0, 0, false, false, false, true) 340 } 341 342 const fn new( 343 rte_index: u8, 344 vector: u8, 345 dest: u8, 346 level_triggered: bool, 347 active_high: bool, 348 dest_logic: bool, 349 mask: bool, 350 ) -> Self { 351 IoApicChipData { 352 inner: SpinLock::new(InnerIoApicChipData { 353 rte_index, 354 vector, 355 dest, 356 level_triggered, 357 active_high, 358 dest_logic, 359 mask, 360 }), 361 } 362 } 363 364 fn inner(&self) -> SpinLockGuard<InnerIoApicChipData> { 365 self.inner.lock_irqsave() 366 } 367 } 368 369 #[derive(Debug)] 370 struct InnerIoApicChipData { 371 rte_index: u8, 372 vector: u8, 373 dest: u8, 374 level_triggered: bool, 375 active_high: bool, 376 dest_logic: bool, 377 mask: bool, 378 } 379 380 impl InnerIoApicChipData { 381 /// 把中断数据同步到芯片 382 fn sync_to_chip(&self) -> Result<(), SystemError> { 383 ioapic_install( 384 self.vector, 385 self.dest, 386 self.level_triggered, 387 self.active_high, 388 self.dest_logic, 389 self.mask, 390 ) 391 } 392 } 393 394 #[inline(never)] 395 pub fn ioapic_init(ignore: &'static [IrqNumber]) { 396 info!("Initializing ioapic..."); 397 let ioapic = unsafe { IoApic::new() }; 398 unsafe { 399 __IOAPIC = Some(SpinLock::new(ioapic)); 400 } 401 unsafe { 402 IOAPIC_IR_CHIP = Some(Arc::new(IoApicChip)); 403 } 404 405 // 绑定irqchip 406 for i in IoApic::VECTOR_BASE as u32..256 { 407 let irq = IrqNumber::new(i); 408 409 if ignore.contains(&irq) { 410 continue; 411 } 412 413 let desc = irq_desc_manager().lookup(irq).unwrap(); 414 let irq_data = desc.irq_data(); 415 let mut chip_info_guard = irq_data.chip_info_write_irqsave(); 416 chip_info_guard.set_chip(Some(ioapic_ir_chip())); 417 let chip_data = IoApicChipData::default(); 418 chip_data.inner().rte_index = IoApic::vector_rte_index(i as u8); 419 chip_data.inner().vector = i as u8; 420 chip_info_guard.set_chip_data(Some(Arc::new(chip_data))); 421 drop(chip_info_guard); 422 let level = irq_data.is_level_type(); 423 424 register_handler(&desc, level); 425 } 426 427 info!("IO Apic initialized."); 428 } 429 430 fn register_handler(desc: &Arc<IrqDesc>, level_triggered: bool) { 431 let fasteoi: bool = if level_triggered { 432 desc.modify_status(IrqLineStatus::empty(), IrqLineStatus::IRQ_LEVEL); 433 true 434 } else { 435 desc.modify_status(IrqLineStatus::IRQ_LEVEL, IrqLineStatus::empty()); 436 false 437 }; 438 439 let handler: &dyn IrqFlowHandler = if fasteoi { 440 fast_eoi_irq_handler() 441 } else { 442 edge_irq_handler() 443 }; 444 desc.set_handler(handler); 445 } 446 447 /// 安装中断 448 /// 449 /// ## 参数 450 /// 451 /// * `vector` - 中断向量号 452 /// * `dest` - 目标CPU的APIC ID 453 /// * `level_triggered` - 是否为电平触发 454 /// * `active_high` - 是否为高电平有效 455 /// * `dest_logic` - 是否为逻辑模式 456 /// * `mask` - 是否屏蔽 457 fn ioapic_install( 458 vector: u8, 459 dest: u8, 460 level_triggered: bool, 461 active_high: bool, 462 dest_logic: bool, 463 mask: bool, 464 ) -> Result<(), SystemError> { 465 let rte_index = IoApic::vector_rte_index(vector); 466 return IOAPIC().lock_irqsave().install( 467 rte_index, 468 vector, 469 dest, 470 level_triggered, 471 active_high, 472 dest_logic, 473 mask, 474 ); 475 } 476 477 /// IoApic中断芯片 478 /// 479 /// https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/io_apic.c#1994 480 #[derive(Debug)] 481 struct IoApicChip; 482 483 impl IrqChip for IoApicChip { 484 fn name(&self) -> &'static str { 485 "IR-IO-APIC" 486 } 487 488 fn irq_startup(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> { 489 self.irq_unmask(irq) 490 } 491 492 fn irq_mask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> { 493 let binding = irq 494 .chip_info_read_irqsave() 495 .chip_data() 496 .ok_or(SystemError::EINVAL)?; 497 let chip_data = binding 498 .as_any_ref() 499 .downcast_ref::<IoApicChipData>() 500 .ok_or(SystemError::EINVAL)?; 501 502 let mut chip_data_inner = chip_data.inner(); 503 chip_data_inner.mask = true; 504 chip_data_inner.sync_to_chip().ok(); 505 506 drop(chip_data_inner); 507 508 return Ok(()); 509 } 510 511 fn can_set_affinity(&self) -> bool { 512 true 513 } 514 515 fn can_set_flow_type(&self) -> bool { 516 true 517 } 518 519 fn irq_set_type( 520 &self, 521 irq: &Arc<IrqData>, 522 flow_type: IrqLineStatus, 523 ) -> Result<IrqChipSetMaskResult, SystemError> { 524 let binding = irq 525 .chip_info_read_irqsave() 526 .chip_data() 527 .ok_or(SystemError::EINVAL)?; 528 let chip_data = binding 529 .as_any_ref() 530 .downcast_ref::<IoApicChipData>() 531 .ok_or(SystemError::EINVAL)?; 532 let mut chip_data_inner = chip_data.inner(); 533 534 let level_triggered = flow_type.is_level_type(); 535 let active_high = flow_type.is_level_high().unwrap_or(false); 536 chip_data_inner.active_high = active_high; 537 chip_data_inner.level_triggered = level_triggered; 538 chip_data_inner.sync_to_chip()?; 539 540 return Ok(IrqChipSetMaskResult::Success); 541 } 542 543 fn irq_set_affinity( 544 &self, 545 irq: &Arc<IrqData>, 546 cpu: &CpuMask, 547 _force: bool, 548 ) -> Result<IrqChipSetMaskResult, SystemError> { 549 // 使用mask的第1个可用CPU 550 let dest = (cpu.first().ok_or(SystemError::EINVAL)?.data() & 0xff) as u8; 551 552 let binding = irq 553 .chip_info_read_irqsave() 554 .chip_data() 555 .ok_or(SystemError::EINVAL)?; 556 let chip_data = binding 557 .as_any_ref() 558 .downcast_ref::<IoApicChipData>() 559 .ok_or(SystemError::EINVAL)?; 560 561 let mut chip_data_inner = chip_data.inner(); 562 let origin_dest = chip_data_inner.dest; 563 if origin_dest == dest { 564 return Ok(IrqChipSetMaskResult::Success); 565 } 566 567 chip_data_inner.dest = dest; 568 569 chip_data_inner.sync_to_chip()?; 570 571 return Ok(IrqChipSetMaskResult::Success); 572 } 573 574 fn irq_unmask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> { 575 IOAPIC() 576 .lock_irqsave() 577 .enable(IoApic::vector_rte_index(irq.irq().data() as u8)); 578 Ok(()) 579 } 580 581 fn can_mask_ack(&self) -> bool { 582 true 583 } 584 585 fn irq_mask_ack(&self, irq: &Arc<IrqData>) { 586 self.irq_mask(irq).ok(); 587 self.irq_eoi(irq); 588 } 589 590 fn irq_eoi(&self, irq: &Arc<IrqData>) { 591 if irq.is_level_type() { 592 IOAPIC().lock_irqsave().level_ack(irq.irq().data() as u8); 593 } else { 594 CurrentApic.send_eoi(); 595 } 596 } 597 598 fn retrigger(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> { 599 irq_manager().irq_chip_retrigger_hierarchy(irq_data) 600 } 601 602 fn irqchip_state(&self, irq: &Arc<IrqData>, which: IrqChipState) -> Result<bool, SystemError> { 603 let binding = irq 604 .chip_info_read_irqsave() 605 .chip_data() 606 .ok_or(SystemError::EINVAL)?; 607 let chip_data = binding 608 .as_any_ref() 609 .downcast_ref::<IoApicChipData>() 610 .ok_or(SystemError::EINVAL)?; 611 612 match which { 613 IrqChipState::Pending => { 614 return Ok(IOAPIC().lock_irqsave().pending(irq.irq().data() as u8)); 615 } 616 IrqChipState::Active => { 617 let chip_data_inner = chip_data.inner(); 618 return Ok(!chip_data_inner.mask); 619 } 620 IrqChipState::Masked => { 621 let chip_data_inner = chip_data.inner(); 622 return Ok(chip_data_inner.mask); 623 } 624 IrqChipState::LineLevel => { 625 let chip_data_inner = chip_data.inner(); 626 return Ok(chip_data_inner.active_high); 627 } 628 #[allow(unreachable_patterns)] 629 _ => { 630 return Err(SystemError::EINVAL); 631 } 632 } 633 } 634 635 fn irq_disable(&self, irq: &Arc<IrqData>) { 636 let binding = irq 637 .chip_info_read_irqsave() 638 .chip_data() 639 .ok_or(SystemError::EINVAL) 640 .unwrap(); 641 let chip_data = binding 642 .as_any_ref() 643 .downcast_ref::<IoApicChipData>() 644 .ok_or(SystemError::EINVAL) 645 .unwrap(); 646 let mut chip_data_inner = chip_data.inner(); 647 chip_data_inner.mask = true; 648 chip_data_inner.sync_to_chip().ok(); 649 } 650 651 fn irq_ack(&self, irq_data: &Arc<IrqData>) { 652 // irq_manager().irq_chip_ack_parent(irq_data); 653 self.irq_eoi(irq_data); 654 } 655 656 fn flags(&self) -> IrqChipFlags { 657 IrqChipFlags::IRQCHIP_SKIP_SET_WAKE | IrqChipFlags::IRQCHIP_AFFINITY_PRE_STARTUP 658 } 659 } 660