[PATCH 00/32] KVM: arm64: Introduce vGIC-v5 with PPI support

Sascha Bischoff Sascha.Bischoff at arm.com
Fri Dec 12 07:22:34 PST 2025


This patch series adds the virtual GICv5 [1] device (vgic_v5). Only
PPIs are supported by this initial series, and the vgic_v5
implementation is restricted to the CPU interface, only. Further patch
series are to follow in due course, and will add support for SPIs,
LPIs, the GICv5 IRS, and the GICv5 ITS.

The main changes in this series are the following:

* Bump vgic_v3 to use generated ICH_VMCR_EL2 definitions
* Introduction of the vgic_v5 device, which can be created using the
  KVM_DEV_TYPE_ARM_VGIC_V5 device type
* GICv5 FGT handling, and trapping for guest accesses to
  ICC_IAFFIDR_EL1 and ICC_PPI_HMRx_EL1
* Introduction of queue_irq_unlock and set_pending_state to struct
  irq_ops
* Management of GICv5 PPI state & injection of PPIs
* Direct injection of PPIs using the GICv5 PPI DVI mechanism (used by
  the Arch Timer for mapped IRQs)
* Userspace injection of GICv5 interrupts via KVM_IRQ_LINE
* Addition of a simple GICv5 PPI selftest

As mentioned above, this series introduces two new irq_ops. The
reasoning for this is the following: GIGv5 doesn't have LRs, but
instead has the ICH_PPI_* registers which are able to manage the state
for all implemented vPPIs concurrently. Therefore, by carefully
managing the state of these, there is no need for per-VCPU AP lists
for GICv5. By using these new irq_ops, it becomes possible to directly
set vPPI pending state and to skip the enqueuing on AP lists.

One small, but noteworthy change is to KVM_IRQ_LINE. Previously,
KVM_IRQ_LINE has limited PPI injection to 16-31, inclusive, and SPI
injection to 32-1019, inclusive. When running with a vgic_v5, these
limits are now 0-127 and 0-65535, respectively. Note that technically
a GICv5 system could use up to 2^24 bits for the SPI ID space, but it
is expected that 65k should be sufficient for the foreseeable
future. If more are desired, it will require more significant changes
to KVM_IRQ_LINE.

One final thing to mention is the change to vgic_is_v3_compat(struct
kvm *kvm), which has now been extended to explicitly check that the
vgic_model is not v5. This was previously not required as native GICv5
guests didn't exist. This has a drawback: if called prior to
vgic_create, this check will return true on a GICv5 host with
FEAT_GCIE_LEGACY. This affects the initial state of the sanitized
system registers.

These changes have been tested on an Arm FVP with GICv5 support. A
guide on how to obtain this model and use it can be found at [2]. Note
that the 11.30 release is required as it adds the virtualisation
support.

