The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mips/mips/cache_mipsNN.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: cache_mipsNN.c,v 1.10 2005/12/24 20:07:19 perry Exp $  */
    2 
    3 /*
    4  * Copyright 2001 Wasabi Systems, Inc.
    5  * All rights reserved.
    6  *
    7  * Written by Jason R. Thorpe and Simon Burge for Wasabi Systems, Inc.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. All advertising materials mentioning features or use of this software
   18  *    must display the following acknowledgement:
   19  *      This product includes software developed for the NetBSD Project by
   20  *      Wasabi Systems, Inc.
   21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
   22  *    or promote products derived from this software without specific prior
   23  *    written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
   29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   35  * POSSIBILITY OF SUCH DAMAGE.
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __FBSDID("$FreeBSD: releng/8.0/sys/mips/mips/cache_mipsNN.c 178172 2008-04-13 07:27:37Z imp $");
   40 
   41 #include <sys/types.h>
   42 #include <sys/systm.h>
   43 #include <sys/param.h>
   44 
   45 #include <machine/cache.h>
   46 #include <machine/cache_r4k.h>
   47 #include <machine/cpuinfo.h>
   48 
   49 #define round_line16(x)         (((x) + 15) & ~15)
   50 #define trunc_line16(x)         ((x) & ~15)
   51 
   52 #define round_line32(x)         (((x) + 31) & ~31)
   53 #define trunc_line32(x)         ((x) & ~31)
   54 
   55 
   56 #ifdef SB1250_PASS1
   57 #define SYNC    __asm volatile("sync; sync")
   58 #else
   59 #define SYNC    __asm volatile("sync")
   60 #endif
   61 
   62 #ifdef TARGET_OCTEON
   63 #define SYNCI  mips_sync_icache();
   64 #else
   65 #define SYNCI
   66 #endif
   67 
   68 
   69 __asm(".set mips32");
   70 
   71 static int picache_size;
   72 static int picache_stride;
   73 static int picache_loopcount;
   74 static int picache_way_mask;
   75 static int pdcache_size;
   76 static int pdcache_stride;
   77 static int pdcache_loopcount;
   78 static int pdcache_way_mask;
   79 
   80 void
   81 mipsNN_cache_init(struct mips_cpuinfo * cpuinfo)
   82 {
   83         int flush_multiple_lines_per_way;
   84 
   85         flush_multiple_lines_per_way = cpuinfo->l1.ic_nsets * cpuinfo->l1.ic_linesize * cpuinfo->l1.ic_linesize > PAGE_SIZE;
   86         if (cpuinfo->icache_virtual) {
   87                 /*
   88                  * With a virtual Icache we don't need to flush
   89                  * multiples of the page size with index ops; we just
   90                  * need to flush one pages' worth.
   91                  */
   92                 flush_multiple_lines_per_way = 0;
   93         }
   94 
   95         if (flush_multiple_lines_per_way) {
   96                 picache_stride = PAGE_SIZE;
   97                 picache_loopcount = (cpuinfo->l1.ic_nsets * cpuinfo->l1.ic_linesize / PAGE_SIZE) *
   98                     cpuinfo->l1.ic_nways;
   99         } else {
  100                 picache_stride = cpuinfo->l1.ic_nsets * cpuinfo->l1.ic_linesize;
  101                 picache_loopcount = cpuinfo->l1.ic_nways;
  102         }
  103 
  104         if (cpuinfo->l1.dc_nsets * cpuinfo->l1.dc_linesize < PAGE_SIZE) {
  105                 pdcache_stride = cpuinfo->l1.dc_nsets * cpuinfo->l1.dc_linesize;
  106                 pdcache_loopcount = cpuinfo->l1.dc_nways;
  107         } else {
  108                 pdcache_stride = PAGE_SIZE;
  109                 pdcache_loopcount = (cpuinfo->l1.dc_nsets * cpuinfo->l1.dc_linesize / PAGE_SIZE) *
  110                     cpuinfo->l1.dc_nways;
  111         }
  112         picache_size = cpuinfo->l1.ic_size;
  113         picache_way_mask = cpuinfo->l1.ic_nways - 1;
  114         pdcache_size = cpuinfo->l1.dc_size;
  115         pdcache_way_mask = cpuinfo->l1.dc_nways - 1;
  116 #define CACHE_DEBUG
  117 #ifdef CACHE_DEBUG
  118         if (cpuinfo->icache_virtual)
  119                 printf("  icache is virtual\n");
  120         printf("  picache_stride    = %d\n", picache_stride);
  121         printf("  picache_loopcount = %d\n", picache_loopcount);
  122         printf("  pdcache_stride    = %d\n", pdcache_stride);
  123         printf("  pdcache_loopcount = %d\n", pdcache_loopcount);
  124 #endif
  125 }
  126 
  127 void
  128 mipsNN_icache_sync_all_16(void)
  129 {
  130         vm_offset_t va, eva;
  131 
  132         va = MIPS_PHYS_TO_KSEG0(0);
  133         eva = va + picache_size;
  134 
  135         /*
  136          * Since we're hitting the whole thing, we don't have to
  137          * worry about the N different "ways".
  138          */
  139 
  140         mips_intern_dcache_wbinv_all();
  141 
  142         while (va < eva) {
  143                 cache_r4k_op_32lines_16(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
  144                 va += (32 * 16);
  145         }
  146 
  147         SYNC;
  148 }
  149 
  150 void
  151 mipsNN_icache_sync_all_32(void)
  152 {
  153         vm_offset_t va, eva;
  154 
  155         va = MIPS_PHYS_TO_KSEG0(0);
  156         eva = va + picache_size;
  157 
  158         /*
  159          * Since we're hitting the whole thing, we don't have to
  160          * worry about the N different "ways".
  161          */
  162 
  163         mips_intern_dcache_wbinv_all();
  164 
  165         while (va < eva) {
  166                 cache_r4k_op_32lines_32(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
  167                 va += (32 * 32);
  168         }
  169 
  170         SYNC;
  171 }
  172 
  173 void
  174 mipsNN_icache_sync_range_16(vm_offset_t va, vm_size_t size)
  175 {
  176         vm_offset_t eva;
  177 
  178         eva = round_line16(va + size);
  179         va = trunc_line16(va);
  180 
  181         mips_intern_dcache_wb_range(va, (eva - va));
  182 
  183         while ((eva - va) >= (32 * 16)) {
  184                 cache_r4k_op_32lines_16(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
  185                 va += (32 * 16);
  186         }
  187 
  188         while (va < eva) {
  189                 cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
  190                 va += 16;
  191         }
  192 
  193         SYNC;
  194 }
  195 
  196 void
  197 mipsNN_icache_sync_range_32(vm_offset_t va, vm_size_t size)
  198 {
  199         vm_offset_t eva;
  200 
  201         eva = round_line32(va + size);
  202         va = trunc_line32(va);
  203 
  204         mips_intern_dcache_wb_range(va, (eva - va));
  205 
  206         while ((eva - va) >= (32 * 32)) {
  207                 cache_r4k_op_32lines_32(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
  208                 va += (32 * 32);
  209         }
  210 
  211         while (va < eva) {
  212                 cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
  213                 va += 32;
  214         }
  215 
  216         SYNC;
  217 }
  218 
  219 void
  220 mipsNN_icache_sync_range_index_16(vm_offset_t va, vm_size_t size)
  221 {
  222         unsigned int eva, tmpva;
  223         int i, stride, loopcount;
  224 
  225         /*
  226          * Since we're doing Index ops, we expect to not be able
  227          * to access the address we've been given.  So, get the
  228          * bits that determine the cache index, and make a KSEG0
  229          * address out of them.
  230          */
  231         va = MIPS_PHYS_TO_KSEG0(va & picache_way_mask);
  232 
  233         eva = round_line16(va + size);
  234         va = trunc_line16(va);
  235 
  236         /*
  237          * GCC generates better code in the loops if we reference local
  238          * copies of these global variables.
  239          */
  240         stride = picache_stride;
  241         loopcount = picache_loopcount;
  242 
  243         mips_intern_dcache_wbinv_range_index(va, (eva - va));
  244 
  245         while ((eva - va) >= (8 * 16)) {
  246                 tmpva = va;
  247                 for (i = 0; i < loopcount; i++, tmpva += stride)
  248                         cache_r4k_op_8lines_16(tmpva,
  249                             CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
  250                 va += 8 * 16;
  251         }
  252 
  253         while (va < eva) {
  254                 tmpva = va;
  255                 for (i = 0; i < loopcount; i++, tmpva += stride)
  256                         cache_op_r4k_line(tmpva,
  257                             CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
  258                 va += 16;
  259         }
  260 }
  261 
  262 void
  263 mipsNN_icache_sync_range_index_32(vm_offset_t va, vm_size_t size)
  264 {
  265         unsigned int eva, tmpva;
  266         int i, stride, loopcount;
  267 
  268         /*
  269          * Since we're doing Index ops, we expect to not be able
  270          * to access the address we've been given.  So, get the
  271          * bits that determine the cache index, and make a KSEG0
  272          * address out of them.
  273          */
  274         va = MIPS_PHYS_TO_KSEG0(va & picache_way_mask);
  275 
  276         eva = round_line32(va + size);
  277         va = trunc_line32(va);
  278 
  279         /*
  280          * GCC generates better code in the loops if we reference local
  281          * copies of these global variables.
  282          */
  283         stride = picache_stride;
  284         loopcount = picache_loopcount;
  285 
  286         mips_intern_dcache_wbinv_range_index(va, (eva - va));
  287 
  288         while ((eva - va) >= (8 * 32)) {
  289                 tmpva = va;
  290                 for (i = 0; i < loopcount; i++, tmpva += stride)
  291                         cache_r4k_op_8lines_32(tmpva,
  292                             CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
  293                 va += 8 * 32;
  294         }
  295 
  296         while (va < eva) {
  297                 tmpva = va;
  298                 for (i = 0; i < loopcount; i++, tmpva += stride)
  299                         cache_op_r4k_line(tmpva,
  300                             CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
  301                 va += 32;
  302         }
  303 }
  304 
  305 void
  306 mipsNN_pdcache_wbinv_all_16(void)
  307 {
  308         vm_offset_t va, eva;
  309 
  310         va = MIPS_PHYS_TO_KSEG0(0);
  311         eva = va + pdcache_size;
  312 
  313         /*
  314          * Since we're hitting the whole thing, we don't have to
  315          * worry about the N different "ways".
  316          */
  317 
  318         while (va < eva) {
  319                 cache_r4k_op_32lines_16(va,
  320                     CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
  321                 va += (32 * 16);
  322         }
  323 
  324         SYNC;
  325 }
  326 
  327 void
  328 mipsNN_pdcache_wbinv_all_32(void)
  329 {
  330         vm_offset_t va, eva;
  331 
  332         va = MIPS_PHYS_TO_KSEG0(0);
  333         eva = va + pdcache_size;
  334 
  335         /*
  336          * Since we're hitting the whole thing, we don't have to
  337          * worry about the N different "ways".
  338          */
  339 
  340         while (va < eva) {
  341                 cache_r4k_op_32lines_32(va,
  342                     CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
  343                 va += (32 * 32);
  344         }
  345 
  346         SYNC;
  347 }
  348 
  349 void
  350 mipsNN_pdcache_wbinv_range_16(vm_offset_t va, vm_size_t size)
  351 {
  352         vm_offset_t eva;
  353 
  354         eva = round_line16(va + size);
  355         va = trunc_line16(va);
  356 
  357         while ((eva - va) >= (32 * 16)) {
  358                 cache_r4k_op_32lines_16(va,
  359                     CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
  360                 va += (32 * 16);
  361         }
  362 
  363         while (va < eva) {
  364                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
  365                 va += 16;
  366         }
  367 
  368         SYNC;
  369 }
  370 
  371 void
  372 mipsNN_pdcache_wbinv_range_32(vm_offset_t va, vm_size_t size)
  373 {
  374         vm_offset_t eva;
  375 
  376         eva = round_line32(va + size);
  377         va = trunc_line32(va);
  378 
  379         while ((eva - va) >= (32 * 32)) {
  380                 cache_r4k_op_32lines_32(va,
  381                     CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
  382                 va += (32 * 32);
  383         }
  384 
  385         while (va < eva) {
  386                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
  387                 va += 32;
  388         }
  389 
  390         SYNC;
  391 }
  392 
  393 void
  394 mipsNN_pdcache_wbinv_range_index_16(vm_offset_t va, vm_size_t size)
  395 {
  396         unsigned int eva, tmpva;
  397         int i, stride, loopcount;
  398 
  399         /*
  400          * Since we're doing Index ops, we expect to not be able
  401          * to access the address we've been given.  So, get the
  402          * bits that determine the cache index, and make a KSEG0
  403          * address out of them.
  404          */
  405         va = MIPS_PHYS_TO_KSEG0(va & pdcache_way_mask);
  406 
  407         eva = round_line16(va + size);
  408         va = trunc_line16(va);
  409 
  410         /*
  411          * GCC generates better code in the loops if we reference local
  412          * copies of these global variables.
  413          */
  414         stride = pdcache_stride;
  415         loopcount = pdcache_loopcount;
  416 
  417         while ((eva - va) >= (8 * 16)) {
  418                 tmpva = va;
  419                 for (i = 0; i < loopcount; i++, tmpva += stride)
  420                         cache_r4k_op_8lines_16(tmpva,
  421                             CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
  422                 va += 8 * 16;
  423         }
  424 
  425         while (va < eva) {
  426                 tmpva = va;
  427                 for (i = 0; i < loopcount; i++, tmpva += stride)
  428                         cache_op_r4k_line(tmpva,
  429                             CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
  430                 va += 16;
  431         }
  432 }
  433 
  434 void
  435 mipsNN_pdcache_wbinv_range_index_32(vm_offset_t va, vm_size_t size)
  436 {
  437         unsigned int eva, tmpva;
  438         int i, stride, loopcount;
  439 
  440         /*
  441          * Since we're doing Index ops, we expect to not be able
  442          * to access the address we've been given.  So, get the
  443          * bits that determine the cache index, and make a KSEG0
  444          * address out of them.
  445          */
  446         va = MIPS_PHYS_TO_KSEG0(va & pdcache_way_mask);
  447 
  448         eva = round_line32(va + size);
  449         va = trunc_line32(va);
  450 
  451         /*
  452          * GCC generates better code in the loops if we reference local
  453          * copies of these global variables.
  454          */
  455         stride = pdcache_stride;
  456         loopcount = pdcache_loopcount;
  457 
  458         while ((eva - va) >= (8 * 32)) {
  459                 tmpva = va;
  460                 for (i = 0; i < loopcount; i++, tmpva += stride)
  461                         cache_r4k_op_8lines_32(tmpva,
  462                             CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
  463                 va += 8 * 32;
  464         }
  465 
  466         while (va < eva) {
  467                 tmpva = va;
  468                 for (i = 0; i < loopcount; i++, tmpva += stride)
  469                         cache_op_r4k_line(tmpva,
  470                             CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
  471                 va += 32;
  472         }
  473 }
  474  
  475 void
  476 mipsNN_pdcache_inv_range_16(vm_offset_t va, vm_size_t size)
  477 {
  478         vm_offset_t eva;
  479 
  480         eva = round_line16(va + size);
  481         va = trunc_line16(va);
  482 
  483         while ((eva - va) >= (32 * 16)) {
  484                 cache_r4k_op_32lines_16(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
  485                 va += (32 * 16);
  486         }
  487 
  488         while (va < eva) {
  489                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
  490                 va += 16;
  491         }
  492 
  493         SYNC;
  494 }
  495 
  496 void
  497 mipsNN_pdcache_inv_range_32(vm_offset_t va, vm_size_t size)
  498 {
  499         vm_offset_t eva;
  500 
  501         eva = round_line32(va + size);
  502         va = trunc_line32(va);
  503 
  504         while ((eva - va) >= (32 * 32)) {
  505                 cache_r4k_op_32lines_32(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
  506                 va += (32 * 32);
  507         }
  508 
  509         while (va < eva) {
  510                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
  511                 va += 32;
  512         }
  513 
  514         SYNC;
  515 }
  516 
  517 void
  518 mipsNN_pdcache_wb_range_16(vm_offset_t va, vm_size_t size)
  519 {
  520         vm_offset_t eva;
  521 
  522         eva = round_line16(va + size);
  523         va = trunc_line16(va);
  524 
  525         while ((eva - va) >= (32 * 16)) {
  526                 cache_r4k_op_32lines_16(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
  527                 va += (32 * 16);
  528         }
  529 
  530         while (va < eva) {
  531                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
  532                 va += 16;
  533         }
  534 
  535         SYNC;
  536 }
  537 
  538 void
  539 mipsNN_pdcache_wb_range_32(vm_offset_t va, vm_size_t size)
  540 {
  541         vm_offset_t eva;
  542 
  543         eva = round_line32(va + size);
  544         va = trunc_line32(va);
  545 
  546         while ((eva - va) >= (32 * 32)) {
  547                 cache_r4k_op_32lines_32(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
  548                 va += (32 * 32);
  549         }
  550 
  551         while (va < eva) {
  552                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
  553                 va += 32;
  554         }
  555 
  556         SYNC;
  557 }
  558 
  559 
  560 #ifdef TARGET_OCTEON
  561 
  562 void
  563 mipsNN_icache_sync_all_128(void)
  564 {
  565         SYNCI
  566 }
  567 
  568 void
  569 mipsNN_icache_sync_range_128(vm_offset_t va, vm_size_t size)
  570 {
  571         SYNC;
  572 }
  573 
  574 void
  575 mipsNN_icache_sync_range_index_128(vm_offset_t va, vm_size_t size)
  576 {
  577 }
  578 
  579 
  580 void
  581 mipsNN_pdcache_wbinv_all_128(void)
  582 {
  583 }
  584 
  585 
  586 void
  587 mipsNN_pdcache_wbinv_range_128(vm_offset_t va, vm_size_t size)
  588 {
  589         SYNC;
  590 }
  591 
  592 void
  593 mipsNN_pdcache_wbinv_range_index_128(vm_offset_t va, vm_size_t size)
  594 {
  595 }
  596 
  597 void
  598 mipsNN_pdcache_inv_range_128(vm_offset_t va, vm_size_t size)
  599 {
  600 }
  601 
  602 void
  603 mipsNN_pdcache_wb_range_128(vm_offset_t va, vm_size_t size)
  604 {
  605         SYNC;
  606 }
  607 
  608 #endif

Cache object: da56275bc2392e72379c2a134eb0f357


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.