On Fri, Feb 06, 2015 at 06:00:29PM +0000, Mark Rutland wrote: > commit 44b82b7700d05a52cd983799d3ecde1a976b3bed upstream. > > [backport to 3.16.x: fold in missing MIDR_EL1 recording] > Thank you Mark, I'll queue this for the next 3.16 kernel release. Cheers, -- Luís > Commit d7a49086f263164a (arm64: cpuinfo: print info for all CPUs) > attempted to clean up /proc/cpuinfo, but due to concerns regarding > further changes was reverted in commit 5e39977edf6500fd (Revert "arm64: > cpuinfo: print info for all CPUs"). > > There are two major issues with the arm64 /proc/cpuinfo format > currently: > > * The "Features" line describes (only) the 64-bit hwcaps, which is > problematic for some 32-bit applications which attempt to parse it. As > the same names are used for analogous ISA features (e.g. aes) despite > these generally being architecturally unrelated, it is not possible to > simply append the 64-bit and 32-bit hwcaps in a manner that might not > be misleading to some applications. > > Various potential solutions have appeared in vendor kernels. Typically > the format of the Features line varies depending on whether the task > is 32-bit. > > * Information is only printed regarding a single CPU. This does not > match the ARM format, and does not provide sufficient information in > big.LITTLE systems where CPUs are heterogeneous. The CPU information > printed is queried from the current CPU's registers, which is racy > w.r.t. cross-cpu migration. > > This patch attempts to solve these issues. The following changes are > made: > > * When a task with a LINUX32 personality attempts to read /proc/cpuinfo, > the "Features" line contains the decoded 32-bit hwcaps, as with the > arm port. Otherwise, the decoded 64-bit hwcaps are shown. This aligns > with the behaviour of COMPAT_UTS_MACHINE and COMPAT_ELF_PLATFORM. In > the absense of compat support, the Features line is empty. > > The set of hwcaps injected into a task's auxval are unaffected. > > * Properties are printed per-cpu, as with the ARM port. The per-cpu > information is queried from pre-recorded cpu information (as used by > the sanity checks). > > * As with the previous attempt at fixing up /proc/cpuinfo, the hardware > field is removed. The only users so far are 32-bit applications tied > to particular boards, so no portable applications should be affected, > and this should prevent future tying to particular boards. > > The following differences remain: > > * No model_name is printed, as this cannot be queried from the hardware > and cannot be provided in a stable fashion. Use of the CPU > {implementor,variant,part,revision} fields is sufficient to identify a > CPU and is portable across arm and arm64. > > * The following system-wide properties are not provided, as they are not > possible to provide generally. Programs relying on these are already > tied to particular (32-bit only) boards: > - Hardware > - Revision > - Serial > > No software has yet been identified for which these remaining > differences are problematic. > > Cc: Catalin Marinas <catalin.marinas@xxxxxxx> > Cc: Will Deacon <will.deacon@xxxxxxx> > Cc: Ian Campbell <ijc@xxxxxxxxxxxxxx> > Cc: stable@xxxxxxxxxxxxxxx # 3.16.x > Signed-off-by: Mark Rutland <mark.rutland@xxxxxxx> > [Mark: backport to v3.16.x] > --- > arch/arm64/include/asm/cputype.h | 2 + > arch/arm64/kernel/setup.c | 99 +++++++++++++++++++++++++++++----------- > arch/arm64/kernel/smp.c | 5 ++ > 3 files changed, 80 insertions(+), 26 deletions(-) > > diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h > index 27f54a7..ad08bc7 100644 > --- a/arch/arm64/include/asm/cputype.h > +++ b/arch/arm64/include/asm/cputype.h > @@ -78,6 +78,8 @@ static inline u32 __attribute_const__ read_cpuid_cachetype(void) > return read_cpuid(CTR_EL0); > } > > +void cpuinfo_store_cpu(void); > + > #endif /* __ASSEMBLY__ */ > > #endif > diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c > index 209070d..37655ae 100644 > --- a/arch/arm64/kernel/setup.c > +++ b/arch/arm64/kernel/setup.c > @@ -43,6 +43,7 @@ > #include <linux/of_fdt.h> > #include <linux/of_platform.h> > #include <linux/efi.h> > +#include <linux/personality.h> > > #include <asm/fixmap.h> > #include <asm/cputype.h> > @@ -78,7 +79,6 @@ unsigned int compat_elf_hwcap2 __read_mostly; > #endif > > static const char *cpu_name; > -static const char *machine_name; > phys_addr_t __fdt_pointer __initdata; > > /* > @@ -198,6 +198,19 @@ static void __init smp_build_mpidr_hash(void) > } > #endif > > +struct cpuinfo_arm64 { > + struct cpu cpu; > + u32 reg_midr; > +}; > + > +static DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data); > + > +void cpuinfo_store_cpu(void) > +{ > + struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data); > + info->reg_midr = read_cpuid_id(); > +} > + > static void __init setup_processor(void) > { > struct cpu_info *cpu_info; > @@ -220,6 +233,8 @@ static void __init setup_processor(void) > sprintf(init_utsname()->machine, ELF_PLATFORM); > elf_hwcap = 0; > > + cpuinfo_store_cpu(); > + > /* > * Check for sane CTR_EL0.CWG value. > */ > @@ -308,8 +323,6 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys) > while (true) > cpu_relax(); > } > - > - machine_name = of_flat_dt_get_machine_name(); > } > > /* > @@ -419,14 +432,12 @@ static int __init arm64_device_init(void) > } > arch_initcall_sync(arm64_device_init); > > -static DEFINE_PER_CPU(struct cpu, cpu_data); > - > static int __init topology_init(void) > { > int i; > > for_each_possible_cpu(i) { > - struct cpu *cpu = &per_cpu(cpu_data, i); > + struct cpu *cpu = &per_cpu(cpu_data.cpu, i); > cpu->hotpluggable = 1; > register_cpu(cpu, i); > } > @@ -447,14 +458,41 @@ static const char *hwcap_str[] = { > NULL > }; > > +#ifdef CONFIG_COMPAT > +static const char *compat_hwcap_str[] = { > + "swp", > + "half", > + "thumb", > + "26bit", > + "fastmult", > + "fpa", > + "vfp", > + "edsp", > + "java", > + "iwmmxt", > + "crunch", > + "thumbee", > + "neon", > + "vfpv3", > + "vfpv3d16", > + "tls", > + "vfpv4", > + "idiva", > + "idivt", > + "vfpd32", > + "lpae", > + "evtstrm" > +}; > +#endif /* CONFIG_COMPAT */ > + > static int c_show(struct seq_file *m, void *v) > { > - int i; > - > - seq_printf(m, "Processor\t: %s rev %d (%s)\n", > - cpu_name, read_cpuid_id() & 15, ELF_PLATFORM); > + int i, j; > > for_each_online_cpu(i) { > + struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i); > + u32 midr = cpuinfo->reg_midr; > + > /* > * glibc reads /proc/cpuinfo to determine the number of > * online processors, looking for lines beginning with > @@ -463,24 +501,33 @@ static int c_show(struct seq_file *m, void *v) > #ifdef CONFIG_SMP > seq_printf(m, "processor\t: %d\n", i); > #endif > - } > - > - /* dump out the processor features */ > - seq_puts(m, "Features\t: "); > - > - for (i = 0; hwcap_str[i]; i++) > - if (elf_hwcap & (1 << i)) > - seq_printf(m, "%s ", hwcap_str[i]); > > - seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24); > - seq_printf(m, "CPU architecture: AArch64\n"); > - seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15); > - seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff); > - seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15); > - > - seq_puts(m, "\n"); > + /* > + * Dump out the common processor features in a single line. > + * Userspace should read the hwcaps with getauxval(AT_HWCAP) > + * rather than attempting to parse this, but there's a body of > + * software which does already (at least for 32-bit). > + */ > + seq_puts(m, "Features\t:"); > + if (personality(current->personality) == PER_LINUX32) { > +#ifdef CONFIG_COMPAT > + for (j = 0; compat_hwcap_str[j]; j++) > + if (compat_elf_hwcap & (1 << j)) > + seq_printf(m, " %s", compat_hwcap_str[j]); > +#endif /* CONFIG_COMPAT */ > + } else { > + for (j = 0; hwcap_str[j]; j++) > + if (elf_hwcap & (1 << j)) > + seq_printf(m, " %s", hwcap_str[j]); > + } > + seq_puts(m, "\n"); > > - seq_printf(m, "Hardware\t: %s\n", machine_name); > + seq_printf(m, "CPU implementer\t: 0x%02x\n", (midr >> 24)); > + seq_printf(m, "CPU architecture: 8\n"); > + seq_printf(m, "CPU variant\t: 0x%x\n", ((midr >> 20) & 0xf)); > + seq_printf(m, "CPU part\t: 0x%03x\n", ((midr >> 4) & 0xfff)); > + seq_printf(m, "CPU revision\t: %d\n\n", (midr & 0xf)); > + } > > return 0; > } > diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c > index 40f38f4..9df272c 100644 > --- a/arch/arm64/kernel/smp.c > +++ b/arch/arm64/kernel/smp.c > @@ -155,6 +155,11 @@ asmlinkage void secondary_start_kernel(void) > cpu_ops[cpu]->cpu_postboot(); > > /* > + * Log the CPU info before it is marked online and might get read. > + */ > + cpuinfo_store_cpu(); > + > + /* > * Enable GIC and timers. > */ > notify_cpu_starting(cpu); > -- > 1.9.1 > > -- > To unsubscribe from this list: send the line "unsubscribe stable" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html