arm64: cpuinfo: Split AArch32 registers out into a separate struct
authorWill Deacon <will@kernel.org>
Tue, 8 Jun 2021 18:02:54 +0000 (19:02 +0100)
committerWill Deacon <will@kernel.org>
Fri, 11 Jun 2021 12:25:40 +0000 (13:25 +0100)
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>
arch/arm64/include/asm/cpu.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/cpuinfo.c

index 9088e72..0f6d16f 100644 (file)
 /*
  * Records attributes of an individual CPU.
  */
-struct cpuinfo_arm64 {
-       struct cpu      cpu;
-       struct kobject  kobj;
-       u64             reg_ctr;
-       u64             reg_cntfrq;
-       u64             reg_dczid;
-       u64             reg_midr;
-       u64             reg_revidr;
-       u64             reg_gmid;
-
-       u64             reg_id_aa64dfr0;
-       u64             reg_id_aa64dfr1;
-       u64             reg_id_aa64isar0;
-       u64             reg_id_aa64isar1;
-       u64             reg_id_aa64mmfr0;
-       u64             reg_id_aa64mmfr1;
-       u64             reg_id_aa64mmfr2;
-       u64             reg_id_aa64pfr0;
-       u64             reg_id_aa64pfr1;
-       u64             reg_id_aa64zfr0;
-
+struct cpuinfo_32bit {
        u32             reg_id_dfr0;
        u32             reg_id_dfr1;
        u32             reg_id_isar0;
@@ -55,6 +35,30 @@ struct cpuinfo_arm64 {
        u32             reg_mvfr0;
        u32             reg_mvfr1;
        u32             reg_mvfr2;
+};
+
+struct cpuinfo_arm64 {
+       struct cpu      cpu;
+       struct kobject  kobj;
+       u64             reg_ctr;
+       u64             reg_cntfrq;
+       u64             reg_dczid;
+       u64             reg_midr;
+       u64             reg_revidr;
+       u64             reg_gmid;
+
+       u64             reg_id_aa64dfr0;
+       u64             reg_id_aa64dfr1;
+       u64             reg_id_aa64isar0;
+       u64             reg_id_aa64isar1;
+       u64             reg_id_aa64mmfr0;
+       u64             reg_id_aa64mmfr1;
+       u64             reg_id_aa64mmfr2;
+       u64             reg_id_aa64pfr0;
+       u64             reg_id_aa64pfr1;
+       u64             reg_id_aa64zfr0;
+
+       struct cpuinfo_32bit    aarch32;
 
        /* pseudo-ZCR for recording maximum ZCR_EL1 LEN value: */
        u64             reg_zcr;
index 0645300..33e5330 100644 (file)
@@ -871,6 +871,31 @@ static void __init init_cpu_hwcaps_indirect_list(void)
 
 static void __init setup_boot_cpu_capabilities(void);
 
+static void __init init_32bit_cpu_features(struct cpuinfo_32bit *info)
+{
+       init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0);
+       init_cpu_ftr_reg(SYS_ID_DFR1_EL1, info->reg_id_dfr1);
+       init_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0);
+       init_cpu_ftr_reg(SYS_ID_ISAR1_EL1, info->reg_id_isar1);
+       init_cpu_ftr_reg(SYS_ID_ISAR2_EL1, info->reg_id_isar2);
+       init_cpu_ftr_reg(SYS_ID_ISAR3_EL1, info->reg_id_isar3);
+       init_cpu_ftr_reg(SYS_ID_ISAR4_EL1, info->reg_id_isar4);
+       init_cpu_ftr_reg(SYS_ID_ISAR5_EL1, info->reg_id_isar5);
+       init_cpu_ftr_reg(SYS_ID_ISAR6_EL1, info->reg_id_isar6);
+       init_cpu_ftr_reg(SYS_ID_MMFR0_EL1, info->reg_id_mmfr0);
+       init_cpu_ftr_reg(SYS_ID_MMFR1_EL1, info->reg_id_mmfr1);
+       init_cpu_ftr_reg(SYS_ID_MMFR2_EL1, info->reg_id_mmfr2);
+       init_cpu_ftr_reg(SYS_ID_MMFR3_EL1, info->reg_id_mmfr3);
+       init_cpu_ftr_reg(SYS_ID_MMFR4_EL1, info->reg_id_mmfr4);
+       init_cpu_ftr_reg(SYS_ID_MMFR5_EL1, info->reg_id_mmfr5);
+       init_cpu_ftr_reg(SYS_ID_PFR0_EL1, info->reg_id_pfr0);
+       init_cpu_ftr_reg(SYS_ID_PFR1_EL1, info->reg_id_pfr1);
+       init_cpu_ftr_reg(SYS_ID_PFR2_EL1, info->reg_id_pfr2);
+       init_cpu_ftr_reg(SYS_MVFR0_EL1, info->reg_mvfr0);
+       init_cpu_ftr_reg(SYS_MVFR1_EL1, info->reg_mvfr1);
+       init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
+}
+
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
        /* Before we start using the tables, make sure it is sorted */
@@ -890,29 +915,8 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
        init_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1);
        init_cpu_ftr_reg(SYS_ID_AA64ZFR0_EL1, info->reg_id_aa64zfr0);
 
