aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
authorSascha Bischoff <sascha.bischoff@arm.com>2026-05-20 10:19:49 +0100
committerMarc Zyngier <maz@kernel.org>2026-05-23 15:07:41 +0100
commitbee399ea20c8fea361c0ada06afdec9fcbf6dfde (patch)
tree65bb7c260d1babc476b4802c6a2a16e83dfffed1 /arch
parentabf60331ebe9a9a7937a72aac7699c2907ab9307 (diff)
downloadlinux-next-history-bee399ea20c8fea361c0ada06afdec9fcbf6dfde.tar.gz
KVM: arm64: Fix arch timer interrupts for GICv3-on-GICv5 guests
When running on a GICv5 host, we push an arch-timer-specific interrupt domain for the timer interrupts. This interrupt domain is used to mask the host interrupt when a GICv5 guest is running. However, this interrupt domain is still in place when running with a GICv3 guest on GICv5 hardware. The result is that some interrupt state changes are not correctly propragated to the host irqchip driver for legacy guests. Explicitly pass irqchip state changes though to the host irqchip driver when running a GICv3-based guest on a GICv5 host. This bypasses all masking, and thereby operates just as a native GICv3 guest would, with the exception of having an additional irq domain in the hierarchy. Fixes: 9491c63b6cd7 ("KVM: arm64: gic-v5: Enlighten arch timer for GICv5") Suggested-by: Marc Zyngier <maz@kernel.org> Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com> Link: https://lore.kernel.org/r/20260520091949.542365-19-maz@kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm64/kvm/arch_timer.c17
1 files changed, 7 insertions, 10 deletions
diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
index f003df76fdda7..53b67b4d0bf24 100644
--- a/arch/arm64/kvm/arch_timer.c
+++ b/arch/arm64/kvm/arch_timer.c
@@ -1294,7 +1294,12 @@ static int timer_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
static int timer_irq_set_irqchip_state(struct irq_data *d,
enum irqchip_irq_state which, bool val)
{
- if (which != IRQCHIP_STATE_ACTIVE || !irqd_is_forwarded_to_vcpu(d))
+ bool passthrough = which != IRQCHIP_STATE_ACTIVE ||
+ !irqd_is_forwarded_to_vcpu(d) ||
+ (kvm_vgic_global_state.type == VGIC_V5 &&
+ vgic_is_v3(kvm_get_running_vcpu()->kvm));
+
+ if (passthrough)
return irq_chip_set_parent_state(d, which, val);
if (val)
@@ -1307,15 +1312,7 @@ static int timer_irq_set_irqchip_state(struct irq_data *d,
static void timer_irq_eoi(struct irq_data *d)
{
- /*
- * On a GICv5 host, we still need to call EOI on the parent for
- * PPIs. The host driver already handles irqs which are forwarded to
- * vcpus, and skips the GIC CDDI while still doing the GIC CDEOI. This
- * is required to emulate the EOIMode=1 on GICv5 hardware. Failure to
- * call EOI unsurprisingly results in *BAD* lock-ups.
- */
- if (!irqd_is_forwarded_to_vcpu(d) ||
- kvm_vgic_global_state.type == VGIC_V5)
+ if (!irqd_is_forwarded_to_vcpu(d))
irq_chip_eoi_parent(d);
}