KVM: arm64: GICv3: Add GICv2 SGI handling to deactivation primitive

The GICv2 SGIs require additional handling for deactivation, as they
are effectively multiple interrrupts muxed into one. Make sure we
check for the source CPU when deactivating.

Tested-by: Fuad Tabba <tabba@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Tested-by: Mark Brown <broonie@kernel.org>
Link: https://msgid.link/20251120172540.2267180-30-maz@kernel.org
Signed-off-by: Oliver Upton <oupton@kernel.org>
This commit is contained in:
Marc Zyngier
2025-11-20 17:25:19 +00:00
committed by Oliver Upton
parent cd4f6ee99b
commit 295b692165

View File

@@ -176,11 +176,20 @@ void vgic_v3_deactivate(struct kvm_vcpu *vcpu, u64 val)
{
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
struct vgic_v3_cpu_if *cpuif = &vgic_cpu->vgic_v3;
u32 model = vcpu->kvm->arch.vgic.vgic_model;
struct kvm_vcpu *target_vcpu = NULL;
bool mmio = false, is_v2_sgi;
struct vgic_irq *irq;
unsigned long flags;
bool mmio = false;
u64 lr = 0;
u8 cpuid;
/* Snapshot CPUID, and remove it from the INTID */
cpuid = FIELD_GET(GENMASK_ULL(12, 10), val);
val &= ~GENMASK_ULL(12, 10);
is_v2_sgi = (model == KVM_DEV_TYPE_ARM_VGIC_V2 &&
val < VGIC_NR_SGIS);
/*
* We only deal with DIR when EOIMode==1, and only for SGI,
@@ -216,6 +225,9 @@ void vgic_v3_deactivate(struct kvm_vcpu *vcpu, u64 val)
* - Or the irq is active, but not in an LR, and we can
* directly deactivate it by building a pseudo-LR, fold it,
* and queue a request to prune the resulting ap_list,
*
* Special care must be taken to match the source CPUID when
* deactivating a GICv2 SGI.
*/
scoped_guard(raw_spinlock, &irq->irq_lock) {
target_vcpu = irq->vcpu;
@@ -233,6 +245,12 @@ void vgic_v3_deactivate(struct kvm_vcpu *vcpu, u64 val)
goto put;
}
/* GICv2 SGI: check that the cpuid matches */
if (is_v2_sgi && irq->active_source != cpuid) {
target_vcpu = NULL;
goto put;
}
/* (with a Dalek voice) DEACTIVATE!!!! */
lr = vgic_v3_compute_lr(vcpu, irq) & ~ICH_LR_ACTIVE_BIT;
}