Annotation of sys/arch/sparc/sparc/cache.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: cache.c,v 1.18 2007/01/22 19:39:33 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: #if defined(solbourne)
74: #include <machine/idt.h>
75: #include <machine/kap.h>
76: #endif
77:
78: struct cachestats cachestats;
79:
80: int cache_alias_dist; /* Cache anti-aliasing constants */
81: int cache_alias_bits;
82:
83: /*
84: * Enable the cache.
85: * We need to clear out the valid bits first.
86: */
87: void
88: sun4_cache_enable()
89: {
90: u_int i, lim, ls, ts;
91:
92: cache_alias_bits = CPU_ISSUN4
93: ? CACHE_ALIAS_BITS_SUN4
94: : CACHE_ALIAS_BITS_SUN4C;
95: cache_alias_dist = CPU_ISSUN4
96: ? CACHE_ALIAS_DIST_SUN4
97: : CACHE_ALIAS_DIST_SUN4C;
98:
99: ls = CACHEINFO.c_linesize;
100: ts = CACHEINFO.c_totalsize;
101:
102: for (i = AC_CACHETAGS, lim = i + ts; i < lim; i += ls)
103: sta(i, ASI_CONTROL, 0);
104:
105: stba(AC_SYSENABLE, ASI_CONTROL,
106: lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_CACHE);
107: CACHEINFO.c_enabled = 1;
108:
109: printf("cache enabled\n");
110:
111: #ifdef notyet
112: if (cpuinfo.flags & SUN4_IOCACHE) {
113: stba(AC_SYSENABLE, ASI_CONTROL,
114: lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_IOCACHE);
115: printf("iocache enabled\n");
116: }
117: #endif
118: }
119:
120: #if defined(SUN4M)
121: void
122: ms1_cache_enable()
123: {
124: u_int pcr;
125:
126: cache_alias_dist = max(
127: CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity,
128: CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity);
129: cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
130:
131: pcr = lda(SRMMU_PCR, ASI_SRMMU);
132:
133: /* We "flash-clear" the I/D caches. */
134: if ((pcr & MS1_PCR_ICE) == 0)
135: sta(0, ASI_ICACHECLR, 0);
136: if ((pcr & MS1_PCR_DCE) == 0)
137: sta(0, ASI_DCACHECLR, 0);
138:
139: /* Turn on caches */
140: sta(SRMMU_PCR, ASI_SRMMU, pcr | MS1_PCR_DCE | MS1_PCR_ICE);
141:
142: CACHEINFO.c_enabled = CACHEINFO.dc_enabled = 1;
143:
144: /*
145: * When zeroing or copying pages, there might still be entries in
146: * the cache, since we don't flush pages from the cache when
147: * unmapping them (`vactype' is VAC_NONE). Fortunately, the
148: * MS1 cache is write-through and not write-allocate, so we can
149: * use cacheable accesses while not displacing cache lines.
150: */
151: cpuinfo.flags |= CPUFLG_CACHE_MANDATORY;
152:
153: printf("cache enabled\n");
154: }
155:
156: void
157: viking_cache_enable()
158: {
159: u_int pcr;
160:
161: cache_alias_dist = max(
162: CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity,
163: CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity);
164: cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
165:
166: pcr = lda(SRMMU_PCR, ASI_SRMMU);
167:
168: if ((pcr & VIKING_PCR_ICE) == 0) {
169: /* I-cache not on; "flash-clear" it now. */
170: sta(0x80000000, ASI_ICACHECLR, 0); /* Unlock */
171: sta(0, ASI_ICACHECLR, 0); /* clear */
172: }
173: if ((pcr & VIKING_PCR_DCE) == 0) {
174: /* D-cache not on: "flash-clear" it. */
175: sta(0x80000000, ASI_DCACHECLR, 0);
176: sta(0, ASI_DCACHECLR, 0);
177: }
178:
179: /* Turn on caches via MMU */
180: sta(SRMMU_PCR, ASI_SRMMU, pcr | VIKING_PCR_DCE | VIKING_PCR_ICE);
181:
182: CACHEINFO.c_enabled = CACHEINFO.dc_enabled = 1;
183:
184: /* Now turn on MultiCache if it exists */
185: if (cpuinfo.mxcc && CACHEINFO.ec_totalsize > 0) {
186: /* Multicache controller */
187: stda(MXCC_ENABLE_ADDR, ASI_CONTROL,
188: ldda(MXCC_ENABLE_ADDR, ASI_CONTROL) |
189: (u_int64_t)MXCC_ENABLE_BIT);
190: cpuinfo.flags |= CPUFLG_CACHEPAGETABLES; /* Ok to cache PTEs */
191: CACHEINFO.ec_enabled = 1;
192: }
193: printf("cache enabled\n");
194: }
195:
196: void
197: hypersparc_cache_enable()
198: {
199: int i, ls, ts;
200: u_int pcr, v;
201: extern u_long dvma_cachealign;
202:
203: ls = CACHEINFO.c_linesize;
204: ts = CACHEINFO.c_totalsize;
205:
206: pcr = lda(SRMMU_PCR, ASI_SRMMU);
207:
208: /*
209: * Setup the anti-aliasing constants and DVMA alignment constraint.
210: */
211: cache_alias_dist = CACHEINFO.c_totalsize;
212: cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
213: dvma_cachealign = cache_alias_dist;
214:
215: /* Now reset cache tag memory if cache not yet enabled */
216: if ((pcr & HYPERSPARC_PCR_CE) == 0)
217: for (i = 0; i < ts; i += ls) {
218: sta(i, ASI_DCACHETAG, 0);
219: while (lda(i, ASI_DCACHETAG))
220: sta(i, ASI_DCACHETAG, 0);
221: }
222:
223: pcr &= ~(HYPERSPARC_PCR_CE | HYPERSPARC_PCR_CM);
224:
225: hypersparc_cache_flush_all();
226:
227: pcr |= HYPERSPARC_PCR_CE;
228: if (CACHEINFO.c_vactype == VAC_WRITEBACK)
229: pcr |= HYPERSPARC_PCR_CM;
230:
231: sta(SRMMU_PCR, ASI_SRMMU, pcr);
232: CACHEINFO.c_enabled = 1;
233:
234: /* XXX: should add support */
235: if (CACHEINFO.c_hwflush)
236: panic("cache_enable: can't handle 4M with hw-flush cache");
237:
238: #ifdef notyet
239: /*
240: * Enable instruction cache and, on single-processor machines,
241: * disable `Unimplemented Flush Traps'.
242: */
243: v = HYPERSPARC_ICCR_ICE | (ncpu == 1 ? HYPERSPARC_ICCR_FTD : 0);
244: #else
245: v = HYPERSPARC_ICCR_FTD | HYPERSPARC_ICCR_ICE;
246: #endif
247: wrasr(v, HYPERSPARC_ASRNUM_ICCR);
248:
249: printf("cache enabled\n");
250: }
251:
252: void
253: swift_cache_enable()
254: {
255: int i, ls, ts;
256: u_int pcr;
257:
258: cache_alias_dist = max(
259: CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity,
260: CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity);
261: cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
262:
263: pcr = lda(SRMMU_PCR, ASI_SRMMU);
264: pcr |= (SWIFT_PCR_ICE | SWIFT_PCR_DCE);
265: sta(SRMMU_PCR, ASI_SRMMU, pcr);
266:
267: /* Now reset cache tag memory if cache not yet enabled */
268: ls = CACHEINFO.ic_linesize;
269: ts = CACHEINFO.ic_totalsize;
270: if ((pcr & SWIFT_PCR_ICE) == 0)
271: for (i = 0; i < ts; i += ls)
272: sta(i, ASI_ICACHETAG, 0);
273:
274: ls = CACHEINFO.dc_linesize;
275: ts = CACHEINFO.dc_totalsize;
276: if ((pcr & SWIFT_PCR_DCE) == 0)
277: for (i = 0; i < ts; i += ls) {
278: sta(i, ASI_DCACHETAG, 0);
279: while (lda(i, ASI_DCACHETAG))
280: sta(i, ASI_DCACHETAG, 0);
281: }
282:
283: CACHEINFO.c_enabled = 1;
284: printf("cache enabled\n");
285: }
286:
287: void
288: cypress_cache_enable()
289: {
290: int i, ls, ts;
291: u_int pcr;
292:
293: cache_alias_dist = CACHEINFO.c_totalsize;
294: cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
295:
296: pcr = lda(SRMMU_PCR, ASI_SRMMU);
297: pcr &= ~(CYPRESS_PCR_CE | CYPRESS_PCR_CM);
298:
299: /* Now reset cache tag memory if cache not yet enabled */
300: ls = CACHEINFO.c_linesize;
301: ts = CACHEINFO.c_totalsize;
302: if ((pcr & CYPRESS_PCR_CE) == 0)
303: for (i = 0; i < ts; i += ls) {
304: sta(i, ASI_DCACHETAG, 0);
305: while (lda(i, ASI_DCACHETAG))
306: sta(i, ASI_DCACHETAG, 0);
307: }
308:
309: pcr |= CYPRESS_PCR_CE;
310:
311: #if 1
312: pcr &= ~CYPRESS_PCR_CM; /* XXX Disable write-back mode */
313: #else
314: /* If put in write-back mode, turn it on */
315: if (CACHEINFO.c_vactype == VAC_WRITEBACK)
316: pcr |= CYPRESS_PCR_CM;
317: #endif
318:
319: sta(SRMMU_PCR, ASI_SRMMU, pcr);
320: CACHEINFO.c_enabled = 1;
321: printf("cache enabled\n");
322: }
323:
324: void
325: turbosparc_cache_enable()
326: {
327: int i, ls, ts;
328: u_int pcr, pcf;
329:
330: cache_alias_dist = max(
331: CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity,
332: CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity);
333: cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET;
334:
335: pcr = lda(SRMMU_PCR, ASI_SRMMU);
336:
337: /* Now reset cache tag memory if cache not yet enabled */
338: ls = CACHEINFO.ic_linesize;
339: ts = CACHEINFO.ic_totalsize;
340: if ((pcr & TURBOSPARC_PCR_ICE) == 0)
341: for (i = 0; i < ts; i += ls)
342: sta(i, ASI_ICACHETAG, 0);
343:
344: ls = CACHEINFO.dc_linesize;
345: ts = CACHEINFO.dc_totalsize;
346: if ((pcr & TURBOSPARC_PCR_DCE) == 0)
347: for (i = 0; i < ts; i += ls) {
348: sta(i, ASI_DCACHETAG, 0);
349: while (lda(i, ASI_DCACHETAG))
350: sta(i, ASI_DCACHETAG, 0);
351: }
352:
353: pcr |= (TURBOSPARC_PCR_ICE | TURBOSPARC_PCR_DCE);
354: sta(SRMMU_PCR, ASI_SRMMU, pcr);
355:
356: pcf = lda(SRMMU_PCFG, ASI_SRMMU);
357: if (pcf & TURBOSPARC_PCFG_SNP)
358: printf("DVMA coherent ");
359:
360: CACHEINFO.c_enabled = 1;
361: printf("cache enabled\n");
362: }
363: #endif /* defined(SUN4M) */
364:
365: #if defined(SUN4) || defined(SUN4C)
366: /*
367: * Flush the current context from the cache.
368: *
369: * This is done by writing to each cache line in the `flush context'
370: * address space (or, for hardware flush, once to each page in the
371: * hardware flush space, for all cache pages).
372: */
373: void
374: sun4_vcache_flush_context()
375: {
376: char *p;
377: int i, ls;
378:
379: cachestats.cs_ncxflush++;
380: p = (char *)0; /* addresses 0..cacheinfo.c_totalsize will do fine */
381: if (CACHEINFO.c_hwflush) {
382: ls = NBPG;
383: i = CACHEINFO.c_totalsize >> PGSHIFT;
384: for (; --i >= 0; p += ls)
385: sta(p, ASI_HWFLUSHCTX, 0);
386: } else {
387: ls = CACHEINFO.c_linesize;
388: i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
389: for (; --i >= 0; p += ls)
390: sta(p, ASI_FLUSHCTX, 0);
391: }
392: }
393:
394: /*
395: * Flush the given virtual region from the cache.
396: *
397: * This is also done by writing to each cache line, except that
398: * now the addresses must include the virtual region number, and
399: * we use the `flush region' space.
400: *
401: * This function is only called on sun4's with 3-level MMUs; there's
402: * no hw-flush space.
403: */
404: void
405: sun4_vcache_flush_region(vreg)
406: int vreg;
407: {
408: int i, ls;
409: char *p;
410:
411: cachestats.cs_nrgflush++;
412: p = (char *)VRTOVA(vreg); /* reg..reg+sz rather than 0..sz */
413: ls = CACHEINFO.c_linesize;
414: i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
415: for (; --i >= 0; p += ls)
416: sta(p, ASI_FLUSHREG, 0);
417: }
418:
419: /*
420: * Flush the given virtual segment from the cache.
421: *
422: * This is also done by writing to each cache line, except that
423: * now the addresses must include the virtual segment number, and
424: * we use the `flush segment' space.
425: *
426: * Again, for hardware, we just write each page (in hw-flush space).
427: */
428: void
429: sun4_vcache_flush_segment(vreg, vseg)
430: int vreg, vseg;
431: {
432: int i, ls;
433: char *p;
434:
435: cachestats.cs_nsgflush++;
436: p = (char *)VSTOVA(vreg, vseg); /* seg..seg+sz rather than 0..sz */
437: if (CACHEINFO.c_hwflush) {
438: ls = NBPG;
439: i = CACHEINFO.c_totalsize >> PGSHIFT;
440: for (; --i >= 0; p += ls)
441: sta(p, ASI_HWFLUSHSEG, 0);
442: } else {
443: ls = CACHEINFO.c_linesize;
444: i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
445: for (; --i >= 0; p += ls)
446: sta(p, ASI_FLUSHSEG, 0);
447: }
448: }
449:
450: /*
451: * Flush the given virtual page from the cache.
452: * (va is the actual address, and must be aligned on a page boundary.)
453: * Again we write to each cache line.
454: */
455: void
456: sun4_vcache_flush_page(va)
457: int va;
458: {
459: int i, ls;
460: char *p;
461:
462: #ifdef DEBUG
463: if (va & PGOFSET)
464: panic("cache_flush_page: asked to flush misaligned va 0x%x",va);
465: #endif
466:
467: cachestats.cs_npgflush++;
468: p = (char *)va;
469: if (CACHEINFO.c_hwflush)
470: sta(p, ASI_HWFLUSHPG, 0);
471: else {
472: ls = CACHEINFO.c_linesize;
473: i = NBPG >> CACHEINFO.c_l2linesize;
474: for (; --i >= 0; p += ls)
475: sta(p, ASI_FLUSHPG, 0);
476: }
477: }
478:
479: /*
480: * Flush a range of virtual addresses (in the current context).
481: * The first byte is at (base&~PGOFSET) and the last one is just
482: * before byte (base+len).
483: *
484: * We choose the best of (context,segment,page) here.
485: */
486:
487: #define CACHE_FLUSH_MAGIC (CACHEINFO.c_totalsize / NBPG)
488:
489: void
490: sun4_cache_flush(base, len)
491: caddr_t base;
492: u_int len;
493: {
494: int i, ls, baseoff;
495: char *p;
496:
497: if (CACHEINFO.c_vactype == VAC_NONE)
498: return;
499:
500: /*
501: * Figure out how much must be flushed.
502: *
503: * If we need to do CACHE_FLUSH_MAGIC pages, we can do a segment
504: * in the same number of loop iterations. We can also do the whole
505: * region. If we need to do between 2 and NSEGRG, do the region.
506: * If we need to do two or more regions, just go ahead and do the
507: * whole context. This might not be ideal (e.g., fsck likes to do
508: * 65536-byte reads, which might not necessarily be aligned).
509: *
510: * We could try to be sneaky here and use the direct mapping
511: * to avoid flushing things `below' the start and `above' the
512: * ending address (rather than rounding to whole pages and
513: * segments), but I did not want to debug that now and it is
514: * not clear it would help much.
515: *
516: * (XXX the magic number 16 is now wrong, must review policy)
517: */
518: baseoff = (int)base & PGOFSET;
519: i = (baseoff + len + PGOFSET) >> PGSHIFT;
520:
521: cachestats.cs_nraflush++;
522: #ifdef notyet
523: cachestats.cs_ra[min(i, MAXCACHERANGE)]++;
524: #endif
525:
526: if (i < CACHE_FLUSH_MAGIC) {
527: /* cache_flush_page, for i pages */
528: p = (char *)((int)base & ~baseoff);
529: if (CACHEINFO.c_hwflush) {
530: for (; --i >= 0; p += NBPG)
531: sta(p, ASI_HWFLUSHPG, 0);
532: } else {
533: ls = CACHEINFO.c_linesize;
534: i <<= PGSHIFT - CACHEINFO.c_l2linesize;
535: for (; --i >= 0; p += ls)
536: sta(p, ASI_FLUSHPG, 0);
537: }
538: return;
539: }
540: baseoff = (u_int)base & SGOFSET;
541: i = (baseoff + len + SGOFSET) >> SGSHIFT;
542: if (i == 1)
543: sun4_vcache_flush_segment(VA_VREG(base), VA_VSEG(base));
544: else {
545: if (HASSUN4_MMU3L) {
546: baseoff = (u_int)base & RGOFSET;
547: i = (baseoff + len + RGOFSET) >> RGSHIFT;
548: if (i == 1)
549: sun4_vcache_flush_region(VA_VREG(base));
550: else
551: sun4_vcache_flush_context();
552: } else
553: sun4_vcache_flush_context();
554: }
555: }
556: #endif /* defined(SUN4) || defined(SUN4C) */
557:
558: #if defined(SUN4M)
559: /*
560: * Flush the current context from the cache.
561: *
562: * This is done by writing to each cache line in the `flush context'
563: * address space (or, for hardware flush, once to each page in the
564: * hardware flush space, for all cache pages).
565: */
566: void
567: srmmu_vcache_flush_context()
568: {
569: char *p;
570: int i, ls;
571:
572: cachestats.cs_ncxflush++;
573: p = (char *)0; /* addresses 0..cacheinfo.c_totalsize will do fine */
574: ls = CACHEINFO.c_linesize;
575: i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
576: for (; --i >= 0; p += ls)
577: sta(p, ASI_IDCACHELFC, 0);
578: }
579:
580: /*
581: * Flush the given virtual region from the cache.
582: *
583: * This is also done by writing to each cache line, except that
584: * now the addresses must include the virtual region number, and
585: * we use the `flush region' space.
586: */
587: void
588: srmmu_vcache_flush_region(vreg)
589: int vreg;
590: {
591: int i, ls;
592: char *p;
593:
594: cachestats.cs_nrgflush++;
595: p = (char *)VRTOVA(vreg); /* reg..reg+sz rather than 0..sz */
596: ls = CACHEINFO.c_linesize;
597: i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
598: for (; --i >= 0; p += ls)
599: sta(p, ASI_IDCACHELFR, 0);
600: }
601:
602: /*
603: * Flush the given virtual segment from the cache.
604: *
605: * This is also done by writing to each cache line, except that
606: * now the addresses must include the virtual segment number, and
607: * we use the `flush segment' space.
608: *
609: * Again, for hardware, we just write each page (in hw-flush space).
610: */
611: void
612: srmmu_vcache_flush_segment(vreg, vseg)
613: int vreg, vseg;
614: {
615: int i, ls;
616: char *p;
617:
618: cachestats.cs_nsgflush++;
619: p = (char *)VSTOVA(vreg, vseg); /* seg..seg+sz rather than 0..sz */
620: ls = CACHEINFO.c_linesize;
621: i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
622: for (; --i >= 0; p += ls)
623: sta(p, ASI_IDCACHELFS, 0);
624: }
625:
626: /*
627: * Flush the given virtual page from the cache.
628: * (va is the actual address, and must be aligned on a page boundary.)
629: * Again we write to each cache line.
630: */
631: void
632: srmmu_vcache_flush_page(va)
633: int va;
634: {
635: int i, ls;
636: char *p;
637:
638: #ifdef DEBUG
639: if (va & PGOFSET)
640: panic("cache_flush_page: asked to flush misaligned va 0x%x",va);
641: #endif
642:
643: cachestats.cs_npgflush++;
644: p = (char *)va;
645: ls = CACHEINFO.c_linesize;
646: i = NBPG >> CACHEINFO.c_l2linesize;
647: for (; --i >= 0; p += ls)
648: sta(p, ASI_IDCACHELFP, 0);
649: }
650:
651: void
652: srmmu_cache_flush_all()
653: {
654: srmmu_vcache_flush_context();
655: }
656:
657: /*
658: * Flush a range of virtual addresses (in the current context).
659: * The first byte is at (base&~PGOFSET) and the last one is just
660: * before byte (base+len).
661: *
662: * We choose the best of (context,segment,page) here.
663: */
664:
665: #define CACHE_FLUSH_MAGIC (CACHEINFO.c_totalsize / NBPG)
666:
667: void
668: srmmu_cache_flush(base, len)
669: caddr_t base;
670: u_int len;
671: {
672: int i, ls, baseoff;
673: char *p;
674:
675: /*
676: * Figure out how much must be flushed.
677: *
678: * If we need to do CACHE_FLUSH_MAGIC pages, we can do a segment
679: * in the same number of loop iterations. We can also do the whole
680: * region. If we need to do between 2 and NSEGRG, do the region.
681: * If we need to do two or more regions, just go ahead and do the
682: * whole context. This might not be ideal (e.g., fsck likes to do
683: * 65536-byte reads, which might not necessarily be aligned).
684: *
685: * We could try to be sneaky here and use the direct mapping
686: * to avoid flushing things `below' the start and `above' the
687: * ending address (rather than rounding to whole pages and
688: * segments), but I did not want to debug that now and it is
689: * not clear it would help much.
690: *
691: * (XXX the magic number 16 is now wrong, must review policy)
692: */
693: baseoff = (int)base & PGOFSET;
694: i = (baseoff + len + PGOFSET) >> PGSHIFT;
695:
696: cachestats.cs_nraflush++;
697: #ifdef notyet
698: cachestats.cs_ra[min(i, MAXCACHERANGE)]++;
699: #endif
700:
701: if (i < CACHE_FLUSH_MAGIC) {
702: /* cache_flush_page, for i pages */
703: p = (char *)((int)base & ~baseoff);
704: ls = CACHEINFO.c_linesize;
705: i <<= PGSHIFT - CACHEINFO.c_l2linesize;
706: for (; --i >= 0; p += ls)
707: sta(p, ASI_IDCACHELFP, 0);
708: return;
709: }
710: baseoff = (u_int)base & SGOFSET;
711: i = (baseoff + len + SGOFSET) >> SGSHIFT;
712: if (i == 1)
713: srmmu_vcache_flush_segment(VA_VREG(base), VA_VSEG(base));
714: else {
715: baseoff = (u_int)base & RGOFSET;
716: i = (baseoff + len + RGOFSET) >> RGSHIFT;
717: if (i == 1)
718: srmmu_vcache_flush_region(VA_VREG(base));
719: else
720: srmmu_vcache_flush_context();
721: }
722: }
723:
724: #ifndef MS1_CACHEFLUSH_MAGIC
725: #define MS1_CACHEFLUSH_MAGIC 0 /* 48 */
726: #endif
727: void
728: ms1_cache_flush(base, len)
729: caddr_t base;
730: u_int len;
731: {
732: /*
733: * Although physically tagged, we still need to flush the
734: * data cache after (if we have a write-through cache) or before
735: * (in case of write-back caches) DMA operations.
736: */
737: #if MS1_CACHEFLUSH_MAGIC != 0
738: if (len <= MS1_CACHEFLUSH_MAGIC) {
739: /*
740: * If the range to be flushed is sufficiently small
741: * invalidate the covered cache lines by hand.
742: *
743: * The MicroSPARC I has a direct-mapped virtually addressed
744: * physically tagged data cache which is organised as
745: * 128 lines of 16 bytes. Virtual address bits [4-10]
746: * select the cache line. The cache tags are accessed
747: * through the standard DCACHE control space using the
748: * same address bits as those used to select the cache
749: * line in the virtual address.
750: *
751: * Note: we don't bother to compare the actual tags
752: * since that would require looking up physical addresses.
753: *
754: * The format of the tags we read from ASI_DCACHE control
755: * space is:
756: *
757: * 31 27 26 11 10 1 0
758: * +--------+----------------+------------+-+
759: * | xxx | PA[26-11] | xxx |V|
760: * +--------+----------------+------------+-+
761: *
762: * PA: bits 11-26 of the physical address
763: * V: line valid bit
764: */
765: int tagaddr = ((u_int)base & 0x7f0);
766:
767: len = roundup(len, 16);
768: while (len != 0) {
769: int tag = lda(tagaddr, ASI_DCACHETAG);
770: if ((tag & 1) == 1) {
771: /* Mark this cache line invalid */
772: sta(tagaddr, ASI_DCACHETAG, 0);
773: }
774: len -= 16;
775: tagaddr = (tagaddr + 16) & 0x7f0;
776: }
777: } else
778: #endif
779: /* Flush entire data cache */
780: sta(0, ASI_DCACHECLR, 0);
781: }
782:
783: /*
784: * Flush entire cache.
785: */
786: void
787: ms1_cache_flush_all()
788: {
789:
790: /* Flash-clear both caches */
791: sta(0, ASI_ICACHECLR, 0);
792: sta(0, ASI_DCACHECLR, 0);
793: }
794:
795: void
796: hypersparc_cache_flush_all()
797: {
798:
799: srmmu_vcache_flush_context();
800: /* Flush instruction cache */
801: hypersparc_pure_vcache_flush();
802: }
803:
804: void
805: cypress_cache_flush_all()
806: {
807: extern char kernel_text[];
808: char *p;
809: int i, ls;
810:
811: /* Fill the cache with known read-only content */
812: p = (char *)kernel_text;
813: ls = CACHEINFO.c_linesize;
814: i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize;
815: for (; --i >= 0; p += ls)
816: (*(volatile char *)p);
817: }
818:
819: void
820: viking_cache_flush(base, len)
821: caddr_t base;
822: u_int len;
823: {
824: /*
825: * Although physically tagged, we still need to flush the
826: * data cache after (if we have a write-through cache) or before
827: * (in case of write-back caches) DMA operations.
828: */
829:
830: }
831:
832: void
833: viking_pcache_flush_line(va, pa)
834: int va;
835: int pa;
836: {
837: /*
838: * Flush cache line corresponding to virtual address `va'
839: * which is mapped at physical address `pa'.
840: */
841: extern char etext[];
842: static char *base;
843: int i;
844: char *v;
845:
846: /*
847: * Construct a virtual address that hits the same cache line
848: * as PA, then read from 2*ASSOCIATIVITY-1 different physical
849: * locations (all different from PA).
850: */
851:
852: #if 0
853: if (base == 0) {
854: cshift = CACHEINFO.ic_l2linesize;
855: csize = CACHEINFO.ic_nlines << cshift;
856: cmask = csize - 1;
857: base = (char *)roundup((int)etext, csize);
858: }
859:
860: v = base + (((va & cmask) >> cshift) << cshift);
861: i = CACHEINFO.dc_associativity * 2 - 1;
862:
863: while (i--) {
864: (*(volatile int *)v);
865: v += csize;
866: }
867: #else
868: #define cshift 5 /* CACHEINFO.ic_l2linesize */
869: #define csize (128 << cshift) /* CACHEINFO.ic_nlines << cshift */
870: #define cmask (csize - 1)
871: #define cass 4 /* CACHEINFO.dc_associativity */
872:
873: if (base == 0)
874: base = (char *)roundup((unsigned int)etext, csize);
875:
876: v = base + (((pa & cmask) >> cshift) << cshift);
877: i = 2 * cass - 1;
878:
879: while (i--) {
880: (*(volatile int *)v);
881: v += csize;
882: }
883: #undef cass
884: #undef cmask
885: #undef csize
886: #undef cshift
887: #endif
888: }
889:
890: void
891: srmmu_pcache_flush_line(va, pa)
892: int va;
893: int pa;
894: {
895: /*
896: * Flush cache line corresponding to virtual address `va'
897: * which is mapped at physical address `pa'.
898: */
899: sta(va, ASI_IDCACHELFP, 0);
900: }
901: #endif /* SUN4M */
902:
903: #if defined(solbourne)
904: void
905: kap_cache_enable()
906: {
907: kap_cache_flush(NULL, 0);
908: sta(0, ASI_ICACHE_INVAL, 0);
909:
910: sta(ICU_CONF, ASI_PHYS_IO,
911: lda(ICU_CONF, ASI_PHYS_IO) & ~CONF_ICACHE_DISABLE);
912: CACHEINFO.c_enabled = 1;
913:
914: printf("cache enabled\n");
915: }
916:
917: void
918: kap_vcache_flush_context()
919: {
920: kap_cache_flush(0, 0);
921: sta(0, ASI_DCACHE_INVAL, 0);
922: sta(0, ASI_ICACHE_INVAL, 0);
923: }
924:
925: void
926: kap_vcache_flush_page(va)
927: int va;
928: {
929: kap_cache_flush((caddr_t)va, PAGE_SIZE);
930: }
931:
932: void
933: kap_cache_flush(base, len)
934: caddr_t base;
935: u_int len;
936: {
937: u_int line;
938: u_int32_t mmcr;
939:
940: /*
941: * Due to the small size of the data cache and the fact that we
942: * would be flushing 4 bytes by 4 bytes, it is faster to flush
943: * the whole cache instead.
944: */
945:
946: mmcr = lda(0, ASI_MMCR) & ~(MMCR_DSET0 | MMCR_DSET1);
947: /* flush bank 0 */
948: sta(0, ASI_MMCR, mmcr | MMCR_DSET0);
949: for (line = 0; line < DCACHE_LINE(DCACHE_LINES); line += DCACHE_INCR)
950: (void)lda(line, ASI_DCACHE_FLUSH);
951: /* flush bank 1 */
952: sta(0, ASI_MMCR, mmcr | MMCR_DSET1);
953: for (line = 0; line < DCACHE_LINE(DCACHE_LINES); line += DCACHE_INCR)
954: (void)lda(line, ASI_DCACHE_FLUSH);
955: }
956:
957: #endif /* solbourne */
CVSweb