BSD 4_4 release
[unix-history] / usr / src / sys / sparc / sparc / cache.c
index be94cce..2bd37da 100644 (file)
@@ -1,6 +1,6 @@
 /*
 /*
- * Copyright (c) 1992 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * This software was developed by the Computer Systems Engineering group
  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
  *
  * This software was developed by the Computer Systems Engineering group
  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
@@ -9,28 +9,58 @@
  * All advertising materials mentioning features or use of this software
  * must display the following acknowledgement:
  *     This product includes software developed by the University of
  * All advertising materials mentioning features or use of this software
  * must display the following acknowledgement:
  *     This product includes software developed by the University of
- *     California, Lawrence Berkeley Laboratories.
+ *     California, Lawrence Berkeley Laboratory.
  *
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  *
  *
- *     @(#)cache.c     7.3 (Berkeley) %G%
+ *     @(#)cache.c     8.1 (Berkeley) 7/19/93
  *
  *
- * from: $Header: cache.c,v 1.5 92/06/17 05:21:56 torek Exp $ (LBL)
+ * from: $Header: cache.c,v 1.10 93/07/18 06:23:51 torek Exp $ (LBL)
  */
 
 /*
  * Cache routines.
  */
 
 /*
  * Cache routines.
+ *
+ * TODO:
+ *     - rework range flush
  */
 
 #include <sys/param.h>
 
  */
 
 #include <sys/param.h>
 
+#include <machine/ctlreg.h>
 #include <machine/pte.h>
 
 #include <sparc/sparc/asm.h>
 #include <sparc/sparc/cache.h>
 #include <machine/pte.h>
 
 #include <sparc/sparc/asm.h>
 #include <sparc/sparc/cache.h>
-#include <sparc/sparc/ctlreg.h>
 
 enum vactype vactype;
 
 enum vactype vactype;
+struct cachestats cachestats;
 
 /*
  * Enable the cache.
 
 /*
  * Enable the cache.
@@ -39,14 +69,17 @@ enum vactype vactype;
 void
 cache_enable()
 {
 void
 cache_enable()
 {
-       register int i;
+       register u_int i, lim, ls;
 
 
-       for (i = AC_CACHETAGS; i < AC_CACHETAGS + 4096 * 4; i += 4)
+       i = AC_CACHETAGS;
+       lim = i + cacheinfo.c_totalsize;
+       ls = cacheinfo.c_linesize;
+       for (; i < lim; i += ls)
                sta(i, ASI_CONTROL, 0);
 
                sta(i, ASI_CONTROL, 0);
 
-       vactype = VAC_WRITETHROUGH;             /* XXX must be set per cpu */
        stba(AC_SYSENABLE, ASI_CONTROL,
            lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_CACHE);
        stba(AC_SYSENABLE, ASI_CONTROL,
            lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_CACHE);
+       cacheinfo.c_enabled = 1;
        printf("cache enabled\n");
 }
 
        printf("cache enabled\n");
 }
 
@@ -55,17 +88,28 @@ cache_enable()
  * Flush the current context from the cache.
  *
  * This is done by writing to each cache line in the `flush context'
  * Flush the current context from the cache.
  *
  * This is done by writing to each cache line in the `flush context'
