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;