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 introduce a new patch_kernel() and ...



details:   https://anonhg.NetBSD.org/src/rev/c05b4f9d6f42
branches:  trunk
changeset: 752106:c05b4f9d6f42
user:      mrg <mrg%NetBSD.org@localhost>
date:      Mon Feb 15 07:56:51 2010 +0000

description:
introduce a new patch_kernel() and call it from the end of bootstrap().
use it to patch up TLB flush instructions that don't match for USI/II
and later.  we can also hopefully use this to make GENERIC.MP minimally
expensive on single CPU machines as well.

this is the last piece needed to get GENERIC/GENERIC.MP to boot on the
USIII* machines.

idea and some initial code from openbsd.

diffstat:

 sys/arch/sparc64/sparc64/autoconf.c |  64 +++++++++++++++++++++++++++++++++++-
 sys/arch/sparc64/sparc64/locore.s   |  49 +++++++++++++++++++---------
 2 files changed, 95 insertions(+), 18 deletions(-)

diffs (215 lines):

diff -r a92c12045d2f -r c05b4f9d6f42 sys/arch/sparc64/sparc64/autoconf.c
--- a/sys/arch/sparc64/sparc64/autoconf.c       Mon Feb 15 07:55:33 2010 +0000
+++ b/sys/arch/sparc64/sparc64/autoconf.c       Mon Feb 15 07:56:51 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: autoconf.c,v 1.166 2010/01/21 15:58:32 martin Exp $ */
+/*     $NetBSD: autoconf.c,v 1.167 2010/02/15 07:56:51 mrg Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.166 2010/01/21 15:58:32 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.167 2010/02/15 07:56:51 mrg Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -183,6 +183,7 @@
 #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);
@@ -334,6 +335,65 @@
 
        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 a92c12045d2f -r c05b4f9d6f42 sys/arch/sparc64/sparc64/locore.s
--- a/sys/arch/sparc64/sparc64/locore.s Mon Feb 15 07:55:33 2010 +0000
+++ b/sys/arch/sparc64/sparc64/locore.s Mon Feb 15 07:56:51 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.s,v 1.313 2010/02/13 22:29:55 mrg Exp $ */
+/*     $NetBSD: locore.s,v 1.314 2010/02/15 07:56:51 mrg Exp $ */
 
 /*
  * Copyright (c) 1996-2002 Eduardo Horvath
@@ -55,15 +55,13 @@
  *     @(#)locore.s    8.4 (Berkeley) 12/10/93
  */
 
-#ifndef CHEETAH
-#define        SPITFIRE
-#endif
 #undef PARANOID                /* Extremely expensive consistency checks */
 #undef NO_VCACHE               /* Map w/D$ disabled */
 #undef TRAPSTATS               /* Count traps */
 #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 */
@@ -195,12 +193,6 @@
 /* Give this real authority: reset the machine */
 #define NOTREACHED     sir
 
-#ifdef SPITFIRE
-#define ASI_DCACHE_TAG_OR_INV  ASI_DCACHE_TAG
-#else
-#define ASI_DCACHE_TAG_OR_INV  ASI_DCACHE_INVALIDATE
-#endif
-
 /*
  * This macro will clear out a cache line before an explicit
  * access to that location.  It's mostly used to make certain
@@ -209,6 +201,12 @@
  * 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; \
@@ -2317,7 +2315,8 @@
 1:
 #if 1
        /* Now we need to blast away the D$ to make sure we're in sync */
-       stxa    %g0, [%g7] ASI_DCACHE_TAG_OR_INV
+dlflush1:
+       stxa    %g0, [%g7] ASI_DCACHE_TAG
        brnz,pt %g7, 1b
         dec    8, %g7
 #endif
@@ -5313,7 +5312,8 @@
        andn    %o3, PSTATE_IE, %o4                     ! Turn off PSTATE_IE bit
        wrpr    %o4, 0, %pstate
 1:
-       stxa    %g0, [%o1] ASI_DCACHE_TAG_OR_INV
+dlflush2:
+       stxa    %g0, [%o1] ASI_DCACHE_TAG
        brnz,pt %o1, 1b
         dec    32, %o1
        sethi   %hi(KERNBASE), %o2
@@ -5386,7 +5386,8 @@
        bne,pt  %xcc, 1b
         membar #LoadStore
 
-       stxa    %g0, [%o0] ASI_DCACHE_TAG_OR_INV
+dlflush3:
+       stxa    %g0, [%o0] ASI_DCACHE_TAG
        ba,pt   %icc, 1b
         membar #StoreLoad
 2:
@@ -5444,9 +5445,13 @@
         nop
 
        membar  #LoadStore
-       stxa    %g0, [%o4] ASI_DCACHE_TAG_OR_INV ! Just right
+dlflush4:
+       stxa    %g0, [%o4] ASI_DCACHE_TAG ! Just right
+       membar  #Sync
 2:
-#ifdef SPITFIRE
+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,7 +5462,6 @@
         nop
        stxa    %g0, [%o4] ASI_ICACHE_TAG
 3:
-#endif
        membar  #StoreLoad
        dec     32, %o5
        brgz,pt %o5, 1b
@@ -9702,3 +9706,16 @@
        .comm   _C_LABEL(trapdebug), 4
        .comm   _C_LABEL(pmapdebug), 4
 #endif
+
+       .globl  _C_LABEL(dlflush_start)
+_C_LABEL(dlflush_start):
+       .xword  dlflush1
+       .xword  dlflush2
+       .xword  dlflush3
+       .xword  dlflush4
+       .xword  0
+
+       .globl  _C_LABEL(nop_on_us_1_start)
+_C_LABEL(nop_on_us_1_start):
+       .xword  nop_on_us_1
+       .xword  0



Home | Main Index | Thread Index | Old Index