Index: sys/kern/kern_shutdown.c =================================================================== --- sys/kern/kern_shutdown.c +++ sys/kern/kern_shutdown.c @@ -119,9 +119,9 @@ #ifdef KDB #ifdef KDB_UNATTENDED -static int debugger_on_panic = 0; +int debugger_on_panic = 0; #else -static int debugger_on_panic = 1; +int debugger_on_panic = 1; #endif SYSCTL_INT(_debug, OID_AUTO, debugger_on_panic, CTLFLAG_RWTUN | CTLFLAG_SECURE, Index: sys/sys/kdb.h =================================================================== --- sys/sys/kdb.h +++ sys/sys/kdb.h @@ -65,6 +65,7 @@ SET_DECLARE(kdb_dbbe_set, struct kdb_dbbe); extern u_char kdb_active; /* Non-zero while in debugger. */ +extern int debugger_on_panic; /* enter the debugger on panic. */ extern int debugger_on_trap; /* enter the debugger on trap. */ extern struct kdb_dbbe *kdb_dbbe; /* Default debugger backend or NULL. */ extern struct trapframe *kdb_frame; /* Frame to kdb_trap(). */ Index: sys/x86/x86/cpu_machdep.c =================================================================== --- sys/x86/x86/cpu_machdep.c +++ sys/x86/x86/cpu_machdep.c @@ -823,20 +823,14 @@ } SYSINIT(cpu_idle_tun, SI_SUB_CPU, SI_ORDER_MIDDLE, cpu_idle_tun, NULL); -static int panic_on_nmi = 1; +static int panic_on_nmi = 0xff; SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RWTUN, &panic_on_nmi, 0, - "Panic on NMI raised by hardware failure"); + "Panic on NMI: 1 = H/W failure; 2 = unknown; 0xff = all"); int nmi_is_broadcast = 1; SYSCTL_INT(_machdep, OID_AUTO, nmi_is_broadcast, CTLFLAG_RWTUN, &nmi_is_broadcast, 0, "Chipset NMI is broadcast"); -#ifdef KDB -int kdb_on_nmi = 1; -SYSCTL_INT(_machdep, OID_AUTO, kdb_on_nmi, CTLFLAG_RWTUN, - &kdb_on_nmi, 0, - "Go to KDB on NMI with unknown source"); -#endif void nmi_call_kdb(u_int cpu, u_int type, struct trapframe *frame) @@ -847,19 +841,31 @@ /* machine/parity/power fail/"kitchen sink" faults */ if (isa_nmi(frame->tf_err)) { claimed = true; - if (panic_on_nmi) + if ((panic_on_nmi & 1) != 0) panic("NMI indicates hardware failure"); } #endif /* DEV_ISA */ + + /* + * NMIs can be useful for debugging. They can be hooked up to a + * pushbutton, usually on an ISA, PCI, or PCIe card. They can also be + * generated by an IPMI BMC, either manually or in response to a + * watchdog timeout. For example, see the "power diag" command in + * ports/sysutils/ipmitool. They can also be generated by a + * hypervisor; see "bhyvectl --inject-nmi". + */ + #ifdef KDB - if (!claimed && kdb_on_nmi) { - /* - * NMI can be hooked up to a pushbutton for debugging. - */ - printf("NMI/cpu%d ... going to debugger\n", cpu); - kdb_trap(type, 0, frame); + if (!claimed && (panic_on_nmi & 2) != 0) { + if (debugger_on_panic) { + printf("NMI/cpu%d ... going to debugger\n", cpu); + claimed = kdb_trap(type, 0, frame); + } } #endif /* KDB */ + + if (!claimed && panic_on_nmi != 0) + panic("NMI"); } void