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 <[email protected]>
> Cc: Will Deacon <[email protected]>
> Cc: Ian Campbell <[email protected]>
> Cc: [email protected] # 3.16.x
> Signed-off-by: Mark Rutland <[email protected]>
> [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 [email protected]
> 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html