This patch restores the ability to enter KDB (and KGDB) from the UV
NMI handler.  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.

The handler also uses the new 'send_ready' pointer to tell KGDB/KDB
to signal the slaves when to proceed into the KGDB slave loop.

Cc: Alexander Gordeev <agord...@redhat.com>
Cc: Suresh Siddha <suresh.b.sid...@intel.com>
Cc: "Michael S. Tsirkin" <m...@redhat.com>
Cc: Steffen Persvold <s...@numascale.com>
Reviewed-by: Dimitri Sivanich <sivan...@sgi.com>
Signed-off-by: Mike Travis <tra...@sgi.com>
---
 arch/x86/platform/uv/uv_nmi.c |   73 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 71 insertions(+), 2 deletions(-)

--- linux.orig/arch/x86/platform/uv/uv_nmi.c
+++ linux/arch/x86/platform/uv/uv_nmi.c
@@ -21,6 +21,8 @@
 
 #include <linux/cpu.h>
 #include <linux/delay.h>
+#include <linux/kgdb.h>
+#include <linux/kdb.h>
 #include <linux/module.h>
 #include <linux/nmi.h>
 #include <linux/sched.h>
@@ -34,6 +36,7 @@
 #include <asm/current.h>
 #include <asm/kdebug.h>
 #include <asm/local64.h>
+#include <asm/traps.h>
 #include <asm/uv/uv.h>
 #include <asm/uv/uv_hub.h>
 #include <asm/uv/uv_mmrs.h>
@@ -521,6 +524,68 @@ static void uv_nmi_touch_watchdogs(void)
        touch_nmi_watchdog();
 }
 
+#ifdef CONFIG_KGDB_KDB
+
+/* Disable to force process dump instead of entering KDB or KGDB */
+static int uv_nmi_kdb_on = 1;
+module_param_named(kdb_on, uv_nmi_kdb_on, int, 0644);
+
+/* Call KDB from NMI handler */
+static void uv_call_kdb(int cpu, struct pt_regs *regs,
+                       int master, unsigned long *flags)
+{
+       int ret;
+
+       if (master) {
+               /* call KGDB NMI handler as MASTER */
+               local_irq_restore(*flags);
+               ret = kgdb_nmicallin(cpu, X86_TRAP_NMI, regs,
+                                       &uv_nmi_slave_continue);
+               local_irq_save(*flags);
+
+               /*
+                * if KGDB/KDB did not handle the NMI, then signal slaves
+                *   to do process dump instead.
+                */
+               if (ret) {
+                       uv_nmi_dump_state(cpu, regs, 1);
+                       return;
+               }
+       } else {
+               int sig;
+
+               /* wait for KGDB to say it's ready for slaves to enter */
+               do {
+                       cpu_relax();
+                       sig = atomic_read(&uv_nmi_slave_continue);
+               } while (!sig);
+
+               /*
+                * if KGDB/KDB did not handle the NMI for the master, then
+                *   the master signals the slaves to do process dump instead.
+                */
+               if (sig == 2) {
+                       uv_nmi_dump_state(cpu, regs, 0);
+                       return;
+               }
+
+               /* call KGDB as slave */
+               local_irq_restore(*flags);
+               ret = kgdb_nmicallback(cpu, regs);
+               local_irq_save(*flags);
+       }
+       uv_nmi_sync_exit(master);
+}
+
+#else /* !CONFIG_KGDB_KDB */
+static inline void uv_call_kdb(int cpu, struct pt_regs *regs,
+                               int master, unsigned long *flags)
+{
+       pr_err("UV: NMI error: KDB is not enabled in this kernel\n");
+       uv_nmi_dump_state(cpu, regs, master);
+}
+#endif /* !CONFIG_KGDB_KDB */
+
 /*
  * UV NMI handler
  */
@@ -547,8 +612,12 @@ int uv_handle_nmi(unsigned int reason, s
        if (master && uv_nmi_kdump_requested)
                uv_nmi_kdump(regs);
 
-       /* Dump state of each cpu */
-       uv_nmi_dump_state(cpu, regs, master);
+       /* Call KDB if enabled */
+       if (uv_nmi_kdb_on)
+               uv_call_kdb(cpu, regs, master, &flags);
+
+       else    /* Otherwise dump state of each cpu */
+               uv_nmi_dump_state(cpu, regs, master);
 
        /* Clear per_cpu "in nmi" flag */
        atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_OUT);

-- 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to