[PATCH 19/20] KVM: arm64: Add sanitisation to SCTLR_EL2
Marc Zyngier
maz at kernel.org
Mon Jan 26 04:16:53 PST 2026
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>
---
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