- * address space.  Cache lines are 16 bytes, hence the declaration of `p'.
+ * address space (or, for hardware flush, once to each page in the
+ * hardware flush space, for all cache pages).
  */
 void
 cache_flush_context()
 {
  */
 void
 cache_flush_context()
 {
-       register int i;
-       register char (*p)[16];
-
-       p = 0;
-       for (i = 0x1000; --i >= 0; p++)
-               sta(p, ASI_FLUSHCTX, 0);
+       register char *p;
+       register int i, ls;
+
+       cachestats.cs_ncxflush++;
+       p = (char *)0;  /* addresses 0..cacheinfo.c_totalsize will do fine */
+       if (cacheinfo.c_hwflush) {
+               ls = NBPG;
+               i = cacheinfo.c_totalsize >> PGSHIFT;
+               for (; --i >= 0; p += ls)
+                       sta(p, ASI_HWFLUSHCTX, 0);
+       } else {
+               ls = cacheinfo.c_linesize;
+               i = cacheinfo.c_totalsize >> cacheinfo.c_l2linesize;
+               for (; --i >= 0; p += ls)
+                       sta(p, ASI_FLUSHCTX, 0);
+       }
 }
 
 /*
 }
 
 /*
@@ -74,17 +118,29 @@ cache_flush_context()
  * This is also done by writing to each cache line, except that
  * now the addresses must include the virtual segment number, and
  * we use the `flush segment' space.
  * This is also done by writing to each cache line, except that
  * now the addresses must include the virtual segment number, and
  * we use the `flush segment' space.
+ *
+ * Again, for hardware, we just write each page (in hw-flush space).
  */
 void
 cache_flush_segment(vseg)
        register int vseg;
 {
  */
 void
 cache_flush_segment(vseg)
        register int vseg;
 {
-       register int i;
-       register char (*p)[16];
-
-       p = (char (*)[16])VSTOVA(vseg);
-       for (i = 0x1000; --i >= 0; p++)
-               sta(p, ASI_FLUSHSEG, 0);
+       register int i, ls;
+       register char *p;
+
+       cachestats.cs_nsgflush++;
+       p = (char *)VSTOVA(vseg);       /* seg..seg+sz rather than 0..sz */
+       if (cacheinfo.c_hwflush) {
+               ls = NBPG;
+               i = cacheinfo.c_totalsize >> PGSHIFT;
+               for (; --i >= 0; p += ls)
+                       sta(p, ASI_HWFLUSHSEG, 0);
+       } else {
+               ls = cacheinfo.c_linesize;
+               i = cacheinfo.c_totalsize >> cacheinfo.c_l2linesize;
+               for (; --i >= 0; p += ls)
+                       sta(p, ASI_FLUSHSEG, 0);
+       }
 }
 
 /*
 }
 
 /*
@@ -96,12 +152,19 @@ void
 cache_flush_page(va)
        int va;
 {
 cache_flush_page(va)
        int va;
 {
-       register int i;
-       register char (*p)[16];
-
-       p = (char (*)[16])va;
-       for (i = NBPG >> 4; --i >= 0; p++)
-               sta(p, ASI_FLUSHPG, 0);
+       register int i, ls;
+       register char *p;
+
+       cachestats.cs_npgflush++;
+       p = (char *)va;
+       if (cacheinfo.c_hwflush)
+               sta(p, ASI_HWFLUSHPG, 0);
+       else {
+               ls = cacheinfo.c_linesize;
+               i = NBPG >> cacheinfo.c_l2linesize;
+               for (; --i >= 0; p += ls)
+                       sta(p, ASI_FLUSHPG, 0);
+       }
 }
 
 /*
 }
 
 /*
@@ -116,8 +179,8 @@ cache_flush(base, len)
        caddr_t base;
        register u_int len;
 {
        caddr_t base;
        register u_int len;
 {
-       register int i, baseoff;
-       register char (*p)[16];
+       register int i, ls, baseoff;
+       register char *p;
 
        /*
         * Figure out how much must be flushed.
 
        /*
         * Figure out how much must be flushed.
@@ -133,27 +196,35 @@ cache_flush(base, len)
         * ending address (rather than rounding to whole pages and
         * segments), but I did not want to debug that now and it is
         * not clear it would help much.
         * ending address (rather than rounding to whole pages and
         * segments), but I did not want to debug that now and it is
         * not clear it would help much.
+        *
+        * (XXX the magic number 16 is now wrong, must review policy)
         */
        baseoff = (int)base & PGOFSET;
        i = (baseoff + len + PGOFSET) >> PGSHIFT;
         */
        baseoff = (int)base & PGOFSET;
        i = (baseoff + len + PGOFSET) >> PGSHIFT;
+
+       cachestats.cs_nraflush++;
+#ifdef notyet
+       cachestats.cs_ra[min(i, MAXCACHERANGE)]++;
+#endif
+
        if (i <= 15) {
                /* cache_flush_page, for i pages */
        if (i <= 15) {
                /* cache_flush_page, for i pages */
-               p = (char (*)[16])((int)base & ~baseoff);
-               for (i <<= PGSHIFT - 4; --i >= 0; p++)
-                       sta(p, ASI_FLUSHPG, 0);
+               p = (char *)((int)base & ~baseoff);
+               if (cacheinfo.c_hwflush) {
+                       for (; --i >= 0; p += NBPG)
+                               sta(p, ASI_HWFLUSHPG, 0);
+               } else {
+                       ls = cacheinfo.c_linesize;
+                       i <<= PGSHIFT - cacheinfo.c_l2linesize;
+                       for (; --i >= 0; p += ls)
+                               sta(p, ASI_FLUSHPG, 0);
+               }
                return;
        }
        baseoff = (u_int)base & SGOFSET;
        i = (baseoff + len + SGOFSET) >> SGSHIFT;
                return;
        }
        baseoff = (u_int)base & SGOFSET;
        i = (baseoff + len + SGOFSET) >> SGSHIFT;
-       if (i == 1) {
-               /* cache_flush_segment */
-               p = (char (*)[16])((int)base & ~baseoff);
-               for (i = 0x1000; --i >= 0; p++)
-                       sta(p, ASI_FLUSHSEG, 0);
-               return;
-       }
-       /* cache_flush_context */
-       p = 0;
-       for (i = 0x1000; --i >= 0; p++)
-               sta(p, ASI_FLUSHCTX, 0);
+       if (i == 1)
+               cache_flush_segment(VA_VSEG(base));
+       else
+               cache_flush_context();
 }
 }