Module Name:    src
Committed By:   mrg
Date:           Mon Feb 22 00:16:31 UTC 2010

Modified Files:
        src/sys/arch/sparc64/sparc64: autoconf.c cache.h cpu.c locore.s

Log Message:
- store the maximum [id]cache size / line size for each cpu

- remove patch_kernel() since it isn't necessary and has been patching
  the wrong thing in general.

- implement USIII versions of blast_icache(), dcache_flush_page() and
  cache_flush_phys().  use the newly recorded cache size/line sizes.

- in winfixsave, flush the D$ with the right size index and ops.  this
  kills one of the wrong tag->inval patches.

- for blast_dcache(), use the newly recorded dcache_size/line_size.

- for blast_icache(), use the newly recorded cache size/line sizes.
  for the USIII verison, disable the I$ while writing to ASI_ICACHE_TAG.

these changes removed several hard coded cache sizes values, some very
wrong kernel patching, and seem to make the current failure modes for
USIII less common, but not gone.


To generate a diff of this commit:
cvs rdiff -u -r1.167 -r1.168 src/sys/arch/sparc64/sparc64/autoconf.c
cvs rdiff -u -r1.11 -r1.12 src/sys/arch/sparc64/sparc64/cache.h
cvs rdiff -u -r1.88 -r1.89 src/sys/arch/sparc64/sparc64/cpu.c
cvs rdiff -u -r1.317 -r1.318 src/sys/arch/sparc64/sparc64/locore.s

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/sparc64/sparc64/autoconf.c
diff -u src/sys/arch/sparc64/sparc64/autoconf.c:1.167 src/sys/arch/sparc64/sparc64/autoconf.c:1.168
--- src/sys/arch/sparc64/sparc64/autoconf.c:1.167	Mon Feb 15 07:56:51 2010
+++ src/sys/arch/sparc64/sparc64/autoconf.c	Mon Feb 22 00:16:31 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: autoconf.c,v 1.167 2010/02/15 07:56:51 mrg Exp $ */
+/*	$NetBSD: autoconf.c,v 1.168 2010/02/22 00:16:31 mrg Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.167 2010/02/15 07:56:51 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.168 2010/02/22 00:16:31 mrg Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -183,7 +183,6 @@
 #endif
 
 int console_node, console_instance;
-static void patch_kernel(void);
 struct genfb_colormap_callback gfb_cb;
 static void of_set_palette(void *, int, int, int, int);
 static void copyprops(struct device *busdev, int, prop_dictionary_t);
@@ -335,65 +334,6 @@
 
 	get_ncpus();
 	pmap_bootstrap(KERNBASE, bi_kend->addr);
-
-	patch_kernel();
-}
-
-/*
- * Now that we've stopped using the prom mappings, we need to handle any
- * text fixups.
- *
- * For the USIII and newer cpus, convert ASI_DCACHE_TAG into
- * ASI_DCACHE_INVALIDATE.
- *
- * For the older CPUs, we need to convert a branch to a nop in
- * cache_flush_phys().
- */
-static void
-patch_kernel(void)
-{
-	paddr_t pa;
-	vaddr_t *pva;
-
-	if (CPU_IS_USIII_UP()) {
-		extern vaddr_t dlflush_start;
-		uint32_t insn, oinsn;
-
-		for (pva = &dlflush_start; *pva; pva++) {
-			oinsn = insn = *(uint32_t *)(*pva);
-			insn &= ~(ASI_DCACHE_TAG << 5);
-			insn |= (ASI_DCACHE_INVALIDATE << 5);
-
-			if (pmap_extract(pmap_kernel(), *pva, &pa)) {
-				sta(pa, ASI_PHYS_CACHED, insn);
-				flush((void *)(*pva));
-#ifdef PATCH_KERNEL_DEBUG
-				printf("patched %p for USIII ASI_DCACHE_INVALIDATE"
-				       ": old insn %08x ew insn %08x\n",
-				    (void *)(intptr_t)*pva, oinsn, insn);
-			} else {
-				printf("could not pmap_extract() to patch %p\n",
-				    (void *)(intptr_t)*pva);
-#endif
-			}
-		}
-	} else {
-		extern vaddr_t nop_on_us_1_start;
-
-		for (pva = &nop_on_us_1_start; *pva; pva++) {
-			if (pmap_extract(pmap_kernel(), *pva, &pa)) {
-				sta(pa, ASI_PHYS_CACHED, 0x01000000);
-				flush((void *)(*pva));
-#ifdef PATCH_KERNEL_DEBUG
-				printf("patched %p for USI/II cache_flush_phys\n",
-				    (void *)(intptr_t)*pva);
-			} else {
-				printf("could not pmap_extract() to patch %p\n",
-				    (void *)(intptr_t)*pva);
-#endif
-			}
-		}
-	}
 }
 
 /*

Index: src/sys/arch/sparc64/sparc64/cache.h
diff -u src/sys/arch/sparc64/sparc64/cache.h:1.11 src/sys/arch/sparc64/sparc64/cache.h:1.12
--- src/sys/arch/sparc64/sparc64/cache.h:1.11	Mon Feb  1 03:43:27 2010
+++ src/sys/arch/sparc64/sparc64/cache.h	Mon Feb 22 00:16:31 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: cache.h,v 1.11 2010/02/01 03:43:27 mrg Exp $ */
+/*	$NetBSD: cache.h,v 1.12 2010/02/22 00:16:31 mrg Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -73,12 +73,46 @@
  */
 
 /* The following are for I$ and D$ flushes and are in locore.s */
