File: /usr/src/linux/include/asm-mips64/r10kcache.h

1     /*
2      * This file is subject to the terms and conditions of the GNU General Public
3      * License.  See the file "COPYING" in the main directory of this archive
4      * for more details.
5      *
6      * Inline assembly cache operations.
7      *
8      * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
9      * Copyright (C) 1999 Ralf Baechle
10      * Copyright (C) 1999 Silicon Graphics, Inc.
11      *
12      * FIXME: Handle split L2 caches.
13      */
14     #ifndef _ASM_R10KCACHE_H
15     #define _ASM_R10KCACHE_H
16     
17     #include <asm/asm.h>
18     #include <asm/r10kcacheops.h>
19     
20     /* These are fixed for the current R10000.  */
21     #define icache_size	0x8000
22     #define dcache_size	0x8000
23     #define icache_way_size	0x4000
24     #define dcache_way_size	0x4000
25     #define ic_lsize	64
26     #define dc_lsize	32
27     
28     /* These are configuration dependant.  */
29     #define scache_size()	({						\
30     	unsigned long __res;						\
31     	__res = (read_32bit_cp0_register(CP0_CONFIG) >> 16) & 3;	\
32     	__res = 1 << (__res + 19);					\
33     	__res;								\
34     })
35     
36     #define sc_lsize()	({						\
37     	unsigned long __res;						\
38     	__res = (read_32bit_cp0_register(CP0_CONFIG) >> 13) & 1;	\
39     	__res = 1 << (__res + 6);					\
40     	__res;								\
41     })
42     
43     extern inline void flush_icache_line_indexed(unsigned long addr)
44     {
45     	__asm__ __volatile__(
46     		".set noreorder\n\t"
47     		"cache %1, (%0)\n\t"
48     		".set reorder"
49     		:
50     		: "r" (addr), "i" (Index_Invalidate_I));
51     }
52     
53     extern inline void flush_dcache_line_indexed(unsigned long addr)
54     {
55     	__asm__ __volatile__(
56     		".set noreorder\n\t"
57     		"cache %1, (%0)\n\t"
58     		".set reorder"
59     		:
60     		: "r" (addr), "i" (Index_Writeback_Inv_D));
61     }
62     
63     extern inline void flush_scache_line_indexed(unsigned long addr)
64     {
65     	__asm__ __volatile__(
66     		".set noreorder\n\t"
67     		"cache %1, (%0)\n\t"
68     		".set reorder"
69     		:
70     		: "r" (addr), "i" (Index_Writeback_Inv_S));
71     }
72     
73     extern inline void flush_icache_line(unsigned long addr)
74     {
75     	__asm__ __volatile__(
76     		".set noreorder\n\t"
77     		"cache %1, (%0)\n\t"
78     		".set reorder"
79     		:
80     		: "r" (addr), "i" (Hit_Invalidate_I));
81     }
82     
83     extern inline void flush_dcache_line(unsigned long addr)
84     {
85     	__asm__ __volatile__(
86     		".set noreorder\n\t"
87     		"cache %1, (%0)\n\t"
88     		".set reorder"
89     		:
90     		: "r" (addr), "i" (Hit_Writeback_Inv_D));
91     }
92     
93     extern inline void invalidate_dcache_line(unsigned long addr)
94     {
95     	__asm__ __volatile__(
96     		".set noreorder\n\t"
97     		"cache %1, (%0)\n\t"
98     		".set reorder"
99     		:
100     		: "r" (addr), "i" (Hit_Invalidate_D));
101     }
102     
103     extern inline void invalidate_scache_line(unsigned long addr)
104     {
105     	__asm__ __volatile__(
106     		".set noreorder\n\t"
107     		"cache %1, (%0)\n\t"
108     		".set reorder"
109     		:
110     		: "r" (addr), "i" (Hit_Invalidate_S));
111     }
112     
113     extern inline void flush_scache_line(unsigned long addr)
114     {
115     	__asm__ __volatile__(
116     		".set noreorder\n\t"
117     		"cache %1, (%0)\n\t"
118     		".set reorder"
119     		:
120     		: "r" (addr), "i" (Hit_Writeback_Inv_S));
121     }
122     
123     /*
124      * The next two are for badland addresses like signal trampolines.
125      */
126     extern inline void protected_flush_icache_line(unsigned long addr)
127     {
128     	__asm__ __volatile__(
129     		".set noreorder\n\t"
130     		"1:\tcache %1,(%0)\n"
131     		"2:\t.set reorder\n\t"
132     		".section\t__ex_table,\"a\"\n\t"
133     		".dword\t1b,2b\n\t"
134     		".previous"
135     		:
136     		: "r" (addr), "i" (Hit_Invalidate_I));
137     }
138     
139     extern inline void protected_writeback_dcache_line(unsigned long addr)
140     {
141     	__asm__ __volatile__(
142     		".set noreorder\n\t"
143     		"1:\tcache %1,(%0)\n"
144     		"2:\t.set reorder\n\t"
145     		".section\t__ex_table,\"a\"\n\t"
146     		".dword\t1b,2b\n\t"
147     		".previous"
148     		:
149     		: "r" (addr), "i" (Hit_Writeback_Inv_D));
150     }
151     
152     #define cache32_unroll16(base,op)				\
153     	__asm__ __volatile__("					\
154     		.set noreorder;					\
155     		cache %1, 0x000(%0); cache %1, 0x020(%0);	\
156     		cache %1, 0x040(%0); cache %1, 0x060(%0);	\
157     		cache %1, 0x080(%0); cache %1, 0x0a0(%0);	\
158     		cache %1, 0x0c0(%0); cache %1, 0x0e0(%0);	\
159     		cache %1, 0x100(%0); cache %1, 0x120(%0);	\
160     		cache %1, 0x140(%0); cache %1, 0x160(%0);	\
161     		cache %1, 0x180(%0); cache %1, 0x1a0(%0);	\
162     		cache %1, 0x1c0(%0); cache %1, 0x1e0(%0);	\
163     		.set reorder"					\
164     		:						\
165     		: "r" (base),					\
166     		  "i" (op));
167     
168     #define cache32_unroll32(base,op)				\
169     	__asm__ __volatile__("					\
170     		.set noreorder;					\
171     		cache %1, 0x000(%0); cache %1, 0x020(%0);	\
172     		cache %1, 0x040(%0); cache %1, 0x060(%0);	\
173     		cache %1, 0x080(%0); cache %1, 0x0a0(%0);	\
174     		cache %1, 0x0c0(%0); cache %1, 0x0e0(%0);	\
175     		cache %1, 0x100(%0); cache %1, 0x120(%0);	\
176     		cache %1, 0x140(%0); cache %1, 0x160(%0);	\
177     		cache %1, 0x180(%0); cache %1, 0x1a0(%0);	\
178     		cache %1, 0x1c0(%0); cache %1, 0x1e0(%0);	\
179     		cache %1, 0x200(%0); cache %1, 0x220(%0);	\
180     		cache %1, 0x240(%0); cache %1, 0x260(%0);	\
181     		cache %1, 0x280(%0); cache %1, 0x2a0(%0);	\
182     		cache %1, 0x2c0(%0); cache %1, 0x2e0(%0);	\
183     		cache %1, 0x300(%0); cache %1, 0x320(%0);	\
184     		cache %1, 0x340(%0); cache %1, 0x360(%0);	\
185     		cache %1, 0x380(%0); cache %1, 0x3a0(%0);	\
186     		cache %1, 0x3c0(%0); cache %1, 0x3e0(%0);	\
187     		.set reorder"					\
188     		:						\
189     		: "r" (base),					\
190     		  "i" (op));
191     
192     extern inline void blast_dcache32(void)
193     {
194     	unsigned long way0 = KSEG0;
195     	unsigned long way1 = way0 ^ 1;
196     	unsigned long end = (way0 + dcache_way_size);
197     
198     	while (way0 < end) {
199     		cache32_unroll16(way0, Index_Writeback_Inv_D);
200     		cache32_unroll16(way1, Index_Writeback_Inv_D);
201     		way0 += 0x200;
202     		way1 += 0x200;
203     	}
204     }
205     
206     extern inline void blast_dcache32_page(unsigned long page)
207     {
208     	unsigned long start = page;
209     	unsigned long end = page + PAGE_SIZE;
210     
211     	while (start < end) {
212     		cache32_unroll32(start, Hit_Writeback_Inv_D);
213     		start += 0x400;
214     	}
215     }
216     
217     extern inline void blast_dcache32_page_indexed(unsigned long page)
218     {
219     	unsigned long way0 = page;
220     	unsigned long way1 = page ^ 1;
221     	unsigned long end = page + PAGE_SIZE;
222     
223     	while (way0 < end) {
224     		cache32_unroll16(way0, Index_Writeback_Inv_D);
225     		cache32_unroll16(way1, Index_Writeback_Inv_D);
226     		way0 += 0x200;
227     		way1 += 0x200;
228     	}
229     }
230     
231     #define cache64_unroll16(base,op)				\
232     	__asm__ __volatile__("					\
233     		.set noreorder;					\
234     		cache %1, 0x000(%0); cache %1, 0x040(%0);	\
235     		cache %1, 0x080(%0); cache %1, 0x0c0(%0);	\
236     		cache %1, 0x100(%0); cache %1, 0x140(%0);	\
237     		cache %1, 0x180(%0); cache %1, 0x1c0(%0);	\
238     		cache %1, 0x200(%0); cache %1, 0x240(%0);	\
239     		cache %1, 0x280(%0); cache %1, 0x2c0(%0);	\
240     		cache %1, 0x300(%0); cache %1, 0x340(%0);	\
241     		cache %1, 0x380(%0); cache %1, 0x3c0(%0);	\
242     		.set reorder"					\
243     		:						\
244     		: "r" (base),					\
245     		  "i" (op));
246     
247     #define cache64_unroll32(base,op)				\
248     	__asm__ __volatile__("					\
249     		.set noreorder;					\
250     		cache %1, 0x000(%0); cache %1, 0x040(%0);	\
251     		cache %1, 0x080(%0); cache %1, 0x0c0(%0);	\
252     		cache %1, 0x100(%0); cache %1, 0x140(%0);	\
253     		cache %1, 0x180(%0); cache %1, 0x1c0(%0);	\
254     		cache %1, 0x200(%0); cache %1, 0x240(%0);	\
255     		cache %1, 0x280(%0); cache %1, 0x2c0(%0);	\
256     		cache %1, 0x300(%0); cache %1, 0x340(%0);	\
257     		cache %1, 0x380(%0); cache %1, 0x3c0(%0);	\
258     		cache %1, 0x400(%0); cache %1, 0x440(%0);	\
259     		cache %1, 0x480(%0); cache %1, 0x4c0(%0);	\
260     		cache %1, 0x500(%0); cache %1, 0x540(%0);	\
261     		cache %1, 0x580(%0); cache %1, 0x5c0(%0);	\
262     		cache %1, 0x600(%0); cache %1, 0x640(%0);	\
263     		cache %1, 0x680(%0); cache %1, 0x6c0(%0);	\
264     		cache %1, 0x700(%0); cache %1, 0x740(%0);	\
265     		cache %1, 0x780(%0); cache %1, 0x7c0(%0);	\
266     		.set reorder"					\
267     		:						\
268     		: "r" (base),					\
269     		  "i" (op));
270     
271     extern inline void blast_icache64(void)
272     {
273     	unsigned long way0 = KSEG0;
274     	unsigned long way1 = way0 ^ 1;
275     	unsigned long end = way0 + icache_way_size;
276     
277     	while (way0 < end) {
278     		cache64_unroll16(way0,Index_Invalidate_I);
279     		cache64_unroll16(way1,Index_Invalidate_I);
280     		way0 += 0x400;
281     		way1 += 0x400;
282     	}
283     }
284     
285     extern inline void blast_icache64_page(unsigned long page)
286     {
287     	unsigned long start = page;
288     	unsigned long end = page + PAGE_SIZE;
289     
290     	while (start < end) {
291     		cache64_unroll32(start,Hit_Invalidate_I);
292     		start += 0x800;
293     	}
294     }
295     
296     extern inline void blast_icache64_page_indexed(unsigned long page)
297     {
298     	unsigned long way0 = page;
299     	unsigned long way1 = page ^ 1;
300     	unsigned long end = page + PAGE_SIZE;
301     
302     	while (way0 < end) {
303     		cache64_unroll16(way0,Index_Invalidate_I);
304     		cache64_unroll16(way1,Index_Invalidate_I);
305     		way0 += 0x400;
306     		way1 += 0x400;
307     	}
308     }
309     
310     extern inline void blast_scache64(void)
311     {
312     	unsigned long way0 = KSEG0;
313     	unsigned long way1 = way0 ^ 1;
314     	unsigned long end = KSEG0 + scache_size();
315     
316     	while (way0 < end) {
317     		cache64_unroll16(way0,Index_Writeback_Inv_S);
318     		cache64_unroll16(way1,Index_Writeback_Inv_S);
319     		way0 += 0x400;
320     		way1 += 0x400;
321     	}
322     }
323     
324     extern inline void blast_scache64_page(unsigned long page)
325     {
326     	unsigned long start = page;
327     	unsigned long end = page + PAGE_SIZE;
328     
329     	while (start < end) {
330     		cache64_unroll32(start,Hit_Writeback_Inv_S);
331     		start += 0x800;
332     	}
333     }
334     
335     extern inline void blast_scache64_page_indexed(unsigned long page)
336     {
337     	unsigned long way0 = page;
338     	unsigned long way1 = page ^ 1;
339     	unsigned long end = page + PAGE_SIZE;
340     
341     	while (way0 < end) {
342     		cache64_unroll16(way0,Index_Writeback_Inv_S);
343     		cache64_unroll16(way1,Index_Writeback_Inv_S);
344     		way0 += 0x400;
345     		way1 += 0x400;
346     	}
347     }
348     
349     #define cache128_unroll16(base,op)				\
350     	__asm__ __volatile__("					\
351     		.set noreorder;					\
352     		cache %1, 0x000(%0); cache %1, 0x080(%0);	\
353     		cache %1, 0x100(%0); cache %1, 0x180(%0);	\
354     		cache %1, 0x200(%0); cache %1, 0x280(%0);	\
355     		cache %1, 0x300(%0); cache %1, 0x380(%0);	\
356     		cache %1, 0x400(%0); cache %1, 0x480(%0);	\
357     		cache %1, 0x500(%0); cache %1, 0x580(%0);	\
358     		cache %1, 0x600(%0); cache %1, 0x680(%0);	\
359     		cache %1, 0x700(%0); cache %1, 0x780(%0);	\
360     		.set reorder"					\
361     		:						\
362     		: "r" (base),					\
363     		  "i" (op));
364     
365     #define cache128_unroll32(base,op)				\
366     	__asm__ __volatile__("					\
367     		.set noreorder;					\
368     		cache %1, 0x000(%0); cache %1, 0x080(%0);	\
369     		cache %1, 0x100(%0); cache %1, 0x180(%0);	\
370     		cache %1, 0x200(%0); cache %1, 0x280(%0);	\
371     		cache %1, 0x300(%0); cache %1, 0x380(%0);	\
372     		cache %1, 0x400(%0); cache %1, 0x480(%0);	\
373     		cache %1, 0x500(%0); cache %1, 0x580(%0);	\
374     		cache %1, 0x600(%0); cache %1, 0x680(%0);	\
375     		cache %1, 0x700(%0); cache %1, 0x780(%0);	\
376     		cache %1, 0x800(%0); cache %1, 0x880(%0);	\
377     		cache %1, 0x900(%0); cache %1, 0x980(%0);	\
378     		cache %1, 0xa00(%0); cache %1, 0xa80(%0);	\
379     		cache %1, 0xb00(%0); cache %1, 0xb80(%0);	\
380     		cache %1, 0xc00(%0); cache %1, 0xc80(%0);	\
381     		cache %1, 0xd00(%0); cache %1, 0xd80(%0);	\
382     		cache %1, 0xe00(%0); cache %1, 0xe80(%0);	\
383     		cache %1, 0xf00(%0); cache %1, 0xf80(%0);	\
384     		.set reorder"					\
385     		:						\
386     		: "r" (base),					\
387     		  "i" (op));
388     
389     extern inline void blast_scache128(void)
390     {
391     	unsigned long way0 = KSEG0;
392     	unsigned long way1 = way0 ^ 1;
393     	unsigned long end = way0 + scache_size();
394     
395     	while (way0 < end) {
396     		cache128_unroll16(way0, Index_Writeback_Inv_S);
397     		cache128_unroll16(way1, Index_Writeback_Inv_S);
398     		way0 += 0x800;
399     		way1 += 0x800;
400     	}
401     }
402     
403     extern inline void blast_scache128_page(unsigned long page)
404     {
405     	cache128_unroll32(page, Hit_Writeback_Inv_S);
406     }
407     
408     extern inline void blast_scache128_page_indexed(unsigned long page)
409     {
410     	cache128_unroll32(page    , Index_Writeback_Inv_S);
411     	cache128_unroll32(page ^ 1, Index_Writeback_Inv_S);
412     }
413     
414     #endif /* _ASM_R10KCACHE_H */
415