]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
arm64/sme: Move storage of reg_smidr to __cpuinfo_store_cpu()
authorMark Brown <broonie@kernel.org>
Tue, 17 Dec 2024 21:59:48 +0000 (21:59 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 17 Feb 2025 09:05:05 +0000 (10:05 +0100)
commit d3c7c48d004f6c8d892f39b5d69884fd0fe98c81 upstream.

In commit 892f7237b3ff ("arm64: Delay initialisation of
cpuinfo_arm64::reg_{zcr,smcr}") we moved access to ZCR, SMCR and SMIDR
later in the boot process in order to ensure that we don't attempt to
interact with them if SVE or SME is disabled on the command line.
Unfortunately when initialising the boot CPU in init_cpu_features() we work
on a copy of the struct cpuinfo_arm64 for the boot CPU used only during
boot, not the percpu copy used by the sysfs code. The expectation of the
feature identification code was that the ID registers would be read in
__cpuinfo_store_cpu() and the values not modified by init_cpu_features().

The main reason for the original change was to avoid early accesses to
ZCR on practical systems that were seen shipping with SVE reported in ID
registers but traps enabled at EL3 and handled as fatal errors, SME was
rolled in due to the similarity with SVE. Since then we have removed the
early accesses to ZCR and SMCR in commits:

  abef0695f9665c3d ("arm64/sve: Remove ZCR pseudo register from cpufeature code")
  391208485c3ad50f ("arm64/sve: Remove SMCR pseudo register from cpufeature code")

so only the SMIDR_EL1 part of the change remains. Since SMIDR_EL1 is
only trapped via FEAT_IDST and not the SME trap it is less likely to be
affected by similar issues, and the factors that lead to issues with SVE
are less likely to apply to SME.

Since we have not yet seen practical SME systems that need to use a
command line override (and are only just beginning to see SME systems at
all) and the ID register read is much more likely to be safe let's just
store SMIDR_EL1 along with all the other ID register reads in
__cpuinfo_store_cpu().

This issue wasn't apparent when testing on emulated platforms that do not
report values in SMIDR_EL1.

Fixes: 892f7237b3ff ("arm64: Delay initialisation of cpuinfo_arm64::reg_{zcr,smcr}")
Signed-off-by: Mark Brown <broonie@kernel.org>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20241217-arm64-fix-boot-cpu-smidr-v3-1-7be278a85623@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/cpuinfo.c

index 29e1e5eb7a0e060b7853857c1fc632c672fce6fa..709f2b51be6df3625d2aaa2278cb9305e79758fb 100644 (file)
@@ -1153,12 +1153,6 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
            id_aa64pfr1_sme(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1))) {
                unsigned long cpacr = cpacr_save_enable_kernel_sme();
 
-               /*
-                * We mask out SMPS since even if the hardware
-                * supports priorities the kernel does not at present
-                * and we block access to them.
-                */
-               info->reg_smidr = read_cpuid(SMIDR_EL1) & ~SMIDR_EL1_SMPS;
                vec_init_vq_map(ARM64_VEC_SME);
 
                cpacr_restore(cpacr);
@@ -1406,13 +1400,6 @@ void update_cpu_features(int cpu,
            id_aa64pfr1_sme(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1))) {
                unsigned long cpacr = cpacr_save_enable_kernel_sme();
 
-               /*
-                * We mask out SMPS since even if the hardware
-                * supports priorities the kernel does not at present
-                * and we block access to them.
-                */
-               info->reg_smidr = read_cpuid(SMIDR_EL1) & ~SMIDR_EL1_SMPS;
-
                /* Probe vector lengths */
                if (!system_capabilities_finalized())
                        vec_update_vq_map(ARM64_VEC_SME);
index 44718d0482b3b43175a1673ccbebc70cf16ddcb2..aec5e3947c780a9f29b1c12bf077df6cfed20461 100644 (file)
@@ -478,6 +478,16 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
        if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
                __cpuinfo_store_cpu_32bit(&info->aarch32);
 
+       if (IS_ENABLED(CONFIG_ARM64_SME) &&
+           id_aa64pfr1_sme(info->reg_id_aa64pfr1)) {
+               /*
+                * We mask out SMPS since even if the hardware
+                * supports priorities the kernel does not at present
+                * and we block access to them.
+                */
+               info->reg_smidr = read_cpuid(SMIDR_EL1) & ~SMIDR_EL1_SMPS;
+       }
+
        cpuinfo_detect_icache_policy(info);
 }