Commit d11a327e authored by Marc Zyngier's avatar Marc Zyngier
Browse files

KVM: arm64: vgic-v3: Restrict SEIS workaround to known broken systems



Contrary to what df652bcf ("KVM: arm64: vgic-v3: Work around GICv3
locally generated SErrors") was asserting, there is at least one other
system out there (Cavium ThunderX2) implementing SEIS, and not in
an obviously broken way.

So instead of imposing the M1 workaround on an innocent bystander,
let's limit it to the two known broken Apple implementations.

Fixes: df652bcf ("KVM: arm64: vgic-v3: Work around GICv3 locally generated SErrors")
Reported-by: default avatarArd Biesheuvel <ardb@kernel.org>
Tested-by: default avatarArd Biesheuvel <ardb@kernel.org>
Acked-by: default avatarArd Biesheuvel <ardb@kernel.org>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20220122103912.795026-1-maz@kernel.org
parent 094d00f8
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -983,6 +983,9 @@ static void __vgic_v3_read_ctlr(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
	val = ((vtr >> 29) & 7) << ICC_CTLR_EL1_PRI_BITS_SHIFT;
	/* IDbits */
	val |= ((vtr >> 23) & 7) << ICC_CTLR_EL1_ID_BITS_SHIFT;
	/* SEIS */
	if (kvm_vgic_global_state.ich_vtr_el2 & ICH_VTR_SEIS_MASK)
		val |= BIT(ICC_CTLR_EL1_SEIS_SHIFT);
	/* A3V */
	val |= ((vtr >> 21) & 1) << ICC_CTLR_EL1_A3V_SHIFT;
	/* EOImode */
+15 −2
Original line number Diff line number Diff line
@@ -609,6 +609,18 @@ static int __init early_gicv4_enable(char *buf)
}
early_param("kvm-arm.vgic_v4_enable", early_gicv4_enable);

static const struct midr_range broken_seis[] = {
	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM),
	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM),
	{},
};

static bool vgic_v3_broken_seis(void)
{
	return ((kvm_vgic_global_state.ich_vtr_el2 & ICH_VTR_SEIS_MASK) &&
		is_midr_in_range_list(read_cpuid_id(), broken_seis));
}

/**
 * vgic_v3_probe - probe for a VGICv3 compatible interrupt controller
 * @info:	pointer to the GIC description
@@ -676,9 +688,10 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
		group1_trap = true;
	}

	if (kvm_vgic_global_state.ich_vtr_el2 & ICH_VTR_SEIS_MASK) {
		kvm_info("GICv3 with locally generated SEI\n");
	if (vgic_v3_broken_seis()) {
		kvm_info("GICv3 with broken locally generated SEI\n");

		kvm_vgic_global_state.ich_vtr_el2 &= ~ICH_VTR_SEIS_MASK;
		group0_trap = true;
		group1_trap = true;
		if (ich_vtr_el2 & ICH_VTR_TDS_MASK)