[BACK]Return to cache.c CVS log [TXT][DIR] Up to [local] / sys / arch / sparc / sparc

Annotation of sys/arch/sparc/sparc/cache.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: cache.c,v 1.18 2007/01/22 19:39:33 miod Exp $ */
                      2: /*     $NetBSD: cache.c,v 1.34 1997/09/26 22:17:23 pk Exp $    */
                      3:
                      4: /*
                      5:  * Copyright (c) 1996
                      6:  *     The President and Fellows of Harvard College. All rights reserved.
                      7:  * Copyright (c) 1992, 1993
                      8:  *     The Regents of the University of California.  All rights reserved.
                      9:  *
                     10:  * This software was developed by the Computer Systems Engineering group
                     11:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
                     12:  * contributed to Berkeley.
                     13:  *
                     14:  * All advertising materials mentioning features or use of this software
                     15:  * must display the following acknowledgement:
                     16:  *     This product includes software developed by Harvard University.
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Lawrence Berkeley Laboratory.
                     19:  *
                     20:  * Redistribution and use in source and binary forms, with or without
                     21:  * modification, are permitted provided that the following conditions
                     22:  * are met:
                     23:  *
                     24:  * 1. Redistributions of source code must retain the above copyright
                     25:  *    notice, this list of conditions and the following disclaimer.
                     26:  * 2. Redistributions in binary form must reproduce the above copyright
                     27:  *    notice, this list of conditions and the following disclaimer in the
                     28:  *    documentation and/or other materials provided with the distribution.
                     29:  * 3. All advertising materials mentioning features or use of this software
                     30:  *    must display the following acknowledgement:
                     31:  *     This product includes software developed by Aaron Brown and
                     32:  *     Harvard University.
                     33:  *     This product includes software developed by the University of
                     34:  *     California, Berkeley and its contributors.
                     35:  * 4. Neither the name of the University nor the names of its contributors
                     36:  *    may be used to endorse or promote products derived from this software
                     37:  *    without specific prior written permission.
                     38:  *
                     39:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     40:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     41:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     42:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     43:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     44:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     45:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     46:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     47:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     48:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     49:  * SUCH DAMAGE.
                     50:  *
                     51:  *     @(#)cache.c     8.2 (Berkeley) 10/30/93
                     52:  *
                     53:  */
                     54:
                     55: /*
                     56:  * Cache routines.
                     57:  *
                     58:  * TODO:
                     59:  *     - rework range flush
                     60:  */
                     61:
                     62: #include <sys/param.h>
                     63: #include <sys/systm.h>
                     64:
                     65: #include <uvm/uvm_extern.h>
                     66:
                     67: #include <machine/ctlreg.h>
                     68:
                     69: #include <sparc/sparc/asm.h>
                     70: #include <sparc/sparc/cache.h>
                     71: #include <sparc/sparc/cpuvar.h>
                     72:
                     73: #if defined(solbourne)
                     74: #include <machine/idt.h>
                     75: #include <machine/kap.h>
                     76: #endif
                     77:
                     78: struct cachestats cachestats;
                     79:
                     80: int cache_alias_dist;          /* Cache anti-aliasing constants */
                     81: int cache_alias_bits;
                     82:
                     83: /*
                     84:  * Enable the cache.
                     85:  * We need to clear out the valid bits first.
                     86:  */
                     87: void
                     88: sun4_cache_enable()
                     89: {
                     90:        u_int i, lim, ls, ts;
                     91:
                     92:        cache_alias_bits = CPU_ISSUN4
                     93:                                ? CACHE_ALIAS_BITS_SUN4
                     94:                                : CACHE_ALIAS_BITS_SUN4C;
                     95:        cache_alias_dist = CPU_ISSUN4
                     96:                                ? CACHE_ALIAS_DIST_SUN4
                     97:                                : CACHE_ALIAS_DIST_SUN4C;
                     98:
                     99:        ls = CACHEINFO.c_linesize;
                    100:        ts = CACHEINFO.c_totalsize;
                    101:
                    102:        for (i = AC_CACHETAGS, lim = i + ts; i < lim; i += ls)
                    103:                sta(i, ASI_CONTROL, 0);
                    104:
                    105:        stba(AC_SYSENABLE, ASI_CONTROL,
                    106:             lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_CACHE);
                    107:        CACHEINFO.c_enabled = 1;
                    108:
                    109:        printf("cache enabled\n");
                    110:
                    111: #ifdef notyet
                    112:        if (cpuinfo.flags & SUN4_IOCACHE) {
                    113:                stba(AC_SYSENABLE, ASI_CONTROL,
                    114:                     lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_IOCACHE);
                    115:                printf("iocache enabled\n");
                    116:        }
                    117: #endif
                    118: }
                    119:
                    120: #if defined(SUN4M)
                    121: void
                    122: ms1_cache_enable()
                    123: {
                    124:        u_int pcr;
                    125:
                    126:        cache_alias_dist = max(
                    127:            CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity,
                    128:            CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity);
                    129:        cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
                    130:
                    131:        pcr = lda(SRMMU_PCR, ASI_SRMMU);
                    132:
                    133:        /* We "flash-clear" the I/D caches. */
                    134:        if ((pcr & MS1_PCR_ICE) == 0)
                    135:                sta(0, ASI_ICACHECLR, 0);
                    136:        if ((pcr & MS1_PCR_DCE) == 0)
                    137:                sta(0, ASI_DCACHECLR, 0);
                    138:
                    139:        /* Turn on caches */
                    140:        sta(SRMMU_PCR, ASI_SRMMU, pcr | MS1_PCR_DCE | MS1_PCR_ICE);
                    141:
                    142:        CACHEINFO.c_enabled = CACHEINFO.dc_enabled = 1;
                    143:
                    144:        /*
                    145:         * When zeroing or copying pages, there might still be entries in
                    146:         * the cache, since we don't flush pages from the cache when
                    147:         * unmapping them (`vactype' is VAC_NONE).  Fortunately, the
                    148:         * MS1 cache is write-through and not write-allocate, so we can
                    149:         * use cacheable accesses while not displacing cache lines.
                    150:         */
                    151:        cpuinfo.flags |= CPUFLG_CACHE_MANDATORY;
                    152:
                    153:        printf("cache enabled\n");
                    154: }
                    155:
                    156: void
                    157: viking_cache_enable()
                    158: {
                    159:        u_int pcr;
                    160:
                    161:        cache_alias_dist = max(
                    162:                CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity,
                    163:                CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity);
                    164:        cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
                    165:
                    166:        pcr = lda(SRMMU_PCR, ASI_SRMMU);
                    167:
                    168:        if ((pcr & VIKING_PCR_ICE) == 0) {
                    169:                /* I-cache not on; "flash-clear" it now. */
                    170:                sta(0x80000000, ASI_ICACHECLR, 0);      /* Unlock */
                    171:                sta(0, ASI_ICACHECLR, 0);               /* clear */
                    172:        }
                    173:        if ((pcr & VIKING_PCR_DCE) == 0) {
                    174:                /* D-cache not on: "flash-clear" it. */
                    175:                sta(0x80000000, ASI_DCACHECLR, 0);
                    176:                sta(0, ASI_DCACHECLR, 0);
                    177:        }
                    178:
                    179:        /* Turn on caches via MMU */
                    180:        sta(SRMMU_PCR, ASI_SRMMU, pcr | VIKING_PCR_DCE | VIKING_PCR_ICE);
                    181:
                    182:        CACHEINFO.c_enabled = CACHEINFO.dc_enabled = 1;
                    183:
                    184:        /* Now turn on MultiCache if it exists */
                    185:        if (cpuinfo.mxcc && CACHEINFO.ec_totalsize > 0) {
                    186:                /* Multicache controller */
                    187:                stda(MXCC_ENABLE_ADDR, ASI_CONTROL,
                    188:                     ldda(MXCC_ENABLE_ADDR, ASI_CONTROL) |
                    189:                     (u_int64_t)MXCC_ENABLE_BIT);
                    190:                cpuinfo.flags |= CPUFLG_CACHEPAGETABLES; /* Ok to cache PTEs */
                    191:                CACHEINFO.ec_enabled = 1;
                    192:        }
                    193:        printf("cache enabled\n");
                    194: }
                    195:
                    196: void
                    197: hypersparc_cache_enable()
                    198: {
                    199:        int i, ls, ts;
                    200:        u_int pcr, v;
                    201:        extern u_long dvma_cachealign;
                    202:
                    203:        ls = CACHEINFO.c_linesize;
                    204:        ts = CACHEINFO.c_totalsize;
                    205:
                    206:        pcr = lda(SRMMU_PCR, ASI_SRMMU);
                    207:
                    208:        /*
                    209:         * Setup the anti-aliasing constants and DVMA alignment constraint.
                    210:         */
                    211:        cache_alias_dist = CACHEINFO.c_totalsize;
                    212:        cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
                    213:        dvma_cachealign = cache_alias_dist;
                    214:
                    215:        /* Now reset cache tag memory if cache not yet enabled */
                    216:        if ((pcr & HYPERSPARC_PCR_CE) == 0)
                    217:                for (i = 0; i < ts; i += ls) {
                    218:                        sta(i, ASI_DCACHETAG, 0);
                    219:                        while (lda(i, ASI_DCACHETAG))
                    220:                                sta(i, ASI_DCACHETAG, 0);
                    221:                }
                    222:
                    223:        pcr &= ~(HYPERSPARC_PCR_CE | HYPERSPARC_PCR_CM);
                    224:
                    225:        hypersparc_cache_flush_all();
                    226:
                    227:        pcr |= HYPERSPARC_PCR_CE;
                    228:        if (CACHEINFO.c_vactype == VAC_WRITEBACK)
                    229:                pcr |= HYPERSPARC_PCR_CM;
                    230:
                    231:        sta(SRMMU_PCR, ASI_SRMMU, pcr);
                    232:        CACHEINFO.c_enabled = 1;
                    233:
                    234:        /* XXX: should add support */
                    235:        if (CACHEINFO.c_hwflush)
                    236:                panic("cache_enable: can't handle 4M with hw-flush cache");
                    237:
                    238: #ifdef notyet
                    239:        /*
                    240:         * Enable instruction cache and, on single-processor machines,
                    241:         * disable `Unimplemented Flush Traps'.
                    242:         */
                    243:        v = HYPERSPARC_ICCR_ICE | (ncpu == 1 ? HYPERSPARC_ICCR_FTD : 0);
                    244: #else
                    245:        v = HYPERSPARC_ICCR_FTD | HYPERSPARC_ICCR_ICE;
                    246: #endif
                    247:        wrasr(v, HYPERSPARC_ASRNUM_ICCR);
                    248:
                    249:        printf("cache enabled\n");
                    250: }
                    251:
                    252: void
                    253: swift_cache_enable()
                    254: {
                    255:        int i, ls, ts;
                    256:        u_int pcr;
                    257:
                    258:        cache_alias_dist = max(
                    259:                CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity,
                    260:                CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity);
                    261:        cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
                    262:
                    263:        pcr = lda(SRMMU_PCR, ASI_SRMMU);
                    264:        pcr |= (SWIFT_PCR_ICE | SWIFT_PCR_DCE);
                    265:        sta(SRMMU_PCR, ASI_SRMMU, pcr);
                    266:
                    267:        /* Now reset cache tag memory if cache not yet enabled */
                    268:        ls = CACHEINFO.ic_linesize;
                    269:        ts = CACHEINFO.ic_totalsize;
                    270:        if ((pcr & SWIFT_PCR_ICE) == 0)
                    271:                for (i = 0; i < ts; i += ls)
                    272:                        sta(i, ASI_ICACHETAG, 0);
                    273:
                    274:        ls = CACHEINFO.dc_linesize;
                    275:        ts = CACHEINFO.dc_totalsize;
                    276:        if ((pcr & SWIFT_PCR_DCE) == 0)
                    277:                for (i = 0; i < ts; i += ls) {
                    278:                        sta(i, ASI_DCACHETAG, 0);
                    279:                        while (lda(i, ASI_DCACHETAG))
                    280:                                sta(i, ASI_DCACHETAG, 0);
                    281:                }
                    282:
                    283:        CACHEINFO.c_enabled = 1;
                    284:        printf("cache enabled\n");
                    285: }
                    286:
                    287: void
                    288: cypress_cache_enable()
                    289: {
                    290:        int i, ls, ts;
                    291:        u_int pcr;
                    292:
                    293:        cache_alias_dist = CACHEINFO.c_totalsize;
                    294:        cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
                    295:
                    296:        pcr = lda(SRMMU_PCR, ASI_SRMMU);
                    297:        pcr &= ~(CYPRESS_PCR_CE | CYPRESS_PCR_CM);
                    298:
                    299:        /* Now reset cache tag memory if cache not yet enabled */
                    300:        ls = CACHEINFO.c_linesize;
                    301:        ts = CACHEINFO.c_totalsize;
                    302:        if ((pcr & CYPRESS_PCR_CE) == 0)
                    303:                for (i = 0; i < ts; i += ls) {
                    304:                        sta(i, ASI_DCACHETAG, 0);
                    305:                        while (lda(i, ASI_DCACHETAG))
                    306:                                sta(i, ASI_DCACHETAG, 0);
                    307:                }
                    308:
                    309:        pcr |= CYPRESS_PCR_CE;
                    310:
                    311: #if 1
                    312:        pcr &= ~CYPRESS_PCR_CM;         /* XXX Disable write-back mode */
                    313: #else
                    314:        /* If put in write-back mode, turn it on */
                    315:        if (CACHEINFO.c_vactype == VAC_WRITEBACK)
                    316:                pcr |= CYPRESS_PCR_CM;
                    317: #endif
                    318:
                    319:        sta(SRMMU_PCR, ASI_SRMMU, pcr);
                    320:        CACHEINFO.c_enabled = 1;
                    321:        printf("cache enabled\n");
                    322: }
                    323:
                    324: void
                    325: turbosparc_cache_enable()
                    326: {
                    327:        int i, ls, ts;
                    328:        u_int pcr, pcf;
                    329:
                    330:        cache_alias_dist = max(
                    331:                CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity,
                    332:                CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity);
                    333:        cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
                    334:
                    335:        pcr = lda(SRMMU_PCR, ASI_SRMMU);
                    336:
                    337:        /* Now reset cache tag memory if cache not yet enabled */
                    338:        ls = CACHEINFO.ic_linesize;
                    339:        ts = CACHEINFO.ic_totalsize;
                    340:        if ((pcr & TURBOSPARC_PCR_ICE) == 0)
                    341:                for (i = 0; i < ts; i += ls)
                    342:                        sta(i, ASI_ICACHETAG, 0);
                    343:
                    344:        ls = CACHEINFO.dc_linesize;
                    345:        ts = CACHEINFO.dc_totalsize;
                    346:        if ((pcr & TURBOSPARC_PCR_DCE) == 0)
                    347:                for (i = 0; i < ts; i += ls) {
                    348:                        sta(i, ASI_DCACHETAG, 0);
                    349:                        while (lda(i, ASI_DCACHETAG))
                    350:                                sta(i, ASI_DCACHETAG, 0);
                    351:                }
                    352:
                    353:        pcr |= (TURBOSPARC_PCR_ICE | TURBOSPARC_PCR_DCE);
                    354:        sta(SRMMU_PCR, ASI_SRMMU, pcr);
                    355:
                    356:        pcf = lda(SRMMU_PCFG, ASI_SRMMU);
                    357:        if (pcf & TURBOSPARC_PCFG_SNP)
                    358:                printf("DVMA coherent ");
                    359:
                    360:        CACHEINFO.c_enabled = 1;
                    361:        printf("cache enabled\n");
                    362: }
                    363: #endif /* defined(SUN4M) */
                    364:
                    365: #if defined(SUN4) || defined(SUN4C)
                    366: /*
                    367:  * Flush the current context from the cache.
                    368:  *
                    369:  * This is done by writing to each cache line in the `flush context'
                    370:  * address space (or, for hardware flush, once to each page in the
                    371:  * hardware flush space, for all cache pages).
                    372:  */
                    373: void
                    374: sun4_vcache_flush_context()
                    375: {
                    376:        char *p;
                    377:        int i, ls;
                    378:
                    379:        cachestats.cs_ncxflush++;
                    380:        p = (char *)0;  /* addresses 0..cacheinfo.c_totalsize will do fine */
                    381:        if (CACHEINFO.c_hwflush) {
                    382:                ls = NBPG;
                    383:                i = CACHEINFO.c_totalsize >> PGSHIFT;
                    384:                for (; --i >= 0; p += ls)
                    385:                        sta(p, ASI_HWFLUSHCTX, 0);
                    386:        } else {
                    387:                ls = CACHEINFO.c_linesize;
                    388:                i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
                    389:                for (; --i >= 0; p += ls)
                    390:                        sta(p, ASI_FLUSHCTX, 0);
                    391:        }
                    392: }
                    393:
                    394: /*
                    395:  * Flush the given virtual region from the cache.
                    396:  *
                    397:  * This is also done by writing to each cache line, except that
                    398:  * now the addresses must include the virtual region number, and
                    399:  * we use the `flush region' space.
                    400:  *
                    401:  * This function is only called on sun4's with 3-level MMUs; there's
                    402:  * no hw-flush space.
                    403:  */
                    404: void
                    405: sun4_vcache_flush_region(vreg)
                    406:        int vreg;
                    407: {
                    408:        int i, ls;
                    409:        char *p;
                    410:
                    411:        cachestats.cs_nrgflush++;
                    412:        p = (char *)VRTOVA(vreg);       /* reg..reg+sz rather than 0..sz */
                    413:        ls = CACHEINFO.c_linesize;
                    414:        i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
                    415:        for (; --i >= 0; p += ls)
                    416:                sta(p, ASI_FLUSHREG, 0);
                    417: }
                    418:
                    419: /*
                    420:  * Flush the given virtual segment from the cache.
                    421:  *
                    422:  * This is also done by writing to each cache line, except that
                    423:  * now the addresses must include the virtual segment number, and
                    424:  * we use the `flush segment' space.
                    425:  *
                    426:  * Again, for hardware, we just write each page (in hw-flush space).
                    427:  */
                    428: void
                    429: sun4_vcache_flush_segment(vreg, vseg)
                    430:        int vreg, vseg;
                    431: {
                    432:        int i, ls;
                    433:        char *p;
                    434:
                    435:        cachestats.cs_nsgflush++;
                    436:        p = (char *)VSTOVA(vreg, vseg); /* seg..seg+sz rather than 0..sz */
                    437:        if (CACHEINFO.c_hwflush) {
                    438:                ls = NBPG;
                    439:                i = CACHEINFO.c_totalsize >> PGSHIFT;
                    440:                for (; --i >= 0; p += ls)
                    441:                        sta(p, ASI_HWFLUSHSEG, 0);
                    442:        } else {
                    443:                ls = CACHEINFO.c_linesize;
                    444:                i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
                    445:                for (; --i >= 0; p += ls)
                    446:                        sta(p, ASI_FLUSHSEG, 0);
                    447:        }
                    448: }
                    449:
                    450: /*
                    451:  * Flush the given virtual page from the cache.
                    452:  * (va is the actual address, and must be aligned on a page boundary.)
                    453:  * Again we write to each cache line.
                    454:  */
                    455: void
                    456: sun4_vcache_flush_page(va)
                    457:        int va;
                    458: {
                    459:        int i, ls;
                    460:        char *p;
                    461:
                    462: #ifdef DEBUG
                    463:        if (va & PGOFSET)
                    464:                panic("cache_flush_page: asked to flush misaligned va 0x%x",va);
                    465: #endif
                    466:
                    467:        cachestats.cs_npgflush++;
                    468:        p = (char *)va;
                    469:        if (CACHEINFO.c_hwflush)
                    470:                sta(p, ASI_HWFLUSHPG, 0);
                    471:        else {
                    472:                ls = CACHEINFO.c_linesize;
                    473:                i = NBPG >> CACHEINFO.c_l2linesize;
                    474:                for (; --i >= 0; p += ls)
                    475:                        sta(p, ASI_FLUSHPG, 0);
                    476:        }
                    477: }
                    478:
                    479: /*
                    480:  * Flush a range of virtual addresses (in the current context).
                    481:  * The first byte is at (base&~PGOFSET) and the last one is just
                    482:  * before byte (base+len).
                    483:  *
                    484:  * We choose the best of (context,segment,page) here.
                    485:  */
                    486:
                    487: #define CACHE_FLUSH_MAGIC      (CACHEINFO.c_totalsize / NBPG)
                    488:
                    489: void
                    490: sun4_cache_flush(base, len)
                    491:        caddr_t base;
                    492:        u_int len;
                    493: {
                    494:        int i, ls, baseoff;
                    495:        char *p;
                    496:
                    497:        if (CACHEINFO.c_vactype == VAC_NONE)
                    498:                return;
                    499:
                    500:        /*
                    501:         * Figure out how much must be flushed.
                    502:         *
                    503:         * If we need to do CACHE_FLUSH_MAGIC pages,  we can do a segment
                    504:         * in the same number of loop iterations.  We can also do the whole
                    505:         * region. If we need to do between 2 and NSEGRG, do the region.
                    506:         * If we need to do two or more regions, just go ahead and do the
                    507:         * whole context. This might not be ideal (e.g., fsck likes to do
                    508:         * 65536-byte reads, which might not necessarily be aligned).
                    509:         *
                    510:         * We could try to be sneaky here and use the direct mapping
                    511:         * to avoid flushing things `below' the start and `above' the
                    512:         * ending address (rather than rounding to whole pages and
                    513:         * segments), but I did not want to debug that now and it is
                    514:         * not clear it would help much.
                    515:         *
                    516:         * (XXX the magic number 16 is now wrong, must review policy)
                    517:         */
                    518:        baseoff = (int)base & PGOFSET;
                    519:        i = (baseoff + len + PGOFSET) >> PGSHIFT;
                    520:
                    521:        cachestats.cs_nraflush++;
                    522: #ifdef notyet
                    523:        cachestats.cs_ra[min(i, MAXCACHERANGE)]++;
                    524: #endif
                    525:
                    526:        if (i < CACHE_FLUSH_MAGIC) {
                    527:                /* cache_flush_page, for i pages */
                    528:                p = (char *)((int)base & ~baseoff);
                    529:                if (CACHEINFO.c_hwflush) {
                    530:                        for (; --i >= 0; p += NBPG)
                    531:                                sta(p, ASI_HWFLUSHPG, 0);
                    532:                } else {
                    533:                        ls = CACHEINFO.c_linesize;
                    534:                        i <<= PGSHIFT - CACHEINFO.c_l2linesize;
                    535:                        for (; --i >= 0; p += ls)
                    536:                                sta(p, ASI_FLUSHPG, 0);
                    537:                }
                    538:                return;
                    539:        }
                    540:        baseoff = (u_int)base & SGOFSET;
                    541:        i = (baseoff + len + SGOFSET) >> SGSHIFT;
                    542:        if (i == 1)
                    543:                sun4_vcache_flush_segment(VA_VREG(base), VA_VSEG(base));
                    544:        else {
                    545:                if (HASSUN4_MMU3L) {
                    546:                        baseoff = (u_int)base & RGOFSET;
                    547:                        i = (baseoff + len + RGOFSET) >> RGSHIFT;
                    548:                        if (i == 1)
                    549:                                sun4_vcache_flush_region(VA_VREG(base));
                    550:                        else
                    551:                                sun4_vcache_flush_context();
                    552:                } else
                    553:                        sun4_vcache_flush_context();
                    554:        }
                    555: }
                    556: #endif /* defined(SUN4) || defined(SUN4C) */
                    557:
                    558: #if defined(SUN4M)
                    559: /*
                    560:  * Flush the current context from the cache.
                    561:  *
                    562:  * This is done by writing to each cache line in the `flush context'
                    563:  * address space (or, for hardware flush, once to each page in the
                    564:  * hardware flush space, for all cache pages).
                    565:  */
                    566: void
                    567: srmmu_vcache_flush_context()
                    568: {
                    569:        char *p;
                    570:        int i, ls;
                    571:
                    572:        cachestats.cs_ncxflush++;
                    573:        p = (char *)0;  /* addresses 0..cacheinfo.c_totalsize will do fine */
                    574:        ls = CACHEINFO.c_linesize;
                    575:        i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
                    576:        for (; --i >= 0; p += ls)
                    577:                sta(p, ASI_IDCACHELFC, 0);
                    578: }
                    579:
                    580: /*
                    581:  * Flush the given virtual region from the cache.
                    582:  *
                    583:  * This is also done by writing to each cache line, except that
                    584:  * now the addresses must include the virtual region number, and
                    585:  * we use the `flush region' space.
                    586:  */
                    587: void
                    588: srmmu_vcache_flush_region(vreg)
                    589:        int vreg;
                    590: {
                    591:        int i, ls;
                    592:        char *p;
                    593:
                    594:        cachestats.cs_nrgflush++;
                    595:        p = (char *)VRTOVA(vreg);       /* reg..reg+sz rather than 0..sz */
                    596:        ls = CACHEINFO.c_linesize;
                    597:        i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
                    598:        for (; --i >= 0; p += ls)
                    599:                sta(p, ASI_IDCACHELFR, 0);
                    600: }
                    601:
                    602: /*
                    603:  * Flush the given virtual segment from the cache.
                    604:  *
                    605:  * This is also done by writing to each cache line, except that
                    606:  * now the addresses must include the virtual segment number, and
                    607:  * we use the `flush segment' space.
                    608:  *
                    609:  * Again, for hardware, we just write each page (in hw-flush space).
                    610:  */
                    611: void
                    612: srmmu_vcache_flush_segment(vreg, vseg)
                    613:        int vreg, vseg;
                    614: {
                    615:        int i, ls;
                    616:        char *p;
                    617:
                    618:        cachestats.cs_nsgflush++;
                    619:        p = (char *)VSTOVA(vreg, vseg); /* seg..seg+sz rather than 0..sz */
                    620:        ls = CACHEINFO.c_linesize;
                    621:        i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
                    622:        for (; --i >= 0; p += ls)
                    623:                sta(p, ASI_IDCACHELFS, 0);
                    624: }
                    625:
                    626: /*
                    627:  * Flush the given virtual page from the cache.
                    628:  * (va is the actual address, and must be aligned on a page boundary.)
                    629:  * Again we write to each cache line.
                    630:  */
                    631: void
                    632: srmmu_vcache_flush_page(va)
                    633:        int va;
                    634: {
                    635:        int i, ls;
                    636:        char *p;
                    637:
                    638: #ifdef DEBUG
                    639:        if (va & PGOFSET)
                    640:                panic("cache_flush_page: asked to flush misaligned va 0x%x",va);
                    641: #endif
                    642:
                    643:        cachestats.cs_npgflush++;
                    644:        p = (char *)va;
                    645:        ls = CACHEINFO.c_linesize;
                    646:        i = NBPG >> CACHEINFO.c_l2linesize;
                    647:        for (; --i >= 0; p += ls)
                    648:                sta(p, ASI_IDCACHELFP, 0);
                    649: }
                    650:
                    651: void
                    652: srmmu_cache_flush_all()
                    653: {
                    654:        srmmu_vcache_flush_context();
                    655: }
                    656:
                    657: /*
                    658:  * Flush a range of virtual addresses (in the current context).
                    659:  * The first byte is at (base&~PGOFSET) and the last one is just
                    660:  * before byte (base+len).
                    661:  *
                    662:  * We choose the best of (context,segment,page) here.
                    663:  */
                    664:
                    665: #define CACHE_FLUSH_MAGIC      (CACHEINFO.c_totalsize / NBPG)
                    666:
                    667: void
                    668: srmmu_cache_flush(base, len)
                    669:        caddr_t base;
                    670:        u_int len;
                    671: {
                    672:        int i, ls, baseoff;
                    673:        char *p;
                    674:
                    675:        /*
                    676:         * Figure out how much must be flushed.
                    677:         *
                    678:         * If we need to do CACHE_FLUSH_MAGIC pages,  we can do a segment
                    679:         * in the same number of loop iterations.  We can also do the whole
                    680:         * region. If we need to do between 2 and NSEGRG, do the region.
                    681:         * If we need to do two or more regions, just go ahead and do the
                    682:         * whole context. This might not be ideal (e.g., fsck likes to do
                    683:         * 65536-byte reads, which might not necessarily be aligned).
                    684:         *
                    685:         * We could try to be sneaky here and use the direct mapping
                    686:         * to avoid flushing things `below' the start and `above' the
                    687:         * ending address (rather than rounding to whole pages and
                    688:         * segments), but I did not want to debug that now and it is
                    689:         * not clear it would help much.
                    690:         *
                    691:         * (XXX the magic number 16 is now wrong, must review policy)
                    692:         */
                    693:        baseoff = (int)base & PGOFSET;
                    694:        i = (baseoff + len + PGOFSET) >> PGSHIFT;
                    695:
                    696:        cachestats.cs_nraflush++;
                    697: #ifdef notyet
                    698:        cachestats.cs_ra[min(i, MAXCACHERANGE)]++;
                    699: #endif
                    700:
                    701:        if (i < CACHE_FLUSH_MAGIC) {
                    702:                /* cache_flush_page, for i pages */
                    703:                p = (char *)((int)base & ~baseoff);
                    704:                ls = CACHEINFO.c_linesize;
                    705:                i <<= PGSHIFT - CACHEINFO.c_l2linesize;
                    706:                for (; --i >= 0; p += ls)
                    707:                        sta(p, ASI_IDCACHELFP, 0);
                    708:                return;
                    709:        }
                    710:        baseoff = (u_int)base & SGOFSET;
                    711:        i = (baseoff + len + SGOFSET) >> SGSHIFT;
                    712:        if (i == 1)
                    713:                srmmu_vcache_flush_segment(VA_VREG(base), VA_VSEG(base));
                    714:        else {
                    715:                baseoff = (u_int)base & RGOFSET;
                    716:                i = (baseoff + len + RGOFSET) >> RGSHIFT;
                    717:                if (i == 1)
                    718:                        srmmu_vcache_flush_region(VA_VREG(base));
                    719:                else
                    720:                        srmmu_vcache_flush_context();
                    721:        }
                    722: }
                    723:
                    724: #ifndef        MS1_CACHEFLUSH_MAGIC
                    725: #define        MS1_CACHEFLUSH_MAGIC    0 /* 48 */
                    726: #endif
                    727: void
                    728: ms1_cache_flush(base, len)
                    729:        caddr_t base;
                    730:        u_int len;
                    731: {
                    732:        /*
                    733:         * Although physically tagged, we still need to flush the
                    734:         * data cache after (if we have a write-through cache) or before
                    735:         * (in case of write-back caches) DMA operations.
                    736:         */
                    737: #if MS1_CACHEFLUSH_MAGIC != 0
                    738:        if (len <= MS1_CACHEFLUSH_MAGIC) {
                    739:                /*
                    740:                 * If the range to be flushed is sufficiently small
                    741:                 * invalidate the covered cache lines by hand.
                    742:                 *
                    743:                 * The MicroSPARC I has a direct-mapped virtually addressed
                    744:                 * physically tagged data cache which is organised as
                    745:                 * 128 lines of 16 bytes. Virtual address bits [4-10]
                    746:                 * select the cache line. The cache tags are accessed
                    747:                 * through the standard DCACHE control space using the
                    748:                 * same address bits as those used to select the cache
                    749:                 * line in the virtual address.
                    750:                 *
                    751:                 * Note: we don't bother to compare the actual tags
                    752:                 * since that would require looking up physical addresses.
                    753:                 *
                    754:                 * The format of the tags we read from ASI_DCACHE control
                    755:                 * space is:
                    756:                 *
                    757:                 * 31     27 26            11 10         1 0
                    758:                 * +--------+----------------+------------+-+
                    759:                 * |  xxx   |    PA[26-11]   |    xxx     |V|
                    760:                 * +--------+----------------+------------+-+
                    761:                 *
                    762:                 * PA: bits 11-26 of the physical address
                    763:                 * V:  line valid bit
                    764:                 */
                    765:                int tagaddr = ((u_int)base & 0x7f0);
                    766:
                    767:                len = roundup(len, 16);
                    768:                while (len != 0) {
                    769:                        int tag = lda(tagaddr, ASI_DCACHETAG);
                    770:                        if ((tag & 1) == 1) {
                    771:                                /* Mark this cache line invalid */
                    772:                                sta(tagaddr, ASI_DCACHETAG, 0);
                    773:                        }
                    774:                        len -= 16;
                    775:                        tagaddr = (tagaddr + 16) & 0x7f0;
                    776:                }
                    777:        } else
                    778: #endif
                    779:                /* Flush entire data cache */
                    780:                sta(0, ASI_DCACHECLR, 0);
                    781: }
                    782:
                    783: /*
                    784:  * Flush entire cache.
                    785:  */
                    786: void
                    787: ms1_cache_flush_all()
                    788: {
                    789:
                    790:        /* Flash-clear both caches */
                    791:        sta(0, ASI_ICACHECLR, 0);
                    792:        sta(0, ASI_DCACHECLR, 0);
                    793: }
                    794:
                    795: void
                    796: hypersparc_cache_flush_all()
                    797: {
                    798:
                    799:        srmmu_vcache_flush_context();
                    800:        /* Flush instruction cache */
                    801:        hypersparc_pure_vcache_flush();
                    802: }
                    803:
                    804: void
                    805: cypress_cache_flush_all()
                    806: {
                    807:        extern char kernel_text[];
                    808:        char *p;
                    809:        int i, ls;
                    810:
                    811:        /* Fill the cache with known read-only content */
                    812:        p = (char *)kernel_text;
                    813:        ls = CACHEINFO.c_linesize;
                    814:        i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
                    815:        for (; --i >= 0; p += ls)
                    816:                (*(volatile char *)p);
                    817: }
                    818:
                    819: void
                    820: viking_cache_flush(base, len)
                    821:        caddr_t base;
                    822:        u_int len;
                    823: {
                    824:        /*
                    825:         * Although physically tagged, we still need to flush the
                    826:         * data cache after (if we have a write-through cache) or before
                    827:         * (in case of write-back caches) DMA operations.
                    828:         */
                    829:
                    830: }
                    831:
                    832: void
                    833: viking_pcache_flush_line(va, pa)
                    834:        int va;
                    835:        int pa;
                    836: {
                    837:        /*
                    838:         * Flush cache line corresponding to virtual address `va'
                    839:         * which is mapped at physical address `pa'.
                    840:         */
                    841:        extern char etext[];
                    842:        static char *base;
                    843:        int i;
                    844:        char *v;
                    845:
                    846:        /*
                    847:         * Construct a virtual address that hits the same cache line
                    848:         * as PA, then read from 2*ASSOCIATIVITY-1 different physical
                    849:         * locations (all different from PA).
                    850:         */
                    851:
                    852: #if 0
                    853:        if (base == 0) {
                    854:                cshift = CACHEINFO.ic_l2linesize;
                    855:                csize = CACHEINFO.ic_nlines << cshift;
                    856:                cmask = csize - 1;
                    857:                base = (char *)roundup((int)etext, csize);
                    858:        }
                    859:
                    860:        v = base + (((va & cmask) >> cshift) << cshift);
                    861:        i = CACHEINFO.dc_associativity * 2 - 1;
                    862:
                    863:        while (i--) {
                    864:                (*(volatile int *)v);
                    865:                v += csize;
                    866:        }
                    867: #else
                    868: #define cshift 5                       /* CACHEINFO.ic_l2linesize */
                    869: #define csize  (128 << cshift)         /* CACHEINFO.ic_nlines << cshift */
                    870: #define cmask  (csize - 1)
                    871: #define cass   4                       /* CACHEINFO.dc_associativity */
                    872:
                    873:        if (base == 0)
                    874:                base = (char *)roundup((unsigned int)etext, csize);
                    875:
                    876:        v = base + (((pa & cmask) >> cshift) << cshift);
                    877:        i = 2 * cass - 1;
                    878:
                    879:        while (i--) {
                    880:                (*(volatile int *)v);
                    881:                v += csize;
                    882:        }
                    883: #undef cass
                    884: #undef cmask
                    885: #undef csize
                    886: #undef cshift
                    887: #endif
                    888: }
                    889:
                    890: void
                    891: srmmu_pcache_flush_line(va, pa)
                    892:        int va;
                    893:        int pa;
                    894: {
                    895:        /*
                    896:         * Flush cache line corresponding to virtual address `va'
                    897:         * which is mapped at physical address `pa'.
                    898:         */
                    899:        sta(va, ASI_IDCACHELFP, 0);
                    900: }
                    901: #endif /* SUN4M */
                    902:
                    903: #if defined(solbourne)
                    904: void
                    905: kap_cache_enable()
                    906: {
                    907:        kap_cache_flush(NULL, 0);
                    908:        sta(0, ASI_ICACHE_INVAL, 0);
                    909:
                    910:        sta(ICU_CONF, ASI_PHYS_IO,
                    911:            lda(ICU_CONF, ASI_PHYS_IO) & ~CONF_ICACHE_DISABLE);
                    912:        CACHEINFO.c_enabled = 1;
                    913:
                    914:        printf("cache enabled\n");
                    915: }
                    916:
                    917: void
                    918: kap_vcache_flush_context()
                    919: {
                    920:        kap_cache_flush(0, 0);
                    921:        sta(0, ASI_DCACHE_INVAL, 0);
                    922:        sta(0, ASI_ICACHE_INVAL, 0);
                    923: }
                    924:
                    925: void
                    926: kap_vcache_flush_page(va)
                    927:        int va;
                    928: {
                    929:        kap_cache_flush((caddr_t)va, PAGE_SIZE);
                    930: }
                    931:
                    932: void
                    933: kap_cache_flush(base, len)
                    934:        caddr_t base;
                    935:        u_int len;
                    936: {
                    937:        u_int line;
                    938:        u_int32_t mmcr;
                    939:
                    940:        /*
                    941:         * Due to the small size of the data cache and the fact that we
                    942:         * would be flushing 4 bytes by 4 bytes, it is faster to flush
                    943:         * the whole cache instead.
                    944:         */
                    945:
                    946:        mmcr = lda(0, ASI_MMCR) & ~(MMCR_DSET0 | MMCR_DSET1);
                    947:        /* flush bank 0 */
                    948:        sta(0, ASI_MMCR, mmcr | MMCR_DSET0);
                    949:        for (line = 0; line < DCACHE_LINE(DCACHE_LINES); line += DCACHE_INCR)
                    950:                (void)lda(line, ASI_DCACHE_FLUSH);
                    951:        /* flush bank 1 */
                    952:        sta(0, ASI_MMCR, mmcr | MMCR_DSET1);
                    953:        for (line = 0; line < DCACHE_LINE(DCACHE_LINES); line += DCACHE_INCR)
                    954:                (void)lda(line, ASI_DCACHE_FLUSH);
                    955: }
                    956:
                    957: #endif /* solbourne */

CVSweb