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;
 

Reply via email to