]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/mips/cache_mipsNN.c
Merge xz 5.2.0.
[FreeBSD/FreeBSD.git] / sys / mips / mips / cache_mipsNN.c
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$");
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 #define round_line128(x)        (((x) + 127) & ~127)
56 #define trunc_line128(x)        ((x) & ~127)
57
58 #if defined(CPU_NLM)
59 static __inline void
60 xlp_sync(void)
61 {
62         __asm __volatile (
63             ".set push              \n"
64             ".set noreorder         \n"
65             ".set mips64            \n"
66             "dla    $8, 1f          \n"
67             "/* jr.hb $8 */         \n"
68             ".word 0x1000408        \n"
69             "nop                    \n"
70          "1: nop                    \n"
71             ".set pop               \n"
72             : : : "$8");
73 }
74 #endif
75
76 #if defined(SB1250_PASS1)
77 #define SYNC    __asm volatile("sync; sync")
78 #elif defined(CPU_NLM)
79 #define SYNC    xlp_sync()
80 #else
81 #define SYNC    __asm volatile("sync")
82 #endif
83
84 #if defined(CPU_CNMIPS)
85 #define SYNCI  mips_sync_icache();
86 #elif defined(CPU_NLM)
87 #define SYNCI   xlp_sync()
88 #else
89 #define SYNCI
90 #endif
91
92 /*
93  * Exported variables for consumers like bus_dma code
94  */
95 int mips_picache_linesize;
96 int mips_pdcache_linesize;
97
98 static int picache_size;
99 static int picache_stride;
100 static int picache_loopcount;
101 static int picache_way_mask;
102 static int pdcache_size;
103 static int pdcache_stride;
104 static int pdcache_loopcount;
105 static int pdcache_way_mask;
106 static int sdcache_size;
107 static int sdcache_stride;
108 static int sdcache_loopcount;
109 static int sdcache_way_mask;
110
111 void
112 mipsNN_cache_init(struct mips_cpuinfo * cpuinfo)
113 {
114         int flush_multiple_lines_per_way;
115
116         flush_multiple_lines_per_way = cpuinfo->l1.ic_nsets * cpuinfo->l1.ic_linesize * cpuinfo->l1.ic_linesize > PAGE_SIZE;
117         if (cpuinfo->icache_virtual) {
118                 /*
119                  * With a virtual Icache we don't need to flush
120                  * multiples of the page size with index ops; we just
121                  * need to flush one pages' worth.
122                  */
123                 flush_multiple_lines_per_way = 0;
124         }
125
126         if (flush_multiple_lines_per_way) {
127                 picache_stride = PAGE_SIZE;
128                 picache_loopcount = (cpuinfo->l1.ic_nsets * cpuinfo->l1.ic_linesize / PAGE_SIZE) *
129                     cpuinfo->l1.ic_nways;
130         } else {
131                 picache_stride = cpuinfo->l1.ic_nsets * cpuinfo->l1.ic_linesize;
132                 picache_loopcount = cpuinfo->l1.ic_nways;
133         }
134
135         if (cpuinfo->l1.dc_nsets * cpuinfo->l1.dc_linesize < PAGE_SIZE) {
136                 pdcache_stride = cpuinfo->l1.dc_nsets * cpuinfo->l1.dc_linesize;
137                 pdcache_loopcount = cpuinfo->l1.dc_nways;
138         } else {
139                 pdcache_stride = PAGE_SIZE;
140                 pdcache_loopcount = (cpuinfo->l1.dc_nsets * cpuinfo->l1.dc_linesize / PAGE_SIZE) *
141                     cpuinfo->l1.dc_nways;
142         }
143
144         mips_picache_linesize = cpuinfo->l1.ic_linesize;
145         mips_pdcache_linesize = cpuinfo->l1.dc_linesize;
146
147         picache_size = cpuinfo->l1.ic_size;
148         picache_way_mask = cpuinfo->l1.ic_nways - 1;
149         pdcache_size = cpuinfo->l1.dc_size;
150         pdcache_way_mask = cpuinfo->l1.dc_nways - 1;
151
152         sdcache_stride = cpuinfo->l2.dc_nsets * cpuinfo->l2.dc_linesize;
153         sdcache_loopcount = cpuinfo->l2.dc_nways;
154         sdcache_size = cpuinfo->l2.dc_size;
155         sdcache_way_mask = cpuinfo->l2.dc_nways - 1;
156
157 #define CACHE_DEBUG
158 #ifdef CACHE_DEBUG
159         printf("Cache info:\n");
160         if (cpuinfo->icache_virtual)
161                 printf("  icache is virtual\n");
162         printf("  picache_stride    = %d\n", picache_stride);
163         printf("  picache_loopcount = %d\n", picache_loopcount);
164         printf("  pdcache_stride    = %d\n", pdcache_stride);
165         printf("  pdcache_loopcount = %d\n", pdcache_loopcount);
166 #endif
167 }
168
169 void
170 mipsNN_icache_sync_all_16(void)
171 {
172         vm_offset_t va, eva;
173
174         va = MIPS_PHYS_TO_KSEG0(0);
175         eva = va + picache_size;
176
177         /*
178          * Since we're hitting the whole thing, we don't have to
179          * worry about the N different "ways".
180          */
181
182         mips_intern_dcache_wbinv_all();
183
184         while (va < eva) {
185                 cache_r4k_op_32lines_16(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
186                 va += (32 * 16);
187         }
188
189         SYNC;
190 }
191
192 void
193 mipsNN_icache_sync_all_32(void)
194 {
195         vm_offset_t va, eva;
196
197         va = MIPS_PHYS_TO_KSEG0(0);
198         eva = va + picache_size;
199
200         /*
201          * Since we're hitting the whole thing, we don't have to
202          * worry about the N different "ways".
203          */
204
205         mips_intern_dcache_wbinv_all();
206
207         while (va < eva) {
208                 cache_r4k_op_32lines_32(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
209                 va += (32 * 32);
210         }
211
212         SYNC;
213 }
214
215 void
216 mipsNN_icache_sync_range_16(vm_offset_t va, vm_size_t size)
217 {
218         vm_offset_t eva;
219
220         eva = round_line16(va + size);
221         va = trunc_line16(va);
222
223         mips_intern_dcache_wb_range(va, (eva - va));
224
225         while ((eva - va) >= (32 * 16)) {
226                 cache_r4k_op_32lines_16(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
227                 va += (32 * 16);
228         }
229
230         while (va < eva) {
231                 cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
232                 va += 16;
233         }
234
235         SYNC;
236 }
237
238 void
239 mipsNN_icache_sync_range_32(vm_offset_t va, vm_size_t size)
240 {
241         vm_offset_t eva;
242
243         eva = round_line32(va + size);
244         va = trunc_line32(va);
245
246         mips_intern_dcache_wb_range(va, (eva - va));
247
248         while ((eva - va) >= (32 * 32)) {
249                 cache_r4k_op_32lines_32(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
250                 va += (32 * 32);
251         }
252
253         while (va < eva) {
254                 cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
255                 va += 32;
256         }
257
258         SYNC;
259 }
260
261 void
262 mipsNN_icache_sync_range_index_16(vm_offset_t va, vm_size_t size)
263 {
264         vm_offset_t eva, tmpva;
265         int i, stride, loopcount;
266
267         /*
268          * Since we're doing Index ops, we expect to not be able
269          * to access the address we've been given.  So, get the
270          * bits that determine the cache index, and make a KSEG0
271          * address out of them.
272          */
273         va = MIPS_PHYS_TO_KSEG0(va & picache_way_mask);
274
275         eva = round_line16(va + size);
276         va = trunc_line16(va);
277
278         /*
279          * GCC generates better code in the loops if we reference local
280          * copies of these global variables.
281          */
282         stride = picache_stride;
283         loopcount = picache_loopcount;
284
285         mips_intern_dcache_wbinv_range_index(va, (eva - va));
286
287         while ((eva - va) >= (8 * 16)) {
288                 tmpva = va;
289                 for (i = 0; i < loopcount; i++, tmpva += stride)
290                         cache_r4k_op_8lines_16(tmpva,
291                             CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
292                 va += 8 * 16;
293         }
294
295         while (va < eva) {
296                 tmpva = va;
297                 for (i = 0; i < loopcount; i++, tmpva += stride)
298                         cache_op_r4k_line(tmpva,
299                             CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
300                 va += 16;
301         }
302 }
303
304 void
305 mipsNN_icache_sync_range_index_32(vm_offset_t va, vm_size_t size)
306 {
307         vm_offset_t eva, tmpva;
308         int i, stride, loopcount;
309
310         /*
311          * Since we're doing Index ops, we expect to not be able
312          * to access the address we've been given.  So, get the
313          * bits that determine the cache index, and make a KSEG0
314          * address out of them.
315          */
316         va = MIPS_PHYS_TO_KSEG0(va & picache_way_mask);
317
318         eva = round_line32(va + size);
319         va = trunc_line32(va);
320
321         /*
322          * GCC generates better code in the loops if we reference local
323          * copies of these global variables.
324          */
325         stride = picache_stride;
326         loopcount = picache_loopcount;
327
328         mips_intern_dcache_wbinv_range_index(va, (eva - va));
329
330         while ((eva - va) >= (8 * 32)) {
331                 tmpva = va;
332                 for (i = 0; i < loopcount; i++, tmpva += stride)
333                         cache_r4k_op_8lines_32(tmpva,
334                             CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
335                 va += 8 * 32;
336         }
337
338         while (va < eva) {
339                 tmpva = va;
340                 for (i = 0; i < loopcount; i++, tmpva += stride)
341                         cache_op_r4k_line(tmpva,
342                             CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
343                 va += 32;
344         }
345 }
346
347 void
348 mipsNN_pdcache_wbinv_all_16(void)
349 {
350         vm_offset_t va, eva;
351
352         va = MIPS_PHYS_TO_KSEG0(0);
353         eva = va + pdcache_size;
354
355         /*
356          * Since we're hitting the whole thing, we don't have to
357          * worry about the N different "ways".
358          */
359
360         while (va < eva) {
361                 cache_r4k_op_32lines_16(va,
362                     CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
363                 va += (32 * 16);
364         }
365
366         SYNC;
367 }
368
369 void
370 mipsNN_pdcache_wbinv_all_32(void)
371 {
372         vm_offset_t va, eva;
373
374         va = MIPS_PHYS_TO_KSEG0(0);
375         eva = va + pdcache_size;
376
377         /*
378          * Since we're hitting the whole thing, we don't have to
379          * worry about the N different "ways".
380          */
381
382         while (va < eva) {
383                 cache_r4k_op_32lines_32(va,
384                     CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
385                 va += (32 * 32);
386         }
387
388         SYNC;
389 }
390
391 void
392 mipsNN_pdcache_wbinv_range_16(vm_offset_t va, vm_size_t size)
393 {
394         vm_offset_t eva;
395
396         eva = round_line16(va + size);
397         va = trunc_line16(va);
398
399         while ((eva - va) >= (32 * 16)) {
400                 cache_r4k_op_32lines_16(va,
401                     CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
402                 va += (32 * 16);
403         }
404
405         while (va < eva) {
406                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
407                 va += 16;
408         }
409
410         SYNC;
411 }
412
413 void
414 mipsNN_pdcache_wbinv_range_32(vm_offset_t va, vm_size_t size)
415 {
416         vm_offset_t eva;
417
418         eva = round_line32(va + size);
419         va = trunc_line32(va);
420
421         while ((eva - va) >= (32 * 32)) {
422                 cache_r4k_op_32lines_32(va,
423                     CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
424                 va += (32 * 32);
425         }
426
427         while (va < eva) {
428                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
429                 va += 32;
430         }
431
432         SYNC;
433 }
434
435 void
436 mipsNN_pdcache_wbinv_range_index_16(vm_offset_t va, vm_size_t size)
437 {
438         vm_offset_t eva, tmpva;
439         int i, stride, loopcount;
440
441         /*
442          * Since we're doing Index ops, we expect to not be able
443          * to access the address we've been given.  So, get the
444          * bits that determine the cache index, and make a KSEG0
445          * address out of them.
446          */
447         va = MIPS_PHYS_TO_KSEG0(va & pdcache_way_mask);
448
449         eva = round_line16(va + size);
450         va = trunc_line16(va);
451
452         /*
453          * GCC generates better code in the loops if we reference local
454          * copies of these global variables.
455          */
456         stride = pdcache_stride;
457         loopcount = pdcache_loopcount;
458
459         while ((eva - va) >= (8 * 16)) {
460                 tmpva = va;
461                 for (i = 0; i < loopcount; i++, tmpva += stride)
462                         cache_r4k_op_8lines_16(tmpva,
463                             CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
464                 va += 8 * 16;
465         }
466
467         while (va < eva) {
468                 tmpva = va;
469                 for (i = 0; i < loopcount; i++, tmpva += stride)
470                         cache_op_r4k_line(tmpva,
471                             CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
472                 va += 16;
473         }
474 }
475
476 void
477 mipsNN_pdcache_wbinv_range_index_32(vm_offset_t va, vm_size_t size)
478 {
479         vm_offset_t eva, tmpva;
480         int i, stride, loopcount;
481
482         /*
483          * Since we're doing Index ops, we expect to not be able
484          * to access the address we've been given.  So, get the
485          * bits that determine the cache index, and make a KSEG0
486          * address out of them.
487          */
488         va = MIPS_PHYS_TO_KSEG0(va & pdcache_way_mask);
489
490         eva = round_line32(va + size);
491         va = trunc_line32(va);
492
493         /*
494          * GCC generates better code in the loops if we reference local
495          * copies of these global variables.
496          */
497         stride = pdcache_stride;
498         loopcount = pdcache_loopcount;
499
500         while ((eva - va) >= (8 * 32)) {
501                 tmpva = va;
502                 for (i = 0; i < loopcount; i++, tmpva += stride)
503                         cache_r4k_op_8lines_32(tmpva,
504                             CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
505                 va += 8 * 32;
506         }
507
508         while (va < eva) {
509                 tmpva = va;
510                 for (i = 0; i < loopcount; i++, tmpva += stride)
511                         cache_op_r4k_line(tmpva,
512                             CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
513                 va += 32;
514         }
515 }
516  
517 void
518 mipsNN_pdcache_inv_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_INV);
527                 va += (32 * 16);
528         }
529
530         while (va < eva) {
531                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
532                 va += 16;
533         }
534
535         SYNC;
536 }
537
538 void
539 mipsNN_pdcache_inv_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_INV);
548                 va += (32 * 32);
549         }
550
551         while (va < eva) {
552                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
553                 va += 32;
554         }
555
556         SYNC;
557 }
558
559 void
560 mipsNN_pdcache_wb_range_16(vm_offset_t va, vm_size_t size)
561 {
562         vm_offset_t eva;
563
564         eva = round_line16(va + size);
565         va = trunc_line16(va);
566
567         while ((eva - va) >= (32 * 16)) {
568                 cache_r4k_op_32lines_16(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
569                 va += (32 * 16);
570         }
571
572         while (va < eva) {
573                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
574                 va += 16;
575         }
576
577         SYNC;
578 }
579
580 void
581 mipsNN_pdcache_wb_range_32(vm_offset_t va, vm_size_t size)
582 {
583         vm_offset_t eva;
584
585         eva = round_line32(va + size);
586         va = trunc_line32(va);
587
588         while ((eva - va) >= (32 * 32)) {
589                 cache_r4k_op_32lines_32(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
590                 va += (32 * 32);
591         }
592
593         while (va < eva) {
594                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
595                 va += 32;
596         }
597
598         SYNC;
599 }
600
601
602 #ifdef CPU_CNMIPS
603
604 void
605 mipsNN_icache_sync_all_128(void)
606 {
607         SYNCI
608 }
609
610 void
611 mipsNN_icache_sync_range_128(vm_offset_t va, vm_size_t size)
612 {
613         SYNC;
614 }
615
616 void
617 mipsNN_icache_sync_range_index_128(vm_offset_t va, vm_size_t size)
618 {
619 }
620
621
622 void
623 mipsNN_pdcache_wbinv_all_128(void)
624 {
625 }
626
627
628 void
629 mipsNN_pdcache_wbinv_range_128(vm_offset_t va, vm_size_t size)
630 {
631         SYNC;
632 }
633
634 void
635 mipsNN_pdcache_wbinv_range_index_128(vm_offset_t va, vm_size_t size)
636 {
637 }
638
639 void
640 mipsNN_pdcache_inv_range_128(vm_offset_t va, vm_size_t size)
641 {
642 }
643
644 void
645 mipsNN_pdcache_wb_range_128(vm_offset_t va, vm_size_t size)
646 {
647         SYNC;
648 }
649
650 #else
651
652 void
653 mipsNN_icache_sync_all_128(void)
654 {
655         vm_offset_t va, eva;
656
657         va = MIPS_PHYS_TO_KSEG0(0);
658         eva = va + picache_size;
659
660         /*
661          * Since we're hitting the whole thing, we don't have to
662          * worry about the N different "ways".
663          */
664
665         mips_intern_dcache_wbinv_all();
666
667         while (va < eva) {
668                 cache_r4k_op_32lines_128(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
669                 va += (32 * 128);
670         }
671
672         SYNC;
673 }
674
675 void
676 mipsNN_icache_sync_range_128(vm_offset_t va, vm_size_t size)
677 {
678         vm_offset_t eva;
679
680         eva = round_line128(va + size);
681         va = trunc_line128(va);
682
683         mips_intern_dcache_wb_range(va, (eva - va));
684
685         while ((eva - va) >= (32 * 128)) {
686                 cache_r4k_op_32lines_128(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
687                 va += (32 * 128);
688         }
689
690         while (va < eva) {
691                 cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
692                 va += 128;
693         }
694
695         SYNC;
696 }
697
698 void
699 mipsNN_icache_sync_range_index_128(vm_offset_t va, vm_size_t size)
700 {
701         vm_offset_t eva, tmpva;
702         int i, stride, loopcount;
703
704         /*
705          * Since we're doing Index ops, we expect to not be able
706          * to access the address we've been given.  So, get the
707          * bits that determine the cache index, and make a KSEG0
708          * address out of them.
709          */
710         va = MIPS_PHYS_TO_KSEG0(va & picache_way_mask);
711
712         eva = round_line128(va + size);
713         va = trunc_line128(va);
714
715         /*
716          * GCC generates better code in the loops if we reference local
717          * copies of these global variables.
718          */
719         stride = picache_stride;
720         loopcount = picache_loopcount;
721
722         mips_intern_dcache_wbinv_range_index(va, (eva - va));
723
724         while ((eva - va) >= (32 * 128)) {
725                 tmpva = va;
726                 for (i = 0; i < loopcount; i++, tmpva += stride)
727                         cache_r4k_op_32lines_128(tmpva,
728                             CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
729                 va += 32 * 128;
730         }
731
732         while (va < eva) {
733                 tmpva = va;
734                 for (i = 0; i < loopcount; i++, tmpva += stride)
735                         cache_op_r4k_line(tmpva,
736                             CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
737                 va += 128;
738         }
739 }
740
741 void
742 mipsNN_pdcache_wbinv_all_128(void)
743 {
744         vm_offset_t va, eva;
745
746         va = MIPS_PHYS_TO_KSEG0(0);
747         eva = va + pdcache_size;
748
749         /*
750          * Since we're hitting the whole thing, we don't have to
751          * worry about the N different "ways".
752          */
753
754         while (va < eva) {
755                 cache_r4k_op_32lines_128(va,
756                     CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
757                 va += (32 * 128);
758         }
759
760         SYNC;
761 }
762
763
764 void
765 mipsNN_pdcache_wbinv_range_128(vm_offset_t va, vm_size_t size)
766 {
767         vm_offset_t eva;
768
769         eva = round_line128(va + size);
770         va = trunc_line128(va);
771
772         while ((eva - va) >= (32 * 128)) {
773                 cache_r4k_op_32lines_128(va,
774                     CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
775                 va += (32 * 128);
776         }
777
778         while (va < eva) {
779                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
780                 va += 128;
781         }
782
783         SYNC;
784 }
785
786 void
787 mipsNN_pdcache_wbinv_range_index_128(vm_offset_t va, vm_size_t size)
788 {
789         vm_offset_t eva, tmpva;
790         int i, stride, loopcount;
791
792         /*
793          * Since we're doing Index ops, we expect to not be able
794          * to access the address we've been given.  So, get the
795          * bits that determine the cache index, and make a KSEG0
796          * address out of them.
797          */
798         va = MIPS_PHYS_TO_KSEG0(va & pdcache_way_mask);
799
800         eva = round_line128(va + size);
801         va = trunc_line128(va);
802
803         /*
804          * GCC generates better code in the loops if we reference local
805          * copies of these global variables.
806          */
807         stride = pdcache_stride;
808         loopcount = pdcache_loopcount;
809
810         while ((eva - va) >= (32 * 128)) {
811                 tmpva = va;
812                 for (i = 0; i < loopcount; i++, tmpva += stride)
813                         cache_r4k_op_32lines_128(tmpva,
814                             CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
815                 va += 32 * 128;
816         }
817
818         while (va < eva) {
819                 tmpva = va;
820                 for (i = 0; i < loopcount; i++, tmpva += stride)
821                         cache_op_r4k_line(tmpva,
822                             CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
823                 va += 128;
824         }
825 }
826
827 void
828 mipsNN_pdcache_inv_range_128(vm_offset_t va, vm_size_t size)
829 {
830         vm_offset_t eva;
831
832         eva = round_line128(va + size);
833         va = trunc_line128(va);
834
835         while ((eva - va) >= (32 * 128)) {
836                 cache_r4k_op_32lines_128(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
837                 va += (32 * 128);
838         }
839
840         while (va < eva) {
841                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
842                 va += 128;
843         }
844
845         SYNC;
846 }
847
848 void
849 mipsNN_pdcache_wb_range_128(vm_offset_t va, vm_size_t size)
850 {
851         vm_offset_t eva;
852
853         eva = round_line128(va + size);
854         va = trunc_line128(va);
855
856         while ((eva - va) >= (32 * 128)) {
857                 cache_r4k_op_32lines_128(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
858                 va += (32 * 128);
859         }
860
861         while (va < eva) {
862                 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
863                 va += 128;
864         }
865
866         SYNC;
867 }
868
869 #endif
870
871 void
872 mipsNN_sdcache_wbinv_all_32(void)
873 {
874         vm_offset_t va = MIPS_PHYS_TO_KSEG0(0);
875         vm_offset_t eva = va + sdcache_size;
876
877         while (va < eva) {
878                 cache_r4k_op_32lines_32(va,
879                     CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
880                 va += (32 * 32);
881         }
882 }
883
884 void
885 mipsNN_sdcache_wbinv_range_32(vm_offset_t va, vm_size_t size)
886 {
887         vm_offset_t eva = round_line32(va + size);
888
889         va = trunc_line32(va);
890
891         while ((eva - va) >= (32 * 32)) {
892                 cache_r4k_op_32lines_32(va,
893                     CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
894                 va += (32 * 32);
895         }
896
897         while (va < eva) {
898                 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
899                 va += 32;
900         }
901 }
902
903 void
904 mipsNN_sdcache_wbinv_range_index_32(vm_offset_t va, vm_size_t size)
905 {
906         vm_offset_t eva;
907
908         /*
909          * Since we're doing Index ops, we expect to not be able
910          * to access the address we've been given.  So, get the
911          * bits that determine the cache index, and make a KSEG0
912          * address out of them.
913          */
914         va = MIPS_PHYS_TO_KSEG0(va & (sdcache_size - 1));
915
916         eva = round_line32(va + size);
917         va = trunc_line32(va);
918
919         while ((eva - va) >= (32 * 32)) {
920                 cache_r4k_op_32lines_32(va,
921                     CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
922                 va += (32 * 32);
923         }
924
925         while (va < eva) {
926                 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
927                 va += 32;
928         }
929 }
930
931 void
932 mipsNN_sdcache_inv_range_32(vm_offset_t va, vm_size_t size)
933 {
934         vm_offset_t eva = round_line32(va + size);
935
936         va = trunc_line32(va);
937
938         while ((eva - va) >= (32 * 32)) {
939                 cache_r4k_op_32lines_32(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
940                 va += (32 * 32);
941         }
942
943         while (va < eva) {
944                 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
945                 va += 32;
946         }
947 }
948
949 void
950 mipsNN_sdcache_wb_range_32(vm_offset_t va, vm_size_t size)
951 {
952         vm_offset_t eva = round_line32(va + size);
953
954         va = trunc_line32(va);
955
956         while ((eva - va) >= (32 * 32)) {
957                 cache_r4k_op_32lines_32(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
958                 va += (32 * 32);
959         }
960
961         while (va < eva) {
962                 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
963                 va += 32;
964         }
965 }
966
967 void
968 mipsNN_sdcache_wbinv_all_128(void)
969 {
970         vm_offset_t va = MIPS_PHYS_TO_KSEG0(0);
971         vm_offset_t eva = va + sdcache_size;
972
973         while (va < eva) {
974                 cache_r4k_op_32lines_128(va,
975                     CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
976                 va += (32 * 128);
977         }
978 }
979
980 void
981 mipsNN_sdcache_wbinv_range_128(vm_offset_t va, vm_size_t size)
982 {
983         vm_offset_t eva = round_line128(va + size);
984
985         va = trunc_line128(va);
986
987         while ((eva - va) >= (32 * 128)) {
988                 cache_r4k_op_32lines_128(va,
989                     CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
990                 va += (32 * 128);
991         }
992
993         while (va < eva) {
994                 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
995                 va += 128;
996         }
997 }
998
999 void
1000 mipsNN_sdcache_wbinv_range_index_128(vm_offset_t va, vm_size_t size)
1001 {
1002         vm_offset_t eva;
1003
1004         /*
1005          * Since we're doing Index ops, we expect to not be able
1006          * to access the address we've been given.  So, get the
1007          * bits that determine the cache index, and make a KSEG0
1008          * address out of them.
1009          */
1010         va = MIPS_PHYS_TO_KSEG0(va & (sdcache_size - 1));
1011
1012         eva = round_line128(va + size);
1013         va = trunc_line128(va);
1014
1015         while ((eva - va) >= (32 * 128)) {
1016                 cache_r4k_op_32lines_128(va,
1017                     CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
1018                 va += (32 * 128);
1019         }
1020
1021         while (va < eva) {
1022                 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
1023                 va += 128;
1024         }
1025 }
1026
1027 void
1028 mipsNN_sdcache_inv_range_128(vm_offset_t va, vm_size_t size)
1029 {
1030         vm_offset_t eva = round_line128(va + size);
1031
1032         va = trunc_line128(va);
1033
1034         while ((eva - va) >= (32 * 128)) {
1035                 cache_r4k_op_32lines_128(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
1036                 va += (32 * 128);
1037         }
1038
1039         while (va < eva) {
1040                 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
1041                 va += 128;
1042         }
1043 }
1044
1045 void
1046 mipsNN_sdcache_wb_range_128(vm_offset_t va, vm_size_t size)
1047 {
1048         vm_offset_t eva = round_line128(va + size);
1049
1050         va = trunc_line128(va);
1051
1052         while ((eva - va) >= (32 * 128)) {
1053                 cache_r4k_op_32lines_128(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
1054                 va += (32 * 128);
1055         }
1056
1057         while (va < eva) {
1058                 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
1059                 va += 128;
1060         }
1061 }