aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Rutland <mark.rutland@arm.com>2014-10-24 09:56:40 -0400
committerWill Deacon <will.deacon@arm.com>2014-11-14 05:42:09 -0500
commit44b82b7700d05a52cd983799d3ecde1a976b3bed (patch)
tree0e6ccf5019e7ef319d6d8fc5924c5788cd255c4f
parent302cd37c417d59549d073a8986fd028998409cb9 (diff)
arm64: Fix up /proc/cpuinfo
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: Greg Hackmann <ghackmann@google.com> Cc: Ian Campbell <ijc@hellion.org.uk> Cc: Serban Constantinescu <serban.constantinescu@arm.com> Cc: Will Deacon <will.deacon@arm.com> Cc: cross-distro@lists.linaro.org Cc: linux-api@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--arch/arm64/kernel/setup.c97
1 files changed, 73 insertions, 24 deletions
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index c73714b6aa96..831c97fe1ae9 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -43,6 +43,7 @@
43#include <linux/of_fdt.h> 43#include <linux/of_fdt.h>
44#include <linux/of_platform.h> 44#include <linux/of_platform.h>
45#include <linux/efi.h> 45#include <linux/efi.h>
46#include <linux/personality.h>
46 47
47#include <asm/fixmap.h> 48#include <asm/fixmap.h>
48#include <asm/cpu.h> 49#include <asm/cpu.h>
@@ -78,7 +79,6 @@ unsigned int compat_elf_hwcap2 __read_mostly;
78#endif 79#endif
79 80
80static const char *cpu_name; 81static const char *cpu_name;
81static const char *machine_name;
82phys_addr_t __fdt_pointer __initdata; 82phys_addr_t __fdt_pointer __initdata;
83 83
84/* 84/*
@@ -315,8 +315,7 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
315 cpu_relax(); 315 cpu_relax();
316 } 316 }
317 317
318 machine_name = of_flat_dt_get_machine_name(); 318 dump_stack_set_arch_desc("%s (DT)", of_flat_dt_get_machine_name());
319 dump_stack_set_arch_desc("%s (DT)", machine_name);
320} 319}
321 320
322/* 321/*
@@ -451,14 +450,50 @@ static const char *hwcap_str[] = {
451 NULL 450 NULL
452}; 451};
453 452
453#ifdef CONFIG_COMPAT
454static const char *compat_hwcap_str[] = {
455 "swp",
456 "half",
457 "thumb",
458 "26bit",
459 "fastmult",
460 "fpa",
461 "vfp",
462 "edsp",
463 "java",
464 "iwmmxt",
465 "crunch",
466 "thumbee",
467 "neon",
468 "vfpv3",
469 "vfpv3d16",
470 "tls",
471 "vfpv4",
472 "idiva",
473 "idivt",
474 "vfpd32",
475 "lpae",
476 "evtstrm"
477};
478
479static const char *compat_hwcap2_str[] = {
480 "aes",
481 "pmull",
482 "sha1",
483 "sha2",
484 "crc32",
485 NULL
486};
487#endif /* CONFIG_COMPAT */
488
454static int c_show(struct seq_file *m, void *v) 489static int c_show(struct seq_file *m, void *v)
455{ 490{
456 int i; 491 int i, j;
457
458 seq_printf(m, "Processor\t: %s rev %d (%s)\n",
459 cpu_name, read_cpuid_id() & 15, ELF_PLATFORM);
460 492
461 for_each_online_cpu(i) { 493 for_each_online_cpu(i) {
494 struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
495 u32 midr = cpuinfo->reg_midr;
496
462 /* 497 /*
463 * glibc reads /proc/cpuinfo to determine the number of 498 * glibc reads /proc/cpuinfo to determine the number of
464 * online processors, looking for lines beginning with 499 * online processors, looking for lines beginning with
@@ -467,24 +502,38 @@ static int c_show(struct seq_file *m, void *v)
467#ifdef CONFIG_SMP 502#ifdef CONFIG_SMP
468 seq_printf(m, "processor\t: %d\n", i); 503 seq_printf(m, "processor\t: %d\n", i);
469#endif 504#endif
470 }
471
472 /* dump out the processor features */
473 seq_puts(m, "Features\t: ");
474
475 for (i = 0; hwcap_str[i]; i++)
476 if (elf_hwcap & (1 << i))
477 seq_printf(m, "%s ", hwcap_str[i]);
478
479 seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
480 seq_printf(m, "CPU architecture: AArch64\n");
481 seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15);
482 seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff);
483 seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
484 505
485 seq_puts(m, "\n"); 506 /*
486 507 * Dump out the common processor features in a single line.
487 seq_printf(m, "Hardware\t: %s\n", machine_name); 508 * Userspace should read the hwcaps with getauxval(AT_HWCAP)
509 * rather than attempting to parse this, but there's a body of
510 * software which does already (at least for 32-bit).
511 */
512 seq_puts(m, "Features\t:");
513 if (personality(current->personality) == PER_LINUX32) {
514#ifdef CONFIG_COMPAT
515 for (j = 0; compat_hwcap_str[j]; j++)
516 if (compat_elf_hwcap & (1 << j))
517 seq_printf(m, " %s", compat_hwcap_str[j]);
518
519 for (j = 0; compat_hwcap2_str[j]; j++)
520 if (compat_elf_hwcap2 & (1 << j))
521 seq_printf(m, " %s", compat_hwcap2_str[j]);
522#endif /* CONFIG_COMPAT */
523 } else {
524 for (j = 0; hwcap_str[j]; j++)
525 if (elf_hwcap & (1 << j))
526 seq_printf(m, " %s", hwcap_str[j]);
527 }
528 seq_puts(m, "\n");
529
530 seq_printf(m, "CPU implementer\t: 0x%02x\n",
531 MIDR_IMPLEMENTOR(midr));
532 seq_printf(m, "CPU architecture: 8\n");
533 seq_printf(m, "CPU variant\t: 0x%x\n", MIDR_VARIANT(midr));
534 seq_printf(m, "CPU part\t: 0x%03x\n", MIDR_PARTNUM(midr));
535 seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr));
536 }
488 537
489 return 0; 538 return 0;
490} 539}