Page MenuHomeFreeBSD

D8249.id21656.diff
No OneTemporary

D8249.id21656.diff

Index: head/sys/amd64/amd64/trap.c
===================================================================
--- head/sys/amd64/amd64/trap.c
+++ head/sys/amd64/amd64/trap.c
@@ -144,11 +144,6 @@
"DTrace pid return trap", /* 32 T_DTRACE_RET */
};
-#ifdef KDB
-static int kdb_on_nmi = 1;
-SYSCTL_INT(_machdep, OID_AUTO, kdb_on_nmi, CTLFLAG_RWTUN,
- &kdb_on_nmi, 0, "Go to KDB on NMI");
-#endif
static int panic_on_nmi = 1;
SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RWTUN,
&panic_on_nmi, 0, "Panic on NMI");
@@ -377,21 +372,7 @@
#ifdef DEV_ISA
case T_NMI:
- /* machine/parity/power fail/"kitchen sink" faults */
- if (isa_nmi(frame->tf_err) == 0) {
-#ifdef KDB
- /*
- * NMI can be hooked up to a pushbutton
- * for debugging.
- */
- if (kdb_on_nmi) {
- printf ("NMI ... going to debugger\n");
- kdb_trap(type, 0, frame);
- }
-#endif /* KDB */
- goto userout;
- } else if (panic_on_nmi)
- panic("NMI indicates hardware failure");
+ nmi_handle_intr(type, frame, true);
break;
#endif /* DEV_ISA */
@@ -563,20 +544,8 @@
#ifdef DEV_ISA
case T_NMI:
- /* machine/parity/power fail/"kitchen sink" faults */
- if (isa_nmi(frame->tf_err) == 0) {
-#ifdef KDB
- /*
- * NMI can be hooked up to a pushbutton
- * for debugging.
- */
- if (kdb_on_nmi) {
- printf ("NMI ... going to debugger\n");
- kdb_trap(type, 0, frame);
- }
-#endif /* KDB */
- goto out;
- } else if (panic_on_nmi == 0)
+ if (nmi_handle_intr(type, frame, false) ||
+ !panic_on_nmi)
goto out;
/* FALLTHROUGH */
#endif /* DEV_ISA */
Index: head/sys/i386/i386/trap.c
===================================================================
--- head/sys/i386/i386/trap.c
+++ head/sys/i386/i386/trap.c
@@ -467,21 +467,7 @@
}
goto userout;
#else /* !POWERFAIL_NMI */
- /* machine/parity/power fail/"kitchen sink" faults */
- if (isa_nmi(frame->tf_err) == 0) {
-#ifdef KDB
- /*
- * NMI can be hooked up to a pushbutton
- * for debugging.
- */
- if (kdb_on_nmi) {
- printf ("NMI ... going to debugger\n");
- kdb_trap(type, 0, frame);
- }
-#endif /* KDB */
- goto userout;
- } else if (panic_on_nmi)
- panic("NMI indicates hardware failure");
+ nmi_handle_intr(type, frame, true);
break;
#endif /* POWERFAIL_NMI */
#endif /* DEV_ISA */
@@ -730,20 +716,8 @@
}
goto out;
#else /* !POWERFAIL_NMI */
- /* machine/parity/power fail/"kitchen sink" faults */
- if (isa_nmi(frame->tf_err) == 0) {
-#ifdef KDB
- /*
- * NMI can be hooked up to a pushbutton
- * for debugging.
- */
- if (kdb_on_nmi) {
- printf ("NMI ... going to debugger\n");
- kdb_trap(type, 0, frame);
- }
-#endif /* KDB */
- goto out;
- } else if (panic_on_nmi == 0)
+ if (nmi_handle_intr(type, frame, false) ||
+ !panic_on_nmi)
goto out;
/* FALLTHROUGH */
#endif /* POWERFAIL_NMI */
Index: head/sys/kern/subr_smp.c
===================================================================
--- head/sys/kern/subr_smp.c
+++ head/sys/kern/subr_smp.c
@@ -209,6 +209,11 @@
* 1: ok
*
*/
+#if defined(__amd64__) || defined(__i386__)
+#define X86 1
+#else
+#define X86 0
+#endif
static int
generic_stop_cpus(cpuset_t map, u_int type)
{
@@ -220,12 +225,11 @@
volatile cpuset_t *cpus;
KASSERT(
-#if defined(__amd64__) || defined(__i386__)
- type == IPI_STOP || type == IPI_STOP_HARD || type == IPI_SUSPEND,
-#else
- type == IPI_STOP || type == IPI_STOP_HARD,
+ type == IPI_STOP || type == IPI_STOP_HARD
+#if X86
+ || type == IPI_SUSPEND
#endif
- ("%s: invalid stop type", __func__));
+ , ("%s: invalid stop type", __func__));
if (!smp_started)
return (0);
@@ -233,7 +237,7 @@
CTR2(KTR_SMP, "stop_cpus(%s) with %u type",
cpusetobj_strprint(cpusetbuf, &map), type);
-#if defined(__amd64__) || defined(__i386__)
+#if X86
/*
* When suspending, ensure there are are no IPIs in progress.
* IPIs that have been issued, but not yet delivered (e.g.
@@ -245,6 +249,9 @@
mtx_lock_spin(&smp_ipi_mtx);
#endif
+#if X86
+ if (!nmi_is_broadcast || nmi_kdb_lock == 0) {
+#endif
if (stopping_cpu != PCPU_GET(cpuid))
while (atomic_cmpset_int(&stopping_cpu, NOCPU,
PCPU_GET(cpuid)) == 0)
@@ -253,8 +260,11 @@
/* send the stop IPI to all CPUs in map */
ipi_selected(map, type);
+#if X86
+ }
+#endif
-#if defined(__amd64__) || defined(__i386__)
+#if X86
if (type == IPI_SUSPEND)
cpus = &suspended_cpus;
else
@@ -272,7 +282,7 @@
}
}
-#if defined(__amd64__) || defined(__i386__)
+#if X86
if (type == IPI_SUSPEND)
mtx_unlock_spin(&smp_ipi_mtx);
#endif
@@ -295,7 +305,7 @@
return (generic_stop_cpus(map, IPI_STOP_HARD));
}
-#if defined(__amd64__) || defined(__i386__)
+#if X86
int
suspend_cpus(cpuset_t map)
{
@@ -325,20 +335,18 @@
#endif
volatile cpuset_t *cpus;
- KASSERT(
-#if defined(__amd64__) || defined(__i386__)
- type == IPI_STOP || type == IPI_STOP_HARD || type == IPI_SUSPEND,
-#else
- type == IPI_STOP || type == IPI_STOP_HARD,
+ KASSERT(type == IPI_STOP || type == IPI_STOP_HARD
+#if X86
+ || type == IPI_SUSPEND
#endif
- ("%s: invalid stop type", __func__));
+ , ("%s: invalid stop type", __func__));
if (!smp_started)
- return 0;
+ return (0);
CTR1(KTR_SMP, "restart_cpus(%s)", cpusetobj_strprint(cpusetbuf, &map));
-#if defined(__amd64__) || defined(__i386__)
+#if X86
if (type == IPI_SUSPEND)
cpus = &suspended_cpus;
else
@@ -348,11 +356,17 @@
/* signal other cpus to restart */
CPU_COPY_STORE_REL(&map, &started_cpus);
+#if X86
+ if (!nmi_is_broadcast || nmi_kdb_lock == 0) {
+#endif
/* wait for each to clear its bit */
while (CPU_OVERLAP(cpus, &map))
cpu_spinwait();
+#if X86
+ }
+#endif
- return 1;
+ return (1);
}
int
@@ -362,7 +376,7 @@
return (generic_restart_cpus(map, IPI_STOP));
}
-#if defined(__amd64__) || defined(__i386__)
+#if X86
int
resume_cpus(cpuset_t map)
{
@@ -370,6 +384,7 @@
return (generic_restart_cpus(map, IPI_SUSPEND));
}
#endif
+#undef X86
/*
* All-CPU rendezvous. CPUs are signalled, all execute the setup function
Index: head/sys/x86/include/x86_smp.h
===================================================================
--- head/sys/x86/include/x86_smp.h
+++ head/sys/x86/include/x86_smp.h
@@ -45,6 +45,9 @@
extern u_int ipi_range;
extern u_int ipi_range_size;
+extern int nmi_kdb_lock;
+extern int nmi_is_broadcast;
+
struct cpu_info {
int cpu_present:1;
int cpu_bsp:1;
Index: head/sys/x86/include/x86_var.h
===================================================================
--- head/sys/x86/include/x86_var.h
+++ head/sys/x86/include/x86_var.h
@@ -85,6 +85,7 @@
struct fpreg;
struct dbreg;
struct dumperinfo;
+struct trapframe;
/*
* The interface type of the interrupt handler entry point cannot be
@@ -107,6 +108,10 @@
void fillw(int /*u_short*/ pat, void *base, size_t cnt);
int is_physical_memory(vm_paddr_t addr);
int isa_nmi(int cd);
+bool nmi_call_kdb(u_int cpu, u_int type, struct trapframe *frame,
+ bool panic);
+bool nmi_call_kdb_smp(u_int type, struct trapframe *frame, bool panic);
+int nmi_handle_intr(u_int type, struct trapframe *frame, bool panic);
void pagecopy(void *from, void *to);
void printcpuinfo(void);
int user_dbreg_trap(void);
Index: head/sys/x86/x86/cpu_machdep.c
===================================================================
--- head/sys/x86/x86/cpu_machdep.c
+++ head/sys/x86/x86/cpu_machdep.c
@@ -47,6 +47,7 @@
#include "opt_ddb.h"
#include "opt_inet.h"
#include "opt_isa.h"
+#include "opt_kdb.h"
#include "opt_kstack_pages.h"
#include "opt_maxmem.h"
#include "opt_mp_watchdog.h"
@@ -522,3 +523,52 @@
SYSCTL_PROC(_machdep, OID_AUTO, idle, CTLTYPE_STRING | CTLFLAG_RW, 0, 0,
idle_sysctl, "A", "currently selected idle function");
+
+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");
+#endif
+
+#ifdef DEV_ISA
+bool
+nmi_call_kdb(u_int cpu, u_int type, struct trapframe *frame, bool do_panic)
+{
+
+ /* machine/parity/power fail/"kitchen sink" faults */
+ if (isa_nmi(frame->tf_err) == 0) {
+#ifdef KDB
+ /*
+ * NMI can be hooked up to a pushbutton for debugging.
+ */
+ if (kdb_on_nmi) {
+ printf ("NMI/cpu%d ... going to debugger\n", cpu);
+ kdb_trap(type, 0, frame);
+ return (true);
+ }
+ } else
+#endif /* KDB */
+ if (do_panic)
+ panic("NMI indicates hardware failure");
+ return (false);
+}
+#endif
+
+int
+nmi_handle_intr(u_int type, struct trapframe *frame, bool panic)
+{
+
+#ifdef DEV_ISA
+#ifdef SMP
+ if (nmi_is_broadcast)
+ return (nmi_call_kdb_smp(type, frame, panic));
+ else
+#endif
+ return (nmi_call_kdb(0, type, frame, panic));
+#endif
+}
Index: head/sys/x86/x86/mp_x86.c
===================================================================
--- head/sys/x86/x86/mp_x86.c
+++ head/sys/x86/x86/mp_x86.c
@@ -31,6 +31,7 @@
#include "opt_apic.h"
#endif
#include "opt_cpu.h"
+#include "opt_isa.h"
#include "opt_kstack_pages.h"
#include "opt_pmap.h"
#include "opt_sched.h"
@@ -140,6 +141,7 @@
volatile u_int cpu_ipi_pending[MAXCPU];
static void release_aps(void *dummy);
+static void cpustop_handler_post(u_int cpu);
static int hyperthreading_allowed = 1;
SYSCTL_INT(_machdep, OID_AUTO, hyperthreading_allowed, CTLFLAG_RDTUN,
@@ -1211,6 +1213,34 @@
return (0);
}
+#ifdef DEV_ISA
+int nmi_kdb_lock;
+
+bool
+nmi_call_kdb_smp(u_int type, struct trapframe *frame, bool do_panic)
+{
+ int cpu;
+ bool call_post, ret;
+
+ cpu = PCPU_GET(cpuid);
+ if (atomic_cmpset_acq_int(&nmi_kdb_lock, 0, 1)) {
+ ret = nmi_call_kdb(cpu, type, frame, do_panic);
+ call_post = false;
+ } else {
+ ret = true;
+ savectx(&stoppcbs[cpu]);
+ CPU_SET_ATOMIC(cpu, &stopped_cpus);
+ while (!atomic_cmpset_acq_int(&nmi_kdb_lock, 0, 1))
+ ia32_pause();
+ call_post = true;
+ }
+ atomic_store_rel_int(&nmi_kdb_lock, 0);
+ if (call_post)
+ cpustop_handler_post(cpu);
+ return (ret);
+}
+#endif
+
/*
* Handle an IPI_STOP by saving our current context and spinning until we
* are resumed.
@@ -1231,6 +1261,13 @@
while (!CPU_ISSET(cpu, &started_cpus))
ia32_pause();
+ cpustop_handler_post(cpu);
+}
+
+static void
+cpustop_handler_post(u_int cpu)
+{
+
CPU_CLR_ATOMIC(cpu, &started_cpus);
CPU_CLR_ATOMIC(cpu, &stopped_cpus);

File Metadata

Mime Type
text/plain
Expires
Wed, Dec 25, 10:06 PM (11 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15598939
Default Alt Text
D8249.id21656.diff (10 KB)

Event Timeline