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

KVM: arm64: Make RAS registers UNDEF when RAS isn't advertised



We currently always expose FEAT_RAS when available on the host.

As we are about to make this feature selectable from userspace,
check for it being present before emulating register accesses
as RAZ/WI, and inject an UNDEF otherwise.

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250721101955.535159-4-maz@kernel.org


Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
parent 303084ad
Loading
Loading
Loading
Loading
+25 −8
Original line number Diff line number Diff line
@@ -2656,6 +2656,23 @@ static bool access_mdcr(struct kvm_vcpu *vcpu,
	return true;
}

static bool access_ras(struct kvm_vcpu *vcpu,
		       struct sys_reg_params *p,
		       const struct sys_reg_desc *r)
{
	struct kvm *kvm = vcpu->kvm;

	switch(reg_to_encoding(r)) {
	default:
		if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, RAS, IMP)) {
			kvm_inject_undefined(vcpu);
			return false;
		}
	}

	return trap_raz_wi(vcpu, p, r);
}

/*
 * For historical (ahem ABI) reasons, KVM treated MIDR_EL1, REVIDR_EL1, and
 * AIDR_EL1 as "invariant" registers, meaning userspace cannot change them.
@@ -3003,14 +3020,14 @@ static const struct sys_reg_desc sys_reg_descs[] = {
	{ SYS_DESC(SYS_AFSR1_EL1), access_vm_reg, reset_unknown, AFSR1_EL1 },
	{ SYS_DESC(SYS_ESR_EL1), access_vm_reg, reset_unknown, ESR_EL1 },

	{ SYS_DESC(SYS_ERRIDR_EL1), trap_raz_wi },
	{ SYS_DESC(SYS_ERRSELR_EL1), trap_raz_wi },
	{ SYS_DESC(SYS_ERXFR_EL1), trap_raz_wi },
	{ SYS_DESC(SYS_ERXCTLR_EL1), trap_raz_wi },
	{ SYS_DESC(SYS_ERXSTATUS_EL1), trap_raz_wi },
	{ SYS_DESC(SYS_ERXADDR_EL1), trap_raz_wi },
	{ SYS_DESC(SYS_ERXMISC0_EL1), trap_raz_wi },
	{ SYS_DESC(SYS_ERXMISC1_EL1), trap_raz_wi },
	{ SYS_DESC(SYS_ERRIDR_EL1), access_ras },
	{ SYS_DESC(SYS_ERRSELR_EL1), access_ras },
	{ SYS_DESC(SYS_ERXFR_EL1), access_ras },
	{ SYS_DESC(SYS_ERXCTLR_EL1), access_ras },
	{ SYS_DESC(SYS_ERXSTATUS_EL1), access_ras },
	{ SYS_DESC(SYS_ERXADDR_EL1), access_ras },
	{ SYS_DESC(SYS_ERXMISC0_EL1), access_ras },
	{ SYS_DESC(SYS_ERXMISC1_EL1), access_ras },

	MTE_REG(TFSR_EL1),
	MTE_REG(TFSRE0_EL1),