Index: sys/arch/sparc/sparc/cpu.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/cpu.c,v retrieving revision 1.211.8.3 diff -p -r1.211.8.3 cpu.c *** sys/arch/sparc/sparc/cpu.c 28 Jan 2011 07:16:13 -0000 1.211.8.3 --- sys/arch/sparc/sparc/cpu.c 13 Feb 2011 23:50:18 -0000 *************** char cpu_model[100]; /* machine model *** 102,108 **** extern char machine_model[]; int sparc_ncpus; /* # of CPUs detected by PROM */ ! struct cpu_info *cpus[_MAXNCPU]; /* we only support 4 CPUs. */ /* The CPU configuration driver. */ static void cpu_mainbus_attach(struct device *, struct device *, void *); --- 102,108 ---- extern char machine_model[]; int sparc_ncpus; /* # of CPUs detected by PROM */ ! 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 *); *************** cpu_attach_non_boot(struct cpu_softc *sc *** 424,430 **** } /* ! * 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; --- 424,430 ---- } /* ! * 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; *************** getcacheinfo_obp(struct cpu_info *sc, in *** 1123,1128 **** --- 1123,1157 ---- 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; *************** getcpuinfo(struct cpu_info *sc, int node *** 1862,1867 **** --- 1891,1899 ---- 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*/) { *************** getcpuinfo(struct cpu_info *sc, int node *** 1875,1883 **** } } - if (sc->master && mp->minfo->getmid != NULL) - bootmid = mp->minfo->getmid(); - /* * Copy CPU/MMU/Cache specific routines into cpu_info. */ --- 1907,1912 ---- *************** cpu_debug_dump(void) *** 2015,2030 **** struct cpu_info *ci; CPU_INFO_ITERATOR cii; ! db_printf("%-4s %-10s %-8s %-10s %-10s %-10s\n", ! "CPU#", "CPUINFO", "FLAGS", "CURLWP", "CURPROC", "FPLWP"); for (CPU_INFO_FOREACH(cii, ci)) { ! db_printf("%-4d %-10p %-8x %-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); } } #endif --- 2044,2060 ---- struct cpu_info *ci; CPU_INFO_ITERATOR cii; ! 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 %-10p\n", ci->ci_cpuid, ci, ci->flags, ci->ci_curlwp, ci->ci_curlwp == NULL ? NULL : ci->ci_curlwp->l_proc, ! ci->fplwp, ! ci->curpcb); } } #endif Index: sys/arch/sparc/sparc/cpuvar.h =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/cpuvar.h,v retrieving revision 1.75.10.3 diff -p -r1.75.10.3 cpuvar.h *** sys/arch/sparc/sparc/cpuvar.h 28 Jan 2011 07:16:13 -0000 1.75.10.3 --- sys/arch/sparc/sparc/cpuvar.h 13 Feb 2011 23:50:18 -0000 *************** struct cpu_info { *** 325,330 **** --- 325,340 ---- /*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; }; /* *************** struct cpu_info { *** 415,421 **** #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 #endif /* --- 425,431 ---- #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) cii = 0, cp = curcpu(); cp != NULL; cp = NULL #endif /* Index: sys/arch/sparc/sparc/pmap.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/pmap.c,v retrieving revision 1.322.20.4 diff -p -r1.322.20.4 pmap.c *** sys/arch/sparc/sparc/pmap.c 28 Jan 2011 07:16:14 -0000 1.322.20.4 --- sys/arch/sparc/sparc/pmap.c 13 Feb 2011 23:50:18 -0000 *************** pmap_page_upload(void) *** 1147,1152 **** --- 1147,1174 ---- 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 } /* *************** pmap_bootstrap4_4c(void *top, int nctx, *** 3446,3451 **** --- 3468,3474 ---- setpte4(p, getpte4(p) & ~PG_NC); } + cpus[0] = (struct cpu_info *)CPUINFO_VA; } #endif *************** pmap_bootstrap4m(void *top) *** 3470,3477 **** vaddr_t va; #ifdef MULTIPROCESSOR vsize_t off; ! size_t cpuinfo_len; uint8_t *cpuinfo_data; #endif /* --- 3493,3503 ---- vaddr_t va; #ifdef MULTIPROCESSOR vsize_t off; ! 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 /* *************** pmap_bootstrap4m(void *top) *** 3505,3526 **** */ 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. --- 3531,3537 ---- */ p = (vaddr_t)top; ! p = (p + NBPG - 1) & ~PGOFSET; /* * Intialize the kernel pmap. *************** pmap_bootstrap4m(void *top) *** 3619,3624 **** --- 3630,3664 ---- 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); /* *************** pmap_bootstrap4m(void *top) *** 3801,3841 **** */ mmu_install_tables(&cpuinfo); ! #ifdef 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)); 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()); prom_printf("pmap_bootstrap4m done\n"); } --- 3841,3917 ---- */ mmu_install_tables(&cpuinfo); ! #if defined(MULTIPROCESSOR) /* * Initialise any cpu-specific data now. */ cpu_init_system(); /* * Setup the cpus[] array and the ci_self links. */ prom_printf("setting cpus self reference\n"); for (i = 0; i < sparc_ncpus; 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"); } *************** pmap_quiet_check(struct pmap *pm) *** 4110,4115 **** --- 4186,4195 ---- 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); *************** pmap_pmap_pool_ctor(void *arg, void *obj *** 4223,4228 **** --- 4303,4314 ---- { 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); *************** pmap_pmap_pool_dtor(void *arg, void *obj *** 4273,4279 **** n = 0; #endif { ! int *pt = pm->pm_reg_ptps[n]; pm->pm_reg_ptps[n] = NULL; pm->pm_reg_ptps_pa[n] = 0; pool_put(&L1_pool, pt); --- 4359,4373 ---- n = 0; #endif { ! 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: sys/arch/sparc/sparc/timer_sun4m.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/timer_sun4m.c,v retrieving revision 1.16.56.1 diff -p -r1.16.56.1 timer_sun4m.c *** sys/arch/sparc/sparc/timer_sun4m.c 30 May 2009 16:57:18 -0000 1.16.56.1 --- sys/arch/sparc/sparc/timer_sun4m.c 13 Feb 2011 23:50:18 -0000 *************** clockintr_4m(void *cap) *** 110,115 **** --- 110,116 ---- * 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 */ *************** statintr_4m(void *cap) *** 128,133 **** --- 129,136 ---- 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); *************** timerattach_obio_4m(struct device *paren *** 221,226 **** --- 224,236 ---- 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;