Note: The first change in this series ("KVM: arm64: Account for RES1
bits in DECLARE_FEAT_MAP() and co") has been cherry-picked from Marc
Zyngier's VTCR sanitisation series [3], and adds support for RES1 FGT
bits. The reason for pulling in this change is that GICv5 adds a RES1
FGT bit, which needs to be correctly handled. Thanks for this change,
Marc!

The initial GICv5 KVM support was prototyped by myself and Timothy
Hayes. Timothy and I therefore have co-authorship on some of the
changes. Thanks for all of your efforts, Timothy!

These changes are based on torvalds/linux:master at 187d0801404f4. Any
future revisions of this series will be posted against the relevant
stable tags, but as we are close to 6.19-rc1 that didn't quite make
sense for this revision.

Thanks all for taking a look, and I look forward to your feedback!

Sascha

[1] https://developer.arm.com/documentation/aes0070/latest
[2] https://linaro.atlassian.net/wiki/x/CQAF-wY
[3] https://lore.kernel.org/all/20251210173024.561160-1-maz@kernel.org/

Marc Zyngier (1):
  KVM: arm64: Account for RES1 bits in DECLARE_FEAT_MAP() and co

Sascha Bischoff (31):
  KVM: arm64: gic-v3: Switch vGIC-v3 to use generated ICH_VMCR_EL2
  arm64/sysreg: Drop ICH_HFGRTR_EL2.ICC_HAPR_EL1 and make RES1
  arm64/sysreg: Add remaining GICv5 ICC_ & ICH_ sysregs for KVM support
  arm64/sysreg: Add GICR CDNMIA encoding
  KVM: arm64: gic-v5: Add ARM_VGIC_V5 device to KVM headers
  KVM: arm64: gic: Introduce interrupt type helpers
  KVM: arm64: gic-v5: Sanitize ID_AA64PFR2_EL1.GCIE
  KVM: arm64: gic-v5: Compute GICv5 FGTs on vcpu load
  KVM: arm64: gic-v5: Add emulation for ICC_IAFFID_EL1 accesses
  KVM: arm64: gic-v5: Trap and emulate ICH_PPI_HMRx_EL1 accesses
  KVM: arm64: gic: Set vgic_model before initing private IRQs
  KVM: arm64: gic-v5: Add vgic-v5 save/restore hyp interface
  KVM: arm64: gic-v5: Implement GICv5 load/put and save/restore
  KVM: arm64: gic-v5: Implement direct injection of PPIs
  KVM: arm64: gic: Introduce irq_queue and set_pending_state to irq_ops
  KVM: arm64: gic-v5: Implement PPI interrupt injection
  KVM: arm64: gic-v5: Check for pending PPIs
  KVM: arm64: gic-v5: Init Private IRQs (PPIs) for GICv5
  KVM: arm64: gic-v5: Support GICv5 interrupts with KVM_IRQ_LINE
  KVM: arm64: gic-v5: Create, init vgic_v5
  KVM: arm64: gic-v5: Reset vcpu state
  KVM: arm64: gic-v5: Bump arch timer for GICv5
  KVM: arm64: gic-v5: Mandate architected PPI for PMU emulation on GICv5
  KVM: arm64: gic: Hide GICv5 for protected guests
  KVM: arm64: gic-v5: Hide FEAT_GCIE from NV GICv5 guests
  KVM: arm64: gic-v5: Introduce kvm_arm_vgic_v5_ops and register them
  KVM: arm64: gic-v5: Set ICH_VCTLR_EL2.En on boot
  irqchip/gic-v5: Check if impl is virt capable
  KVM: arm64: gic-v5: Probe for GICv5 device
  Documentation: KVM: Introduce documentation for VGICv5
  KVM: arm64: selftests: Introduce a minimal GICv5 PPI selftest

 Documentation/virt/kvm/api.rst                |   6 +-
 .../virt/kvm/devices/arm-vgic-v5.rst          |  18 +
 arch/arm64/include/asm/el2_setup.h            |   3 +-
 arch/arm64/include/asm/kvm_asm.h              |   4 +
 arch/arm64/include/asm/kvm_host.h             |  20 +
 arch/arm64/include/asm/kvm_hyp.h              |   9 +
 arch/arm64/include/asm/sysreg.h               |  28 +-
 arch/arm64/include/asm/vncr_mapping.h         |   3 +
 arch/arm64/kvm/arch_timer.c                   | 116 +++-
 arch/arm64/kvm/arm.c                          |  25 +-
 arch/arm64/kvm/config.c                       | 133 ++++-
 arch/arm64/kvm/emulate-nested.c               | 123 ++++-
 arch/arm64/kvm/hyp/include/hyp/switch.h       |  27 +
 arch/arm64/kvm/hyp/nvhe/Makefile              |   2 +-
 arch/arm64/kvm/hyp/nvhe/hyp-main.c            |  32 ++
 arch/arm64/kvm/hyp/nvhe/switch.c              |  13 +
 arch/arm64/kvm/hyp/nvhe/sys_regs.c            |   8 +
 arch/arm64/kvm/hyp/vgic-v3-sr.c               |  64 +--
 arch/arm64/kvm/hyp/vgic-v5.c                  | 155 ++++++
 arch/arm64/kvm/hyp/vhe/Makefile               |   2 +-
 arch/arm64/kvm/nested.c                       |   5 +
 arch/arm64/kvm/pmu-emul.c                     |  20 +-
 arch/arm64/kvm/sys_regs.c                     |  86 ++-
 arch/arm64/kvm/vgic/vgic-init.c               | 119 +++--
 arch/arm64/kvm/vgic/vgic-kvm-device.c         |  74 ++-
 arch/arm64/kvm/vgic/vgic-mmio.c               |  28 +-
 arch/arm64/kvm/vgic/vgic-v3-nested.c          |   8 +-
 arch/arm64/kvm/vgic/vgic-v3.c                 |  48 +-
 arch/arm64/kvm/vgic/vgic-v5.c                 | 505 +++++++++++++++++-
 arch/arm64/kvm/vgic/vgic.c                    | 120 +++--
 arch/arm64/kvm/vgic/vgic.h                    |  76 ++-
 arch/arm64/tools/sysreg                       | 482 ++++++++++++++++-
 drivers/irqchip/irq-gic-v5-irs.c              |   4 +
 drivers/irqchip/irq-gic-v5.c                  |   5 +
 include/kvm/arm_arch_timer.h                  |   7 +-
 include/kvm/arm_pmu.h                         |   5 +-
 include/kvm/arm_vgic.h                        |  87 ++-
 include/linux/irqchip/arm-gic-v5.h            |  15 +
 include/linux/kvm_host.h                      |   1 +
 include/uapi/linux/kvm.h                      |   2 +
 tools/include/uapi/linux/kvm.h                |   2 +
 tools/testing/selftests/kvm/Makefile.kvm      |   1 +
 tools/testing/selftests/kvm/arm64/vgic_v5.c   | 248 +++++++++
 .../selftests/kvm/include/arm64/gic_v5.h      | 148 +++++
 44 files changed, 2623 insertions(+), 264 deletions(-)
 create mode 100644 Documentation/virt/kvm/devices/arm-vgic-v5.rst
 create mode 100644 arch/arm64/kvm/hyp/vgic-v5.c
 create mode 100644 tools/testing/selftests/kvm/arm64/vgic_v5.c
 create mode 100644 tools/testing/selftests/kvm/include/arm64/gic_v5.h

-- 
2.34.1



More information about the linux-arm-kernel mailing list