diff options
Diffstat (limited to 'arch/tile/kernel/hardwall.c')
-rw-r--r-- | arch/tile/kernel/hardwall.c | 101 |
1 files changed, 71 insertions, 30 deletions
diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c index 584b965dc824..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) |
@@ -151,12 +162,12 @@ enum direction_protect { | |||
151 | 162 | ||
152 | static void enable_firewall_interrupts(void) | 163 | static void enable_firewall_interrupts(void) |
153 | { | 164 | { |
154 | raw_local_irq_unmask_now(INT_UDN_FIREWALL); | 165 | arch_local_irq_unmask_now(INT_UDN_FIREWALL); |
155 | } | 166 | } |
156 | 167 | ||
157 | static void disable_firewall_interrupts(void) | 168 | static void disable_firewall_interrupts(void) |
158 | { | 169 | { |
159 | raw_local_irq_mask_now(INT_UDN_FIREWALL); | 170 | arch_local_irq_mask_now(INT_UDN_FIREWALL); |
160 | } | 171 | } |
161 | 172 | ||
162 | /* Set up hardwall on this cpu based on the passed hardwall_info. */ | 173 | /* Set up hardwall on this cpu based on the passed hardwall_info. */ |
@@ -268,12 +279,10 @@ void __kprobes do_hardwall_trap(struct pt_regs* regs, int fault_num) | |||
268 | found_processes = 0; | 279 | found_processes = 0; |
269 | list_for_each_entry(p, &rect->task_head, thread.hardwall_list) { | 280 | list_for_each_entry(p, &rect->task_head, thread.hardwall_list) { |
270 | BUG_ON(p->thread.hardwall != rect); | 281 | BUG_ON(p->thread.hardwall != rect); |
271 | if (p->sighand) { | 282 | if (!(p->flags & PF_EXITING)) { |
272 | found_processes = 1; | 283 | found_processes = 1; |
273 | pr_notice("hardwall: killing %d\n", p->pid); | 284 | pr_notice("hardwall: killing %d\n", p->pid); |
274 | spin_lock(&p->sighand->siglock); | 285 | do_send_sig_info(info.si_signo, &info, p, false); |
275 | __group_send_sig_info(info.si_signo, &info, p); | ||
276 | spin_unlock(&p->sighand->siglock); | ||
277 | } | 286 | } |
278 | } | 287 | } |
279 | if (!found_processes) | 288 | if (!found_processes) |
@@ -390,6 +399,9 @@ static struct hardwall_info *hardwall_create( | |||
390 | /* Set up appropriate hardwalling on all affected cpus. */ | 399 | /* Set up appropriate hardwalling on all affected cpus. */ |
391 | hardwall_setup(rect); | 400 | hardwall_setup(rect); |
392 | 401 | ||
402 | /* Create a /proc/tile/hardwall entry. */ | ||
403 | hardwall_add_proc(rect); | ||
404 | |||
393 | return rect; | 405 | return rect; |
394 | } | 406 | } |
395 | 407 | ||
@@ -647,6 +659,9 @@ static void hardwall_destroy(struct hardwall_info *rect) | |||
647 | /* Restart switch and disable firewall. */ | 659 | /* Restart switch and disable firewall. */ |
648 | on_each_cpu_mask(&mask, restart_udn_switch, NULL, 1); | 660 | on_each_cpu_mask(&mask, restart_udn_switch, NULL, 1); |
649 | 661 | ||
662 | /* Remove the /proc/tile/hardwall entry. */ | ||
663 | hardwall_remove_proc(rect); | ||
664 | |||
650 | /* Now free the rectangle from the list. */ | 665 | /* Now free the rectangle from the list. */ |
651 | spin_lock_irqsave(&hardwall_lock, flags); | 666 | spin_lock_irqsave(&hardwall_lock, flags); |
652 | BUG_ON(!list_empty(&rect->task_head)); | 667 | BUG_ON(!list_empty(&rect->task_head)); |
@@ -656,35 +671,57 @@ static void hardwall_destroy(struct hardwall_info *rect) | |||
656 | } | 671 | } |
657 | 672 | ||
658 | 673 | ||
659 | /* | 674 | static int hardwall_proc_show(struct seq_file *sf, void *v) |
660 | * Dump hardwall state via /proc; initialized in arch/tile/sys/proc.c. | ||
661 | */ | ||
662 | int proc_tile_hardwall_show(struct seq_file *sf, void *v) | ||
663 | { | 675 | { |
664 | struct hardwall_info *r; | 676 | struct hardwall_info *rect = sf->private; |
677 | char buf[256]; | ||
665 | 678 | ||
666 | if (udn_disabled) { | 679 | int rc = cpulist_scnprintf(buf, sizeof(buf), &rect->cpumask); |
667 | seq_printf(sf, "%dx%d 0,0 pids:\n", smp_width, smp_height); | 680 | buf[rc++] = '\n'; |
668 | return 0; | 681 | seq_write(sf, buf, rc); |
669 | } | ||
670 | |||
671 | spin_lock_irq(&hardwall_lock); | ||
672 | list_for_each_entry(r, &rectangles, list) { | ||
673 | struct task_struct *p; | ||
674 | seq_printf(sf, "%dx%d %d,%d pids:", | ||
675 | r->width, r->height, r->ulhc_x, r->ulhc_y); | ||
676 | list_for_each_entry(p, &r->task_head, thread.hardwall_list) { | ||
677 | unsigned int cpu = cpumask_first(&p->cpus_allowed); | ||
678 | unsigned int x = cpu % smp_width; | ||
679 | unsigned int y = cpu / smp_width; | ||
680 | seq_printf(sf, " %d@%d,%d", p->pid, x, y); | ||
681 | } | ||
682 | seq_printf(sf, "\n"); | ||
683 | } | ||
684 | spin_unlock_irq(&hardwall_lock); | ||
685 | return 0; | 682 | return 0; |
686 | } | 683 | } |
687 | 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 | |||
688 | 725 | ||
689 | /* | 726 | /* |
690 | * Character device support via ioctl/close. | 727 | * Character device support via ioctl/close. |
@@ -718,6 +755,9 @@ static long hardwall_ioctl(struct file *file, unsigned int a, unsigned long b) | |||
718 | return -EINVAL; | 755 | return -EINVAL; |
719 | return hardwall_deactivate(current); | 756 | return hardwall_deactivate(current); |
720 | 757 | ||
758 | case _HARDWALL_GET_ID: | ||
759 | return rect ? rect->id : -EINVAL; | ||
760 | |||
721 | default: | 761 | default: |
722 | return -EINVAL; | 762 | return -EINVAL; |
723 | } | 763 | } |
@@ -768,6 +808,7 @@ static int hardwall_release(struct inode *inode, struct file *file) | |||
768 | } | 808 | } |
769 | 809 | ||
770 | static const struct file_operations dev_hardwall_fops = { | 810 | static const struct file_operations dev_hardwall_fops = { |
811 | .open = nonseekable_open, | ||
771 | .unlocked_ioctl = hardwall_ioctl, | 812 | .unlocked_ioctl = hardwall_ioctl, |
772 | #ifdef CONFIG_COMPAT | 813 | #ifdef CONFIG_COMPAT |
773 | .compat_ioctl = hardwall_compat_ioctl, | 814 | .compat_ioctl = hardwall_compat_ioctl, |