[PATCH 19/20] KVM: arm64: Add sanitisation to SCTLR_EL2

Fuad Tabba tabba at google.com
Thu Jan 29 10:11:16 PST 2026


Hi Marc,

On Mon, 26 Jan 2026 at 12:17, Marc Zyngier <maz at kernel.org> wrote:
>
> 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.
>
> Signed-off-by: Marc Zyngier <maz at kernel.org>

This would change slightly when you change patch 12, but it matches
the spec and those changes would be trivial to apply here.

Reviewed-by: Fuad Tabba <tabba at google.com>

Cheers,
/fuad






> ---
>  arch/arm64/include/asm/kvm_host.h |  2 +-
>  arch/arm64/kvm/config.c           | 82 +++++++++++++++++++++++++++++++
>  arch/arm64/kvm/nested.c           |  4 ++
>  3 files changed, 87 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 9dca94e4361f0..c82b071ade2a5 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -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) */
> diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
> index eebafb90bcf62..562513a4683e2 100644
> --- a/arch/arm64/kvm/config.c
> +++ b/arch/arm64/kvm/config.c
> @@ -1130,6 +1130,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,
> +                       RES0_WHEN_E2H1 | RES1_WHEN_E2H0 | REQUIRES_E2H1,
> +                       FEAT_AA32EL0),
> +       NEEDS_FEAT_FLAG(SCTLR_EL2_ITD   |
> +                       SCTLR_EL2_SED,
> +                       RES1_WHEN_E2H1 | RES0_WHEN_E2H0 | 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,
> +                       RES0_WHEN_E2H0 | 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),
> @@ -1249,6 +1327,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);
>  }
> @@ -1454,6 +1533,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;
> diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> index 96e899dbd9192..ed710228484f3 100644
> --- a/arch/arm64/kvm/nested.c
> +++ b/arch/arm64/kvm/nested.c
> @@ -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);
> --
> 2.47.3
>



More information about the linux-arm-kernel mailing list