Fundamentals 10 min read

Linux Kernel Interrupt Mapping: Hardware and Software IRQ Translation Process

The article explains how the Linux kernel translates ARM GIC hardware interrupt numbers into virtual software IRQs by maintaining a global bitmap, initializing the interrupt controller, using irq_domain structures to map and associate hwirq and virq values, and storing relationships in descriptor and revmap trees for efficient lookup.

OPPO Kernel Craftsman
OPPO Kernel Craftsman
OPPO Kernel Craftsman
Linux Kernel Interrupt Mapping: Hardware and Software IRQ Translation Process

Interrupts are a fundamental function of modern computer systems and serve as the essential bridge for responding to peripheral events. Different architectures design interrupt controllers differently; this article introduces the mapping process between hardware interrupt numbers and software interrupt numbers for ARM's Generic Interrupt Controller (GIC) in Linux.

Hardware Interrupt Number : GIC assigns a unique identifier to each hardware interrupt source, called the hardware interrupt number (hwirq). The range of supported hardware interrupt numbers for GIC‑v3 is shown in the figure below.

IC 分配的中断号范围

Software Interrupt Number : The number used by the kernel during interrupt registration and handling, also known as a virtual interrupt number (virq).

Why perform interrupt mapping? Software can ignore the specific hardware source of an interrupt. Early SoCs used a single global interrupt status register, allowing a linear mapping from hardware to software numbers. Modern SoCs contain multiple interrupt controllers (e.g., GIC, GPIO), each with overlapping hardware numbers, making a simple linear mapping insufficient. Mapping provides a unique identifier for each peripheral interrupt, simplifying kernel development.

The Linux interrupt mapping process involves several key data structures (see kernel source for details):

struct irq_desc : descriptor for each IRQ, containing the associated irqaction .

struct irq_domain / struct irq_chip : software abstraction of the interrupt controller.

struct irq_data : core structure for mapping; it holds both the software IRQ ( irq ) and the hardware IRQ ( hwirq ).

The relationships among these structures are illustrated below:

The mapping process can be divided into the following steps:

System maintains a global allocated_irqs bitmap.

Interrupt controller initialization.

Acquisition and mapping of software interrupt numbers.

Acquisition and mapping of hardware interrupt numbers.

1. System maintains global allocated_irqs

When CONFIG_SPARSE_IRQ is enabled, the kernel reserves NR_IRQS + 8196 bits, each representing a possible software IRQ. Allocation scans the bitmap for the first contiguous free region to assign a new virtual IRQ.

2. Interrupt controller initialization

The controller registers via the IRQCHIP_DECLARE macro into __irqchip_of_table . During boot ( start_kernel() → init_IRQ() → irqchip_init ), gic_of_init() is invoked to initialize the GIC.

During gic_of_init , domain handling functions are registered; gic_irq_domain_translate() translates DTS interrupt information into hwirq . A domain tree is allocated and added to the global irq_domain_list , and the interrupt entry point is set.

3. Software interrupt number acquisition and mapping

The kernel follows the call chain: kernel_init() → … → of_device_alloc() . of_irq_count() determines the number of IRQs in a DTS node, then each IRQ is processed via of_irq_to_resource() → of_irq_get() . of_irq_get() parses the interrupt description and records it in an oirq structure, after which irq_create_of_mapping() performs the mapping and returns a virtual IRQ.

irq_create_of_mapping() eventually calls irq_create_fwspec_mapping() , which uses irq_domain_translate() (registered earlier) to obtain the hwirq . If the IRQ is already mapped, the existing irq_data is reused; otherwise, a free bit from allocated_irqs is allocated as a new software IRQ, an irq_desc is created, and the mapping is inserted into the irq_desc_tree .

4. Hardware interrupt number acquisition and mapping

irq_create_fwspec_mapping() first obtains the hardware IRQ via irq_domain_translate() , adds any required offset for SGI/PPI, then calls irq_domain_associate() to store the hwirq in irq_data . irq_domain_set_mapping() establishes the relationship: if hwirq is within the linear range, a direct mapping is used; otherwise, the hwirq becomes a key in the revmap_tree for fast lookup.

5. Summary

Through the described steps, one can retrieve the interrupt descriptor ( irq_desc ) from a virtual IRQ, then obtain irq_data and the corresponding hardware IRQ ( hwirq ). Conversely, given a hardware IRQ, the domain's revmap_tree can be used to locate the associated irq_data and thus the virtual IRQ.

The article provides a high‑level overview of Linux kernel interrupt mapping without delving into specific source code; readers can explore the detailed implementation using the presented framework.

kernelLinuxInterruptDevice TreeGICIRQ Mapping
OPPO Kernel Craftsman
Written by

OPPO Kernel Craftsman

Sharing Linux kernel-related cutting-edge technology, technical articles, technical news, and curated tutorials

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.