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 Type | Access Pattern | Example 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:
Module | Purpose | Key Components |
---|---|---|
regs/mod.rs | Module exports | Re-exportsgicd_sgiritems |
regs/gicd_sgir.rs | SGIR register | GICD_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)