Skip to content

Commit 892f723

Browse files
Marc Zyngierwilldeacon
Marc Zyngier
authored andcommitted
arm64: Delay initialisation of cpuinfo_arm64::reg_{zcr,smcr}
Even if we are now able to tell the kernel to avoid exposing SVE/SME from the command line, we still have a couple of places where we unconditionally access the ZCR_EL1 (resp. SMCR_EL1) registers. On systems with broken firmwares, this results in a crash even if arm64.nosve (resp. arm64.nosme) was passed on the command-line. To avoid this, only update cpuinfo_arm64::reg_{zcr,smcr} once we have computed the sanitised version for the corresponding feature registers (ID_AA64PFR0 for SVE, and ID_AA64PFR1 for SME). This results in some minor refactoring. Reviewed-by: Mark Brown <[email protected]> Reviewed-by: Peter Collingbourne <[email protected]> Tested-by: Peter Collingbourne <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent f96d67a commit 892f723

File tree

2 files changed

+29
-28
lines changed

2 files changed

+29
-28
lines changed

arch/arm64/kernel/cpufeature.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,15 +1001,24 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
10011001
if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
10021002
init_32bit_cpu_features(&info->aarch32);
10031003

1004-
if (id_aa64pfr0_sve(info->reg_id_aa64pfr0)) {
1004+
if (IS_ENABLED(CONFIG_ARM64_SVE) &&
1005+
id_aa64pfr0_sve(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
1006+
info->reg_zcr = read_zcr_features();
10051007
init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
10061008
vec_init_vq_map(ARM64_VEC_SVE);
10071009
}
10081010

1009-
if (id_aa64pfr1_sme(info->reg_id_aa64pfr1)) {
1011+
if (IS_ENABLED(CONFIG_ARM64_SME) &&
1012+
id_aa64pfr1_sme(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1))) {
1013+
info->reg_smcr = read_smcr_features();
1014+
/*
1015+
* We mask out SMPS since even if the hardware
1016+
* supports priorities the kernel does not at present
1017+
* and we block access to them.
1018+
*/
1019+
info->reg_smidr = read_cpuid(SMIDR_EL1) & ~SMIDR_EL1_SMPS;
10101020
init_cpu_ftr_reg(SYS_SMCR_EL1, info->reg_smcr);
1011-
if (IS_ENABLED(CONFIG_ARM64_SME))
1012-
vec_init_vq_map(ARM64_VEC_SME);
1021+
vec_init_vq_map(ARM64_VEC_SME);
10131022
}
10141023

10151024
if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
@@ -1241,23 +1250,31 @@ void update_cpu_features(int cpu,
12411250
taint |= check_update_ftr_reg(SYS_ID_AA64SMFR0_EL1, cpu,
12421251
info->reg_id_aa64smfr0, boot->reg_id_aa64smfr0);
12431252

1244-
if (id_aa64pfr0_sve(info->reg_id_aa64pfr0)) {
1253+
if (IS_ENABLED(CONFIG_ARM64_SVE) &&
1254+
id_aa64pfr0_sve(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
1255+
info->reg_zcr = read_zcr_features();
12451256
taint |= check_update_ftr_reg(SYS_ZCR_EL1, cpu,
12461257
info->reg_zcr, boot->reg_zcr);
12471258

1248-
/* Probe vector lengths, unless we already gave up on SVE */
1249-
if (id_aa64pfr0_sve(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1)) &&
1250-
!system_capabilities_finalized())
1259+
/* Probe vector lengths */
1260+
if (!system_capabilities_finalized())
12511261
vec_update_vq_map(ARM64_VEC_SVE);
12521262
}
12531263

1254-
if (id_aa64pfr1_sme(info->reg_id_aa64pfr1)) {
1264+
if (IS_ENABLED(CONFIG_ARM64_SME) &&
1265+
id_aa64pfr1_sme(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1))) {
1266+
info->reg_smcr = read_smcr_features();
1267+
/*
1268+
* We mask out SMPS since even if the hardware
1269+
* supports priorities the kernel does not at present
1270+
* and we block access to them.
1271+
*/
1272+
info->reg_smidr = read_cpuid(SMIDR_EL1) & ~SMIDR_EL1_SMPS;
12551273
taint |= check_update_ftr_reg(SYS_SMCR_EL1, cpu,
12561274
info->reg_smcr, boot->reg_smcr);
12571275

1258-
/* Probe vector lengths, unless we already gave up on SME */
1259-
if (id_aa64pfr1_sme(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1)) &&
1260-
!system_capabilities_finalized())
1276+
/* Probe vector lengths */
1277+
if (!system_capabilities_finalized())
12611278
vec_update_vq_map(ARM64_VEC_SME);
12621279
}
12631280

arch/arm64/kernel/cpuinfo.c

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -439,22 +439,6 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
439439
if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
440440
__cpuinfo_store_cpu_32bit(&info->aarch32);
441441

442-
if (IS_ENABLED(CONFIG_ARM64_SVE) &&
443-
id_aa64pfr0_sve(info->reg_id_aa64pfr0))
444-
info->reg_zcr = read_zcr_features();
445-
446-
if (IS_ENABLED(CONFIG_ARM64_SME) &&
447-
id_aa64pfr1_sme(info->reg_id_aa64pfr1)) {
448-
info->reg_smcr = read_smcr_features();
449-
450-
/*
451-
* We mask out SMPS since even if the hardware
452-
* supports priorities the kernel does not at present
453-
* and we block access to them.
454-
*/
455-
info->reg_smidr = read_cpuid(SMIDR_EL1) & ~SMIDR_EL1_SMPS;
456-
}
457-
458442
cpuinfo_detect_icache_policy(info);
459443
}
460444

0 commit comments

Comments
 (0)