diff options
| -rw-r--r-- | sys/mips/include/kdb.h | 2 | ||||
| -rw-r--r-- | sys/mips/include/smp.h | 4 | ||||
| -rw-r--r-- | sys/mips/mips/db_trace.c | 12 | ||||
| -rw-r--r-- | sys/mips/mips/mp_machdep.c | 14 | ||||
| -rw-r--r-- | sys/mips/mips/swtch.S | 8 |
5 files changed, 35 insertions, 5 deletions
diff --git a/sys/mips/include/kdb.h b/sys/mips/include/kdb.h index cd8c61858556..6ca665413e89 100644 --- a/sys/mips/include/kdb.h +++ b/sys/mips/include/kdb.h @@ -32,6 +32,8 @@ #include <machine/frame.h> +#define KDB_STOPPEDPCB(pc) &stoppcbs[pc->pc_cpuid] + static __inline void kdb_cpu_clear_singlestep(void) { diff --git a/sys/mips/include/smp.h b/sys/mips/include/smp.h index 346c863437eb..1cb0596bde90 100644 --- a/sys/mips/include/smp.h +++ b/sys/mips/include/smp.h @@ -17,6 +17,8 @@ #ifdef _KERNEL +#include <machine/pcb.h> + /* * Interprocessor interrupts for SMP. */ @@ -31,6 +33,8 @@ void ipi_selected(cpumask_t cpus, int ipi); void smp_init_secondary(u_int32_t cpuid); void mpentry(void); +extern struct pcb stoppcbs[]; + #endif /* !LOCORE */ #endif /* _KERNEL */ diff --git a/sys/mips/mips/db_trace.c b/sys/mips/mips/db_trace.c index 4eadc25a835a..af4e202e2e52 100644 --- a/sys/mips/mips/db_trace.c +++ b/sys/mips/mips/db_trace.c @@ -169,6 +169,12 @@ loop: subr = (uintptr_t)MipsKernTLBInvalidException; else if (pcBetween(MipsUserTLBInvalidException, MipsTLBMissException)) subr = (uintptr_t)MipsUserTLBInvalidException; + else if (pcBetween(fork_trampoline, savectx)) + subr = (uintptr_t)fork_trampoline; + else if (pcBetween(savectx, mips_cpu_throw)) + subr = (uintptr_t)savectx; + else if (pcBetween(mips_cpu_throw, cpu_switch)) + subr = (uintptr_t)cpu_throw; else if (pcBetween(cpu_switch, MipsSwitchFPState)) subr = (uintptr_t)cpu_switch; else if (pcBetween(_locore, _locoreEnd)) { @@ -412,10 +418,8 @@ db_trace_thread(struct thread *thr, int count) : "=r" (pc) : "r" (ra)); - } - - else { - ctx = thr->td_pcb; + } else { + ctx = kdb_thr_ctx(thr); sp = (register_t)ctx->pcb_context[PREG_SP]; pc = (register_t)ctx->pcb_context[PREG_PC]; ra = (register_t)ctx->pcb_context[PREG_RA]; diff --git a/sys/mips/mips/mp_machdep.c b/sys/mips/mips/mp_machdep.c index d8520ccfa5cb..8069826e9b95 100644 --- a/sys/mips/mips/mp_machdep.c +++ b/sys/mips/mips/mp_machdep.c @@ -50,6 +50,8 @@ __FBSDID("$FreeBSD$"); #include <machine/intr_machdep.h> #include <machine/cache.h> +struct pcb stoppcbs[MAXCPU]; + static void *dpcpu; static struct mtx ap_boot_mtx; @@ -88,10 +90,14 @@ ipi_selected(cpumask_t cpus, int ipi) static int mips_ipi_handler(void *arg) { + int cpu; cpumask_t cpumask; u_int ipi, ipi_bitmap; int bit; + cpu = PCPU_GET(cpuid); + cpumask = PCPU_GET(cpumask); + platform_ipi_clear(); /* quiesce the pending ipi interrupt */ ipi_bitmap = atomic_readandclear_int(PCPU_PTR(pending_ipis)); @@ -120,10 +126,16 @@ mips_ipi_handler(void *arg) * necessary to add it in the switch. */ CTR0(KTR_SMP, "IPI_STOP or IPI_STOP_HARD"); - cpumask = PCPU_GET(cpumask); + + savectx(&stoppcbs[cpu]); + + /* Indicate we are stopped */ atomic_set_int(&stopped_cpus, cpumask); + + /* Wait for restart */ while ((started_cpus & cpumask) == 0) cpu_spinwait(); + atomic_clear_int(&started_cpus, cpumask); atomic_clear_int(&stopped_cpus, cpumask); CTR0(KTR_SMP, "IPI_STOP (restart)"); diff --git a/sys/mips/mips/swtch.S b/sys/mips/mips/swtch.S index 124827610add..dd66ecec684b 100644 --- a/sys/mips/mips/swtch.S +++ b/sys/mips/mips/swtch.S @@ -245,6 +245,14 @@ LEAF(savectx) SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0) SAVE_U_PCB_CONTEXT(v0, PREG_SR, a0) SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0) + + move v0, ra /* save 'ra' before we trash it */ + jal 1f + nop +1: + SAVE_U_PCB_CONTEXT(ra, PREG_PC, a0) + move ra, v0 /* restore 'ra' before returning */ + /* * FREEBSD_DEVELOPERS_FIXME: * In case there are CPU-specific registers that need |