-void 	dcache_flush_page(paddr_t);	/* flush page from D$ */
+void 	dcache_flush_page_us(paddr_t);	/* flush page from D$ */
+void 	dcache_flush_page_usiii(paddr_t); /* flush page from D$ */
 void 	blast_dcache(void);		/* Clear entire D$ */
-void 	blast_icache(void);		/* Clear entire I$ */
+void 	blast_icache_us(void);		/* Clear entire I$ */
+void 	blast_icache_usiii(void);	/* Clear entire I$ */
 
 /* The following flush a range from the D$ and I$ but not E$. */
-void	cache_flush_phys(paddr_t, psize_t, int);
+void	cache_flush_phys_us(paddr_t, psize_t, int);
+void	cache_flush_phys_usiii(paddr_t, psize_t, int);
 
-/* Smallest E$ line size. */
+static __inline__ void
+dcache_flush_page(paddr_t pa)
+{
+	if (CPU_IS_USIII_UP())
+		dcache_flush_page_usiii(pa);
+	else
+		dcache_flush_page_us(pa);
+}
+
+static __inline__ void
+cache_flush_phys(paddr_t pa, psize_t size, int ecache)
+{
+	if (CPU_IS_USIII_UP())
+		cache_flush_phys_usiii(pa, size, ecache);
+	else
+		cache_flush_phys_us(pa, size, ecache);
+}
+
+static __inline__ void
+blast_icache(void)
+{
+	if (CPU_IS_USIII_UP())
+		blast_icache_usiii();
+	else
+		blast_icache_us();
+}
+
+/* Various cache size/line sizes */
 extern	int	ecache_min_line_size;
+extern	int	dcache_line_size;
+extern	int	dcache_size;
+extern	int	icache_line_size;
+extern	int	icache_size;

Index: src/sys/arch/sparc64/sparc64/cpu.c
diff -u src/sys/arch/sparc64/sparc64/cpu.c:1.88 src/sys/arch/sparc64/sparc64/cpu.c:1.89
--- src/sys/arch/sparc64/sparc64/cpu.c:1.88	Wed Dec  2 07:55:01 2009
+++ src/sys/arch/sparc64/sparc64/cpu.c	Mon Feb 22 00:16:31 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.c,v 1.88 2009/12/02 07:55:01 mrg Exp $ */
+/*	$NetBSD: cpu.c,v 1.89 2010/02/22 00:16:31 mrg Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -52,7 +52,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.88 2009/12/02 07:55:01 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.89 2010/02/22 00:16:31 mrg Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -92,6 +92,12 @@
 char	cpu_model[100];			/* machine model (primary CPU) */
 extern char machine_model[];
 
+/* These are used in locore.s, and are maximums */
+int	dcache_line_size;
+int	dcache_size;
+int	icache_line_size;
+int	icache_size;
+
 #ifdef MULTIPROCESSOR
 static const char *ipi_evcnt_names[IPI_EVCNT_NUM] = IPI_EVCNT_NAMES;
 #endif
@@ -238,7 +244,7 @@
 	int bigcache, cachesize;
 	char buf[100];
 	int 	totalsize = 0;
-	int 	linesize;
+	int 	linesize, dcachesize, icachesize;
 
 	/* tell them what we have */
 	node = ma->ma_node;
@@ -295,14 +301,18 @@
 
 	bigcache = 0;
 
