Software Generated Interrupts

Relevant source files

This document covers Software Generated Interrupts (SGIs) in the ARM GICv2 implementation, including their generation methods, register interface, and targeting mechanisms. SGIs are a critical component for inter-processor communication in multi-core systems.

For information about the overall interrupt classification system, see Interrupt Classification System. For details about the underlying register implementations, see GICD_SGIR Register Details.

SGI Overview and Characteristics

Software Generated Interrupts occupy interrupt IDs 0-15 and serve as the primary mechanism for inter-processor communication in ARM GICv2 systems. Unlike peripheral interrupts, SGIs are generated entirely through software writes to the GICD_SGIR register.

CharacteristicValue
Interrupt ID Range0-15
Total Count16 SGIs
Primary Use CaseInter-processor communication
Generation MethodSoftware write to GICD_SGIR
TargetingFlexible CPU targeting modes

SGIs are defined by the SGI_RANGE constant and classified through the InterruptType::SGI enum variant. The translate_irq function handles SGI ID validation, ensuring only IDs 0-15 are accepted for SGI operations.

SGI Generation Flow

flowchart TD
A["Software Request"]
B["GicDistributor::send_sgi*"]
C["GICD_SGIR Register Write"]
D["TargetListFilter Mode"]
E["ForwardToCPUTargetList"]
F["ForwardToAllExceptRequester"]
G["ForwardToRequester"]
H["CPUTargetList Field"]
I["All CPUs Except Current"]
J["Current CPU Only"]
K["Target CPU Interfaces"]
L["SGI Delivery"]

A --> B
B --> C
C --> D
D --> E
D --> F
D --> G
E --> H
F --> I
G --> J
H --> K
I --> K
J --> K
K --> L

Sources: src/lib.rs(L14 - L18)  src/lib.rs(L92 - L116)  src/gic_v2.rs(L202 - L223) 

SGI Generation Methods

The GicDistributor struct provides three primary methods for generating SGIs, each corresponding to different targeting strategies. These methods abstract the complexity of GICD_SGIR register programming.

send_sgi Method

The send_sgi method targets a specific CPU interface using the ForwardToCPUTargetList mode:

// Method signature from GicDistributor implementation
pub fn send_sgi(&mut self, dest_cpu_id: usize, sgi_num: usize)

This method constructs a GICD_SGIR register write with:

  • TargetListFilter = ForwardToCPUTargetList (0b00)
  • CPUTargetList = destination CPU ID bitmask
  • SGIINTID = SGI number (0-15)

send_sgi_all_except_self Method

The send_sgi_all_except_self method broadcasts to all CPU interfaces except the requesting processor:

// Method signature from GicDistributor implementation  
pub fn send_sgi_all_except_self(&mut self, sgi_num: usize)

This method uses TargetListFilter = ForwardToAllExceptRequester (0b01), eliminating the need to specify individual CPU targets.

send_sgi_to_self Method

The send_sgi_to_self method targets only the requesting CPU interface:

// Method signature from GicDistributor implementation
pub fn send_sgi_to_self(&mut self, sgi_num: usize)

This method uses TargetListFilter = ForwardToRequester (0b10) for local SGI generation.

SGI Method Mapping

flowchart TD
subgraph subGraph2["Hardware Behavior"]
    G["Target specific CPU interface"]
    H["Broadcast to all except sender"]
    I["Self-targeting only"]
end
subgraph subGraph1["GICD_SGIR TargetListFilter"]
    D["ForwardToCPUTargetList (0b00)"]
    E["ForwardToAllExceptRequester (0b01)"]
    F["ForwardToRequester (0b10)"]
end
subgraph subGraph0["GicDistributor Methods"]
    A["send_sgi(dest_cpu_id, sgi_num)"]
    B["send_sgi_all_except_self(sgi_num)"]
    C["send_sgi_to_self(sgi_num)"]
end

A --> D
B --> E
C --> F
D --> G
E --> H
F --> I

