arm64: Add the arm64.nosme command line option
authorMarc Zyngier <maz@kernel.org>
Thu, 30 Jun 2022 16:04:58 +0000 (17:04 +0100)
committerWill Deacon <will@kernel.org>
Fri, 1 Jul 2022 14:22:52 +0000 (15:22 +0100)
In order to be able to completely disable SME even if the HW
seems to support it (most likely because the FW is broken),
move the SME setup into the EL2 finalisation block, and
use a new idreg override to deal with it.

Note that we also nuke id_aa64smfr0_el1 as a byproduct.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20220630160500.1536744-8-maz@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
Documentation/admin-guide/kernel-parameters.txt
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/el2_setup.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/hyp-stub.S
arch/arm64/kernel/idreg-override.c

index 2522b11..301d2d0 100644 (file)
        arm64.nomte     [ARM64] Unconditionally disable Memory Tagging Extension
                        support
 
+       arm64.nosme     [ARM64] Unconditionally disable Scalable Matrix
+                       Extension support
+
        ataflop=        [HW,M68k]
 
        atarimouse=     [HW,MOUSE] Atari Mouse
index 14a8f3d..5adda12 100644 (file)
@@ -909,6 +909,7 @@ static inline unsigned int get_vmid_bits(u64 mmfr1)
 
 extern struct arm64_ftr_override id_aa64mmfr1_override;
 extern struct arm64_ftr_override id_aa64pfr1_override;
+extern struct arm64_ftr_override id_aa64smfr0_override;
 extern struct arm64_ftr_override id_aa64isar1_override;
 extern struct arm64_ftr_override id_aa64isar2_override;
 
index 34ceff0..18641dc 100644 (file)
 .Lskip_sve_\@:
 .endm
 
-/* SME register access and priority mapping */
-.macro __init_el2_nvhe_sme
-       mrs     x1, id_aa64pfr1_el1
-       ubfx    x1, x1, #ID_AA64PFR1_SME_SHIFT, #4
-       cbz     x1, .Lskip_sme_\@
-
-       bic     x0, x0, #CPTR_EL2_TSM           // Also disable SME traps
-       msr     cptr_el2, x0                    // Disable copro. traps to EL2
-       isb
-
-       mrs     x1, sctlr_el2
-       orr     x1, x1, #SCTLR_ELx_ENTP2        // Disable TPIDR2 traps
-       msr     sctlr_el2, x1
-       isb
-
-       mov     x1, #0                          // SMCR controls
-
-       mrs_s   x2, SYS_ID_AA64SMFR0_EL1
-       ubfx    x2, x2, #ID_AA64SMFR0_FA64_SHIFT, #1 // Full FP in SM?
-       cbz     x2, .Lskip_sme_fa64_\@
-
-       orr     x1, x1, SMCR_ELx_FA64_MASK
-.Lskip_sme_fa64_\@:
-
-       orr     x1, x1, #SMCR_ELx_LEN_MASK      // Enable full SME vector
-       msr_s   SYS_SMCR_EL2, x1                // length for EL1.
-
-       mrs_s   x1, SYS_SMIDR_EL1               // Priority mapping supported?
-       ubfx    x1, x1, #SMIDR_EL1_SMPS_SHIFT, #1
-       cbz     x1, .Lskip_sme_\@
-
-       msr_s   SYS_SMPRIMAP_EL2, xzr           // Make all priorities equal
-
-       mrs     x1, id_aa64mmfr1_el1            // HCRX_EL2 present?
-       ubfx    x1, x1, #ID_AA64MMFR1_HCX_SHIFT, #4
-       cbz     x1, .Lskip_sme_\@
-
-       mrs_s   x1, SYS_HCRX_EL2
-       orr     x1, x1, #HCRX_EL2_SMPME_MASK    // Enable priority mapping
-       msr_s   SYS_HCRX_EL2, x1
-
-.Lskip_sme_\@:
-.endm
-
 /* Disable any fine grained traps */
 .macro __init_el2_fgt
        mrs     x1, id_aa64mmfr0_el1
        __init_el2_nvhe_idregs
        __init_el2_nvhe_cptr
        __init_el2_nvhe_sve
-       __init_el2_nvhe_sme
        __init_el2_fgt
        __init_el2_nvhe_prepare_eret
 .endm
