Core Architecture
Relevant source files
Purpose and Scope
This document covers the fundamental architectural design of the arm_gicv2 crate, focusing on the two primary hardware abstraction components and their interaction patterns. The architecture centers around providing safe, type-safe access to ARM GICv2 hardware through two main abstractions: system-wide interrupt distribution and per-CPU interrupt handling.
For detailed information about specific interrupt types and classification, see Interrupt Types and Management. For register-level implementation details, see Register Interface.
Architectural Overview
The arm_gicv2 crate implements a two-tier architecture that mirrors the ARM GICv2 hardware design. The core architecture consists of two primary components that work in coordination to manage interrupt processing across the system.
Component Architecture Diagram
flowchart TD
subgraph subGraph3["Hardware Layer"]
HW_DIST["GIC Distributor Hardware"]
HW_CPU["CPU Interface Hardware"]
end
subgraph subGraph2["Interrupt Classification"]
SGI_RANGE["SGI_RANGE (0..16)Software Generated"]
PPI_RANGE["PPI_RANGE (16..32)Private Peripheral"]
SPI_RANGE["SPI_RANGE (32..1020)Shared Peripheral"]
translate_irq["translate_irq()Type conversion"]
end
subgraph subGraph1["Register Abstractions"]
GicDistributorRegs["GicDistributorRegs(memory-mapped registers)"]
GicCpuInterfaceRegs["GicCpuInterfaceRegs(CPU interface registers)"]
end
subgraph subGraph0["Hardware Abstraction Layer"]
GicDistributor["GicDistributor(system-wide control)"]
GicCpuInterface["GicCpuInterface(per-CPU handling)"]
end
GicCpuInterface --> GicCpuInterfaceRegs
GicCpuInterfaceRegs --> HW_CPU
GicDistributor --> GicCpuInterface
GicDistributor --> GicDistributorRegs
GicDistributorRegs --> HW_DIST
PPI_RANGE --> translate_irq
SGI_RANGE --> translate_irq
SPI_RANGE --> translate_irq
translate_irq --> GicCpuInterface
translate_irq --> GicDistributor
Sources: src/gic_v2.rs(L92 - L131) src/lib.rs(L12 - L29) src/lib.rs(L91 - L116)
Core Components
GicDistributor Component
The GicDistributor struct serves as the system-wide interrupt controller, responsible for global interrupt management and routing decisions. It encapsulates a pointer to memory-mapped distributor registers and maintains the maximum interrupt count.
Key Responsibilities:
- Global interrupt enable/disable control via
set_enable() - Priority management through
set_priority()andget_priority() - CPU targeting via
set_target_cpu()andget_target_cpu() - Interrupt configuration using
configure_interrupt() - Software-generated interrupt (SGI) distribution via
send_sgi()family of methods - System initialization through
init()
GicCpuInterface Component
The GicCpuInterface struct handles per-CPU interrupt processing, managing the interface between the distributor and individual processor cores. Each CPU in the system has its own CPU interface instance.
Key Responsibilities:
- Interrupt acknowledgment via
iar()(Interrupt Acknowledge Register) - End-of-interrupt signaling through
eoi()(End of Interrupt Register) - Interrupt deactivation using
dir()(Deactivate Interrupt Register, EL2 feature) - Priority masking and control register management
- Complete interrupt handling workflow via
handle_irq()
Sources: src/gic_v2.rs(L92 - L136) src/gic_v2.rs(L376 - L479)
Component Interaction Flow
The two core components work together to process interrupts from generation to completion. The following diagram illustrates the interaction patterns and method calls involved in typical interrupt processing scenarios.
Interrupt Processing Coordination
sequenceDiagram
participant HardwareSource as "Hardware Source"
participant GicDistributor as "GicDistributor"
participant GicCpuInterface as "GicCpuInterface"
participant InterruptHandler as "Interrupt Handler"
Note over HardwareSource,InterruptHandler: "Interrupt Configuration Phase"
GicDistributor ->> GicDistributor: "init()"
GicCpuInterface ->> GicCpuInterface: "init()"
GicDistributor ->> GicDistributor: "set_enable(vector, true)"
GicDistributor ->> GicDistributor: "set_priority(vector, priority)"
GicDistributor ->> GicDistributor: "set_target_cpu(vector, cpu_mask)"
GicDistributor ->> GicDistributor: "configure_interrupt(vector, TriggerMode)"
Note over HardwareSource,InterruptHandler: "Interrupt Processing Phase"
HardwareSource ->> GicDistributor: "Interrupt Signal"
GicDistributor ->> GicCpuInterface: "Route to Target CPU"
GicCpuInterface ->> GicCpuInterface: "iar() -> interrupt_id"
GicCpuInterface ->> InterruptHandler: "Call handler(interrupt_id)"
InterruptHandler ->> GicCpuInterface: "Processing complete"
GicCpuInterface ->> GicCpuInterface: "eoi(iar_value)"
Note over HardwareSource,InterruptHandler: "EL2 Feature: Separated Priority Drop"
alt "EL2 mode
alt enabled"
GicCpuInterface ->> GicCpuInterface: "dir(iar_value)"
end
end
Note over HardwareSource,InterruptHandler: "Software Generated Interrupt"
GicDistributor ->> GicDistributor: "send_sgi(dest_cpu, sgi_num)"
GicDistributor ->> GicCpuInterface: "SGI delivery"
GicCpuInterface ->> GicCpuInterface: "handle_irq(handler)"
Sources: src/gic_v2.rs(L201 - L223) src/gic_v2.rs(L443 - L459) src/gic_v2.rs(L342 - L373) src/gic_v2.rs(L461 - L478)
Register Architecture Integration
The core components interact with hardware through structured register abstractions. Each component maintains a base pointer to its respective register structure, providing type-safe access to memory-mapped hardware registers.
Register Structure Mapping
flowchart TD
subgraph subGraph3["GicCpuInterfaceRegs Fields"]
CPU_CTLR["CTLR(Control)"]
IAR["IAR(Acknowledge)"]
EOIR["EOIR(End of Interrupt)"]
DIR["DIR(Deactivate)"]
PMR["PMR(Priority Mask)"]
end
subgraph subGraph2["GicCpuInterface Methods"]
handle_irq["handle_irq()"]
iar["iar()"]
eoi["eoi()"]
dir["dir()"]
cpu_init["init()"]
end
subgraph subGraph1["GicDistributorRegs Fields"]
CTLR["CTLR(Control)"]
ISENABLER["ISENABLER(Set-Enable)"]
ICENABLER["ICENABLER(Clear-Enable)"]
SGIR["SGIR(SGI Register)"]
IPRIORITYR["IPRIORITYR(Priority)"]
ITARGETSR["ITARGETSR(Target)"]
ICFGR["ICFGR(Configuration)"]
end
subgraph subGraph0["GicDistributor Methods"]
init["init()"]
set_enable["set_enable()"]
send_sgi["send_sgi()"]
set_priority["set_priority()"]
configure_interrupt["configure_interrupt()"]
end
configure_interrupt --> ICFGR
cpu_init --> CPU_CTLR
cpu_init --> PMR
dir --> DIR
eoi --> EOIR
handle_irq --> DIR
handle_irq --> EOIR
handle_irq --> IAR
iar --> IAR
init --> CTLR
send_sgi --> SGIR
set_enable --> ICENABLER
set_enable --> ISENABLER
set_priority --> IPRIORITYR
Sources: src/gic_v2.rs(L20 - L62) src/gic_v2.rs(L64 - L90) src/gic_v2.rs(L147 - L149) src/gic_v2.rs(L384 - L386)
System State Management
The architecture maintains both global system state through the distributor and per-CPU state through individual CPU interfaces. The distributor manages the max_irqs field to track the hardware-supported interrupt count, while CPU interfaces remain stateless, relying on hardware register state.
Initialization and Configuration
| Component | Initialization Method | Key Configuration |
|---|---|---|
| GicDistributor | init() | Disable all interrupts, set SPI targets to CPU 0, configure edge-triggered mode, enable GICD |
| GicCpuInterface | init() | Set priority mask to maximum, enable CPU interface, configure EL2 mode if feature enabled |
The architecture ensures thread safety through Send and Sync implementations for both core components, allowing safe concurrent access across multiple threads or CPU cores.
Sources: src/gic_v2.rs(L132 - L136) src/gic_v2.rs(L342 - L373) src/gic_v2.rs(L461 - L478)