aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/mips/include/kdb.h2
-rw-r--r--sys/mips/include/smp.h4
-rw-r--r--sys/mips/mips/db_trace.c12
-rw-r--r--sys/mips/mips/mp_machdep.c14
-rw-r--r--sys/mips/mips/swtch.S8
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