IOAPIC fails on real hardware

2026-06-06

Stack Overflow: View Question

Tags: operating-system, osdev, apic

Score: 0 | Views: 96

The asker is writing a hobby OS and just migrated from the legacy 8259 PIC to the modern APIC architecture. Under QEMU everything works; on real hardware they see three distinct symptoms: spurious INT 2 firings, no keyboard or mouse interrupts at all, and (with PIT enabled and its source override honored) a flood of vector 39.

Why this is hard. QEMU is famously forgiving. It tolerates missing EOIs, sloppy redirection-table programming, and skipping bus quirks. Real chipsets do not. Three independent things have to be correct simultaneously for IOAPIC to work on bare metal:

Direction to investigate. I'd suggest a layered bring-up:

  1. Dump the full MADT and print every ISO, NMI source, and IOAPIC entry. Compare against what's actually programmed in the redirection table after init — many bugs are simply a mismatch between "what ACPI said" and "what got written."
  2. For each IOAPIC RTE, explicitly set delivery mode (000 = fixed), destination mode, polarity (high for ISA, low for PCI), and trigger (edge for ISA, level for PCI). Don't rely on reset defaults.
  3. Add a vector-127 spurious handler in the LAPIC SVR and verify it isn't firing constantly — that's often where INT 2-like surprises actually originate.
  4. Check that the PS/2 controller is actually emitting IRQ1/12. Some modern boards route the keyboard through USB legacy emulation; if the BIOS handed off USB, the PS/2 IRQ never comes.

Gotchas. The asker should test on a machine with real PS/2 ports, not USB-emulated ones. They should also confirm the IOAPIC base address from MADT rather than assuming 0xFEC00000 — most boards use it, but it's not guaranteed.

The challenge: APIC bring-up requires three subsystems (legacy PIC masking, ACPI MADT interpretation, LAPIC EOI discipline) to all be correct at once, and QEMU silently forgives mistakes that real hardware punishes.

All newsletters