1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/init.h>
18#include <linux/kernel.h>
19#include <linux/sched.h>
20#include <linux/mm.h>
21
22#include <asm/bootinfo.h>
23#include <asm/cpu.h>
24#include <asm/bcache.h>
25#include <asm/io.h>
26#include <asm/page.h>
27#include <asm/pgtable.h>
28#include <asm/system.h>
29#include <asm/mmu_context.h>
30
31
32#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
33 "nop; nop; nop; nop; nop; nop;\n\t" \
34 ".set reorder\n\t")
35
36
37static int icache_size, dcache_size;
38static int ic_lsize, dc_lsize;
39
40
41static unsigned int scache_size, sc_lsize;
42
43#include <asm/cacheops.h>
44#include <asm/r4kcache.h>
45
46#undef DEBUG_CACHE
47
48
49
50
51static void no_sc_noop(void) {}
52
53static struct bcache_ops no_sc_ops = {
54 (void *)no_sc_noop, (void *)no_sc_noop,
55 (void *)no_sc_noop, (void *)no_sc_noop
56};
57
58struct bcache_ops *bcops = &no_sc_ops;
59
60
61
62
63
64
65#define icache_waybit (icache_size >> 1)
66#define dcache_waybit (dcache_size >> 1)
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81static void r4k_clear_page_d16(void * page)
82{
83 __asm__ __volatile__(
84 ".set\tnoreorder\n\t"
85 ".set\tnoat\n\t"
86 ".set\tmips3\n\t"
87 "daddiu\t$1,%0,%2\n"
88 "1:\tcache\t%3,(%0)\n\t"
89 "sd\t$0,(%0)\n\t"
90 "sd\t$0,8(%0)\n\t"
91 "cache\t%3,16(%0)\n\t"
92 "sd\t$0,16(%0)\n\t"
93 "sd\t$0,24(%0)\n\t"
94 "daddiu\t%0,64\n\t"
95 "cache\t%3,-32(%0)\n\t"
96 "sd\t$0,-32(%0)\n\t"
97 "sd\t$0,-24(%0)\n\t"
98 "cache\t%3,-16(%0)\n\t"
99 "sd\t$0,-16(%0)\n\t"
100 "bne\t$1,%0,1b\n\t"
101 "sd\t$0,-8(%0)\n\t"
102 ".set\tmips0\n\t"
103 ".set\tat\n\t"
104 ".set\treorder"
105 :"=r" (page)
106 :"0" (page),
107 "I" (PAGE_SIZE),
108 "i" (Create_Dirty_Excl_D)
109 :"$1","memory");
110}
111
112static void r4k_clear_page_d32(void * page)
113{
114 __asm__ __volatile__(
115 ".set\tnoreorder\n\t"
116 ".set\tnoat\n\t"
117 ".set\tmips3\n\t"
118 "daddiu\t$1,%0,%2\n"
119 "1:\tcache\t%3,(%0)\n\t"
120 "sd\t$0,(%0)\n\t"
121 "sd\t$0,8(%0)\n\t"
122 "sd\t$0,16(%0)\n\t"
123 "sd\t$0,24(%0)\n\t"
124 "daddiu\t%0,64\n\t"
125 "cache\t%3,-32(%0)\n\t"
126 "sd\t$0,-32(%0)\n\t"
127 "sd\t$0,-24(%0)\n\t"
128 "sd\t$0,-16(%0)\n\t"
129 "bne\t$1,%0,1b\n\t"
130 "sd\t$0,-8(%0)\n\t"
131 ".set\tmips0\n\t"
132 ".set\tat\n\t"
133 ".set\treorder"
134 :"=r" (page)
135 :"0" (page),
136 "I" (PAGE_SIZE),
137 "i" (Create_Dirty_Excl_D)
138 :"$1","memory");
139}
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169static void r4k_clear_page_r4600_v1(void * page)
170{
171 __asm__ __volatile__(
172 ".set\tnoreorder\n\t"
173 ".set\tnoat\n\t"
174 ".set\tmips3\n\t"
175 "daddiu\t$1,%0,%2\n"
176 "1:\tnop\n\t"
177 "nop\n\t"
178 "nop\n\t"
179 "nop\n\t"
180 "cache\t%3,(%0)\n\t"
181 "sd\t$0,(%0)\n\t"
182 "sd\t$0,8(%0)\n\t"
183 "sd\t$0,16(%0)\n\t"
184 "sd\t$0,24(%0)\n\t"
185 "daddiu\t%0,64\n\t"
186 "nop\n\t"
187 "nop\n\t"
188 "nop\n\t"
189 "cache\t%3,-32(%0)\n\t"
190 "sd\t$0,-32(%0)\n\t"
191 "sd\t$0,-24(%0)\n\t"
192 "sd\t$0,-16(%0)\n\t"
193 "bne\t$1,%0,1b\n\t"
194 "sd\t$0,-8(%0)\n\t"
195 ".set\tmips0\n\t"
196 ".set\tat\n\t"
197 ".set\treorder"
198 :"=r" (page)
199 :"0" (page),
200 "I" (PAGE_SIZE),
201 "i" (Create_Dirty_Excl_D)
202 :"$1","memory");
203}
204
205
206
207
208static void r4k_clear_page_r4600_v2(void * page)
209{
210 unsigned int flags;
211
212 local_irq_save(flags);
213 *(volatile unsigned int *)KSEG1;
214 __asm__ __volatile__(
215 ".set\tnoreorder\n\t"
216 ".set\tnoat\n\t"
217 ".set\tmips3\n\t"
218 "daddiu\t$1,%0,%2\n"
219 "1:\tcache\t%3,(%0)\n\t"
220 "sd\t$0,(%0)\n\t"
221 "sd\t$0,8(%0)\n\t"
222 "sd\t$0,16(%0)\n\t"
223 "sd\t$0,24(%0)\n\t"
224 "daddiu\t%0,64\n\t"
225 "cache\t%3,-32(%0)\n\t"
226 "sd\t$0,-32(%0)\n\t"
227 "sd\t$0,-24(%0)\n\t"
228 "sd\t$0,-16(%0)\n\t"
229 "bne\t$1,%0,1b\n\t"
230 "sd\t$0,-8(%0)\n\t"
231 ".set\tmips0\n\t"
232 ".set\tat\n\t"
233 ".set\treorder"
234 :"=r" (page)
235 :"0" (page),
236 "I" (PAGE_SIZE),
237 "i" (Create_Dirty_Excl_D)
238 :"$1","memory");
239 local_irq_restore(flags);
240}
241
242
243
244
245
246
247
248
249
250
251static void r4k_clear_page_s16(void * page)
252{
253 __asm__ __volatile__(
254 ".set\tnoreorder\n\t"
255 ".set\tnoat\n\t"
256 ".set\tmips3\n\t"
257 "daddiu\t$1,%0,%2\n"
258 "1:\tcache\t%3,(%0)\n\t"
259 "sd\t$0,(%0)\n\t"
260 "sd\t$0,8(%0)\n\t"
261 "cache\t%3,16(%0)\n\t"
262 "sd\t$0,16(%0)\n\t"
263 "sd\t$0,24(%0)\n\t"
264 "daddiu\t%0,64\n\t"
265 "cache\t%3,-32(%0)\n\t"
266 "sd\t$0,-32(%0)\n\t"
267 "sd\t$0,-24(%0)\n\t"
268 "cache\t%3,-16(%0)\n\t"
269 "sd\t$0,-16(%0)\n\t"
270 "bne\t$1,%0,1b\n\t"
271 "sd\t$0,-8(%0)\n\t"
272 ".set\tmips0\n\t"
273 ".set\tat\n\t"
274 ".set\treorder"
275 :"=r" (page)
276 :"0" (page),
277 "I" (PAGE_SIZE),
278 "i" (Create_Dirty_Excl_SD)
279 :"$1","memory");
280}
281
282static void r4k_clear_page_s32(void * page)
283{
284 __asm__ __volatile__(
285 ".set\tnoreorder\n\t"
286 ".set\tnoat\n\t"
287 ".set\tmips3\n\t"
288 "daddiu\t$1,%0,%2\n"
289 "1:\tcache\t%3,(%0)\n\t"
290 "sd\t$0,(%0)\n\t"
291 "sd\t$0,8(%0)\n\t"
292 "sd\t$0,16(%0)\n\t"
293 "sd\t$0,24(%0)\n\t"
294 "daddiu\t%0,64\n\t"
295 "cache\t%3,-32(%0)\n\t"
296 "sd\t$0,-32(%0)\n\t"
297 "sd\t$0,-24(%0)\n\t"
298 "sd\t$0,-16(%0)\n\t"
299 "bne\t$1,%0,1b\n\t"
300 "sd\t$0,-8(%0)\n\t"
301 ".set\tmips0\n\t"
302 ".set\tat\n\t"
303 ".set\treorder"
304 :"=r" (page)
305 :"0" (page),
306 "I" (PAGE_SIZE),
307 "i" (Create_Dirty_Excl_SD)
308 :"$1","memory");
309}
310
311static void r4k_clear_page_s64(void * page)
312{
313 __asm__ __volatile__(
314 ".set\tnoreorder\n\t"
315 ".set\tnoat\n\t"
316 ".set\tmips3\n\t"
317 "daddiu\t$1,%0,%2\n"
318 "1:\tcache\t%3,(%0)\n\t"
319 "sd\t$0,(%0)\n\t"
320 "sd\t$0,8(%0)\n\t"
321 "sd\t$0,16(%0)\n\t"
322 "sd\t$0,24(%0)\n\t"
323 "daddiu\t%0,64\n\t"
324 "sd\t$0,-32(%0)\n\t"
325 "sd\t$0,-24(%0)\n\t"
326 "sd\t$0,-16(%0)\n\t"
327 "bne\t$1,%0,1b\n\t"
328 "sd\t$0,-8(%0)\n\t"
329 ".set\tmips0\n\t"
330 ".set\tat\n\t"
331 ".set\treorder"
332 :"=r" (page)
333 :"0" (page),
334 "I" (PAGE_SIZE),
335 "i" (Create_Dirty_Excl_SD)
336 :"$1","memory");
337}
338
339static void r4k_clear_page_s128(void * page)
340{
341 __asm__ __volatile__(
342 ".set\tnoreorder\n\t"
343 ".set\tnoat\n\t"
344 ".set\tmips3\n\t"
345 "daddiu\t$1,%0,%2\n"
346 "1:\tcache\t%3,(%0)\n\t"
347 "sd\t$0,(%0)\n\t"
348 "sd\t$0,8(%0)\n\t"
349 "sd\t$0,16(%0)\n\t"
350 "sd\t$0,24(%0)\n\t"
351 "sd\t$0,32(%0)\n\t"
352 "sd\t$0,40(%0)\n\t"
353 "sd\t$0,48(%0)\n\t"
354 "sd\t$0,56(%0)\n\t"
355 "daddiu\t%0,128\n\t"
356 "sd\t$0,-64(%0)\n\t"
357 "sd\t$0,-56(%0)\n\t"
358 "sd\t$0,-48(%0)\n\t"
359 "sd\t$0,-40(%0)\n\t"
360 "sd\t$0,-32(%0)\n\t"
361 "sd\t$0,-24(%0)\n\t"
362 "sd\t$0,-16(%0)\n\t"
363 "bne\t$1,%0,1b\n\t"
364 "sd\t$0,-8(%0)\n\t"
365 ".set\tmips0\n\t"
366 ".set\tat\n\t"
367 ".set\treorder"
368 :"=r" (page)
369 :"0" (page),
370 "I" (PAGE_SIZE),
371 "i" (Create_Dirty_Excl_SD)
372 :"$1","memory");
373}
374
375
376
377
378
379
380
381static void r4k_copy_page_d16(void * to, void * from)
382{
383 unsigned long dummy1, dummy2;
384 unsigned long reg1, reg2, reg3, reg4;
385
386 __asm__ __volatile__(
387 ".set\tnoreorder\n\t"
388 ".set\tnoat\n\t"
389 ".set\tmips3\n\t"
390 "daddiu\t$1,%0,%8\n"
391 "1:\tcache\t%9,(%0)\n\t"
392 "lw\t%2,(%1)\n\t"
393 "lw\t%3,4(%1)\n\t"
394 "lw\t%4,8(%1)\n\t"
395 "lw\t%5,12(%1)\n\t"
396 "sw\t%2,(%0)\n\t"
397 "sw\t%3,4(%0)\n\t"
398 "sw\t%4,8(%0)\n\t"
399 "sw\t%5,12(%0)\n\t"
400 "cache\t%9,16(%0)\n\t"
401 "lw\t%2,16(%1)\n\t"
402 "lw\t%3,20(%1)\n\t"
403 "lw\t%4,24(%1)\n\t"
404 "lw\t%5,28(%1)\n\t"
405 "sw\t%2,16(%0)\n\t"
406 "sw\t%3,20(%0)\n\t"
407 "sw\t%4,24(%0)\n\t"
408 "sw\t%5,28(%0)\n\t"
409 "cache\t%9,32(%0)\n\t"
410 "daddiu\t%0,64\n\t"
411 "daddiu\t%1,64\n\t"
412 "lw\t%2,-32(%1)\n\t"
413 "lw\t%3,-28(%1)\n\t"
414 "lw\t%4,-24(%1)\n\t"
415 "lw\t%5,-20(%1)\n\t"
416 "sw\t%2,-32(%0)\n\t"
417 "sw\t%3,-28(%0)\n\t"
418 "sw\t%4,-24(%0)\n\t"
419 "sw\t%5,-20(%0)\n\t"
420 "cache\t%9,-16(%0)\n\t"
421 "lw\t%2,-16(%1)\n\t"
422 "lw\t%3,-12(%1)\n\t"
423 "lw\t%4,-8(%1)\n\t"
424 "lw\t%5,-4(%1)\n\t"
425 "sw\t%2,-16(%0)\n\t"
426 "sw\t%3,-12(%0)\n\t"
427 "sw\t%4,-8(%0)\n\t"
428 "bne\t$1,%0,1b\n\t"
429 "sw\t%5,-4(%0)\n\t"
430 ".set\tmips0\n\t"
431 ".set\tat\n\t"
432 ".set\treorder"
433 :"=r" (dummy1), "=r" (dummy2),
434 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
435 :"0" (to), "1" (from),
436 "I" (PAGE_SIZE),
437 "i" (Create_Dirty_Excl_D));
438}
439
440static void r4k_copy_page_d32(void * to, void * from)
441{
442 unsigned long dummy1, dummy2;
443 unsigned long reg1, reg2, reg3, reg4;
444
445 __asm__ __volatile__(
446 ".set\tnoreorder\n\t"
447 ".set\tnoat\n\t"
448 ".set\tmips3\n\t"
449 "daddiu\t$1,%0,%8\n"
450 "1:\tcache\t%9,(%0)\n\t"
451 "lw\t%2,(%1)\n\t"
452 "lw\t%3,4(%1)\n\t"
453 "lw\t%4,8(%1)\n\t"
454 "lw\t%5,12(%1)\n\t"
455 "sw\t%2,(%0)\n\t"
456 "sw\t%3,4(%0)\n\t"
457 "sw\t%4,8(%0)\n\t"
458 "sw\t%5,12(%0)\n\t"
459 "lw\t%2,16(%1)\n\t"
460 "lw\t%3,20(%1)\n\t"
461 "lw\t%4,24(%1)\n\t"
462 "lw\t%5,28(%1)\n\t"
463 "sw\t%2,16(%0)\n\t"
464 "sw\t%3,20(%0)\n\t"
465 "sw\t%4,24(%0)\n\t"
466 "sw\t%5,28(%0)\n\t"
467 "cache\t%9,32(%0)\n\t"
468 "daddiu\t%0,64\n\t"
469 "daddiu\t%1,64\n\t"
470 "lw\t%2,-32(%1)\n\t"
471 "lw\t%3,-28(%1)\n\t"
472 "lw\t%4,-24(%1)\n\t"
473 "lw\t%5,-20(%1)\n\t"
474 "sw\t%2,-32(%0)\n\t"
475 "sw\t%3,-28(%0)\n\t"
476 "sw\t%4,-24(%0)\n\t"
477 "sw\t%5,-20(%0)\n\t"
478 "lw\t%2,-16(%1)\n\t"
479 "lw\t%3,-12(%1)\n\t"
480 "lw\t%4,-8(%1)\n\t"
481 "lw\t%5,-4(%1)\n\t"
482 "sw\t%2,-16(%0)\n\t"
483 "sw\t%3,-12(%0)\n\t"
484 "sw\t%4,-8(%0)\n\t"
485 "bne\t$1,%0,1b\n\t"
486 "sw\t%5,-4(%0)\n\t"
487 ".set\tmips0\n\t"
488 ".set\tat\n\t"
489 ".set\treorder"
490 :"=r" (dummy1), "=r" (dummy2),
491 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
492 :"0" (to), "1" (from),
493 "I" (PAGE_SIZE),
494 "i" (Create_Dirty_Excl_D));
495}
496
497
498
499
500static void r4k_copy_page_r4600_v1(void * to, void * from)
501{
502 unsigned long dummy1, dummy2;
503 unsigned long reg1, reg2, reg3, reg4;
504
505 __asm__ __volatile__(
506 ".set\tnoreorder\n\t"
507 ".set\tnoat\n\t"
508 ".set\tmips3\n\t"
509 "daddiu\t$1,%0,%8\n"
510 "1:\tnop\n\t"
511 "nop\n\t"
512 "nop\n\t"
513 "nop\n\t"
514 "\tcache\t%9,(%0)\n\t"
515 "lw\t%2,(%1)\n\t"
516 "lw\t%3,4(%1)\n\t"
517 "lw\t%4,8(%1)\n\t"
518 "lw\t%5,12(%1)\n\t"
519 "sw\t%2,(%0)\n\t"
520 "sw\t%3,4(%0)\n\t"
521 "sw\t%4,8(%0)\n\t"
522 "sw\t%5,12(%0)\n\t"
523 "lw\t%2,16(%1)\n\t"
524 "lw\t%3,20(%1)\n\t"
525 "lw\t%4,24(%1)\n\t"
526 "lw\t%5,28(%1)\n\t"
527 "sw\t%2,16(%0)\n\t"
528 "sw\t%3,20(%0)\n\t"
529 "sw\t%4,24(%0)\n\t"
530 "sw\t%5,28(%0)\n\t"
531 "nop\n\t"
532 "nop\n\t"
533 "nop\n\t"
534 "nop\n\t"
535 "cache\t%9,32(%0)\n\t"
536 "daddiu\t%0,64\n\t"
537 "daddiu\t%1,64\n\t"
538 "lw\t%2,-32(%1)\n\t"
539 "lw\t%3,-28(%1)\n\t"
540 "lw\t%4,-24(%1)\n\t"
541 "lw\t%5,-20(%1)\n\t"
542 "sw\t%2,-32(%0)\n\t"
543 "sw\t%3,-28(%0)\n\t"
544 "sw\t%4,-24(%0)\n\t"
545 "sw\t%5,-20(%0)\n\t"
546 "lw\t%2,-16(%1)\n\t"
547 "lw\t%3,-12(%1)\n\t"
548 "lw\t%4,-8(%1)\n\t"
549 "lw\t%5,-4(%1)\n\t"
550 "sw\t%2,-16(%0)\n\t"
551 "sw\t%3,-12(%0)\n\t"
552 "sw\t%4,-8(%0)\n\t"
553 "bne\t$1,%0,1b\n\t"
554 "sw\t%5,-4(%0)\n\t"
555 ".set\tmips0\n\t"
556 ".set\tat\n\t"
557 ".set\treorder"
558 :"=r" (dummy1), "=r" (dummy2),
559 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
560 :"0" (to), "1" (from),
561 "I" (PAGE_SIZE),
562 "i" (Create_Dirty_Excl_D));
563}
564
565static void r4k_copy_page_r4600_v2(void * to, void * from)
566{
567 unsigned long dummy1, dummy2;
568 unsigned long reg1, reg2, reg3, reg4;
569 unsigned int flags;
570
571 local_irq_save(flags);
572 __asm__ __volatile__(
573 ".set\tnoreorder\n\t"
574 ".set\tnoat\n\t"
575 ".set\tmips3\n\t"
576 "daddiu\t$1,%0,%8\n"
577 "1:\tnop\n\t"
578 "nop\n\t"
579 "nop\n\t"
580 "nop\n\t"
581 "\tcache\t%9,(%0)\n\t"
582 "lw\t%2,(%1)\n\t"
583 "lw\t%3,4(%1)\n\t"
584 "lw\t%4,8(%1)\n\t"
585 "lw\t%5,12(%1)\n\t"
586 "sw\t%2,(%0)\n\t"
587 "sw\t%3,4(%0)\n\t"
588 "sw\t%4,8(%0)\n\t"
589 "sw\t%5,12(%0)\n\t"
590 "lw\t%2,16(%1)\n\t"
591 "lw\t%3,20(%1)\n\t"
592 "lw\t%4,24(%1)\n\t"
593 "lw\t%5,28(%1)\n\t"
594 "sw\t%2,16(%0)\n\t"
595 "sw\t%3,20(%0)\n\t"
596 "sw\t%4,24(%0)\n\t"
597 "sw\t%5,28(%0)\n\t"
598 "nop\n\t"
599 "nop\n\t"
600 "nop\n\t"
601 "nop\n\t"
602 "cache\t%9,32(%0)\n\t"
603 "daddiu\t%0,64\n\t"
604 "daddiu\t%1,64\n\t"
605 "lw\t%2,-32(%1)\n\t"
606 "lw\t%3,-28(%1)\n\t"
607 "lw\t%4,-24(%1)\n\t"
608 "lw\t%5,-20(%1)\n\t"
609 "sw\t%2,-32(%0)\n\t"
610 "sw\t%3,-28(%0)\n\t"
611 "sw\t%4,-24(%0)\n\t"
612 "sw\t%5,-20(%0)\n\t"
613 "lw\t%2,-16(%1)\n\t"
614 "lw\t%3,-12(%1)\n\t"
615 "lw\t%4,-8(%1)\n\t"
616 "lw\t%5,-4(%1)\n\t"
617 "sw\t%2,-16(%0)\n\t"
618 "sw\t%3,-12(%0)\n\t"
619 "sw\t%4,-8(%0)\n\t"
620 "bne\t$1,%0,1b\n\t"
621 "sw\t%5,-4(%0)\n\t"
622 ".set\tmips0\n\t"
623 ".set\tat\n\t"
624 ".set\treorder"
625 :"=r" (dummy1), "=r" (dummy2),
626 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
627 :"0" (to), "1" (from),
628 "I" (PAGE_SIZE),
629 "i" (Create_Dirty_Excl_D));
630 local_irq_restore(flags);
631}
632
633
634
635
636static void r4k_copy_page_s16(void * to, void * from)
637{
638 unsigned long dummy1, dummy2;
639 unsigned long reg1, reg2, reg3, reg4;
640
641 __asm__ __volatile__(
642 ".set\tnoreorder\n\t"
643 ".set\tnoat\n\t"
644 ".set\tmips3\n\t"
645 "daddiu\t$1,%0,%8\n"
646 "1:\tcache\t%9,(%0)\n\t"
647 "lw\t%2,(%1)\n\t"
648 "lw\t%3,4(%1)\n\t"
649 "lw\t%4,8(%1)\n\t"
650 "lw\t%5,12(%1)\n\t"
651 "sw\t%2,(%0)\n\t"
652 "sw\t%3,4(%0)\n\t"
653 "sw\t%4,8(%0)\n\t"
654 "sw\t%5,12(%0)\n\t"
655 "cache\t%9,16(%0)\n\t"
656 "lw\t%2,16(%1)\n\t"
657 "lw\t%3,20(%1)\n\t"
658 "lw\t%4,24(%1)\n\t"
659 "lw\t%5,28(%1)\n\t"
660 "sw\t%2,16(%0)\n\t"
661 "sw\t%3,20(%0)\n\t"
662 "sw\t%4,24(%0)\n\t"
663 "sw\t%5,28(%0)\n\t"
664 "cache\t%9,32(%0)\n\t"
665 "daddiu\t%0,64\n\t"
666 "daddiu\t%1,64\n\t"
667 "lw\t%2,-32(%1)\n\t"
668 "lw\t%3,-28(%1)\n\t"
669 "lw\t%4,-24(%1)\n\t"
670 "lw\t%5,-20(%1)\n\t"
671 "sw\t%2,-32(%0)\n\t"
672 "sw\t%3,-28(%0)\n\t"
673 "sw\t%4,-24(%0)\n\t"
674 "sw\t%5,-20(%0)\n\t"
675 "cache\t%9,-16(%0)\n\t"
676 "lw\t%2,-16(%1)\n\t"
677 "lw\t%3,-12(%1)\n\t"
678 "lw\t%4,-8(%1)\n\t"
679 "lw\t%5,-4(%1)\n\t"
680 "sw\t%2,-16(%0)\n\t"
681 "sw\t%3,-12(%0)\n\t"
682 "sw\t%4,-8(%0)\n\t"
683 "bne\t$1,%0,1b\n\t"
684 "sw\t%5,-4(%0)\n\t"
685 ".set\tmips0\n\t"
686 ".set\tat\n\t"
687 ".set\treorder"
688 :"=r" (dummy1), "=r" (dummy2),
689 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
690 :"0" (to), "1" (from),
691 "I" (PAGE_SIZE),
692 "i" (Create_Dirty_Excl_SD));
693}
694
695static void r4k_copy_page_s32(void * to, void * from)
696{
697 unsigned long dummy1, dummy2;
698 unsigned long reg1, reg2, reg3, reg4;
699
700 __asm__ __volatile__(
701 ".set\tnoreorder\n\t"
702 ".set\tnoat\n\t"
703 ".set\tmips3\n\t"
704 "daddiu\t$1,%0,%8\n"
705 "1:\tcache\t%9,(%0)\n\t"
706 "lw\t%2,(%1)\n\t"
707 "lw\t%3,4(%1)\n\t"
708 "lw\t%4,8(%1)\n\t"
709 "lw\t%5,12(%1)\n\t"
710 "sw\t%2,(%0)\n\t"
711 "sw\t%3,4(%0)\n\t"
712 "sw\t%4,8(%0)\n\t"
713 "sw\t%5,12(%0)\n\t"
714 "lw\t%2,16(%1)\n\t"
715 "lw\t%3,20(%1)\n\t"
716 "lw\t%4,24(%1)\n\t"
717 "lw\t%5,28(%1)\n\t"
718 "sw\t%2,16(%0)\n\t"
719 "sw\t%3,20(%0)\n\t"
720 "sw\t%4,24(%0)\n\t"
721 "sw\t%5,28(%0)\n\t"
722 "cache\t%9,32(%0)\n\t"
723 "daddiu\t%0,64\n\t"
724 "daddiu\t%1,64\n\t"
725 "lw\t%2,-32(%1)\n\t"
726 "lw\t%3,-28(%1)\n\t"
727 "lw\t%4,-24(%1)\n\t"
728 "lw\t%5,-20(%1)\n\t"
729 "sw\t%2,-32(%0)\n\t"
730 "sw\t%3,-28(%0)\n\t"
731 "sw\t%4,-24(%0)\n\t"
732 "sw\t%5,-20(%0)\n\t"
733 "lw\t%2,-16(%1)\n\t"
734 "lw\t%3,-12(%1)\n\t"
735 "lw\t%4,-8(%1)\n\t"
736 "lw\t%5,-4(%1)\n\t"
737 "sw\t%2,-16(%0)\n\t"
738 "sw\t%3,-12(%0)\n\t"
739 "sw\t%4,-8(%0)\n\t"
740 "bne\t$1,%0,1b\n\t"
741 "sw\t%5,-4(%0)\n\t"
742 ".set\tmips0\n\t"
743 ".set\tat\n\t"
744 ".set\treorder"
745 :"=r" (dummy1), "=r" (dummy2),
746 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
747 :"0" (to), "1" (from),
748 "I" (PAGE_SIZE),
749 "i" (Create_Dirty_Excl_SD));
750}
751
752static void r4k_copy_page_s64(void * to, void * from)
753{
754 unsigned long dummy1, dummy2;
755 unsigned long reg1, reg2, reg3, reg4;
756
757 __asm__ __volatile__(
758 ".set\tnoreorder\n\t"
759 ".set\tnoat\n\t"
760 ".set\tmips3\n\t"
761 "daddiu\t$1,%0,%8\n"
762 "1:\tcache\t%9,(%0)\n\t"
763 "lw\t%2,(%1)\n\t"
764 "lw\t%3,4(%1)\n\t"
765 "lw\t%4,8(%1)\n\t"
766 "lw\t%5,12(%1)\n\t"
767 "sw\t%2,(%0)\n\t"
768 "sw\t%3,4(%0)\n\t"
769 "sw\t%4,8(%0)\n\t"
770 "sw\t%5,12(%0)\n\t"
771 "lw\t%2,16(%1)\n\t"
772 "lw\t%3,20(%1)\n\t"
773 "lw\t%4,24(%1)\n\t"
774 "lw\t%5,28(%1)\n\t"
775 "sw\t%2,16(%0)\n\t"
776 "sw\t%3,20(%0)\n\t"
777 "sw\t%4,24(%0)\n\t"
778 "sw\t%5,28(%0)\n\t"
779 "daddiu\t%0,64\n\t"
780 "daddiu\t%1,64\n\t"
781 "lw\t%2,-32(%1)\n\t"
782 "lw\t%3,-28(%1)\n\t"
783 "lw\t%4,-24(%1)\n\t"
784 "lw\t%5,-20(%1)\n\t"
785 "sw\t%2,-32(%0)\n\t"
786 "sw\t%3,-28(%0)\n\t"
787 "sw\t%4,-24(%0)\n\t"
788 "sw\t%5,-20(%0)\n\t"
789 "lw\t%2,-16(%1)\n\t"
790 "lw\t%3,-12(%1)\n\t"
791 "lw\t%4,-8(%1)\n\t"
792 "lw\t%5,-4(%1)\n\t"
793 "sw\t%2,-16(%0)\n\t"
794 "sw\t%3,-12(%0)\n\t"
795 "sw\t%4,-8(%0)\n\t"
796 "bne\t$1,%0,1b\n\t"
797 "sw\t%5,-4(%0)\n\t"
798 ".set\tmips0\n\t"
799 ".set\tat\n\t"
800 ".set\treorder"
801 :"=r" (dummy1), "=r" (dummy2),
802 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
803 :"0" (to), "1" (from),
804 "I" (PAGE_SIZE),
805 "i" (Create_Dirty_Excl_SD));
806}
807
808static void r4k_copy_page_s128(void * to, void * from)
809{
810 unsigned long dummy1, dummy2;
811 unsigned long reg1, reg2, reg3, reg4;
812
813 __asm__ __volatile__(
814 ".set\tnoreorder\n\t"
815 ".set\tnoat\n\t"
816 ".set\tmips3\n\t"
817 "daddiu\t$1,%0,%8\n"
818 "1:\tcache\t%9,(%0)\n\t"
819 "lw\t%2,(%1)\n\t"
820 "lw\t%3,4(%1)\n\t"
821 "lw\t%4,8(%1)\n\t"
822 "lw\t%5,12(%1)\n\t"
823 "sw\t%2,(%0)\n\t"
824 "sw\t%3,4(%0)\n\t"
825 "sw\t%4,8(%0)\n\t"
826 "sw\t%5,12(%0)\n\t"
827 "lw\t%2,16(%1)\n\t"
828 "lw\t%3,20(%1)\n\t"
829 "lw\t%4,24(%1)\n\t"
830 "lw\t%5,28(%1)\n\t"
831 "sw\t%2,16(%0)\n\t"
832 "sw\t%3,20(%0)\n\t"
833 "sw\t%4,24(%0)\n\t"
834 "sw\t%5,28(%0)\n\t"
835 "lw\t%2,32(%1)\n\t"
836 "lw\t%3,36(%1)\n\t"
837 "lw\t%4,40(%1)\n\t"
838 "lw\t%5,44(%1)\n\t"
839 "sw\t%2,32(%0)\n\t"
840 "sw\t%3,36(%0)\n\t"
841 "sw\t%4,40(%0)\n\t"
842 "sw\t%5,44(%0)\n\t"
843 "lw\t%2,48(%1)\n\t"
844 "lw\t%3,52(%1)\n\t"
845 "lw\t%4,56(%1)\n\t"
846 "lw\t%5,60(%1)\n\t"
847 "sw\t%2,48(%0)\n\t"
848 "sw\t%3,52(%0)\n\t"
849 "sw\t%4,56(%0)\n\t"
850 "sw\t%5,60(%0)\n\t"
851 "daddiu\t%0,128\n\t"
852 "daddiu\t%1,128\n\t"
853 "lw\t%2,-64(%1)\n\t"
854 "lw\t%3,-60(%1)\n\t"
855 "lw\t%4,-56(%1)\n\t"
856 "lw\t%5,-52(%1)\n\t"
857 "sw\t%2,-64(%0)\n\t"
858 "sw\t%3,-60(%0)\n\t"
859 "sw\t%4,-56(%0)\n\t"
860 "sw\t%5,-52(%0)\n\t"
861 "lw\t%2,-48(%1)\n\t"
862 "lw\t%3,-44(%1)\n\t"
863 "lw\t%4,-40(%1)\n\t"
864 "lw\t%5,-36(%1)\n\t"
865 "sw\t%2,-48(%0)\n\t"
866 "sw\t%3,-44(%0)\n\t"
867 "sw\t%4,-40(%0)\n\t"
868 "sw\t%5,-36(%0)\n\t"
869 "lw\t%2,-32(%1)\n\t"
870 "lw\t%3,-28(%1)\n\t"
871 "lw\t%4,-24(%1)\n\t"
872 "lw\t%5,-20(%1)\n\t"
873 "sw\t%2,-32(%0)\n\t"
874 "sw\t%3,-28(%0)\n\t"
875 "sw\t%4,-24(%0)\n\t"
876 "sw\t%5,-20(%0)\n\t"
877 "lw\t%2,-16(%1)\n\t"
878 "lw\t%3,-12(%1)\n\t"
879 "lw\t%4,-8(%1)\n\t"
880 "lw\t%5,-4(%1)\n\t"
881 "sw\t%2,-16(%0)\n\t"
882 "sw\t%3,-12(%0)\n\t"
883 "sw\t%4,-8(%0)\n\t"
884 "bne\t$1,%0,1b\n\t"
885 "sw\t%5,-4(%0)\n\t"
886 ".set\tmips0\n\t"
887 ".set\tat\n\t"
888 ".set\treorder"
889 :"=r" (dummy1), "=r" (dummy2),
890 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
891 :"0" (to), "1" (from),
892 "I" (PAGE_SIZE),
893 "i" (Create_Dirty_Excl_SD));
894}
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910static inline void r4k_flush_cache_all_s16d16i16(void)
911{
912 unsigned long flags;
913
914 local_irq_save(flags);
915 blast_dcache16(); blast_icache16(); blast_scache16();
916 local_irq_restore(flags);
917}
918
919static inline void r4k_flush_cache_all_s32d16i16(void)
920{
921 unsigned long flags;
922
923 local_irq_save(flags);
924 blast_dcache16(); blast_icache16(); blast_scache32();
925 local_irq_restore(flags);
926}
927
928static inline void r4k_flush_cache_all_s64d16i16(void)
929{
930 unsigned long flags;
931
932 local_irq_save(flags);
933 blast_dcache16(); blast_icache16(); blast_scache64();
934 local_irq_restore(flags);
935}
936
937static inline void r4k_flush_cache_all_s128d16i16(void)
938{
939 unsigned long flags;
940
941 local_irq_save(flags);
942 blast_dcache16(); blast_icache16(); blast_scache128();
943 local_irq_restore(flags);
944}
945
946static inline void r4k_flush_cache_all_s32d32i32(void)
947{
948 unsigned long flags;
949
950 local_irq_save(flags);
951 blast_dcache32(); blast_icache32(); blast_scache32();
952 local_irq_restore(flags);
953}
954
955static inline void r4k_flush_cache_all_s64d32i32(void)
956{
957 unsigned long flags;
958
959 local_irq_save(flags);
960 blast_dcache32(); blast_icache32(); blast_scache64();
961 local_irq_restore(flags);
962}
963
964static inline void r4k_flush_cache_all_s128d32i32(void)
965{
966 unsigned long flags;
967
968 local_irq_save(flags);
969 blast_dcache32(); blast_icache32(); blast_scache128();
970 local_irq_restore(flags);
971}
972
973static inline void r4k_flush_cache_all_d16i16(void)
974{
975 unsigned long flags;
976
977 local_irq_save(flags);
978 blast_dcache16(); blast_icache16();
979 local_irq_restore(flags);
980}
981
982static inline void r4k_flush_cache_all_d32i32(void)
983{
984 unsigned long flags;
985
986 local_irq_save(flags);
987 blast_dcache32(); blast_icache32();
988 local_irq_restore(flags);
989}
990
991static void
992r4k_flush_cache_range_s16d16i16(struct vm_area_struct *vma,
993 unsigned long start,
994 unsigned long end)
995{
996 struct mm_struct *mm = vma->vm_mm;
997 unsigned long flags;
998
999 if (mm->context == 0)
1000 return;
1001
1002 start &= PAGE_MASK;
1003#ifdef DEBUG_CACHE
1004 printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
1005#endif
1006 if (vma) {
1007 if (mm->context != current->active_mm->context) {
1008 r4k_flush_cache_all_s16d16i16();
1009 } else {
1010 pgd_t *pgd;
1011 pmd_t *pmd;
1012 pte_t *pte;
1013
1014 local_irq_save(flags);
1015 while(start < end) {
1016 pgd = pgd_offset(mm, start);
1017 pmd = pmd_offset(pgd, start);
1018 pte = pte_offset(pmd, start);
1019
1020 if(pte_val(*pte) & _PAGE_VALID)
1021 blast_scache16_page(start);
1022 start += PAGE_SIZE;
1023 }
1024 local_irq_restore(flags);
1025 }
1026 }
1027}
1028
1029static void
1030r4k_flush_cache_range_s32d16i16(struct vm_area_struct *vma,
1031 unsigned long start,
1032 unsigned long end)
1033{
1034 struct mm_struct *mm = vma->vm_mm;
1035 unsigned long flags;
1036
1037 if (mm->context == 0)
1038 return;
1039
1040 start &= PAGE_MASK;
1041#ifdef DEBUG_CACHE
1042 printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
1043#endif
1044 if (vma) {
1045 if (mm->context != current->active_mm->context) {
1046 r4k_flush_cache_all_s32d16i16();
1047 } else {
1048 pgd_t *pgd;
1049 pmd_t *pmd;
1050 pte_t *pte;
1051
1052 local_irq_save(flags);
1053 while(start < end) {
1054 pgd = pgd_offset(mm, start);
1055 pmd = pmd_offset(pgd, start);
1056 pte = pte_offset(pmd, start);
1057
1058 if(pte_val(*pte) & _PAGE_VALID)
1059 blast_scache32_page(start);
1060 start += PAGE_SIZE;
1061 }
1062 local_irq_restore(flags);
1063 }
1064 }
1065}
1066
1067static void r4k_flush_cache_range_s64d16i16(struct vm_area_struct *vma,
1068 unsigned long start,
1069 unsigned long end)
1070{
1071 struct mm_struct *mm = vma->vm_mm;
1072 unsigned long flags;
1073
1074 if (mm->context == 0)
1075 return;
1076
1077 start &= PAGE_MASK;
1078#ifdef DEBUG_CACHE
1079 printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
1080#endif
1081 if(vma) {
1082 if (mm->context != current->active_mm->context) {
1083 r4k_flush_cache_all_s64d16i16();
1084 } else {
1085 pgd_t *pgd;
1086 pmd_t *pmd;
1087 pte_t *pte;
1088
1089 local_irq_save(flags);
1090 while(start < end) {
1091 pgd = pgd_offset(mm, start);
1092 pmd = pmd_offset(pgd, start);
1093 pte = pte_offset(pmd, start);
1094
1095 if(pte_val(*pte) & _PAGE_VALID)
1096 blast_scache64_page(start);
1097 start += PAGE_SIZE;
1098 }
1099 local_irq_restore(flags);
1100 }
1101 }
1102}
1103
1104static void r4k_flush_cache_range_s128d16i16(struct vm_area_struct *vma,
1105 unsigned long start,
1106 unsigned long end)
1107{
1108 struct mm_struct *mm = vma->vm_mm;
1109 unsigned long flags;
1110
1111 if (mm->context == 0)
1112 return;
1113
1114 start &= PAGE_MASK;
1115#ifdef DEBUG_CACHE
1116 printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
1117#endif
1118 if (vma) {
1119 if (mm->context != current->active_mm->context) {
1120 r4k_flush_cache_all_s128d16i16();
1121 } else {
1122 pgd_t *pgd;
1123 pmd_t *pmd;
1124 pte_t *pte;
1125
1126 local_irq_save(flags);
1127 while(start < end) {
1128 pgd = pgd_offset(mm, start);
1129 pmd = pmd_offset(pgd, start);
1130 pte = pte_offset(pmd, start);
1131
1132 if(pte_val(*pte) & _PAGE_VALID)
1133 blast_scache128_page(start);
1134 start += PAGE_SIZE;
1135 }
1136 local_irq_restore(flags);
1137 }
1138 }
1139}
1140
1141static void r4k_flush_cache_range_s32d32i32(struct vm_area_struct *vma,
1142 unsigned long start,
1143 unsigned long end)
1144{
1145 struct mm_struct *mm = vma->vm_mm;
1146 unsigned long flags;
1147
1148 if (mm->context == 0)
1149 return;
1150
1151 start &= PAGE_MASK;
1152#ifdef DEBUG_CACHE
1153 printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
1154#endif
1155 if (vma) {
1156 if (mm->context != current->active_mm->context) {
1157 r4k_flush_cache_all_s32d32i32();
1158 } else {
1159 pgd_t *pgd;
1160 pmd_t *pmd;
1161 pte_t *pte;
1162
1163 local_irq_save(flags);
1164 while(start < end) {
1165 pgd = pgd_offset(mm, start);
1166 pmd = pmd_offset(pgd, start);
1167 pte = pte_offset(pmd, start);
1168
1169 if(pte_val(*pte) & _PAGE_VALID)
1170 blast_scache32_page(start);
1171 start += PAGE_SIZE;
1172 }
1173 local_irq_restore(flags);
1174 }
1175 }
1176}
1177
1178static void r4k_flush_cache_range_s64d32i32(struct vm_area_struct *vma,
1179 unsigned long start,
1180 unsigned long end)
1181{
1182 struct mm_struct *mm = vma->vm_mm;
1183 unsigned long flags;
1184
1185 if (mm->context == 0)
1186 return;
1187
1188 start &= PAGE_MASK;
1189#ifdef DEBUG_CACHE
1190 printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
1191#endif
1192 if (vma) {
1193 if (mm->context != current->active_mm->context) {
1194 r4k_flush_cache_all_s64d32i32();
1195 } else {
1196 pgd_t *pgd;
1197 pmd_t *pmd;
1198 pte_t *pte;
1199
1200 local_irq_save(flags);
1201 while(start < end) {
1202 pgd = pgd_offset(mm, start);
1203 pmd = pmd_offset(pgd, start);
1204 pte = pte_offset(pmd, start);
1205
1206 if(pte_val(*pte) & _PAGE_VALID)
1207 blast_scache64_page(start);
1208 start += PAGE_SIZE;
1209 }
1210 local_irq_restore(flags);
1211 }
1212 }
1213}
1214
1215static void r4k_flush_cache_range_s128d32i32(struct vm_area_struct *vma,
1216 unsigned long start,
1217 unsigned long end)
1218{
1219 struct mm_struct *mm = vma->vm_mm;
1220 unsigned long flags;
1221
1222 if (mm->context == 0)
1223 return;
1224
1225 start &= PAGE_MASK;
1226#ifdef DEBUG_CACHE
1227 printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
1228#endif
1229 if (vma) {
1230 if (mm->context != current->active_mm->context) {
1231 r4k_flush_cache_all_s128d32i32();
1232 } else {
1233 pgd_t *pgd;
1234 pmd_t *pmd;
1235 pte_t *pte;
1236
1237 local_irq_save(flags);
1238 while(start < end) {
1239 pgd = pgd_offset(mm, start);
1240 pmd = pmd_offset(pgd, start);
1241 pte = pte_offset(pmd, start);
1242
1243 if(pte_val(*pte) & _PAGE_VALID)
1244 blast_scache128_page(start);
1245 start += PAGE_SIZE;
1246 }
1247 local_irq_restore(flags);
1248 }
1249 }
1250}
1251
1252static void r4k_flush_cache_range_d16i16(struct mm_struct *vma,
1253 unsigned long start,
1254 unsigned long end)
1255{
1256 struct mm_struct *mm = vma->vm_mm;
1257
1258 if (mm->context != 0) {
1259 unsigned long flags;
1260
1261#ifdef DEBUG_CACHE
1262 printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
1263#endif
1264 local_irq_save(flags);
1265 blast_dcache16(); blast_icache16();
1266 local_irq_restore(flags);
1267 }
1268}
1269
1270static void r4k_flush_cache_range_d32i32(struct vm_area_struct *vma,
1271 unsigned long start,
1272 unsigned long end)
1273{
1274 struct mm_struct *mm = vma->vm_mm;
1275
1276 if (mm->context != 0) {
1277 unsigned long flags;
1278
1279#ifdef DEBUG_CACHE
1280 printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
1281#endif
1282 local_irq_save(flags);
1283 blast_dcache32(); blast_icache32();
1284 local_irq_restore(flags);
1285 }
1286}
1287
1288
1289
1290
1291
1292
1293static void r4k_flush_cache_mm_s16d16i16(struct mm_struct *mm)
1294{
1295 if (mm->context != 0) {
1296#ifdef DEBUG_CACHE
1297 printk("cmm[%d]", (int)mm->context);
1298#endif
1299 r4k_flush_cache_all_s16d16i16();
1300 }
1301}
1302
1303static void r4k_flush_cache_mm_s32d16i16(struct mm_struct *mm)
1304{
1305 if (mm->context != 0) {
1306#ifdef DEBUG_CACHE
1307 printk("cmm[%d]", (int)mm->context);
1308#endif
1309 r4k_flush_cache_all_s32d16i16();
1310 }
1311}
1312
1313static void r4k_flush_cache_mm_s64d16i16(struct mm_struct *mm)
1314{
1315 if (mm->context != 0) {
1316#ifdef DEBUG_CACHE
1317 printk("cmm[%d]", (int)mm->context);
1318#endif
1319 r4k_flush_cache_all_s64d16i16();
1320 }
1321}
1322
1323static void r4k_flush_cache_mm_s128d16i16(struct mm_struct *mm)
1324{
1325 if (mm->context != 0) {
1326#ifdef DEBUG_CACHE
1327 printk("cmm[%d]", (int)mm->context);
1328#endif
1329 r4k_flush_cache_all_s128d16i16();
1330 }
1331}
1332
1333static void r4k_flush_cache_mm_s32d32i32(struct mm_struct *mm)
1334{
1335 if (mm->context != 0) {
1336#ifdef DEBUG_CACHE
1337 printk("cmm[%d]", (int)mm->context);
1338#endif
1339 r4k_flush_cache_all_s32d32i32();
1340 }
1341}
1342
1343static void r4k_flush_cache_mm_s64d32i32(struct mm_struct *mm)
1344{
1345 if (mm->context != 0) {
1346#ifdef DEBUG_CACHE
1347 printk("cmm[%d]", (int)mm->context);
1348#endif
1349 r4k_flush_cache_all_s64d32i32();
1350 }
1351}
1352
1353static void r4k_flush_cache_mm_s128d32i32(struct mm_struct *mm)
1354{
1355 if (mm->context != 0) {
1356#ifdef DEBUG_CACHE
1357 printk("cmm[%d]", (int)mm->context);
1358#endif
1359 r4k_flush_cache_all_s128d32i32();
1360 }
1361}
1362
1363static void r4k_flush_cache_mm_d16i16(struct mm_struct *mm)
1364{
1365 if (mm->context != 0) {
1366#ifdef DEBUG_CACHE
1367 printk("cmm[%d]", (int)mm->context);
1368#endif
1369 r4k_flush_cache_all_d16i16();
1370 }
1371}
1372
1373static void r4k_flush_cache_mm_d32i32(struct mm_struct *mm)
1374{
1375 if (mm->context != 0) {
1376#ifdef DEBUG_CACHE
1377 printk("cmm[%d]", (int)mm->context);
1378#endif
1379 r4k_flush_cache_all_d32i32();
1380 }
1381}
1382
1383static void r4k_flush_cache_page_s16d16i16(struct vm_area_struct *vma,
1384 unsigned long page)
1385{
1386 struct mm_struct *mm = vma->vm_mm;
1387 unsigned long flags;
1388 pgd_t *pgdp;
1389 pmd_t *pmdp;
1390 pte_t *ptep;
1391
1392
1393
1394
1395
1396 if (mm->context == 0)
1397 return;
1398
1399#ifdef DEBUG_CACHE
1400 printk("cpage[%d,%08lx]", (int)mm->context, page);
1401#endif
1402 local_irq_save(flags);
1403 page &= PAGE_MASK;
1404 pgdp = pgd_offset(mm, page);
1405 pmdp = pmd_offset(pgdp, page);
1406 ptep = pte_offset(pmdp, page);
1407
1408
1409
1410
1411
1412 if (!(pte_val(*ptep) & _PAGE_VALID))
1413 goto out;
1414
1415
1416
1417
1418
1419
1420
1421 if (mm->context != current->active_mm->context) {
1422
1423
1424
1425
1426 page = (KSEG0 + (page & (scache_size - 1)));
1427 blast_dcache16_page_indexed(page);
1428 blast_scache16_page_indexed(page);
1429 } else
1430 blast_scache16_page(page);
1431out:
1432 local_irq_restore(flags);
1433}
1434
1435static void r4k_flush_cache_page_s32d16i16(struct vm_area_struct *vma,
1436 unsigned long page)
1437{
1438 struct mm_struct *mm = vma->vm_mm;
1439 unsigned long flags;
1440 pgd_t *pgdp;
1441 pmd_t *pmdp;
1442 pte_t *ptep;
1443
1444
1445
1446
1447
1448 if (mm->context == 0)
1449 return;
1450
1451#ifdef DEBUG_CACHE
1452 printk("cpage[%d,%08lx]", (int)mm->context, page);
1453#endif
1454 local_irq_save(flags);
1455 page &= PAGE_MASK;
1456 pgdp = pgd_offset(mm, page);
1457 pmdp = pmd_offset(pgdp, page);
1458 ptep = pte_offset(pmdp, page);
1459
1460
1461
1462
1463 if (!(pte_val(*ptep) & _PAGE_VALID))
1464 goto out;
1465
1466
1467
1468
1469
1470
1471
1472 if (mm->context != current->active_mm->context) {
1473
1474
1475
1476
1477 page = (KSEG0 + (page & (scache_size - 1)));
1478 blast_dcache16_page_indexed(page);
1479 blast_scache32_page_indexed(page);
1480 } else
1481 blast_scache32_page(page);
1482out:
1483 local_irq_restore(flags);
1484}
1485
1486static void r4k_flush_cache_page_s64d16i16(struct vm_area_struct *vma,
1487 unsigned long page)
1488{
1489 struct mm_struct *mm = vma->vm_mm;
1490 unsigned long flags;
1491 pgd_t *pgdp;
1492 pmd_t *pmdp;
1493 pte_t *ptep;
1494
1495
1496
1497
1498
1499 if (mm->context == 0)
1500 return;
1501
1502#ifdef DEBUG_CACHE
1503 printk("cpage[%d,%08lx]", (int)mm->context, page);
1504#endif
1505 local_irq_save(flags);
1506 page &= PAGE_MASK;
1507 pgdp = pgd_offset(mm, page);
1508 pmdp = pmd_offset(pgdp, page);
1509 ptep = pte_offset(pmdp, page);
1510
1511
1512
1513
1514 if (!(pte_val(*ptep) & _PAGE_VALID))
1515 goto out;
1516
1517
1518
1519
1520
1521
1522
1523 if (mm->context != current->active_mm->context) {
1524
1525
1526
1527
1528 page = (KSEG0 + (page & (scache_size - 1)));
1529 blast_dcache16_page_indexed(page);
1530 blast_scache64_page_indexed(page);
1531 } else
1532 blast_scache64_page(page);
1533out:
1534 local_irq_restore(flags);
1535}
1536
1537static void r4k_flush_cache_page_s128d16i16(struct vm_area_struct *vma,
1538 unsigned long page)
1539{
1540 struct mm_struct *mm = vma->vm_mm;
1541 unsigned long flags;
1542 pgd_t *pgdp;
1543 pmd_t *pmdp;
1544 pte_t *ptep;
1545
1546
1547
1548
1549
1550 if (mm->context == 0)
1551 return;
1552
1553#ifdef DEBUG_CACHE
1554 printk("cpage[%d,%08lx]", (int)mm->context, page);
1555#endif
1556 local_irq_save(flags);
1557 page &= PAGE_MASK;
1558 pgdp = pgd_offset(mm, page);
1559 pmdp = pmd_offset(pgdp, page);
1560 ptep = pte_offset(pmdp, page);
1561
1562
1563
1564
1565
1566 if (!(pte_val(*ptep) & _PAGE_VALID))
1567 goto out;
1568
1569
1570
1571
1572
1573
1574
1575 if (mm->context != current->active_mm->context) {
1576
1577
1578
1579
1580 page = (KSEG0 + (page & (scache_size - 1)));
1581 blast_dcache16_page_indexed(page);
1582 blast_scache128_page_indexed(page);
1583 } else
1584 blast_scache128_page(page);
1585out:
1586 local_irq_restore(flags);
1587}
1588
1589static void r4k_flush_cache_page_s32d32i32(struct vm_area_struct *vma,
1590 unsigned long page)
1591{
1592 struct mm_struct *mm = vma->vm_mm;
1593 unsigned long flags;
1594 pgd_t *pgdp;
1595 pmd_t *pmdp;
1596 pte_t *ptep;
1597
1598
1599
1600
1601
1602 if (mm->context == 0)
1603 return;
1604
1605#ifdef DEBUG_CACHE
1606 printk("cpage[%d,%08lx]", (int)mm->context, page);
1607#endif
1608 local_irq_save(flags);
1609 page &= PAGE_MASK;
1610 pgdp = pgd_offset(mm, page);
1611 pmdp = pmd_offset(pgdp, page);
1612 ptep = pte_offset(pmdp, page);
1613
1614
1615
1616
1617
1618 if (!(pte_val(*ptep) & _PAGE_VALID))
1619 goto out;
1620
1621
1622
1623
1624
1625
1626
1627 if (mm->context != current->active_mm->context) {
1628
1629
1630
1631
1632 page = (KSEG0 + (page & (scache_size - 1)));
1633 blast_dcache32_page_indexed(page);
1634 blast_scache32_page_indexed(page);
1635 } else
1636 blast_scache32_page(page);
1637out:
1638 local_irq_restore(flags);
1639}
1640
1641static void r4k_flush_cache_page_s64d32i32(struct vm_area_struct *vma,
1642 unsigned long page)
1643{
1644 struct mm_struct *mm = vma->vm_mm;
1645 unsigned long flags;
1646 pgd_t *pgdp;
1647 pmd_t *pmdp;
1648 pte_t *ptep;
1649
1650
1651
1652
1653
1654 if (mm->context == 0)
1655 return;
1656
1657#ifdef DEBUG_CACHE
1658 printk("cpage[%d,%08lx]", (int)mm->context, page);
1659#endif
1660 local_irq_save(flags);
1661 page &= PAGE_MASK;
1662 pgdp = pgd_offset(mm, page);
1663 pmdp = pmd_offset(pgdp, page);
1664 ptep = pte_offset(pmdp, page);
1665
1666
1667
1668
1669
1670 if (!(pte_val(*ptep) & _PAGE_VALID))
1671 goto out;
1672
1673
1674
1675
1676
1677
1678
1679 if (mm->context != current->active_mm->context) {
1680
1681
1682
1683
1684 page = (KSEG0 + (page & (scache_size - 1)));
1685 blast_dcache32_page_indexed(page);
1686 blast_scache64_page_indexed(page);
1687 } else
1688 blast_scache64_page(page);
1689out:
1690 local_irq_restore(flags);
1691}
1692
1693static void r4k_flush_cache_page_s128d32i32(struct vm_area_struct *vma,
1694 unsigned long page)
1695{
1696 struct mm_struct *mm = vma->vm_mm;
1697 unsigned long flags;
1698 pgd_t *pgdp;
1699 pmd_t *pmdp;
1700 pte_t *ptep;
1701
1702
1703
1704
1705
1706 if (mm->context == 0)
1707 return;
1708
1709#ifdef DEBUG_CACHE
1710 printk("cpage[%d,%08lx]", (int)mm->context, page);
1711#endif
1712 local_irq_save(flags);
1713 page &= PAGE_MASK;
1714 pgdp = pgd_offset(mm, page);
1715 pmdp = pmd_offset(pgdp, page);
1716 ptep = pte_offset(pmdp, page);
1717
1718
1719
1720
1721
1722 if (!(pte_val(*ptep) & _PAGE_VALID))
1723 goto out;
1724
1725
1726
1727
1728
1729
1730
1731 if (mm->context != current->active_mm->context) {
1732
1733
1734
1735 page = (KSEG0 + (page & (scache_size - 1)));
1736 blast_dcache32_page_indexed(page);
1737 blast_scache128_page_indexed(page);
1738 } else
1739 blast_scache128_page(page);
1740out:
1741 local_irq_restore(flags);
1742}
1743
1744static void r4k_flush_cache_page_d16i16(struct vm_area_struct *vma,
1745 unsigned long page)
1746{
1747 struct mm_struct *mm = vma->vm_mm;
1748 unsigned long flags;
1749 pgd_t *pgdp;
1750 pmd_t *pmdp;
1751 pte_t *ptep;
1752
1753
1754
1755
1756
1757 if (mm->context == 0)
1758 return;
1759
1760#ifdef DEBUG_CACHE
1761 printk("cpage[%d,%08lx]", (int)mm->context, page);
1762#endif
1763 local_irq_save(flags);
1764 page &= PAGE_MASK;
1765 pgdp = pgd_offset(mm, page);
1766 pmdp = pmd_offset(pgdp, page);
1767 ptep = pte_offset(pmdp, page);
1768
1769
1770
1771
1772
1773 if (!(pte_val(*ptep) & _PAGE_VALID))
1774 goto out;
1775
1776
1777
1778
1779
1780
1781
1782 if (mm == current->active_mm) {
1783 blast_dcache16_page(page);
1784 } else {
1785
1786
1787
1788 page = (KSEG0 + (page & (dcache_size - 1)));
1789 blast_dcache16_page_indexed(page);
1790 }
1791out:
1792 local_irq_restore(flags);
1793}
1794
1795static void r4k_flush_cache_page_d32i32(struct vm_area_struct *vma,
1796 unsigned long page)
1797{
1798 struct mm_struct *mm = vma->vm_mm;
1799 unsigned long flags;
1800 pgd_t *pgdp;
1801 pmd_t *pmdp;
1802 pte_t *ptep;
1803
1804
1805
1806
1807
1808 if (mm->context == 0)
1809 return;
1810
1811#ifdef DEBUG_CACHE
1812 printk("cpage[%d,%08lx]", (int)mm->context, page);
1813#endif
1814 local_irq_save(flags);
1815 page &= PAGE_MASK;
1816 pgdp = pgd_offset(mm, page);
1817 pmdp = pmd_offset(pgdp, page);
1818 ptep = pte_offset(pmdp, page);
1819
1820
1821
1822
1823
1824 if (!(pte_val(*ptep) & _PAGE_PRESENT))
1825 goto out;
1826
1827
1828
1829
1830
1831
1832
1833 if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) {
1834 blast_dcache32_page(page);
1835 } else {
1836
1837
1838
1839
1840 page = (KSEG0 + (page & (dcache_size - 1)));
1841 blast_dcache32_page_indexed(page);
1842 }
1843out:
1844 local_irq_restore(flags);
1845}
1846
1847static void r4k_flush_cache_page_d32i32_r4600(struct vm_area_struct *vma,
1848 unsigned long page)
1849{
1850 struct mm_struct *mm = vma->vm_mm;
1851 unsigned long flags;
1852 pgd_t *pgdp;
1853 pmd_t *pmdp;
1854 pte_t *ptep;
1855
1856
1857
1858
1859
1860 if (mm->context == 0)
1861 return;
1862
1863#ifdef DEBUG_CACHE
1864 printk("cpage[%d,%08lx]", (int)mm->context, page);
1865#endif
1866 local_irq_save(flags);
1867 page &= PAGE_MASK;
1868 pgdp = pgd_offset(mm, page);
1869 pmdp = pmd_offset(pgdp, page);
1870 ptep = pte_offset(pmdp, page);
1871
1872
1873
1874
1875
1876 if (!(pte_val(*ptep) & _PAGE_PRESENT))
1877 goto out;
1878
1879
1880
1881
1882
1883
1884
1885 if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) {
1886 blast_dcache32_page(page);
1887 } else {
1888
1889
1890
1891 page = (KSEG0 + (page & (dcache_size - 1)));
1892 blast_dcache32_page_indexed(page);
1893 blast_dcache32_page_indexed(page ^ dcache_waybit);
1894 }
1895out:
1896 local_irq_restore(flags);
1897}
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908static void r4k_flush_page_to_ram_s16(struct page *page)
1909{
1910 blast_scache16_page((unsigned long)page_address(page));
1911}
1912
1913static void r4k_flush_page_to_ram_s32(struct page *page)
1914{
1915 blast_scache32_page((unsigned long)page_address(page));
1916}
1917
1918static void r4k_flush_page_to_ram_s64(struct page *page)
1919{
1920 blast_scache64_page((unsigned long)page_address(page));
1921}
1922
1923static void r4k_flush_page_to_ram_s128(struct page *page)
1924{
1925 blast_scache128_page((unsigned long)page_address(page));
1926}
1927
1928static void r4k_flush_page_to_ram_d16(struct page *page)
1929{
1930 blast_dcache16_page((unsigned long)page_address(page));
1931}
1932
1933static void r4k_flush_page_to_ram_d32(struct page *page)
1934{
1935 blast_dcache32_page((unsigned long)page_address(page));
1936}
1937
1938static void r4k_flush_page_to_ram_d32_r4600(struct page *page)
1939{
1940 unsigned long flags;
1941
1942 local_irq_save(flags);
1943 blast_dcache32_page((unsigned long)page_address(page));
1944 local_irq_restore(flags);
1945}
1946
1947static void
1948r4k_flush_icache_page_s(struct vm_area_struct *vma, struct page *page)
1949{
1950
1951
1952
1953}
1954
1955static void
1956r4k_flush_icache_range(unsigned long start, unsigned long end)
1957{
1958 flush_cache_all();
1959}
1960
1961
1962
1963
1964
1965
1966static void
1967r4k_flush_icache_page_p(struct vm_area_struct *vma, struct page *page)
1968{
1969 if (!(vma->vm_flags & VM_EXEC))
1970 return;
1971
1972 flush_cache_all();
1973}
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986static void
1987r4k_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size)
1988{
1989 unsigned long end, a;
1990 unsigned int flags;
1991
1992 if (size >= dcache_size) {
1993 flush_cache_all();
1994 } else {
1995
1996 local_irq_save(flags);
1997 *(volatile unsigned long *)KSEG1;
1998
1999 a = addr & ~(dc_lsize - 1);
2000 end = (addr + size) & ~(dc_lsize - 1);
2001 while (1) {
2002 flush_dcache_line(a);
2003 if (a == end) break;
2004 a += dc_lsize;
2005 }
2006 local_irq_restore(flags);
2007 }
2008 bc_wback_inv(addr, size);
2009}
2010
2011static void
2012r4k_dma_cache_wback_inv_sc(unsigned long addr, unsigned long size)
2013{
2014 unsigned long end, a;
2015
2016 if (size >= scache_size) {
2017 flush_cache_all();
2018 return;
2019 }
2020
2021 a = addr & ~(sc_lsize - 1);
2022 end = (addr + size) & ~(sc_lsize - 1);
2023 while (1) {
2024 flush_scache_line(a);
2025 if (a == end) break;
2026 a += sc_lsize;
2027 }
2028}
2029
2030static void
2031r4k_dma_cache_inv_pc(unsigned long addr, unsigned long size)
2032{
2033 unsigned long end, a;
2034 unsigned int flags;
2035
2036 if (size >= dcache_size) {
2037 flush_cache_all();
2038 } else {
2039
2040 local_irq_save(flags);
2041 *(volatile unsigned long *)KSEG1;
2042
2043 a = addr & ~(dc_lsize - 1);
2044 end = (addr + size) & ~(dc_lsize - 1);
2045 while (1) {
2046 flush_dcache_line(a);
2047 if (a == end) break;
2048 a += dc_lsize;
2049 }
2050 local_irq_restore(flags);
2051 }
2052
2053 bc_inv(addr, size);
2054}
2055
2056static void
2057r4k_dma_cache_inv_sc(unsigned long addr, unsigned long size)
2058{
2059 unsigned long end, a;
2060
2061 if (size >= scache_size) {
2062 flush_cache_all();
2063 return;
2064 }
2065
2066 a = addr & ~(sc_lsize - 1);
2067 end = (addr + size) & ~(sc_lsize - 1);
2068 while (1) {
2069 flush_scache_line(a);
2070 if (a == end) break;
2071 a += sc_lsize;
2072 }
2073}
2074
2075static void
2076r4k_dma_cache_wback(unsigned long addr, unsigned long size)
2077{
2078 panic("r4k_dma_cache called - should not happen.\n");
2079}
2080
2081
2082
2083
2084
2085
2086static void r4k_flush_cache_sigtramp(unsigned long addr)
2087{
2088 __asm__ __volatile__("nop;nop;nop;nop");
2089 protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
2090 protected_flush_icache_line(addr & ~(ic_lsize - 1));
2091}
2092
2093static void r4600v20k_flush_cache_sigtramp(unsigned long addr)
2094{
2095 unsigned int flags;
2096
2097 local_irq_save(flags);
2098
2099
2100 *(volatile unsigned int *)KSEG1;
2101
2102 protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
2103 protected_flush_icache_line(addr & ~(ic_lsize - 1));
2104
2105 local_irq_restore(flags);
2106}
2107
2108#undef DEBUG_TLB
2109#undef DEBUG_TLBUPDATE
2110
2111void flush_tlb_all(void)
2112{
2113 unsigned long flags;
2114 unsigned long old_ctx;
2115 int entry;
2116
2117#ifdef DEBUG_TLB
2118 printk("[tlball]");
2119#endif
2120
2121 local_irq_save(flags);
2122
2123 old_ctx = (get_entryhi() & 0xff);
2124 set_entryhi(KSEG0);
2125 set_entrylo0(0);
2126 set_entrylo1(0);
2127 BARRIER;
2128
2129 entry = get_wired();
2130
2131
2132 while(entry < mips_cpu.tlbsize) {
2133 set_index(entry);
2134 BARRIER;
2135 tlb_write_indexed();
2136 BARRIER;
2137 entry++;
2138 }
2139 BARRIER;
2140 set_entryhi(old_ctx);
2141 local_irq_restore(flags);
2142}
2143
2144void flush_tlb_mm(struct mm_struct *mm)
2145{
2146 if (mm->context != 0) {
2147 unsigned long flags;
2148
2149#ifdef DEBUG_TLB
2150 printk("[tlbmm<%d>]", mm->context);
2151#endif
2152 local_irq_save(flags);
2153 get_new_mmu_context(mm, asid_cache);
2154 if (mm == current->active_mm)
2155 set_entryhi(mm->context & 0xff);
2156 local_irq_restore(flags);
2157 }
2158}
2159
2160void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
2161 unsigned long end)
2162{
2163 struct mm_struct *mm = vma->vm_mm;
2164
2165 if (mm->context != 0) {
2166 unsigned long flags;
2167 int size;
2168
2169#ifdef DEBUG_TLB
2170 printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff),
2171 start, end);
2172#endif
2173 local_irq_save(flags);
2174 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
2175 size = (size + 1) >> 1;
2176 if(size <= mips_cpu.tlbsize/2) {
2177 int oldpid = (get_entryhi() & 0xff);
2178 int newpid = (mm->context & 0xff);
2179
2180 start &= (PAGE_MASK << 1);
2181 end += ((PAGE_SIZE << 1) - 1);
2182 end &= (PAGE_MASK << 1);
2183 while(start < end) {
2184 int idx;
2185
2186 set_entryhi(start | newpid);
2187 start += (PAGE_SIZE << 1);
2188 BARRIER;
2189 tlb_probe();
2190 BARRIER;
2191 idx = get_index();
2192 set_entrylo0(0);
2193 set_entrylo1(0);
2194 set_entryhi(KSEG0);
2195 BARRIER;
2196 if(idx < 0)
2197 continue;
2198 tlb_write_indexed();
2199 BARRIER;
2200 }
2201 set_entryhi(oldpid);
2202 } else {
2203 get_new_mmu_context(mm, asid_cache);
2204 if (mm == current->active_mm)
2205 set_entryhi(mm->context & 0xff);
2206 }
2207 local_irq_restore(flags);
2208 }
2209}
2210
2211void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
2212{
2213 if (vma->vm_mm->context != 0) {
2214 unsigned long flags;
2215 int oldpid, newpid, idx;
2216
2217#ifdef DEBUG_TLB
2218 printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page);
2219#endif
2220 newpid = (vma->vm_mm->context & 0xff);
2221 page &= (PAGE_MASK << 1);
2222 local_irq_save(flags);
2223 oldpid = (get_entryhi() & 0xff);
2224 set_entryhi(page | newpid);
2225 BARRIER;
2226 tlb_probe();
2227 BARRIER;
2228 idx = get_index();
2229 set_entrylo0(0);
2230 set_entrylo1(0);
2231 set_entryhi(KSEG0);
2232 if(idx < 0)
2233 goto finish;
2234 BARRIER;
2235 tlb_write_indexed();
2236
2237 finish:
2238 BARRIER;
2239 set_entryhi(oldpid);
2240 local_irq_restore(flags);
2241 }
2242}
2243
2244void pgd_init(unsigned long page)
2245{
2246 unsigned long *p = (unsigned long *) page;
2247 int i;
2248
2249 for(i = 0; i < USER_PTRS_PER_PGD; i+=8) {
2250 p[i + 0] = (unsigned long) invalid_pte_table;
2251 p[i + 1] = (unsigned long) invalid_pte_table;
2252 p[i + 2] = (unsigned long) invalid_pte_table;
2253 p[i + 3] = (unsigned long) invalid_pte_table;
2254 p[i + 4] = (unsigned long) invalid_pte_table;
2255 p[i + 5] = (unsigned long) invalid_pte_table;
2256 p[i + 6] = (unsigned long) invalid_pte_table;
2257 p[i + 7] = (unsigned long) invalid_pte_table;
2258 }
2259}
2260
2261
2262
2263
2264
2265void update_mmu_cache(struct vm_area_struct * vma,
2266 unsigned long address, pte_t pte)
2267{
2268 unsigned long flags;
2269 pgd_t *pgdp;
2270 pmd_t *pmdp;
2271 pte_t *ptep;
2272 int idx, pid;
2273
2274
2275
2276
2277 if (current->active_mm != vma->vm_mm)
2278 return;
2279
2280 pid = get_entryhi() & 0xff;
2281
2282#ifdef DEBUG_TLB
2283 if((pid != (vma->vm_mm->context & 0xff)) || (vma->vm_mm->context == 0)) {
2284 printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n",
2285 (int) (vma->vm_mm->context & 0xff), pid);
2286 }
2287#endif
2288
2289 local_irq_save(flags);
2290 address &= (PAGE_MASK << 1);
2291 set_entryhi(address | (pid));
2292 pgdp = pgd_offset(vma->vm_mm, address);
2293 BARRIER;
2294 tlb_probe();
2295 BARRIER;
2296 pmdp = pmd_offset(pgdp, address);
2297 idx = get_index();
2298 ptep = pte_offset(pmdp, address);
2299 BARRIER;
2300 set_entrylo0(pte_val(*ptep++) >> 6);
2301 set_entrylo1(pte_val(*ptep) >> 6);
2302 set_entryhi(address | (pid));
2303 BARRIER;
2304 if(idx < 0) {
2305 tlb_write_random();
2306 } else {
2307 tlb_write_indexed();
2308 }
2309 BARRIER;
2310 set_entryhi(pid);
2311 BARRIER;
2312 local_irq_restore(flags);
2313}
2314
2315#if 0
2316static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
2317 unsigned long address, pte_t pte)
2318{
2319 unsigned long flags;
2320 pgd_t *pgdp;
2321 pmd_t *pmdp;
2322 pte_t *ptep;
2323 int idx;
2324
2325 local_irq_save(flags);
2326 address &= (PAGE_MASK << 1);
2327 set_entryhi(address | (get_entryhi() & 0xff));
2328 pgdp = pgd_offset(vma->vm_mm, address);
2329 tlb_probe();
2330 pmdp = pmd_offset(pgdp, address);
2331 idx = get_index();
2332 ptep = pte_offset(pmdp, address);
2333 set_entrylo0(pte_val(*ptep++) >> 6);
2334 set_entrylo1(pte_val(*ptep) >> 6);
2335 BARRIER;
2336 if(idx < 0)
2337 tlb_write_random();
2338 else
2339 tlb_write_indexed();
2340 BARRIER;
2341 local_irq_restore(flags);
2342}
2343#endif
2344
2345void show_regs(struct pt_regs * regs)
2346{
2347
2348 printk("$0 : %08lx %08lx %08lx %08lx\n",
2349 0UL, regs->regs[1], regs->regs[2], regs->regs[3]);
2350 printk("$4 : %08lx %08lx %08lx %08lx\n",
2351 regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
2352 printk("$8 : %08lx %08lx %08lx %08lx\n",
2353 regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]);
2354 printk("$12: %08lx %08lx %08lx %08lx\n",
2355 regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]);
2356 printk("$16: %08lx %08lx %08lx %08lx\n",
2357 regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]);
2358 printk("$20: %08lx %08lx %08lx %08lx\n",
2359 regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]);
2360 printk("$24: %08lx %08lx\n",
2361 regs->regs[24], regs->regs[25]);
2362 printk("$28: %08lx %08lx %08lx %08lx\n",
2363 regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]);
2364
2365
2366 printk("epc : %08lx %s\nStatus: %08lx\nCause : %08lx\n",
2367 regs->cp0_epc, print_tainted(), regs->cp0_status, regs->cp0_cause);
2368}
2369
2370void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
2371 unsigned long entryhi, unsigned long pagemask)
2372{
2373 unsigned long flags;
2374 unsigned long wired;
2375 unsigned long old_pagemask;
2376 unsigned long old_ctx;
2377
2378 local_irq_save(flags);
2379
2380 old_ctx = (get_entryhi() & 0xff);
2381 old_pagemask = get_pagemask();
2382 wired = get_wired();
2383 set_wired (wired + 1);
2384 set_index (wired);
2385 BARRIER;
2386 set_pagemask (pagemask);
2387 set_entryhi(entryhi);
2388 set_entrylo0(entrylo0);
2389 set_entrylo1(entrylo1);
2390 BARRIER;
2391 tlb_write_indexed();
2392 BARRIER;
2393
2394 set_entryhi(old_ctx);
2395 BARRIER;
2396 set_pagemask (old_pagemask);
2397 flush_tlb_all();
2398 local_irq_restore(flags);
2399}
2400
2401
2402static void __init probe_icache(unsigned long config)
2403{
2404 switch (mips_cpu.cputype) {
2405 case CPU_VR41XX:
2406 icache_size = 1 << (10 + ((config >> 9) & 7));
2407 break;
2408 default:
2409 icache_size = 1 << (12 + ((config >> 9) & 7));
2410 break;
2411 }
2412 ic_lsize = 16 << ((config >> 5) & 1);
2413
2414 printk("Primary instruction cache %dkb, linesize %d bytes.\n",
2415 icache_size >> 10, ic_lsize);
2416}
2417
2418static void __init probe_dcache(unsigned long config)
2419{
2420 switch (mips_cpu.cputype) {
2421 case CPU_VR41XX:
2422 dcache_size = 1 << (10 + ((config >> 6) & 7));
2423 break;
2424 default:
2425 dcache_size = 1 << (12 + ((config >> 6) & 7));
2426 break;
2427 }
2428 dc_lsize = 16 << ((config >> 4) & 1);
2429
2430 printk("Primary data cache %dkb, linesize %d bytes.\n",
2431 dcache_size >> 10, dc_lsize);
2432}
2433
2434
2435
2436
2437
2438
2439
2440static int __init probe_scache(unsigned long config)
2441{
2442 extern unsigned long stext;
2443 unsigned long flags, addr, begin, end, pow2;
2444 int tmp;
2445
2446 tmp = ((config >> 17) & 1);
2447 if(tmp)
2448 return 0;
2449 tmp = ((config >> 22) & 3);
2450 switch(tmp) {
2451 case 0:
2452 sc_lsize = 16;
2453 break;
2454 case 1:
2455 sc_lsize = 32;
2456 break;
2457 case 2:
2458 sc_lsize = 64;
2459 break;
2460 case 3:
2461 sc_lsize = 128;
2462 break;
2463 }
2464
2465 begin = (unsigned long) &stext;
2466 begin &= ~((4 * 1024 * 1024) - 1);
2467 end = begin + (4 * 1024 * 1024);
2468
2469
2470
2471
2472 local_irq_save(flags);
2473
2474
2475 pow2 = (64 * 1024);
2476 for(addr = begin; addr < end; addr = (begin + pow2)) {
2477 unsigned long *p = (unsigned long *) addr;
2478 __asm__ __volatile__("nop" : : "r" (*p));
2479 pow2 <<= 1;
2480 }
2481
2482
2483 set_taglo(0);
2484 set_taghi(0);
2485 __asm__ __volatile__("nop; nop; nop; nop;");
2486 __asm__ __volatile__("\n\t.set noreorder\n\t"
2487 ".set mips3\n\t"
2488 "cache 8, (%0)\n\t"
2489 ".set mips0\n\t"
2490 ".set reorder\n\t" : : "r" (begin));
2491 __asm__ __volatile__("\n\t.set noreorder\n\t"
2492 ".set mips3\n\t"
2493 "cache 9, (%0)\n\t"
2494 ".set mips0\n\t"
2495 ".set reorder\n\t" : : "r" (begin));
2496 __asm__ __volatile__("\n\t.set noreorder\n\t"
2497 ".set mips3\n\t"
2498 "cache 11, (%0)\n\t"
2499 ".set mips0\n\t"
2500 ".set reorder\n\t" : : "r" (begin));
2501
2502
2503 pow2 = (128 * 1024);
2504 tmp = 0;
2505 for(addr = (begin + (128 * 1024)); addr < (end); addr = (begin + pow2)) {
2506 __asm__ __volatile__("\n\t.set noreorder\n\t"
2507 ".set mips3\n\t"
2508 "cache 7, (%0)\n\t"
2509 ".set mips0\n\t"
2510 ".set reorder\n\t" : : "r" (addr));
2511 __asm__ __volatile__("nop; nop; nop; nop;");
2512 if(!get_taglo())
2513 break;
2514 pow2 <<= 1;
2515 }
2516 local_irq_restore(flags);
2517 addr -= begin;
2518 printk("Secondary cache sized at %dK linesize %d bytes.\n",
2519 (int) (addr >> 10), sc_lsize);
2520 scache_size = addr;
2521 return 1;
2522}
2523
2524static void __init setup_noscache_funcs(void)
2525{
2526 unsigned int prid;
2527
2528 switch(dc_lsize) {
2529 case 16:
2530 _clear_page = r4k_clear_page_d16;
2531 _copy_page = r4k_copy_page_d16;
2532 _flush_cache_all = r4k_flush_cache_all_d16i16;
2533 _flush_cache_mm = r4k_flush_cache_mm_d16i16;
2534 _flush_cache_range = r4k_flush_cache_range_d16i16;
2535 _flush_cache_page = r4k_flush_cache_page_d16i16;
2536 _flush_page_to_ram = r4k_flush_page_to_ram_d16;
2537 break;
2538 case 32:
2539 prid = read_32bit_cp0_register(CP0_PRID) & 0xfff0;
2540 if (prid == 0x2010) {
2541 _clear_page = r4k_clear_page_r4600_v1;
2542 _copy_page = r4k_copy_page_r4600_v1;
2543 _flush_page_to_ram = r4k_flush_page_to_ram_d32_r4600;
2544 } else if (prid == 0x2020) {
2545 _clear_page = r4k_clear_page_r4600_v2;
2546 _copy_page = r4k_copy_page_r4600_v2;
2547 _flush_page_to_ram = r4k_flush_page_to_ram_d32;
2548 } else {
2549 _clear_page = r4k_clear_page_d32;
2550 _copy_page = r4k_copy_page_d32;
2551 _flush_page_to_ram = r4k_flush_page_to_ram_d32;
2552 }
2553 _flush_cache_all = r4k_flush_cache_all_d32i32;
2554 _flush_cache_mm = r4k_flush_cache_mm_d32i32;
2555 _flush_cache_range = r4k_flush_cache_range_d32i32;
2556 _flush_cache_page = r4k_flush_cache_page_d32i32;
2557 break;
2558 }
2559 ___flush_cache_all = _flush_cache_all;
2560
2561 _flush_icache_page = r4k_flush_icache_page_p;
2562
2563 _dma_cache_wback_inv = r4k_dma_cache_wback_inv_pc;
2564 _dma_cache_wback = r4k_dma_cache_wback;
2565 _dma_cache_inv = r4k_dma_cache_inv_pc;
2566}
2567
2568static void __init setup_scache_funcs(void)
2569{
2570 switch(sc_lsize) {
2571 case 16:
2572 switch(dc_lsize) {
2573 case 16:
2574 _flush_cache_all = r4k_flush_cache_all_s16d16i16;
2575 _flush_cache_mm = r4k_flush_cache_mm_s16d16i16;
2576 _flush_cache_range = r4k_flush_cache_range_s16d16i16;
2577 _flush_cache_page = r4k_flush_cache_page_s16d16i16;
2578 break;
2579 case 32:
2580 panic("Invalid cache configuration detected");
2581 };
2582 _flush_page_to_ram = r4k_flush_page_to_ram_s16;
2583 _clear_page = r4k_clear_page_s16;
2584 _copy_page = r4k_copy_page_s16;
2585 break;
2586 case 32:
2587 switch(dc_lsize) {
2588 case 16:
2589 _flush_cache_all = r4k_flush_cache_all_s32d16i16;
2590 _flush_cache_mm = r4k_flush_cache_mm_s32d16i16;
2591 _flush_cache_range = r4k_flush_cache_range_s32d16i16;
2592 _flush_cache_page = r4k_flush_cache_page_s32d16i16;
2593 break;
2594 case 32:
2595 _flush_cache_all = r4k_flush_cache_all_s32d32i32;
2596 _flush_cache_mm = r4k_flush_cache_mm_s32d32i32;
2597 _flush_cache_range = r4k_flush_cache_range_s32d32i32;
2598 _flush_cache_page = r4k_flush_cache_page_s32d32i32;
2599 break;
2600 };
2601 _flush_page_to_ram = r4k_flush_page_to_ram_s32;
2602 _clear_page = r4k_clear_page_s32;
2603 _copy_page = r4k_copy_page_s32;
2604 break;
2605 case 64:
2606 switch(dc_lsize) {
2607 case 16:
2608 _flush_cache_all = r4k_flush_cache_all_s64d16i16;
2609 _flush_cache_mm = r4k_flush_cache_mm_s64d16i16;
2610 _flush_cache_range = r4k_flush_cache_range_s64d16i16;
2611 _flush_cache_page = r4k_flush_cache_page_s64d16i16;
2612 break;
2613 case 32:
2614 _flush_cache_all = r4k_flush_cache_all_s64d32i32;
2615 _flush_cache_mm = r4k_flush_cache_mm_s64d32i32;
2616 _flush_cache_range = r4k_flush_cache_range_s64d32i32;
2617 _flush_cache_page = r4k_flush_cache_page_s64d32i32;
2618 break;
2619 };
2620 _flush_page_to_ram = r4k_flush_page_to_ram_s64;
2621 _clear_page = r4k_clear_page_s64;
2622 _copy_page = r4k_copy_page_s64;
2623 break;
2624 case 128:
2625 switch(dc_lsize) {
2626 case 16:
2627 _flush_cache_all = r4k_flush_cache_all_s128d16i16;
2628 _flush_cache_mm = r4k_flush_cache_mm_s128d16i16;
2629 _flush_cache_range = r4k_flush_cache_range_s128d16i16;
2630 _flush_cache_page = r4k_flush_cache_page_s128d16i16;
2631 break;
2632 case 32:
2633 _flush_cache_all = r4k_flush_cache_all_s128d32i32;
2634 _flush_cache_mm = r4k_flush_cache_mm_s128d32i32;
2635 _flush_cache_range = r4k_flush_cache_range_s128d32i32;
2636 _flush_cache_page = r4k_flush_cache_page_s128d32i32;
2637 break;
2638 };
2639 _flush_page_to_ram = r4k_flush_page_to_ram_s128;
2640 _clear_page = r4k_clear_page_s128;
2641 _copy_page = r4k_copy_page_s128;
2642 break;
2643 }
2644 ___flush_cache_all = _flush_cache_all;
2645 _flush_icache_page = r4k_flush_icache_page_s;
2646 _dma_cache_wback_inv = r4k_dma_cache_wback_inv_sc;
2647 _dma_cache_wback = r4k_dma_cache_wback;
2648 _dma_cache_inv = r4k_dma_cache_inv_sc;
2649}
2650
2651typedef int (*probe_func_t)(unsigned long);
2652
2653static inline void __init setup_scache(unsigned int config)
2654{
2655 probe_func_t probe_scache_kseg1;
2656 int sc_present = 0;
2657
2658
2659 probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
2660 sc_present = probe_scache_kseg1(config);
2661
2662 if (sc_present) {
2663 setup_scache_funcs();
2664 return;
2665 }
2666
2667 setup_noscache_funcs();
2668}
2669
2670void __init ld_mmu_r4xx0(void)
2671{
2672 unsigned long config = read_32bit_cp0_register(CP0_CONFIG);
2673
2674 printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID));
2675
2676#ifdef CONFIG_MIPS_UNCACHED
2677 change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
2678#else
2679 change_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NONCOHERENT);
2680#endif
2681
2682 probe_icache(config);
2683 probe_dcache(config);
2684 setup_scache(config);
2685
2686 switch(mips_cpu.cputype) {
2687 case CPU_R4600:
2688 case CPU_R4700:
2689 case CPU_R5000:
2690 case CPU_NEVADA:
2691 _flush_cache_page = r4k_flush_cache_page_d32i32_r4600;
2692 }
2693
2694 _flush_cache_sigtramp = r4k_flush_cache_sigtramp;
2695 _flush_icache_range = r4k_flush_icache_range;
2696 if ((read_32bit_cp0_register(CP0_PRID) & 0xfff0) == 0x2020) {
2697 _flush_cache_sigtramp = r4600v20k_flush_cache_sigtramp;
2698 }
2699
2700 __flush_cache_all();
2701 write_32bit_cp0_register(CP0_WIRED, 0);
2702
2703
2704
2705
2706
2707
2708
2709
2710 set_pagemask(PM_4K);
2711 flush_tlb_all();
2712}
2713