Skip to content

Commit 930a58b

Browse files
committed
arm64: cpuinfo: Split AArch32 registers out into a separate struct
In preparation for late initialisation of the "sanitised" AArch32 register state, move the AArch32 registers out of 'struct cpuinfo' and into their own struct definition. Acked-by: Mark Rutland <mark.rutland@arm.com> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Link: https://lore.kernel.org/r/20210608180313.11502-2-will@kernel.org Signed-off-by: Will Deacon <will@kernel.org>
1 parent 21047e9 commit 930a58b

3 files changed

Lines changed: 92 additions & 81 deletions

File tree

arch/arm64/include/asm/cpu.h

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,7 @@
1212
/*
1313
* Records attributes of an individual CPU.
1414
*/
15-
struct cpuinfo_arm64 {
16-
struct cpu cpu;
17-
struct kobject kobj;
18-
u64 reg_ctr;
19-
u64 reg_cntfrq;
20-
u64 reg_dczid;
21-
u64 reg_midr;
22-
u64 reg_revidr;
23-
u64 reg_gmid;
24-
25-
u64 reg_id_aa64dfr0;
26-
u64 reg_id_aa64dfr1;
27-
u64 reg_id_aa64isar0;
28-
u64 reg_id_aa64isar1;
29-
u64 reg_id_aa64mmfr0;
30-
u64 reg_id_aa64mmfr1;
31-
u64 reg_id_aa64mmfr2;
32-
u64 reg_id_aa64pfr0;
33-
u64 reg_id_aa64pfr1;
34-
u64 reg_id_aa64zfr0;
35-
15+
struct cpuinfo_32bit {
3616
u32 reg_id_dfr0;
3717
u32 reg_id_dfr1;
3818
u32 reg_id_isar0;
@@ -55,6 +35,30 @@ struct cpuinfo_arm64 {
5535
u32 reg_mvfr0;
5636
u32 reg_mvfr1;
5737
u32 reg_mvfr2;
38+
};
39+
40+
struct cpuinfo_arm64 {
41+
struct cpu cpu;
42+
struct kobject kobj;
43+
u64 reg_ctr;
44+
u64 reg_cntfrq;
45+
u64 reg_dczid;
46+
u64 reg_midr;
47+
u64 reg_revidr;
48+
u64 reg_gmid;
49+
50+
u64 reg_id_aa64dfr0;
51+
u64 reg_id_aa64dfr1;
52+
u64 reg_id_aa64isar0;
53+
u64 reg_id_aa64isar1;
54+
u64 reg_id_aa64mmfr0;
55+
u64 reg_id_aa64mmfr1;
56+
u64 reg_id_aa64mmfr2;
57+
u64 reg_id_aa64pfr0;
58+
u64 reg_id_aa64pfr1;
59+
u64 reg_id_aa64zfr0;
60+
61+
struct cpuinfo_32bit aarch32;
5862

5963
/* pseudo-ZCR for recording maximum ZCR_EL1 LEN value: */
6064
u64 reg_zcr;

arch/arm64/kernel/cpufeature.c

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,31 @@ static void __init init_cpu_hwcaps_indirect_list(void)
871871

872872
static void __init setup_boot_cpu_capabilities(void);
873873

874+
static void __init init_32bit_cpu_features(struct cpuinfo_32bit *info)
875+
{
876+
init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0);
877+
init_cpu_ftr_reg(SYS_ID_DFR1_EL1, info->reg_id_dfr1);
878+
init_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0);
879+
init_cpu_ftr_reg(SYS_ID_ISAR1_EL1, info->reg_id_isar1);
880+
init_cpu_ftr_reg(SYS_ID_ISAR2_EL1, info->reg_id_isar2);
881+
init_cpu_ftr_reg(SYS_ID_ISAR3_EL1, info->reg_id_isar3);
882+
init_cpu_ftr_reg(SYS_ID_ISAR4_EL1, info->reg_id_isar4);
883+
init_cpu_ftr_reg(SYS_ID_ISAR5_EL1, info->reg_id_isar5);
884+
init_cpu_ftr_reg(SYS_ID_ISAR6_EL1, info->reg_id_isar6);
885+
init_cpu_ftr_reg(SYS_ID_MMFR0_EL1, info->reg_id_mmfr0);
886+
init_cpu_ftr_reg(SYS_ID_MMFR1_EL1, info->reg_id_mmfr1);
887+
init_cpu_ftr_reg(SYS_ID_MMFR2_EL1, info->reg_id_mmfr2);
888+
init_cpu_ftr_reg(SYS_ID_MMFR3_EL1, info->reg_id_mmfr3);
889+
init_cpu_ftr_reg(SYS_ID_MMFR4_EL1, info->reg_id_mmfr4);
890+
init_cpu_ftr_reg(SYS_ID_MMFR5_EL1, info->reg_id_mmfr5);
891+
init_cpu_ftr_reg(SYS_ID_PFR0_EL1, info->reg_id_pfr0);
892+
init_cpu_ftr_reg(SYS_ID_PFR1_EL1, info->reg_id_pfr1);
893+
init_cpu_ftr_reg(SYS_ID_PFR2_EL1, info->reg_id_pfr2);
894+
init_cpu_ftr_reg(SYS_MVFR0_EL1, info->reg_mvfr0);
895+
init_cpu_ftr_reg(SYS_MVFR1_EL1, info->reg_mvfr1);
896+
init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
897+
}
898+
874899
void __init init_cpu_features(struct cpuinfo_arm64 *info)
875900
{
876901
/* Before we start using the tables, make sure it is sorted */
@@ -890,29 +915,8 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
890915
init_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1);
891916
init_cpu_ftr_reg(SYS_ID_AA64ZFR0_EL1, info->reg_id_aa64zfr0);
892917

893-
if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
894-
init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0);
895-
init_cpu_ftr_reg(SYS_ID_DFR1_EL1, info->reg_id_dfr1);
896-
init_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0);
897-
init_cpu_ftr_reg(SYS_ID_ISAR1_EL1, info->reg_id_isar1);
898-
init_cpu_ftr_reg(SYS_ID_ISAR2_EL1, info->reg_id_isar2);
899-
init_cpu_ftr_reg(SYS_ID_ISAR3_EL1, info->reg_id_isar3);
900-
init_cpu_ftr_reg(SYS_ID_ISAR4_EL1, info->reg_id_isar4);
901-
init_cpu_ftr_reg(SYS_ID_ISAR5_EL1, info->reg_id_isar5);
902-
init_cpu_ftr_reg(SYS_ID_ISAR6_EL1, info->reg_id_isar6);
903-
init_cpu_ftr_reg(SYS_ID_MMFR0_EL1, info->reg_id_mmfr0);
904-
init_cpu_ftr_reg(SYS_ID_MMFR1_EL1, info->reg_id_mmfr1);
905-
init_cpu_ftr_reg(SYS_ID_MMFR2_EL1, info->reg_id_mmfr2);
906-
init_cpu_ftr_reg(SYS_ID_MMFR3_EL1, info->reg_id_mmfr3);
907-
init_cpu_ftr_reg(SYS_ID_MMFR4_EL1, info->reg_id_mmfr4);
908-
init_cpu_ftr_reg(SYS_ID_MMFR5_EL1, info->reg_id_mmfr5);
909-
init_cpu_ftr_reg(SYS_ID_PFR0_EL1, info->reg_id_pfr0);
910-
init_cpu_ftr_reg(SYS_ID_PFR1_EL1, info->reg_id_pfr1);
911-
init_cpu_ftr_reg(SYS_ID_PFR2_EL1, info->reg_id_pfr2);
912-
init_cpu_ftr_reg(SYS_MVFR0_EL1, info->reg_mvfr0);
913-
init_cpu_ftr_reg(SYS_MVFR1_EL1, info->reg_mvfr1);
914-
init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
915-
}
918+
if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
919+
init_32bit_cpu_features(&info->aarch32);
916920

