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: Move undeliverable interrupts to the end of ap_list

Interrupts in the ap_list that cannot be acted upon because they
are not enabled, or that their group is not enabled, shouldn't
make it into the LRs if we are space-constrained.

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-26-maz@kernel.org
Signed-off-by: Oliver Upton <oupton@kernel.org>

authored by

Marc Zyngier and committed by
Oliver Upton
33c1f60b 05984ba6

+22 -1
+22 -1
arch/arm64/kvm/vgic/vgic.c
··· 265 265 return NULL; 266 266 } 267 267 268 + struct vgic_sort_info { 269 + struct kvm_vcpu *vcpu; 270 + struct vgic_vmcr vmcr; 271 + }; 272 + 268 273 /* 269 274 * The order of items in the ap_lists defines how we'll pack things in LRs as 270 275 * well, the first items in the list being the first things populated in the ··· 278 273 * Pending, non-active interrupts must be placed at the head of the list. 279 274 * Otherwise things should be sorted by the priority field and the GIC 280 275 * hardware support will take care of preemption of priority groups etc. 276 + * Interrupts that are not deliverable should be at the end of the list. 281 277 * 282 278 * Return negative if "a" sorts before "b", 0 to preserve order, and positive 283 279 * to sort "b" before "a". ··· 288 282 { 289 283 struct vgic_irq *irqa = container_of(a, struct vgic_irq, ap_list); 290 284 struct vgic_irq *irqb = container_of(b, struct vgic_irq, ap_list); 285 + struct vgic_sort_info *info = priv; 286 + struct kvm_vcpu *vcpu = info->vcpu; 291 287 bool penda, pendb; 292 288 int ret; 293 289 ··· 302 294 303 295 raw_spin_lock(&irqa->irq_lock); 304 296 raw_spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING); 297 + 298 + /* Undeliverable interrupts should be last */ 299 + ret = (int)(vgic_target_oracle(irqb) == vcpu) - (int)(vgic_target_oracle(irqa) == vcpu); 300 + if (ret) 301 + goto out; 302 + 303 + /* Same thing for interrupts targeting a disabled group */ 304 + ret = (int)(irqb->group ? info->vmcr.grpen1 : info->vmcr.grpen0); 305 + ret -= (int)(irqa->group ? info->vmcr.grpen1 : info->vmcr.grpen0); 306 + if (ret) 307 + goto out; 305 308 306 309 penda = irqa->enabled && irq_is_pending(irqa) && !irqa->active; 307 310 pendb = irqb->enabled && irq_is_pending(irqb) && !irqb->active; ··· 339 320 static void vgic_sort_ap_list(struct kvm_vcpu *vcpu) 340 321 { 341 322 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; 323 + struct vgic_sort_info info = { .vcpu = vcpu, }; 342 324 343 325 lockdep_assert_held(&vgic_cpu->ap_list_lock); 344 326 345 - list_sort(NULL, &vgic_cpu->ap_list_head, vgic_irq_cmp); 327 + vgic_get_vmcr(vcpu, &info.vmcr); 328 + list_sort(&info, &vgic_cpu->ap_list_head, vgic_irq_cmp); 346 329 } 347 330 348 331 /*