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