917921
if (id_aa64pfr0_sve(info->reg_id_aa64pfr0)) {
918922
init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
@@ -986,20 +990,12 @@ static void relax_cpu_ftr_reg(u32 sys_id, int field)
986990
WARN_ON(!ftrp->width);
987991
}
988992

989-
static int update_32bit_cpu_features(int cpu, struct cpuinfo_arm64 *info,
990-
struct cpuinfo_arm64 *boot)
993+
static int update_32bit_cpu_features(int cpu, struct cpuinfo_32bit *info,
994+
struct cpuinfo_32bit *boot)
991995
{
992996
int taint = 0;
993997
u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
994998

995-
/*
996-
* If we don't have AArch32 at all then skip the checks entirely
997-
* as the register values may be UNKNOWN and we're not going to be
998-
* using them for anything.
999-
*/
1000-
if (!id_aa64pfr0_32bit_el0(pfr0))
1001-
return taint;
1002-
1003999
/*
10041000
* If we don't have AArch32 at EL1, then relax the strictness of
10051001
* EL1-dependent register fields to avoid spurious sanity check fails.
@@ -1151,15 +1147,23 @@ void update_cpu_features(int cpu,
11511147
* value is the same on all CPUs.
11521148
*/
11531149
if (IS_ENABLED(CONFIG_ARM64_MTE) &&
1154-
id_aa64pfr1_mte(info->reg_id_aa64pfr1))
1150+
id_aa64pfr1_mte(info->reg_id_aa64pfr1)) {
11551151
taint |= check_update_ftr_reg(SYS_GMID_EL1, cpu,
11561152
info->reg_gmid, boot->reg_gmid);
1153+
}
11571154

