Commit 281c6c06 authored by Marc Zyngier's avatar Marc Zyngier Committed by Oliver Upton
Browse files

KVM: arm64: GICv2: Handle LR overflow when EOImode==0



Similarly to the GICv3 version, handle the EOIcount-driven deactivation
by walking the overflow list.

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


Signed-off-by: default avatarOliver Upton <oupton@kernel.org>
parent 78ffc284
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -100,6 +100,8 @@ static void vgic_v2_fold_lr(struct kvm_vcpu *vcpu, u32 val)
	vgic_put_irq(vcpu->kvm, irq);
}

static u32 vgic_v2_compute_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq);

/*
 * transfer the content of the LRs back into the corresponding ap_list:
 * - active bit is transferred as is
@@ -111,12 +113,37 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
{
	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
	struct vgic_v2_cpu_if *cpuif = &vgic_cpu->vgic_v2;
	u32 eoicount = FIELD_GET(GICH_HCR_EOICOUNT, cpuif->vgic_hcr);
	struct vgic_irq *irq;

	DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());

	for (int lr = 0; lr < vgic_cpu->vgic_v2.used_lrs; lr++)
		vgic_v2_fold_lr(vcpu, cpuif->vgic_lr[lr]);

	/* See the GICv3 equivalent for the EOIcount handling rationale */
	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
		u32 lr;

		if (!eoicount) {
			break;
		} else {
			guard(raw_spinlock)(&irq->irq_lock);

			if (!(likely(vgic_target_oracle(irq) == vcpu) &&
			      irq->active))
				continue;

			lr = vgic_v2_compute_lr(vcpu, irq) & ~GICH_LR_ACTIVE_BIT;
		}

		if (lr & GICH_LR_HW)
			writel_relaxed(FIELD_GET(GICH_LR_PHYSID_CPUID, lr),
				       kvm_vgic_global_state.gicc_base + GIC_CPU_DEACTIVATE);
		vgic_v2_fold_lr(vcpu, lr);
		eoicount--;
	}

	cpuif->used_lrs = 0;
}