Re: [PATCH 3.16.x] arm64: Fix up /proc/cpuinfo

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]