diff options
author | Mike Travis <travis@sgi.com> | 2013-09-23 17:25:03 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2013-09-24 03:02:03 -0400 |
commit | 12ba6c990fab50fe568f3ad8715e81e356552428 (patch) | |
tree | 7d35b961d4ef8fdf02eae86e9d0e795113950a42 | |
parent | 3c121d9a21dc16ef030ad6ca3ebb159b5726fab9 (diff) |
x86/UV: Add kdump to UV NMI handler
If a system has hung and it no longer responds to external
events, this patch adds the capability of doing a standard kdump
and system reboot then triggered by the system NMI command.
It is enabled when the nmi action is changed to "kdump" and the
kernel is built with CONFIG_KEXEC enabled.
Signed-off-by: Mike Travis <travis@sgi.com>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Reviewed-by: Hedi Berriche <hedi@sgi.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Jason Wessel <jason.wessel@windriver.com>
Link: http://lkml.kernel.org/r/20130923212500.660567460@asylum.americas.sgi.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/platform/uv/uv_nmi.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/arch/x86/platform/uv/uv_nmi.c b/arch/x86/platform/uv/uv_nmi.c index 4efcde1b9d54..2579fbd6b95c 100644 --- a/arch/x86/platform/uv/uv_nmi.c +++ b/arch/x86/platform/uv/uv_nmi.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include <linux/cpu.h> | 22 | #include <linux/cpu.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/kexec.h> | ||
24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
25 | #include <linux/nmi.h> | 26 | #include <linux/nmi.h> |
26 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
@@ -70,6 +71,7 @@ static atomic_t uv_in_nmi; | |||
70 | static atomic_t uv_nmi_cpu = ATOMIC_INIT(-1); | 71 | static atomic_t uv_nmi_cpu = ATOMIC_INIT(-1); |
71 | static atomic_t uv_nmi_cpus_in_nmi = ATOMIC_INIT(-1); | 72 | static atomic_t uv_nmi_cpus_in_nmi = ATOMIC_INIT(-1); |
72 | static atomic_t uv_nmi_slave_continue; | 73 | static atomic_t uv_nmi_slave_continue; |
74 | static atomic_t uv_nmi_kexec_failed; | ||
73 | static cpumask_var_t uv_nmi_cpu_mask; | 75 | static cpumask_var_t uv_nmi_cpu_mask; |
74 | 76 | ||
75 | /* Values for uv_nmi_slave_continue */ | 77 | /* Values for uv_nmi_slave_continue */ |
@@ -143,6 +145,7 @@ module_param_named(retry_count, uv_nmi_retry_count, int, 0644); | |||
143 | * Valid NMI Actions: | 145 | * Valid NMI Actions: |
144 | * "dump" - dump process stack for each cpu | 146 | * "dump" - dump process stack for each cpu |
145 | * "ips" - dump IP info for each cpu | 147 | * "ips" - dump IP info for each cpu |
148 | * "kdump" - do crash dump | ||
146 | */ | 149 | */ |
147 | static char uv_nmi_action[8] = "dump"; | 150 | static char uv_nmi_action[8] = "dump"; |
148 | module_param_string(action, uv_nmi_action, sizeof(uv_nmi_action), 0644); | 151 | module_param_string(action, uv_nmi_action, sizeof(uv_nmi_action), 0644); |
@@ -496,6 +499,40 @@ static void uv_nmi_touch_watchdogs(void) | |||
496 | touch_nmi_watchdog(); | 499 | touch_nmi_watchdog(); |
497 | } | 500 | } |
498 | 501 | ||
502 | #if defined(CONFIG_KEXEC) | ||
503 | static void uv_nmi_kdump(int cpu, int master, struct pt_regs *regs) | ||
504 | { | ||
505 | /* Call crash to dump system state */ | ||
506 | if (master) { | ||
507 | pr_emerg("UV: NMI executing crash_kexec on CPU%d\n", cpu); | ||
508 | crash_kexec(regs); | ||
509 | |||
510 | pr_emerg("UV: crash_kexec unexpectedly returned, "); | ||
511 | if (!kexec_crash_image) { | ||
512 | pr_cont("crash kernel not loaded\n"); | ||
513 | atomic_set(&uv_nmi_kexec_failed, 1); | ||
514 | uv_nmi_sync_exit(1); | ||
515 | return; | ||
516 | } | ||
517 | pr_cont("kexec busy, stalling cpus while waiting\n"); | ||
518 | } | ||
519 | |||
520 | /* If crash exec fails the slaves should return, otherwise stall */ | ||
521 | while (atomic_read(&uv_nmi_kexec_failed) == 0) | ||
522 | mdelay(10); | ||
523 | |||
524 | /* Crash kernel most likely not loaded, return in an orderly fashion */ | ||
525 | uv_nmi_sync_exit(0); | ||
526 | } | ||
527 | |||
528 | #else /* !CONFIG_KEXEC */ | ||
529 | static inline void uv_nmi_kdump(int cpu, int master, struct pt_regs *regs) | ||
530 | { | ||
531 | if (master) | ||
532 | pr_err("UV: NMI kdump: KEXEC not supported in this kernel\n"); | ||
533 | } | ||
534 | #endif /* !CONFIG_KEXEC */ | ||
535 | |||
499 | /* | 536 | /* |
500 | * UV NMI handler | 537 | * UV NMI handler |
501 | */ | 538 | */ |
@@ -517,6 +554,10 @@ int uv_handle_nmi(unsigned int reason, struct pt_regs *regs) | |||
517 | /* Indicate we are the first CPU into the NMI handler */ | 554 | /* Indicate we are the first CPU into the NMI handler */ |
518 | master = (atomic_read(&uv_nmi_cpu) == cpu); | 555 | master = (atomic_read(&uv_nmi_cpu) == cpu); |
519 | 556 | ||
557 | /* If NMI action is "kdump", then attempt to do it */ | ||
558 | if (uv_nmi_action_is("kdump")) | ||
559 | uv_nmi_kdump(cpu, master, regs); | ||
560 | |||
520 | /* Pause as all cpus enter the NMI handler */ | 561 | /* Pause as all cpus enter the NMI handler */ |
521 | uv_nmi_wait(master); | 562 | uv_nmi_wait(master); |
522 | 563 | ||