Home | History | Annotate | Line # | Download | only in mips
      1 /*	$NetBSD: cache_r10k.c,v 1.8 2016/07/13 21:25:15 macallan Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2003 Takao Shinohara.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 /*
     28  * Copyright 2001 Wasabi Systems, Inc.
     29  * All rights reserved.
     30  *
     31  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
     32  *
     33  * Redistribution and use in source and binary forms, with or without
     34  * modification, are permitted provided that the following conditions
     35  * are met:
     36  * 1. Redistributions of source code must retain the above copyright
     37  *    notice, this list of conditions and the following disclaimer.
     38  * 2. Redistributions in binary form must reproduce the above copyright
     39  *    notice, this list of conditions and the following disclaimer in the
     40  *    documentation and/or other materials provided with the distribution.
     41  * 3. All advertising materials mentioning features or use of this software
     42  *    must display the following acknowledgement:
     43  *	This product includes software developed for the NetBSD Project by
     44  *	Wasabi Systems, Inc.
     45  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     46  *    or promote products derived from this software without specific prior
     47  *    written permission.
     48  *
     49  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     51  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     52  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     53  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     54  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     55  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     56  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     57  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     58  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     59  * POSSIBILITY OF SUCH DAMAGE.
     60  */
     61 
     62 #include <sys/param.h>
     63 
     64 #include <mips/cpuregs.h>
     65 #include <mips/cache.h>
     66 #include <mips/cache_r4k.h>
     67 #include <mips/cache_r10k.h>
     68 
     69 /*
     70  * Cache operations for R10000-style caches:
     71  *
     72  *	2-way, write-back
     73  *	primary cache: virtual index/physical tag
     74  *	secondary cache: physical index/physical tag
     75  */
     76 
     77 __asm(".set mips3");
     78 
     79 #define	round_line(x)	(((x) + 64 - 1) & ~(64 - 1))
     80 #define	trunc_line(x)	((x) & ~(64 - 1))
     81 
     82 void
     83 r10k_icache_sync_all(void)
     84 {
     85 	const struct mips_cache_info * const mci = &mips_cache_info;
     86 	vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
     87 	vaddr_t eva = va + mci->mci_picache_way_size;
     88 
     89 	mips_dcache_wbinv_all();
     90 
     91 	__asm volatile("sync");
     92 
     93 	while (va < eva) {
     94 		cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
     95 		va++;
     96 		cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
     97 		va += 63;
     98 	}
     99 }
    100 
    101 void
    102 r10k_icache_sync_range(register_t va, vsize_t size)
    103 {
    104 	vaddr_t eva = round_line(va + size);
    105 
    106 	va = trunc_line(va);
    107 
    108 	mips_dcache_wb_range(va, (eva - va));
    109 
    110 	__asm volatile("sync");
    111 
    112 	while (va < eva) {
    113 		cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
    114 		va += 64;
    115 	}
    116 }
    117 
    118 void
    119 r10k_icache_sync_range_index(vaddr_t va, vsize_t size)
    120 {
    121 	const struct mips_cache_info * const mci = &mips_cache_info;
    122 	vaddr_t eva, orig_va;
    123 
    124 	orig_va = va;
    125 
    126 	eva = round_line(va + size);
    127 	va = trunc_line(va);
    128 
    129 	mips_dcache_wbinv_range_index(va, (eva - va));
    130 
    131 	__asm volatile("sync");
    132 
    133 	/*
    134 	 * Since we're doing Index ops, we expect to not be able
    135 	 * to access the address we've been given.  So, get the
    136 	 * bits that determine the cache index, and make a KSEG0
    137 	 * address out of them.
    138 	 */
    139 	va = MIPS_PHYS_TO_KSEG0(orig_va & mci->mci_picache_way_mask);
    140 
    141 	eva = round_line(va + size);
    142 	va = trunc_line(va);
    143 
    144 	while (va < eva) {
    145 		cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
    146 		va++;
    147 		cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
    148 		va += 63;
    149 	}
    150 }
    151 
    152 #undef round_line
    153 #undef trunc_line
    154 
    155 #define	round_line(x)	(((x) + 32 - 1) & ~(32 - 1))
    156 #define	trunc_line(x)	((x) & ~(32 - 1))
    157 
    158 void
    159 r10k_pdcache_wbinv_all(void)
    160 {
    161 	const struct mips_cache_info * const mci = &mips_cache_info;
    162 	vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
    163 	vaddr_t eva = va + mci->mci_pdcache_way_size;
    164 
    165 	while (va < eva) {
    166 		cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
    167 		va++;
    168 		cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
    169 		va += 31;
    170 	}
    171 }
    172 
    173 void
    174 r10k_pdcache_wbinv_range(register_t va, vsize_t size)
    175 {
    176 	vaddr_t eva = round_line(va + size);
    177 
    178 	va = trunc_line(va);
    179 
    180 	while (va < eva) {
    181 		cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
    182 		va += 32;
    183 	}
    184 }
    185 
    186 void
    187 r10k_pdcache_wbinv_range_index(vaddr_t va, vsize_t size)
    188 {
    189 	const struct mips_cache_info * const mci = &mips_cache_info;
    190 	vaddr_t eva;
    191 
    192 	/*
    193 	 * Since we're doing Index ops, we expect to not be able
    194 	 * to access the address we've been given.  So, get the
    195 	 * bits that determine the cache index, and make a KSEG0
    196 	 * address out of them.
    197 	 */
    198 	va = MIPS_PHYS_TO_KSEG0(va & mci->mci_pdcache_way_mask);
    199 
    200 	eva = round_line(va + size);
    201 	va = trunc_line(va);
    202 
    203 	while (va < eva) {
    204 		cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
    205 		va++;
    206 		cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
    207 		va += 31;
    208 	}
    209 }
    210 
    211 void
    212 r10k_pdcache_inv_range(register_t va, vsize_t size)
    213 {
    214 	vaddr_t eva = round_line(va + size);
    215 
    216 	va = trunc_line(va);
    217 
    218 	while (va < eva) {
    219 		cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
    220 		va += 32;
    221 	}
    222 }
    223 
    224 void
    225 r10k_pdcache_wb_range(register_t va, vsize_t size)
    226 {
    227 	vaddr_t eva = round_line(va + size);
    228 
    229 	va = trunc_line(va);
    230 
    231 	while (va < eva) {
    232 		/* R10000 does not support HitWriteBack operation */
    233 		cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
    234 		va += 32;
    235 	}
    236 }
    237 
    238 #undef round_line
    239 #undef trunc_line
    240 
    241 #define	round_line(x)	(((x) + mci->mci_sdcache_line_size - 1) & ~(mci->mci_sdcache_line_size - 1))
    242 #define	trunc_line(x)	((x) & ~(mci->mci_sdcache_line_size - 1))
    243 
    244 void
    245 r10k_sdcache_wbinv_all(void)
    246 {
    247 	const struct mips_cache_info * const mci = &mips_cache_info;
    248 	vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
    249 	vaddr_t eva = va + mci->mci_sdcache_way_size;
    250 	vsize_t line_size = mci->mci_sdcache_line_size;
    251 
    252 	while (va < eva) {
    253 		cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
    254 		va++;
    255 		cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
    256 		va += line_size - 1;
    257 	}
    258 }
    259 
    260 void
    261 r10k_sdcache_wbinv_range(register_t va, vsize_t size)
    262 {
    263 	const struct mips_cache_info * const mci = &mips_cache_info;
    264 	vaddr_t eva = round_line(va + size);
    265 	vsize_t line_size = mci->mci_sdcache_line_size;
    266 
    267 	va = trunc_line(va);
    268 
    269 	while (va < eva) {
    270 		cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
    271 		va += line_size;
    272 	}
    273 }
    274 
    275 void
    276 r10k_sdcache_wbinv_range_index(vaddr_t va, vsize_t size)
    277 {
    278 	const struct mips_cache_info * const mci = &mips_cache_info;
    279 	vaddr_t eva;
    280 	vsize_t line_size = mci->mci_sdcache_line_size;
    281 
    282 	/*
    283 	 * Since we're doing Index ops, we expect to not be able
    284 	 * to access the address we've been given.  So, get the
    285 	 * bits that determine the cache index, and make a KSEG0
    286 	 * address out of them.
    287 	 */
    288 	va = MIPS_PHYS_TO_KSEG0(va & mci->mci_sdcache_way_mask);
    289 
    290 	eva = round_line(va + size);
    291 	va = trunc_line(va);
    292 
    293 	while (va < eva) {
    294 		cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
    295 		va++;
    296 		cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
    297 		va += line_size - 1;
    298 	}
    299 }
    300 
    301 void
    302 r10k_sdcache_inv_range(register_t va, vsize_t size)
    303 {
    304 	const struct mips_cache_info * const mci = &mips_cache_info;
    305 	vaddr_t eva = round_line(va + size);
    306 	vsize_t line_size = mci->mci_sdcache_line_size;
    307 
    308 	va = trunc_line(va);
    309 
    310 	while (va < eva) {
    311 		cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
    312 		va += line_size;
    313 	}
    314 }
    315 
    316 void
    317 r10k_sdcache_wb_range(register_t va, vsize_t size)
    318 {
    319 	const struct mips_cache_info * const mci = &mips_cache_info;
    320 	vaddr_t eva = round_line(va + size);
    321 	vsize_t line_size = mci->mci_sdcache_line_size;
    322 
    323 	va = trunc_line(va);
    324 
    325 	while (va < eva) {
    326 		/* R10000 does not support HitWriteBack operation */
    327 		cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
    328 		va += line_size;
    329 	}
    330 }
    331 
    332 #undef round_line
    333 #undef trunc_line
    334