Register Interface

Relevant source files

This document describes how the arm_gicv2 crate abstracts ARM GICv2 hardware registers and provides safe, type-checked access to GIC functionality. The register interface serves as the foundation layer that bridges Rust code with memory-mapped hardware registers.

For information about the higher-level GIC components that use these registers, see Core Architecture. For specific register details and bit field definitions, see Register Module Organization and GICD_SGIR Register Details.

Register Abstraction Architecture

The crate implements a three-layer abstraction for hardware register access:

flowchart TD
subgraph subGraph3["Hardware Layer"]
    MMIO["Memory-Mapped I/O"]
    GICD_HW["GIC Distributor Hardware"]
    GICC_HW["CPU Interface Hardware"]
end
subgraph subGraph2["Hardware Abstraction Layer"]
    TOCK_REGS["tock-registers crate"]
    BITFIELDS["register_bitfields! macro"]
    REGISTER_TYPES["ReadOnly, WriteOnly, ReadWrite"]
end
subgraph subGraph1["Register Structure Layer"]
    DIST_REGS["GicDistributorRegs struct"]
    CPU_REGS["GicCpuInterfaceRegs struct"]
    REG_FIELDS["Individual Register FieldsCTLR, SGIR, IAR, EOIR, etc."]
end
subgraph subGraph0["Application Layer"]
    APP["High-Level API Methods"]
    DIST_METHODS["GicDistributor methodssend_sgi(), set_enable(), etc."]
    CPU_METHODS["GicCpuInterface methodsiar(), eoi(), handle_irq(), etc."]
end

APP --> CPU_METHODS
APP --> DIST_METHODS
BITFIELDS --> MMIO
CPU_METHODS --> CPU_REGS
CPU_REGS --> REG_FIELDS
DIST_METHODS --> DIST_REGS
DIST_REGS --> REG_FIELDS
MMIO --> GICC_HW
MMIO --> GICD_HW
REGISTER_TYPES --> MMIO
REG_FIELDS --> BITFIELDS
REG_FIELDS --> REGISTER_TYPES
REG_FIELDS --> TOCK_REGS
TOCK_REGS --> MMIO

Sources: src/gic_v2.rs(L1 - L480)  src/regs/gicd_sgir.rs(L1 - L62) 

Memory-Mapped Register Structures

The crate defines two primary register structures that map directly to hardware memory layouts:

GicDistributorRegs Layout

flowchart TD
subgraph subGraph0["GicDistributorRegs Memory Layout"]
    CTLR["0x0000: CTLRDistributor Control RegisterReadWrite<u32>"]
    TYPER["0x0004: TYPERInterrupt Controller TypeReadOnly<u32>"]
    IIDR["0x0008: IIDRImplementer IdentificationReadOnly<u32>"]
    IGROUPR["0x0080: IGROUPR[0x20]Interrupt Group RegistersReadWrite<u32>"]
    ISENABLER["0x0100: ISENABLER[0x20]Interrupt Set-EnableReadWrite<u32>"]
    ICENABLER["0x0180: ICENABLER[0x20]Interrupt Clear-EnableReadWrite<u32>"]
    IPRIORITYR["0x0400: IPRIORITYR[0x100]Interrupt PriorityReadWrite<u32>"]
    ITARGETSR["0x0800: ITARGETSR[0x100]Interrupt Processor TargetsReadWrite<u32>"]
    ICFGR["0x0c00: ICFGR[0x40]Interrupt ConfigurationReadWrite<u32>"]
    SGIR["0x0f00: SGIRSoftware Generated InterruptGicdSgirReg (WriteOnly)"]
    CPENDSGIR["0x0f10: CPENDSGIR[0x4]SGI Clear-PendingReadWrite<u32>"]
    SPENDSGIR["0x0f20: SPENDSGIR[0x4]SGI Set-PendingReadWrite<u32>"]
end

CPENDSGIR --> SPENDSGIR
CTLR --> TYPER
ICENABLER --> IPRIORITYR
ICFGR --> SGIR
IGROUPR --> ISENABLER
IIDR --> IGROUPR
IPRIORITYR --> ITARGETSR
ISENABLER --> ICENABLER
ITARGETSR --> ICFGR
SGIR --> CPENDSGIR
TYPER --> IIDR

