Module Name: src
Committed By: mrg
Date: Sun May 31 20:09:44 UTC 2009
Modified Files:
src/sys/arch/sparc/sparc: cpu.c cpuvar.h pmap.c
Log Message:
- 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
i believe that the first used cpuinfo_data page is still being wasted,
but i haven't checked.
To generate a diff of this commit:
cvs rdiff -u -r1.216 -r1.217 src/sys/arch/sparc/sparc/cpu.c
cvs rdiff -u -r1.78 -r1.79 src/sys/arch/sparc/sparc/cpuvar.h
cvs rdiff -u -r1.329 -r1.330 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.216 src/sys/arch/sparc/sparc/cpu.c:1.217
--- src/sys/arch/sparc/sparc/cpu.c:1.216 Sat May 30 01:19:29 2009
+++ src/sys/arch/sparc/sparc/cpu.c Sun May 31 20:09:44 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.216 2009/05/30 01:19:29 mrg Exp $ */
+/* $NetBSD: cpu.c,v 1.217 2009/05/31 20:09:44 mrg Exp $ */
/*
* Copyright (c) 1996
@@ -52,7 +52,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.216 2009/05/30 01:19:29 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.217 2009/05/31 20:09:44 mrg 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 *);
@@ -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.
*/
Index: src/sys/arch/sparc/sparc/cpuvar.h
diff -u src/sys/arch/sparc/sparc/cpuvar.h:1.78 src/sys/arch/sparc/sparc/cpuvar.h:1.79
--- src/sys/arch/sparc/sparc/cpuvar.h:1.78 Wed May 27 02:19:49 2009
+++ src/sys/arch/sparc/sparc/cpuvar.h Sun May 31 20:09:44 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: cpuvar.h,v 1.78 2009/05/27 02:19:49 mrg Exp $ */
+/* $NetBSD: cpuvar.h,v 1.79 2009/05/31 20:09:44 mrg Exp $ */
/*
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -325,6 +325,12 @@
/*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;
};
/*
Index: src/sys/arch/sparc/sparc/pmap.c
diff -u src/sys/arch/sparc/sparc/pmap.c:1.329 src/sys/arch/sparc/sparc/pmap.c:1.330
--- src/sys/arch/sparc/sparc/pmap.c:1.329 Wed May 27 02:19:50 2009
+++ src/sys/arch/sparc/sparc/pmap.c Sun May 31 20:09:44 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.329 2009/05/27 02:19:50 mrg Exp $ */
+/* $NetBSD: pmap.c,v 1.330 2009/05/31 20:09:44 mrg Exp $ */
/*
* Copyright (c) 1996
@@ -56,7 +56,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.329 2009/05/27 02:19:50 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.330 2009/05/31 20:09:44 mrg Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -1148,6 +1148,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
}
/*
@@ -3467,8 +3489,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
/*
@@ -3502,22 +3527,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.
@@ -3616,6 +3626,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).
+ */
+ if (sparc_ncpus > 1) {
+ if (CACHEINFO.c_totalsize > align) {
+ /* Need a power of two */
+ while (align <= CACHEINFO.c_totalsize)
+ align <<= 1;
+ align >>= 1;
+ }
+ sz = sizeof(struct cpu_info);
+
+ 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);
/*
@@ -3798,35 +3837,63 @@
*/
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;