|
@@ -24,8 +24,11 @@
|
|
|
#include <linux/bug.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/kernel.h>
|
|
|
+#include <linux/personality.h>
|
|
|
#include <linux/preempt.h>
|
|
|
#include <linux/printk.h>
|
|
|
+#include <linux/seq_file.h>
|
|
|
+#include <linux/sched.h>
|
|
|
#include <linux/smp.h>
|
|
|
|
|
|
/*
|
|
@@ -45,6 +48,127 @@ static char *icache_policy_str[] = {
|
|
|
|
|
|
unsigned long __icache_flags;
|
|
|
|
|
|
+static const char *hwcap_str[] = {
|
|
|
+ "fp",
|
|
|
+ "asimd",
|
|
|
+ "evtstrm",
|
|
|
+ "aes",
|
|
|
+ "pmull",
|
|
|
+ "sha1",
|
|
|
+ "sha2",
|
|
|
+ "crc32",
|
|
|
+ "atomics",
|
|
|
+ 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"
|
|
|
+};
|
|
|
+
|
|
|
+static const char *compat_hwcap2_str[] = {
|
|
|
+ "aes",
|
|
|
+ "pmull",
|
|
|
+ "sha1",
|
|
|
+ "sha2",
|
|
|
+ "crc32",
|
|
|
+ NULL
|
|
|
+};
|
|
|
+#endif /* CONFIG_COMPAT */
|
|
|
+
|
|
|
+static int c_show(struct seq_file *m, void *v)
|
|
|
+{
|
|
|
+ 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
|
|
|
+ * "processor". Give glibc what it expects.
|
|
|
+ */
|
|
|
+ seq_printf(m, "processor\t: %d\n", i);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 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]);
|
|
|
+
|
|
|
+ for (j = 0; compat_hwcap2_str[j]; j++)
|
|
|
+ if (compat_elf_hwcap2 & (1 << j))
|
|
|
+ seq_printf(m, " %s", compat_hwcap2_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, "CPU implementer\t: 0x%02x\n",
|
|
|
+ MIDR_IMPLEMENTOR(midr));
|
|
|
+ seq_printf(m, "CPU architecture: 8\n");
|
|
|
+ seq_printf(m, "CPU variant\t: 0x%x\n", MIDR_VARIANT(midr));
|
|
|
+ seq_printf(m, "CPU part\t: 0x%03x\n", MIDR_PARTNUM(midr));
|
|
|
+ seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr));
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void *c_start(struct seq_file *m, loff_t *pos)
|
|
|
+{
|
|
|
+ return *pos < 1 ? (void *)1 : NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
|
|
|
+{
|
|
|
+ ++*pos;
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static void c_stop(struct seq_file *m, void *v)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+const struct seq_operations cpuinfo_op = {
|
|
|
+ .start = c_start,
|
|
|
+ .next = c_next,
|
|
|
+ .stop = c_stop,
|
|
|
+ .show = c_show
|
|
|
+};
|
|
|
+
|
|
|
static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
|
|
|
{
|
|
|
unsigned int cpu = smp_processor_id();
|