Module Name: src Committed By: bouyer Date: Wed Feb 16 21:33:25 UTC 2011
Modified Files: src/sys/arch/sparc/sparc [netbsd-5]: cpu.c cpuvar.h pmap.c timer_sun4m.c Log Message: Apply patch, requested my mrg in ticket 1553: sys/arch/sparc/sparc/cpu.c: patch sys/arch/sparc/sparc/cpuvar.h: patch sys/arch/sparc/sparc/pmap.c: patch sys/arch/sparc/sparc/timer_sun4m.c: patch - print the curpcb in ddb "mach cpu" output as well. - bump the size of cpus[] by one, so we have a NULL pointer at the end, from tsutsui - for MP kernels, copy the loop to find the bootcpu in mainbus_attach() into getcacheinfo_obp() so we can get cache properties on the bootcpu before calling main() - in getcpuinfo(), move the call of getmid() before the call to getcacheinfo() so that the above change to getcacheinfo_obp() can work - move the struct cpu_info setup to the end of the initial kernel page setup and don't access this space until after we have switched to the kernel pagetables - revive most of the old CPUINFO_VA alignment/congruency code from the old alloc_cpuinfo_global_va() function, and ensure that all cpuinfo structures are sanely aligned. this makes hypersparc work again - introduce a new way to free the wasted pages back to UVM, as we can't simply uvm_unmap() them this early in bootstrap - make sure to initialise the cpuinfo sz in all cases. noted by martin. - add per-cpu event counters for lev10 and lev14 interrupts. - make CPU_INFO_FOREACH() set the iterator count to '0' in the !MP case. - add some disabled MP code to poke other cpus on level 14 interrupts. - add a diagnostic to ensure that cpus[0] == cpu0's cpu_info->ci_self - if a cpu doesn't have any mappings allocated, don't copy them. this occurs if a cpu isn't attached (such as a MP kernel with only "cpu0" listed in the config file..) - fix the previous to compile !MULTIPROCESSOR. To generate a diff of this commit: cvs rdiff -u -r1.211.8.3 -r1.211.8.4 src/sys/arch/sparc/sparc/cpu.c cvs rdiff -u -r1.75.10.3 -r1.75.10.4 src/sys/arch/sparc/sparc/cpuvar.h cvs rdiff -u -r1.322.20.4 -r1.322.20.5 src/sys/arch/sparc/sparc/pmap.c cvs rdiff -u -r1.16.56.1 -r1.16.56.2 src/sys/arch/sparc/sparc/timer_sun4m.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.3 src/sys/arch/sparc/sparc/cpu.c:1.211.8.4 --- src/sys/arch/sparc/sparc/cpu.c:1.211.8.3 Fri Jan 28 07:16:13 2011 +++ src/sys/arch/sparc/sparc/cpu.c Wed Feb 16 21:33:25 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.c,v 1.211.8.3 2011/01/28 07:16:13 snj Exp $ */ +/* $NetBSD: cpu.c,v 1.211.8.4 2011/02/16 21:33:25 bouyer Exp $ */ /* * Copyright (c) 1996 @@ -52,7 +52,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.211.8.3 2011/01/28 07:16:13 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.211.8.4 2011/02/16 21:33:25 bouyer Exp $"); #include "opt_multiprocessor.h" #include "opt_lockdebug.h" @@ -102,7 +102,7 @@ extern char machine_model[]; int sparc_ncpus; /* # of CPUs detected by PROM */ -struct cpu_info *cpus[_MAXNCPU]; /* we only support 4 CPUs. */ +struct cpu_info *cpus[_MAXNCPU+1]; /* we only support 4 CPUs. */ /* The CPU configuration driver. */ static void cpu_mainbus_attach(struct device *, struct device *, void *); @@ -424,7 +424,7 @@ } /* - * Note: `eintstack' is set in init_cpuinfo() above. + * Note: `eintstack' is set in cpu_attach_non_boot() above. * The %wim register will be initialized in cpu_hatch(). */ cpi->ci_curlwp = cpi->ci_data.cpu_idlelwp; @@ -1123,6 +1123,35 @@ struct cacheinfo *ci = &sc->cacheinfo; int i, l; +#if defined(MULTIPROCESSOR) + /* + * We really really want the cache info early for MP systems, + * so figure out the boot node, if we can. + * + * XXX this loop stolen from mainbus_attach() + */ + if (node == 0 && CPU_ISSUN4M && bootmid != 0) { + const char *cp; + char namebuf[32]; + int mid, node2; + + for (node2 = firstchild(findroot()); + node2; + node2 = nextsibling(node2)) { + cp = prom_getpropstringA(node2, "device_type", + namebuf, sizeof namebuf); + if (strcmp(cp, "cpu") != 0) + continue; + + mid = prom_getpropint(node2, "mid", -1); + if (mid == bootmid) { + node = node2; + break; + } + } + } +#endif + if (node == 0) /* Bootstrapping */ return; @@ -1862,6 +1891,9 @@ if (sc->cacheinfo.c_vactype == VAC_UNKNOWN) sc->cacheinfo.c_vactype = mp->minfo->vactype; + if (sc->master && mp->minfo->getmid != NULL) + bootmid = mp->minfo->getmid(); + mp->minfo->getcacheinfo(sc, node); if (node && sc->hz == 0 && !CPU_ISSUN4/*XXX*/) { @@ -1875,9 +1907,6 @@ } } - if (sc->master && mp->minfo->getmid != NULL) - bootmid = mp->minfo->getmid(); - /* * Copy CPU/MMU/Cache specific routines into cpu_info. */ @@ -2015,16 +2044,17 @@ struct cpu_info *ci; CPU_INFO_ITERATOR cii; - db_printf("%-4s %-10s %-8s %-10s %-10s %-10s\n", - "CPU#", "CPUINFO", "FLAGS", "CURLWP", "CURPROC", "FPLWP"); + db_printf("%-4s %-10s %-8s %-10s %-10s %-10s %-10s\n", + "CPU#", "CPUINFO", "FLAGS", "CURLWP", "CURPROC", "FPLWP", "CPCB"); for (CPU_INFO_FOREACH(cii, ci)) { - db_printf("%-4d %-10p %-8x %-10p %-10p %-10p\n", + db_printf("%-4d %-10p %-8x %-10p %-10p %-10p %-10p\n", ci->ci_cpuid, ci, ci->flags, ci->ci_curlwp, ci->ci_curlwp == NULL ? NULL : ci->ci_curlwp->l_proc, - ci->fplwp); + ci->fplwp, + ci->curpcb); } } #endif Index: src/sys/arch/sparc/sparc/cpuvar.h diff -u src/sys/arch/sparc/sparc/cpuvar.h:1.75.10.3 src/sys/arch/sparc/sparc/cpuvar.h:1.75.10.4 --- src/sys/arch/sparc/sparc/cpuvar.h:1.75.10.3 Fri Jan 28 07:16:13 2011 +++ src/sys/arch/sparc/sparc/cpuvar.h Wed Feb 16 21:33:25 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: cpuvar.h,v 1.75.10.3 2011/01/28 07:16:13 snj Exp $ */ +/* $NetBSD: cpuvar.h,v 1.75.10.4 2011/02/16 21:33:25 bouyer Exp $ */ /* * Copyright (c) 1996 The NetBSD Foundation, Inc. @@ -325,6 +325,16 @@ /*bus_space_handle_t*/ long ci_mxccregs; u_int ci_tt; /* Last trap (if tracing) */ + + /* + * Start/End VA's of this cpu_info region; we upload the other pages + * in this region that aren't part of the cpu_info to uvm. + */ + vaddr_t ci_free_sva1, ci_free_eva1, ci_free_sva2, ci_free_eva2; + + char ci_cpuname[8]; /* "cpu/0", etc. */ + struct evcnt ci_lev10; + struct evcnt ci_lev14; }; /* @@ -415,7 +425,7 @@ #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) cii = 0, cp = curcpu(); cp != NULL; cp = NULL #endif /* Index: src/sys/arch/sparc/sparc/pmap.c diff -u src/sys/arch/sparc/sparc/pmap.c:1.322.20.4 src/sys/arch/sparc/sparc/pmap.c:1.322.20.5 --- src/sys/arch/sparc/sparc/pmap.c:1.322.20.4 Fri Jan 28 07:16:14 2011 +++ src/sys/arch/sparc/sparc/pmap.c Wed Feb 16 21:33:25 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.322.20.4 2011/01/28 07:16:14 snj Exp $ */ +/* $NetBSD: pmap.c,v 1.322.20.5 2011/02/16 21:33:25 bouyer Exp $ */ /* * Copyright (c) 1996 @@ -56,7 +56,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.322.20.4 2011/01/28 07:16:14 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.322.20.5 2011/02/16 21:33:25 bouyer Exp $"); #include "opt_ddb.h" #include "opt_kgdb.h" @@ -1147,6 +1147,28 @@ atop(start), atop(end), VM_FREELIST_DEFAULT); } + +#if defined(MULTIPROCESSOR) + { + CPU_INFO_ITERATOR cpunum; + struct cpu_info *cpi; + + for (CPU_INFO_FOREACH(cpunum, cpi)) { + if (cpi->ci_free_sva1) + uvm_page_physload(atop(PMAP_BOOTSTRAP_VA2PA(cpi->ci_free_sva1)), + atop(PMAP_BOOTSTRAP_VA2PA(cpi->ci_free_eva1)), + atop(PMAP_BOOTSTRAP_VA2PA(cpi->ci_free_sva1)), + atop(PMAP_BOOTSTRAP_VA2PA(cpi->ci_free_eva1)), + VM_FREELIST_DEFAULT); + if (cpi->ci_free_sva2) + uvm_page_physload(atop(PMAP_BOOTSTRAP_VA2PA(cpi->ci_free_sva2)), + atop(PMAP_BOOTSTRAP_VA2PA(cpi->ci_free_eva2)), + atop(PMAP_BOOTSTRAP_VA2PA(cpi->ci_free_sva2)), + atop(PMAP_BOOTSTRAP_VA2PA(cpi->ci_free_eva2)), + VM_FREELIST_DEFAULT); + } + } +#endif } /* @@ -3446,6 +3468,7 @@ setpte4(p, getpte4(p) & ~PG_NC); } + cpus[0] = (struct cpu_info *)CPUINFO_VA; } #endif @@ -3470,8 +3493,11 @@ vaddr_t va; #ifdef MULTIPROCESSOR vsize_t off; - size_t cpuinfo_len; + size_t cpuinfo_len = sizeof(struct cpu_info); uint8_t *cpuinfo_data; + int align = PAGE_SIZE; + vaddr_t sva, cpuinfo_va; + vsize_t sz; #endif /* @@ -3505,22 +3531,7 @@ */ 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 + p = (p + NBPG - 1) & ~PGOFSET; /* * Intialize the kernel pmap. @@ -3619,6 +3630,35 @@ p = (p + NBPG - 1) & ~PGOFSET; pagetables_end = p; +#if defined(MULTIPROCESSOR) + /* + * Allocate aligned KVA. `cpuinfo' resides at a fixed virtual + * address. Since we need to access an other CPU's cpuinfo + * structure occasionally, this must be done at a virtual address + * that's cache congruent to the fixed address CPUINFO_VA. + * + * NOTE: we're using the cache properties of the boot CPU to + * determine the alignment (XXX). + */ + sz = sizeof(struct cpu_info); + if (sparc_ncpus > 1) { + if (CACHEINFO.c_totalsize > align) { + /* Need a power of two */ + while (align <= CACHEINFO.c_totalsize) + align <<= 1; + align >>= 1; + } + + sz = (sz + PAGE_SIZE - 1) & -PAGE_SIZE; + cpuinfo_len = sz + align - PAGE_SIZE; + + /* Grab as much space as we need */ + cpuinfo_data = (uint8_t *)p; + p += (cpuinfo_len * sparc_ncpus); + } else + cpuinfo_data = (uint8_t *)CPUINFO_VA; +#endif + avail_start = PMAP_BOOTSTRAP_VA2PA(p); /* @@ -3801,41 +3841,77 @@ */ mmu_install_tables(&cpuinfo); -#ifdef MULTIPROCESSOR +#if defined(MULTIPROCESSOR) /* * Initialise any cpu-specific data now. */ cpu_init_system(); /* - * Remap cpu0 from CPUINFO_VA to the new correct value, wasting the - * backing page we allocated above XXX. - */ - for (off = 0, va = (vaddr_t)cpuinfo_data; - 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); - } - - /* * Setup the cpus[] array and the ci_self links. */ prom_printf("setting cpus self reference\n"); for (i = 0; i < sparc_ncpus; i++) { - cpus[i] = (struct cpu_info *)(cpuinfo_data + (cpuinfo_len * i)); + sva = (vaddr_t) (cpuinfo_data + (cpuinfo_len * i)); + cpuinfo_va = sva + + (((CPUINFO_VA & (align - 1)) + align - sva) & (align - 1)); + + /* + * Either remap from CPUINFO_VA to the new correct value + * or clear out this cpuinfo. + */ + if (i == 0) { + for (off = 0, va = cpuinfo_va; + 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); + } + + } else + memset((void *)cpuinfo_va, 0, sizeof(struct cpu_info)); + + cpus[i] = (struct cpu_info *)cpuinfo_va; cpus[i]->ci_self = cpus[i]; prom_printf("set cpu%d ci_self address: %p\n", i, cpus[i]); + + /* Unmap and prepare to return unused pages */ + if (cpuinfo_va != sva) { + cpus[i]->ci_free_sva1 = sva; + cpus[i]->ci_free_eva1 = cpuinfo_va; + for (va = cpus[i]->ci_free_sva1; + va < cpus[i]->ci_free_eva1; + va += NBPG) + setpte4m(va, 0); + } + if (cpuinfo_va + sz != sva + cpuinfo_len) { + cpus[i]->ci_free_sva2 = cpuinfo_va + sz; + cpus[i]->ci_free_eva2 = sva + cpuinfo_len; + for (va = cpus[i]->ci_free_sva2; + va < cpus[i]->ci_free_eva2; + va += NBPG) + setpte4m(va, 0); + } } #else cpus[0] = (struct cpu_info *)CPUINFO_VA; #endif pmap_update(pmap_kernel()); + +#ifdef DIAGNOSTIC + if (curcpu()->ci_self != cpus[0]) { + prom_printf("curcpu()->ci_self %p != cpus[0] %p\n", curcpu()->ci_self, cpus[0]); + panic("cpuinfo inconsistent"); + } +#endif + prom_printf("pmap_bootstrap4m done\n"); } @@ -4110,6 +4186,10 @@ n = 0; #endif { + /* Did this cpu attach? */ + if (pmap_kernel()->pm_reg_ptps[n] == 0) + continue; + if (pm->pm_reg_ptps[n][vr] != SRMMU_TEINVALID) printf("pmap_chk: spurious PTP in user " "region %d on CPU %d\n", vr, n); @@ -4223,6 +4303,12 @@ { int *upt, *kpt; +#if defined(MULTIPROCESSOR) + /* Did this cpu attach? */ + if (pmap_kernel()->pm_reg_ptps[n] == 0) + continue; +#endif + upt = pool_get(&L1_pool, flags); pm->pm_reg_ptps[n] = upt; pm->pm_reg_ptps_pa[n] = VA2PA((char *)upt); @@ -4273,7 +4359,15 @@ n = 0; #endif { - int *pt = pm->pm_reg_ptps[n]; + int *pt; + +#if defined(MULTIPROCESSOR) + /* Did this cpu attach? */ + if (pmap_kernel()->pm_reg_ptps[n] == 0) + continue; +#endif + + pt = pm->pm_reg_ptps[n]; pm->pm_reg_ptps[n] = NULL; pm->pm_reg_ptps_pa[n] = 0; pool_put(&L1_pool, pt); Index: src/sys/arch/sparc/sparc/timer_sun4m.c diff -u src/sys/arch/sparc/sparc/timer_sun4m.c:1.16.56.1 src/sys/arch/sparc/sparc/timer_sun4m.c:1.16.56.2 --- src/sys/arch/sparc/sparc/timer_sun4m.c:1.16.56.1 Sat May 30 16:57:18 2009 +++ src/sys/arch/sparc/sparc/timer_sun4m.c Wed Feb 16 21:33:25 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: timer_sun4m.c,v 1.16.56.1 2009/05/30 16:57:18 snj Exp $ */ +/* $NetBSD: timer_sun4m.c,v 1.16.56.2 2011/02/16 21:33:25 bouyer Exp $ */ /* * Copyright (c) 1992, 1993 @@ -58,7 +58,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: timer_sun4m.c,v 1.16.56.1 2009/05/30 16:57:18 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: timer_sun4m.c,v 1.16.56.2 2011/02/16 21:33:25 bouyer Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -110,6 +110,7 @@ * panic * so for now just bail when cold */ + cpuinfo.ci_lev10.ev_count++; if (cold) return 0; /* read the limit register to clear the interrupt */ @@ -128,6 +129,8 @@ struct clockframe *frame = cap; u_long newint; + cpuinfo.ci_lev14.ev_count++; + /* read the limit register to clear the interrupt */ *((volatile int *)&counterreg4m->t_limit); @@ -221,6 +224,13 @@ cpi->counterreg_4m = (struct counter_4m *)bh; } + /* Install timer/statclock event counters, per cpu */ + for (CPU_INFO_FOREACH(n, cpi)) { + snprintf(cpi->ci_cpuname, sizeof(cpi->ci_cpuname), "cpu/%d", n); + evcnt_attach_dynamic(&cpi->ci_lev10, EVCNT_TYPE_INTR, NULL, cpi->ci_cpuname, "lev10"); + evcnt_attach_dynamic(&cpi->ci_lev14, EVCNT_TYPE_INTR, NULL, cpi->ci_cpuname, "lev14"); + } + /* Put processor counter in "timer" mode */ timerreg4m->t_cfg = 0;