diff options
| author | Chris Metcalf <cmetcalf@tilera.com> | 2011-05-26 12:40:09 -0400 |
|---|---|---|
| committer | Chris Metcalf <cmetcalf@tilera.com> | 2011-05-27 10:39:05 -0400 |
| commit | f133ecca9cbb31b5e6e9bda27cbe3034fbf656df (patch) | |
| tree | 1887377b71ee9fc73d4e1226d1d9776ae5a5d7ad | |
| parent | 7a0287df3e83a0012dfc496d4a8af9c1c5b126ef (diff) | |
arch/tile: more /proc and /sys file support
This change introduces a few of the less controversial /proc and
/proc/sys interfaces for tile, along with sysfs attributes for
various things that were originally proposed as /proc/tile files.
It also adjusts the "hardwall" proc API.
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.
Another knob was /proc/tile/grid, which reported the "grid" dimensions
of a tile chip (e.g. 8x8 processors = 64-core chip). Arnd 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. We also put the "chip_serial"
and "chip_revision" information from our old /proc/tile/board file
as attributes in /sys/devices/system/cpu.
Other information collected via hypervisor APIs is now placed in
/sys/hypervisor. We create a /sys/hypervisor/type file (holding the
constant string "tilera") to be parallel with the Xen use of
/sys/hypervisor/type holding "xen". We create three top-level files,
"version" (the hypervisor's own version), "config_version" (the
version of the configuration file), and "hvconfig" (the contents of
the configuration file). The remaining information from our old
/proc/tile/board and /proc/tile/switch files becomes an attribute
group appearing under /sys/hypervisor/board/.
Finally, after some feedback from Arnd Bergmann for the previous
version of this patch, the /proc/tile/hardwall file is split up into
two conceptual parts. First, a directory /proc/tile/hardwall/ which
contains one file per active hardwall, each file named after the
hardwall's ID and holding a cpulist that says which cpus are enclosed by
the hardwall. Second, a /proc/PID file "hardwall" that is either
empty (for non-hardwall-using processes) or contains the hardwall ID.
Finally, this change pushes the /proc/sys/tile/unaligned_fixup/
directory, with knobs controlling the kernel code for handling the
fixup of unaligned exceptions.
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
| -rw-r--r-- | arch/tile/Kconfig | 1 | ||||
| -rw-r--r-- | arch/tile/include/asm/hardwall.h | 15 | ||||
| -rw-r--r-- | arch/tile/kernel/Makefile | 2 | ||||
| -rw-r--r-- | arch/tile/kernel/hardwall.c | 90 | ||||
| -rw-r--r-- | arch/tile/kernel/proc.c | 73 | ||||
| -rw-r--r-- | arch/tile/kernel/sysfs.c | 185 | ||||
| -rw-r--r-- | fs/proc/base.c | 9 |
7 files changed, 347 insertions, 28 deletions
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 635e1bfb1c5d..3f7d63c7ae85 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig | |||
| @@ -12,6 +12,7 @@ config TILE | |||
| 12 | select GENERIC_IRQ_PROBE | 12 | select GENERIC_IRQ_PROBE |
| 13 | select GENERIC_PENDING_IRQ if SMP | 13 | select GENERIC_PENDING_IRQ if SMP |
| 14 | select GENERIC_IRQ_SHOW | 14 | select GENERIC_IRQ_SHOW |
| 15 | select SYS_HYPERVISOR | ||
| 15 | 16 | ||
| 16 | # FIXME: investigate whether we need/want these options. | 17 | # FIXME: investigate whether we need/want these options. |
| 17 | # select HAVE_IOREMAP_PROT | 18 | # select HAVE_IOREMAP_PROT |
diff --git a/arch/tile/include/asm/hardwall.h b/arch/tile/include/asm/hardwall.h index 0bed3ec7b42c..2ac422848c7d 100644 --- a/arch/tile/include/asm/hardwall.h +++ b/arch/tile/include/asm/hardwall.h | |||
| @@ -40,6 +40,10 @@ | |||
| 40 | #define HARDWALL_DEACTIVATE \ | 40 | #define HARDWALL_DEACTIVATE \ |
| 41 | _IO(HARDWALL_IOCTL_BASE, _HARDWALL_DEACTIVATE) | 41 | _IO(HARDWALL_IOCTL_BASE, _HARDWALL_DEACTIVATE) |
| 42 | 42 | ||
| 43 | #define _HARDWALL_GET_ID 4 | ||
| 44 | #define HARDWALL_GET_ID \ | ||
| 45 | _IO(HARDWALL_IOCTL_BASE, _HARDWALL_GET_ID) | ||
| 46 | |||
| 43 | #ifndef __KERNEL__ | 47 | #ifndef __KERNEL__ |
| 44 | 48 | ||
| 45 | /* This is the canonical name expected by userspace. */ | 49 | /* This is the canonical name expected by userspace. */ |
| @@ -47,9 +51,14 @@ | |||
| 47 | 51 | ||
| 48 | #else | 52 | #else |
| 49 | 53 | ||
| 50 | /* Hook for /proc/tile/hardwall. */ | 54 | /* /proc hooks for hardwall. */ |
| 51 | struct seq_file; | 55 | struct proc_dir_entry; |
| 52 | int proc_tile_hardwall_show(struct seq_file *sf, void *v); | 56 | #ifdef CONFIG_HARDWALL |
| 57 | void proc_tile_hardwall_init(struct proc_dir_entry *root); | ||
| 58 | int proc_pid_hardwall(struct task_struct *task, char *buffer); | ||
| 59 | #else | ||
| 60 | static inline void proc_tile_hardwall_init(struct proc_dir_entry *root) {} | ||
| 61 | #endif | ||
| 53 | 62 | ||
| 54 | #endif | 63 | #endif |
| 55 | 64 | ||
diff --git a/arch/tile/kernel/Makefile b/arch/tile/kernel/Makefile index b4c8e8ec45dc..b4dbc057baad 100644 --- a/arch/tile/kernel/Makefile +++ b/arch/tile/kernel/Makefile | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | extra-y := vmlinux.lds head_$(BITS).o | 5 | extra-y := vmlinux.lds head_$(BITS).o |
| 6 | obj-y := backtrace.o entry.o init_task.o irq.o messaging.o \ | 6 | obj-y := backtrace.o entry.o init_task.o irq.o messaging.o \ |
| 7 | pci-dma.o proc.o process.o ptrace.o reboot.o \ | 7 | pci-dma.o proc.o process.o ptrace.o reboot.o \ |
| 8 | setup.o signal.o single_step.o stack.o sys.o time.o traps.o \ | 8 | setup.o signal.o single_step.o stack.o sys.o sysfs.o time.o traps.o \ |
| 9 | intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o | 9 | intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o |
| 10 | 10 | ||
| 11 | obj-$(CONFIG_HARDWALL) += hardwall.o | 11 | obj-$(CONFIG_HARDWALL) += hardwall.o |
diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c index 3bddef710de4..8c41891aab34 100644 --- a/arch/tile/kernel/hardwall.c +++ b/arch/tile/kernel/hardwall.c | |||
| @@ -40,16 +40,25 @@ | |||
| 40 | struct hardwall_info { | 40 | struct hardwall_info { |
| 41 | struct list_head list; /* "rectangles" list */ | 41 | struct list_head list; /* "rectangles" list */ |
| 42 | struct list_head task_head; /* head of tasks in this hardwall */ | 42 | struct list_head task_head; /* head of tasks in this hardwall */ |
| 43 | struct cpumask cpumask; /* cpus in the rectangle */ | ||
| 43 | int ulhc_x; /* upper left hand corner x coord */ | 44 | int ulhc_x; /* upper left hand corner x coord */ |
| 44 | int ulhc_y; /* upper left hand corner y coord */ | 45 | int ulhc_y; /* upper left hand corner y coord */ |
| 45 | int width; /* rectangle width */ | 46 | int width; /* rectangle width */ |
| 46 | int height; /* rectangle height */ | 47 | int height; /* rectangle height */ |
| 48 | int id; /* integer id for this hardwall */ | ||
| 47 | int teardown_in_progress; /* are we tearing this one down? */ | 49 | int teardown_in_progress; /* are we tearing this one down? */ |
| 48 | }; | 50 | }; |
| 49 | 51 | ||
| 50 | /* Currently allocated hardwall rectangles */ | 52 | /* Currently allocated hardwall rectangles */ |
| 51 | static LIST_HEAD(rectangles); | 53 | static LIST_HEAD(rectangles); |
| 52 | 54 | ||
| 55 | /* /proc/tile/hardwall */ | ||
| 56 | static struct proc_dir_entry *hardwall_proc_dir; | ||
| 57 | |||
| 58 | /* Functions to manage files in /proc/tile/hardwall. */ | ||
| 59 | static void hardwall_add_proc(struct hardwall_info *rect); | ||
| 60 | static void hardwall_remove_proc(struct hardwall_info *rect); | ||
| 61 | |||
| 53 | /* | 62 | /* |
| 54 | * Guard changes to the hardwall data structures. | 63 | * Guard changes to the hardwall data structures. |
| 55 | * This could be finer grained (e.g. one lock for the list of hardwall | 64 | * This could be finer grained (e.g. one lock for the list of hardwall |
| @@ -105,6 +114,8 @@ static int setup_rectangle(struct hardwall_info *r, struct cpumask *mask) | |||
| 105 | r->ulhc_y = cpu_y(ulhc); | 114 | r->ulhc_y = cpu_y(ulhc); |
| 106 | r->width = cpu_x(lrhc) - r->ulhc_x + 1; | 115 | r->width = cpu_x(lrhc) - r->ulhc_x + 1; |
| 107 | r->height = cpu_y(lrhc) - r->ulhc_y + 1; | 116 | r->height = cpu_y(lrhc) - r->ulhc_y + 1; |
| 117 | cpumask_copy(&r->cpumask, mask); | ||
| 118 | r->id = ulhc; /* The ulhc cpu id can be the hardwall id. */ | ||
| 108 | 119 | ||
| 109 | /* Width and height must be positive */ | 120 | /* Width and height must be positive */ |
| 110 | if (r->width <= 0 || r->height <= 0) | 121 | if (r->width <= 0 || r->height <= 0) |
| @@ -388,6 +399,9 @@ static struct hardwall_info *hardwall_create( | |||
| 388 | /* Set up appropriate hardwalling on all affected cpus. */ | 399 | /* Set up appropriate hardwalling on all affected cpus. */ |
| 389 | hardwall_setup(rect); | 400 | hardwall_setup(rect); |
| 390 | 401 | ||
| 402 | /* Create a /proc/tile/hardwall entry. */ | ||
| 403 | hardwall_add_proc(rect); | ||
| 404 | |||
| 391 | return rect; | 405 | return rect; |
| 392 | } | 406 | } |
| 393 | 407 | ||
| @@ -645,6 +659,9 @@ static void hardwall_destroy(struct hardwall_info *rect) | |||
| 645 | /* Restart switch and disable firewall. */ | 659 | /* Restart switch and disable firewall. */ |
| 646 | on_each_cpu_mask(&mask, restart_udn_switch, NULL, 1); | 660 | on_each_cpu_mask(&mask, restart_udn_switch, NULL, 1); |
| 647 | 661 | ||
| 662 | /* Remove the /proc/tile/hardwall entry. */ | ||
| 663 | hardwall_remove_proc(rect); | ||
| 664 | |||
| 648 | /* Now free the rectangle from the list. */ | 665 | /* Now free the rectangle from the list. */ |
| 649 | spin_lock_irqsave(&hardwall_lock, flags); | 666 | spin_lock_irqsave(&hardwall_lock, flags); |
| 650 | BUG_ON(!list_empty(&rect->task_head)); | 667 | BUG_ON(!list_empty(&rect->task_head)); |
| @@ -654,35 +671,57 @@ static void hardwall_destroy(struct hardwall_info *rect) | |||
| 654 | } | 671 | } |
| 655 | 672 | ||
| 656 | 673 | ||
| 657 | /* | 674 | static int hardwall_proc_show(struct seq_file *sf, void *v) |
| 658 | * Dump hardwall state via /proc; initialized in arch/tile/sys/proc.c. | ||
| 659 | */ | ||
| 660 | int proc_tile_hardwall_show(struct seq_file *sf, void *v) | ||
| 661 | { | 675 | { |
| 662 | struct hardwall_info *r; | 676 | struct hardwall_info *rect = sf->private; |
| 677 | char buf[256]; | ||
| 663 | 678 | ||
| 664 | if (udn_disabled) { | 679 | int rc = cpulist_scnprintf(buf, sizeof(buf), &rect->cpumask); |
| 665 | seq_printf(sf, "%dx%d 0,0 pids:\n", smp_width, smp_height); | 680 | buf[rc++] = '\n'; |
| 666 | return 0; | 681 | seq_write(sf, buf, rc); |
| 667 | } | ||
| 668 | |||
| 669 | spin_lock_irq(&hardwall_lock); | ||
| 670 | list_for_each_entry(r, &rectangles, list) { | ||
| 671 | struct task_struct *p; | ||
| 672 | seq_printf(sf, "%dx%d %d,%d pids:", | ||
| 673 | r->width, r->height, r->ulhc_x, r->ulhc_y); | ||
| 674 | list_for_each_entry(p, &r->task_head, thread.hardwall_list) { | ||
| 675 | unsigned int cpu = cpumask_first(&p->cpus_allowed); | ||
| 676 | unsigned int x = cpu % smp_width; | ||
| 677 | unsigned int y = cpu / smp_width; | ||
| 678 | seq_printf(sf, " %d@%d,%d", p->pid, x, y); | ||
| 679 | } | ||
| 680 | seq_printf(sf, "\n"); | ||
| 681 | } | ||
| 682 | spin_unlock_irq(&hardwall_lock); | ||
| 683 | return 0; | 682 | return 0; |
| 684 | } | 683 | } |
| 685 | 684 | ||
| 685 | static int hardwall_proc_open(struct inode *inode, | ||
| 686 | struct file *file) | ||
| 687 | { | ||
| 688 | return single_open(file, hardwall_proc_show, PDE(inode)->data); | ||
| 689 | } | ||
| 690 | |||
| 691 | static const struct file_operations hardwall_proc_fops = { | ||
| 692 | .open = hardwall_proc_open, | ||
| 693 | .read = seq_read, | ||
| 694 | .llseek = seq_lseek, | ||
| 695 | .release = single_release, | ||
| 696 | }; | ||
| 697 | |||
| 698 | static void hardwall_add_proc(struct hardwall_info *rect) | ||
| 699 | { | ||
| 700 | char buf[64]; | ||
| 701 | snprintf(buf, sizeof(buf), "%d", rect->id); | ||
| 702 | proc_create_data(buf, 0444, hardwall_proc_dir, | ||
| 703 | &hardwall_proc_fops, rect); | ||
| 704 | } | ||
| 705 | |||
| 706 | static void hardwall_remove_proc(struct hardwall_info *rect) | ||
| 707 | { | ||
| 708 | char buf[64]; | ||
| 709 | snprintf(buf, sizeof(buf), "%d", rect->id); | ||
| 710 | remove_proc_entry(buf, hardwall_proc_dir); | ||
| 711 | } | ||
| 712 | |||
| 713 | int proc_pid_hardwall(struct task_struct *task, char *buffer) | ||
| 714 | { | ||
| 715 | struct hardwall_info *rect = task->thread.hardwall; | ||
| 716 | return rect ? sprintf(buffer, "%d\n", rect->id) : 0; | ||
| 717 | } | ||
| 718 | |||
| 719 | void proc_tile_hardwall_init(struct proc_dir_entry *root) | ||
| 720 | { | ||
| 721 | if (!udn_disabled) | ||
| 722 | hardwall_proc_dir = proc_mkdir("hardwall", root); | ||
| 723 | } | ||
| 724 | |||
| 686 | 725 | ||
| 687 | /* | 726 | /* |
| 688 | * Character device support via ioctl/close. | 727 | * Character device support via ioctl/close. |
| @@ -716,6 +755,9 @@ static long hardwall_ioctl(struct file *file, unsigned int a, unsigned long b) | |||
| 716 | return -EINVAL; | 755 | return -EINVAL; |
| 717 | return hardwall_deactivate(current); | 756 | return hardwall_deactivate(current); |
| 718 | 757 | ||
| 758 | case _HARDWALL_GET_ID: | ||
| 759 | return rect ? rect->id : -EINVAL; | ||
| 760 | |||
| 719 | default: | 761 | default: |
| 720 | return -EINVAL; | 762 | return -EINVAL; |
| 721 | } | 763 | } |
diff --git a/arch/tile/kernel/proc.c b/arch/tile/kernel/proc.c index 2e02c41ddf3b..62d820833c68 100644 --- a/arch/tile/kernel/proc.c +++ b/arch/tile/kernel/proc.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
| 28 | #include <asm/sections.h> | 28 | #include <asm/sections.h> |
| 29 | #include <asm/homecache.h> | 29 | #include <asm/homecache.h> |
| 30 | #include <asm/hardwall.h> | ||
| 30 | #include <arch/chip.h> | 31 | #include <arch/chip.h> |
| 31 | 32 | ||
| 32 | 33 | ||
| @@ -88,3 +89,75 @@ const struct seq_operations cpuinfo_op = { | |||
| 88 | .stop = c_stop, | 89 | .stop = c_stop, |
| 89 | .show = show_cpuinfo, | 90 | .show = show_cpuinfo, |
| 90 | }; | 91 | }; |
| 92 | |||
| 93 | /* | ||
| 94 | * Support /proc/tile directory | ||
| 95 | */ | ||
| 96 | |||
| 97 | static int __init proc_tile_init(void) | ||
| 98 | { | ||
| 99 | struct proc_dir_entry *root = proc_mkdir("tile", NULL); | ||
| 100 | if (root == NULL) | ||
| 101 | return 0; | ||
| 102 | |||
| 103 | proc_tile_hardwall_init(root); | ||
| 104 | |||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | arch_initcall(proc_tile_init); | ||
| 109 | |||
| 110 | /* | ||
| 111 | * Support /proc/sys/tile directory | ||
| 112 | */ | ||
| 113 | |||
| 114 | #ifndef __tilegx__ /* FIXME: GX: no support for unaligned access yet */ | ||
| 115 | static ctl_table unaligned_subtable[] = { | ||
| 116 | { | ||
| 117 | .procname = "enabled", | ||
| 118 | .data = &unaligned_fixup, | ||
| 119 | .maxlen = sizeof(int), | ||
| 120 | .mode = 0644, | ||
| 121 | .proc_handler = &proc_dointvec | ||
| 122 | }, | ||
| 123 | { | ||
| 124 | .procname = "printk", | ||
| 125 | .data = &unaligned_printk, | ||
| 126 | .maxlen = sizeof(int), | ||
| 127 | .mode = 0644, | ||
| 128 | .proc_handler = &proc_dointvec | ||
| 129 | }, | ||
| 130 | { | ||
| 131 | .procname = "count", | ||
| 132 | .data = &unaligned_fixup_count, | ||
| 133 | .maxlen = sizeof(int), | ||
| 134 | .mode = 0644, | ||
| 135 | .proc_handler = &proc_dointvec | ||
| 136 | }, | ||
| 137 | {} | ||
| 138 | }; | ||
| 139 | |||
| 140 | static ctl_table unaligned_table[] = { | ||
| 141 | { | ||
| 142 | .procname = "unaligned_fixup", | ||
| 143 | .mode = 0555, | ||
| 144 | .child = unaligned_subtable | ||
| 145 | }, | ||
| 146 | {} | ||
| 147 | }; | ||
| 148 | #endif | ||
| 149 | |||
| 150 | static struct ctl_path tile_path[] = { | ||
| 151 | { .procname = "tile" }, | ||
| 152 | { } | ||
| 153 | }; | ||
| 154 | |||
| 155 | static int __init proc_sys_tile_init(void) | ||
| 156 | { | ||
| 157 | #ifndef __tilegx__ /* FIXME: GX: no support for unaligned access yet */ | ||
| 158 | register_sysctl_paths(tile_path, unaligned_table); | ||
| 159 | #endif | ||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | 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 000000000000..b671a86f4515 --- /dev/null +++ b/arch/tile/kernel/sysfs.c | |||
| @@ -0,0 +1,185 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2011 Tilera Corporation. All Rights Reserved. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License | ||
| 6 | * as published by the Free Software Foundation, version 2. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, but | ||
| 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
| 11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | * | ||
| 14 | * /sys entry support. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/sysdev.h> | ||
| 18 | #include <linux/cpu.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/smp.h> | ||
| 21 | #include <hv/hypervisor.h> | ||
| 22 | |||
| 23 | /* Return a string queried from the hypervisor, truncated to page size. */ | ||
| 24 | static ssize_t get_hv_confstr(char *page, int query) | ||
| 25 | { | ||
| 26 | ssize_t n = hv_confstr(query, (unsigned long)page, PAGE_SIZE - 1); | ||
| 27 | n = n < 0 ? 0 : min(n, (ssize_t)PAGE_SIZE - 1) - 1; | ||
| 28 | if (n) | ||
| 29 | page[n++] = '\n'; | ||
| 30 | page[n] = '\0'; | ||
| 31 | return n; | ||
| 32 | } | ||
| 33 | |||
| 34 | static ssize_t chip_width_show(struct sysdev_class *dev, | ||
| 35 | struct sysdev_class_attribute *attr, | ||
| 36 | char *page) | ||
| 37 | { | ||
| 38 | return sprintf(page, "%u\n", smp_width); | ||
| 39 | } | ||
| 40 | static SYSDEV_CLASS_ATTR(chip_width, 0444, chip_width_show, NULL); | ||
| 41 | |||
| 42 | static ssize_t chip_height_show(struct sysdev_class *dev, | ||
| 43 | struct sysdev_class_attribute *attr, | ||
| 44 | char *page) | ||
| 45 | { | ||
| 46 | return sprintf(page, "%u\n", smp_height); | ||
| 47 | } | ||
| 48 | static SYSDEV_CLASS_ATTR(chip_height, 0444, chip_height_show, NULL); | ||
| 49 | |||
| 50 | static ssize_t chip_serial_show(struct sysdev_class *dev, | ||
| 51 | struct sysdev_class_attribute *attr, | ||
| 52 | char *page) | ||
| 53 | { | ||
| 54 | return get_hv_confstr(page, HV_CONFSTR_CHIP_SERIAL_NUM); | ||
| 55 | } | ||
| 56 | static SYSDEV_CLASS_ATTR(chip_serial, 0444, chip_serial_show, NULL); | ||
| 57 | |||
| 58 | static ssize_t chip_revision_show(struct sysdev_class *dev, | ||
| 59 | struct sysdev_class_attribute *attr, | ||
| 60 | char *page) | ||
| 61 | { | ||
| 62 | return get_hv_confstr(page, HV_CONFSTR_CHIP_REV); | ||
| 63 | } | ||
| 64 | static SYSDEV_CLASS_ATTR(chip_revision, 0444, chip_revision_show, NULL); | ||
| 65 | |||
| 66 | |||
| 67 | static ssize_t type_show(struct sysdev_class *dev, | ||
| 68 | struct sysdev_class_attribute *attr, | ||
| 69 | char *page) | ||
| 70 | { | ||
| 71 | return sprintf(page, "tilera\n"); | ||
| 72 | } | ||
| 73 | static SYSDEV_CLASS_ATTR(type, 0444, type_show, NULL); | ||
| 74 | |||
| 75 | #define HV_CONF_ATTR(name, conf) \ | ||
| 76 | static ssize_t name ## _show(struct sysdev_class *dev, \ | ||
| 77 | struct sysdev_class_attribute *attr, \ | ||
| 78 | char *page) \ | ||
| 79 | { \ | ||
| 80 | return get_hv_confstr(page, conf); \ | ||
| 81 | } \ | ||
| 82 | static SYSDEV_CLASS_ATTR(name, 0444, name ## _show, NULL); | ||
| 83 | |||
| 84 | HV_CONF_ATTR(version, HV_CONFSTR_HV_SW_VER) | ||
| 85 | HV_CONF_ATTR(config_version, HV_CONFSTR_HV_CONFIG_VER) | ||
| 86 | |||
| 87 | HV_CONF_ATTR(board_part, HV_CONFSTR_BOARD_PART_NUM) | ||
| 88 | HV_CONF_ATTR(board_serial, HV_CONFSTR_BOARD_SERIAL_NUM) | ||
| 89 | HV_CONF_ATTR(board_revision, HV_CONFSTR_BOARD_REV) | ||
| 90 | HV_CONF_ATTR(board_description, HV_CONFSTR_BOARD_DESC) | ||
| 91 | HV_CONF_ATTR(mezz_part, HV_CONFSTR_MEZZ_PART_NUM) | ||
| 92 | HV_CONF_ATTR(mezz_serial, HV_CONFSTR_MEZZ_SERIAL_NUM) | ||
| 93 | HV_CONF_ATTR(mezz_revision, HV_CONFSTR_MEZZ_REV) | ||
| 94 | HV_CONF_ATTR(mezz_description, HV_CONFSTR_MEZZ_DESC) | ||
| 95 | HV_CONF_ATTR(switch_control, HV_CONFSTR_SWITCH_CONTROL) | ||
| 96 | |||
| 97 | static struct attribute *board_attrs[] = { | ||
| 98 | &attr_board_part.attr, | ||
| 99 | &attr_board_serial.attr, | ||
| 100 | &attr_board_revision.attr, | ||
| 101 | &attr_board_description.attr, | ||
| 102 | &attr_mezz_part.attr, | ||
| 103 | &attr_mezz_serial.attr, | ||
| 104 | &attr_mezz_revision.attr, | ||
| 105 | &attr_mezz_description.attr, | ||
| 106 | &attr_switch_control.attr, | ||
| 107 | NULL | ||
| 108 | }; | ||
| 109 | |||
| 110 | static struct attribute_group board_attr_group = { | ||
| 111 | .name = "board", | ||
| 112 | .attrs = board_attrs, | ||
| 113 | }; | ||
| 114 | |||
| 115 | |||
| 116 | static struct bin_attribute hvconfig_bin; | ||
| 117 | |||
| 118 | static ssize_t | ||
| 119 | hvconfig_bin_read(struct file *filp, struct kobject *kobj, | ||
| 120 | struct bin_attribute *bin_attr, | ||
| 121 | char *buf, loff_t off, size_t count) | ||
| 122 | { | ||
| 123 | static size_t size; | ||
| 124 | |||
| 125 | /* Lazily learn the true size (minus the trailing NUL). */ | ||
| 126 | if (size == 0) | ||
| 127 | size = hv_confstr(HV_CONFSTR_HV_CONFIG, 0, 0) - 1; | ||
| 128 | |||
| 129 | /* Check and adjust input parameters. */ | ||
| 130 | if (off > size) | ||
| 131 | return -EINVAL; | ||
| 132 | if (count > size - off) | ||
| 133 | count = size - off; | ||
| 134 | |||
| 135 | if (count) { | ||
| 136 | /* Get a copy of the hvc and copy out the relevant portion. */ | ||
| 137 | char *hvc; | ||
| 138 | |||
| 139 | size = off + count; | ||
| 140 | hvc = kmalloc(size, GFP_KERNEL); | ||
| 141 | if (hvc == NULL) | ||
| 142 | return -ENOMEM; | ||
| 143 | hv_confstr(HV_CONFSTR_HV_CONFIG, (unsigned long)hvc, size); | ||
| 144 | memcpy(buf, hvc + off, count); | ||
| 145 | kfree(hvc); | ||
| 146 | } | ||
| 147 | |||
| 148 | return count; | ||
| 149 | } | ||
| 150 | |||
| 151 | static int __init create_sysfs_entries(void) | ||
| 152 | { | ||
| 153 | struct sysdev_class *cls = &cpu_sysdev_class; | ||
| 154 | int err = 0; | ||
| 155 | |||
| 156 | #define create_cpu_attr(name) \ | ||
| 157 | if (!err) \ | ||
| 158 | err = sysfs_create_file(&cls->kset.kobj, &attr_##name.attr); | ||
| 159 | create_cpu_attr(chip_width); | ||
| 160 | create_cpu_attr(chip_height); | ||
| 161 | create_cpu_attr(chip_serial); | ||
| 162 | create_cpu_attr(chip_revision); | ||
| 163 | |||
| 164 | #define create_hv_attr(name) \ | ||
| 165 | if (!err) \ | ||
| 166 | err = sysfs_create_file(hypervisor_kobj, &attr_##name.attr); | ||
| 167 | create_hv_attr(type); | ||
| 168 | create_hv_attr(version); | ||
| 169 | create_hv_attr(config_version); | ||
| 170 | |||
| 171 | if (!err) | ||
| 172 | err = sysfs_create_group(hypervisor_kobj, &board_attr_group); | ||
| 173 | |||
| 174 | if (!err) { | ||
| 175 | sysfs_bin_attr_init(&hvconfig_bin); | ||
| 176 | hvconfig_bin.attr.name = "hvconfig"; | ||
| 177 | hvconfig_bin.attr.mode = S_IRUGO; | ||
| 178 | hvconfig_bin.read = hvconfig_bin_read; | ||
| 179 | hvconfig_bin.size = PAGE_SIZE; | ||
| 180 | err = sysfs_create_bin_file(hypervisor_kobj, &hvconfig_bin); | ||
| 181 | } | ||
| 182 | |||
| 183 | return err; | ||
| 184 | } | ||
| 185 | subsys_initcall(create_sysfs_entries); | ||
diff --git a/fs/proc/base.c b/fs/proc/base.c index dfa532730e55..3ad615fb8656 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -83,6 +83,9 @@ | |||
| 83 | #include <linux/pid_namespace.h> | 83 | #include <linux/pid_namespace.h> |
| 84 | #include <linux/fs_struct.h> | 84 | #include <linux/fs_struct.h> |
| 85 | #include <linux/slab.h> | 85 | #include <linux/slab.h> |
| 86 | #ifdef CONFIG_HARDWALL | ||
| 87 | #include <asm/hardwall.h> | ||
| 88 | #endif | ||
| 86 | #include "internal.h" | 89 | #include "internal.h" |
| 87 | 90 | ||
| 88 | /* NOTE: | 91 | /* NOTE: |
| @@ -2894,6 +2897,9 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2894 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2897 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
| 2895 | INF("io", S_IRUGO, proc_tgid_io_accounting), | 2898 | INF("io", S_IRUGO, proc_tgid_io_accounting), |
| 2896 | #endif | 2899 | #endif |
| 2900 | #ifdef CONFIG_HARDWALL | ||
| 2901 | INF("hardwall", S_IRUGO, proc_pid_hardwall), | ||
| 2902 | #endif | ||
| 2897 | }; | 2903 | }; |
| 2898 | 2904 | ||
| 2899 | static int proc_tgid_base_readdir(struct file * filp, | 2905 | static int proc_tgid_base_readdir(struct file * filp, |
| @@ -3232,6 +3238,9 @@ static const struct pid_entry tid_base_stuff[] = { | |||
| 3232 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 3238 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
| 3233 | INF("io", S_IRUGO, proc_tid_io_accounting), | 3239 | INF("io", S_IRUGO, proc_tid_io_accounting), |
| 3234 | #endif | 3240 | #endif |
| 3241 | #ifdef CONFIG_HARDWALL | ||
| 3242 | INF("hardwall", S_IRUGO, proc_pid_hardwall), | ||
| 3243 | #endif | ||
| 3235 | }; | 3244 | }; |
| 3236 | 3245 | ||
| 3237 | static int proc_tid_base_readdir(struct file * filp, | 3246 | static int proc_tid_base_readdir(struct file * filp, |
