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