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