Interrupt Routing and Handling
IRQs and Domains
All interrupts are represented by an Irq object, and possess an ID consisting of a (port, vector) pair. The meaning of the port and vector fields depends on the interrupt’s Domain, an abstraction over different types of interrupts with different controllers and dispatching mechanisms.
An interrupt Domain has two required and four optional functions in its VTable:
reserve: Reserve an Irq in this domain. May provide acceptable ID options, a minimum IRQL, and/or force a specific handling CPU.destroy: Unregister and destroy an Irq in this domain.mask(optional): Temporarily mask an Irq to prevent it from being dispatchedunmask(optional): Unmask an Irq to ensure it may be dispatched.move(optional): Move an Irq from one vector to another, in case of conflicts in fixed vector IRQs.deinit(optional): Deinitialize this domain. Only relevant for domains associated with removable features, such as device-specific MSI Domains or with removable interrupt controller devices.
Generally, an interrupt ID’s port refers to a physical endpoint whereas vector refers to a payload passed to that endpoint: e.g. a port for each core on an x86_64 system with one vector per x86 interrupt vector on that core, or one port per requester id on a PCI hierarchy with one vector per MSI(-X) vector that pci device uses. Some domains do not use one or both fields, such as the Global System Interrupt (GSI) domain, which makes no use of the port field and fixes it to 0.
Domains may, and most do, wrap Irqs from lower level domains, e.g. the x86 implementation of the GSI domain wrapping Irqs from the “x86 vector” domain and remapping IOAPICs to point to those lower-level x86 vectors.
MSI Domains
To support IOMMUs and the GIC ITS, MSIs are routed using a per-device-id Irq Domain. These per-device domains are created and managed by an MsiDomain, which has a single function: create, which creates or references such a per-device-id domain.
The Irq object representing an MSI stores the message address in the port field of its ID, and the message data in the vector field.
Required Domains
An architecture/interrupt controller combination is required to provide two Irq Domains and one MSI Domain:
- GSI Domain: Routes GSIs (one-to-one with GIC INTIDs)
- SGI Domain: Routes Software Generated Interrupts (SGIs)
- MSI Domain: Creates per-device domains to route MSIs.
In addition, the architecture/interrupt controller combination must provide a function to atomically issue an SGI to the current processor, a single target processor, or all processors excluding the current processor. It may additionally implement an atomic mechanism for issuing an SGI to all processors including the current processor if supported.
It must also provide functionality to change the IRQL of the current processor.
IRQLs
All interrupts are associated with an IRQL. All executing logical processors have a current IRQL. A logical processor shall not dispatch interrupts of a lower or equal IRQL to the current IRQL. A logical processor shall dispatch unmasked interrupts of a higher IRQL than the current IRQL.
When an interrupt is dispatched to a logical processor, its previous current IRQL is stored and its current IRQL is set to the IRQL of the dispatched interrupt before interrupts are unmasked.
When a logical processor finishes dispatching an interrupt, its current IRQL is set to the stored value after interrupts are masked in advance of the return-from-interrupt.
An interrupt dispatcher must provide for a stack of saved IRQLs in case of preemption, but may use hardware support or local stack variables to provide this.
System software may modify the current IRQL of the current processor at any time for any reason, pursuant to the above requirements.
The IRQLs are as follows:
| IRQL | Value | GIC PMR | Purpose |
|---|---|---|---|
| passive | 0x0 | 0xF0 | Normal execution. No interrupts, all unmasked |
| apc | 0x1 | 0xE0 | Kernel APCs switch to target thread context |
| dispatch | 0x2 | 0xD0 | DPCs, other dispatching EXCEPT APCs, debug |
| dev0 – dev9 | 0x3 – 0xC | 0x30 – 0xC0 | Normal device interrupts |
| clock | 0xD | 0x20 | Local timer(s) |
| ipi | 0xE | 0x10 | Sync IPIs, other cross-core synchronization |
| high | 0xF | 0x00 | Profiling/performance-counting interrupts, pseudo-NMIs |
Known Interrupt Numbers
Some interrupt numbers are architecturally known to exist on some or all platforms, detailed in the below table. If a single value is given for x86 Vector or GIGc3 INTID, the irq in question shall always use the specified vector or INTID. However, system software should not rely on this fixed value except in the Interrupt Controller Manager implementation.
| Domain | Number | Purpose | GICv3 INTID | x86 Vector |
|---|---|---|---|---|
| Spurious Interrupts | 1022 | 0xDF | ||
| SGI | 0 | APCs | 0 | 0x1F |
| SGI | 1 | DPCs | 1 | 0x2F |
| SGI | 6 | Sync IPIs | 6 | 0xE0 |
| SGI | 7 | Panic | 7 | 0xFF |
| PPI | varies | Gen. Timer | equal to PPI num | N/A |
| GSI | varies | ACPI SCI | equal if present | any dev8 (0xBx) |
Interrupt Dispatching
The interrupt controller manager implementation must be able to retrieve the hardware vector or INTID of the signaled interrupt.
IRQ objects may provide a function to check if the irq is currently asserted. If an IRQ may share a hardware vector with other IRQs, the check function shall be provided by the IRQ object.
If an interrupt controller architecture supports sharing interrupt vectors, the interrupt controller manager implementation shall use the IRQ check function to determine which IRQ has been asserted when a shared vector is dispatched.
If a check function is provided by an IRQ object, the interrupt controller manager shall invoke it even if the associated vector is unshared.
IRQ objects shall provide a handler function to perform actions as required by the driver which registered the IRQ.
The IRQ handler function shall return flags to determine the post-handler action of the dispatcher. One of the returnable flags shall signal to the interrupt controller manager implementation that it shall communicate an end-of-interrupt signal to the interrupt controller. An IRQ handler function may omit this flag if the IRQ handler function intends to communicate the end-of-interrupt signal on its own.
If an IRQ check function returns false, the IRQ handler function shall not be invoked.
If no handler could be invoked when dispatching an interrupt, the interrupt controller manager implementation shall invoke a kernel panic.
An interrupt controller manager implementation shall ensure that all IRQ objects associated with a vector whose check functions return true have their handler functions invoked. An interrupt controller manager implementation may rely on the behavior of the interrupt controller hardware to meet this requirement.
If the spurious interrupt is signaled by the interrupt controller, the interrupt controller manager shall return from the interrupt handler immediately and take no action.