Commit 295b6921 authored by Marc Zyngier's avatar Marc Zyngier Committed by Oliver Upton
Browse files

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: default avatarFuad Tabba <tabba@google.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Tested-by: default avatarMark Brown <broonie@kernel.org>
Link: https://msgid.link/20251120172540.2267180-30-maz@kernel.org


Signed-off-by: default avatarOliver Upton <oupton@kernel.org>
parent cd4f6ee9
Loading
Loading
Loading
Loading
+19 −1
Original line number Diff line number Diff line
@@ -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;
	}