Annotation of sys/arch/mips64/mips64/cache_r5k.S, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: cache_r5k.S,v 1.19 2007/06/18 20:25:55 miod Exp $ */
2:
3: /*
4: * Copyright (c) 1998-2004 Opsycon AB (www.opsycon.se)
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25: * SUCH DAMAGE.
26: *
27: */
28:
29: /*
30: * NOTE!
31: *
32: * This code does not support caches with other linesize than 32.
33: * Neither will it support R4000 or R4400 Secondary caches. These
34: * configurations will need another set of cache functions.
35: *
36: * Processors supported:
37: * R4600/R4700
38: * R5000
39: * RM52xx
40: * RM7xxx
41: * RM9xxx
42: */
43:
44: #include <sys/errno.h>
45: #include <sys/syscall.h>
46:
47: #include <machine/param.h>
48: #include <machine/psl.h>
49: #include <machine/asm.h>
50: #include <machine/cpu.h>
51: #include <machine/regnum.h>
52: #include <machine/pte.h>
53:
54: #include "assym.h"
55:
56: .set mips3
57:
58: #define LOAD_XKPHYS(reg, cca) \
59: li reg, cca | 0x10; \
60: dsll reg, reg, 59
61:
62: /*
63: * Skip the .h file. Noone else need to know!
64: */
65:
66: #define IndexInvalidate_I 0x00
67: #define IndexWBInvalidate_D 0x01
68: #define IndexFlashInvalidate_T 0x02
69: #define IndexWBInvalidate_S 0x03
70:
71: #define IndexLoadTag_I 0x04
72: #define IndexLoadTag_D 0x05
73: #define IndexLoadTag_T 0x06
74: #define IndexLoadTag_S 0x07
75:
76: #define IndexStoreTag_I 0x08
77: #define IndexStoreTag_D 0x09
78: #define IndexStoreTag_T 0x0a
79: #define IndexStoreTag_S 0x0b
80:
81: #define CreateDirtyExclusive 0x09
82:
83: #define HitInvalidate_I 0x10
84: #define HitInvalidate_D 0x11
85: #define HitInvalidate_S 0x13
86:
87: #define Fill_I 0x14
88: #define HitWBInvalidate_D 0x15
89: #define InvalidatePage_T 0x16
90: #define HitWBInvalidate_S 0x17
91:
92: #define HitWB_I 0x18
93: #define HitWB_D 0x19
94: #define HitWB_S 0x1b
95:
96: #define InvalidateSecondaryPage 0x17 /* Only RM527[0-1] */
97:
98:
99:
100: /*
101: * R5000 config register bits.
102: */
103: #define CF_5_SE (1 << 12) /* Secondary cache enable */
104: #define CF_5_SC (1 << 17) /* Secondary cache not present */
105: #define CF_5_SS (3 << 20) /* Secondary cache size */
106: #define CF_5_SS_AL 20 /* Shift to align */
107:
108: /*
109: * RM52xx config register bits. (like R5000)
110: */
111: #define CF_52_SE (1 << 12) /* Secondary cache enable */
112: #define CF_52_SC (1 << 17) /* Secondary cache not present */
113: #define CF_52_SS (3 << 20) /* Secondary cache size */
114: #define CF_52_SS_AL 20 /* Shift to align */
115:
116: /*
117: * RM7000 config register bits.
118: */
119: #define CF_7_SE (1 << 3) /* Secondary cache enable */
120: #define CF_7_SC (1 << 31) /* Secondary cache not present */
121: #define CF_7_TE (1 << 12) /* Tertiary cache enable */
122: #define CF_7_TC (1 << 17) /* Tertiary cache not present */
123: #define CF_7_TS (3 << 20) /* Tertiary cache size */
124: #define CF_7_TS_AL 20 /* Shift to align */
125:
126: /*
127: * Define cache type definition bits. NOTE! the 3 lsb may NOT change!
128: */
129: #define CTYPE_DIR 0x0001 /* Cache is direct mapped */
130: #define CTYPE_2WAY 0x0002 /* Cache is TWO way */
131: #define CTYPE_4WAY 0x0004 /* Cache is FOUR way */
132: #define CTYPE_WAYMASK 0x0007
133:
134: #define CTYPE_HAS_IL2 0x0100 /* Internal L2 Cache present */
135: #define CTYPE_HAS_XL2 0x0200 /* External L2 Cache present */
136: #define CTYPE_HAS_XL3 0x0400 /* External L3 Cache present */
137:
138: /*
139: * Due to a flaw in RM7000 1.x processors a pipleine 'drain' is
140: * required after some mtc0 instructions.
141: * Ten nops in sequence does the trick.
142: */
143: #define NOP10 nop;nop;nop;nop;nop;\
144: nop;nop;nop;nop;nop /* Two cycles for dual issue machine */
145:
146: .set noreorder # Noreorder is default style!
147:
148: /*----------------------------------------------------------------------------
149: *
150: * Mips5k_ConfigCache --
151: *
152: * Size and configure the caches.
153: * NOTE: should only be called from mips_init().
154: *
155: * Results:
156: * Returns the value of the cpu configuration register.
157: *
158: * Side effects:
159: * The size of the data cache is stored into CpuPrimaryDataCacheSize.
160: * The size of instruction cache is stored into CpuPrimaryInstCacheSize.
161: * Alignment mask for cache aliasing test is stored in CpuCacheAliasMask.
162: * CpuSecondaryCacheSize is set to the size of the secondary cache.
163: * CpuTertiaryCacheSize is set to the size of the tertiary cache.
164: * CpuNWayCache is set to 0 for direct mapped caches, 2 for two way
165: * caches and 4 for four way caches. This primarily indicates the
166: * primary cache associativity.
167: *
168: * Allocation:
169: * ta0, ta1 ta2 used to hold I and D set size and Alias mask.
170: *
171: *----------------------------------------------------------------------------
172: */
173: LEAF(Mips5k_ConfigCache, 0)
174: .set noreorder
175: LA v0, 1f
176: LA v1, KSEG1_BASE
177: or v0, v1
178: jr v0 # Switch to uncached.
179: nop
180: 1:
181: mfc0 v1, COP_0_PRID # read processor ID register
182: mfc0 v0, COP_0_CONFIG # Get configuration register
183:
184: srl t1, v0, 9 # Get I cache size.
185: and t1, 3
186: li t2, 4096
187: sllv ta0, t2, t1 # ta0 = Initial I set size.
188:
189: and t2, v0, 0x20
190: srl t2, t2, 1 # Get I cache line size.
191: addu t2, t2, 16
192: sw t2, CpuPrimaryInstCacheLSize
193:
194: srl t1, v0, 6 # Get D cache size.
195: and t1, 3
196: li t2, 4096 # Fixed page size.
197: sllv ta1, t2, t1
198:
199: and t2, v0, 0x10
200: addu t2, t2, 16 # Get D cache line size.
201: sw t2, CpuPrimaryDataCacheLSize
202:
203: li t2, CTYPE_2WAY # Assume two way cache
204: li ta2, 0 # Secondary size 0.
205: li ta3, 0 # Tertiary size 0.
206:
207: and v1, 0xff00 # Recognize CPU's with
208: li t1, (MIPS_R4600 << 8) # N way L1 caches only.
209: beq v1, t1, ConfResult # R4K 2 way, no L2 control
210: li t1, (MIPS_R4700 << 8)
211: beq v1, t1, ConfResult # R4K 2 way, No L2 control
212: li t1, (MIPS_R5000 << 8)
213: beq v1, t1, Conf5K # R5K 2 way, check L2
214: li t1, (MIPS_RM52X0 << 8)
215: beq v1, t1, Conf52K # R52K 2 way, check L2
216: li t1, (MIPS_RM7000 << 8)
217: beq v1, t1, Conf7K
218: li t1, (MIPS_RM9000 << 8)
219: beq v1, t1, Conf7K
220: nop
221: # R4000PC/R4400PC or unknown.
222: li t2, CTYPE_DIR # default direct mapped cache
223: b ConfResult
224: nop
225:
226: #---- R5K ------------------------------
227: Conf5K: # R5xxx type, check for L2 cache
228: and t1, v0, CF_5_SC
229: bnez t1, ConfResult # not enabled
230: li ta2, 0 # set size to 0.
231:
232: li t3, CF_5_SS
233: and t1, t3, v0
234: beq t1, t3, ConfResult # No L2 cache
235: srl t1, CF_5_SS_AL
236:
237: li t3, CF_5_SE # Set SE in conf
238: or v0, t3 # Update config register
239: li ta2, 512*1024 # 512k per 'click'.
240: sll ta2, t1
241:
242: mtc0 v0, COP_0_CONFIG # Enable L2 cache
243: or t2, CTYPE_HAS_XL2 # External L2 present.
244: LOAD_XKPHYS(t0, CCA_NONCOHERENT)
245: PTR_ADDU t1, t0, ta2
246: 1:
247: cache InvalidateSecondaryPage, 0(t0)
248: PTR_ADDU t0, 4096
249: bne t0, t1, 1b
250: nop
251:
252: b ConfResult
253: nop
254:
255:
256: #---- R52K ------------------------------
257: Conf52K: # R5200 type, check for L2 cache
258: and t1, v0, CF_52_SC
259: bnez t1, ConfResult # not present
260: li ta2, 0 # set size to 0.
261:
262: li t3, CF_52_SS
263: and t1, t3, v0
264: beq t1, t3, ConfResult # No L2 cache
265: srl t1, CF_52_SS_AL
266:
267: li t3, CF_52_SE # Set SE in conf
268: or v0, t3 # Update config register
269: li ta2, 512*1024 # 512k per 'click'.
270: sll ta2, t1
271:
272: mtc0 v0, COP_0_CONFIG # Enable L2 cache
273: or t2, CTYPE_HAS_XL2 # External L2 present.
274: LOAD_XKPHYS(t0, CCA_NONCOHERENT)
275: PTR_ADDU t1, t0, ta2
276: 1:
277: cache InvalidateSecondaryPage, 0(t0)
278: PTR_ADDU t0, 4096
279: bne t0, t1, 1b
280: nop
281:
282: b ConfResult
283: nop
284:
285:
286: #---- RM7K -----------------------------
287: Conf7K: # RM7000, check for L2 and L3 cache
288: li t2, CTYPE_4WAY # 4-way cache
289: and t1, v0, CF_7_TC
290: bnez t1, Conf7KL2 # No L3 cache if set
291: li ta3, 0 # Set size = 0
292:
293: #ifndef L3SZEXT
294: li t3, CF_7_TS
295: and t1, t3, v0
296: beq t1, t3, Conf7KL2 # No L3 cache
297: srl t1, CF_7_TS_AL
298:
299: or t2, CTYPE_HAS_XL3 # External L2 present.
300: li t3, CF_7_TE # Set SE in conf
301: or v0, t3 # Update config register
302: li ta3, 512*1024 # 512k per 'click'.
303: sll ta3, t1
304: #else
305: lw ta3, CpuTertiaryCacheSize
306: and t2, ~CTYPE_HAS_XL3
307: beqz ta3, Conf7KL2 # No L3 cache present
308: nop
309:
310: li t3, CF_7_TE # Set SE in conf
311: or v0, t3 # Update config register
312: mtc0 v0, COP_0_CONFIG # Enable L3 cache
313: or t2, CTYPE_HAS_XL3
314: #endif
315: LOAD_XKPHYS(t0, CCA_NONCOHERENT)
316: PTR_ADDU t1, t0, ta3
317: 1:
318: cache InvalidatePage_T, 0(t0)
319: PTR_ADDU t0, 4096
320: bne t0, t1, 1b
321: nop
322:
323:
324: Conf7KL2:
325: and t1, v0, CF_7_SC # check for L2 cache
326: bnez t1, ConfResult
327: li ta2, 0 # No L2?
328:
329: and t1, v0, CF_7_SE
330: bnez t1, 3f
331: ori v0, CF_7_SE
332:
333: mtc0 v0, COP_0_CONFIG # Enable and init L2 cache
334: LOAD_XKPHYS(t0, CCA_NONCOHERENT)
335: PTR_ADDU t1, t0, ta3
336: 1:
337: PTR_ADDU t0, 32
338: bne t0, t1, 1b
339: cache IndexStoreTag_S, -4(t0)
340: sync
341:
342: LOAD_XKPHYS(t0, CCA_NONCOHERENT)
343: PTR_ADDU t1, t0, ta3
344: 1:
345: PTR_ADDU t0, 32
346: bne t0, t1, 1b
347: lw zero, -4(t0)
348: sync
349:
350: LOAD_XKPHYS(t0, CCA_NONCOHERENT)
351: PTR_ADDU t1, t0, ta3
352: 1:
353: PTR_ADDU t0, 32
354: bne t0, t1, 1b
355: cache IndexStoreTag_S, -4(t0)
356: sync
357:
358: 3:
359: or t2, CTYPE_HAS_IL2 # L2 is on chip
360: b ConfResult
361: li ta2, 256*1024 # L2 size = 256k
362:
363: /*
364: * Get here with t2 = Cache type, ta0 = L1 I size, ta1 = L1 D size.
365: * ta2 = secondary size, ta3 = tertiary size.
366: */
367: ConfResult:
368: sw v0, CpuConfigRegister
369: mfc0 t3, COP_0_STATUS_REG
370: sw t2, CpuCacheType # Save cache attributes
371: sw t3, CpuStatusRegister
372: and t2, CTYPE_WAYMASK # isolate number of sets.
373: sw t2, CpuNWayCache
374: srl t2, 1 # get div shift for set size.
375:
376: sw ta2, CpuSecondaryCacheSize
377: sw ta3, CpuTertiaryCacheSize
378:
379: addu t1, ta0, -1 # Use icache for alias mask
380: srl t1, t2 # Some cpus have different
381: and t1, ~(NBPG - 1) # i and d cache sizes...
382: sw t1, CpuCacheAliasMask
383:
384: sw ta0, CpuPrimaryInstCacheSize # store cache size.
385: srl ta0, t2 # calculate set size.
386: sw ta0, CpuPrimaryInstSetSize
387:
388: sw ta1, CpuPrimaryDataCacheSize # store cache size.
389: srl ta1, t2 # calculate set size.
390: sw ta1, CpuPrimaryDataSetSize
391:
392: and v0, 0xfffffff8
393: or v0, 0x00000003 # set cachable writeback kseg0
394: mtc0 v0, COP_0_CONFIG # establish any new config
395: NOP10
396: j ra
397: nop
398: END(Mips5k_ConfigCache)
399:
400: /*----------------------------------------------------------------------------
401: *
402: * Mips5k_SyncCache --
403: *
404: * Sync ALL caches.
405: * No need to look at number of sets since we are cleaning out
406: * the entire cache and thus will address all sets anyway.
407: *
408: * Results:
409: * None.
410: *
411: * Side effects:
412: * The contents of ALL caches are Invalidated or Synched.
413: *
414: *----------------------------------------------------------------------------
415: */
416: LEAF(Mips5k_SyncCache, 0)
417: .set noreorder
418: lw t1, CpuPrimaryInstCacheSize
419: lw t2, CpuPrimaryDataCacheSize
420:
421: /*
422: * Sync the instruction cache.
423: */
424: #ifdef CPUR4600
425: mfc0 v1, COP_0_STATUS_REG # Save the status register.
426: li v0, SR_DIAG_DE
427: mtc0 v0, COP_0_STATUS_REG # Disable interrupts
428: #endif
429:
430: LOAD_XKPHYS(t0, CCA_NONCOHERENT)
431: PTR_ADDU t1, t0, t1 # Compute end address
432: PTR_SUBU t1, 128
433:
434: 1:
435: cache IndexInvalidate_I, 0(t0)
436: cache IndexInvalidate_I, 32(t0)
437: cache IndexInvalidate_I, 64(t0)
438: cache IndexInvalidate_I, 96(t0)
439:
440: bne t0, t1, 1b
441: PTR_ADDU t0, t0, 128
442:
443: /*
444: * Sync the data cache. Do L1 first. Indexed only operate on
445: * the selected cache and differs from Hit in that sense.
446: */
447:
448: LOAD_XKPHYS(t0, CCA_NONCOHERENT)
449: PTR_ADDU t1, t0, t2 # End address
450: PTR_SUBU t1, t1, 128
451: 1:
452: cache IndexWBInvalidate_D, 0(t0)
453: cache IndexWBInvalidate_D, 32(t0)
454: cache IndexWBInvalidate_D, 64(t0)
455: cache IndexWBInvalidate_D, 96(t0)
456:
457: bne t0, t1, 1b
458: PTR_ADDU t0, t0, 128
459:
460: /* Do on chip L2 if present */
461: lw t0, CpuCacheType
462: and t0, CTYPE_HAS_IL2
463: beqz t0, 20f
464: nop
465:
466: 3:
467: LOAD_XKPHYS(t3, CCA_NONCOHERENT)
468: lw ta0, CpuSecondaryCacheSize
469: 10:
470: cache IndexWBInvalidate_S, 0(t3)
471: PTR_SUBU ta0, 32 # Fixed cache line size.
472: bgtz ta0, 10b
473: PTR_ADDU t3, 32
474:
475: /* Do off chip L2 if present */
476: 20:
477: lw t0, CpuCacheType
478: and t0, CTYPE_HAS_XL2
479: beqz t0, 30f
480: nop
481:
482: mtc0 zero, COP_0_TAG_LO
483: LOAD_XKPHYS(t3, CCA_NONCOHERENT)
484: lw ta0, CpuSecondaryCacheSize
485: 21:
486: cache InvalidateSecondaryPage, 0(t3)
487: PTR_SUBU ta0, 4096 # Fixed cache page size.
488: bgtz ta0, 21b
489: PTR_ADDU t3, 4096
490:
491: /* Do off chip L3 if present */
492: 30:
493: lw t0, CpuCacheType
494: and t0, CTYPE_HAS_XL3
495: beqz t0, 99f
496: nop
497:
498: mtc0 zero, COP_0_TAG_LO
499: LOAD_XKPHYS(t3, CCA_NONCOHERENT)
500: lw ta0, CpuTertiaryCacheSize
501: 31:
502: cache InvalidatePage_T, 0(t3)
503: PTR_SUBU ta0, 4096 # Fixed cache page size.
504: bgtz ta0, 31b
505: PTR_ADDU t3, 4096
506:
507: 99:
508: #ifdef CPUR4600
509: mtc0 v1, COP_0_STATUS_REG # Restore the status register.
510: NOP10
511: #endif
512: j ra
513: nop
514: END(Mips5k_SyncCache)
515:
516: /*----------------------------------------------------------------------------
517: *
518: * Mips5k_InvalidateICachePage --
519: *
520: * void Mips5k_InvalidateICachePage(addr)
521: * vaddr_t addr;
522: *
523: * Invalidate the L1 instruction cache page given by addr.
524: *
525: * Results:
526: * Void.
527: *
528: * Side effects:
529: * The contents of the L1 Instruction cache is flushed.
530: *
531: *----------------------------------------------------------------------------
532: */
533: LEAF(Mips5k_InvalidateICachePage, 0)
534: #ifdef CPUR4600
535: mfc0 v1, COP_0_STATUS_REG # Save the status register.
536: li v0, SR_DIAG_DE
537: mtc0 v0, COP_0_STATUS_REG # Disable interrupts
538: #endif
539: lw v0, CpuNWayCache # Cache properties
540: lw t0, CpuPrimaryInstSetSize # Set size
541: and a0, ~PAGE_MASK # Page align start address
542: PTR_ADDU a1, a0, PAGE_SIZE-128 # End address.
543: addiu v0, -2 # <0 1way, 0 = two, >0 four
544: 1:
545: cache HitInvalidate_I, 0(a0)
546: cache HitInvalidate_I, 32(a0)
547: cache HitInvalidate_I, 64(a0)
548: cache HitInvalidate_I, 96(a0)
549:
550: bne a0, a1, 1b
551: PTR_ADDU a0, 128
552:
553: #ifdef CPUR4600
554: mtc0 v1, COP_0_STATUS_REG # Restore the status register.
555: NOP10
556: #endif
557: j ra
558: move v0, zero
559: END(Mips5k_InvalidateICachePage)
560:
561: /*----------------------------------------------------------------------------
562: *
563: * Mips5k_InvalidateICache --
564: *
565: * void Mips5k_SyncICache(addr, len)
566: * vaddr_t addr, len;
567: *
568: * Invalidate the L1 instruction cache for at least range
569: * of addr to addr + len - 1.
570: * The address is reduced to a XKPHYS index to avoid TLB faults.
571: *
572: * Results:
573: * None.
574: *
575: * Side effects:
576: * The contents of the L1 Instruction cache is flushed.
577: * Must not touch v0.
578: *
579: *----------------------------------------------------------------------------
580: */
581: LEAF(Mips5k_InvalidateICache, 0)
582: #ifdef CPUR4600
583: mfc0 v1, COP_0_STATUS_REG # Save the status register.
584: li v0, SR_DIAG_DE
585: mtc0 v0, COP_0_STATUS_REG # Disable interrupts
586: #endif
587: lw v0, CpuNWayCache # Cache properties
588: lw t0, CpuPrimaryInstSetSize # Set size
589: and a0, 0x00ffffff # Reduce addr to cache index
590: LOAD_XKPHYS(a2, CCA_NONCOHERENT)
591: PTR_ADDU a1, 31 # Round up size
592: PTR_ADDU a1, a0 # Add extra from address
593: and a0, -32 # Align start address
594: PTR_SUBU a1, a1, a0
595: PTR_ADDU a0, a2 # a0 now new XKPHYS address
596: srl a1, a1, 5 # Number of unrolled loops
597: addiu v0, -2 # <0 1way, 0 = two, >0 four
598: 1:
599: bltz v0, 3f
600: addu a1, -1
601:
602: 2:
603: PTR_ADDU t1, t0, a0 # Nway cache, flush set B.
604: cache IndexInvalidate_I, 0(t1)
605: beqz v0, 3f # Is two way do set A
606: PTR_ADDU t1, t0 # else step to set C.
607:
608: cache IndexInvalidate_I, 0(t1)
609:
610: PTR_ADDU t1, t0 # step to set D
611: cache IndexInvalidate_I, 0(t1)
612:
613: 3:
614: cache IndexInvalidate_I, 0(a0) # do set (A if NWay)
615:
616: bne a1, zero, 1b
617: PTR_ADDU a0, 32
618:
619: #ifdef CPUR4600
620: mtc0 v1, COP_0_STATUS_REG # Restore the status register.
621: NOP10
622: #endif
623: j ra
624: move v0, zero
625: END(Mips5k_InvalidateICache)
626:
627: /*----------------------------------------------------------------------------
628: *
629: * Mips5k_SyncDCachePage --
630: *
631: * void Mips5k_SyncDCachePage(addr)
632: * vaddr_t addr;
633: *
634: * Sync the L1 data cache page for address addr.
635: * The address is reduced to a XKPHYS index to avoid TLB faults.
636: *
637: * Results:
638: * None.
639: *
640: * Side effects:
641: * The contents of the cache is written back to primary memory.
642: * The cache line is invalidated.
643: *
644: *----------------------------------------------------------------------------
645: */
646: LEAF(Mips5k_SyncDCachePage, 0)
647: #ifdef CPUR4600
648: mfc0 v1, COP_0_STATUS_REG # Save the status register.
649: li v0, SR_DIAG_DE
650: mtc0 v0, COP_0_STATUS_REG # Disable interrupts
651: #endif
652: LOAD_XKPHYS(a2, CCA_NONCOHERENT)
653: lw v0, CpuNWayCache
654: dsll a0, 34
655: dsrl a0, 34
656: PTR_ADDU a0, a2 # a0 now new XKPHYS address
657: and a0, ~PAGE_MASK # Page align start address
658: PTR_ADDU a1, a0, PAGE_SIZE-128
659: addiu v0, -2 # <0 1way, 0 = two, >0 four
660: lw a2, CpuPrimaryDataSetSize
661:
662: 1:
663: bltz v0, 3f
664: PTR_ADDU t1, a0, a2 # flush set B.
665: cache IndexWBInvalidate_D, 0(t1)
666: cache IndexWBInvalidate_D, 32(t1)
667: cache IndexWBInvalidate_D, 64(t1)
668: cache IndexWBInvalidate_D, 96(t1)
669: beqz v0, 3f # Two way, do set A,
670: PTR_ADDU t1, a2
671:
672: cache IndexWBInvalidate_D, 0(t1) # do set C
673: cache IndexWBInvalidate_D, 32(t1)
674: cache IndexWBInvalidate_D, 64(t1)
675: cache IndexWBInvalidate_D, 96(t1)
676:
677: PTR_ADDU t1, a2 # do set D
678: cache IndexWBInvalidate_D, 0(t1)
679: cache IndexWBInvalidate_D, 32(t1)
680: cache IndexWBInvalidate_D, 64(t1)
681: cache IndexWBInvalidate_D, 96(t1)
682:
683: 3:
684: cache IndexWBInvalidate_D, 0(a0) # do set A
685: cache IndexWBInvalidate_D, 32(a0)
686: cache IndexWBInvalidate_D, 64(a0)
687: cache IndexWBInvalidate_D, 96(a0)
688:
689: bne a1, a0, 1b
690: PTR_ADDU a0, 128
691:
692: #ifdef CPUR4600
693: mtc0 v1, COP_0_STATUS_REG # Restore the status register.
694: #endif
695: j ra
696: nop
697: END(Mips5k_SyncDCachePage)
698:
699: /*----------------------------------------------------------------------------
700: *
701: * Mips5k_HitSyncDCache --
702: *
703: * void Mips5k_HitSyncDCache(addr, len)
704: * vaddr_t addr, len;
705: *
706: * Sync data cache for range of addr to addr + len - 1.
707: * The address can be any valid virtual address as long
708: * as no TLB invalid traps occur. Only lines with matching
709: * addr are flushed.
710: *
711: * Note: Use the CpuNWayCache flag to select 16 or 32 byte linesize.
712: * All Nway cpu's now available have a fixed 32byte linesize.
713: *
714: * Results:
715: * None.
716: *
717: * Side effects:
718: * The contents of the L1 cache is written back to primary memory.
719: * The cache line is invalidated.
720: *
721: * IMPORTANT NOTE:
722: * Since orphaned L1 cache entries will not be synched it is
723: * mandatory to pass over the L1 cache once after the L2 is done.
724: *
725: *----------------------------------------------------------------------------
726: */
727: LEAF(Mips5k_HitSyncDCache, 0)
728: #ifdef CPUR4600
729: mfc0 v1, COP_0_STATUS_REG # Save the status register.
730: li v0, SR_DIAG_DE
731: mtc0 v0, COP_0_STATUS_REG # Disable interrupts
732: #endif
733:
734: beq a1, zero, 3f # size is zero!
735: PTR_ADDU a1, 31 # Round up
736: PTR_ADDU a1, a1, a0 # Add extra from address
737: and a0, a0, -32 # align address
738: PTR_SUBU a1, a1, a0
739: srl a1, a1, 5 # Compute number of cache lines
740:
741: 1:
742: PTR_ADDU a1, -1
743: cache HitWBInvalidate_D, 0(a0)
744: bne a1, zero, 1b
745: PTR_ADDU a0, 32
746:
747: 3:
748: #ifdef CPUR4600
749: mtc0 v1, COP_0_STATUS_REG # Restore the status register.
750: NOP10
751: #endif
752: j ra
753: nop
754: END(Mips5k_HitSyncDCache)
755:
756:
757: /*----------------------------------------------------------------------------
758: *
759: * Mips5k_HitSyncSCache --
760: *
761: * void Mips5k_HitSyncSCache(addr, len)
762: * vaddr_t addr, len;
763: *
764: * Sync secondary cache for range of addr to addr + len - 1.
765: * The address can be any valid virtual address as long
766: * as no TLB invalid traps occur. Only lines with matching
767: * addr are flushed.
768: *
769: * Results:
770: * None.
771: *
772: * Side effects:
773: * The contents of the L2 cache is written back to primary memory.
774: * The cache line is invalidated.
775: *
776: * IMPORTANT NOTE:
777: * Since orphaned L1 cache entries will not be synched it is
778: * mandatory to pass over the L1 cache once after the L2 is done.
779: *
780: *----------------------------------------------------------------------------
781: */
782: LEAF(Mips5k_HitSyncSCache, 0)
783: #ifdef CPUR4600
784: mfc0 v1, COP_0_STATUS_REG # Save the status register.
785: li v0, SR_DIAG_DE
786: mtc0 v0, COP_0_STATUS_REG # Disable interrupts
787: #endif
788:
789: beq a1, zero, 3f # size is zero!
790: PTR_ADDU a1, a1, a0 # Add in extra from align
791: and a0, a0, -32 # Align address
792: PTR_SUBU a1, a1, a0
793: 1:
794: PTR_ADDU a1, -32
795:
796: cache HitWBInvalidate_S, 0(a0)
797: cache HitWBInvalidate_D, 0(a0) # Kill any orphans...
798:
799: bgtz a1, 1b
800: PTR_ADDU a0, 32
801:
802: 3:
803: #ifdef CPUR4600
804: mtc0 v1, COP_0_STATUS_REG # Restore the status register.
805: NOP10
806: #endif
807: j ra
808: nop
809: END(Mips5k_HitSyncSCache)
810:
811: /*----------------------------------------------------------------------------
812: *
813: * Mips5k_HitInvalidateDCache --
814: *
815: * void Mips5k_HitInvalidateDCache(addr, len)
816: * vaddr_t addr, len;
817: *
818: * Invalidate data cache for range of addr to addr + len - 1.
819: * The address can be any valid address as long as no TLB misses occur.
820: * (Be sure to use cached K0SEG kernel addresses or mapped addresses)
821: * Only lines with matching addresses are invalidated.
822: *
823: * Results:
824: * None.
825: *
826: * Side effects:
827: * The L1 cache line is invalidated.
828: *
829: *----------------------------------------------------------------------------
830: */
831: LEAF(Mips5k_HitInvalidateDCache, 0)
832: #ifdef CPUR4600
833: mfc0 v1, COP_0_STATUS_REG # Save the status register.
834: li v0, SR_DIAG_DE
835: mtc0 v0, COP_0_STATUS_REG # Disable interrupts
836: #endif
837:
838: beq a1, zero, 3f # size is zero!
839: PTR_ADDU a1, a1, a0 # Add in extra from align
840: and a0, a0, -32 # Align address
841: PTR_SUBU a1, a1, a0
842:
843: 1:
844: PTR_ADDU a1, -32
845:
846: cache HitInvalidate_D, 0(a0)
847:
848: bgtz a1, 1b
849: PTR_ADDU a0, 32
850:
851: 3:
852: #ifdef CPUR4600
853: mtc0 v1, COP_0_STATUS_REG # Restore the status register.
854: NOP10
855: #endif
856: j ra
857: nop
858: END(Mips5k_HitInvalidateDCache)
859:
860:
861: /*----------------------------------------------------------------------------
862: *
863: * Mips5k_HitInvalidateSCache --
864: *
865: * void Mips5k_HitInvalidateSCache(addr, len)
866: * vaddr_t addr, len;
867: *
868: * Invalidate secondary cache for range of addr to addr + len - 1.
869: * The address can be any valid address as long as no TLB misses occur.
870: * (Be sure to use cached K0SEG kernel addresses or mapped addresses)
871: * Only lines with matching addresses are invalidated.
872: *
873: * Results:
874: * None.
875: *
876: * Side effects:
877: * The L2 cache line is invalidated.
878: *
879: *----------------------------------------------------------------------------
880: */
881: LEAF(Mips5k_HitInvalidateSCache, 0)
882: #ifdef CPUR4600
883: mfc0 v1, COP_0_STATUS_REG # Save the status register.
884: li v0, SR_DIAG_DE
885: mtc0 v0, COP_0_STATUS_REG # Disable interrupts
886: #endif
887:
888: beq a1, zero, 3f # size is zero!
889: PTR_ADDU a1, a1, a0 # Add in extra from align
890: and a0, a0, -32 # Align address
891: PTR_SUBU a1, a1, a0
892: 1:
893: PTR_ADDU a1, -32
894:
895: cache HitInvalidate_S, 0(a0)
896: cache HitInvalidate_D, 0(a0) # Orphans in L1
897:
898: bgtz a1, 1b
899: PTR_ADDU a0, 32
900:
901: 3:
902: #ifdef CPUR4600
903: mtc0 v1, COP_0_STATUS_REG # Restore the status register.
904: NOP10
905: #endif
906: j ra
907: nop
908: END(Mips5k_HitInvalidateSCache)
909:
910: /*----------------------------------------------------------------------------
911: *
912: * Mips5k_IOSyncDCache --
913: *
914: * void Mips5k_IOSyncDCache(addr, len, rw)
915: * vaddr_t addr;
916: * int len, rw;
917: *
918: * Invalidate or flush data cache for range of addr to addr + len - 1.
919: * The address can be any valid address as long as no TLB misses occur.
920: * (Be sure to use cached K0SEG kernel addresses or mapped addresses)
921: *
922: * In case of the existence of an external cache we invalidate pages
923: * which are in the given range ONLY if transfer direction is READ.
924: * The assumption here is a 'write through' external cache which is
925: * true for all now supported processors.
926: *
927: * Results:
928: * None.
929: *
930: * Side effects:
931: * If rw == 0 (read), L1 and on-chip L2 caches are invalidated or
932: * flushed if the area does not match the alignment
933: * requirements. Writethrough L2 and L3 cache are
934: * invalidated for the address range.
935: * If rw == 1 (write), L1 and on-chip L2 caches are written back
936: * to memory and invalidated. Writethrough L2 and L3 caches
937: * are left alone.
938: * If rw == 2 (write-read), L1 and on-chip L2 caches are written back
939: * to memory and invalidated. Writethrough L2 and L3 caches
940: * are invalidated.
941: *
942: *----------------------------------------------------------------------------
943: */
944: NON_LEAF(Mips5k_IOSyncDCache, FRAMESZ(CF_SZ+2*REGSZ), ra)
945:
946: PTR_SUBU sp, FRAMESZ(CF_SZ+2*REGSZ)
947: PTR_S ra, CF_RA_OFFS+2*REGSZ(sp)
948: REG_S a0, CF_ARGSZ(sp) # save args
949: beqz a2, SyncRD # Sync PREREAD
950: REG_S a1, CF_ARGSZ+REGSZ(sp)
951: addiu a2, -1
952: bnez a2, SyncRDWB # Sync PREWRITE+PREREAD
953: nop
954:
955: lw t0, CpuCacheType # Sync PREWRITE
956: and t0, CTYPE_HAS_IL2 # Have internal L2?
957: bnez t0, SyncSC # Yes
958: nop
959: jal Mips5k_HitSyncDCache # No flush L1.
960: nop
961: b SyncDone
962: PTR_L ra, CF_RA_OFFS+2*REGSZ(sp)
963:
964: SyncSC:
965: jal Mips5k_HitSyncSCache # Do internal L2 cache
966: nop # L1 done in parallel
967: b SyncDone
968: PTR_L ra, CF_RA_OFFS+2*REGSZ(sp)
969:
970: SyncRD:
971: and t0, a0, 31 # check if invalidate possible
972: bnez t0, SyncRDWB # both address and size must
973: and t0, a1, 31 # be aligned at the cache size
974: bnez t0, SyncRDWB
975: nop
976:
977: /*
978: * Sync for aligned read, no writeback required.
979: */
980: lw t0, CpuCacheType # Aligned, do invalidate
981: and t0, CTYPE_HAS_IL2 # Have internal L2?
982: bnez t0, SyncRDL2
983: nop
984:
985: jal Mips5k_HitInvalidateDCache # External L2 or no L2. Do L1.
986: nop
987:
988: b SyncRDXL2
989: PTR_L ra, CF_RA_OFFS+2*REGSZ(sp) # External L2 if present
990:
991: SyncRDL2:
992: jal Mips5k_HitInvalidateSCache # Internal L2 cache
993: nop # L1 done in parallel
994:
995: b SyncRDL3
996: PTR_L ra, CF_RA_OFFS+2*REGSZ(sp) # L3 invalidate if present
997:
998: /*
999: * Sync for unaligned read or write-read.
1000: */
1001: SyncRDWB:
1002: lw t0, CpuCacheType
1003: and t0, CTYPE_HAS_IL2 # Have internal L2?
1004: bnez t0, SyncRDWBL2 # Yes, do L2
1005: nop
1006:
1007: jal Mips5k_HitSyncDCache
1008: nop
1009:
1010: b SyncRDXL2
1011: PTR_L ra, CF_RA_OFFS+2*REGSZ(sp) # External L2 if present
1012:
1013: SyncRDWBL2:
1014: jal Mips5k_HitSyncSCache # Internal L2 cache
1015: nop # L1 done in parallel
1016:
1017: b SyncRDL3
1018: PTR_L ra, CF_RA_OFFS+2*REGSZ(sp) # L3 invalidate if present
1019:
1020: SyncRDXL2:
1021: lw t0, CpuCacheType
1022: and t0, CTYPE_HAS_XL2 # Have external L2?
1023: beqz t0, SyncRDL3 # Nope.
1024: REG_L a0, CF_ARGSZ(sp)
1025: REG_L a1, CF_ARGSZ+REGSZ(sp)
1026: and a2, a0, 4095 # align on page size
1027: PTR_SUBU a0, a2
1028: PTR_ADDU a1, a2
1029: 50:
1030: blez a1, SyncDone
1031: PTR_SUBU a1, 4096 # Fixed cache page size.
1032:
1033: cache InvalidateSecondaryPage, 0(a0)
1034: b 50b
1035: PTR_ADDU a0, 4096
1036:
1037: SyncRDL3:
1038: lw t0, CpuCacheType
1039: and t0, CTYPE_HAS_XL3 # Have L3?
1040: beqz t0, SyncDone # Nope.
1041: REG_L a0, CF_ARGSZ(sp)
1042: REG_L a1, CF_ARGSZ+REGSZ(sp)
1043: and a2, a0, 4095 # align on page size
1044: PTR_SUBU a0, a2
1045: PTR_ADDU a1, a2
1046: 40:
1047: blez a1, SyncDone
1048: PTR_SUBU a1, 4096 # Fixed cache page size.
1049:
1050: cache InvalidatePage_T, 0(a0)
1051: b 40b
1052: PTR_ADDU a0, 4096
1053:
1054: SyncDone:
1055: j ra
1056: PTR_ADDU sp, FRAMESZ(CF_SZ+2*REGSZ)
1057: END(Mips5k_IOSyncDCache)
CVSweb