aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Travis <travis@sgi.com>2013-10-02 11:14:19 -0400
committerIngo Molnar <mingo@kernel.org>2013-10-03 12:48:09 -0400
commite379ea82dd53a5cc8e3ac0b7899a8012006c712c (patch)
tree9a42f2d9716d8956389ed381e4c15a2fe53695d4
parent8daaa5f8261bffd2f6217a960f9182d0503a5c44 (diff)
x86/UV: Add call to KGDB/KDB from NMI handler
This patch restores the capability to enter KDB (and KGDB) from the UV NMI handler. This is needed because the UV system console is not capable of sending the 'break' signal to the serial console port. It is also useful when the kernel is hung in such a way that it isn't responding to normal external I/O, so sending 'g' to sysreq-trigger does not work either. Another benefit of the external NMI command is that all the cpus receive the NMI signal at roughly the same time so they are more closely aligned timewise. It utilizes the newly added kgdb_nmicallin function to gain entry to KGDB/KDB by the master. The slaves still enter via the standard kgdb_nmicallback function. It also uses the new 'send_ready' pointer to tell KGDB/KDB to signal the slaves when to proceed into the KGDB slave loop. It is enabled when the nmi action is set to "kdb" and the kernel is built with CONFIG_KDB enabled. Note that if kgdb is connected that interface will be used instead. 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/20131002151418.089692683@asylum.americas.sgi.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/platform/uv/uv_nmi.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/arch/x86/platform/uv/uv_nmi.c b/arch/x86/platform/uv/uv_nmi.c
index 9126dfb6dbfc..9b8ac60ad8db 100644
--- a/arch/x86/platform/uv/uv_nmi.c
+++ b/arch/x86/platform/uv/uv_nmi.c
@@ -21,7 +21,9 @@
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/kdb.h>
24#include <linux/kexec.h> 25#include <linux/kexec.h>
26#include <linux/kgdb.h>
25#include <linux/module.h> 27#include <linux/module.h>
26#include <linux/nmi.h> 28#include <linux/nmi.h>
27#include <linux/sched.h> 29#include <linux/sched.h>
@@ -32,6 +34,7 @@
32#include <asm/kdebug.h> 34#include <asm/kdebug.h>
33#include <asm/local64.h> 35#include <asm/local64.h>
34#include <asm/nmi.h> 36#include <asm/nmi.h>
37#include <asm/traps.h>
35#include <asm/uv/uv.h> 38#include <asm/uv/uv.h>
36#include <asm/uv/uv_hub.h> 39#include <asm/uv/uv_hub.h>
37#include <asm/uv/uv_mmrs.h> 40#include <asm/uv/uv_mmrs.h>
@@ -153,8 +156,9 @@ module_param_named(retry_count, uv_nmi_retry_count, int, 0644);
153 * "dump" - dump process stack for each cpu 156 * "dump" - dump process stack for each cpu
154 * "ips" - dump IP info for each cpu 157 * "ips" - dump IP info for each cpu
155 * "kdump" - do crash dump 158 * "kdump" - do crash dump
159 * "kdb" - enter KDB/KGDB (default)
156 */ 160 */
157static char uv_nmi_action[8] = "dump"; 161static char uv_nmi_action[8] = "kdb";
158module_param_string(action, uv_nmi_action, sizeof(uv_nmi_action), 0644); 162module_param_string(action, uv_nmi_action, sizeof(uv_nmi_action), 0644);
159 163
160static inline bool uv_nmi_action_is(const char *action) 164static inline bool uv_nmi_action_is(const char *action)
@@ -540,6 +544,43 @@ static inline void uv_nmi_kdump(int cpu, int master, struct pt_regs *regs)
540} 544}
541#endif /* !CONFIG_KEXEC */ 545#endif /* !CONFIG_KEXEC */
542 546
547#ifdef CONFIG_KGDB_KDB
548/* Call KDB from NMI handler */
549static void uv_call_kdb(int cpu, struct pt_regs *regs, int master)
550{
551 int ret;
552
553 if (master) {
554 /* call KGDB NMI handler as MASTER */
555 ret = kgdb_nmicallin(cpu, X86_TRAP_NMI, regs,
556 &uv_nmi_slave_continue);
557 if (ret) {
558 pr_alert("KDB returned error, is kgdboc set?\n");
559 atomic_set(&uv_nmi_slave_continue, SLAVE_EXIT);
560 }
561 } else {
562 /* wait for KGDB signal that it's ready for slaves to enter */
563 int sig;
564
565 do {
566 cpu_relax();
567 sig = atomic_read(&uv_nmi_slave_continue);
568 } while (!sig);
569
570 /* call KGDB as slave */
571 if (sig == SLAVE_CONTINUE)
572 kgdb_nmicallback(cpu, regs);
573 }
574 uv_nmi_sync_exit(master);
575}
576
577#else /* !CONFIG_KGDB_KDB */
578static inline void uv_call_kdb(int cpu, struct pt_regs *regs, int master)
579{
580 pr_err("UV: NMI error: KGDB/KDB is not enabled in this kernel\n");
581}
582#endif /* !CONFIG_KGDB_KDB */
583
543/* 584/*
544 * UV NMI handler 585 * UV NMI handler
545 */ 586 */
@@ -576,6 +617,10 @@ int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
576 if (uv_nmi_action_is("ips") || uv_nmi_action_is("dump")) 617 if (uv_nmi_action_is("ips") || uv_nmi_action_is("dump"))
577 uv_nmi_dump_state(cpu, regs, master); 618 uv_nmi_dump_state(cpu, regs, master);
578 619
620 /* Call KDB if enabled */
621 else if (uv_nmi_action_is("kdb"))
622 uv_call_kdb(cpu, regs, master);
623
579 /* Clear per_cpu "in nmi" flag */ 624 /* Clear per_cpu "in nmi" flag */
580 atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_OUT); 625 atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_OUT);
581 626