Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/sparc64/sparc64 - store the maximum [id]cache size ...



details:   https://anonhg.NetBSD.org/src/rev/36f69339e658
branches:  trunk
changeset: 752283:36f69339e658
user:      mrg <mrg%NetBSD.org@localhost>
date:      Mon Feb 22 00:16:31 2010 +0000

description:
- 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.

diffstat:

 sys/arch/sparc64/sparc64/autoconf.c |   64 +-------------
 sys/arch/sparc64/sparc64/cache.h    |   44 ++++++++-
 sys/arch/sparc64/sparc64/cpu.c      |   36 +++++--
 sys/arch/sparc64/sparc64/locore.s   |  166 ++++++++++++++++++++++++-----------
 4 files changed, 180 insertions(+), 130 deletions(-)

diffs (truncated from 530 to 300 lines):

diff -r 398058e0b063 -r 36f69339e658 sys/arch/sparc64/sparc64/autoconf.c
--- a/sys/arch/sparc64/sparc64/autoconf.c       Sun Feb 21 21:16:09 2010 +0000
+++ b/sys/arch/sparc64/sparc64/autoconf.c       Mon Feb 22 00:16:31 2010 +0000
@@ -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
-                       }
-               }
-       }
 }
 
 /*
diff -r 398058e0b063 -r 36f69339e658 sys/arch/sparc64/sparc64/cache.h
--- a/sys/arch/sparc64/sparc64/cache.h  Sun Feb 21 21:16:09 2010 +0000
+++ b/sys/arch/sparc64/sparc64/cache.h  Mon Feb 22 00:16:31 2010 +0000
@@ -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);
+
+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);
+}
 
-/* Smallest E$ line size. */
+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;
diff -r 398058e0b063 -r 36f69339e658 sys/arch/sparc64/sparc64/cpu.c
--- a/sys/arch/sparc64/sparc64/cpu.c    Sun Feb 21 21:16:09 2010 +0000
+++ b/sys/arch/sparc64/sparc64/cpu.c    Mon Feb 22 00:16:31 2010 +0000
@@ -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 *
diff -r 398058e0b063 -r 36f69339e658 sys/arch/sparc64/sparc64/locore.s
--- a/sys/arch/sparc64/sparc64/locore.s Sun Feb 21 21:16:09 2010 +0000
+++ b/sys/arch/sparc64/sparc64/locore.s Mon Feb 22 00:16:31 2010 +0000
@@ -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



Home | Main Index | Thread Index | Old Index