summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/amd64/mp_machdep.c59
-rw-r--r--sys/amd64/amd64/trap.c6
-rw-r--r--sys/amd64/conf/NOTES2
-rw-r--r--sys/amd64/include/smp.h5
-rw-r--r--sys/conf/options.amd642
-rw-r--r--sys/conf/options.i3862
-rw-r--r--sys/conf/options.pc982
-rw-r--r--sys/i386/conf/NOTES2
-rw-r--r--sys/i386/i386/mp_machdep.c53
-rw-r--r--sys/i386/i386/trap.c6
-rw-r--r--sys/i386/include/smp.h5
-rw-r--r--sys/kern/subr_kdb.c43
-rw-r--r--sys/kern/subr_smp.c32
-rw-r--r--sys/pc98/conf/NOTES2
-rw-r--r--sys/sys/smp.h3
15 files changed, 115 insertions, 109 deletions
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c
index 286dae9..be4f878 100644
--- a/sys/amd64/amd64/mp_machdep.c
+++ b/sys/amd64/amd64/mp_machdep.c
@@ -28,7 +28,6 @@
__FBSDID("$FreeBSD$");
#include "opt_cpu.h"
-#include "opt_kdb.h"
#include "opt_kstack_pages.h"
#include "opt_mp_watchdog.h"
#include "opt_sched.h"
@@ -113,10 +112,30 @@ volatile int smp_tlb_wait;
extern inthand_t IDTVEC(fast_syscall), IDTVEC(fast_syscall32);
+#ifdef STOP_NMI
+volatile cpumask_t ipi_nmi_pending;
+
+static void ipi_nmi_selected(u_int32_t cpus);
+#endif
+
/*
* Local data and functions.
*/
+#ifdef STOP_NMI
+/*
+ * Provide an alternate method of stopping other CPUs. If another CPU has
+ * disabled interrupts the conventional STOP IPI will be blocked. This
+ * NMI-based stop should get through in that case.
+ */
+static int stop_cpus_with_nmi = 1;
+SYSCTL_INT(_debug, OID_AUTO, stop_cpus_with_nmi, CTLTYPE_INT | CTLFLAG_RW,
+ &stop_cpus_with_nmi, 0, "");
+TUNABLE_INT("debug.stop_cpus_with_nmi", &stop_cpus_with_nmi);
+#else
+#define stop_cpus_with_nmi 0
+#endif
+
static u_int logical_cpus;
/* used to hold the AP's until we are ready to release them */
@@ -199,11 +218,6 @@ mp_topology(void)
smp_topology = &mp_top;
}
-
-#ifdef KDB_STOP_NMI
-volatile cpumask_t ipi_nmi_pending;
-#endif
-
/*
* Calculate usable address in base memory for AP trampoline code.
*/
@@ -944,6 +958,12 @@ ipi_selected(u_int32_t cpus, u_int ipi)
ipi = IPI_BITMAP_VECTOR;
}
+#ifdef STOP_NMI
+ if (ipi == IPI_STOP && stop_cpus_with_nmi) {
+ ipi_nmi_selected(cpus);
+ return;
+ }
+#endif
CTR3(KTR_SMP, "%s: cpus: %x ipi: %x", __func__, cpus, ipi);
while ((cpu = ffs(cpus)) != 0) {
cpu--;
@@ -974,6 +994,10 @@ void
ipi_all(u_int ipi)
{
+ if (IPI_IS_BITMAPED(ipi) || (ipi == IPI_STOP && stop_cpus_with_nmi)) {
+ ipi_selected(all_cpus, ipi);
+ return;
+ }
CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
lapic_ipi_vectored(ipi, APIC_IPI_DEST_ALL);
}
@@ -985,6 +1009,10 @@ void
ipi_all_but_self(u_int ipi)
{
+ if (IPI_IS_BITMAPED(ipi) || (ipi == IPI_STOP && stop_cpus_with_nmi)) {
+ ipi_selected(PCPU_GET(other_cpus), ipi);
+ return;
+ }
CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
lapic_ipi_vectored(ipi, APIC_IPI_DEST_OTHERS);
}
@@ -996,11 +1024,15 @@ void
ipi_self(u_int ipi)
{
+ if (IPI_IS_BITMAPED(ipi) || (ipi == IPI_STOP && stop_cpus_with_nmi)) {
+ ipi_selected(PCPU_GET(cpumask), ipi);
+ return;
+ }
CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
lapic_ipi_vectored(ipi, APIC_IPI_DEST_SELF);
}
-#ifdef KDB_STOP_NMI
+#ifdef STOP_NMI
/*
* send NMI IPI to selected CPUs
*/
@@ -1040,8 +1072,9 @@ ipi_nmi_handler()
{
int cpu = PCPU_GET(cpuid);
int cpumask = PCPU_GET(cpumask);
+ void (*restartfunc)(void);
- if (!(atomic_load_acq_int(&ipi_nmi_pending) & cpumask))
+ if (!(ipi_nmi_pending & cpumask))
return 1;
atomic_clear_int(&ipi_nmi_pending, cpumask);
@@ -1052,19 +1085,21 @@ ipi_nmi_handler()
atomic_set_int(&stopped_cpus, cpumask);
/* Wait for restart */
- while (!(atomic_load_acq_int(&started_cpus) & cpumask))
+ while (!(started_cpus & cpumask))
ia32_pause();
atomic_clear_int(&started_cpus, cpumask);
atomic_clear_int(&stopped_cpus, cpumask);
- if (cpu == 0 && cpustop_restartfunc != NULL)
- cpustop_restartfunc();
+ restartfunc = (void (*)(void))atomic_readandclear_long(
+ (u_long *)&cpustop_restartfunc);
+ if (restartfunc != NULL)
+ restartfunc();
return 0;
}
-#endif /* KDB_STOP_NMI */
+#endif /* STOP_NMI */
/*
* This is called once the rest of the system is up and running and we're
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index ed74171..173ee2c 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -167,13 +167,13 @@ trap(frame)
PCPU_LAZY_INC(cnt.v_trap);
type = frame.tf_trapno;
-#ifdef KDB_STOP_NMI
- /* Handler for NMI IPIs used for debugging */
+#ifdef STOP_NMI
+ /* Handler for NMI IPIs used for stopping CPUs. */
if (type == T_NMI) {
if (ipi_nmi_handler() == 0)
goto out;
}
-#endif /* KDB_STOP_NMI */
+#endif /* STOP_NMI */
#ifdef KDB
if (kdb_active) {
diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES
index 8799252..4bf2e7c 100644
--- a/sys/amd64/conf/NOTES
+++ b/sys/amd64/conf/NOTES
@@ -39,7 +39,7 @@ options MP_WATCHDOG
#
# Debugging options.
#
-options KDB_STOP_NMI # Stop CPUS using NMI instead of IPI
+options STOP_NMI # Stop CPUS using NMI instead of IPI
diff --git a/sys/amd64/include/smp.h b/sys/amd64/include/smp.h
index 2c63dc9..ba967c6 100644
--- a/sys/amd64/include/smp.h
+++ b/sys/amd64/include/smp.h
@@ -63,9 +63,8 @@ void smp_masked_invlpg_range(u_int mask, vm_offset_t startva,
void smp_invltlb(void);
void smp_masked_invltlb(u_int mask);
-#ifdef KDB_STOP_NMI
-int ipi_nmi_handler(void);
-void ipi_nmi_selected(u_int32_t cpus);
+#ifdef STOP_NMI
+int ipi_nmi_handler(void);
#endif
#endif /* !LOCORE */
diff --git a/sys/conf/options.amd64 b/sys/conf/options.amd64
index fdbc8f8..7b115ef 100644
--- a/sys/conf/options.amd64
+++ b/sys/conf/options.amd64
@@ -57,4 +57,4 @@ PSM_DEBUG opt_psm.h
DEV_ATPIC opt_atpic.h
# Debugging
-KDB_STOP_NMI opt_kdb.h
+STOP_NMI opt_cpu.h
diff --git a/sys/conf/options.i386 b/sys/conf/options.i386
index 8ad0b8b..7dafd5e 100644
--- a/sys/conf/options.i386
+++ b/sys/conf/options.i386
@@ -161,5 +161,5 @@ DEV_NPX opt_npx.h
ASR_COMPAT opt_asr.h
# Debugging
-KDB_STOP_NMI opt_kdb.h
+STOP_NMI opt_cpu.h
NPX_DEBUG opt_npx.h
diff --git a/sys/conf/options.pc98 b/sys/conf/options.pc98
index f50c867..a1f3cc1 100644
--- a/sys/conf/options.pc98
+++ b/sys/conf/options.pc98
@@ -103,5 +103,5 @@ DEV_MECIA opt_mecia.h
DEV_NPX opt_npx.h
# Debugging
-KDB_STOP_NMI opt_kdb.h
+STOP_NMI opt_cpu.h
NPX_DEBUG opt_npx.h
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 4a3a5b4..9cbbab5 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -56,7 +56,7 @@ options MP_WATCHDOG
# Debugging options.
#
-options KDB_STOP_NMI # Stop CPUS using NMI instead of IPI
+options STOP_NMI # Stop CPUS using NMI instead of IPI
diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c
index 90ded0c..bfc3c5b 100644
--- a/sys/i386/i386/mp_machdep.c
+++ b/sys/i386/i386/mp_machdep.c
@@ -28,7 +28,6 @@ __FBSDID("$FreeBSD$");
#include "opt_apic.h"
#include "opt_cpu.h"
-#include "opt_kdb.h"
#include "opt_kstack_pages.h"
#include "opt_mp_watchdog.h"
#include "opt_sched.h"
@@ -177,8 +176,10 @@ vm_offset_t smp_tlb_addr1;
vm_offset_t smp_tlb_addr2;
volatile int smp_tlb_wait;
-#ifdef KDB_STOP_NMI
+#ifdef STOP_NMI
volatile cpumask_t ipi_nmi_pending;
+
+static void ipi_nmi_selected(u_int32_t cpus);
#endif
#ifdef COUNT_IPIS
@@ -198,6 +199,20 @@ u_long *ipi_lazypmap_counts[MAXCPU];
* Local data and functions.
*/
+#ifdef STOP_NMI
+/*
+ * Provide an alternate method of stopping other CPUs. If another CPU has
+ * disabled interrupts the conventional STOP IPI will be blocked. This
+ * NMI-based stop should get through in that case.
+ */
+static int stop_cpus_with_nmi = 1;
+SYSCTL_INT(_debug, OID_AUTO, stop_cpus_with_nmi, CTLTYPE_INT | CTLFLAG_RW,
+ &stop_cpus_with_nmi, 0, "");
+TUNABLE_INT("debug.stop_cpus_with_nmi", &stop_cpus_with_nmi);
+#else
+#define stop_cpus_with_nmi 0
+#endif
+
static u_int logical_cpus;
/* used to hold the AP's until we are ready to release them */
@@ -1182,6 +1197,12 @@ ipi_selected(u_int32_t cpus, u_int ipi)
ipi = IPI_BITMAP_VECTOR;
}
+#ifdef STOP_NMI
+ if (ipi == IPI_STOP && stop_cpus_with_nmi) {
+ ipi_nmi_selected(cpus);
+ return;
+ }
+#endif
CTR3(KTR_SMP, "%s: cpus: %x ipi: %x", __func__, cpus, ipi);
while ((cpu = ffs(cpus)) != 0) {
cpu--;
@@ -1212,6 +1233,10 @@ void
ipi_all(u_int ipi)
{
+ if (IPI_IS_BITMAPED(ipi) || (ipi == IPI_STOP && stop_cpus_with_nmi)) {
+ ipi_selected(all_cpus, ipi);
+ return;
+ }
CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
lapic_ipi_vectored(ipi, APIC_IPI_DEST_ALL);
}
@@ -1223,6 +1248,10 @@ void
ipi_all_but_self(u_int ipi)
{
+ if (IPI_IS_BITMAPED(ipi) || (ipi == IPI_STOP && stop_cpus_with_nmi)) {
+ ipi_selected(PCPU_GET(other_cpus), ipi);
+ return;
+ }
CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
lapic_ipi_vectored(ipi, APIC_IPI_DEST_OTHERS);
}
@@ -1234,11 +1263,15 @@ void
ipi_self(u_int ipi)
{
+ if (IPI_IS_BITMAPED(ipi) || (ipi == IPI_STOP && stop_cpus_with_nmi)) {
+ ipi_selected(PCPU_GET(cpumask), ipi);
+ return;
+ }
CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
lapic_ipi_vectored(ipi, APIC_IPI_DEST_SELF);
}
-#ifdef KDB_STOP_NMI
+#ifdef STOP_NMI
/*
* send NMI IPI to selected CPUs
*/
@@ -1273,14 +1306,14 @@ ipi_nmi_selected(u_int32_t cpus)
}
}
-
int
ipi_nmi_handler()
{
int cpu = PCPU_GET(cpuid);
int cpumask = PCPU_GET(cpumask);
+ void (*restartfunc)(void);
- if (!(atomic_load_acq_int(&ipi_nmi_pending) & cpumask))
+ if (!(ipi_nmi_pending & cpumask))
return 1;
atomic_clear_int(&ipi_nmi_pending, cpumask);
@@ -1291,19 +1324,21 @@ ipi_nmi_handler()
atomic_set_int(&stopped_cpus, cpumask);
/* Wait for restart */
- while (!(atomic_load_acq_int(&started_cpus) & cpumask))
+ while (!(started_cpus & cpumask))
ia32_pause();
atomic_clear_int(&started_cpus, cpumask);
atomic_clear_int(&stopped_cpus, cpumask);
- if (cpu == 0 && cpustop_restartfunc != NULL)
- cpustop_restartfunc();
+ restartfunc = (void (*)(void))atomic_readandclear_int(
+ (u_int *)&cpustop_restartfunc);
+ if (restartfunc != NULL)
+ restartfunc();
return 0;
}
-#endif /* KDB_STOP_NMI */
+#endif /* STOP_NMI */
/*
* This is called once the rest of the system is up and running and we're
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 4703537..4c1df2a 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -185,13 +185,13 @@ trap(frame)
PCPU_LAZY_INC(cnt.v_trap);
type = frame.tf_trapno;
-#ifdef KDB_STOP_NMI
- /* Handler for NMI IPIs used for debugging */
+#ifdef STOP_NMI
+ /* Handler for NMI IPIs used for stopping CPUs. */
if (type == T_NMI) {
if (ipi_nmi_handler() == 0)
goto out;
}
-#endif /* KDB_STOP_NMI */
+#endif /* STOP_NMI */
#ifdef KDB
if (kdb_active) {
diff --git a/sys/i386/include/smp.h b/sys/i386/include/smp.h
index 4c9ae76..d2482fe 100644
--- a/sys/i386/include/smp.h
+++ b/sys/i386/include/smp.h
@@ -79,9 +79,8 @@ void smp_masked_invlpg_range(u_int mask, vm_offset_t startva,
void smp_invltlb(void);
void smp_masked_invltlb(u_int mask);
-#ifdef KDB_STOP_NMI
-int ipi_nmi_handler(void);
-void ipi_nmi_selected(u_int32_t cpus);
+#ifdef STOP_NMI
+int ipi_nmi_handler(void);
#endif
#endif /* !LOCORE */
diff --git a/sys/kern/subr_kdb.c b/sys/kern/subr_kdb.c
index c4f14d8..3157578 100644
--- a/sys/kern/subr_kdb.c
+++ b/sys/kern/subr_kdb.c
@@ -42,16 +42,11 @@ __FBSDID("$FreeBSD$");
#include <machine/kdb.h>
#include <machine/pcb.h>
-#ifdef KDB_STOP_NMI
+#ifdef SMP
+#if defined (__i386__) || defined(__amd64__)
+#define HAVE_STOPPEDPCBS
#include <machine/smp.h>
#endif
-
-/*
- * KDB_STOP_NMI requires SMP to pick up the right dependencies
- * (And isn't useful on UP anyway)
- */
-#if defined(KDB_STOP_NMI) && !defined(SMP)
-#error "options KDB_STOP_NMI" requires "options SMP"
#endif
int kdb_active = 0;
@@ -91,19 +86,6 @@ static int kdb_stop_cpus = 1;
SYSCTL_INT(_debug_kdb, OID_AUTO, stop_cpus, CTLTYPE_INT | CTLFLAG_RW,
&kdb_stop_cpus, 0, "");
TUNABLE_INT("debug.kdb.stop_cpus", &kdb_stop_cpus);
-
-#ifdef KDB_STOP_NMI
-/*
- * Provide an alternate method of stopping other CPUs. If another CPU has
- * disabled interrupts the conventional STOP IPI will be blocked. This
- * NMI-based stop should get through in that case.
- */
-static int kdb_stop_cpus_with_nmi = 1;
-SYSCTL_INT(_debug_kdb, OID_AUTO, stop_cpus_with_nmi, CTLTYPE_INT | CTLFLAG_RW,
- &kdb_stop_cpus_with_nmi, 0, "");
-TUNABLE_INT("debug.kdb.stop_cpus_with_nmi", &kdb_stop_cpus_with_nmi);
-#endif /* KDB_STOP_NMI */
-
#endif
static int
@@ -335,26 +317,24 @@ kdb_reenter(void)
struct pcb *
kdb_thr_ctx(struct thread *thr)
-#ifdef KDB_STOP_NMI
{
+#ifdef HAVE_STOPPEDPCBS
struct pcpu *pc;
u_int cpuid;
+#endif
if (thr == curthread)
return (&kdb_pcb);
+#ifdef HAVE_STOPPEDPCBS
SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
cpuid = pc->pc_cpuid;
- if (pc->pc_curthread == thr && (atomic_load_acq_int(&stopped_cpus) & (1 << cpuid)))
+ if (pc->pc_curthread == thr && (stopped_cpus & (1 << cpuid)))
return (&stoppcbs[cpuid]);
}
+#endif
return (thr->td_pcb);
}
-#else
-{
- return ((thr == curthread) ? &kdb_pcb : thr->td_pcb);
-}
-#endif /* KDB_STOP_NMI */
struct thread *
kdb_thr_first(void)
@@ -451,14 +431,7 @@ kdb_trap(int type, int code, struct trapframe *tf)
#ifdef SMP
if ((did_stop_cpus = kdb_stop_cpus) != 0)
- {
-#ifdef KDB_STOP_NMI
- if(kdb_stop_cpus_with_nmi)
- stop_cpus_nmi(PCPU_GET(other_cpus));
- else
-#endif /* KDB_STOP_NMI */
stop_cpus(PCPU_GET(other_cpus));
- }
#endif
kdb_frame = tf;
diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c
index 6b11b47..f0c0994 100644
--- a/sys/kern/subr_smp.c
+++ b/sys/kern/subr_smp.c
@@ -35,8 +35,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_kdb.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -256,36 +254,6 @@ stop_cpus(cpumask_t map)
return 1;
}
-#ifdef KDB_STOP_NMI
-int
-stop_cpus_nmi(cpumask_t map)
-{
- int i;
-
- if (!smp_started)
- return 0;
-
- CTR1(KTR_SMP, "stop_cpus(%x)", map);
-
- /* send the stop IPI to all CPUs in map */
- ipi_nmi_selected(map);
-
- i = 0;
- while ((atomic_load_acq_int(&stopped_cpus) & map) != map) {
- /* spin */
- i++;
-#ifdef DIAGNOSTIC
- if (i == 100000) {
- printf("timeout stopping cpus\n");
- break;
- }
-#endif
- }
-
- return 1;
-}
-#endif /* KDB_STOP_NMI */
-
/*
* Called by a CPU to restart stopped CPUs.
*
diff --git a/sys/pc98/conf/NOTES b/sys/pc98/conf/NOTES
index af8d271..6e410f6 100644
--- a/sys/pc98/conf/NOTES
+++ b/sys/pc98/conf/NOTES
@@ -39,7 +39,7 @@ options MP_WATCHDOG
# Debugging options.
#
-options KDB_STOP_NMI # Stop CPUS using NMI instead of IPI
+options STOP_NMI # Stop CPUS using NMI instead of IPI
diff --git a/sys/sys/smp.h b/sys/sys/smp.h
index 88c6ae2..f2b2f52 100644
--- a/sys/sys/smp.h
+++ b/sys/sys/smp.h
@@ -102,9 +102,6 @@ int stop_cpus(cpumask_t);
void smp_rendezvous_action(void);
extern struct mtx smp_ipi_mtx;
-#ifdef KDB_STOP_NMI
-int stop_cpus_nmi(cpumask_t);
-#endif
#endif /* SMP */
void smp_rendezvous(void (*)(void *),
void (*)(void *),
OpenPOWER on IntegriCloud