-       if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
-               init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0);
-               init_cpu_ftr_reg(SYS_ID_DFR1_EL1, info->reg_id_dfr1);
-               init_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0);
-               init_cpu_ftr_reg(SYS_ID_ISAR1_EL1, info->reg_id_isar1);
-               init_cpu_ftr_reg(SYS_ID_ISAR2_EL1, info->reg_id_isar2);
-               init_cpu_ftr_reg(SYS_ID_ISAR3_EL1, info->reg_id_isar3);
-               init_cpu_ftr_reg(SYS_ID_ISAR4_EL1, info->reg_id_isar4);
-               init_cpu_ftr_reg(SYS_ID_ISAR5_EL1, info->reg_id_isar5);
-               init_cpu_ftr_reg(SYS_ID_ISAR6_EL1, info->reg_id_isar6);
-               init_cpu_ftr_reg(SYS_ID_MMFR0_EL1, info->reg_id_mmfr0);
-               init_cpu_ftr_reg(SYS_ID_MMFR1_EL1, info->reg_id_mmfr1);
-               init_cpu_ftr_reg(SYS_ID_MMFR2_EL1, info->reg_id_mmfr2);
-               init_cpu_ftr_reg(SYS_ID_MMFR3_EL1, info->reg_id_mmfr3);
-               init_cpu_ftr_reg(SYS_ID_MMFR4_EL1, info->reg_id_mmfr4);
-               init_cpu_ftr_reg(SYS_ID_MMFR5_EL1, info->reg_id_mmfr5);
-               init_cpu_ftr_reg(SYS_ID_PFR0_EL1, info->reg_id_pfr0);
-               init_cpu_ftr_reg(SYS_ID_PFR1_EL1, info->reg_id_pfr1);
-               init_cpu_ftr_reg(SYS_ID_PFR2_EL1, info->reg_id_pfr2);
-               init_cpu_ftr_reg(SYS_MVFR0_EL1, info->reg_mvfr0);
-               init_cpu_ftr_reg(SYS_MVFR1_EL1, info->reg_mvfr1);
-               init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
-       }
+       if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
+               init_32bit_cpu_features(&info->aarch32);
 
        if (id_aa64pfr0_sve(info->reg_id_aa64pfr0)) {
                init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
@@ -986,21 +990,13 @@ static void relax_cpu_ftr_reg(u32 sys_id, int field)
        WARN_ON(!ftrp->width);
 }
 