-	linesize = l =
-		prom_getpropint(node, "icache-line-size", 0);
+	icachesize = prom_getpropint(node, "icache-size", 0);
+	if (icachesize > icache_size)
+		icache_size = icachesize;
+	linesize = l = prom_getpropint(node, "icache-line-size", 0);
+	if (linesize > icache_line_size)
+		icache_line_size = linesize;
+
 	for (i = 0; (1 << i) < l && l; i++)
 		/* void */;
 	if ((1 << i) != l && l)
 		panic("bad icache line size %d", l);
-	totalsize =
-		prom_getpropint(node, "icache-size", 0) *
+	totalsize = icachesize *
 		prom_getpropint(node, "icache-associativity", 1);
 	if (totalsize == 0)
 		totalsize = l *
@@ -321,14 +331,18 @@
 		sep = ", ";
 	}
 
-	linesize = l =
-		prom_getpropint(node, "dcache-line-size",0);
+	dcachesize = prom_getpropint(node, "dcache-size", 0);
+	if (dcachesize > dcache_size)
+		dcache_size = dcachesize;
+	linesize = l = prom_getpropint(node, "dcache-line-size", 0);
+	if (linesize > dcache_line_size)
+		dcache_line_size = linesize;
+
 	for (i = 0; (1 << i) < l && l; i++)
 		/* void */;
 	if ((1 << i) != l && l)
 		panic("bad dcache line size %d", l);
-	totalsize =
-		prom_getpropint(node, "dcache-size", 0) *
+	totalsize = dcachesize *
 		prom_getpropint(node, "dcache-associativity", 1);
 	if (totalsize == 0)
 		totalsize = l *

Index: src/sys/arch/sparc64/sparc64/locore.s
diff -u src/sys/arch/sparc64/sparc64/locore.s:1.317 src/sys/arch/sparc64/sparc64/locore.s:1.318
--- src/sys/arch/sparc64/sparc64/locore.s:1.317	Mon Feb 15 12:46:24 2010
+++ src/sys/arch/sparc64/sparc64/locore.s	Mon Feb 22 00:16:31 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.s,v 1.317 2010/02/15 12:46:24 mrg Exp $	*/
+/*	$NetBSD: locore.s,v 1.318 2010/02/22 00:16:31 mrg Exp $	*/
 
 /*
  * Copyright (c) 1996-2002 Eduardo Horvath
@@ -61,7 +61,6 @@
 #undef	TRAPS_USE_IG		/* Use Interrupt Globals for all traps */
 #define	HWREF			/* Track ref/mod bits in trap handlers */
 #undef	DCACHE_BUG		/* Flush D$ around ASI_PHYS accesses */
-#undef	SPITFIRE		/* Only used in DLFLUSH* now, see DCACHE_BUG */
 #undef	NO_TSB			/* Don't use TSB */
 #define	USE_BLOCK_STORE_LOAD	/* enable block load/store ops */
 #define	BB_ERRATA_1		/* writes to TICK_CMPR may fail */
@@ -202,20 +201,14 @@
  * It uses a register with the address to clear and a temporary
  * which is destroyed.
  */
-#ifdef SPITFIRE
-#define ASI_DCACHE_TAG_OR_INV	ASI_DCACHE_TAG
-#else
-#define ASI_DCACHE_TAG_OR_INV	ASI_DCACHE_INVALIDATE
-#endif
-
 #ifdef DCACHE_BUG
 #define DLFLUSH(a,t) \
 	andn	a, 0x1f, t; \
-	stxa	%g0, [ t ] ASI_DCACHE_TAG_OR_INV; \
+	stxa	%g0, [ t ] ASI_DCACHE_TAG; \
 	membar	#Sync
 /* The following can be used if the pointer is 16-byte aligned */
 #define DLFLUSH2(t) \
-	stxa	%g0, [ t ] ASI_DCACHE_TAG_OR_INV; \
+	stxa	%g0, [ t ] ASI_DCACHE_TAG; \
 	membar	#Sync
 #else
 #define DLFLUSH(a,t)
@@ -2285,9 +2278,12 @@
 	/* Did we save a user or kernel window ? */
 !	srax	%g3, 48, %g5				! User or kernel store? (TAG TARGET)
 	sllx	%g3, (64-13), %g5			! User or kernel store? (TAG ACCESS)
-	sethi	%hi((2*NBPG)-8), %g7
+	sethi	%hi(dcache_size), %g7
+	ld	[%g7 + %lo(dcache_size)], %g7
+	sethi	%hi(dcache_line_size), %g6
+	ld	[%g6 + %lo(dcache_line_size)], %g6
 	brnz,pt	%g5, 1f					! User fault -- save windows to pcb
