cache_r4k.c revision 1.6 1 /* $NetBSD: cache_r4k.c,v 1.6 2001/11/23 06:21:50 tsutsui Exp $ */
2
3 /*
4 * Copyright 2001 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Jason R. Thorpe 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/param.h>
39
40 #include <mips/cache.h>
41 #include <mips/cache_r4k.h>
42
43 /*
44 * Cache operations for R4000/R4400-style caches:
45 *
46 * - Direct-mapped
47 * - Write-back
48 * - Virtually indexed, physically tagged
49 *
50 * XXX Does not handle split secondary caches.
51 */
52
53 #define round_line(x) (((x) + 15) & ~15)
54 #define trunc_line(x) ((x) & ~15)
55
56 __asm(".set mips3");
57
58 void
59 r4k_icache_sync_all_16(void)
60 {
61 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
62 vaddr_t eva = va + mips_picache_size;
63
64 mips_dcache_wbinv_all();
65
66 __asm __volatile("sync");
67
68 while (va < eva) {
69 cache_r4k_op_32lines_16(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
70 va += (32 * 16);
71 }
72 }
73
74 void
75 r4k_icache_sync_range_16(vaddr_t va, vsize_t size)
76 {
77 vaddr_t eva = round_line(va + size);
78
79 va = trunc_line(va);
80
81 mips_dcache_wb_range(va, (eva - va));
82
83 __asm __volatile("sync");
84
85 while ((eva - va) >= (32 * 16)) {
86 cache_r4k_op_32lines_16(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
87 va += (32 * 16);
88 }
89
90 while (va < eva) {
91 cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
92 va += 16;
93 }
94 }
95
96 void
97 r4k_icache_sync_range_index_16(vaddr_t va, vsize_t size)
98 {
99 vaddr_t eva;
100
101 eva = round_line(va + size);
102 va = trunc_line(va);
103
104 mips_dcache_wbinv_range_index(va, (eva - va));
105
106 __asm __volatile("sync");
107
108 /*
109 * Since we're doing Index ops, we expect to not be able
110 * to access the address we've been given. So, get the
111 * bits that determine the cache index, and make a KSEG0
112 * address out of them.
113 */
114 va = MIPS_PHYS_TO_KSEG0(va & mips_picache_way_mask);
115
116 eva = round_line(va + size);
117 va = trunc_line(va);
118
119 while ((eva - va) >= (32 * 16)) {
120 cache_r4k_op_32lines_16(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
121 va += (32 * 16);
122 }
123
124 while (va < eva) {
125 cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
126 va += 16;
127 }
128 }
129
130 void
131 r4k_pdcache_wbinv_all_16(void)
132 {
133 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
134 vaddr_t eva = va + mips_pdcache_size;
135
136 while (va < eva) {
137 cache_r4k_op_32lines_16(va,
138 CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
139 va += (32 * 16);
140 }
141 }
142
143 void
144 r4k_pdcache_wbinv_range_16(vaddr_t va, vsize_t size)
145 {
146 vaddr_t eva = round_line(va + size);
147
148 va = trunc_line(va);
149
150 while ((eva - va) >= (32 * 16)) {
151 cache_r4k_op_32lines_16(va,
152 CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
153 va += (32 * 16);
154 }
155
156 while (va < eva) {
157 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
158 va += 16;
159 }
160 }
161
162 void
163 r4k_pdcache_wbinv_range_index_16(vaddr_t va, vsize_t size)
164 {
165 vaddr_t eva;
166
167 /*
168 * Since we're doing Index ops, we expect to not be able
169 * to access the address we've been given. So, get the
170 * bits that determine the cache index, and make a KSEG0
171 * address out of them.
172 */
173 va = MIPS_PHYS_TO_KSEG0(va & (mips_pdcache_size - 1));
174
175 eva = round_line(va + size);
176 va = trunc_line(va);
177
178 while ((eva - va) >= (32 * 16)) {
179 cache_r4k_op_32lines_16(va,
180 CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
181 va += (32 * 16);
182 }
183
184 while (va < eva) {
185 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
186 va += 16;
187 }
188 }
189
190 void
191 r4k_pdcache_inv_range_16(vaddr_t va, vsize_t size)
192 {
193 vaddr_t eva = round_line(va + size);
194
195 va = trunc_line(va);
196
197 while ((eva - va) >= (32 * 16)) {
198 cache_r4k_op_32lines_16(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
199 va += (32 * 16);
200 }
201
202 while (va < eva) {
203 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
204 va += 16;
205 }
206 }
207
208 void
209 r4k_pdcache_wb_range_16(vaddr_t va, vsize_t size)
210 {
211 vaddr_t eva = round_line(va + size);
212
213 va = trunc_line(va);
214
215 while ((eva - va) >= (32 * 16)) {
216 cache_r4k_op_32lines_16(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
217 va += (32 * 16);
218 }
219
220 while (va < eva) {
221 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
222 va += 16;
223 }
224 }
225
226 #undef round_line
227 #undef trunc_line
228
229 #define round_line(x) (((x) + 31) & ~31)
230 #define trunc_line(x) ((x) & ~31)
231
232 void
233 r4k_icache_sync_all_32(void)
234 {
235 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
236 vaddr_t eva = va + mips_picache_size;
237
238 mips_dcache_wbinv_all();
239
240 __asm __volatile("sync");
241
242 while (va < eva) {
243 cache_r4k_op_32lines_32(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
244 va += (32 * 32);
245 }
246 }
247
248 void
249 r4k_icache_sync_range_32(vaddr_t va, vsize_t size)
250 {
251 vaddr_t eva = round_line(va + size);
252
253 va = trunc_line(va);
254
255 mips_dcache_wb_range(va, (eva - va));
256
257 __asm __volatile("sync");
258
259 while ((eva - va) >= (32 * 32)) {
260 cache_r4k_op_32lines_32(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
261 va += (32 * 32);
262 }
263
264 while (va < eva) {
265 cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
266 va += 32;
267 }
268 }
269
270 void
271 r4k_icache_sync_range_index_32(vaddr_t va, vsize_t size)
272 {
273 vaddr_t eva;
274
275 eva = round_line(va + size);
276 va = trunc_line(va);
277
278 mips_dcache_wbinv_range_index(va, (eva - va));
279
280 __asm __volatile("sync");
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 & mips_picache_way_mask);
289
290 eva = round_line(va + size);
291 va = trunc_line(va);
292
293 while ((eva - va) >= (32 * 32)) {
294 cache_r4k_op_32lines_32(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
295 va += (32 * 32);
296 }
297
298 while (va < eva) {
299 cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
300 va += 32;
301 }
302 }
303
304 void
305 r4k_pdcache_wbinv_all_32(void)
306 {
307 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
308 vaddr_t eva = va + mips_pdcache_size;
309
310 while (va < eva) {
311 cache_r4k_op_32lines_32(va,
312 CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
313 va += (32 * 32);
314 }
315 }
316
317 void
318 r4k_pdcache_wbinv_range_32(vaddr_t va, vsize_t size)
319 {
320 vaddr_t eva = round_line(va + size);
321
322 va = trunc_line(va);
323
324 while ((eva - va) >= (32 * 32)) {
325 cache_r4k_op_32lines_32(va,
326 CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
327 va += (32 * 32);
328 }
329
330 while (va < eva) {
331 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
332 va += 32;
333 }
334 }
335
336 void
337 r4k_pdcache_wbinv_range_index_32(vaddr_t va, vsize_t size)
338 {
339 vaddr_t eva;
340
341 /*
342 * Since we're doing Index ops, we expect to not be able
343 * to access the address we've been given. So, get the
344 * bits that determine the cache index, and make a KSEG0
345 * address out of them.
346 */
347 va = MIPS_PHYS_TO_KSEG0(va & (mips_pdcache_size - 1));
348
349 eva = round_line(va + size);
350 va = trunc_line(va);
351
352 while ((eva - va) >= (32 * 32)) {
353 cache_r4k_op_32lines_32(va,
354 CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
355 va += (32 * 32);
356 }
357
358 while (va < eva) {
359 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
360 va += 32;
361 }
362 }
363
364 void
365 r4k_pdcache_inv_range_32(vaddr_t va, vsize_t size)
366 {
367 vaddr_t eva = round_line(va + size);
368
369 va = trunc_line(va);
370
371 while ((eva - va) >= (32 * 32)) {
372 cache_r4k_op_32lines_32(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
373 va += (32 * 32);
374 }
375
376 while (va < eva) {
377 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
378 va += 32;
379 }
380 }
381
382 void
383 r4k_pdcache_wb_range_32(vaddr_t va, vsize_t size)
384 {
385 vaddr_t eva = round_line(va + size);
386
387 va = trunc_line(va);
388
389 while ((eva - va) >= (32 * 32)) {
390 cache_r4k_op_32lines_32(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
391 va += (32 * 32);
392 }
393
394 while (va < eva) {
395 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
396 va += 32;
397 }
398 }
399
400 void
401 r4k_sdcache_wbinv_all_32(void)
402 {
403 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
404 vaddr_t eva = va + mips_sdcache_size;
405
406 while (va < eva) {
407 cache_r4k_op_32lines_32(va,
408 CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
409 va += (32 * 32);
410 }
411 }
412
413 void
414 r4k_sdcache_wbinv_range_32(vaddr_t va, vsize_t size)
415 {
416 vaddr_t eva = round_line(va + size);
417
418 va = trunc_line(va);
419
420 while ((eva - va) >= (32 * 32)) {
421 cache_r4k_op_32lines_32(va,
422 CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
423 va += (32 * 32);
424 }
425
426 while (va < eva) {
427 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
428 va += 32;
429 }
430 }
431
432 void
433 r4k_sdcache_wbinv_range_index_32(vaddr_t va, vsize_t size)
434 {
435 vaddr_t eva;
436
437 /*
438 * Since we're doing Index ops, we expect to not be able
439 * to access the address we've been given. So, get the
440 * bits that determine the cache index, and make a KSEG0
441 * address out of them.
442 */
443 va = MIPS_PHYS_TO_KSEG0(va & (mips_sdcache_size - 1));
444
445 eva = round_line(va + size);
446 va = trunc_line(va);
447
448 while ((eva - va) >= (32 * 32)) {
449 cache_r4k_op_32lines_32(va,
450 CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
451 va += (32 * 32);
452 }
453
454 while (va < eva) {
455 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
456 va += 32;
457 }
458 }
459
460 void
461 r4k_sdcache_inv_range_32(vaddr_t va, vsize_t size)
462 {
463 vaddr_t eva = round_line(va + size);
464
465 va = trunc_line(va);
466
467 while ((eva - va) >= (32 * 32)) {
468 cache_r4k_op_32lines_32(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
469 va += (32 * 32);
470 }
471
472 while (va < eva) {
473 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
474 va += 32;
475 }
476 }
477
478 void
479 r4k_sdcache_wb_range_32(vaddr_t va, vsize_t size)
480 {
481 vaddr_t eva = round_line(va + size);
482
483 va = trunc_line(va);
484
485 while ((eva - va) >= (32 * 32)) {
486 cache_r4k_op_32lines_32(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
487 va += (32 * 32);
488 }
489
490 while (va < eva) {
491 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
492 va += 32;
493 }
494 }
495
496 #undef round_line
497 #undef trunc_line
498
499 #define round_line(x) (((x) + 127) & ~127)
500 #define trunc_line(x) ((x) & ~127)
501
502 void
503 r4k_sdcache_wbinv_all_128(void)
504 {
505 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
506 vaddr_t eva = va + mips_sdcache_size;
507
508 while (va < eva) {
509 cache_r4k_op_32lines_128(va,
510 CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
511 va += (32 * 128);
512 }
513 }
514
515 void
516 r4k_sdcache_wbinv_range_128(vaddr_t va, vsize_t size)
517 {
518 vaddr_t eva = round_line(va + size);
519
520 va = trunc_line(va);
521
522 while ((eva - va) >= (32 * 128)) {
523 cache_r4k_op_32lines_128(va,
524 CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
525 va += (32 * 128);
526 }
527
528 while (va < eva) {
529 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
530 va += 128;
531 }
532 }
533
534 void
535 r4k_sdcache_wbinv_range_index_128(vaddr_t va, vsize_t size)
536 {
537 vaddr_t eva;
538
539 /*
540 * Since we're doing Index ops, we expect to not be able
541 * to access the address we've been given. So, get the
542 * bits that determine the cache index, and make a KSEG0
543 * address out of them.
544 */
545 va = MIPS_PHYS_TO_KSEG0(va & (mips_sdcache_size - 1));
546
547 eva = round_line(va + size);
548 va = trunc_line(va);
549
550 while ((eva - va) >= (32 * 128)) {
551 cache_r4k_op_32lines_128(va,
552 CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
553 va += (32 * 128);
554 }
555
556 while (va < eva) {
557 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
558 va += 128;
559 }
560 }
561
562 void
563 r4k_sdcache_inv_range_128(vaddr_t va, vsize_t size)
564 {
565 vaddr_t eva = round_line(va + size);
566
567 va = trunc_line(va);
568
569 while ((eva - va) >= (32 * 128)) {
570 cache_r4k_op_32lines_128(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
571 va += (32 * 128);
572 }
573
574 while (va < eva) {
575 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
576 va += 128;
577 }
578 }
579
580 void
581 r4k_sdcache_wb_range_128(vaddr_t va, vsize_t size)
582 {
583 vaddr_t eva = round_line(va + size);
584
585 va = trunc_line(va);
586
587 while ((eva - va) >= (32 * 128)) {
588 cache_r4k_op_32lines_128(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
589 va += (32 * 128);
590 }
591
592 while (va < eva) {
593 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
594 va += 128;
595 }
596 }
597
598 #undef round_line
599 #undef trunc_line
600
601 #define round_line(x) (((x) + mips_sdcache_line_size - 1) & ~(mips_sdcache_line_size - 1))
602 #define trunc_line(x) ((x) & ~(mips_sdcache_line_size - 1))
603
604 void
605 r4k_sdcache_wbinv_all_generic(void)
606 {
607 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
608 vaddr_t eva = va + mips_sdcache_size;
609 int line_size = mips_sdcache_line_size;
610
611 while (va < eva) {
612 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
613 va += line_size;
614 }
615 }
616
617 void
618 r4k_sdcache_wbinv_range_generic(vaddr_t va, vsize_t size)
619 {
620 vaddr_t eva = round_line(va + size);
621 int line_size = mips_sdcache_line_size;
622
623 va = trunc_line(va);
624
625 while (va < eva) {
626 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
627 va += line_size;
628 }
629 }
630
631 void
632 r4k_sdcache_wbinv_range_index_generic(vaddr_t va, vsize_t size)
633 {
634 vaddr_t eva;
635 int line_size = mips_sdcache_line_size;
636
637 /*
638 * Since we're doing Index ops, we expect to not be able
639 * to access the address we've been given. So, get the
640 * bits that determine the cache index, and make a KSEG0
641 * address out of them.
642 */
643 va = MIPS_PHYS_TO_KSEG0(va & (mips_sdcache_size - 1));
644
645 eva = round_line(va + size);
646 va = trunc_line(va);
647
648 while (va < eva) {
649 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
650 va += line_size;
651 }
652 }
653
654 void
655 r4k_sdcache_inv_range_generic(vaddr_t va, vsize_t size)
656 {
657 vaddr_t eva = round_line(va + size);
658 int line_size = mips_sdcache_line_size;
659
660 va = trunc_line(va);
661
662 while (va < eva) {
663 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
664 va += line_size;
665 }
666 }
667
668 void
669 r4k_sdcache_wb_range_generic(vaddr_t va, vsize_t size)
670 {
671 vaddr_t eva = round_line(va + size);
672 int line_size = mips_sdcache_line_size;
673
674 va = trunc_line(va);
675
676 while (va < eva) {
677 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
678 va += line_size;
679 }
680 }
681
682 #undef round_line
683 #undef trunc_line
684