GicCpuInterfaceRegs Layout

flowchart TD
subgraph subGraph0["GicCpuInterfaceRegs Memory Layout"]
    CPU_CTLR["0x0000: CTLRCPU Interface ControlReadWrite<u32>"]
    PMR["0x0004: PMRInterrupt Priority MaskReadWrite<u32>"]
    BPR["0x0008: BPRBinary Point RegisterReadWrite<u32>"]
    IAR["0x000c: IARInterrupt AcknowledgeReadOnly<u32>"]
    EOIR["0x0010: EOIREnd of InterruptWriteOnly<u32>"]
    RPR["0x0014: RPRRunning PriorityReadOnly<u32>"]
    HPPIR["0x0018: HPPIRHighest Priority PendingReadOnly<u32>"]
    CPU_IIDR["0x00fc: IIDRCPU Interface IdentificationReadOnly<u32>"]
    DIR["0x1000: DIRDeactivate InterruptWriteOnly<u32>"]
end

BPR --> IAR
CPU_CTLR --> PMR
CPU_IIDR --> DIR
EOIR --> RPR
HPPIR --> CPU_IIDR
IAR --> EOIR
PMR --> BPR
RPR --> HPPIR

Sources: src/gic_v2.rs(L20 - L90) 

Register Access Patterns

The register interface implements type-safe access patterns through the tock-registers crate:

Register TypeAccess PatternExample Usage
ReadOnly.get()self.regs().IAR.get()
WriteOnly.set(value)self.regs().EOIR.set(iar)
ReadWrite.get(),.set(value)self.regs().CTLR.set(val)
GicdSgirReg.write(fields)self.regs().SGIR.write(fields)

Register Structure Instantiation

flowchart TD
BASE_PTR["Raw Base Pointer*mut u8"]
NONNULL["NonNull<GicDistributorRegs>NonNull<GicCpuInterfaceRegs>"]
STRUCT_FIELD["base field inGicDistributor/GicCpuInterface"]
REGS_METHOD["regs() methodunsafe { self.base.as_ref() }"]
REGISTER_ACCESS["Direct register accessself.regs().CTLR.get()"]

BASE_PTR --> NONNULL
NONNULL --> STRUCT_FIELD
REGS_METHOD --> REGISTER_ACCESS
STRUCT_FIELD --> REGS_METHOD

Sources: src/gic_v2.rs(L140 - L149)  src/gic_v2.rs(L378 - L386) 

Type-Safe Bit Field Access

The GICD_SGIR register demonstrates advanced bit field abstraction:

flowchart TD
subgraph subGraph1["Enum Values for TargetListFilter"]
    TLF_00["ForwardToCPUTargetList = 0b00"]
    TLF_01["ForwardToAllExceptRequester = 0b01"]
    TLF_10["ForwardToRequester = 0b10"]
    TLF_11["Reserved = 0b11"]
end
subgraph subGraph0["GICD_SGIR Register Bit Fields"]
    BITS_31_26["Bits [31:26]Reserved316 bits"]
    BITS_25_24["Bits [25:24]TargetListFilter2 bits"]
    BITS_23_16["Bits [23:16]CPUTargetList8 bits"]
    BITS_15["Bit [15]NSATT1 bit"]
    BITS_14_4["Bits [14:4]Reserved14_411 bits"]
    BITS_3_0["Bits [3:0]SGIINTID4 bits"]
end

Usage Example

The register is accessed through structured field composition:

self.regs().SGIR.write(
    GICD_SGIR::TargetListFilter::ForwardToCPUTargetList
        + GICD_SGIR::CPUTargetList.val(dest_cpu_id as _)
        + GICD_SGIR::SGIINTID.val(sgi_num as _)
);

Sources: src/regs/gicd_sgir.rs(L21 - L58)  src/gic_v2.rs(L203 - L208) 

Register Module Organization

The register definitions are organized in the regs/ module:

ModulePurposeKey Components
regs/mod.rsModule exportsRe-exportsgicd_sgiritems
regs/gicd_sgir.rsSGIR registerGICD_SGIRbitfields,GicdSgirRegtype

The module structure allows for extensible register definitions while maintaining clean separation between different register types.

Sources: src/regs/mod.rs(L1 - L4)  src/regs/gicd_sgir.rs(L1 - L62)