From d3b1cc167d9328cc89b0ff568c8f91e121fa3dbc Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 7 Jun 2001 17:59:47 +0000 Subject: [PATCH] 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. --- sys/arch/sparc/sparc/cpu.c | 73 ++++++++++++++++++++++++++--------- sys/arch/sparc/sparc/cpuvar.h | 5 ++- sys/arch/sparc/sparc/intr.c | 27 ++++++------- 3 files changed, 69 insertions(+), 36 deletions(-) diff --git a/sys/arch/sparc/sparc/cpu.c b/sys/arch/sparc/sparc/cpu.c index cd9fde7a1089..110ed3bd4434 100644 --- a/sys/arch/sparc/sparc/cpu.c +++ b/sys/arch/sparc/sparc/cpu.c @@ -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 #include #include #include +#include #include @@ -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. diff --git a/sys/arch/sparc/sparc/cpuvar.h b/sys/arch/sparc/sparc/cpuvar.h index 9acbdffc69c8..f2db0d30d149 100644 --- a/sys/arch/sparc/sparc/cpuvar.h +++ b/sys/arch/sparc/sparc/cpuvar.h @@ -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; diff --git a/sys/arch/sparc/sparc/intr.c b/sys/arch/sparc/sparc/intr.c index 2aad7b2c6392..e86d31eea549 100644 --- a/sys/arch/sparc/sparc/intr.c +++ b/sys/arch/sparc/sparc/intr.c @@ -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