[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