-static int update_32bit_cpu_features(int cpu, struct cpuinfo_arm64 *info,
-                                    struct cpuinfo_arm64 *boot)
+static int update_32bit_cpu_features(int cpu, struct cpuinfo_32bit *info,
+                                    struct cpuinfo_32bit *boot)
 {
        int taint = 0;
        u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
 
        /*
-        * If we don't have AArch32 at all then skip the checks entirely
-        * as the register values may be UNKNOWN and we're not going to be
-        * using them for anything.
-        */
-       if (!id_aa64pfr0_32bit_el0(pfr0))
-               return taint;
-
-       /*
         * If we don't have AArch32 at EL1, then relax the strictness of
         * EL1-dependent register fields to avoid spurious sanity check fails.
         */
@@ -1151,15 +1147,23 @@ void update_cpu_features(int cpu,
         * value is the same on all CPUs.
         */
        if (IS_ENABLED(CONFIG_ARM64_MTE) &&
-           id_aa64pfr1_mte(info->reg_id_aa64pfr1))
+           id_aa64pfr1_mte(info->reg_id_aa64pfr1)) {
                taint |= check_update_ftr_reg(SYS_GMID_EL1, cpu,
                                              info->reg_gmid, boot->reg_gmid);
+       }
 
        /*
+        * If we don't have AArch32 at all then skip the checks entirely
+        * as the register values may be UNKNOWN and we're not going to be
+        * using them for anything.
+        *
         * This relies on a sanitised view of the AArch64 ID registers
         * (e.g. SYS_ID_AA64PFR0_EL1), so we call it last.
         */
-       taint |= update_32bit_cpu_features(cpu, info, boot);
+       if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
+               taint |= update_32bit_cpu_features(cpu, &info->aarch32,
+                                                  &boot->aarch32);
+       }
 
        /*
         * Mismatched CPU features are a recipe for disaster. Don't even
index 5321b82..87731fe 100644 (file)
@@ -344,6 +344,32 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
        pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
 }
 
+static void __cpuinfo_store_cpu_32bit(struct cpuinfo_32bit *info)
+{
+       info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1);
+       info->reg_id_dfr1 = read_cpuid(ID_DFR1_EL1);
+       info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
+       info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
+       info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
+       info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
+       info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
+       info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
+       info->reg_id_isar6 = read_cpuid(ID_ISAR6_EL1);
+       info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
+       info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
+       info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
+       info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
+       info->reg_id_mmfr4 = read_cpuid(ID_MMFR4_EL1);
+       info->reg_id_mmfr5 = read_cpuid(ID_MMFR5_EL1);
+       info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
+       info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
+       info->reg_id_pfr2 = read_cpuid(ID_PFR2_EL1);
+
+       info->reg_mvfr0 = read_cpuid(MVFR0_EL1);
+       info->reg_mvfr1 = read_cpuid(MVFR1_EL1);
+       info->reg_mvfr2 = read_cpuid(MVFR2_EL1);
+}
+
 static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
 {
        info->reg_cntfrq = arch_timer_get_cntfrq();
@@ -374,31 +400,8 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
        if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
                info->reg_gmid = read_cpuid(GMID_EL1);
 
-       /* Update the 32bit ID registers only if AArch32 is implemented */
-       if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
-               info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1);
-               info->reg_id_dfr1 = read_cpuid(ID_DFR1_EL1);
-               info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
-               info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
-               info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
-               info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
-               info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
-               info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
-               info->reg_id_isar6 = read_cpuid(ID_ISAR6_EL1);
-               info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
-               info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
-               info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
-               info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
-               info->reg_id_mmfr4 = read_cpuid(ID_MMFR4_EL1);
-               info->reg_id_mmfr5 = read_cpuid(ID_MMFR5_EL1);
-               info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
-               info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
-               info->reg_id_pfr2 = read_cpuid(ID_PFR2_EL1);
-
-               info->reg_mvfr0 = read_cpuid(MVFR0_EL1);
-               info->reg_mvfr1 = read_cpuid(MVFR1_EL1);
-               info->reg_mvfr2 = read_cpuid(MVFR2_EL1);
-       }
+       if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
+               __cpuinfo_store_cpu_32bit(&info->aarch32);
 
        if (IS_ENABLED(CONFIG_ARM64_SVE) &&
            id_aa64pfr0_sve(info->reg_id_aa64pfr0))