more SMP work:

make IPI's work.  modify boot_secondary_processors() to clear the startup flag
in each cpu.  new raise_ipi_wait_and_unlock() that calls raise_ipi(), waits
for the cpu to acknowledge it got the message, and then unlocks the msglock.
use the new framework in mp_{pause,resume}_cpus().  nmi_soft() takes a
`struct trapframe *', to be used by ddb.
This commit is contained in:
mrg 2001-06-07 17:59:47 +00:00
parent ba991d978b
commit d3b1cc167d
3 changed files with 69 additions and 36 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.c,v 1.118 2001/05/26 21:27:14 chs Exp $ */
/* $NetBSD: cpu.c,v 1.119 2001/06/07 17:59:47 mrg Exp $ */
/*
* Copyright (c) 1996
@ -52,12 +52,14 @@
*/
#include "opt_multiprocessor.h"
#include "opt_lockdebug.h"
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/lock.h>
#include <uvm/uvm.h>
@ -104,7 +106,6 @@ struct cfattach cpu_ca = {
static char *fsrtoname __P((int, int, int));
void cache_print __P((struct cpu_softc *));
void cpu_setup __P((struct cpu_softc *));
void cpu_spinup __P((struct cpu_softc *));
void fpu_init __P((struct cpu_info *));
#define IU_IMPL(psr) ((u_int)(psr) >> 28)
@ -114,9 +115,11 @@ void fpu_init __P((struct cpu_info *));
#define SRMMU_VERS(mmusr) (((mmusr) >> 24) & 0xf)
#if defined(MULTIPROCESSOR)
void cpu_spinup __P((struct cpu_softc *));
struct cpu_info *alloc_cpuinfo_global_va __P((int, vsize_t *));
struct cpu_info *alloc_cpuinfo __P((void));
struct cpu_info *
alloc_cpuinfo_global_va(ismaster, sizep)
int ismaster;
@ -203,6 +206,7 @@ alloc_cpuinfo()
pmap_update();
bzero((void *)cpi, sz);
cpi->flags = CPUFLG_STARTUP;
cpi->eintstack = (void *)((vaddr_t)cpi + sz);
cpi->idle_u = (void *)((vaddr_t)cpi + sz - INT_STACK_SIZE - USPACE);
@ -398,19 +402,31 @@ static struct cpu_softc *bootcpu;
void
cpu_boot_secondary_processors()
{
/*
* XXX This is currently a noop; the CPUs are already running, but
* XXX aren't doing anything. Eventually, this will release a
* XXX semaphore that all those secondary processors are anxiously
* XXX waiting on.
*/
int n;
if (cpu_instance != ncpu) {
printf("NOTICE: only %d out of %d CPUs were configured\n",
cpu_instance, ncpu);
return;
}
if (cpus == NULL)
return;
/* Tell the other CPU's to start up. */
printf("cpu0: booting secondary processors:");
for (n = 0; n < ncpu; n++) {
struct cpu_info *cpi = cpus[n];
if (cpi == NULL || cpuinfo.mid == cpi->mid)
continue;
printf(" cpu%d", cpi->ci_cpuid);
/* tell it to continue */
//cpi->flags &= ~CPUFLG_STARTUP;
}
printf("\n");
}
#endif /* MULTIPROCESSOR */
@ -444,6 +460,7 @@ cpu_setup(sc)
#endif
}
#if defined(MULTIPROCESSOR)
/*
* Allocate per-CPU data, then start up this CPU using PROM.
*/
@ -451,7 +468,6 @@ void
cpu_spinup(sc)
struct cpu_softc *sc;
{
#if defined(MULTIPROCESSOR)
struct cpu_info *cpi = sc->sc_cpuinfo;
int n;
extern void cpu_hatch __P((void)); /* in locore.s */
@ -491,13 +507,31 @@ extern void cpu_hatch __P((void)); /* in locore.s */
delay(100);
}
printf("CPU did not spin up\n");
#endif
}
void
raise_ipi_wait_and_unlock(cpi)
struct cpu_info *cpi;
{
int i;
raise_ipi(cpi);
i = 0;
while ((cpi->flags & CPUFLG_GOTMSG) == 0) {
if (i++ > 10000) {
printf("raise_ipi_wait_and_unlock(cpu%d): couldn't ping cpu%d\n",
cpuinfo.ci_cpuid, cpi->ci_cpuid);
break;
}
delay(1);
cpuinfo.cache_flush((caddr_t)&cpi->flags, sizeof(cpi->flags));
}
simple_unlock(&cpi->msg.lock);
}
void
mp_pause_cpus()
{
#if defined(MULTIPROCESSOR)
int n;
if (cpus == NULL)
@ -505,19 +539,20 @@ mp_pause_cpus()
for (n = 0; n < ncpu; n++) {
struct cpu_info *cpi = cpus[n];
if (cpi == NULL || cpuinfo.mid == cpi->mid)
continue;
simple_lock(&cpi->msg.lock);
cpi->msg.tag = XPMSG_PAUSECPU;
raise_ipi(cpi);
cpi->flags &= ~CPUFLG_GOTMSG;
raise_ipi_wait_and_unlock(cpi);
}
#endif
}
void
mp_resume_cpus()
{
#if defined(MULTIPROCESSOR)
int n;
if (cpus == NULL)
@ -525,15 +560,15 @@ mp_resume_cpus()
for (n = 0; n < ncpu; n++) {
struct cpu_info *cpi = cpus[n];
if (cpi == NULL || cpuinfo.mid == cpi->mid)
continue;
simple_lock(&cpi->msg.lock);
cpi->msg.tag = XPMSG_RESUMECPU;
raise_ipi(cpi);
/* tell it to continue */
cpi->flags &= ~CPUFLG_PAUSED;
}
#endif
}
#endif /* MULTIPROCESSOR */
/*
* fpu_init() must be run on associated CPU.

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpuvar.h,v 1.33 2001/06/03 04:03:29 mrg Exp $ */
/* $NetBSD: cpuvar.h,v 1.34 2001/06/07 17:59:48 mrg Exp $ */
/*
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@ -393,6 +393,9 @@ void getcpuinfo __P((struct cpu_info *sc, int node));
void mmu_install_tables __P((struct cpu_info *));
void pmap_alloc_cpu __P((struct cpu_info *));
void pmap_globalize_boot_cpu __P((struct cpu_info *));
#if defined(MULTIPROCESSOR)
void raise_ipi_wait_and_unlock __P((struct cpu_info *));
#endif
extern struct cpu_info **cpus;

View File

@ -1,4 +1,4 @@
/* $NetBSD: intr.c,v 1.50 2001/03/22 15:56:43 mrg Exp $ */
/* $NetBSD: intr.c,v 1.51 2001/06/07 17:59:48 mrg Exp $ */
/*
* Copyright (c) 1992, 1993
@ -159,7 +159,7 @@ soft01intr(fp)
#if defined(SUN4M)
void nmi_hard __P((void));
void nmi_soft __P((void));
void nmi_soft __P((struct trapframe *));
int (*memerr_handler) __P((void));
int (*sbuserr_handler) __P((void));
@ -198,7 +198,7 @@ nmi_hard()
* Examine pending system interrupts.
*/
si = *((u_int32_t *)ICR_SI_PEND);
printf("NMI: system interrupts: %s\n",
printf("cpu%d: NMI: system interrupts: %s\n", cpu_number(),
bitmask_snprintf(si, SINTR_BITS, bits, sizeof(bits)));
if ((si & SINTR_M) != 0) {
@ -227,28 +227,24 @@ nmi_hard()
}
void
nmi_soft()
nmi_soft(tf)
struct trapframe *tf;
{
#ifdef MULTIPROCESSOR
switch (cpuinfo.msg.tag) {
case XPMSG_SAVEFPU: {
savefpstate(cpuinfo.fpproc->p_md.md_fpstate);
cpuinfo.fpproc->p_md.md_fpumid = -1;
cpuinfo.fpproc = NULL;
}
break;
case XPMSG_PAUSECPU: {
cpuinfo.flags |= 0x4000;
while (cpuinfo.flags & 0x4000) {
simple_unlock(&cpuinfo.msg.lock);
delay(1);
simple_lock(&cpuinfo.msg.lock);
cpuinfo.flags |= CPUFLG_PAUSED|CPUFLG_GOTMSG;
while (cpuinfo.flags & CPUFLG_PAUSED)
cpuinfo.cache_flush((caddr_t)&cpuinfo.flags, sizeof(cpuinfo.flags));
return;
}
}
break;
case XPMSG_RESUMECPU: {
cpuinfo.flags &= ~0x4000;
}
break;
case XPMSG_VCACHE_FLUSH_PAGE: {
struct xpmsg_flush_page *p = &cpuinfo.msg.u.xpmsg_flush_page;
int ctx = getcontext();
@ -290,7 +286,6 @@ nmi_soft()
}
break;
}
simple_unlock(&cpuinfo.msg.lock);
#endif
}
#endif