11581155
/*
1156+
* If we don't have AArch32 at all then skip the checks entirely
1157+
* as the register values may be UNKNOWN and we're not going to be
1158+
* using them for anything.
1159+
*
11591160
* This relies on a sanitised view of the AArch64 ID registers
11601161
* (e.g. SYS_ID_AA64PFR0_EL1), so we call it last.
11611162
*/
1162-
taint |= update_32bit_cpu_features(cpu, info, boot);
1163+
if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
1164+
taint |= update_32bit_cpu_features(cpu, &info->aarch32,
1165+
&boot->aarch32);
1166+
}
11631167

11641168
/*
11651169
* Mismatched CPU features are a recipe for disaster. Don't even

arch/arm64/kernel/cpuinfo.c

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,32 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
344344
pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
345345
}
346346

347+
static void __cpuinfo_store_cpu_32bit(struct cpuinfo_32bit *info)
348+
{
349+
info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1);
350+
info->reg_id_dfr1 = read_cpuid(ID_DFR1_EL1);
351+
info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
352+
info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
353+
info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
354+
info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
355+
info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
356+
info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
357+
info->reg_id_isar6 = read_cpuid(ID_ISAR6_EL1);
358+
info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
359+
info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
360+
info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
361+
info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
362+
info->reg_id_mmfr4 = read_cpuid(ID_MMFR4_EL1);
363+
info->reg_id_mmfr5 = read_cpuid(ID_MMFR5_EL1);
364+
info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
365+
info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
366+
info->reg_id_pfr2 = read_cpuid(ID_PFR2_EL1);
367+
368+
info->reg_mvfr0 = read_cpuid(MVFR0_EL1);
369+
info->reg_mvfr1 = read_cpuid(MVFR1_EL1);
370+
info->reg_mvfr2 = read_cpuid(MVFR2_EL1);
371+
}
372+
347373
static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
348374
{
349375
info->reg_cntfrq = arch_timer_get_cntfrq();
@@ -374,31 +400,8 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
374400
if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
375401
info->reg_gmid = read_cpuid(GMID_EL1);
376402

377-
/* Update the 32bit ID registers only if AArch32 is implemented */
378-
if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
379-
info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1);
380-
info->reg_id_dfr1 = read_cpuid(ID_DFR1_EL1);
381-
info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
382-
info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
383-
info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
384-
info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
385-
info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
386-
info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
387-
info->reg_id_isar6 = read_cpuid(ID_ISAR6_EL1);
388-
info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
389-
info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
390-
info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
391-
info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
392-
info->reg_id_mmfr4 = read_cpuid(ID_MMFR4_EL1);
393-
info->reg_id_mmfr5 = read_cpuid(ID_MMFR5_EL1);
394-
info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
395-
info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
396-
info->reg_id_pfr2 = read_cpuid(ID_PFR2_EL1);
397-
398-
info->reg_mvfr0 = read_cpuid(MVFR0_EL1);
399-
info->reg_mvfr1 = read_cpuid(MVFR1_EL1);
400-
info->reg_mvfr2 = read_cpuid(MVFR2_EL1);
401-
}
403+
if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
404+
__cpuinfo_store_cpu_32bit(&info->aarch32);
402405

403406
if (IS_ENABLED(CONFIG_ARM64_SVE) &&
404407
id_aa64pfr0_sve(info->reg_id_aa64pfr0))

0 commit comments

Comments
 (0)