index a97913d..a7d0686 100644 (file)
@@ -632,6 +632,7 @@ static const struct arm64_ftr_bits ftr_raz[] = {
 
 struct arm64_ftr_override __ro_after_init id_aa64mmfr1_override;
 struct arm64_ftr_override __ro_after_init id_aa64pfr1_override;
+struct arm64_ftr_override __ro_after_init id_aa64smfr0_override;
 struct arm64_ftr_override __ro_after_init id_aa64isar1_override;
 struct arm64_ftr_override __ro_after_init id_aa64isar2_override;
 
@@ -672,7 +673,8 @@ static const struct __ftr_reg_entry {
        ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64PFR1_EL1, ftr_id_aa64pfr1,
                               &id_aa64pfr1_override),
        ARM64_FTR_REG(SYS_ID_AA64ZFR0_EL1, ftr_id_aa64zfr0),
-       ARM64_FTR_REG(SYS_ID_AA64SMFR0_EL1, ftr_id_aa64smfr0),
+       ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64SMFR0_EL1, ftr_id_aa64smfr0,
+                              &id_aa64smfr0_override),
 
        /* Op1 = 0, CRn = 0, CRm = 5 */
        ARM64_FTR_REG(SYS_ID_AA64DFR0_EL1, ftr_id_aa64dfr0),
index de1ab98..0c69def 100644 (file)
@@ -98,6 +98,47 @@ SYM_CODE_START_LOCAL(elx_sync)
 SYM_CODE_END(elx_sync)
 
 SYM_CODE_START_LOCAL(__finalise_el2)
+       check_override id_aa64pfr1 ID_AA64PFR1_SME_SHIFT .Linit_sme .Lskip_sme
+
+.Linit_sme:    /* SME register access and priority mapping */
+       mrs     x0, cptr_el2                    // Disable SME traps
+       bic     x0, x0, #CPTR_EL2_TSM
+       msr     cptr_el2, x0
+       isb
+
+       mrs     x1, sctlr_el2
+       orr     x1, x1, #SCTLR_ELx_ENTP2        // Disable TPIDR2 traps
+       msr     sctlr_el2, x1
+       isb
+
+       mov     x1, #0                          // SMCR controls
+
+       mrs_s   x2, SYS_ID_AA64SMFR0_EL1
+       ubfx    x2, x2, #ID_AA64SMFR0_FA64_SHIFT, #1 // Full FP in SM?
+       cbz     x2, .Lskip_sme_fa64
+
+       orr     x1, x1, SMCR_ELx_FA64_MASK
+.Lskip_sme_fa64:
+
+       orr     x1, x1, #SMCR_ELx_LEN_MASK      // Enable full SME vector
+       msr_s   SYS_SMCR_EL2, x1                // length for EL1.
+
+       mrs_s   x1, SYS_SMIDR_EL1               // Priority mapping supported?
+       ubfx    x1, x1, #SMIDR_EL1_SMPS_SHIFT, #1
+       cbz     x1, .Lskip_sme
+
+       msr_s   SYS_SMPRIMAP_EL2, xzr           // Make all priorities equal
+
+       mrs     x1, id_aa64mmfr1_el1            // HCRX_EL2 present?
+       ubfx    x1, x1, #ID_AA64MMFR1_HCX_SHIFT, #4
+       cbz     x1, .Lskip_sme
+
+       mrs_s   x1, SYS_HCRX_EL2
+       orr     x1, x1, #HCRX_EL2_SMPME_MASK    // Enable priority mapping
+       msr_s   SYS_HCRX_EL2, x1
+
+.Lskip_sme:
+
        // nVHE? No way! Give me the real thing!
        // Sanity check: MMU *must* be off
        mrs     x1, sctlr_el2
index 1e5f3db..9314f0a 100644 (file)
@@ -55,12 +55,28 @@ static const struct ftr_set_desc mmfr1 __initconst = {
        },
 };
 
+static bool __init pfr1_sme_filter(u64 val)
+{
+       /*
+        * Similarly to SVE, disabling SME also means disabling all
+        * the features that are associated with it. Just set
+        * id_aa64smfr0_el1 to 0 and don't look back.
+        */
+       if (!val) {
+               id_aa64smfr0_override.val = 0;
+               id_aa64smfr0_override.mask = GENMASK(63, 0);
+       }
+
+       return true;
+}
+
 static const struct ftr_set_desc pfr1 __initconst = {
        .name           = "id_aa64pfr1",
        .override       = &id_aa64pfr1_override,
        .fields         = {
                FIELD("bt", ID_AA64PFR1_BT_SHIFT, NULL),
                FIELD("mte", ID_AA64PFR1_MTE_SHIFT, NULL),
+               FIELD("sme", ID_AA64PFR1_SME_SHIFT, pfr1_sme_filter),
                {}
        },
 };
@@ -114,6 +130,7 @@ static const struct {
 } aliases[] __initconst = {
        { "kvm-arm.mode=nvhe",          "id_aa64mmfr1.vh=0" },
        { "kvm-arm.mode=protected",     "id_aa64mmfr1.vh=0" },
+       { "arm64.nosme",                "id_aa64pfr1.sme=0" },
        { "arm64.nobti",                "id_aa64pfr1.bt=0" },
        { "arm64.nopauth",
          "id_aa64isar1.gpi=0 id_aa64isar1.gpa=0 "