Commit 05984ba6 authored by Marc Zyngier's avatar Marc Zyngier Committed by Oliver Upton
Browse files

KVM: arm64: Invert ap_list sorting to push active interrupts out



Having established that pending interrupts should have priority
to be moved into the LRs over the active interrupts, implement this
in the ap_list sorting.

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-25-maz@kernel.org


Signed-off-by: default avatarOliver Upton <oupton@kernel.org>
parent 76b2eda6
Loading
Loading
Loading
Loading
+12 −15
Original line number Diff line number Diff line
@@ -270,10 +270,7 @@ struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
 * well, the first items in the list being the first things populated in the
 * LRs.
 *
 * A hard rule is that active interrupts can never be pushed out of the LRs
 * (and therefore take priority) since we cannot reliably trap on deactivation
 * of IRQs and therefore they have to be present in the LRs.
 *
 * Pending, non-active interrupts must be placed at the head of the list.
 * Otherwise things should be sorted by the priority field and the GIC
 * hardware support will take care of preemption of priority groups etc.
 *
@@ -298,21 +295,21 @@ static int vgic_irq_cmp(void *priv, const struct list_head *a,
	raw_spin_lock(&irqa->irq_lock);
	raw_spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING);

	if (irqa->active || irqb->active) {
		ret = (int)irqb->active - (int)irqa->active;
		goto out;
	}
	penda = irqa->enabled && irq_is_pending(irqa) && !irqa->active;
	pendb = irqb->enabled && irq_is_pending(irqb) && !irqb->active;

	penda = irqa->enabled && irq_is_pending(irqa);
	pendb = irqb->enabled && irq_is_pending(irqb);

	if (!penda || !pendb) {
	ret = (int)pendb - (int)penda;
	if (ret)
		goto out;
	}

	/* Both pending and enabled, sort by priority */
	ret = irqa->priority - irqb->priority;
	/* Both pending and enabled, sort by priority (lower number first) */
	ret = (int)irqa->priority - (int)irqb->priority;
	if (ret)
		goto out;

	/* Finally, HW bit active interrupts have priority over non-HW ones */
	ret = (int)irqb->hw - (int)irqa->hw;

out:
	raw_spin_unlock(&irqb->irq_lock);
	raw_spin_unlock(&irqa->irq_lock);