Advanced Programmable Interrupt Controller
1. Terminology
- IRQ - interrupt request, an request sent to the CPU in order to stop execution and do something else (execute interrupt handler).
- Interrupt - the event that happens on the IRQ.
- Interrupt handler - an piece of code which is executed on specific IRQ.
- Interrupt vector table - a list of interrupt handlers; it's a technical abstract term; the IVT has different implementations on specific CPUs.
- Interrupt vector - an entry in the IVT.
- Interrupt Descriptor Table - Intel's x86 implementation of IVT.
- Global System Interrupt (GSI) - another name of the IRQ but in the context of I/O APIC.
2. What is it?
APIC is a modern replacement for the 8259 Programmable Interrupt Controller (PIC). It is an Intel concept.
IMPORTANT: CPU Interrupt Flag (EFLAGS.IF) must be enabled.
3. Architecture
APIC architecture is split into two hardware devices. Information about both parts (installed version, abilities, presence, MMIO addresses) can be found using ACPI Standard Description Table MADT (Multiple APIC Description Table).
3.1. Local APIC
MORE: LAPIC is part of the CPU so it's specified in Intel's Manual, volume 3, chapter 10. APIC.
LAPIC is usually integrated into the CPU itself. Every CPU has its own LAPIC. It manages all external IRQs for specific CPU in an SMP system. LAPIC is also able to accept and generate inter-processor interrupts (IPI) used to communication between CPUs. LAPIC can process up to 224 interrupt vectors - first 32 entries are reserved for standard x86 exceptions.
Local APIC receives interrupts from the processor’s interrupt pins, internal sources and an external I/O APIC (or other external interrupt controller). It sends IRQs to the processor core for handling.
Local APIC handles following interrupts:
- IRQs from the I/O APIC
- IPIs (Inter-Processor Interrupts) from other CPUs. They are used in SMP systems.
- Local (self-generated) interrupts (e.g. APIC timer, thermal sensors, etc.). The role of LAPIC for local interrupts is analogous to the role of I/O APIC for external interrupts. It uses the LVT (Local Vector Table) as a redirection table for local interrupts.
LAPIC has one set of registers. See all of them in "Table 10-1" in Intel's Manual, volume 3. It is configured by memory-mapped registers (default starting address: 0xFEE00000
).
3.1.1. Local APIC ID
Each APIC has APIC ID assigned. It can be used as a CPU ID. The APIC ID is unique for all CPUs installed in the system. It can be read from APIC ID register (offset: 0x20). On xAPIC up to 256 CPUs are supported.
3.1.2. Spurious interrupt vector
TBD
3.1.3. How does fixed interrupt handling work?
MORE: Intel's Manual, volume 3, chapter 10.8.4 Interrupt Acceptance for Fixed Interrupts.
The LAPIC IRR register (256 bits) contains the active IRQ that have been accepted, but not yet dispatched to the processor for processing. When the LAPIC accepts an IRQ, it sets the bit in the IRR that corresponds the vector of the accepted IRQ. When the processor core is ready to handle the next IRQ, the LAPIC clears the corresponding IRR bit that is set and sets the corresponding ISR bit. IRR and ISR registers are some kind of bitmaps. Each bit is an interrupt vector. When the Interrupt Service Routine issues a write to the EOI register the local APIC responds by clearing corresponding the ISR bit.
3.1.4. Return from interrupt
MORE: Intel's Manual, volume 3, chapter 10.8.5 Signaling Interrupt Servicing Completion
To signal interrupt handling completion to the LAPIC, the interrupt handler must include a write to the end-of-interrupt (EOI) register. This write must occur at the end of the handler function. This action indicates that the handling of the current interrupt is complete and the LAPIC can issue the next interrupt from the ISR.
3.2. I/O APIC
MORE: I/O APIC is very platform related and there is no latest official documentation of this piece of hardware.
IOAPIC is part of the chipset. It contains a redirection table, which is used to route the IRQs from peripherals (external hardware) to a specific LAPIC. It allows to translate an hardware IRQ number to specific interrupt vector (the mapping can be controlled by a software). Most often IOAPIC supports 24 separately programmable interrupt entries.
NOTE: Formally (according to the Intel's Manual), the signal that is sent between IOAPIC and LAPIC is called an Interrupt Message.
3.2.1. Configuration
IOAPIC is configured by memory-mapped registers (starting address: 0xFEC00000
). Due to space saving IOAPIC registers are accessed by writing selected register offset
into IOREGSEL register and then writing/reading register's data in IOWIN register (where the selected register is placed).
There is one 64-bit register for each redirection entry. Data IOWIN register is 32-bit long, it means that the 64-bit entry's register must be written in two rounds. Lower half must be written first. Writing higher half (offset + 1) actually applies the changes.
IOAPIC registers schema:
REDIRECTION ENTRY: The schema of a redirection entry register can be found in I/O APIC Specification, chapter 3.2.4 IOREDTBL[23:0].
3.2.2. How does it work?
NOTE: The number of the sent IRQ does not have to correspond to the entry number to which it will go (see: I/O APIC Specification, chapter 2.4 Interrupt Signals).
When the IOAPIC receives an external interrupt from a external device, it forwards the interrupt to the LAPIC. When an LAPIC is able to accept the interrupt, the LAPIC will signal an interrupt to the CPU and the CPU will interrupt through the corresponding interrupt vector that was programmed into the IOAPIC.
4. Additional resources
- Dreamos82: Os-dev notes - APIC
- Kestrel Williams-King: OSDev notes 3: Hardware & Interrupts
- Wesleyac: How to set up the APIC to get keyboard interrupts
- Kostr: External Interrupts in the x86 system. Part 1. Interrupt controller evolution
- Kostr: External Interrupts in the x86 system. Part 2. Linux kernel boot options
- Kostr: External Interrupts in the x86 system. Part 3. Interrupt routing setup in a chipset, with the example of coreboot