aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorRobin Holt <holt@sgi.com>2012-12-20 18:05:50 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-20 20:40:20 -0500
commit891348ca0f66206f1dc0e30d63757e3df1ae2d15 (patch)
tree4c85b91a26bfe3892ffc61e26551cb4ac23eebd3 /drivers/misc
parentc39540c6d1add1d0ad843b3d2437311924193359 (diff)
SGI-XP: handle non-fatal traps
We found a user code which was raising a divide-by-zero trap. That trap would lead to XPC connections between system-partitions being torn down due to the die_chain notifier callouts it received. This also revealed a different issue where multiple callers into xpc_die_deactivate() would all attempt to do the disconnect in parallel which would sometimes lock up but often overwhelm the console on very large machines as each would print at least one line of output at the end of the deactivate. I reviewed all the users of the die_chain notifier and changed the code to ignore the notifier callouts for reasons which will not actually lead to a system to continue on to call die(). [akpm@linux-foundation.org: fix ia64] Signed-off-by: Robin Holt <holt@sgi.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@elte.hu> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
index 8d082b46426b..d971817182f7 100644
--- a/drivers/misc/sgi-xp/xpc_main.c
+++ b/drivers/misc/sgi-xp/xpc_main.c
@@ -53,6 +53,10 @@
53#include <linux/kthread.h> 53#include <linux/kthread.h>
54#include "xpc.h" 54#include "xpc.h"
55 55
56#ifdef CONFIG_X86_64
57#include <asm/traps.h>
58#endif
59
56/* define two XPC debug device structures to be used with dev_dbg() et al */ 60/* define two XPC debug device structures to be used with dev_dbg() et al */
57 61
58struct device_driver xpc_dbg_name = { 62struct device_driver xpc_dbg_name = {
@@ -1079,6 +1083,9 @@ xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
1079 return NOTIFY_DONE; 1083 return NOTIFY_DONE;
1080} 1084}
1081 1085
1086/* Used to only allow one cpu to complete disconnect */
1087static unsigned int xpc_die_disconnecting;
1088
1082/* 1089/*
1083 * Notify other partitions to deactivate from us by first disengaging from all 1090 * Notify other partitions to deactivate from us by first disengaging from all
1084 * references to our memory. 1091 * references to our memory.
@@ -1092,6 +1099,9 @@ xpc_die_deactivate(void)
1092 long keep_waiting; 1099 long keep_waiting;
1093 long wait_to_print; 1100 long wait_to_print;
1094 1101
1102 if (cmpxchg(&xpc_die_disconnecting, 0, 1))
1103 return;
1104
1095 /* keep xpc_hb_checker thread from doing anything (just in case) */ 1105 /* keep xpc_hb_checker thread from doing anything (just in case) */
1096 xpc_exiting = 1; 1106 xpc_exiting = 1;
1097 1107
@@ -1159,7 +1169,7 @@ xpc_die_deactivate(void)
1159 * about the lack of a heartbeat. 1169 * about the lack of a heartbeat.
1160 */ 1170 */
1161static int 1171static int
1162xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) 1172xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args)
1163{ 1173{
1164#ifdef CONFIG_IA64 /* !!! temporary kludge */ 1174#ifdef CONFIG_IA64 /* !!! temporary kludge */
1165 switch (event) { 1175 switch (event) {
@@ -1191,7 +1201,27 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
1191 break; 1201 break;
1192 } 1202 }
1193#else 1203#else
1194 xpc_die_deactivate(); 1204 struct die_args *die_args = _die_args;
1205
1206 switch (event) {
1207 case DIE_TRAP:
1208 if (die_args->trapnr == X86_TRAP_DF)
1209 xpc_die_deactivate();
1210
1211 if (((die_args->trapnr == X86_TRAP_MF) ||
1212 (die_args->trapnr == X86_TRAP_XF)) &&
1213 !user_mode_vm(die_args->regs))
1214 xpc_die_deactivate();
1215
1216 break;
1217 case DIE_INT3:
1218 case DIE_DEBUG:
1219 break;
1220 case DIE_OOPS:
1221 case DIE_GPF:
1222 default:
1223 xpc_die_deactivate();
1224 }
1195#endif 1225#endif
1196 1226
1197 return NOTIFY_DONE; 1227 return NOTIFY_DONE;