]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: arm64: Make RAS registers UNDEF when RAS isn't advertised
authorMarc Zyngier <maz@kernel.org>
Mon, 21 Jul 2025 10:19:51 +0000 (11:19 +0100)
committerOliver Upton <oliver.upton@linux.dev>
Mon, 21 Jul 2025 16:35:57 +0000 (09:35 -0700)
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: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250721101955.535159-4-maz@kernel.org
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kvm/sys_regs.c

index 9d4fe892e8b4bdc107652713148044fd1e7847bf..0baa1b6050e70a90bfa641cb008a073921e6bf35 100644 (file)
@@ -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),