? 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 +#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 */