CPU Interface (Vgicc)

Relevant source files

This document covers the Vgicc struct, which implements the per-CPU interface portion of the virtual Generic Interrupt Controller (GIC). The Vgicc manages CPU-specific interrupt state, list registers for interrupt virtualization, and processor state saving/restoration.

For information about the main VGIC controller that coordinates multiple CPU interfaces, see Virtual GIC Controller (Vgic). For system-wide constants and register layouts, see Constants and Register Layout.

Structure Overview

The Vgicc struct represents a single CPU's interface to the virtual interrupt controller. Each CPU core in the virtualized system has its own Vgicc instance that maintains independent interrupt state and configuration.

Vgicc Struct Layout

flowchart TD
subgraph subGraph3["Vgicc Struct"]
    ID["id: u32CPU Identifier"]
    subgraph subGraph1["Processor State Registers"]
        SAVED_ELSR["saved_elsr0: u32Empty List Status Register"]
        SAVED_APR["saved_apr: u32Active Priority Register"]
        SAVED_HCR["saved_hcr: u32Hypervisor Control Register"]
    end
    subgraph subGraph0["List Register Management"]
        PENDING_LR["pending_lr: [u32; 512]SPI Pending List Registers"]
        SAVED_LR["saved_lr: [u32; 4]Hardware List Register State"]
    end
    subgraph subGraph2["Interrupt Configuration"]
        ISENABLER["isenabler: u32SGI/PPI Enable Bits 0-31"]
        PRIORITYR["priorityr: [u8; 32]PPI Priority Configuration"]
    end
end

ID --> PENDING_LR
ISENABLER --> PRIORITYR
SAVED_ELSR --> SAVED_LR
SAVED_LR --> PENDING_LR

Sources: src/vgicc.rs(L3 - L14) 

Field Categories and Responsibilities

CategoryFieldsPurpose
CPU IdentityidUniquely identifies the CPU core this interface serves
List Register Statepending_lr,saved_lrManages virtual interrupt injection through hardware list registers
Processor Contextsaved_elsr0,saved_apr,saved_hcrPreserves CPU-specific GIC state during VM context switches
Interrupt Controlisenabler,priorityrConfigures interrupt enables and priorities for SGIs and PPIs

Sources: src/vgicc.rs(L4 - L13)  src/consts.rs(L1 - L4) 

List Register Management

The Vgicc manages two types of list register arrays that are central to ARM GIC virtualization:

Hardware List Registers vs Pending Arrays

flowchart TD
subgraph subGraph2["Interrupt Sources"]
    SPI["SPI Interrupts(32-543)"]
    PPI_SGI["PPI/SGI Interrupts(0-31)"]
end
subgraph subGraph1["Vgicc State"]
    SAVED_LR["saved_lr[4]Hardware LR Backup"]
    PENDING_LR["pending_lr[512]SPI Virtual Queue"]
    SAVED_ELSR["saved_elsr0Empty LR Status"]
end
subgraph subGraph0["Physical Hardware"]
    HW_LR["Physical List Registers(4 registers)"]
end

HW_LR --> SAVED_LR
PENDING_LR --> SAVED_LR
PPI_SGI --> HW_LR
SAVED_LR --> HW_LR
SAVED_LR --> SAVED_ELSR
SPI --> PENDING_LR

Sources: src/vgicc.rs(L5 - L6)  src/consts.rs(L3 - L4) 

The saved_lr array holds the contents of the 4 physical hardware list registers, while pending_lr provides a much larger virtual queue for SPI interrupts that cannot fit in the limited hardware registers.

Processor State Management

The Vgicc maintains three critical processor state registers that must be preserved across VM context switches:

State Register Functions

flowchart TD
subgraph subGraph2["Hardware Registers"]
    HW_HCR["Physical GICH_HCR"]
    HW_APR["Physical GICH_APR"]
    HW_ELSR["Physical GICH_ELSR"]
end
subgraph subGraph1["Vgicc State Preservation"]
    HCR["saved_hcrHypervisor Control• Virtual IRQ/FIQ enables• List register usage"]
    APR["saved_aprActive Priority• Currently active interrupt priority• Priority grouping config"]
    ELSR["saved_elsr0Empty List Status• Which LRs are available• Hardware resource tracking"]
end
subgraph subGraph0["VM Context Switch"]
    VM_EXIT["VM Exit"]
    VM_ENTRY["VM Entry"]
end

APR --> HW_APR
APR --> VM_ENTRY
ELSR --> HW_ELSR
ELSR --> VM_ENTRY
HCR --> HW_HCR
HCR --> VM_ENTRY
VM_EXIT --> APR
VM_EXIT --> ELSR
VM_EXIT --> HCR

Sources: src/vgicc.rs(L8 - L10) 

Interrupt Configuration State

The Vgicc maintains per-CPU interrupt configuration for Software Generated Interrupts (SGIs) and Private Peripheral Interrupts (PPIs):

SGI and PPI Management

flowchart TD
subgraph subGraph2["Per-bit Mapping"]
    BIT0["Bit 0: SGI 0"]
    BIT15["Bit 15: SGI 15"]
    BIT16["Bit 16: PPI 16"]
    BIT31["Bit 31: PPI 31"]
end
subgraph subGraph1["Vgicc Configuration"]
    ISENABLER["isenabler: u3232-bit enable maskOne bit per interrupt 0-31"]
    PRIORITYR["priorityr: [u8; 32]8-bit priority per PPIIndices 0-31 for PPI IDs 0-31"]
end
subgraph subGraph0["Interrupt ID Space"]
    SGI["SGI IDs 0-15Software Generated"]
    PPI["PPI IDs 16-31Private Peripheral"]
end

ISENABLER --> BIT0
ISENABLER --> BIT15
ISENABLER --> BIT16
ISENABLER --> BIT31
PPI --> ISENABLER
PPI --> PRIORITYR
SGI --> ISENABLER

Sources: src/vgicc.rs(L12 - L13)  src/consts.rs(L1 - L2) 

The isenabler field uses individual bits to track enable/disable state for each of the 32 SGI and PPI interrupts, while priorityr stores 8-bit priority values specifically for the 32 PPI interrupts.

Integration with VGIC System

The Vgicc operates as part of the larger VGIC virtualization system:

System Integration Flow

flowchart TD
subgraph subGraph2["Physical Hardware"]
    PHYSICAL_GIC["arm_gicv2Physical GIC Driver"]
    HW_CPU_IF["Hardware CPUInterface Registers"]
end
subgraph subGraph1["VGIC System"]
    VGIC_MAIN["Vgic Controller(Main coordinator)"]
    VGICC_INSTANCES["Multiple Vgicc(Per-CPU instances)"]
end
subgraph subGraph0["Guest VM"]
    GUEST["Guest OSInterrupt Operations"]
end

GUEST --> VGIC_MAIN
PHYSICAL_GIC --> HW_CPU_IF
VGICC_INSTANCES --> HW_CPU_IF
VGICC_INSTANCES --> PHYSICAL_GIC
VGIC_MAIN --> VGICC_INSTANCES

Sources: src/vgicc.rs(L1 - L14) 

Each Vgicc instance manages the virtualization state for one CPU core, coordinating with the main Vgic controller to provide a complete virtual interrupt controller implementation to guest operating systems.