Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Marc Zyngier and committed by
Oliver Upton
295b6921 cd4f6ee9

+19 -1
+19 -1
arch/arm64/kvm/vgic/vgic-v3.c
··· 176 176 { 177 177 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; 178 178 struct vgic_v3_cpu_if *cpuif = &vgic_cpu->vgic_v3; 179 + u32 model = vcpu->kvm->arch.vgic.vgic_model; 179 180 struct kvm_vcpu *target_vcpu = NULL; 181 + bool mmio = false, is_v2_sgi; 180 182 struct vgic_irq *irq; 181 183 unsigned long flags; 182 - bool mmio = false; 183 184 u64 lr = 0; 185 + u8 cpuid; 186 + 187 + /* Snapshot CPUID, and remove it from the INTID */ 188 + cpuid = FIELD_GET(GENMASK_ULL(12, 10), val); 189 + val &= ~GENMASK_ULL(12, 10); 190 + 191 + is_v2_sgi = (model == KVM_DEV_TYPE_ARM_VGIC_V2 && 192 + val < VGIC_NR_SGIS); 184 193 185 194 /* 186 195 * We only deal with DIR when EOIMode==1, and only for SGI, ··· 225 216 * - Or the irq is active, but not in an LR, and we can 226 217 * directly deactivate it by building a pseudo-LR, fold it, 227 218 * and queue a request to prune the resulting ap_list, 219 + * 220 + * Special care must be taken to match the source CPUID when 221 + * deactivating a GICv2 SGI. 228 222 */ 229 223 scoped_guard(raw_spinlock, &irq->irq_lock) { 230 224 target_vcpu = irq->vcpu; ··· 242 230 */ 243 231 if (irq->on_lr) { 244 232 mmio = true; 233 + goto put; 234 + } 235 + 236 + /* GICv2 SGI: check that the cpuid matches */ 237 + if (is_v2_sgi && irq->active_source != cpuid) { 238 + target_vcpu = NULL; 245 239 goto put; 246 240 } 247 241