]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: arm64: Wire up SCTLR2_ELx sysreg descriptors
authorOliver Upton <oliver.upton@linux.dev>
Tue, 8 Jul 2025 17:25:16 +0000 (10:25 -0700)
committerOliver Upton <oliver.upton@linux.dev>
Tue, 8 Jul 2025 18:36:35 +0000 (11:36 -0700)
Set up the sysreg descriptors for SCTLR2_ELx, along with the associated
storage and VNCR mapping.

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

index 20d63ece313889f9cf50f1686531d5834a47046e..e54d29feb469bf07448349df55a79759bae6574a 100644 (file)
@@ -523,6 +523,7 @@ enum vcpu_sysreg {
        /* Anything from this can be RES0/RES1 sanitised */
        MARKER(__SANITISED_REG_START__),
        TCR2_EL2,       /* Extended Translation Control Register (EL2) */
+       SCTLR2_EL2,     /* System Control Register 2 (EL2) */
        MDCR_EL2,       /* Monitor Debug Configuration Register (EL2) */
        CNTHCTL_EL2,    /* Counter-timer Hypervisor Control register */
 
@@ -537,6 +538,7 @@ enum vcpu_sysreg {
        VNCR(TTBR1_EL1),/* Translation Table Base Register 1 */
        VNCR(TCR_EL1),  /* Translation Control Register */
        VNCR(TCR2_EL1), /* Extended Translation Control Register */
+       VNCR(SCTLR2_EL1), /* System Control Register 2 */
        VNCR(ESR_EL1),  /* Exception Syndrome Register */
        VNCR(AFSR0_EL1),/* Auxiliary Fault Status Register 0 */
        VNCR(AFSR1_EL1),/* Auxiliary Fault Status Register 1 */
@@ -1204,6 +1206,7 @@ static inline bool __vcpu_read_sys_reg_from_cpu(int reg, u64 *val)
        case IFSR32_EL2:        *val = read_sysreg_s(SYS_IFSR32_EL2);   break;
        case DBGVCR32_EL2:      *val = read_sysreg_s(SYS_DBGVCR32_EL2); break;
        case ZCR_EL1:           *val = read_sysreg_s(SYS_ZCR_EL12);     break;
+       case SCTLR2_EL1:        *val = read_sysreg_s(SYS_SCTLR2_EL12);  break;
        default:                return false;
        }
 
@@ -1254,6 +1257,7 @@ static inline bool __vcpu_write_sys_reg_to_cpu(u64 val, int reg)
        case IFSR32_EL2:        write_sysreg_s(val, SYS_IFSR32_EL2);    break;
        case DBGVCR32_EL2:      write_sysreg_s(val, SYS_DBGVCR32_EL2);  break;
        case ZCR_EL1:           write_sysreg_s(val, SYS_ZCR_EL12);      break;
+       case SCTLR2_EL1:        write_sysreg_s(val, SYS_SCTLR2_EL12);   break;
        default:                return false;
        }
 
@@ -1685,6 +1689,9 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val);
 #define kvm_has_ras(k)                                 \
        (kvm_has_feat((k), ID_AA64PFR0_EL1, RAS, IMP))
 
+#define kvm_has_sctlr2(k)                              \
+       (kvm_has_feat((k), ID_AA64MMFR3_EL1, SCTLRX, IMP))
+
 static inline bool kvm_arch_has_irq_bypass(void)
 {
        return true;
index f4ec53166d8e11590330b9f8580d8f2ecdeea466..f6ec500ad3fa0d22ea815a65eef8f47c506aaadd 100644 (file)
@@ -51,6 +51,7 @@
 #define VNCR_SP_EL1             0x240
 #define VNCR_VBAR_EL1           0x250
 #define VNCR_TCR2_EL1          0x270
+#define VNCR_SCTLR2_EL1                0x278
 #define VNCR_PIRE0_EL1         0x290
 #define VNCR_PIR_EL1           0x2A0
 #define VNCR_POR_EL1           0x2A8
index b6d75d473ab8864af590f38f4bd6c70cc25c632b..a3dacfce2e5b40029740f4550f88539841fcab3f 100644 (file)
@@ -144,6 +144,7 @@ static bool get_el2_to_el1_mapping(unsigned int reg,
                MAPPED_EL2_SYSREG(SPSR_EL2,    SPSR_EL1,    NULL             );
                MAPPED_EL2_SYSREG(ZCR_EL2,     ZCR_EL1,     NULL             );
                MAPPED_EL2_SYSREG(CONTEXTIDR_EL2, CONTEXTIDR_EL1, NULL       );
+               MAPPED_EL2_SYSREG(SCTLR2_EL2,  SCTLR2_EL1,  NULL             );
        default:
                return false;
        }
@@ -2483,6 +2484,21 @@ static unsigned int vncr_el2_visibility(const struct kvm_vcpu *vcpu,
        return REG_HIDDEN;
 }
 
+static unsigned int sctlr2_visibility(const struct kvm_vcpu *vcpu,
+                                     const struct sys_reg_desc *rd)
+{
+       if (kvm_has_sctlr2(vcpu->kvm))
+               return 0;
+
+       return REG_HIDDEN;
+}
+
+static unsigned int sctlr2_el2_visibility(const struct kvm_vcpu *vcpu,
+                                         const struct sys_reg_desc *rd)
+{
+       return __el2_visibility(vcpu, rd, sctlr2_visibility);
+}
+
 static bool access_zcr_el2(struct kvm_vcpu *vcpu,
                           struct sys_reg_params *p,
                           const struct sys_reg_desc *r)
@@ -2955,6 +2971,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_SCTLR_EL1), access_vm_reg, reset_val, SCTLR_EL1, 0x00C50078 },
        { SYS_DESC(SYS_ACTLR_EL1), access_actlr, reset_actlr, ACTLR_EL1 },
        { SYS_DESC(SYS_CPACR_EL1), NULL, reset_val, CPACR_EL1, 0 },
+       { SYS_DESC(SYS_SCTLR2_EL1), access_vm_reg, reset_val, SCTLR2_EL1, 0,
+         .visibility = sctlr2_visibility },
 
        MTE_REG(RGSR_EL1),
        MTE_REG(GCR_EL1),
@@ -3302,6 +3320,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        EL2_REG_VNCR(VMPIDR_EL2, reset_unknown, 0),
        EL2_REG(SCTLR_EL2, access_rw, reset_val, SCTLR_EL2_RES1),
        EL2_REG(ACTLR_EL2, access_rw, reset_val, 0),
+       EL2_REG_FILTERED(SCTLR2_EL2, access_vm_reg, reset_val, 0,
+                        sctlr2_el2_visibility),
        EL2_REG_VNCR(HCR_EL2, reset_hcr, 0),
        EL2_REG(MDCR_EL2, access_mdcr, reset_mdcr, 0),
        EL2_REG(CPTR_EL2, access_rw, reset_val, CPTR_NVHE_EL2_RES1),