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 system_error::SystemError; 8 9 use crate::{ 10 driver::acpi::acpi_manager, 11 exception::{ 12 handle::{edge_irq_handler, fast_eoi_irq_handler}, 13 irqchip::{IrqChip, IrqChipData, IrqChipFlags, IrqChipSetMaskResult, IrqChipState}, 14 irqdata::{IrqData, IrqLineStatus}, 15 irqdesc::{irq_desc_manager, IrqDesc, IrqFlowHandler}, 16 manage::irq_manager, 17 IrqNumber, 18 }, 19 kdebug, kinfo, 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 kinfo!("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 .map(|x| { 90 if let acpi::madt::MadtEntry::IoApic(x) = x { 91 Some(x.io_apic_address) 92 } else { 93 None 94 } 95 }) 96 .flatten() 97 .unwrap(); 98 99 let phys_base = PhysAddr::new(io_apic_paddr as usize); 100 101 let mmio_guard = mmio_pool() 102 .create_mmio(0x1000) 103 .expect("IoApic::new(): failed to create mmio"); 104 assert!( 105 mmio_guard.map_phys(phys_base, 0x1000).is_ok(), 106 "IoApic::new(): failed to map phys" 107 ); 108 kdebug!("Ioapic map ok"); 109 let reg = mmio_guard.vaddr(); 110 111 result = Some(IoApic { 112 reg: reg.data() as *mut u32, 113 data: (reg + 0x10).data() as *mut u32, 114 virt_eoi: (reg + 0x40).data() as *mut u32, 115 phys_base, 116 mmio_guard, 117 }); 118 kdebug!("IOAPIC: to mask all RTE"); 119 // 屏蔽所有的RTE 120 let res_mut = result.as_mut().unwrap(); 121 for i in 0..res_mut.supported_interrupts() { 122 res_mut.write_rte(i, 0x20 + i, RedirectionEntry::DISABLED, 0); 123 } 124 kdebug!("Ioapic init done"); 125 }); 126 127 assert!( 128 result.is_some(), 129 "Failed to init ioapic, maybe this is a double initialization bug?" 130 ); 131 return result.unwrap(); 132 } 133 134 /// Disable all interrupts. 135 #[allow(dead_code)] 136 pub fn disable_all(&mut self) { 137 // Mark all interrupts edge-triggered, active high, disabled, 138 // and not routed to any CPUs. 139 for i in 0..self.supported_interrupts() { 140 self.disable(i); 141 } 142 } 143 144 unsafe fn read(&mut self, reg: u8) -> u32 { 145 assert!(!(0x3..REG_TABLE).contains(®)); 146 self.reg.write_volatile(reg as u32); 147 self.data.read_volatile() 148 } 149 150 /// 直接写入REG_TABLE内的寄存器 151 /// 152 /// ## 参数 153 /// 154 /// * `reg` - 寄存器下标 155 /// * `data` - 寄存器数据 156 unsafe fn write(&mut self, reg: u8, data: u32) { 157 // 0x1 & 0x2 are read-only regs 158 assert!(!(0x1..REG_TABLE).contains(®)); 159 self.reg.write_volatile(reg as u32); 160 self.data.write_volatile(data); 161 } 162 163 fn write_rte(&mut self, rte_index: u8, vector: u8, flags: RedirectionEntry, dest: u8) { 164 unsafe { 165 self.write(REG_TABLE + 2 * rte_index, vector as u32 | flags.bits()); 166 self.write(REG_TABLE + 2 * rte_index + 1, (dest as u32) << 24); 167 } 168 } 169 170 /// 标记中断边沿触发、高电平有效、 171 /// 启用并路由到给定的 cpunum,即是是该 cpu 的 APIC ID(不是cpuid) 172 pub fn enable(&mut self, rte_index: u8) { 173 let mut val = unsafe { self.read(REG_TABLE + 2 * rte_index) }; 174 val &= !RedirectionEntry::DISABLED.bits(); 175 unsafe { self.write(REG_TABLE + 2 * rte_index, val) }; 176 } 177 178 pub fn disable(&mut self, rte_index: u8) { 179 let reg = REG_TABLE + 2 * rte_index; 180 let mut val = unsafe { self.read(reg) }; 181 val |= RedirectionEntry::DISABLED.bits(); 182 unsafe { self.write(reg, val) }; 183 } 184 185 /// 安装中断 186 /// 187 /// ## 参数 188 /// 189 /// * `rte_index` - RTE下标 190 /// * `vector` - 中断向量号 191 /// * `dest` - 目标CPU的APIC ID 192 /// * `level_triggered` - 是否为电平触发 193 /// * `active_high` - 是否为高电平有效 194 /// * `dest_logic` - 是否为逻辑模式 195 /// * `mask` - 是否屏蔽 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 DEFAULT: Self = Self::new(0, 0, 0, false, false, false, true); 339 340 const fn new( 341 rte_index: u8, 342 vector: u8, 343 dest: u8, 344 level_triggered: bool, 345 active_high: bool, 346 dest_logic: bool, 347 mask: bool, 348 ) -> Self { 349 IoApicChipData { 350 inner: SpinLock::new(InnerIoApicChipData { 351 rte_index, 352 vector, 353 dest, 354 level_triggered, 355 active_high, 356 dest_logic, 357 mask, 358 }), 359 } 360 } 361 362 fn inner(&self) -> SpinLockGuard<InnerIoApicChipData> { 363 self.inner.lock_irqsave() 364 } 365 } 366 367 #[derive(Debug)] 368 struct InnerIoApicChipData { 369 rte_index: u8, 370 vector: u8, 371 dest: u8, 372 level_triggered: bool, 373 active_high: bool, 374 dest_logic: bool, 375 mask: bool, 376 } 377 378 impl InnerIoApicChipData { 379 /// 把中断数据同步到芯片 380 fn sync_to_chip(&self) -> Result<(), SystemError> { 381 ioapic_install( 382 self.vector, 383 self.dest, 384 self.level_triggered, 385 self.active_high, 386 self.dest_logic, 387 self.mask, 388 ) 389 } 390 } 391 392 #[inline(never)] 393 pub fn ioapic_init(ignore: &'static [IrqNumber]) { 394 kinfo!("Initializing ioapic..."); 395 let ioapic = unsafe { IoApic::new() }; 396 unsafe { 397 __IOAPIC = Some(SpinLock::new(ioapic)); 398 } 399 unsafe { 400 IOAPIC_IR_CHIP = Some(Arc::new(IoApicChip)); 401 } 402 403 // 绑定irqchip 404 for i in 32..256 { 405 let irq = IrqNumber::new(i); 406 407 if ignore.contains(&irq) { 408 continue; 409 } 410 411 let desc = irq_desc_manager().lookup(irq).unwrap(); 412 let irq_data = desc.irq_data(); 413 let mut chip_info_guard = irq_data.chip_info_write_irqsave(); 414 chip_info_guard.set_chip(Some(ioapic_ir_chip())); 415 let chip_data = IoApicChipData::DEFAULT; 416 chip_data.inner().rte_index = IoApic::vector_rte_index(i as u8); 417 chip_data.inner().vector = i as u8; 418 chip_info_guard.set_chip_data(Some(Arc::new(chip_data))); 419 drop(chip_info_guard); 420 let level = irq_data.is_level_type(); 421 422 register_handler(&desc, level); 423 } 424 425 kinfo!("IO Apic initialized."); 426 } 427 428 fn register_handler(desc: &Arc<IrqDesc>, level_triggered: bool) { 429 let fasteoi: bool; 430 if level_triggered { 431 desc.modify_status(IrqLineStatus::empty(), IrqLineStatus::IRQ_LEVEL); 432 fasteoi = true; 433 } else { 434 desc.modify_status(IrqLineStatus::IRQ_LEVEL, IrqLineStatus::empty()); 435 fasteoi = false; 436 } 437 438 let handler: &dyn IrqFlowHandler = if fasteoi { 439 fast_eoi_irq_handler() 440 } else { 441 edge_irq_handler() 442 }; 443 desc.set_handler(handler); 444 } 445 446 /// 安装中断 447 /// 448 /// ## 参数 449 /// 450 /// * `vector` - 中断向量号 451 /// * `dest` - 目标CPU的APIC ID 452 /// * `level_triggered` - 是否为电平触发 453 /// * `active_high` - 是否为高电平有效 454 /// * `dest_logic` - 是否为逻辑模式 455 /// * `mask` - 是否屏蔽 456 fn ioapic_install( 457 vector: u8, 458 dest: u8, 459 level_triggered: bool, 460 active_high: bool, 461 dest_logic: bool, 462 mask: bool, 463 ) -> Result<(), SystemError> { 464 let rte_index = IoApic::vector_rte_index(vector); 465 return IOAPIC().lock_irqsave().install( 466 rte_index, 467 vector, 468 dest, 469 level_triggered, 470 active_high, 471 dest_logic, 472 mask, 473 ); 474 } 475 476 /// IoApic中断芯片 477 /// 478 /// https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/io_apic.c#1994 479 #[derive(Debug)] 480 struct IoApicChip; 481 482 impl IrqChip for IoApicChip { 483 fn name(&self) -> &'static str { 484 "IR-IO-APIC" 485 } 486 487 fn irq_startup(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> { 488 self.irq_unmask(irq) 489 } 490 491 fn irq_mask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> { 492 let binding = irq 493 .chip_info_read_irqsave() 494 .chip_data() 495 .ok_or(SystemError::EINVAL)?; 496 let chip_data = binding 497 .as_any_ref() 498 .downcast_ref::<IoApicChipData>() 499 .ok_or(SystemError::EINVAL)?; 500 501 let mut chip_data_inner = chip_data.inner(); 502 chip_data_inner.mask = true; 503 chip_data_inner.sync_to_chip().ok(); 504 505 drop(chip_data_inner); 506 507 return Ok(()); 508 } 509 510 fn can_set_affinity(&self) -> bool { 511 true 512 } 513 514 fn can_set_flow_type(&self) -> bool { 515 true 516 } 517 518 fn irq_set_type( 519 &self, 520 irq: &Arc<IrqData>, 521 flow_type: IrqLineStatus, 522 ) -> Result<IrqChipSetMaskResult, SystemError> { 523 let binding = irq 524 .chip_info_read_irqsave() 525 .chip_data() 526 .ok_or(SystemError::EINVAL)?; 527 let chip_data = binding 528 .as_any_ref() 529 .downcast_ref::<IoApicChipData>() 530 .ok_or(SystemError::EINVAL)?; 531 let mut chip_data_inner = chip_data.inner(); 532 533 let level_triggered = flow_type.is_level_type(); 534 let active_high = flow_type.is_level_high().unwrap_or(false); 535 chip_data_inner.active_high = active_high; 536 chip_data_inner.level_triggered = level_triggered; 537 chip_data_inner.sync_to_chip()?; 538 539 return Ok(IrqChipSetMaskResult::SetMaskOk); 540 } 541 542 fn irq_set_affinity( 543 &self, 544 irq: &Arc<IrqData>, 545 cpu: &CpuMask, 546 _force: bool, 547 ) -> Result<IrqChipSetMaskResult, SystemError> { 548 // 使用mask的第1个可用CPU 549 let dest = (cpu.first().ok_or(SystemError::EINVAL)?.data() & 0xff) as u8; 550 551 let binding = irq 552 .chip_info_read_irqsave() 553 .chip_data() 554 .ok_or(SystemError::EINVAL)?; 555 let chip_data = binding 556 .as_any_ref() 557 .downcast_ref::<IoApicChipData>() 558 .ok_or(SystemError::EINVAL)?; 559 560 let mut chip_data_inner = chip_data.inner(); 561 let origin_dest = chip_data_inner.dest; 562 if origin_dest == dest { 563 return Ok(IrqChipSetMaskResult::SetMaskOk); 564 } 565 566 chip_data_inner.dest = dest; 567 568 chip_data_inner.sync_to_chip()?; 569 570 return Ok(IrqChipSetMaskResult::SetMaskOk); 571 } 572 573 fn irq_unmask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> { 574 IOAPIC() 575 .lock_irqsave() 576 .enable(IoApic::vector_rte_index(irq.irq().data() as u8)); 577 Ok(()) 578 } 579 580 fn can_mask_ack(&self) -> bool { 581 true 582 } 583 584 fn irq_mask_ack(&self, irq: &Arc<IrqData>) { 585 self.irq_mask(irq).ok(); 586 self.irq_eoi(irq); 587 } 588 589 fn irq_eoi(&self, irq: &Arc<IrqData>) { 590 if irq.is_level_type() { 591 IOAPIC().lock_irqsave().level_ack(irq.irq().data() as u8); 592 } else { 593 CurrentApic.send_eoi(); 594 } 595 } 596 597 fn retrigger(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> { 598 irq_manager().irq_chip_retrigger_hierarchy(irq_data) 599 } 600 601 fn irqchip_state(&self, irq: &Arc<IrqData>, which: IrqChipState) -> Result<bool, SystemError> { 602 let binding = irq 603 .chip_info_read_irqsave() 604 .chip_data() 605 .ok_or(SystemError::EINVAL)?; 606 let chip_data = binding 607 .as_any_ref() 608 .downcast_ref::<IoApicChipData>() 609 .ok_or(SystemError::EINVAL)?; 610 611 match which { 612 IrqChipState::Pending => { 613 return Ok(IOAPIC().lock_irqsave().pending(irq.irq().data() as u8)); 614 } 615 IrqChipState::Active => { 616 let chip_data_inner = chip_data.inner(); 617 return Ok(!chip_data_inner.mask); 618 } 619 IrqChipState::Masked => { 620 let chip_data_inner = chip_data.inner(); 621 return Ok(chip_data_inner.mask); 622 } 623 IrqChipState::LineLevel => { 624 let chip_data_inner = chip_data.inner(); 625 return Ok(chip_data_inner.active_high); 626 } 627 #[allow(unreachable_patterns)] 628 _ => { 629 return Err(SystemError::EINVAL); 630 } 631 } 632 } 633 634 fn irq_disable(&self, irq: &Arc<IrqData>) { 635 let binding = irq 636 .chip_info_read_irqsave() 637 .chip_data() 638 .ok_or(SystemError::EINVAL) 639 .unwrap(); 640 let chip_data = binding 641 .as_any_ref() 642 .downcast_ref::<IoApicChipData>() 643 .ok_or(SystemError::EINVAL) 644 .unwrap(); 645 let mut chip_data_inner = chip_data.inner(); 646 chip_data_inner.mask = true; 647 chip_data_inner.sync_to_chip().ok(); 648 } 649 650 fn irq_ack(&self, irq_data: &Arc<IrqData>) { 651 // irq_manager().irq_chip_ack_parent(irq_data); 652 self.irq_eoi(irq_data); 653 } 654 655 fn flags(&self) -> IrqChipFlags { 656 IrqChipFlags::IRQCHIP_SKIP_SET_WAKE | IrqChipFlags::IRQCHIP_AFFINITY_PRE_STARTUP 657 } 658 } 659