aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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