? sys/i386/conf/OARC-SMP
Index: sys/i386/i386/mp_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/i386/i386/mp_machdep.c,v
retrieving revision 1.235.2.6
diff -u -r1.235.2.6 mp_machdep.c
--- sys/i386/i386/mp_machdep.c	14 Feb 2005 10:42:22 -0000	1.235.2.6
+++ sys/i386/i386/mp_machdep.c	16 Apr 2005 18:49:41 -0000
@@ -1241,6 +1241,82 @@
 	lapic_ipi_vectored(ipi, APIC_IPI_DEST_SELF);
 }
 
+
+
+volatile cpumask_t ipi_nmi_pending;
+
+/*
+ * send NMI IPI to selected CPUs
+ */
+
+#define	BEFORE_SPIN	1000000
+
+void
+ipi_nmi_selected(u_int32_t cpus)
+{
+
+	int cpu;
+	register_t icrlo;
+
+	icrlo = APIC_DELMODE_NMI | APIC_DESTMODE_PHY | APIC_LEVEL_ASSERT 
+		| APIC_TRIGMOD_EDGE; 
+	
+	CTR2(KTR_SMP, "%s: cpus: %x nmi", __func__, cpus);
+
+
+	atomic_set_int(&ipi_nmi_pending, cpus);
+
+
+	while ((cpu = ffs(cpus)) != 0) {
+		cpu--;
+		cpus &= ~(1 << cpu);
+
+		KASSERT(cpu_apic_ids[cpu] != -1,
+		    ("IPI NMI to non-existent CPU %d", cpu));
+		
+		/* Wait for an earlier IPI to finish. */
+		if (!lapic_ipi_wait(BEFORE_SPIN))
+			panic("APIC: Previous IPI is stuck");
+
+		lapic_ipi_raw(icrlo,cpu_apic_ids[cpu]);
+	}
+}
+
+
+int
+ipi_nmi_handler()
+{
+	int cpu  = PCPU_GET(cpuid);
+
+	if(!(atomic_load_acq_int(&ipi_nmi_pending) & (1 << cpu)))
+		return 1;
+
+	atomic_clear_int(&ipi_nmi_pending,1 << cpu);
+
+	savectx(&stoppcbs[cpu]);
+
+	/* Indicate that we are stopped */
+	atomic_set_int(&stopped_cpus,1 << cpu);
+
+
+	/* Wait for restart */
+	while(!(atomic_load_acq_int(&started_cpus) & (1 << cpu)))
+	    ia32_pause();
+
+	atomic_clear_int(&started_cpus,1 << cpu);
+	atomic_clear_int(&stopped_cpus,1 << cpu);
+
+	if(cpu == 0 && cpustop_restartfunc != NULL)
+		cpustop_restartfunc();
+
+	return 0;
+}
+     
+
+		
+
+
+
 /*
  * This is called once the rest of the system is up and running and we're
  * ready to let the AP's out of the pen.
Index: sys/i386/i386/trap.c
===================================================================
RCS file: /cvsroot/src/sys/i386/i386/trap.c,v
retrieving revision 1.267.2.2
diff -u -r1.267.2.2 trap.c
--- sys/i386/i386/trap.c	3 Sep 2004 06:40:25 -0000	1.267.2.2
+++ sys/i386/i386/trap.c	16 Apr 2005 18:49:41 -0000
@@ -186,6 +186,12 @@
 	atomic_add_int(&cnt.v_trap, 1);
 	type = frame.tf_trapno;
 
+	/* Handler for NMI IPIs used for debugging */
+	if (type == T_NMI) {
+	         if (ipi_nmi_handler() == 0)
+	                   goto out;
+	}
+
 #ifdef KDB
 	if (kdb_active) {
 		kdb_reenter();
Index: sys/i386/include/smp.h
===================================================================
RCS file: /cvsroot/src/sys/i386/include/smp.h,v
retrieving revision 1.78.2.2
diff -u -r1.78.2.2 smp.h
--- sys/i386/include/smp.h	31 Jan 2005 23:26:04 -0000	1.78.2.2
+++ sys/i386/include/smp.h	16 Apr 2005 18:49:42 -0000
@@ -81,6 +81,9 @@
 void	smp_invltlb(void);
 void	smp_masked_invltlb(u_int mask);
 
+int ipi_nmi_handler(void);
+void ipi_nmi_selected(u_int32_t cpus);
+
 #endif /* !LOCORE */
 #endif /* SMP */
 
Index: sys/kern/subr_kdb.c
===================================================================
RCS file: /cvsroot/src/sys/kern/subr_kdb.c,v
retrieving revision 1.5.2.2
diff -u -r1.5.2.2 subr_kdb.c
--- sys/kern/subr_kdb.c	31 Jan 2005 23:26:17 -0000	1.5.2.2
+++ sys/kern/subr_kdb.c	16 Apr 2005 18:49:42 -0000
@@ -77,6 +77,12 @@
 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);
