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 Cc: Suresh Siddha Cc: "Michael S. Tsirkin" Cc: Steffen Persvold Reviewed-by: Dimitri Sivanich Signed-off-by: Mike Travis --- 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 #include +#include +#include #include #include #include @@ -33,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -511,6 +514,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 */ @@ -537,8 +602,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 majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/