Sources: src/gic_v2.rs(L202 - L208)  src/gic_v2.rs(L211 - L216)  src/gic_v2.rs(L219 - L223) 

GICD_SGIR Register Interface

The GICD_SGIR register controls SGI generation through a structured bit field layout. The register is implemented as a write-only interface using the tock-registers abstraction.

Register Bit Fields

BitsFieldPurpose
[31:26]ReservedMust be zero
[25:24]TargetListFilterDetermines targeting mode
[23:16]CPUTargetListCPU interface bitmask (when TargetListFilter = 0b00)
[15]NSATTSecurity attribute (Security Extensions only)
[14:4]ReservedShould be zero
[3:0]SGIINTIDSGI interrupt ID (0-15)

The TargetListFilter field provides four targeting modes:

ValueModeDescription
0b00ForwardToCPUTargetListUse CPUTargetList bitmask
0b01ForwardToAllExceptRequesterBroadcast except sender
0b10ForwardToRequesterSelf-targeting only
0b11ReservedInvalid mode

GICD_SGIR Register Layout

flowchart TD
subgraph subGraph0["GICD_SGIR Register (32 bits)"]
    A["[31:26]Reserved"]
    B["[25:24]TargetListFilter"]
    C["[23:16]CPUTargetList"]
    D["[15]NSATT"]
    E["[14:4]Reserved"]
    F["[3:0]SGIINTID"]
end
G["Targeting Mode0b00: CPUTargetList0b01: All except self0b10: Self only"]
H["8-bit CPU maskEach bit = CPU interface"]
I["SGI ID (0-15)4-bit value"]

B --> G
C --> H
F --> I

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

SGI State Management

SGIs require special handling in the GIC distributor's state management functions due to their per-CPU nature. The set_pend method implements SGI-specific logic using dedicated pending registers.

SGI Pending State Registers

SGIs use separate pending state registers compared to other interrupt types:

  • SPENDSGIR: Set SGI pending registers (4 registers, 32 bits each)
  • CPENDSGIR: Clear SGI pending registers (4 registers, 32 bits each)

Each register covers 4 SGIs with 8 bits per SGI (one bit per CPU interface).

SGI Pending State Implementation

The set_pend method handles SGIs using a different code path:

// SGI range check and register access pattern
if SGI_RANGE.contains(&int_id) {
    let reg_idx = int_id / 4;        // SGI register index (0-3)
    let offset = (int_id % 4) * 8;   // Bit offset within register
    // Set/clear pending state per CPU
}

SGI Pending State Flow

flowchart TD
A["set_pend(int_id, is_pend, current_cpu_id)"]
B["SGI_RANGE.contains(int_id)?"]
C["SGI Pending Path"]
D["Standard Pending Path"]
E["reg_idx = int_id / 4"]
F["offset = (int_id % 4) * 8"]
G["is_pend?"]
H["SPENDSGIR[reg_idx]Set bit at offset + current_cpu_id"]
I["CPENDSGIR[reg_idx]Clear 8 bits at offset"]
J["ISPENDR/ICPENDR registers"]

A --> B
B --> C
B --> D
C --> E
C --> F
D --> J
E --> G
F --> G
G --> H
G --> I

Sources: src/gic_v2.rs(L264 - L283)  src/gic_v2.rs(L55 - L58)  src/lib.rs(L14 - L18) 

SGI Security and Access Control

When the GIC implements Security Extensions, the NSATT bit in GICD_SGIR controls SGI security attributes. This field determines whether SGIs are forwarded based on their Group 0 or Group 1 configuration.

Security Behavior

NSATT ValueSGI Forwarding Condition
0Forward only if SGI configured as Group 0
1Forward only if SGI configured as Group 1

Non-secure writes to GICD_SGIR can only generate Group 1 SGIs, regardless of the NSATT field value. This provides hardware-enforced security isolation between secure and non-secure SGI generation.

Sources: src/regs/gicd_sgir.rs(L42 - L49)