-	 or	%g7, %lo((2*NBPG)-8), %g7
+	 sub	%g7, %g6, %g7
 
 	and	%g4, CWP, %g4				! %g4 = %cwp of trap
 	wrpr	%g4, 0, %cwp				! Kernel fault -- restore %cwp and force and trap to debugger
@@ -2316,10 +2312,9 @@
 1:
 #if 1
 	/* Now we need to blast away the D$ to make sure we're in sync */
-dlflush1:
 	stxa	%g0, [%g7] ASI_DCACHE_TAG
 	brnz,pt	%g7, 1b
-	 dec	8, %g7
+	 sub	%g7, %g6, %g7
 #endif
 
 #ifdef NOTDEF_DEBUG
@@ -5296,14 +5291,19 @@
 #endif
 
 	rdpr	%pstate, %o3
-	set	(2 * NBPG) - 32, %o1
+	sethi	%hi(dcache_size), %o1
+	ld	[%o1 + %lo(dcache_size)], %o1
+	sethi	%hi(dcache_line_size), %o5
+	ld	[%o5 + %lo(dcache_line_size)], %o5
+	sub	%o1, %o5, %o1
 	andn	%o3, PSTATE_IE, %o4			! Turn off PSTATE_IE bit
 	wrpr	%o4, 0, %pstate
 1:
-dlflush2:
 	stxa	%g0, [%o1] ASI_DCACHE_TAG
+	membar	#Sync
 	brnz,pt	%o1, 1b
-	 dec	32, %o1
+	 sub	%o1, %o5, %o1
+
 	sethi	%hi(KERNBASE), %o2
 	flush	%o2
 	membar	#Sync
@@ -5317,39 +5317,69 @@
 #endif
 
 /*
- * blast_icache()
+ * blast_icache_us()
+ * blast_icache_usiii()
  *
  * Clear out all of I$ regardless of contents
  * Does not modify %o0
  *
- */
-	.align 8
-ENTRY(blast_icache)
-/*
  * We turn off interrupts for the duration to prevent RED exceptions.
+ * For the Cheetah version, we also have to to turn off the I$ during this as
+ * ASI_ICACHE_TAG accesses interfere with coherency.
  */
+	.align 8
+ENTRY(blast_icache_us)
 	rdpr	%pstate, %o3
-	set	(2 * NBPG) - 32, %o1
+	sethi	%hi(icache_size), %o1
+	ld	[%o1 + %lo(icache_size)], %o1
+	sethi	%hi(icache_line_size), %o2
+	ld	[%o2 + %lo(icache_line_size)], %o2
+	sub	%o1, %o2, %o1
 	andn	%o3, PSTATE_IE, %o4			! Turn off PSTATE_IE bit
 	wrpr	%o4, 0, %pstate
 1:
 	stxa	%g0, [%o1] ASI_ICACHE_TAG
 	brnz,pt	%o1, 1b
-	 dec	32, %o1
-	sethi	%hi(KERNBASE), %o2
-	flush	%o2
+	 sub	%o1, %o2, %o1
+	sethi	%hi(KERNBASE), %o5
+	flush	%o5
 	membar	#Sync
 	retl
 	 wrpr	%o3, %pstate
 
+	.align 8
+ENTRY(blast_icache_usiii)
+	rdpr	%pstate, %o3
+	sethi	%hi(icache_size), %o1
+	ld	[%o1 + %lo(icache_size)], %o1
+	sethi	%hi(icache_line_size), %o2
+	ld	[%o2 + %lo(icache_line_size)], %o2
+	sub	%o1, %o2, %o1
+	andn	%o3, PSTATE_IE, %o4			! Turn off PSTATE_IE bit
+	wrpr	%o4, 0, %pstate
+	ldxa    [%g0] ASI_MCCR, %o5
+	andn	%o5, MCCR_ICACHE_EN, %o4		! Turn off the I$
+	stxa	%o4, [%g0] ASI_MCCR
+	flush 	%g0
+1:
+	stxa	%g0, [%o1] ASI_ICACHE_TAG
+	membar	#Sync
+	brnz,pt	%o1, 1b
+	 sub	%o1, %o2, %o1
+	stxa	%o5, [%g0] ASI_MCCR			! Restore the I$
+	flush 	%g0
+	retl
+	 wrpr	%o3, %pstate
+
 /*
- * dcache_flush_page(paddr_t pa)
+ * dcache_flush_page_us(paddr_t pa)
+ * dcache_flush_page_usiii(paddr_t pa)
  *
  * Clear one page from D$.
  *
  */
 	.align 8
