[PATCH] MIPS: Make CP0 config registers readable via sysfs.

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] MIPS: Make CP0 config registers readable via sysfs.

Steven J. Hill-3
From: "Steven J. Hill" <[hidden email]>

Allow reading of CP0 config registers via sysfs for each core
in the system. The registers will show up in sysfs at the path:

   /sys/devices/system/cpu/cpuX/configX

Only CP0 config registers 0 through 7 are currently supported.

Signed-off-by: Steven J. Hill <[hidden email]>
---
 arch/mips/kernel/Makefile |    1 +
 arch/mips/kernel/sysfs.c  |   93 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+)
 create mode 100644 arch/mips/kernel/sysfs.c

diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index e034ad6..e208a6b 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -98,6 +98,7 @@ obj-$(CONFIG_PERF_EVENTS) += perf_event.o
 obj-$(CONFIG_HW_PERF_EVENTS) += perf_event_mipsxx.o
 
 obj-$(CONFIG_JUMP_LABEL) += jump_label.o
+obj-y += sysfs.o
 
 ifeq ($(CONFIG_CPU_MIPS32), y)
 #
diff --git a/arch/mips/kernel/sysfs.c b/arch/mips/kernel/sysfs.c
new file mode 100644
index 0000000..a64f559
--- /dev/null
+++ b/arch/mips/kernel/sysfs.c
@@ -0,0 +1,93 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/cpu.h>
+#include <linux/percpu.h>
+
+#include <asm/page.h>
+
+
+#define __BUILD_CP0_SYSFS(reg) \
+static DEFINE_PER_CPU(unsigned int, cpu_config##reg); \
+static ssize_t show_config##reg(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct cpu *cpu = container_of(dev, struct cpu, dev); \
+ int n = snprintf(buf, PAGE_SIZE-2, "%x\n", \
+ per_cpu(cpu_config##reg, cpu->dev.id)); \
+ return n; \
+} \
+static DEVICE_ATTR(config##reg, 0444, show_config##reg, NULL);
+
+__BUILD_CP0_SYSFS(0)
+__BUILD_CP0_SYSFS(1)
+__BUILD_CP0_SYSFS(2)
+__BUILD_CP0_SYSFS(3)
+__BUILD_CP0_SYSFS(4)
+__BUILD_CP0_SYSFS(5)
+__BUILD_CP0_SYSFS(6)
+__BUILD_CP0_SYSFS(7)
+
+static void read_c0_registers(void *arg)
+{
+ struct device *dev = get_cpu_device(smp_processor_id());
+ struct cpu *cpu;
+ int ok;
+
+ if (dev != NULL) {
+ cpu = container_of(dev, struct cpu, dev);
+ per_cpu(cpu_config0, cpu->dev.id) = read_c0_config();
+ device_create_file(dev, &dev_attr_config0);
+ ok = per_cpu(cpu_config0, cpu->dev.id) & MIPS_CONF_M;
+ } else
+ return;
+
+ if (ok) {
+ per_cpu(cpu_config1, cpu->dev.id) = read_c0_config1();
+ device_create_file(dev, &dev_attr_config1);
+ ok = per_cpu(cpu_config1, cpu->dev.id) & MIPS_CONF_M;
+ }
+ if (ok) {
+ per_cpu(cpu_config2, cpu->dev.id) = read_c0_config2();
+ device_create_file(dev, &dev_attr_config2);
+ ok = per_cpu(cpu_config2, cpu->dev.id) & MIPS_CONF_M;
+ }
+ if (ok) {
+ per_cpu(cpu_config3, cpu->dev.id) = read_c0_config3();
+ device_create_file(dev, &dev_attr_config3);
+ ok = per_cpu(cpu_config3, cpu->dev.id) & MIPS_CONF_M;
+ }
+ if (ok) {
+ per_cpu(cpu_config4, cpu->dev.id) = read_c0_config4();
+ device_create_file(dev, &dev_attr_config4);
+ ok = per_cpu(cpu_config4, cpu->dev.id) & MIPS_CONF_M;
+ }
+ if (ok) {
+ per_cpu(cpu_config5, cpu->dev.id) = read_c0_config5();
+ device_create_file(dev, &dev_attr_config5);
+ ok = per_cpu(cpu_config5, cpu->dev.id) & MIPS_CONF_M;
+ }
+ if (ok) {
+ per_cpu(cpu_config6, cpu->dev.id) = read_c0_config6();
+ device_create_file(dev, &dev_attr_config6);
+ ok = per_cpu(cpu_config6, cpu->dev.id) & MIPS_CONF_M;
+ }
+ if (ok) {
+ per_cpu(cpu_config7, cpu->dev.id) = read_c0_config7();
+ device_create_file(dev, &dev_attr_config7);
+ ok = per_cpu(cpu_config7, cpu->dev.id) & MIPS_CONF_M;
+ }
+}
+
+static int __init mips_sysfs_registers(void)
+{
+ on_each_cpu(read_c0_registers, NULL, 1);
+ return 0;
+}
+late_initcall(mips_sysfs_registers);
--
1.7.9.5