]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: arm64: Add sanitisation to SCTLR_EL2
authorMarc Zyngier <maz@kernel.org>
Mon, 2 Feb 2026 18:43:28 +0000 (18:43 +0000)
committerMarc Zyngier <maz@kernel.org>
Thu, 5 Feb 2026 09:02:13 +0000 (09:02 +0000)
Sanitise SCTLR_EL2 the usual way. The most important aspect of
this is that we benefit from SCTLR_EL2.SPAN being RES1 when
HCR_EL2.E2H==0.

Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
Link: https://patch.msgid.link/20260202184329.2724080-20-maz@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/include/asm/kvm_host.h
arch/arm64/kvm/config.c
arch/arm64/kvm/nested.c

index 20ebc1610ac8495b5ef6dd588d58a783cd46a1eb..771ef1b61f9a9928b999ec2b4542f60284ed0b1c 100644 (file)
@@ -495,7 +495,6 @@ enum vcpu_sysreg {
        DBGVCR32_EL2,   /* Debug Vector Catch Register */
 
        /* EL2 registers */
-       SCTLR_EL2,      /* System Control Register (EL2) */
        ACTLR_EL2,      /* Auxiliary Control Register (EL2) */
        CPTR_EL2,       /* Architectural Feature Trap Register (EL2) */
        HACR_EL2,       /* Hypervisor Auxiliary Control Register */
@@ -526,6 +525,7 @@ enum vcpu_sysreg {
 
        /* Anything from this can be RES0/RES1 sanitised */
        MARKER(__SANITISED_REG_START__),
+       SCTLR_EL2,      /* System Control Register (EL2) */
        TCR2_EL2,       /* Extended Translation Control Register (EL2) */
        SCTLR2_EL2,     /* System Control Register 2 (EL2) */
        MDCR_EL2,       /* Monitor Debug Configuration Register (EL2) */
index 8640f9c9b2e0e8c70e681d042837013be091d0f5..d9f553cbf9dfdf585f3cb4d748ce2ab2337a0322 100644 (file)
@@ -1123,6 +1123,84 @@ static const struct reg_bits_to_feat_map sctlr_el1_feat_map[] = {
 static const DECLARE_FEAT_MAP(sctlr_el1_desc, SCTLR_EL1,
                              sctlr_el1_feat_map, FEAT_AA64EL1);
 
+static const struct reg_bits_to_feat_map sctlr_el2_feat_map[] = {
+       NEEDS_FEAT_FLAG(SCTLR_EL2_CP15BEN,
+                       RES1_WHEN_E2H0 | REQUIRES_E2H1,
+                       FEAT_AA32EL0),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_ITD   |
+                       SCTLR_EL2_SED,
+                       RES1_WHEN_E2H1 | REQUIRES_E2H1,
+                       FEAT_AA32EL0),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_BT0, REQUIRES_E2H1, FEAT_BTI),
+       NEEDS_FEAT(SCTLR_EL2_BT, FEAT_BTI),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_CMOW, REQUIRES_E2H1, FEAT_CMOW),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_TSCXT,
+                       RES1_WHEN_E2H1 | REQUIRES_E2H1,
+                       feat_csv2_2_csv2_1p2),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_EIS   |
+                       SCTLR_EL2_EOS,
+                       AS_RES1, FEAT_ExS),
+       NEEDS_FEAT(SCTLR_EL2_EnFPM, FEAT_FPMR),
+       NEEDS_FEAT(SCTLR_EL2_IESB, FEAT_IESB),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_EnALS, REQUIRES_E2H1, FEAT_LS64),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_EnAS0, REQUIRES_E2H1, FEAT_LS64_ACCDATA),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_EnASR, REQUIRES_E2H1, FEAT_LS64_V),
+       NEEDS_FEAT(SCTLR_EL2_nAA, FEAT_LSE2),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_LSMAOE        |
+                       SCTLR_EL2_nTLSMD,
+                       AS_RES1 | REQUIRES_E2H1, FEAT_LSMAOC),
+       NEEDS_FEAT(SCTLR_EL2_EE, FEAT_MixedEnd),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_E0E, REQUIRES_E2H1, feat_mixedendel0),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_MSCEn, REQUIRES_E2H1, FEAT_MOPS),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_ATA0  |
+                       SCTLR_EL2_TCF0,
+                       REQUIRES_E2H1, FEAT_MTE2),
+       NEEDS_FEAT(SCTLR_EL2_ATA        |
+                  SCTLR_EL2_TCF,
+                  FEAT_MTE2),
+       NEEDS_FEAT(SCTLR_EL2_ITFSB, feat_mte_async),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_TCSO0, REQUIRES_E2H1, FEAT_MTE_STORE_ONLY),
+       NEEDS_FEAT(SCTLR_EL2_TCSO,
+                  FEAT_MTE_STORE_ONLY),
+       NEEDS_FEAT(SCTLR_EL2_NMI        |
+                  SCTLR_EL2_SPINTMASK,
+                  FEAT_NMI),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_SPAN, AS_RES1 | REQUIRES_E2H1, FEAT_PAN),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_EPAN, REQUIRES_E2H1, FEAT_PAN3),
+       NEEDS_FEAT(SCTLR_EL2_EnDA       |
+                  SCTLR_EL2_EnDB       |
+                  SCTLR_EL2_EnIA       |
+                  SCTLR_EL2_EnIB,
+                  feat_pauth),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_EnTP2, REQUIRES_E2H1, FEAT_SME),
+       NEEDS_FEAT(SCTLR_EL2_EnRCTX, FEAT_SPECRES),
+       NEEDS_FEAT(SCTLR_EL2_DSSBS, FEAT_SSBS),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_TIDCP, REQUIRES_E2H1, FEAT_TIDCP1),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_TWEDEL        |
+                       SCTLR_EL2_TWEDEn,
+                       REQUIRES_E2H1, FEAT_TWED),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_nTWE  |
+                       SCTLR_EL2_nTWI,
+                       AS_RES1 | REQUIRES_E2H1, FEAT_AA64EL2),
+       NEEDS_FEAT_FLAG(SCTLR_EL2_UCI   |
+                       SCTLR_EL2_UCT   |
+                       SCTLR_EL2_DZE   |
+                       SCTLR_EL2_SA0,
+                       REQUIRES_E2H1, FEAT_AA64EL2),
+       NEEDS_FEAT(SCTLR_EL2_WXN        |
+                  SCTLR_EL2_I          |
+                  SCTLR_EL2_SA         |
+                  SCTLR_EL2_C          |
+                  SCTLR_EL2_A          |
+                  SCTLR_EL2_M,
+                  FEAT_AA64EL2),
+       FORCE_RES0(SCTLR_EL2_RES0),
+       FORCE_RES1(SCTLR_EL2_RES1),
+};
+
+static const DECLARE_FEAT_MAP(sctlr_el2_desc, SCTLR_EL2,
+                             sctlr_el2_feat_map, FEAT_AA64EL2);
+
 static const struct reg_bits_to_feat_map mdcr_el2_feat_map[] = {
        NEEDS_FEAT(MDCR_EL2_EBWE, FEAT_Debugv8p9),
        NEEDS_FEAT(MDCR_EL2_TDOSA, FEAT_DoubleLock),
@@ -1247,6 +1325,7 @@ void __init check_feature_map(void)
        check_reg_desc(&sctlr2_desc);
        check_reg_desc(&tcr2_el2_desc);
        check_reg_desc(&sctlr_el1_desc);
+       check_reg_desc(&sctlr_el2_desc);
        check_reg_desc(&mdcr_el2_desc);
        check_reg_desc(&vtcr_el2_desc);
 }
@@ -1443,6 +1522,9 @@ struct resx get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg)
        case SCTLR_EL1:
                resx = compute_reg_resx_bits(kvm, &sctlr_el1_desc, 0, 0);
                break;
+       case SCTLR_EL2:
+               resx = compute_reg_resx_bits(kvm, &sctlr_el2_desc, 0, 0);
+               break;
        case MDCR_EL2:
                resx = compute_reg_resx_bits(kvm, &mdcr_el2_desc, 0, 0);
                break;
index 96e899dbd9192873780864899399455ee4e4e1e6..ed710228484f34cb0a4ead26e3f2d1c2e9f895fc 100644 (file)
@@ -1766,6 +1766,10 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
        resx = get_reg_fixed_bits(kvm, SCTLR_EL1);
        set_sysreg_masks(kvm, SCTLR_EL1, resx);
 
+       /* SCTLR_EL2 */
+       resx = get_reg_fixed_bits(kvm, SCTLR_EL2);
+       set_sysreg_masks(kvm, SCTLR_EL2, resx);
+
        /* SCTLR2_ELx */
        resx = get_reg_fixed_bits(kvm, SCTLR2_EL1);
        set_sysreg_masks(kvm, SCTLR2_EL1, resx);