]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: arm64: Describe SCTLR2_ELx RESx masks
authorOliver Upton <oliver.upton@linux.dev>
Tue, 8 Jul 2025 17:25:19 +0000 (10:25 -0700)
committerOliver Upton <oliver.upton@linux.dev>
Tue, 8 Jul 2025 18:36:35 +0000 (11:36 -0700)
External abort injection will soon rely on a sanitised view of
SCTLR2_ELx to determine exception routing. Compute the RESx masks.

Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250708172532.1699409-15-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kvm/config.c
arch/arm64/kvm/nested.c

index 54911a93b0018e8e644496f8c4fd6b61e00ea66f..e8a33e91e665036d59d6063af64e6932d7f0fcf7 100644 (file)
@@ -131,6 +131,8 @@ struct reg_bits_to_feat_map {
 #define FEAT_SPMU              ID_AA64DFR1_EL1, SPMU, IMP
 #define FEAT_SPE_nVM           ID_AA64DFR2_EL1, SPE_nVM, IMP
 #define FEAT_STEP2             ID_AA64DFR2_EL1, STEP, IMP
+#define FEAT_SYSREG128         ID_AA64ISAR2_EL1, SYSREG_128, IMP
+#define FEAT_CPA2              ID_AA64ISAR3_EL1, CPA, CPA2
 
 static bool not_feat_aa64el3(struct kvm *kvm)
 {
@@ -832,6 +834,23 @@ static const struct reg_bits_to_feat_map hcr_feat_map[] = {
        NEEDS_FEAT_FIXED(HCR_EL2_E2H, compute_hcr_e2h),
 };
 
+static const struct reg_bits_to_feat_map sctlr2_feat_map[] = {
+       NEEDS_FEAT(SCTLR2_EL1_NMEA      |
+                  SCTLR2_EL1_EASE,
+                  FEAT_DoubleFault2),
+       NEEDS_FEAT(SCTLR2_EL1_EnADERR, feat_aderr),
+       NEEDS_FEAT(SCTLR2_EL1_EnANERR, feat_anerr),
+       NEEDS_FEAT(SCTLR2_EL1_EnIDCP128, FEAT_SYSREG128),
+       NEEDS_FEAT(SCTLR2_EL1_EnPACM    |
+                  SCTLR2_EL1_EnPACM0,
+                  feat_pauth_lr),
+       NEEDS_FEAT(SCTLR2_EL1_CPTA      |
+                  SCTLR2_EL1_CPTA0     |
+                  SCTLR2_EL1_CPTM      |
+                  SCTLR2_EL1_CPTM0,
+                  FEAT_CPA2),
+};
+
 static void __init check_feat_map(const struct reg_bits_to_feat_map *map,
                                  int map_size, u64 res0, const char *str)
 {
@@ -863,6 +882,8 @@ void __init check_feature_map(void)
                       __HCRX_EL2_RES0, "HCRX_EL2");
        check_feat_map(hcr_feat_map, ARRAY_SIZE(hcr_feat_map),
                       HCR_EL2_RES0, "HCR_EL2");
+       check_feat_map(sctlr2_feat_map, ARRAY_SIZE(sctlr2_feat_map),
+                      SCTLR2_EL1_RES0, "SCTLR2_EL1");
 }
 
 static bool idreg_feat_match(struct kvm *kvm, const struct reg_bits_to_feat_map *map)
@@ -1077,6 +1098,13 @@ void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *r
                *res0 |= HCR_EL2_RES0 | (mask & ~fixed);
                *res1 = HCR_EL2_RES1 | (mask & fixed);
                break;
+       case SCTLR2_EL1:
+       case SCTLR2_EL2:
+               *res0 = compute_res0_bits(kvm, sctlr2_feat_map,
+                                         ARRAY_SIZE(sctlr2_feat_map), 0, 0);
+               *res0 |= SCTLR2_EL1_RES0;
+               *res1 = SCTLR2_EL1_RES1;
+               break;
        default:
                WARN_ON_ONCE(1);
                *res0 = *res1 = 0;
index c7063f670187337b6a872a4ab55fc99b33759c28..096747a61bf65278aa78170520f338002ab1e12d 100644 (file)
@@ -1690,6 +1690,12 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
                res0 |= SCTLR_EL1_EPAN;
        set_sysreg_masks(kvm, SCTLR_EL1, res0, res1);
 
+       /* SCTLR2_ELx */
+       get_reg_fixed_bits(kvm, SCTLR2_EL1, &res0, &res1);
+       set_sysreg_masks(kvm, SCTLR2_EL1, res0, res1);
+       get_reg_fixed_bits(kvm, SCTLR2_EL2, &res0, &res1);
+       set_sysreg_masks(kvm, SCTLR2_EL2, res0, res1);
+
        /* MDCR_EL2 */
        res0 = MDCR_EL2_RES0;
        res1 = MDCR_EL2_RES1;