+++ /dev/null
-From 891348ca0f66206f1dc0e30d63757e3df1ae2d15 Mon Sep 17 00:00:00 2001
-From: Robin Holt <holt@sgi.com>
-Date: Thu, 20 Dec 2012 15:05:50 -0800
-Subject: SGI-XP: handle non-fatal traps
-
-From: Robin Holt <holt@sgi.com>
-
-commit 891348ca0f66206f1dc0e30d63757e3df1ae2d15 upstream.
-
-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>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- drivers/misc/sgi-xp/xpc_main.c | 34 ++++++++++++++++++++++++++++++++--
- 1 file changed, 32 insertions(+), 2 deletions(-)
-
---- a/drivers/misc/sgi-xp/xpc_main.c
-+++ b/drivers/misc/sgi-xp/xpc_main.c
-@@ -53,6 +53,10 @@
- #include <linux/kthread.h>
- #include "xpc.h"
-
-+#ifdef CONFIG_X86_64
-+#include <asm/traps.h>
-+#endif
-+
- /* define two XPC debug device structures to be used with dev_dbg() et al */
-
- struct device_driver xpc_dbg_name = {
-@@ -1079,6 +1083,9 @@ xpc_system_reboot(struct notifier_block
- return NOTIFY_DONE;
- }
-
-+/* Used to only allow one cpu to complete disconnect */
-+static unsigned int xpc_die_disconnecting;
-+
- /*
- * Notify other partitions to deactivate from us by first disengaging from all
- * references to our memory.
-@@ -1092,6 +1099,9 @@ xpc_die_deactivate(void)
- long keep_waiting;
- long wait_to_print;
-
-+ if (cmpxchg(&xpc_die_disconnecting, 0, 1))
-+ return;
-+
- /* keep xpc_hb_checker thread from doing anything (just in case) */
- xpc_exiting = 1;
-
-@@ -1159,7 +1169,7 @@ xpc_die_deactivate(void)
- * about the lack of a heartbeat.
- */
- static int
--xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
-+xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args)
- {
- #ifdef CONFIG_IA64 /* !!! temporary kludge */
- switch (event) {
-@@ -1191,7 +1201,27 @@ xpc_system_die(struct notifier_block *nb
- break;
- }
- #else
-- xpc_die_deactivate();
-+ struct die_args *die_args = _die_args;
-+
-+ switch (event) {
-+ case DIE_TRAP:
-+ if (die_args->trapnr == X86_TRAP_DF)
-+ xpc_die_deactivate();
-+
-+ if (((die_args->trapnr == X86_TRAP_MF) ||
-+ (die_args->trapnr == X86_TRAP_XF)) &&
-+ !user_mode_vm(die_args->regs))
-+ xpc_die_deactivate();
-+
-+ break;
-+ case DIE_INT3:
-+ case DIE_DEBUG:
-+ break;
-+ case DIE_OOPS:
-+ case DIE_GPF:
-+ default:
-+ xpc_die_deactivate();
-+ }
- #endif
-
- return NOTIFY_DONE;