[PATCH] arch/tile: add /proc/tile, /proc/sys/tile, and a sysfs cpu attribute

From: Chris Metcalf
Date: Wed May 18 2011 - 14:08:14 EST


This change introduces a few of the less controversial /proc and
/proc/sys interfaces for tile, along with a sysfs attribute for
something that was originally proposed as a /proc/tile file.

Arnd Bergmann reviewed the initial arch/tile submission, which
included a complete set of all the /proc/tile and /proc/sys/tile
knobs that we had added in a somewhat ad hoc way during initial
development, and provided feedback on where most of them should go.

One knob turned out to be similar enough to the existing
/proc/sys/debug/exception-trace that it was re-implemented to use
that model instead (in a separate commit).

Another knob was /proc/tile/grid, which reported the "grid" dimensions
of a tile chip (e.g. 8x8 processors = 64-core chip). He suggested
looking at sysfs for that, so this change moves that information
to a pair of sysfs attributes (chip_width and chip_height) in the
/sys/devices/system/cpu directory.

The entries that don't seem to have an obvious place in /sys
or elsewhere, and that are added with this patch, are:

/proc/tile/hv
Version information about the running Tilera hypervisor

/proc/tile/hvconfig
Detailed configuration description of the hypervisor config

/proc/tile/board
Information on part numbers, serial numbers, etc., of the
hardware that the kernel is executing on

/proc/tile/switch
The type of control path for the onboard network switch, if any.

/proc/tile/hardwall
Information on the set of currently active hardwalls (note that
the implementation is already present in arch/tile/kernel/hardwall.c;
this change just enables it)

/proc/sys/tile/unaligned_fixup/
Knobs controlling the kernel code to fix up unaligned exceptions

Signed-off-by: Chris Metcalf <cmetcalf@xxxxxxxxxx>
---
arch/tile/kernel/Makefile | 2 +-
arch/tile/kernel/proc.c | 178 +++++++++++++++++++++++++++++++++++++++++++++
arch/tile/kernel/sysfs.c | 52 +++++++++++++
3 files changed, 231 insertions(+), 1 deletions(-)
create mode 100644 arch/tile/kernel/sysfs.c

diff --git a/arch/tile/kernel/Makefile b/arch/tile/kernel/Makefile
index b4c8e8e..b4dbc05 100644
--- a/arch/tile/kernel/Makefile
+++ b/arch/tile/kernel/Makefile
@@ -5,7 +5,7 @@
extra-y := vmlinux.lds head_$(BITS).o
obj-y := backtrace.o entry.o init_task.o irq.o messaging.o \
pci-dma.o proc.o process.o ptrace.o reboot.o \
- setup.o signal.o single_step.o stack.o sys.o time.o traps.o \
+ setup.o signal.o single_step.o stack.o sys.o sysfs.o time.o traps.o \
intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o

obj-$(CONFIG_HARDWALL) += hardwall.o
diff --git a/arch/tile/kernel/proc.c b/arch/tile/kernel/proc.c
index 2e02c41..c871674 100644
--- a/arch/tile/kernel/proc.c
+++ b/arch/tile/kernel/proc.c
@@ -27,6 +27,7 @@
#include <asm/processor.h>
#include <asm/sections.h>
#include <asm/homecache.h>
+#include <asm/hardwall.h>
#include <arch/chip.h>


