KVM: arm64: Handle AArch32 SPSR_{irq,abt,und,fiq} as RAZ/WI
authorMarc Zyngier <maz@kernel.org>
Mon, 23 Oct 2023 09:54:44 +0000 (10:54 +0100)
committerOliver Upton <oliver.upton@linux.dev>
Wed, 25 Oct 2023 00:25:06 +0000 (00:25 +0000)
When trapping accesses from a NV guest that tries to access
SPSR_{irq,abt,und,fiq}, make sure we handle them as RAZ/WI,
as if AArch32 wasn't implemented.

This involves a bit of repainting to make the visibility
handler more generic.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20231023095444.1587322-6-maz@kernel.org
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/include/asm/sysreg.h
arch/arm64/kvm/sys_regs.c

index 4a20a7dc5bc4cbf68829a9fedb7c62d6c48e7612..5e65f51c10d2444c036aaef62d1e865c3d0f6c55 100644 (file)
 #define SYS_SPSR_EL2                   sys_reg(3, 4, 4, 0, 0)
 #define SYS_ELR_EL2                    sys_reg(3, 4, 4, 0, 1)
 #define SYS_SP_EL1                     sys_reg(3, 4, 4, 1, 0)
+#define SYS_SPSR_irq                   sys_reg(3, 4, 4, 3, 0)
+#define SYS_SPSR_abt                   sys_reg(3, 4, 4, 3, 1)
+#define SYS_SPSR_und                   sys_reg(3, 4, 4, 3, 2)
+#define SYS_SPSR_fiq                   sys_reg(3, 4, 4, 3, 3)
 #define SYS_IFSR32_EL2                 sys_reg(3, 4, 5, 0, 1)
 #define SYS_AFSR0_EL2                  sys_reg(3, 4, 5, 1, 0)
 #define SYS_AFSR1_EL2                  sys_reg(3, 4, 5, 1, 1)
index 0f8690027a0f87c7e7b04193e288a083a8f001b8..16d2b2c4badaceaa35311f180092993cff0fb01f 100644 (file)
@@ -1791,8 +1791,8 @@ static unsigned int el2_visibility(const struct kvm_vcpu *vcpu,
  * HCR_EL2.E2H==1, and only in the sysreg table for convenience of
  * handling traps. Given that, they are always hidden from userspace.
  */
-static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu,
-                                   const struct sys_reg_desc *rd)
+static unsigned int hidden_user_visibility(const struct kvm_vcpu *vcpu,
+                                          const struct sys_reg_desc *rd)
 {
        return REG_HIDDEN_USER;
 }
@@ -1803,7 +1803,7 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu,
        .reset = rst,                           \
        .reg = name##_EL1,                      \
        .val = v,                               \
-       .visibility = elx2_visibility,          \
+       .visibility = hidden_user_visibility,   \
 }
 
 /*
@@ -2387,6 +2387,16 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        EL2_REG(ELR_EL2, access_rw, reset_val, 0),
        { SYS_DESC(SYS_SP_EL1), access_sp_el1},
 
+       /* AArch32 SPSR_* are RES0 if trapped from a NV guest */
+       { SYS_DESC(SYS_SPSR_irq), .access = trap_raz_wi,
+         .visibility = hidden_user_visibility },
+       { SYS_DESC(SYS_SPSR_abt), .access = trap_raz_wi,
+         .visibility = hidden_user_visibility },
+       { SYS_DESC(SYS_SPSR_und), .access = trap_raz_wi,
+         .visibility = hidden_user_visibility },
+       { SYS_DESC(SYS_SPSR_fiq), .access = trap_raz_wi,
+         .visibility = hidden_user_visibility },
+
        { SYS_DESC(SYS_IFSR32_EL2), trap_undef, reset_unknown, IFSR32_EL2 },
        EL2_REG(AFSR0_EL2, access_rw, reset_val, 0),
        EL2_REG(AFSR1_EL2, access_rw, reset_val, 0),