Module Name: src Committed By: snj Date: Fri Jan 28 07:16:14 UTC 2011
Modified Files: src/sys/arch/sparc/sparc [netbsd-5]: cpu.c cpuvar.h genassym.cf intr.c locore.s pmap.c Log Message: Pull up following revision(s) (requested by mrg in ticket #1532): sys/arch/sparc/sparc/cpu.c: revision 1.215 via patch sys/arch/sparc/sparc/cpuvar.h: revision 1.78 via patch sys/arch/sparc/sparc/genassym.cf: revision 1.57 via patch sys/arch/sparc/sparc/intr.c: revision 1.103-1.105 via patch sys/arch/sparc/sparc/locore.s: revision 1.247, 1.250 via patch sys/arch/sparc/sparc/pmap.c: revision 1.329 via patch - print the cpu_number() when we get a strayintr(). - use _MAXNCPU instead of 4 - convert xpmsg_lock from a simplelock to a kmutex - don't wait for sparc_noop IPI calls - remove xmpsg_func's "retval" parameter and usage - remove the IPI at high IPL message - rework cpu_attach() a bunch, refactoring calls to getcpuinfo() and setting of cpi, and split most of the non-boot CPU handling into a new function - make CPU_INFO_FOREACH() work whether modular or not - move the MP cpu_info pages earlier - move a few things in cpu.c around to colsolidate the MP code together - remove useless if (cpus == NULL) tests -- cpus is an array now with these changes, and an additional change to crazyintr() to not printf(), i can get to single user shell on my SS20 again. i can run a few commands but some of them cause hangs. "ps auxw" works, but "top -b" does not. convert sparc "intrcnt" counters to evcnt(9) style. XXX some of the names could be better, but i just copied them from the old intrnames in locore. i benchmarked this with a simple test of ircii ./configure && make, to see if the additional load/store & arith would cause any noticeable degradation as the change also converts 32 bit counters to 64 bits. amusingly, the only trend i saw in this was that for both portions, i see a consistent (across at least 8 runs) benefit of about 0.8% improvement. ie, the newer larger code size / counter size code actually runs faster for some reason.. maybe there's a cacheline effect in the size of the code? XXX the current implementation depends on a couple of things: XXX - ev_count member of evcnt{} is first and has offset 0 XXX - that sizeof(struct evcnt) equals 32 XXX if these are not true, locore.s has #error's to catch it - remove unused ft_want_ast() - give nmi_sun* ENTRY() points so they show up in symbols properly - add some disabled code to use this cpu's idlelwp area when hatching a cpu, but right now it makes this worse not better... To generate a diff of this commit: cvs rdiff -u -r1.211.8.2 -r1.211.8.3 src/sys/arch/sparc/sparc/cpu.c cvs rdiff -u -r1.75.10.2 -r1.75.10.3 src/sys/arch/sparc/sparc/cpuvar.h cvs rdiff -u -r1.56 -r1.56.4.1 src/sys/arch/sparc/sparc/genassym.cf cvs rdiff -u -r1.100.20.1 -r1.100.20.2 src/sys/arch/sparc/sparc/intr.c cvs rdiff -u -r1.244.8.2 -r1.244.8.3 src/sys/arch/sparc/sparc/locore.s cvs rdiff -u -r1.322.20.3 -r1.322.20.4 src/sys/arch/sparc/sparc/pmap.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/sparc/sparc/cpu.c diff -u src/sys/arch/sparc/sparc/cpu.c:1.211.8.2 src/sys/arch/sparc/sparc/cpu.c:1.211.8.3 --- src/sys/arch/sparc/sparc/cpu.c:1.211.8.2 Sun Jan 16 12:58:23 2011 +++ src/sys/arch/sparc/sparc/cpu.c Fri Jan 28 07:16:13 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.c,v 1.211.8.2 2011/01/16 12:58:23 bouyer Exp $ */ +/* $NetBSD: cpu.c,v 1.211.8.3 2011/01/28 07:16:13 snj Exp $ */ /* * Copyright (c) 1996 @@ -52,7 +52,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.211.8.2 2011/01/16 12:58:23 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.211.8.3 2011/01/28 07:16:13 snj Exp $"); #include "opt_multiprocessor.h" #include "opt_lockdebug.h" @@ -102,10 +102,7 @@ extern char machine_model[]; int sparc_ncpus; /* # of CPUs detected by PROM */ -#ifdef MULTIPROCESSOR -struct cpu_info *cpus[4]; /* we only support 4 CPUs. */ -u_int cpu_ready_mask; /* the set of CPUs marked as READY */ -#endif +struct cpu_info *cpus[_MAXNCPU]; /* we only support 4 CPUs. */ /* The CPU configuration driver. */ static void cpu_mainbus_attach(struct device *, struct device *, void *); @@ -136,43 +133,6 @@ #define SRMMU_VERS(mmusr) (((mmusr) >> 24) & 0xf) int bootmid; /* Module ID of boot CPU */ -#if defined(MULTIPROCESSOR) -void cpu_spinup(struct cpu_info *); -static void init_cpuinfo(struct cpu_info *, int); - -int go_smp_cpus = 0; /* non-primary CPUs wait for this to go */ - -/* lock this to send IPI's */ -struct simplelock xpmsg_lock = SIMPLELOCK_INITIALIZER; - -static void -init_cpuinfo(struct cpu_info *cpi, int node) -{ - vaddr_t intstack, va; - - /* - * Finish initialising this cpu_info. - */ - getcpuinfo(cpi, node); - - /* - * Arrange interrupt stack. This cpu will also abuse the bottom - * half of the interrupt stack before it gets to run its idle LWP. - */ - intstack = uvm_km_alloc(kernel_map, INT_STACK_SIZE, 0, UVM_KMF_WIRED); - if (intstack == 0) - panic("%s: no uspace/intstack", __func__); - cpi->eintstack = (void*)(intstack + INT_STACK_SIZE); - - /* Allocate virtual space for pmap page_copy/page_zero */ - va = uvm_km_alloc(kernel_map, 2*PAGE_SIZE, 0, UVM_KMF_VAONLY); - if (va == 0) - panic("%s: no virtual space", __func__); - - cpi->vpage[0] = (void *)(va + 0); - cpi->vpage[1] = (void *)(va + PAGE_SIZE); -} -#endif /* MULTIPROCESSOR */ #ifdef notdef /* @@ -199,6 +159,21 @@ }; #endif +#if defined(MULTIPROCESSOR) +u_int cpu_ready_mask; /* the set of CPUs marked as READY */ +void cpu_spinup(struct cpu_info *); +static void cpu_attach_non_boot(struct cpu_softc *, struct cpu_info *, int); + +int go_smp_cpus = 0; /* non-primary CPUs wait for this to go */ + +/* + * This must be locked around all message transactions to ensure only + * one CPU is generating them. + */ +static kmutex_t xpmsg_mutex; + +#endif /* MULTIPROCESSOR */ + /* * 4/110 comment: the 4/110 chops off the top 4 bits of an OBIO address. * this confuses autoconf. for example, if you try and map @@ -326,6 +301,7 @@ static void cpu_attach(struct cpu_softc *sc, int node, int mid) { + char buf[100]; struct cpu_info *cpi; int idx; static int cpu_attach_count = 0; @@ -335,69 +311,26 @@ * (see autoconf.c and cpuunit.c) */ idx = cpu_attach_count++; - if (cpu_attach_count == 1) { - getcpuinfo(&cpuinfo, node); - -#if defined(MULTIPROCESSOR) - cpi = sc->sc_cpuinfo = cpus[idx]; -#else - /* The `local' VA is global for uniprocessor. */ - cpi = sc->sc_cpuinfo = (struct cpu_info *)CPUINFO_VA; -#endif - cpi->master = 1; - cpi->eintstack = eintstack; - /* Note: `curpcb' is set to `proc0' in locore */ - - /* - * If we haven't been able to determine the Id of the - * boot CPU, set it now. In this case we can only boot - * from CPU #0 (see also the CPU attach code in autoconf.c) - */ - if (bootmid == 0) - bootmid = mid; - } else { -#if defined(MULTIPROCESSOR) - int error; - - /* - * Initialise this cpu's cpu_info. - */ - cpi = sc->sc_cpuinfo = cpus[idx]; - init_cpuinfo(cpi, node); - /* - * Call the MI attach which creates an idle LWP for us. - */ - error = mi_cpu_attach(cpi); - if (error != 0) { - aprint_normal("\n"); - aprint_error("%s: mi_cpu_attach failed with %d\n", - sc->sc_dev.dv_xname, error); - return; - } - - /* - * Note: `eintstack' is set in init_cpuinfo() above. - * The %wim register will be initialized in cpu_hatch(). - */ - cpi->ci_curlwp = cpi->ci_data.cpu_idlelwp; - cpi->curpcb = (struct pcb *)cpi->ci_curlwp->l_addr; - cpi->curpcb->pcb_wim = 1; - -#else - sc->sc_cpuinfo = NULL; +#if !defined(MULTIPROCESSOR) + if (cpu_attach_count > 1) { printf(": no SMP support in kernel\n"); return; -#endif } - -#ifdef DEBUG - cpi->redzone = (void *)((long)cpi->eintstack + REDSIZE); #endif + /* + * Initialise this cpu's cpu_info. + */ + cpi = sc->sc_cpuinfo = cpus[idx]; + getcpuinfo(cpi, node); + cpi->ci_cpuid = idx; cpi->mid = mid; cpi->node = node; +#ifdef DEBUG + cpi->redzone = (void *)((long)cpi->eintstack + REDSIZE); +#endif if (sparc_ncpus > 1) { printf(": mid %d", mid); @@ -405,24 +338,102 @@ printf(" [WARNING: mid should not be 0]"); } +#if defined(MULTIPROCESSOR) + if (cpu_attach_count > 1) { + cpu_attach_non_boot(sc, cpi, node); + return; + } +#endif /* MULTIPROCESSOR */ + + /* Stuff to only run on the boot CPU */ + cpu_setup(); + snprintf(buf, sizeof buf, "%s @ %s MHz, %s FPU", + cpi->cpu_name, clockfreq(cpi->hz), cpi->fpu_name); + snprintf(cpu_model, sizeof cpu_model, "%s (%s)", + machine_model, buf); + printf(": %s\n", buf); + cache_print(sc); + + cpi->master = 1; + cpi->eintstack = eintstack; + + /* + * If we haven't been able to determine the Id of the + * boot CPU, set it now. In this case we can only boot + * from CPU #0 (see also the CPU attach code in autoconf.c) + */ + if (bootmid == 0) + bootmid = mid; +} + +/* + * Finish CPU attach. + * Must be run by the CPU which is being attached. + */ +void +cpu_setup(void) +{ + if (cpuinfo.hotfix) + (*cpuinfo.hotfix)(&cpuinfo); + + /* Initialize FPU */ + fpu_init(&cpuinfo); + + /* Enable the cache */ + cpuinfo.cache_enable(); + + cpuinfo.flags |= CPUFLG_HATCHED; +} + +#if defined(MULTIPROCESSOR) +/* + * Perform most of the tasks needed for a non-boot CPU. + */ +static void +cpu_attach_non_boot(struct cpu_softc *sc, struct cpu_info *cpi, int node) +{ + vaddr_t intstack, va; + int error; + + /* + * Arrange interrupt stack. This cpu will also abuse the bottom + * half of the interrupt stack before it gets to run its idle LWP. + */ + intstack = uvm_km_alloc(kernel_map, INT_STACK_SIZE, 0, UVM_KMF_WIRED); + if (intstack == 0) + panic("%s: no uspace/intstack", __func__); + cpi->eintstack = (void*)(intstack + INT_STACK_SIZE); - if (cpi->master) { - char buf[100]; + /* Allocate virtual space for pmap page_copy/page_zero */ + va = uvm_km_alloc(kernel_map, 2*PAGE_SIZE, 0, UVM_KMF_VAONLY); + if (va == 0) + panic("%s: no virtual space", __func__); - cpu_setup(); - snprintf(buf, sizeof buf, "%s @ %s MHz, %s FPU", - cpi->cpu_name, clockfreq(cpi->hz), cpi->fpu_name); - snprintf(cpu_model, sizeof cpu_model, "%s (%s)", - machine_model, buf); - printf(": %s\n", buf); - cache_print(sc); + cpi->vpage[0] = (void *)(va + 0); + cpi->vpage[1] = (void *)(va + PAGE_SIZE); + + /* + * Call the MI attach which creates an idle LWP for us. + */ + error = mi_cpu_attach(cpi); + if (error != 0) { + aprint_normal("\n"); + aprint_error("%s: mi_cpu_attach failed with %d\n", + sc->sc_dev.dv_xname, error); return; } -#if defined(MULTIPROCESSOR) + /* + * Note: `eintstack' is set in init_cpuinfo() above. + * The %wim register will be initialized in cpu_hatch(). + */ + cpi->ci_curlwp = cpi->ci_data.cpu_idlelwp; + cpi->curpcb = (struct pcb *)cpi->ci_curlwp->l_addr; + cpi->curpcb->pcb_wim = 1; + /* for now use the fixed virtual addresses setup in autoconf.c */ cpi->intreg_4m = (struct icr_pi *) - (PI_INTR_VA + (_MAXNBPG * CPU_MID2CPUNO(mid))); + (PI_INTR_VA + (_MAXNBPG * CPU_MID2CPUNO(cpi->mid))); /* Now start this CPU */ cpu_spinup(cpi); @@ -431,7 +442,10 @@ cache_print(sc); - if (sparc_ncpus > 1 && idx == sparc_ncpus-1) { + /* + * Now we're on the last CPU to be attaching. + */ + if (sparc_ncpus > 1 && cpi->ci_cpuid == sparc_ncpus - 1) { CPU_INFO_ITERATOR n; /* * Install MP cache flush functions, unless the @@ -446,10 +460,9 @@ SET_CACHE_FUNC(vcache_flush_context); } } -#endif /* MULTIPROCESSOR */ +#undef SET_CACHE_FUNC } -#if defined(MULTIPROCESSOR) /* * Start secondary processors in motion. */ @@ -479,41 +492,30 @@ printf("\n"); } -#endif /* MULTIPROCESSOR */ /* - * Finish CPU attach. - * Must be run by the CPU which is being attached. + * Early initialisation, before main(). */ void -cpu_setup(void) +cpu_init_system(void) { - if (cpuinfo.hotfix) - (*cpuinfo.hotfix)(&cpuinfo); - - /* Initialize FPU */ - fpu_init(&cpuinfo); - /* Enable the cache */ - cpuinfo.cache_enable(); - - cpuinfo.flags |= CPUFLG_HATCHED; + mutex_init(&xpmsg_mutex, MUTEX_SPIN, IPL_VM); } -#if defined(MULTIPROCESSOR) - -extern void cpu_hatch(void); /* in locore.s */ - /* * Allocate per-CPU data, then start up this CPU using PROM. */ void cpu_spinup(struct cpu_info *cpi) { + extern void cpu_hatch(void); /* in locore.s */ struct openprom_addr oa; - void *pc = (void *)cpu_hatch; + void *pc; int n; + pc = (void *)cpu_hatch; + /* Setup CPU-specific MMU tables */ pmap_alloc_cpu(cpi); @@ -556,42 +558,20 @@ u_int cpuset) { struct cpu_info *cpi; - int s, n, i, done, callself, mybit; + int n, i, done, callself, mybit; volatile struct xpmsg_func *p; int fasttrap; - - /* XXX - note p->retval is probably no longer useful */ + int is_noop = func == (xcall_func_t)sparc_noop; mybit = (1 << cpuinfo.ci_cpuid); callself = func && (cpuset & mybit) != 0; cpuset &= ~mybit; - /* - * If no cpus are configured yet, just call ourselves. - */ - if (cpus == NULL) { - p = &cpuinfo.msg.u.xpmsg_func; - if (callself) - p->retval = (*func)(arg0, arg1, arg2); - return; - } - /* Mask any CPUs that are not ready */ cpuset &= cpu_ready_mask; /* prevent interrupts that grab the kernel lock */ - s = splsched(); -#ifdef DEBUG - if (!cold) { - u_int pc, lvl = ((u_int)s & PSR_PIL) >> 8; - if (lvl > IPL_SCHED) { - __asm("mov %%i7, %0" : "=r" (pc) : ); - printf_nolog("%d: xcall at lvl %u from 0x%x\n", - cpu_number(), lvl, pc); - } - } -#endif - LOCK_XPMSG(); + mutex_spin_enter(&xpmsg_mutex); /* * Firstly, call each CPU. We do this so that they might have @@ -621,14 +601,14 @@ */ p = &cpuinfo.msg.u.xpmsg_func; if (callself) - p->retval = (*func)(arg0, arg1, arg2); + (*func)(arg0, arg1, arg2); /* * Lastly, start looping, waiting for all CPUs to register that they * have completed (bailing if it takes "too long", being loud about * this in the process). */ - done = 0; + done = is_noop; i = 100000; /* time-out, not too long, but still an _AGE_ */ while (!done) { if (--i < 0) { @@ -654,8 +634,7 @@ if (i < 0) printf_nolog("\n"); - UNLOCK_XPMSG(); - splx(s); + mutex_spin_exit(&xpmsg_mutex); } /* @@ -667,9 +646,6 @@ CPU_INFO_ITERATOR n; struct cpu_info *cpi; - if (cpus == NULL) - return; - for (CPU_INFO_FOREACH(n, cpi)) { if (cpuinfo.mid == cpi->mid || (cpi->flags & CPUFLG_HATCHED) == 0) @@ -694,9 +670,6 @@ CPU_INFO_ITERATOR n; struct cpu_info *cpi; - if (cpus == NULL) - return; - for (CPU_INFO_FOREACH(n, cpi)) { if (cpuinfo.mid == cpi->mid || (cpi->flags & CPUFLG_HATCHED) == 0) @@ -720,9 +693,6 @@ CPU_INFO_ITERATOR n; struct cpu_info *cpi; - if (cpus == NULL) - return; - for (CPU_INFO_FOREACH(n, cpi)) { int r; @@ -747,9 +717,6 @@ CPU_INFO_ITERATOR n; struct cpu_info *cpi; - if (cpus == NULL) - return; - for (CPU_INFO_FOREACH(n, cpi)) { if (cpi == NULL || cpi->mid == cpuinfo.mid || (cpi->flags & CPUFLG_HATCHED) == 0) @@ -766,9 +733,6 @@ CPU_INFO_ITERATOR n; struct cpu_info *cpi; - if (cpus == NULL) - return; - for (CPU_INFO_FOREACH(n, cpi)) { if (cpi == NULL || cpuinfo.mid == cpi->mid || (cpi->flags & CPUFLG_PAUSED) == 0) Index: src/sys/arch/sparc/sparc/cpuvar.h diff -u src/sys/arch/sparc/sparc/cpuvar.h:1.75.10.2 src/sys/arch/sparc/sparc/cpuvar.h:1.75.10.3 --- src/sys/arch/sparc/sparc/cpuvar.h:1.75.10.2 Sun Jan 16 12:58:23 2011 +++ src/sys/arch/sparc/sparc/cpuvar.h Fri Jan 28 07:16:13 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: cpuvar.h,v 1.75.10.2 2011/01/16 12:58:23 bouyer Exp $ */ +/* $NetBSD: cpuvar.h,v 1.75.10.3 2011/01/28 07:16:13 snj Exp $ */ /* * Copyright (c) 1996 The NetBSD Foundation, Inc. @@ -37,6 +37,7 @@ #include "opt_lockdebug.h" #include "opt_ddb.h" #include "opt_sparc_arch.h" +#include "opt_modular.h" #endif #include <sys/device.h> @@ -104,12 +105,11 @@ * the trap window (see locore.s). */ struct xpmsg_func { - int (*func)(int, int, int); + void (*func)(int, int, int); void (*trap)(int, int, int); int arg0; int arg1; int arg2; - int retval; } xpmsg_func; } u; volatile int received; @@ -117,15 +117,6 @@ }; /* - * This must be locked around all message transactions to ensure only - * one CPU is generating them. - */ -extern struct simplelock xpmsg_lock; - -#define LOCK_XPMSG() simple_lock(&xpmsg_lock); -#define UNLOCK_XPMSG() simple_unlock(&xpmsg_lock); - -/* * The cpuinfo structure. This structure maintains information about one * currently installed CPU (there may be several of these if the machine * supports multiple CPUs, as on some Sun4m architectures). The information @@ -415,10 +406,16 @@ #define CPU_INFO_ITERATOR int -#ifdef MULTIPROCESSOR -#define CPU_INFO_FOREACH(cii, cp) cii = 0; cp = cpus[cii], cii < sparc_ncpus; cii++ +/* + * Provide two forms of CPU_INFO_FOREACH. One fast one for non-modular + * non-SMP kernels, and the other for everyone else. Both work in the + * non-SMP case, just involving an extra indirection through cpus[0] for + * the portable version. + */ +#if defined(MULTIPROCESSOR) || defined(MODULAR) || defined(_MODULE) +#define CPU_INFO_FOREACH(cii, cp) cii = 0; (cp = cpus[cii]) && cp->eintstack && cii < sparc_ncpus; cii++ #else -#define CPU_INFO_FOREACH(cii, cp) (void)cii, cp = curcpu(); cp != NULL; cp = NULL +#define CPU_INFO_FOREACH(cii, cp) (void)cii, cp = curcpu(); cp != NULL; cp = NULL #endif /* @@ -437,7 +434,8 @@ #define CPUSET_ALL 0xffffffffU /* xcall to all configured CPUs */ #if defined(MULTIPROCESSOR) -typedef int (*xcall_func_t)(int, int, int); +void cpu_init_system(void); +typedef void (*xcall_func_t)(int, int, int); typedef void (*xcall_trap_t)(int, int, int); void xcall(xcall_func_t, xcall_trap_t, int, int, int, u_int); /* Shorthand */ @@ -472,8 +470,8 @@ extern int bootmid; /* Module ID of boot CPU */ #define CPU_MID2CPUNO(mid) ((mid) != 0 ? (mid) - 8 : 0) -#ifdef MULTIPROCESSOR extern struct cpu_info *cpus[]; +#ifdef MULTIPROCESSOR extern u_int cpu_ready_mask; /* the set of CPUs marked as READY */ #endif Index: src/sys/arch/sparc/sparc/genassym.cf diff -u src/sys/arch/sparc/sparc/genassym.cf:1.56 src/sys/arch/sparc/sparc/genassym.cf:1.56.4.1 --- src/sys/arch/sparc/sparc/genassym.cf:1.56 Sat Sep 20 18:29:05 2008 +++ src/sys/arch/sparc/sparc/genassym.cf Fri Jan 28 07:16:13 2011 @@ -1,4 +1,4 @@ -# $NetBSD: genassym.cf,v 1.56 2008/09/20 18:29:05 tsutsui Exp $ +# $NetBSD: genassym.cf,v 1.56.4.1 2011/01/28 07:16:13 snj Exp $ # # Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -129,6 +129,7 @@ define V_SOFT offsetof(struct uvmexp, softs) define V_FAULTS offsetof(struct uvmexp, faults) define EV_COUNT offsetof(struct evcnt, ev_count) +define EV_STRUCTSIZE sizeof(struct evcnt) # CPU info structure define CPUINFO_STRUCTSIZE sizeof(struct cpu_info) Index: src/sys/arch/sparc/sparc/intr.c diff -u src/sys/arch/sparc/sparc/intr.c:1.100.20.1 src/sys/arch/sparc/sparc/intr.c:1.100.20.2 --- src/sys/arch/sparc/sparc/intr.c:1.100.20.1 Sat May 30 16:57:18 2009 +++ src/sys/arch/sparc/sparc/intr.c Fri Jan 28 07:16:13 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: intr.c,v 1.100.20.1 2009/05/30 16:57:18 snj Exp $ */ +/* $NetBSD: intr.c,v 1.100.20.2 2011/01/28 07:16:13 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.100.20.1 2009/05/30 16:57:18 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.100.20.2 2011/01/28 07:16:13 snj Exp $"); #include "opt_multiprocessor.h" #include "opt_sparc_arch.h" @@ -80,6 +80,39 @@ EVCNT_ATTACH_STATIC(lev14_evcnt); #endif +struct evcnt intrcnt[15] = { + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "spur", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev1", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev2", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev3", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev4", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev5", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev6", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev7", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev8", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev9", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "clock", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev11", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev12", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev13", "hard"), + EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "prof", "hard"), +}; + +EVCNT_ATTACH_STATIC2(intrcnt, 0); +EVCNT_ATTACH_STATIC2(intrcnt, 1); +EVCNT_ATTACH_STATIC2(intrcnt, 2); +EVCNT_ATTACH_STATIC2(intrcnt, 3); +EVCNT_ATTACH_STATIC2(intrcnt, 4); +EVCNT_ATTACH_STATIC2(intrcnt, 5); +EVCNT_ATTACH_STATIC2(intrcnt, 6); +EVCNT_ATTACH_STATIC2(intrcnt, 7); +EVCNT_ATTACH_STATIC2(intrcnt, 8); +EVCNT_ATTACH_STATIC2(intrcnt, 9); +EVCNT_ATTACH_STATIC2(intrcnt, 10); +EVCNT_ATTACH_STATIC2(intrcnt, 11); +EVCNT_ATTACH_STATIC2(intrcnt, 12); +EVCNT_ATTACH_STATIC2(intrcnt, 13); +EVCNT_ATTACH_STATIC2(intrcnt, 14); void strayintr(struct clockframe *); #ifdef DIAGNOSTIC @@ -98,9 +131,9 @@ char bits[64]; int timesince; - printf("stray interrupt ipl 0x%x pc=0x%x npc=0x%x psr=%s\n", - fp->ipl, fp->pc, fp->npc, bitmask_snprintf(fp->psr, - PSR_BITS, bits, sizeof(bits))); + printf("stray interrupt cpu%d ipl 0x%x pc=0x%x npc=0x%x psr=%s\n", + cpu_number(), fp->ipl, fp->pc, fp->npc, + bitmask_snprintf(fp->psr, PSR_BITS, bits, sizeof(bits))); timesince = time_uptime - straytime; if (timesince <= 10) { @@ -344,7 +377,7 @@ volatile struct xpmsg_func *p = &cpuinfo.msg.u.xpmsg_func; if (p->func) - p->retval = (*p->func)(p->arg0, p->arg1, p->arg2); + (*p->func)(p->arg0, p->arg1, p->arg2); break; } } Index: src/sys/arch/sparc/sparc/locore.s diff -u src/sys/arch/sparc/sparc/locore.s:1.244.8.2 src/sys/arch/sparc/sparc/locore.s:1.244.8.3 --- src/sys/arch/sparc/sparc/locore.s:1.244.8.2 Sun Jan 16 12:58:23 2011 +++ src/sys/arch/sparc/sparc/locore.s Fri Jan 28 07:16:13 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: locore.s,v 1.244.8.2 2011/01/16 12:58:23 bouyer Exp $ */ +/* $NetBSD: locore.s,v 1.244.8.3 2011/01/28 07:16:13 snj Exp $ */ /* * Copyright (c) 1996 Paul Kranenburg @@ -118,6 +118,15 @@ inc %o1; \ st %o1, [%o0 + %lo(what)] +#if EV_COUNT != 0 +# error "this code does not work with EV_COUNT != 0" +#endif +#if EV_STRUCTSIZE != 32 +# error "this code does not work with EV_STRUCTSIZE != 32" +#else +# define EV_STRUCTSHIFT 5 +#endif + /* * Another handy macro: load one register window, given `base' address. * This can be either a simple register (e.g., %sp) or include an initial @@ -2518,11 +2527,13 @@ wr %l4, PSR_ET, %psr ! song and dance is necessary std %l0, [%sp + CCFSZ + 0] ! set up intrframe/clockframe sll %l3, 2, %l5 - set _C_LABEL(intrcnt), %l4 ! intrcnt[intlev]++; - ld [%l4 + %l5], %o0 + set intrcnt, %l4 ! intrcnt[intlev].ev_count++; + sll %l3, EV_STRUCTSHIFT, %o2 + ldd [%l4 + %o2], %o0 std %l2, [%sp + CCFSZ + 8] - inc %o0 - st %o0, [%l4 + %l5] + inccc %o1 + addx %o0, 0, %o0 + std %o0, [%l4 + %o2] set _C_LABEL(sintrhand), %l4! %l4 = sintrhand[intlev]; ld [%l4 + %l5], %l4 @@ -2670,11 +2681,13 @@ wr %l4, PSR_ET, %psr ! song and dance is necessary std %l0, [%sp + CCFSZ + 0] ! set up intrframe/clockframe sll %l3, 2, %l5 - set _C_LABEL(intrcnt), %l4 ! intrcnt[intlev]++; - ld [%l4 + %l5], %o0 + set intrcnt, %l4 ! intrcnt[intlev].ev_count++; + sll %l3, EV_STRUCTSHIFT, %o2 + ldd [%l4 + %o2], %o0 std %l2, [%sp + CCFSZ + 8] ! set up intrframe/clockframe - inc %o0 - st %o0, [%l4 + %l5] + inccc %o1 + addx %o0, 0, %o0 + std %o0, [%l4 + %o2] st %fp, [%sp + CCFSZ + 16] @@ -2715,11 +2728,13 @@ wr %l4, PSR_ET, %psr ! song and dance is necessary std %l0, [%sp + CCFSZ + 0] ! set up intrframe/clockframe sll %l3, 2, %l5 - set _C_LABEL(intrcnt), %l4 ! intrcnt[intlev]++; - ld [%l4 + %l5], %o0 + set intrcnt, %l4 ! intrcnt[intlev].ev_count++; + sll %l3, EV_STRUCTSHIFT, %o2 + ldd [%l4 + %o2], %o0 std %l2, [%sp + CCFSZ + 8] ! set up intrframe/clockframe - inc %o0 - st %o0, [%l4 + %l5] + inccc %o1 + addx %o0, 0, %o0 + std %o0, [%l4 + %o2] set _C_LABEL(intrhand), %l4 ! %l4 = intrhand[intlev]; ld [%l4 + %l5], %l4 @@ -2973,17 +2988,6 @@ b ft_rett mov SRMMU_CXR, %l7 ! reload ctx register -_ENTRY(_C_LABEL(ft_want_ast)) - mov 1, %l4 ! ack xcall in all cases - st %l4, [%l6 + CPUINFO_XMSG_CMPLT] ! completed = 1 - - btst PSR_PS, %l0 ! if from user mode - be,a slowtrap ! call trap(T_AST) - mov T_AST, %l3 - - mov %l0, %psr ! else return from trap - nop ! AST will be noticed on out way out - RETT #endif /* MULTIPROCESSOR */ #ifdef notyet @@ -3026,7 +3030,7 @@ */ #if defined(SUN4) -nmi_sun4: +_ENTRY(_C_LABEL(nmi_sun4)) INTR_SETUP(-CCFSZ-80) INCR(_C_LABEL(uvmexp)+V_INTR) ! cnt.v_intr++; (clobbers %o0,%o1) /* @@ -3052,7 +3056,7 @@ #endif #if defined(SUN4C) -nmi_sun4c: +_ENTRY(_C_LABEL(nmi_sun4c)) INTR_SETUP(-CCFSZ-80) INCR(_C_LABEL(uvmexp)+V_INTR) ! cnt.v_intr++; (clobbers %o0,%o1) /* @@ -3086,7 +3090,7 @@ #endif /* SUN4M */ #endif /* SUN4C */ -nmi_common: +_ENTRY(_C_LABEL(nmi_common)) ! and call C code call _C_LABEL(memerr4_4c) ! memerr(0, ser, sva, aer, ava) clr %o0 @@ -3107,7 +3111,7 @@ wr %l4, 0, %y ! restore y #if defined(SUN4M) -nmi_sun4m: +_ENTRY(_C_LABEL(nmi_sun4m)) INTR_SETUP(-CCFSZ-80) INCR(_C_LABEL(uvmexp)+V_INTR) ! cnt.v_intr++; (clobbers %o0,%o1) @@ -4601,12 +4605,25 @@ wr %g6, 0, %tbr nop; nop; nop ! paranoia - /* Set up a stack. We use the bottom half of the interrupt stack */ +#if 1 set USRSTACK - CCFSZ, %fp ! as if called from user code + + /* Set up a stack. We use the bottom half of the interrupt stack */ sethi %hi(_EINTSTACKP), %o0 ld [%o0 + %lo(_EINTSTACKP)], %o0 set (INT_STACK_SIZE/2) + CCFSZ + 80, %sp sub %o0, %sp, %sp +#else + /* + * Use this CPUs idlelwp's stack + */ + sethi %hi(cpcb), %o0 + ld [%o0 + %lo(cpcb)], %o0 + set USPACE - 80 - CCFSZ, %sp + add %o0, %sp, %sp + + add 80, %sp, %fp +#endif /* Enable traps */ rd %psr, %l0 @@ -6320,30 +6337,5 @@ _C_LABEL(proc0paddr): .word _C_LABEL(u0) ! KVA of proc0 uarea -/* interrupt counters XXX THESE BELONG ELSEWHERE (if anywhere) */ - .globl _C_LABEL(intrcnt), _C_LABEL(eintrcnt) - .globl _C_LABEL(intrnames), _C_LABEL(eintrnames) -_C_LABEL(intrnames): - .asciz "spur" - .asciz "lev1" - .asciz "lev2" - .asciz "lev3" - .asciz "lev4" - .asciz "lev5" - .asciz "lev6" - .asciz "lev7" - .asciz "lev8" - .asciz "lev9" - .asciz "clock" - .asciz "lev11" - .asciz "lev12" - .asciz "lev13" - .asciz "prof" -_C_LABEL(eintrnames): - _ALIGN -_C_LABEL(intrcnt): - .skip 4*15 -_C_LABEL(eintrcnt): - .comm _C_LABEL(nwindows), 4 .comm _C_LABEL(romp), 4 Index: src/sys/arch/sparc/sparc/pmap.c diff -u src/sys/arch/sparc/sparc/pmap.c:1.322.20.3 src/sys/arch/sparc/sparc/pmap.c:1.322.20.4 --- src/sys/arch/sparc/sparc/pmap.c:1.322.20.3 Sun Jan 16 12:58:23 2011 +++ src/sys/arch/sparc/sparc/pmap.c Fri Jan 28 07:16:14 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.322.20.3 2011/01/16 12:58:23 bouyer Exp $ */ +/* $NetBSD: pmap.c,v 1.322.20.4 2011/01/28 07:16:14 snj Exp $ */ /* * Copyright (c) 1996 @@ -56,7 +56,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.322.20.3 2011/01/16 12:58:23 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.322.20.4 2011/01/28 07:16:14 snj Exp $"); #include "opt_ddb.h" #include "opt_kgdb.h" @@ -3505,6 +3505,23 @@ */ p = (vaddr_t)top; +#if defined(MULTIPROCESSOR) + /* + * allocate the rest of the cpu_info{} area. note we waste the + * first one to get a VA space. + */ + cpuinfo_len = ((sizeof(struct cpu_info) + NBPG - 1) & ~PGOFSET); + if (sparc_ncpus > 1) { + p = (p + NBPG - 1) & ~PGOFSET; + cpuinfo_data = (uint8_t *)p; + p += (cpuinfo_len * sparc_ncpus); + + /* XXX we waste the first one */ + memset(cpuinfo_data + cpuinfo_len, 0, cpuinfo_len * (sparc_ncpus - 1)); + } else + cpuinfo_data = (uint8_t *)CPUINFO_VA; +#endif + /* * Intialize the kernel pmap. */ @@ -3542,22 +3559,6 @@ p += ncontext * sizeof *ci; bzero((void *)ci, (u_int)p - (u_int)ci); -#if defined(MULTIPROCESSOR) - /* - * allocate the rest of the cpu_info{} area. note we waste the - * first one to get a VA space. - */ - p = (p + NBPG - 1) & ~PGOFSET; - cpuinfo_data = (uint8_t *)p; - cpuinfo_len = ((sizeof(struct cpu_info) + NBPG - 1) & ~PGOFSET); - p += (cpuinfo_len * sparc_ncpus); - prom_printf("extra cpus: %p, p: %p, gap start: %p, gap end: %p\n", - cpuinfo_data, p, etext_gap_start, etext_gap_end); - - /* XXX we waste the first one */ - memset(cpuinfo_data + cpuinfo_len, 0, cpuinfo_len * (sparc_ncpus - 1)); -#endif - /* * Set up the `constants' for the call to vm_init() * in main(). All pages beginning at p (rounded up to @@ -3802,16 +3803,23 @@ #ifdef MULTIPROCESSOR /* + * Initialise any cpu-specific data now. + */ + cpu_init_system(); + + /* * Remap cpu0 from CPUINFO_VA to the new correct value, wasting the - * backing pages we allocated above XXX. + * backing page we allocated above XXX. */ for (off = 0, va = (vaddr_t)cpuinfo_data; - off < sizeof(struct cpu_info); + sparc_ncpus > 1 && off < sizeof(struct cpu_info); va += NBPG, off += NBPG) { paddr_t pa = PMAP_BOOTSTRAP_VA2PA(CPUINFO_VA + off); prom_printf("going to pmap_kenter_pa(va=%p, pa=%p)\n", va, pa); pmap_kremove(va, NBPG); pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE); + cache_flush_page(va, 0); + cache_flush_page(CPUINFO_VA, 0); } /* @@ -3823,6 +3831,8 @@ cpus[i]->ci_self = cpus[i]; prom_printf("set cpu%d ci_self address: %p\n", i, cpus[i]); } +#else + cpus[0] = (struct cpu_info *)CPUINFO_VA; #endif pmap_update(pmap_kernel());