@@ -88,3 +89,180 @@ const struct seq_operations cpuinfo_op = {
.stop = c_stop,
.show = show_cpuinfo,
};
+
+/*
+ * Support /proc/tile directory
+ */
+
+static struct proc_dir_entry *proc_tile_root;
+
+/*
+ * Define a /proc/tile file which uses a seq_file to provide a more
+ * complex set of data.
+ */
+#define SEQ_PROC_ENTRY(name) \
+ static int proc_tile_##name##_open(struct inode *inode, \
+ struct file *file) \
+ { \
+ return single_open(file, proc_tile_##name##_show, NULL); \
+ } \
+ static const struct file_operations proc_tile_##name##_fops = { \
+ .open = proc_tile_##name##_open, \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .release = single_release, \
+ }; \
+ static void proc_tile_##name##_init(void) \
+ { \
+ struct proc_dir_entry *entry = \
+ create_proc_entry(#name, 0444, proc_tile_root); \
+ if (entry) \
+ entry->proc_fops = &proc_tile_##name##_fops; \
+ }
+
+/* Print to a seq_file the result of hv_confstr(query). */
+static void proc_tile_seq_strconf(struct seq_file *sf, char* what, int query)
+{
+ char tmpbuf[256];
+ char *bufptr = tmpbuf;
+ int buflen = sizeof(tmpbuf);
+ int len = hv_confstr(query, (HV_VirtAddr) bufptr, buflen);
+
+ if (len > buflen) {
+ bufptr = kmalloc(len, GFP_KERNEL);
+ if (!bufptr)
+ return;
+ buflen = len;
+ len = hv_confstr(query, (HV_VirtAddr) bufptr, buflen);
+ }
+
+ bufptr[buflen - 1] = 0;
+ /* Length includes the trailing null, so if it's 1, it's empty. */
+ if (len > 1) {
+ if (what)
+ seq_printf(sf, "%s: %s\n", what, bufptr);
+ else
+ seq_printf(sf, "%s", bufptr);
+ }
+
+ if (bufptr != tmpbuf)
+ kfree(bufptr);
+}
+
+static int proc_tile_hv_show(struct seq_file *sf, void *v)
+{
+ proc_tile_seq_strconf(sf, "version", HV_CONFSTR_HV_SW_VER);
+ proc_tile_seq_strconf(sf, "config_version", HV_CONFSTR_HV_CONFIG_VER);
+ return 0;
+}
+SEQ_PROC_ENTRY(hv)
+
+static int proc_tile_hvconfig_show(struct seq_file *sf, void *v)
+{
+ proc_tile_seq_strconf(sf, NULL, HV_CONFSTR_HV_CONFIG);
+ return 0;
+}
+SEQ_PROC_ENTRY(hvconfig)
+
+static int proc_tile_board_show(struct seq_file *sf, void *v)
+{
+ proc_tile_seq_strconf(sf, "board_part", HV_CONFSTR_BOARD_PART_NUM);
+ proc_tile_seq_strconf(sf, "board_serial", HV_CONFSTR_BOARD_SERIAL_NUM);
+ proc_tile_seq_strconf(sf, "chip_serial", HV_CONFSTR_CHIP_SERIAL_NUM);
+ proc_tile_seq_strconf(sf, "chip_revision", HV_CONFSTR_CHIP_REV);
+ proc_tile_seq_strconf(sf, "board_revision", HV_CONFSTR_BOARD_REV);
+ proc_tile_seq_strconf(sf, "board_description", HV_CONFSTR_BOARD_DESC);
+ proc_tile_seq_strconf(sf, "mezz_part", HV_CONFSTR_MEZZ_PART_NUM);
+ proc_tile_seq_strconf(sf, "mezz_serial", HV_CONFSTR_MEZZ_SERIAL_NUM);
+ proc_tile_seq_strconf(sf, "mezz_revision", HV_CONFSTR_MEZZ_REV);
+ proc_tile_seq_strconf(sf, "mezz_description", HV_CONFSTR_MEZZ_DESC);
+ return 0;
+}
+SEQ_PROC_ENTRY(board)
+
+static int proc_tile_switch_show(struct seq_file *sf, void *v)
+{
+ proc_tile_seq_strconf(sf, "control", HV_CONFSTR_SWITCH_CONTROL);
+ return 0;
+}
+SEQ_PROC_ENTRY(switch)
+
+
+#ifdef CONFIG_HARDWALL
+/* See arch/tile/kernel/hardwall.c for the implementation. */
+SEQ_PROC_ENTRY(hardwall)
+#endif
+
+static int __init proc_tile_init(void)
+{
+ proc_tile_root = proc_mkdir("tile", NULL);
+ if (!proc_tile_root)
+ return 0;
+
+ proc_tile_board_init();
+ proc_tile_switch_init();
+ proc_tile_hv_init();
+ proc_tile_hvconfig_init();
+#ifdef CONFIG_HARDWALL
+ proc_tile_hardwall_init();
+#endif
+
+ return 0;
+}
+
+arch_initcall(proc_tile_init);
+
+/*
+ * Support /proc/sys/tile directory
+ */
+
+#ifndef __tilegx__ /* FIXME: GX: no support for unaligned access yet */
+static ctl_table unaligned_subtable[] = {
+ {
+ .procname = "enabled",
+ .data = &unaligned_fixup,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec
+ },
+ {
+ .procname = "printk",
+ .data = &unaligned_printk,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec
+ },
+ {
+ .procname = "count",
+ .data = &unaligned_fixup_count,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec
+ },
+ {}
+};
+
+static ctl_table unaligned_table[] = {
+ {
+ .procname = "unaligned_fixup",
+ .mode = 0555,
+ .child = unaligned_subtable
+ },
+ {}
+};
+#endif
+
+static struct ctl_path tile_path[] = {
+ { .procname = "tile" },
+ { }
+};
+
+static int __init proc_sys_tile_init(void)
+{
+#ifndef __tilegx__ /* FIXME: GX: no support for unaligned access yet */
+ register_sysctl_paths(tile_path, unaligned_table);
+#endif
+ return 0;
+}
+
+arch_initcall(proc_sys_tile_init);
diff --git a/arch/tile/kernel/sysfs.c b/arch/tile/kernel/sysfs.c
new file mode 100644
index 0000000..151deeb
--- /dev/null
+++ b/arch/tile/kernel/sysfs.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for
+ * more details.
+ *
+ * /sys entry support.
+ */
+
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+
+static ssize_t chip_width_show(struct sysdev_class *dev,
+ struct sysdev_class_attribute *attr,
+ char *page)
+{
+ return sprintf(page, "%u\n", smp_width);
+}
+static SYSDEV_CLASS_ATTR(chip_width, 0444, chip_width_show, NULL);
+
+static ssize_t chip_height_show(struct sysdev_class *dev,
+ struct sysdev_class_attribute *attr,
+ char *page)
+{
+ return sprintf(page, "%u\n", smp_height);
+}
+static SYSDEV_CLASS_ATTR(chip_height, 0444, chip_height_show, NULL);
+
+
+static int __init create_cpu_entries(void)
+{
+ struct sysdev_class *cls = &cpu_sysdev_class;
+ int err = 0;
+
+ if (!err)
+ err = sysfs_create_file(&cls->kset.kobj,
+ &attr_chip_width.attr);
+ if (!err)
+ err = sysfs_create_file(&cls->kset.kobj,
+ &attr_chip_height.attr);
+
+ return err;
+}
+subsys_initcall(create_cpu_entries);
--
1.6.5.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/