[PATCH 00/33] KVM: arm64: Add LR overflow infrastructure

Marc Zyngier maz at kernel.org
Mon Nov 3 08:54:44 PST 2025


Despite being an awfully complex piece of software, the KVM vgic
implementation is not doing what it should in a number of cases:

- It behaves very badly when the number of in-flight interrupts
  targeting a specific CPU exceed the number of list registers
  (LRs). This is catastrophic with NV (Volodymyr triggered that one
  with a Xen guest), but can easily be triggered without it. You just
  have to activate more interrupts than the number of LRs to end-up
  with a guest live-lock.

- Similar issues exist when making high-priority interrupts targeting
  a group that isn't enabled.

Overall, this stems from the vgic implementation not sorting the
interrupts presented to the guest in the correct order (i.e. the one
expected by the architecture), and allow deactivation outside of the
window exposed by the LRs.

Unfortunately, the cure for this is pretty involved, and involves
adding a significant amount of complexity:

- Order the list as the architecture requires it, by starting with
  placing the HPPIs at the forefront of the ap_list

- Handle deactivation for EOImode being 0 or 1, which is specially
  annoying as we cannot easily find out which mode we're in, and we
  need to handle both concurrently

- Deal with individual interrupt groups being enabled/disabled

- Deal with SPIs being acked on one CPU and deactivated on another

Implementation wise, this is about extracting the relevant primitive
from the existing code, making guest state available to the emulation
more eagerly, dealing with a lot more MI sources, and be creative
about trapping stuff. Oh, and of course dealing with broken HW,
because nothing would be fun if we didn't.

The eagle eyed reviewer will notice that this series doesn't provide
any selftest. That's on purpose: I'm still working on those, and I
could do with some reviewing while I'm finishing them, and plan to
post them with v2.

Marc Zyngier (33):
  irqchip/gic: Add missing GICH_HCR control bits
  irqchip/gic: Expose CPU interface VA to KVM
  irqchip/apple-aic: Spit out ICH_MIDR_EL2 value on spurious vGIC MI
  KVM: arm64: Turn vgic-v3 errata traps into a patched-in constant
  KVM: arm64: GICv3: Detect and work around the lack of ICV_DIR_EL1
    trapping
  KVM: arm64: Repack struct vgic_irq fields
  KVM: arm64: Add tracking of vgic_irq being present in a LR
  KVM: arm64: Add LR overflow handling documentation
  KVM: arm64: GICv3: Drop LPI active state when folding LRs
  KVM: arm64: GICv3: Preserve EOIcount on exit
  KVM: arm64: GICv3: Decouple ICH_HCR_EL2 programming from LRs
  KVM: arm64: GICv3: Extract LR folding primitive
  KVM: arm64: GICv3: Extract LR computing primitive
  KVM: arm64: GICv2: Preserve EOIcount on exit
  KVM: arm64: GICv2: Decouple GICH_HCR programming from LRs being loaded
  KVM: arm64: GICv2: Extract LR folding primitive
  KVM: arm64: GICv2: Extract LR computing primitive
  KVM: arm64: Compute vgic state irrespective of the number of
    interrupts
  KVM: arm64: Eagerly save VMCR on exit
  KVM: arm64: Revamp vgic maintenance interrupt configuration
  KVM: arm64: Make vgic_target_oracle() globally available
  KVM: arm64: Invert ap_list sorting to push active interrupts out
  KVM: arm64: Move undeliverable interrupts to the end of ap_list
  KVM: arm64: Use MI to detect groups being enabled/disabled
  KVM: arm64: Add AP-list overflow split/splice
  KVM: arm64: GICv3: Handle LR overflow when EOImode==0
  KVM: arm64: GICv3: Handle deactivation via ICV_DIR_EL1 traps
  KVM: arm64: GICv3: Add GICv2 SGI handling to deactivation primitive
  KVM: arm64: GICv3: Set ICH_HCR_EL2.TDIR when interrupts overflow LR
    capacity
  KVM: arm64: GICv2: Handle LR overflow when EOImode==0
  KVM: arm64: GICv2: Handle deactivation via GICV_DIR traps
  KVM: arm64: GICv2: Always trap GICV_DIR register
  KVM: arm64: GICv3: Add SPI tracking to handle asymmetric deactivation

 arch/arm64/include/asm/kvm_asm.h         |   2 +-
 arch/arm64/include/asm/kvm_host.h        |   1 +
 arch/arm64/include/asm/kvm_hyp.h         |   2 +-
 arch/arm64/include/asm/virt.h            |   7 +-
 arch/arm64/kernel/cpufeature.c           |  34 ++
 arch/arm64/kernel/hyp-stub.S             |   5 +
 arch/arm64/kernel/image-vars.h           |   1 +
 arch/arm64/kvm/arm.c                     |   7 +-
 arch/arm64/kvm/hyp/nvhe/hyp-main.c       |   7 +-
 arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c |   4 +
 arch/arm64/kvm/hyp/vgic-v3-sr.c          |  55 +--
 arch/arm64/kvm/sys_regs.c                |  19 +-
 arch/arm64/kvm/vgic/vgic-init.c          |   3 +
 arch/arm64/kvm/vgic/vgic-mmio-v2.c       |  24 ++
 arch/arm64/kvm/vgic/vgic-mmio.h          |   1 +
 arch/arm64/kvm/vgic/vgic-v2.c            | 311 +++++++++++++----
 arch/arm64/kvm/vgic/vgic-v3-nested.c     |  11 +-
 arch/arm64/kvm/vgic/vgic-v3.c            | 419 ++++++++++++++++++-----
 arch/arm64/kvm/vgic/vgic-v4.c            |   5 +-
 arch/arm64/kvm/vgic/vgic.c               | 328 ++++++++++++------
 arch/arm64/kvm/vgic/vgic.h               |  44 ++-
 arch/arm64/tools/cpucaps                 |   1 +
 drivers/irqchip/irq-apple-aic.c          |   7 +-
 drivers/irqchip/irq-gic.c                |   3 +
 include/kvm/arm_vgic.h                   |  35 +-
 include/linux/irqchip/arm-gic.h          |   6 +
 include/linux/irqchip/arm-vgic-info.h    |   2 +
 27 files changed, 1012 insertions(+), 332 deletions(-)

-- 
2.47.3




More information about the linux-arm-kernel mailing list