+
+static int kdb_stop_cpus_with_nmi = 0;
+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
 
 static int
@@ -300,15 +306,37 @@
 	/* NOTREACHED */
 }
 
+#ifdef SMP
+#include <machine/smp.h>
+#endif
+
 /*
  * Thread related support functions.
  */
 
 struct pcb *
 kdb_thr_ctx(struct thread *thr)
+#ifdef SMP
+{  
+  u_int		cpuid;
+  struct pcpu *pc;
+  
+  if (thr == curthread) 
+    return &kdb_pcb;
+
+  SLIST_FOREACH(pc, &cpuhead, pc_allcpu)  {
+    cpuid = pc->pc_cpuid;
+    if (pc->pc_curthread == thr && (atomic_load_acq_int(&stopped_cpus) & (1 << cpuid)))
+      return &stoppcbs[cpuid];
+  }
+
+  return  thr->td_pcb;
+}
+#else
 {
 	return ((thr == curthread) ? &kdb_pcb : thr->td_pcb);
 }
+#endif
 
 struct thread *
 kdb_thr_first(void)
@@ -409,7 +437,12 @@
 
 #ifdef SMP
 	if ((did_stop_cpus = kdb_stop_cpus) != 0)
+	  {
+	    if(kdb_stop_cpus_with_nmi)
+	      stop_cpus_nmi(PCPU_GET(other_cpus));
+	    else
 		stop_cpus(PCPU_GET(other_cpus));
+	  }
 #endif
 
 	/* Let MD code do its thing first... */
Index: sys/kern/subr_smp.c
===================================================================
RCS file: /cvsroot/src/sys/kern/subr_smp.c,v
retrieving revision 1.188.2.4
diff -u -r1.188.2.4 subr_smp.c
--- sys/kern/subr_smp.c	14 Feb 2005 10:42:23 -0000	1.188.2.4
+++ sys/kern/subr_smp.c	16 Apr 2005 18:49:43 -0000
@@ -254,6 +254,34 @@
 	return 1;
 }
 
+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;
+}
+
 
 /*
  * Called by a CPU to restart stopped CPUs. 
Index: sys/sys/smp.h
===================================================================
RCS file: /cvsroot/src/sys/sys/smp.h,v
retrieving revision 1.77.2.4
diff -u -r1.77.2.4 smp.h
--- sys/sys/smp.h	14 Feb 2005 10:42:23 -0000	1.77.2.4
+++ sys/sys/smp.h	16 Apr 2005 18:49:47 -0000
@@ -99,6 +99,7 @@
 void	forward_roundrobin(void);
 int	restart_cpus(cpumask_t);
 int	stop_cpus(cpumask_t);
+int	stop_cpus_nmi(cpumask_t);
 void	smp_rendezvous_action(void);
 extern	struct mtx smp_ipi_mtx;
 #endif /* SMP */
