|
@@ -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 *nb, unsigned long event, void *unused)
|
|
|
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, unsigned long event, void *unused)
|
|
|
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;
|