Fix handling of NMIs from unknown sources (BMC, hypervisor)
Release kernels have no KDB backends enabled, so they discard an NMI if it is not due to a hardware failure. This includes NMIs from IPMI BMCs and hypervisors. Furthermore, the interaction of panic_on_nmi, kdb_on_nmi, and debugger_on_panic is confusing. Respond to all NMIs according to panic_on_nmi and debugger_on_panic. Remove kdb_on_nmi. Expand the meaning of panic_on_nmi by making it a bitfield. There are currently two bits: one for NMIs due to hardware failure, and one for all others. Leave room for more. If panic_on_nmi and debugger_on_panic are both true, don't actually panic, but directly enter the debugger, to allow someone to leave the debugger and [hopefully] resume normal execution. Reviewed by: kib MFC after: 2 weeks Relnotes: yes: machdep.kdb_on_nmi is gone; machdep.panic_on_nmi changed Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D24558
This commit is contained in:
parent
bccd2db598
commit
3188fdb7b8
@ -119,9 +119,9 @@ SYSCTL_INT(_kern, OID_AUTO, panic_reboot_wait_time, CTLFLAG_RWTUN,
|
||||
|
||||
#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,
|
||||
|
@ -65,6 +65,7 @@ struct kdb_dbbe {
|
||||
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(). */
|
||||
|
@ -823,20 +823,14 @@ cpu_idle_tun(void *unused __unused)
|
||||
}
|
||||
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 @@ nmi_call_kdb(u_int cpu, u_int type, struct trapframe *frame)
|
||||
/* 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
|
||||
|
Loading…
Reference in New Issue
Block a user