1 /* $OpenBSD: cache.c,v 1.16 2002/03/13 00:24:21 miod Exp $ */
2 /* $NetBSD: cache.c,v 1.34 1997/09/26 22:17:23 pk Exp $ */
3
4 /*
5 * Copyright (c) 1996
6 * The President and Fellows of Harvard College. All rights reserved.
7 * Copyright (c) 1992, 1993
8 * The Regents of the University of California. All rights reserved.
9 *
10 * This software was developed by the Computer Systems Engineering group
11 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
12 * contributed to Berkeley.
13 *
14 * All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Harvard University.
17 * This product includes software developed by the University of
18 * California, Lawrence Berkeley Laboratory.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 *
24 * 1. Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
29 * 3. All advertising materials mentioning features or use of this software
30 * must display the following acknowledgement:
31 * This product includes software developed by Aaron Brown and
32 * Harvard University.
33 * This product includes software developed by the University of
34 * California, Berkeley and its contributors.
35 * 4. Neither the name of the University nor the names of its contributors
36 * may be used to endorse or promote products derived from this software
37 * without specific prior written permission.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
40 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
43 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
45 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
48 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
49 * SUCH DAMAGE.
50 *
51 * @(#)cache.c 8.2 (Berkeley) 10/30/93
52 *
53 */
54
55 /*
56 * Cache routines.
57 *
58 * TODO:
59 * - rework range flush
60 */
61
62 #include <sys/param.h>
63 #include <sys/systm.h>
64
65 #include <uvm/uvm_extern.h>
66
67 #include <machine/ctlreg.h>
68
69 #include <sparc/sparc/asm.h>
70 #include <sparc/sparc/cache.h>
71 #include <sparc/sparc/cpuvar.h>
72
73 struct cachestats cachestats;
74
75 int cache_alias_dist; /* Cache anti-aliasing constants */
76 int cache_alias_bits;
77
78 /*
79 * Enable the cache.
80 * We need to clear out the valid bits first.
81 */
82 void
sun4_cache_enable()83 sun4_cache_enable()
84 {
85 register u_int i, lim, ls, ts;
86
87 cache_alias_bits = CPU_ISSUN4
88 ? CACHE_ALIAS_BITS_SUN4
89 : CACHE_ALIAS_BITS_SUN4C;
90 cache_alias_dist = CPU_ISSUN4
91 ? CACHE_ALIAS_DIST_SUN4
92 : CACHE_ALIAS_DIST_SUN4C;
93
94 ls = CACHEINFO.c_linesize;
95 ts = CACHEINFO.c_totalsize;
96
97 for (i = AC_CACHETAGS, lim = i + ts; i < lim; i += ls)
98 sta(i, ASI_CONTROL, 0);
99
100 stba(AC_SYSENABLE, ASI_CONTROL,
101 lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_CACHE);
102 CACHEINFO.c_enabled = 1;
103
104 printf("cache enabled\n");
105
106 #ifdef notyet
107 if (cpuinfo.flags & SUN4_IOCACHE) {
108 stba(AC_SYSENABLE, ASI_CONTROL,
109 lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_IOCACHE);
110 printf("iocache enabled\n");
111 }
112 #endif
113 }
114
115 #if defined(SUN4M)
116 void
ms1_cache_enable()117 ms1_cache_enable()
118 {
119 u_int pcr;
120
121 cache_alias_bits = GUESS_CACHE_ALIAS_BITS;
122 cache_alias_dist = GUESS_CACHE_ALIAS_DIST;
123
124 pcr = lda(SRMMU_PCR, ASI_SRMMU);
125
126 /* We "flash-clear" the I/D caches. */
127 if ((pcr & MS1_PCR_ICE) == 0)
128 sta(0, ASI_ICACHECLR, 0);
129 if ((pcr & MS1_PCR_DCE) == 0)
130 sta(0, ASI_DCACHECLR, 0);
131
132 /* Turn on caches */
133 sta(SRMMU_PCR, ASI_SRMMU, pcr | MS1_PCR_DCE | MS1_PCR_ICE);
134
135 CACHEINFO.c_enabled = CACHEINFO.dc_enabled = 1;
136
137 printf("cache enabled\n");
138 }
139
140 void
viking_cache_enable()141 viking_cache_enable()
142 {
143 u_int pcr;
144
145 cache_alias_dist = max(
146 CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity,
147 CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity);
148 cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
149
150 pcr = lda(SRMMU_PCR, ASI_SRMMU);
151
152 if ((pcr & VIKING_PCR_ICE) == 0) {
153 /* I-cache not on; "flash-clear" it now. */
154 sta(0x80000000, ASI_ICACHECLR, 0); /* Unlock */
155 sta(0, ASI_ICACHECLR, 0); /* clear */
156 }
157 if ((pcr & VIKING_PCR_DCE) == 0) {
158 /* D-cache not on: "flash-clear" it. */
159 sta(0x80000000, ASI_DCACHECLR, 0);
160 sta(0, ASI_DCACHECLR, 0);
161 }
162
163 /* Turn on caches via MMU */
164 sta(SRMMU_PCR, ASI_SRMMU, pcr | VIKING_PCR_DCE | VIKING_PCR_ICE);
165
166 CACHEINFO.c_enabled = CACHEINFO.dc_enabled = 1;
167
168 /* Now turn on MultiCache if it exists */
169 if (cpuinfo.mxcc && CACHEINFO.ec_totalsize > 0) {
170 /* Multicache controller */
171 stda(MXCC_ENABLE_ADDR, ASI_CONTROL,
172 ldda(MXCC_ENABLE_ADDR, ASI_CONTROL) |
173 (u_int64_t)MXCC_ENABLE_BIT);
174 cpuinfo.flags |= CPUFLG_CACHEPAGETABLES; /* Ok to cache PTEs */
175 CACHEINFO.ec_enabled = 1;
176 }
177 printf("cache enabled\n");
178 }
179
180 void
hypersparc_cache_enable()181 hypersparc_cache_enable()
182 {
183 int i, ls, ts;
184 u_int pcr, v;
185 extern u_long dvma_cachealign;
186
187 ls = CACHEINFO.c_linesize;
188 ts = CACHEINFO.c_totalsize;
189
190 pcr = lda(SRMMU_PCR, ASI_SRMMU);
191
192 /*
193 * Setup the anti-aliasing constants and DVMA alignment constraint.
194 */
195 cache_alias_dist = CACHEINFO.c_totalsize;
196 cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
197 dvma_cachealign = cache_alias_dist;
198
199 /* Now reset cache tag memory if cache not yet enabled */
200 if ((pcr & HYPERSPARC_PCR_CE) == 0)
201 for (i = 0; i < ts; i += ls) {
202 sta(i, ASI_DCACHETAG, 0);
203 while (lda(i, ASI_DCACHETAG))
204 sta(i, ASI_DCACHETAG, 0);
205 }
206
207 pcr &= ~(HYPERSPARC_PCR_CE | HYPERSPARC_PCR_CM);
208
209 hypersparc_cache_flush_all();
210
211 pcr |= HYPERSPARC_PCR_CE;
212 if (CACHEINFO.c_vactype == VAC_WRITEBACK)
213 pcr |= HYPERSPARC_PCR_CM;
214
215 sta(SRMMU_PCR, ASI_SRMMU, pcr);
216 CACHEINFO.c_enabled = 1;
217
218 /* XXX: should add support */
219 if (CACHEINFO.c_hwflush)
220 panic("cache_enable: can't handle 4M with hw-flush cache");
221
222 #ifdef notyet
223 /*
224 * Enable instruction cache and, on single-processor machines,
225 * disable `Unimplemented Flush Traps'.
226 */
227 v = HYPERSPARC_ICCR_ICE | (ncpu == 1 ? HYPERSPARC_ICCR_FTD : 0);
228 #else
229 v = HYPERSPARC_ICCR_FTD | HYPERSPARC_ICCR_ICE;
230 #endif
231 wrasr(v, HYPERSPARC_ASRNUM_ICCR);
232
233 printf("cache enabled\n");
234 }
235
236 void
swift_cache_enable()237 swift_cache_enable()
238 {
239 int i, ls, ts;
240 u_int pcr;
241
242 cache_alias_dist = max(
243 CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity,
244 CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity);
245 cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
246
247 pcr = lda(SRMMU_PCR, ASI_SRMMU);
248 pcr |= (SWIFT_PCR_ICE | SWIFT_PCR_DCE);
249 sta(SRMMU_PCR, ASI_SRMMU, pcr);
250
251 /* Now reset cache tag memory if cache not yet enabled */
252 ls = CACHEINFO.ic_linesize;
253 ts = CACHEINFO.ic_totalsize;
254 if ((pcr & SWIFT_PCR_ICE) == 0)
255 for (i = 0; i < ts; i += ls)
256 sta(i, ASI_ICACHETAG, 0);
257
258 ls = CACHEINFO.dc_linesize;
259 ts = CACHEINFO.dc_totalsize;
260 if ((pcr & SWIFT_PCR_DCE) == 0)
261 for (i = 0; i < ts; i += ls) {
262 sta(i, ASI_DCACHETAG, 0);
263 while (lda(i, ASI_DCACHETAG))
264 sta(i, ASI_DCACHETAG, 0);
265 }
266
267 CACHEINFO.c_enabled = 1;
268 printf("cache enabled\n");
269 }
270
271 void
cypress_cache_enable()272 cypress_cache_enable()
273 {
274 int i, ls, ts;
275 u_int pcr;
276
277 cache_alias_dist = CACHEINFO.c_totalsize;
278 cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
279
280 pcr = lda(SRMMU_PCR, ASI_SRMMU);
281 pcr &= ~(CYPRESS_PCR_CE | CYPRESS_PCR_CM);
282
283 /* Now reset cache tag memory if cache not yet enabled */
284 ls = CACHEINFO.c_linesize;
285 ts = CACHEINFO.c_totalsize;
286 if ((pcr & CYPRESS_PCR_CE) == 0)
287 for (i = 0; i < ts; i += ls) {
288 sta(i, ASI_DCACHETAG, 0);
289 while (lda(i, ASI_DCACHETAG))
290 sta(i, ASI_DCACHETAG, 0);
291 }
292
293 pcr |= CYPRESS_PCR_CE;
294
295 #if 1
296 pcr &= ~CYPRESS_PCR_CM; /* XXX Disable write-back mode */
297 #else
298 /* If put in write-back mode, turn it on */
299 if (CACHEINFO.c_vactype == VAC_WRITEBACK)
300 pcr |= CYPRESS_PCR_CM;
301 #endif
302
303 sta(SRMMU_PCR, ASI_SRMMU, pcr);
304 CACHEINFO.c_enabled = 1;
305 printf("cache enabled\n");
306 }
307
308 void
turbosparc_cache_enable()309 turbosparc_cache_enable()
310 {
311 int i, ls, ts;
312 u_int pcr, pcf;
313
314 cache_alias_dist = max(
315 CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity,
316 CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity);
317 cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
318
319 pcr = lda(SRMMU_PCR, ASI_SRMMU);
320
321 /* Now reset cache tag memory if cache not yet enabled */
322 ls = CACHEINFO.ic_linesize;
323 ts = CACHEINFO.ic_totalsize;
324 if ((pcr & TURBOSPARC_PCR_ICE) == 0)
325 for (i = 0; i < ts; i += ls)
326 sta(i, ASI_ICACHETAG, 0);
327
328 ls = CACHEINFO.dc_linesize;
329 ts = CACHEINFO.dc_totalsize;
330 if ((pcr & TURBOSPARC_PCR_DCE) == 0)
331 for (i = 0; i < ts; i += ls) {
332 sta(i, ASI_DCACHETAG, 0);
333 while (lda(i, ASI_DCACHETAG))
334 sta(i, ASI_DCACHETAG, 0);
335 }
336
337 pcr |= (TURBOSPARC_PCR_ICE | TURBOSPARC_PCR_DCE);
338 sta(SRMMU_PCR, ASI_SRMMU, pcr);
339
340 pcf = lda(SRMMU_PCFG, ASI_SRMMU);
341 if (pcf & TURBOSPARC_PCFG_SNP)
342 printf("DVMA coherent ");
343
344 CACHEINFO.c_enabled = 1;
345 printf("cache enabled\n");
346 }
347 #endif /* defined(SUN4M) */
348
349 /*
350 * Flush the current context from the cache.
351 *
352 * This is done by writing to each cache line in the `flush context'
353 * address space (or, for hardware flush, once to each page in the
354 * hardware flush space, for all cache pages).
355 */
356 void
sun4_vcache_flush_context()357 sun4_vcache_flush_context()
358 {
359 register char *p;
360 register int i, ls;
361
362 cachestats.cs_ncxflush++;
363 p = (char *)0; /* addresses 0..cacheinfo.c_totalsize will do fine */
364 if (CACHEINFO.c_hwflush) {
365 ls = NBPG;
366 i = CACHEINFO.c_totalsize >> PGSHIFT;
367 for (; --i >= 0; p += ls)
368 sta(p, ASI_HWFLUSHCTX, 0);
369 } else {
370 ls = CACHEINFO.c_linesize;
371 i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
372 for (; --i >= 0; p += ls)
373 sta(p, ASI_FLUSHCTX, 0);
374 }
375 }
376
377 /*
378 * Flush the given virtual region from the cache.
379 *
380 * This is also done by writing to each cache line, except that
381 * now the addresses must include the virtual region number, and
382 * we use the `flush region' space.
383 *
384 * This function is only called on sun4's with 3-level MMUs; there's
385 * no hw-flush space.
386 */
387 void
sun4_vcache_flush_region(vreg)388 sun4_vcache_flush_region(vreg)
389 register int vreg;
390 {
391 register int i, ls;
392 register char *p;
393
394 cachestats.cs_nrgflush++;
395 p = (char *)VRTOVA(vreg); /* reg..reg+sz rather than 0..sz */
396 ls = CACHEINFO.c_linesize;
397 i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
398 for (; --i >= 0; p += ls)
399 sta(p, ASI_FLUSHREG, 0);
400 }
401
402 /*
403 * Flush the given virtual segment from the cache.
404 *
405 * This is also done by writing to each cache line, except that
406 * now the addresses must include the virtual segment number, and
407 * we use the `flush segment' space.
408 *
409 * Again, for hardware, we just write each page (in hw-flush space).
410 */
411 void
sun4_vcache_flush_segment(vreg,vseg)412 sun4_vcache_flush_segment(vreg, vseg)
413 register int vreg, vseg;
414 {
415 register int i, ls;
416 register char *p;
417
418 cachestats.cs_nsgflush++;
419 p = (char *)VSTOVA(vreg, vseg); /* seg..seg+sz rather than 0..sz */
420 if (CACHEINFO.c_hwflush) {
421 ls = NBPG;
422 i = CACHEINFO.c_totalsize >> PGSHIFT;
423 for (; --i >= 0; p += ls)
424 sta(p, ASI_HWFLUSHSEG, 0);
425 } else {
426 ls = CACHEINFO.c_linesize;
427 i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
428 for (; --i >= 0; p += ls)
429 sta(p, ASI_FLUSHSEG, 0);
430 }
431 }
432
433 /*
434 * Flush the given virtual page from the cache.
435 * (va is the actual address, and must be aligned on a page boundary.)
436 * Again we write to each cache line.
437 */
438 void
sun4_vcache_flush_page(va)439 sun4_vcache_flush_page(va)
440 int va;
441 {
442 register int i, ls;
443 register char *p;
444
445 #ifdef DEBUG
446 if (va & PGOFSET)
447 panic("cache_flush_page: asked to flush misaligned va 0x%x",va);
448 #endif
449
450 cachestats.cs_npgflush++;
451 p = (char *)va;
452 if (CACHEINFO.c_hwflush)
453 sta(p, ASI_HWFLUSHPG, 0);
454 else {
455 ls = CACHEINFO.c_linesize;
456 i = NBPG >> CACHEINFO.c_l2linesize;
457 for (; --i >= 0; p += ls)
458 sta(p, ASI_FLUSHPG, 0);
459 }
460 }
461
462 /*
463 * Flush a range of virtual addresses (in the current context).
464 * The first byte is at (base&~PGOFSET) and the last one is just
465 * before byte (base+len).
466 *
467 * We choose the best of (context,segment,page) here.
468 */
469
470 #define CACHE_FLUSH_MAGIC (CACHEINFO.c_totalsize / NBPG)
471
472 void
sun4_cache_flush(base,len)473 sun4_cache_flush(base, len)
474 caddr_t base;
475 register u_int len;
476 {
477 register int i, ls, baseoff;
478 register char *p;
479
480 if (CACHEINFO.c_vactype == VAC_NONE)
481 return;
482
483 /*
484 * Figure out how much must be flushed.
485 *
486 * If we need to do CACHE_FLUSH_MAGIC pages, we can do a segment
487 * in the same number of loop iterations. We can also do the whole
488 * region. If we need to do between 2 and NSEGRG, do the region.
489 * If we need to do two or more regions, just go ahead and do the
490 * whole context. This might not be ideal (e.g., fsck likes to do
491 * 65536-byte reads, which might not necessarily be aligned).
492 *
493 * We could try to be sneaky here and use the direct mapping
494 * to avoid flushing things `below' the start and `above' the
495 * ending address (rather than rounding to whole pages and
496 * segments), but I did not want to debug that now and it is
497 * not clear it would help much.
498 *
499 * (XXX the magic number 16 is now wrong, must review policy)
500 */
501 baseoff = (int)base & PGOFSET;
502 i = (baseoff + len + PGOFSET) >> PGSHIFT;
503
504 cachestats.cs_nraflush++;
505 #ifdef notyet
506 cachestats.cs_ra[min(i, MAXCACHERANGE)]++;
507 #endif
508
509 if (i < CACHE_FLUSH_MAGIC) {
510 /* cache_flush_page, for i pages */
511 p = (char *)((int)base & ~baseoff);
512 if (CACHEINFO.c_hwflush) {
513 for (; --i >= 0; p += NBPG)
514 sta(p, ASI_HWFLUSHPG, 0);
515 } else {
516 ls = CACHEINFO.c_linesize;
517 i <<= PGSHIFT - CACHEINFO.c_l2linesize;
518 for (; --i >= 0; p += ls)
519 sta(p, ASI_FLUSHPG, 0);
520 }
521 return;
522 }
523 baseoff = (u_int)base & SGOFSET;
524 i = (baseoff + len + SGOFSET) >> SGSHIFT;
525 if (i == 1)
526 sun4_vcache_flush_segment(VA_VREG(base), VA_VSEG(base));
527 else {
528 if (HASSUN4_MMU3L) {
529 baseoff = (u_int)base & RGOFSET;
530 i = (baseoff + len + RGOFSET) >> RGSHIFT;
531 if (i == 1)
532 sun4_vcache_flush_region(VA_VREG(base));
533 else
534 sun4_vcache_flush_context();
535 } else
536 sun4_vcache_flush_context();
537 }
538 }
539
540
541 #if defined(SUN4M)
542 /*
543 * Flush the current context from the cache.
544 *
545 * This is done by writing to each cache line in the `flush context'
546 * address space (or, for hardware flush, once to each page in the
547 * hardware flush space, for all cache pages).
548 */
549 void
srmmu_vcache_flush_context()550 srmmu_vcache_flush_context()
551 {
552 register char *p;
553 register int i, ls;
554
555 cachestats.cs_ncxflush++;
556 p = (char *)0; /* addresses 0..cacheinfo.c_totalsize will do fine */
557 ls = CACHEINFO.c_linesize;
558 i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
559 for (; --i >= 0; p += ls)
560 sta(p, ASI_IDCACHELFC, 0);
561 }
562
563 /*
564 * Flush the given virtual region from the cache.
565 *
566 * This is also done by writing to each cache line, except that
567 * now the addresses must include the virtual region number, and
568 * we use the `flush region' space.
569 */
570 void
srmmu_vcache_flush_region(vreg)571 srmmu_vcache_flush_region(vreg)
572 register int vreg;
573 {
574 register int i, ls;
575 register char *p;
576
577 cachestats.cs_nrgflush++;
578 p = (char *)VRTOVA(vreg); /* reg..reg+sz rather than 0..sz */
579 ls = CACHEINFO.c_linesize;
580 i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
581 for (; --i >= 0; p += ls)
582 sta(p, ASI_IDCACHELFR, 0);
583 }
584
585 /*
586 * Flush the given virtual segment from the cache.
587 *
588 * This is also done by writing to each cache line, except that
589 * now the addresses must include the virtual segment number, and
590 * we use the `flush segment' space.
591 *
592 * Again, for hardware, we just write each page (in hw-flush space).
593 */
594 void
srmmu_vcache_flush_segment(vreg,vseg)595 srmmu_vcache_flush_segment(vreg, vseg)
596 register int vreg, vseg;
597 {
598 register int i, ls;
599 register char *p;
600
601 cachestats.cs_nsgflush++;
602 p = (char *)VSTOVA(vreg, vseg); /* seg..seg+sz rather than 0..sz */
603 ls = CACHEINFO.c_linesize;
604 i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
605 for (; --i >= 0; p += ls)
606 sta(p, ASI_IDCACHELFS, 0);
607 }
608
609 /*
610 * Flush the given virtual page from the cache.
611 * (va is the actual address, and must be aligned on a page boundary.)
612 * Again we write to each cache line.
613 */
614 void
srmmu_vcache_flush_page(va)615 srmmu_vcache_flush_page(va)
616 int va;
617 {
618 register int i, ls;
619 register char *p;
620
621 #ifdef DEBUG
622 if (va & PGOFSET)
623 panic("cache_flush_page: asked to flush misaligned va 0x%x",va);
624 #endif
625
626 cachestats.cs_npgflush++;
627 p = (char *)va;
628 ls = CACHEINFO.c_linesize;
629 i = NBPG >> CACHEINFO.c_l2linesize;
630 for (; --i >= 0; p += ls)
631 sta(p, ASI_IDCACHELFP, 0);
632 }
633
634 void
srmmu_cache_flush_all()635 srmmu_cache_flush_all()
636 {
637 srmmu_vcache_flush_context();
638 }
639
640 /*
641 * Flush a range of virtual addresses (in the current context).
642 * The first byte is at (base&~PGOFSET) and the last one is just
643 * before byte (base+len).
644 *
645 * We choose the best of (context,segment,page) here.
646 */
647
648 #define CACHE_FLUSH_MAGIC (CACHEINFO.c_totalsize / NBPG)
649
650 void
srmmu_cache_flush(base,len)651 srmmu_cache_flush(base, len)
652 caddr_t base;
653 register u_int len;
654 {
655 register int i, ls, baseoff;
656 register char *p;
657
658 /*
659 * Figure out how much must be flushed.
660 *
661 * If we need to do CACHE_FLUSH_MAGIC pages, we can do a segment
662 * in the same number of loop iterations. We can also do the whole
663 * region. If we need to do between 2 and NSEGRG, do the region.
664 * If we need to do two or more regions, just go ahead and do the
665 * whole context. This might not be ideal (e.g., fsck likes to do
666 * 65536-byte reads, which might not necessarily be aligned).
667 *
668 * We could try to be sneaky here and use the direct mapping
669 * to avoid flushing things `below' the start and `above' the
670 * ending address (rather than rounding to whole pages and
671 * segments), but I did not want to debug that now and it is
672 * not clear it would help much.
673 *
674 * (XXX the magic number 16 is now wrong, must review policy)
675 */
676 baseoff = (int)base & PGOFSET;
677 i = (baseoff + len + PGOFSET) >> PGSHIFT;
678
679 cachestats.cs_nraflush++;
680 #ifdef notyet
681 cachestats.cs_ra[min(i, MAXCACHERANGE)]++;
682 #endif
683
684 if (i < CACHE_FLUSH_MAGIC) {
685 /* cache_flush_page, for i pages */
686 p = (char *)((int)base & ~baseoff);
687 ls = CACHEINFO.c_linesize;
688 i <<= PGSHIFT - CACHEINFO.c_l2linesize;
689 for (; --i >= 0; p += ls)
690 sta(p, ASI_IDCACHELFP, 0);
691 return;
692 }
693 baseoff = (u_int)base & SGOFSET;
694 i = (baseoff + len + SGOFSET) >> SGSHIFT;
695 if (i == 1)
696 srmmu_vcache_flush_segment(VA_VREG(base), VA_VSEG(base));
697 else {
698 baseoff = (u_int)base & RGOFSET;
699 i = (baseoff + len + RGOFSET) >> RGSHIFT;
700 if (i == 1)
701 srmmu_vcache_flush_region(VA_VREG(base));
702 else
703 srmmu_vcache_flush_context();
704 }
705 }
706
707 void
ms1_cache_flush(base,len)708 ms1_cache_flush(base, len)
709 caddr_t base;
710 register u_int len;
711 {
712 /*
713 * Although physically tagged, we still need to flush the
714 * data cache after (if we have a write-through cache) or before
715 * (in case of write-back caches) DMA operations.
716 */
717
718 /* XXX investigate other methods instead of blowing the entire cache */
719 sta(0, ASI_DCACHECLR, 0);
720 }
721
722 /*
723 * Flush entire cache.
724 */
725 void
ms1_cache_flush_all()726 ms1_cache_flush_all()
727 {
728
729 /* Flash-clear both caches */
730 sta(0, ASI_ICACHECLR, 0);
731 sta(0, ASI_DCACHECLR, 0);
732 }
733
734 void
hypersparc_cache_flush_all()735 hypersparc_cache_flush_all()
736 {
737
738 srmmu_vcache_flush_context();
739 /* Flush instruction cache */
740 hypersparc_pure_vcache_flush();
741 }
742
743 void
cypress_cache_flush_all()744 cypress_cache_flush_all()
745 {
746 extern char kernel_text[];
747 char *p;
748 int i, ls;
749
750 /* Fill the cache with known read-only content */
751 p = (char *)kernel_text;
752 ls = CACHEINFO.c_linesize;
753 i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
754 for (; --i >= 0; p += ls)
755 (*(volatile char *)p);
756 }
757
758 void
viking_cache_flush(base,len)759 viking_cache_flush(base, len)
760 caddr_t base;
761 register u_int len;
762 {
763 /*
764 * Although physically tagged, we still need to flush the
765 * data cache after (if we have a write-through cache) or before
766 * (in case of write-back caches) DMA operations.
767 */
768
769 }
770
771 void
viking_pcache_flush_line(va,pa)772 viking_pcache_flush_line(va, pa)
773 int va;
774 int pa;
775 {
776 /*
777 * Flush cache line corresponding to virtual address `va'
778 * which is mapped at physical address `pa'.
779 */
780 extern char etext[];
781 static char *base;
782 int i;
783 char *v;
784
785 /*
786 * Construct a virtual address that hits the same cache line
787 * as PA, then read from 2*ASSOCIATIVITY-1 different physical
788 * locations (all different from PA).
789 */
790
791 #if 0
792 if (base == 0) {
793 cshift = CACHEINFO.ic_l2linesize;
794 csize = CACHEINFO.ic_nlines << cshift;
795 cmask = csize - 1;
796 base = (char *)roundup((int)etext, csize);
797 }
798
799 v = base + (((va & cmask) >> cshift) << cshift);
800 i = CACHEINFO.dc_associativity * 2 - 1;
801
802 while (i--) {
803 (*(volatile int *)v);
804 v += csize;
805 }
806 #else
807 #define cshift 5 /* CACHEINFO.ic_l2linesize */
808 #define csize (128 << cshift) /* CACHEINFO.ic_nlines << cshift */
809 #define cmask (csize - 1)
810 #define cass 4 /* CACHEINFO.dc_associativity */
811
812 if (base == 0)
813 base = (char *)roundup((unsigned int)etext, csize);
814
815 v = base + (((pa & cmask) >> cshift) << cshift);
816 i = 2 * cass - 1;
817
818 while (i--) {
819 (*(volatile int *)v);
820 v += csize;
821 }
822 #undef cass
823 #undef cmask
824 #undef csize
825 #undef cshift
826 #endif
827 }
828
829 void
srmmu_pcache_flush_line(va,pa)830 srmmu_pcache_flush_line(va, pa)
831 int va;
832 int pa;
833 {
834 /*
835 * Flush cache line corresponding to virtual address `va'
836 * which is mapped at physical address `pa'.
837 */
838 sta(va, ASI_IDCACHELFP, 0);
839 }
840 #endif /* SUN4M */
841