-ENTRY(dcache_flush_page)
+ENTRY(dcache_flush_page_us)
 #ifndef _LP64
 	COMBINE(%o0, %o1, %o0)
 #endif
@@ -5374,7 +5404,6 @@
 	bne,pt	%xcc, 1b
 	 membar	#LoadStore
 
-dlflush3:
 	stxa	%g0, [%o0] ASI_DCACHE_TAG
 	ba,pt	%icc, 1b
 	 membar	#StoreLoad
@@ -5385,15 +5414,38 @@
 	retl
 	 membar	#Sync
 
+	.align 8
+ENTRY(dcache_flush_page_usiii)
+#ifndef _LP64
+	COMBINE(%o0, %o1, %o0)
+#endif
+	set	NBPG, %o1
+	sethi	%hi(dcache_line_size), %o2
+	add	%o0, %o1, %o1	! end address
+	ld	[%o2 + %lo(dcache_line_size)], %o2
+
+1:
+	stxa	%g0, [%o0] ASI_DCACHE_INVALIDATE
+	add	%o0, %o2, %o0
+	cmp	%o0, %o1
+	bl,pt	%xcc, 1b
+	 nop
+
+	sethi	%hi(KERNBASE), %o5
+	flush	%o5
+	retl
+	 membar	#Sync
+
 /*
- *	cache_flush_phys(paddr_t, psize_t, int);
+ *	cache_flush_phys_us(paddr_t, psize_t, int);
+ *	cache_flush_phys_usiii(paddr_t, psize_t, int);
  *
  *	Clear a set of paddrs from the D$, I$ and if param3 is
  *	non-zero, E$.  (E$ is not supported yet).
  */
 
 	.align 8
-ENTRY(cache_flush_phys)
+ENTRY(cache_flush_phys_us)
 #ifndef _LP64
 	COMBINE(%o0, %o1, %o0)
 	COMBINE(%o2, %o3, %o1)
@@ -5433,13 +5485,9 @@
 	 nop
 
 	membar	#LoadStore
-dlflush4:
 	stxa	%g0, [%o4] ASI_DCACHE_TAG ! Just right
 	membar	#Sync
 2:
-nop_on_us_1:
-	b	3f
-	 nop					! XXXMRG put something useful here?
 	ldda	[%o4] ASI_ICACHE_TAG, %g0	! Tag goes in %g1
 	sllx	%g1, 40-35, %g1			! Shift I$ tag into place
 	and	%g1, %o2, %g1			! Mask out trash
@@ -5457,10 +5505,37 @@
 
 	sethi	%hi(KERNBASE), %o5
 	flush	%o5
-	membar	#Sync
 	retl
+	 membar	#Sync
+
+	.align 8
+ENTRY(cache_flush_phys_usiii)
+#ifndef _LP64
+	COMBINE(%o0, %o1, %o0)
+	COMBINE(%o2, %o3, %o1)
+	mov	%o4, %o2
+#endif
+#ifdef DEBUG
+	tst	%o2		! Want to clear E$?
+	tnz	1		! Error!
+#endif
+	add	%o0, %o1, %o1	! End PA
+	sethi	%hi(dcache_line_size), %o3
+	ld	[%o3 + %lo(dcache_line_size)], %o3
+	sethi	%hi(KERNBASE), %o5
+1:
+	stxa	%g0, [%o0] ASI_DCACHE_INVALIDATE
+	add	%o0, %o3, %o0
+	cmp	%o0, %o1
+	bl,pt	%xcc, 1b
 	 nop
 
+	/* don't need to flush the I$ on cheetah */
+
+	flush	%o5
+	retl
+	 membar	#Sync
+
 #ifdef COMPAT_16
 #ifdef _LP64
 /*
@@ -9694,16 +9769,3 @@
 	.comm	_C_LABEL(trapdebug), 4
 	.comm	_C_LABEL(pmapdebug), 4
 #endif
-
-	.globl  _C_LABEL(dlflush_start)
-_C_LABEL(dlflush_start):
-	POINTER	dlflush1
-	POINTER	dlflush2
-	POINTER	dlflush3
-	POINTER	dlflush4
-	POINTER	0
-
-	.globl  _C_LABEL(nop_on_us_1_start)
-_C_LABEL(nop_on_us_1_start):
-	POINTER	nop_on_us_1
-	POINTER	0

Reply via email to