1 /* $NetBSD: cache_r10k.c,v 1.4 2005/12/24 20:07:19 perry 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/cache.h> 65 #include <mips/cache_r4k.h> 66 #include <mips/cache_r10k.h> 67 68 /* 69 * Cache operations for R10000-style caches: 70 * 71 * 2-way, write-back 72 * primary cache: virtual index/physical tag 73 * secondary cache: physical index/physical tag 74 */ 75 76 __asm(".set mips3"); 77 78 #define round_line(x) (((x) + 64 - 1) & ~(64 - 1)) 79 #define trunc_line(x) ((x) & ~(64 - 1)) 80 81 void 82 r10k_icache_sync_all(void) 83 { 84 vaddr_t va = MIPS_PHYS_TO_KSEG0(0); 85 vaddr_t eva = va + mips_picache_way_size; 86 87 mips_dcache_wbinv_all(); 88 89 __asm volatile("sync"); 90 91 while (va < eva) { 92 cache_op_r4k_line(va+0, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); 93 cache_op_r4k_line(va+1, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); 94 va += 64; 95 } 96 } 97 98 void 99 r10k_icache_sync_range(vaddr_t va, vsize_t size) 100 { 101 vaddr_t eva = round_line(va + size); 102 103 va = trunc_line(va); 104 105 mips_dcache_wb_range(va, (eva - va)); 106 107 __asm volatile("sync"); 108 109 while (va < eva) { 110 cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV); 111 va += 64; 112 } 113 } 114 115 void 116 r10k_icache_sync_range_index(vaddr_t va, vsize_t size) 117 { 118 vaddr_t eva, orig_va; 119 120 orig_va = va; 121 122 eva = round_line(va + size); 123 va = trunc_line(va); 124 125 mips_dcache_wbinv_range_index(va, (eva - va)); 126 127 __asm volatile("sync"); 128 129 /* 130 * Since we're doing Index ops, we expect to not be able 131 * to access the address we've been given. So, get the 132 * bits that determine the cache index, and make a KSEG0 133 * address out of them. 134 */ 135 va = MIPS_PHYS_TO_KSEG0(orig_va & mips_picache_way_mask); 136 137 eva = round_line(va + size); 138 va = trunc_line(va); 139 140 while (va < eva) { 141 cache_op_r4k_line(va+0, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); 142 cache_op_r4k_line(va+1, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); 143 va += 64; 144 } 145 } 146 147 #undef round_line 148 #undef trunc_line 149 150 #define round_line(x) (((x) + 32 - 1) & ~(32 - 1)) 151 #define trunc_line(x) ((x) & ~(32 - 1)) 152 153 void 154 r10k_pdcache_wbinv_all(void) 155 { 156 vaddr_t va = MIPS_PHYS_TO_KSEG0(0); 157 vaddr_t eva = va + mips_pdcache_way_size; 158 159 while (va < eva) { 160 cache_op_r4k_line(va+0, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); 161 cache_op_r4k_line(va+1, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); 162 va += 32; 163 } 164 } 165 166 void 167 r10k_pdcache_wbinv_range(vaddr_t va, vsize_t size) 168 { 169 vaddr_t eva = round_line(va + size); 170 171 va = trunc_line(va); 172 173 while (va < eva) { 174 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV); 175 va += 32; 176 } 177 } 178 179 void 180 r10k_pdcache_wbinv_range_index(vaddr_t va, vsize_t size) 181 { 182 vaddr_t eva; 183 184 /* 185 * Since we're doing Index ops, we expect to not be able 186 * to access the address we've been given. So, get the 187 * bits that determine the cache index, and make a KSEG0 188 * address out of them. 189 */ 190 va = MIPS_PHYS_TO_KSEG0(va & mips_pdcache_way_mask); 191 192 eva = round_line(va + size); 193 va = trunc_line(va); 194 195 while (va < eva) { 196 cache_op_r4k_line(va+0, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); 197 cache_op_r4k_line(va+1, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); 198 va += 32; 199 } 200 } 201 202 void 203 r10k_pdcache_inv_range(vaddr_t va, vsize_t size) 204 { 205 vaddr_t eva = round_line(va + size); 206 207 va = trunc_line(va); 208 209 while (va < eva) { 210 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV); 211 va += 32; 212 } 213 } 214 215 void 216 r10k_pdcache_wb_range(vaddr_t va, vsize_t size) 217 { 218 vaddr_t eva = round_line(va + size); 219 220 va = trunc_line(va); 221 222 while (va < eva) { 223 /* R10000 does not support HitWriteBack operation */ 224 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV); 225 va += 32; 226 } 227 } 228 229 #undef round_line 230 #undef trunc_line 231 232 #define round_line(x) (((x) + mips_sdcache_line_size - 1) & ~(mips_sdcache_line_size - 1)) 233 #define trunc_line(x) ((x) & ~(mips_sdcache_line_size - 1)) 234 235 void 236 r10k_sdcache_wbinv_all(void) 237 { 238 vaddr_t va = MIPS_PHYS_TO_KSEG0(0); 239 vaddr_t eva = va + mips_sdcache_way_size; 240 int line_size = mips_sdcache_line_size; 241 242 while (va < eva) { 243 cache_op_r4k_line(va+0, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV); 244 cache_op_r4k_line(va+1, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV); 245 va += line_size; 246 } 247 } 248 249 void 250 r10k_sdcache_wbinv_range(vaddr_t va, vsize_t size) 251 { 252 vaddr_t eva = round_line(va + size); 253 int line_size = mips_sdcache_line_size; 254 255 va = trunc_line(va); 256 257 while (va < eva) { 258 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV); 259 va += line_size; 260 } 261 } 262 263 void 264 r10k_sdcache_wbinv_range_index(vaddr_t va, vsize_t size) 265 { 266 vaddr_t eva; 267 int line_size = mips_sdcache_line_size; 268 269 /* 270 * Since we're doing Index ops, we expect to not be able 271 * to access the address we've been given. So, get the 272 * bits that determine the cache index, and make a KSEG0 273 * address out of them. 274 */ 275 va = MIPS_PHYS_TO_KSEG0(va & mips_sdcache_way_mask); 276 277 eva = round_line(va + size); 278 va = trunc_line(va); 279 280 while (va < eva) { 281 cache_op_r4k_line(va+0, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV); 282 cache_op_r4k_line(va+1, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV); 283 va += line_size; 284 } 285 } 286 287 void 288 r10k_sdcache_inv_range(vaddr_t va, vsize_t size) 289 { 290 vaddr_t eva = round_line(va + size); 291 int line_size = mips_sdcache_line_size; 292 293 va = trunc_line(va); 294 295 while (va < eva) { 296 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV); 297 va += line_size; 298 } 299 } 300 301 void 302 r10k_sdcache_wb_range(vaddr_t va, vsize_t size) 303 { 304 vaddr_t eva = round_line(va + size); 305 int line_size = mips_sdcache_line_size; 306 307 va = trunc_line(va); 308 309 while (va < eva) { 310 /* R10000 does not support HitWriteBack operation */ 311 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV); 312 va += line_size; 313 } 314 } 315 316 #undef round_line 317 #undef trunc_line 318