File: /usr/src/linux/arch/mips/mm/r2300.c
1 /*
2 * r2300.c: R2000 and R3000 specific mmu/cache code.
3 *
4 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
5 *
6 * with a lot of changes to make this thing work for R3000s
7 * Tx39XX R4k style caches added. HK
8 * Copyright (C) 1998, 1999, 2000 Harald Koerfgen
9 * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
10 */
11 #include <linux/init.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/mm.h>
15
16 #include <asm/page.h>
17 #include <asm/pgtable.h>
18 #include <asm/mmu_context.h>
19 #include <asm/system.h>
20 #include <asm/isadep.h>
21 #include <asm/io.h>
22 #include <asm/wbflush.h>
23 #include <asm/bootinfo.h>
24 #include <asm/cpu.h>
25
26 /*
27 * According to the paper written by D. Miller about Linux cache & TLB
28 * flush implementation, DMA/Driver coherence should be done at the
29 * driver layer. Thus, normally, we don't need flush dcache for R3000.
30 * Define this if driver does not handle cache consistency during DMA ops.
31 */
32
33 /* For R3000 cores with R4000 style caches */
34 static unsigned long icache_size, dcache_size; /* Size in bytes */
35 static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */
36 static unsigned long scache_size;
37
38 #include <asm/cacheops.h>
39 #include <asm/r4kcache.h>
40
41 #undef DEBUG_TLB
42 #undef DEBUG_CACHE
43
44 /* page functions */
45 void r3k_clear_page(void * page)
46 {
47 __asm__ __volatile__(
48 ".set\tnoreorder\n\t"
49 ".set\tnoat\n\t"
50 "addiu\t$1,%0,%2\n"
51 "1:\tsw\t$0,(%0)\n\t"
52 "sw\t$0,4(%0)\n\t"
53 "sw\t$0,8(%0)\n\t"
54 "sw\t$0,12(%0)\n\t"
55 "addiu\t%0,32\n\t"
56 "sw\t$0,-16(%0)\n\t"
57 "sw\t$0,-12(%0)\n\t"
58 "sw\t$0,-8(%0)\n\t"
59 "bne\t$1,%0,1b\n\t"
60 "sw\t$0,-4(%0)\n\t"
61 ".set\tat\n\t"
62 ".set\treorder"
63 :"=r" (page)
64 :"0" (page),
65 "I" (PAGE_SIZE)
66 :"$1","memory");
67 }
68
69 static void r3k_copy_page(void * to, void * from)
70 {
71 unsigned long dummy1, dummy2;
72 unsigned long reg1, reg2, reg3, reg4;
73
74 __asm__ __volatile__(
75 ".set\tnoreorder\n\t"
76 ".set\tnoat\n\t"
77 "addiu\t$1,%0,%8\n"
78 "1:\tlw\t%2,(%1)\n\t"
79 "lw\t%3,4(%1)\n\t"
80 "lw\t%4,8(%1)\n\t"
81 "lw\t%5,12(%1)\n\t"
82 "sw\t%2,(%0)\n\t"
83 "sw\t%3,4(%0)\n\t"
84 "sw\t%4,8(%0)\n\t"
85 "sw\t%5,12(%0)\n\t"
86 "lw\t%2,16(%1)\n\t"
87 "lw\t%3,20(%1)\n\t"
88 "lw\t%4,24(%1)\n\t"
89 "lw\t%5,28(%1)\n\t"
90 "sw\t%2,16(%0)\n\t"
91 "sw\t%3,20(%0)\n\t"
92 "sw\t%4,24(%0)\n\t"
93 "sw\t%5,28(%0)\n\t"
94 "addiu\t%0,64\n\t"
95 "addiu\t%1,64\n\t"
96 "lw\t%2,-32(%1)\n\t"
97 "lw\t%3,-28(%1)\n\t"
98 "lw\t%4,-24(%1)\n\t"
99 "lw\t%5,-20(%1)\n\t"
100 "sw\t%2,-32(%0)\n\t"
101 "sw\t%3,-28(%0)\n\t"
102 "sw\t%4,-24(%0)\n\t"
103 "sw\t%5,-20(%0)\n\t"
104 "lw\t%2,-16(%1)\n\t"
105 "lw\t%3,-12(%1)\n\t"
106 "lw\t%4,-8(%1)\n\t"
107 "lw\t%5,-4(%1)\n\t"
108 "sw\t%2,-16(%0)\n\t"
109 "sw\t%3,-12(%0)\n\t"
110 "sw\t%4,-8(%0)\n\t"
111 "bne\t$1,%0,1b\n\t"
112 "sw\t%5,-4(%0)\n\t"
113 ".set\tat\n\t"
114 ".set\treorder"
115 :"=r" (dummy1), "=r" (dummy2),
116 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
117 :"0" (to), "1" (from),
118 "I" (PAGE_SIZE));
119 }
120
121 unsigned long __init r3k_cache_size(unsigned long ca_flags)
122 {
123 unsigned long flags, status, dummy, size;
124 volatile unsigned long *p;
125
126 p = (volatile unsigned long *) KSEG0;
127
128 flags = read_32bit_cp0_register(CP0_STATUS);
129
130 /* isolate cache space */
131 write_32bit_cp0_register(CP0_STATUS, (ca_flags|flags)&~ST0_IEC);
132
133 *p = 0xa5a55a5a;
134 dummy = *p;
135 status = read_32bit_cp0_register(CP0_STATUS);
136
137 if (dummy != 0xa5a55a5a || (status & ST0_CM)) {
138 size = 0;
139 } else {
140 for (size = 128; size <= 0x40000; size <<= 1)
141 *(p + size) = 0;
142 *p = -1;
143 for (size = 128;
144 (size <= 0x40000) && (*(p + size) == 0);
145 size <<= 1)
146 ;
147 if (size > 0x40000)
148 size = 0;
149 }
150
151 write_32bit_cp0_register(CP0_STATUS, flags);
152
153 return size * sizeof(*p);
154 }
155
156 unsigned long __init r3k_cache_lsize(unsigned long ca_flags)
157 {
158 unsigned long flags, status, lsize, i, j;
159 volatile unsigned long *p;
160
161 p = (volatile unsigned long *) KSEG0;
162
163 flags = read_32bit_cp0_register(CP0_STATUS);
164
165 /* isolate cache space */
166 write_32bit_cp0_register(CP0_STATUS, (ca_flags|flags)&~ST0_IEC);
167
168 for (i = 0; i < 128; i++)
169 *(p + i) = 0;
170 *(volatile unsigned char *)p = 0;
171 for (lsize = 1; lsize < 128; lsize <<= 1) {
172 *(p + lsize);
173 status = read_32bit_cp0_register(CP0_STATUS);
174 if (!(status & ST0_CM))
175 break;
176 }
177 for (i = 0; i < 128; i += lsize)
178 *(volatile unsigned char *)(p + i) = 0;
179
180 write_32bit_cp0_register(CP0_STATUS, flags);
181
182 return lsize * sizeof(*p);
183 }
184
185 static void __init r3k_probe_cache(void)
186 {
187 dcache_size = r3k_cache_size(ST0_ISC);
188 if (dcache_size)
189 dcache_lsize = r3k_cache_lsize(ST0_ISC);
190
191
192 icache_size = r3k_cache_size(ST0_ISC|ST0_SWC);
193 if (icache_size)
194 icache_lsize = r3k_cache_lsize(ST0_ISC|ST0_SWC);
195 }
196
197 static void r3k_flush_icache_range(unsigned long start, unsigned long end)
198 {
199 unsigned long size, i, flags;
200 volatile unsigned char *p = (char *)start;
201
202 size = end - start;
203 if (size > icache_size)
204 size = icache_size;
205
206 flags = read_32bit_cp0_register(CP0_STATUS);
207
208 /* isolate cache space */
209 write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|ST0_SWC|flags)&~ST0_IEC);
210
211 for (i = 0; i < size; i += 0x080) {
212 asm ( "sb\t$0,0x000(%0)\n\t"
213 "sb\t$0,0x004(%0)\n\t"
214 "sb\t$0,0x008(%0)\n\t"
215 "sb\t$0,0x00c(%0)\n\t"
216 "sb\t$0,0x010(%0)\n\t"
217 "sb\t$0,0x014(%0)\n\t"
218 "sb\t$0,0x018(%0)\n\t"
219 "sb\t$0,0x01c(%0)\n\t"
220 "sb\t$0,0x020(%0)\n\t"
221 "sb\t$0,0x024(%0)\n\t"
222 "sb\t$0,0x028(%0)\n\t"
223 "sb\t$0,0x02c(%0)\n\t"
224 "sb\t$0,0x030(%0)\n\t"
225 "sb\t$0,0x034(%0)\n\t"
226 "sb\t$0,0x038(%0)\n\t"
227 "sb\t$0,0x03c(%0)\n\t"
228 "sb\t$0,0x040(%0)\n\t"
229 "sb\t$0,0x044(%0)\n\t"
230 "sb\t$0,0x048(%0)\n\t"
231 "sb\t$0,0x04c(%0)\n\t"
232 "sb\t$0,0x050(%0)\n\t"
233 "sb\t$0,0x054(%0)\n\t"
234 "sb\t$0,0x058(%0)\n\t"
235 "sb\t$0,0x05c(%0)\n\t"
236 "sb\t$0,0x060(%0)\n\t"
237 "sb\t$0,0x064(%0)\n\t"
238 "sb\t$0,0x068(%0)\n\t"
239 "sb\t$0,0x06c(%0)\n\t"
240 "sb\t$0,0x070(%0)\n\t"
241 "sb\t$0,0x074(%0)\n\t"
242 "sb\t$0,0x078(%0)\n\t"
243 "sb\t$0,0x07c(%0)\n\t"
244 : : "r" (p) );
245 p += 0x080;
246 }
247
248 write_32bit_cp0_register(CP0_STATUS,flags);
249 }
250
251 static void r3k_flush_dcache_range(unsigned long start, unsigned long end)
252 {
253 unsigned long size, i, flags;
254 volatile unsigned char *p = (char *)start;
255
256 size = end - start;
257 if (size > dcache_size)
258 size = dcache_size;
259
260 flags = read_32bit_cp0_register(CP0_STATUS);
261
262 /* isolate cache space */
263 write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|flags)&~ST0_IEC);
264
265 for (i = 0; i < size; i += 0x080) {
266 asm ( "sb\t$0,0x000(%0)\n\t"
267 "sb\t$0,0x004(%0)\n\t"
268 "sb\t$0,0x008(%0)\n\t"
269 "sb\t$0,0x00c(%0)\n\t"
270 "sb\t$0,0x010(%0)\n\t"
271 "sb\t$0,0x014(%0)\n\t"
272 "sb\t$0,0x018(%0)\n\t"
273 "sb\t$0,0x01c(%0)\n\t"
274 "sb\t$0,0x020(%0)\n\t"
275 "sb\t$0,0x024(%0)\n\t"
276 "sb\t$0,0x028(%0)\n\t"
277 "sb\t$0,0x02c(%0)\n\t"
278 "sb\t$0,0x030(%0)\n\t"
279 "sb\t$0,0x034(%0)\n\t"
280 "sb\t$0,0x038(%0)\n\t"
281 "sb\t$0,0x03c(%0)\n\t"
282 "sb\t$0,0x040(%0)\n\t"
283 "sb\t$0,0x044(%0)\n\t"
284 "sb\t$0,0x048(%0)\n\t"
285 "sb\t$0,0x04c(%0)\n\t"
286 "sb\t$0,0x050(%0)\n\t"
287 "sb\t$0,0x054(%0)\n\t"
288 "sb\t$0,0x058(%0)\n\t"
289 "sb\t$0,0x05c(%0)\n\t"
290 "sb\t$0,0x060(%0)\n\t"
291 "sb\t$0,0x064(%0)\n\t"
292 "sb\t$0,0x068(%0)\n\t"
293 "sb\t$0,0x06c(%0)\n\t"
294 "sb\t$0,0x070(%0)\n\t"
295 "sb\t$0,0x074(%0)\n\t"
296 "sb\t$0,0x078(%0)\n\t"
297 "sb\t$0,0x07c(%0)\n\t"
298 : : "r" (p) );
299 p += 0x080;
300 }
301
302 write_32bit_cp0_register(CP0_STATUS,flags);
303 }
304
305 static inline unsigned long get_phys_page (unsigned long addr,
306 struct mm_struct *mm)
307 {
308 pgd_t *pgd;
309 pmd_t *pmd;
310 pte_t *pte;
311 unsigned long physpage;
312
313 pgd = pgd_offset(mm, addr);
314 pmd = pmd_offset(pgd, addr);
315 pte = pte_offset(pmd, addr);
316
317 if ((physpage = pte_val(*pte)) & _PAGE_VALID)
318 return KSEG0ADDR(physpage & PAGE_MASK);
319
320 return 0;
321 }
322
323 static inline void r3k_flush_cache_all(void)
324 {
325 r3k_flush_icache_range(KSEG0, KSEG0 + icache_size);
326 }
327
328 static void r3k_flush_cache_mm(struct mm_struct *mm)
329 {
330 if (mm->context != 0) {
331
332 #ifdef DEBUG_CACHE
333 printk("cmm[%d]", (int)mm->context);
334 #endif
335 r3k_flush_cache_all();
336 }
337 }
338
339 static void r3k_flush_cache_range(struct mm_struct *mm, unsigned long start,
340 unsigned long end)
341 {
342 struct vm_area_struct *vma;
343
344 if (mm->context == 0)
345 return;
346
347 start &= PAGE_MASK;
348 #ifdef DEBUG_CACHE
349 printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
350 #endif
351 vma = find_vma(mm, start);
352 if (!vma)
353 return;
354
355 if (mm->context != current->active_mm->context) {
356 flush_cache_all();
357 } else {
358 unsigned long flags, physpage;
359
360 save_and_cli(flags);
361 while (start < end) {
362 if ((physpage = get_phys_page(start, mm)))
363 r3k_flush_icache_range(physpage,
364 physpage + PAGE_SIZE);
365 start += PAGE_SIZE;
366 }
367 restore_flags(flags);
368 }
369 }
370
371 static void r3k_flush_cache_page(struct vm_area_struct *vma,
372 unsigned long page)
373 {
374 struct mm_struct *mm = vma->vm_mm;
375
376 if (mm->context == 0)
377 return;
378
379 #ifdef DEBUG_CACHE
380 printk("cpage[%d,%08lx]", (int)mm->context, page);
381 #endif
382 if (vma->vm_flags & VM_EXEC) {
383 unsigned long physpage;
384
385 if ((physpage = get_phys_page(page, vma->vm_mm)))
386 r3k_flush_icache_range(physpage, physpage + PAGE_SIZE);
387 }
388 }
389
390 static void r3k_flush_page_to_ram(struct page * page)
391 {
392 /*
393 * Nothing to be done
394 */
395 }
396
397 static void r3k_flush_icache_page(struct vm_area_struct *vma, struct page *page)
398 {
399 struct mm_struct *mm = vma->vm_mm;
400 unsigned long physpage;
401
402 if (mm->context == 0)
403 return;
404
405 if (!(vma->vm_flags & VM_EXEC))
406 return;
407
408 #ifdef DEBUG_CACHE
409 printk("cpage[%d,%08lx]", (int)mm->context, page);
410 #endif
411
412 physpage = (unsigned long) page_address(page);
413 if (physpage)
414 r3k_flush_icache_range(physpage, physpage + PAGE_SIZE);
415 }
416
417 static void r3k_flush_cache_sigtramp(unsigned long addr)
418 {
419 unsigned long flags;
420
421 #ifdef DEBUG_CACHE
422 printk("csigtramp[%08lx]", addr);
423 #endif
424
425 flags = read_32bit_cp0_register(CP0_STATUS);
426
427 write_32bit_cp0_register(CP0_STATUS, flags&~ST0_IEC);
428
429 /* Fill the TLB to avoid an exception with caches isolated. */
430 asm ( "lw\t$0,0x000(%0)\n\t"
431 "lw\t$0,0x004(%0)\n\t"
432 : : "r" (addr) );
433
434 write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|ST0_SWC|flags)&~ST0_IEC);
435
436 asm ( "sb\t$0,0x000(%0)\n\t"
437 "sb\t$0,0x004(%0)\n\t"
438 : : "r" (addr) );
439
440 write_32bit_cp0_register(CP0_STATUS, flags);
441 }
442
443 static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size)
444 {
445 wbflush();
446 r3k_flush_dcache_range(start, start + size);
447 }
448
449 /* TLB operations. */
450 void flush_tlb_all(void)
451 {
452 unsigned long flags;
453 unsigned long old_ctx;
454 int entry;
455
456 #ifdef DEBUG_TLB
457 printk("[tlball]");
458 #endif
459
460 save_and_cli(flags);
461 old_ctx = (get_entryhi() & 0xfc0);
462 write_32bit_cp0_register(CP0_ENTRYLO0, 0);
463 for (entry = 8; entry < mips_cpu.tlbsize; entry++) {
464 write_32bit_cp0_register(CP0_INDEX, entry << 8);
465 write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x80000) << 12));
466 __asm__ __volatile__("tlbwi");
467 }
468 set_entryhi(old_ctx);
469 restore_flags(flags);
470 }
471
472 void flush_tlb_mm(struct mm_struct *mm)
473 {
474 if (mm->context != 0) {
475 unsigned long flags;
476
477 #ifdef DEBUG_TLB
478 printk("[tlbmm<%lu>]", (unsigned long) mm->context);
479 #endif
480 save_and_cli(flags);
481 get_new_mmu_context(mm, asid_cache);
482 if (mm == current->active_mm)
483 set_entryhi(mm->context & 0xfc0);
484 restore_flags(flags);
485 }
486 }
487
488 void flush_tlb_range(struct mm_struct *mm, unsigned long start,
489 unsigned long end)
490 {
491 if (mm->context != 0) {
492 unsigned long flags;
493 int size;
494
495 #ifdef DEBUG_TLB
496 printk("[tlbrange<%lu,0x%08lx,0x%08lx>]",
497 (mm->context & 0xfc0), start, end);
498 #endif
499 save_and_cli(flags);
500 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
501 if(size <= mips_cpu.tlbsize) {
502 int oldpid = (get_entryhi() & 0xfc0);
503 int newpid = (mm->context & 0xfc0);
504
505 start &= PAGE_MASK;
506 end += (PAGE_SIZE - 1);
507 end &= PAGE_MASK;
508 while(start < end) {
509 int idx;
510
511 set_entryhi(start | newpid);
512 start += PAGE_SIZE;
513 tlb_probe();
514 idx = get_index();
515 set_entrylo0(0);
516 set_entryhi(KSEG0);
517 if(idx < 0)
518 continue;
519 tlb_write_indexed();
520 }
521 set_entryhi(oldpid);
522 } else {
523 get_new_mmu_context(mm, asid_cache);
524 if (mm == current->active_mm)
525 set_entryhi(mm->context & 0xfc0);
526 }
527 restore_flags(flags);
528 }
529 }
530
531 void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
532 {
533 if(vma->vm_mm->context != 0) {
534 unsigned long flags;
535 int oldpid, newpid, idx;
536
537 #ifdef DEBUG_TLB
538 printk("[tlbpage<%lu,0x%08lx>]", vma->vm_mm->context, page);
539 #endif
540 newpid = (vma->vm_mm->context & 0xfc0);
541 page &= PAGE_MASK;
542 save_and_cli(flags);
543 oldpid = (get_entryhi() & 0xfc0);
544 set_entryhi(page | newpid);
545 tlb_probe();
546 idx = get_index();
547 set_entrylo0(0);
548 set_entryhi(KSEG0);
549 if(idx < 0)
550 goto finish;
551 tlb_write_indexed();
552
553 finish:
554 set_entryhi(oldpid);
555 restore_flags(flags);
556 }
557 }
558
559 /*
560 * Initialize new page directory with pointers to invalid ptes
561 */
562 void pgd_init(unsigned long page)
563 {
564 unsigned long dummy1, dummy2;
565
566 /*
567 * The plain and boring version for the R3000. No cache flushing
568 * stuff is implemented since the R3000 has physical caches.
569 */
570 __asm__ __volatile__(
571 ".set\tnoreorder\n"
572 "1:\tsw\t%2,(%0)\n\t"
573 "sw\t%2,4(%0)\n\t"
574 "sw\t%2,8(%0)\n\t"
575 "sw\t%2,12(%0)\n\t"
576 "sw\t%2,16(%0)\n\t"
577 "sw\t%2,20(%0)\n\t"
578 "sw\t%2,24(%0)\n\t"
579 "sw\t%2,28(%0)\n\t"
580 "subu\t%1,1\n\t"
581 "bnez\t%1,1b\n\t"
582 "addiu\t%0,32\n\t"
583 ".set\treorder"
584 :"=r" (dummy1),
585 "=r" (dummy2)
586 :"r" ((unsigned long) invalid_pte_table),
587 "0" (page),
588 "1" (PAGE_SIZE/(sizeof(pmd_t)*8)));
589 }
590
591 void update_mmu_cache(struct vm_area_struct * vma, unsigned long address,
592 pte_t pte)
593 {
594 unsigned long flags;
595 pgd_t *pgdp;
596 pmd_t *pmdp;
597 pte_t *ptep;
598 int idx, pid;
599
600 /*
601 * Handle debugger faulting in for debugee.
602 */
603 if (current->active_mm != vma->vm_mm)
604 return;
605
606 pid = get_entryhi() & 0xfc0;
607
608 #ifdef DEBUG_TLB
609 if((pid != (vma->vm_mm->context & 0xfc0)) || (vma->vm_mm->context == 0)) {
610 printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n",
611 (vma->vm_mm->context & 0xfc0), pid);
612 }
613 #endif
614
615 save_and_cli(flags);
616 address &= PAGE_MASK;
617 set_entryhi(address | (pid));
618 pgdp = pgd_offset(vma->vm_mm, address);
619 tlb_probe();
620 pmdp = pmd_offset(pgdp, address);
621 idx = get_index();
622 ptep = pte_offset(pmdp, address);
623 set_entrylo0(pte_val(*ptep));
624 set_entryhi(address | (pid));
625 if(idx < 0) {
626 tlb_write_random();
627 #if 0
628 printk("[MISS]");
629 #endif
630 } else {
631 tlb_write_indexed();
632 #if 0
633 printk("[HIT]");
634 #endif
635 }
636 set_entryhi(pid);
637 restore_flags(flags);
638 }
639
640 void show_regs(struct pt_regs * regs)
641 {
642 /*
643 * Saved main processor registers
644 */
645 printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
646 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2],
647 (unsigned long) regs->regs[3], (unsigned long) regs->regs[4],
648 (unsigned long) regs->regs[5], (unsigned long) regs->regs[6],
649 (unsigned long) regs->regs[7]);
650 printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
651 (unsigned long) regs->regs[8], (unsigned long) regs->regs[9],
652 (unsigned long) regs->regs[10], (unsigned long) regs->regs[11],
653 (unsigned long) regs->regs[12], (unsigned long) regs->regs[13],
654 (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]);
655 printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
656 (unsigned long) regs->regs[16], (unsigned long) regs->regs[17],
657 (unsigned long) regs->regs[18], (unsigned long) regs->regs[19],
658 (unsigned long) regs->regs[20], (unsigned long) regs->regs[21],
659 (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]);
660 printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n",
661 (unsigned long) regs->regs[24], (unsigned long) regs->regs[25],
662 (unsigned long) regs->regs[28], (unsigned long) regs->regs[29],
663 (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]);
664
665 /*
666 * Saved cp0 registers
667 */
668 printk("epc : %08lx\nStatus: %08x\nCause : %08x\n",
669 (unsigned long) regs->cp0_epc, (unsigned int) regs->cp0_status,
670 (unsigned int) regs->cp0_cause);
671 }
672
673 /* Todo: handle r4k-style TX39 TLB */
674 void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
675 unsigned long entryhi, unsigned long pagemask)
676 {
677 unsigned long flags;
678 unsigned long old_ctx;
679 static unsigned long wired = 0;
680
681 if (wired < 8) {
682 save_and_cli(flags);
683 old_ctx = get_entryhi() & 0xfc0;
684 set_entrylo0(entrylo0);
685 set_entryhi(entryhi);
686 set_index(wired);
687 wired++;
688 tlb_write_indexed();
689 set_entryhi(old_ctx);
690 flush_tlb_all();
691 restore_flags(flags);
692 }
693 }
694
695 static void tx39_flush_icache_all(void )
696 {
697
698 unsigned long start = KSEG0;
699 unsigned long end = (start + icache_size);
700 unsigned long dummy = 0;
701
702 /* disable icache and stop streaming */
703 __asm__ __volatile__(
704 ".set\tnoreorder\n\t"
705 "mfc0\t%0,$3\n\t"
706 "xori\t%0,32\n\t"
707 "mtc0\t%0,$3\n\t"
708 "j\t1f\n\t"
709 "nop\n\t"
710 "1:\t.set\treorder\n\t"
711 : : "r"(dummy));
712
713 /* invalidate icache */
714 while (start < end) {
715 cache16_unroll32(start,Index_Invalidate_I);
716 start += 0x200;
717 }
718
719 /* enable icache */
720 __asm__ __volatile__(
721 ".set\tnoreorder\n\t"
722 "mfc0\t%0,$3\n\t"
723 "xori\t%0,32\n\t"
724 "mtc0\t%0,$3\n\t"
725 ".set\treorder\n\t"
726 : : "r"(dummy));
727 }
728
729 static __init void tx39_probe_cache(void)
730 {
731 unsigned long config;
732
733 config = read_32bit_cp0_register(CP0_CONF);
734
735 icache_size = 1 << (10 + ((config >> 19) & 3));
736 icache_lsize = 16;
737
738 dcache_size = 1 << (10 + ((config >> 16) & 3));
739 dcache_lsize = 4;
740 }
741
742 void __init ld_mmu_r23000(void)
743 {
744 unsigned long config;
745
746 printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID));
747
748 _clear_page = r3k_clear_page;
749 _copy_page = r3k_copy_page;
750
751 switch (mips_cpu.cputype) {
752 case CPU_R2000:
753 case CPU_R3000:
754 case CPU_R3000A:
755 case CPU_R3081:
756 case CPU_R3081E:
757
758 r3k_probe_cache();
759
760 _flush_cache_all = r3k_flush_cache_all;
761 ___flush_cache_all = r3k_flush_cache_all;
762 _flush_cache_mm = r3k_flush_cache_mm;
763 _flush_cache_range = r3k_flush_cache_range;
764 _flush_cache_page = r3k_flush_cache_page;
765 _flush_cache_sigtramp = r3k_flush_cache_sigtramp;
766 _flush_page_to_ram = r3k_flush_page_to_ram;
767 _flush_icache_page = r3k_flush_icache_page;
768 _flush_icache_range = r3k_flush_icache_range;
769
770 _dma_cache_wback_inv = r3k_dma_cache_wback_inv;
771 break;
772
773 case CPU_TX3912:
774 case CPU_TX3922:
775 case CPU_TX3927:
776
777 config=read_32bit_cp0_register(CP0_CONF);
778 config &= ~TX39_CONF_WBON;
779 write_32bit_cp0_register(CP0_CONF, config);
780
781 tx39_probe_cache();
782
783 _flush_cache_all = tx39_flush_icache_all;
784 ___flush_cache_all = tx39_flush_icache_all;
785 _flush_cache_mm = tx39_flush_icache_all;
786 _flush_cache_range = tx39_flush_icache_all;
787 _flush_cache_page = tx39_flush_icache_all;
788 _flush_cache_sigtramp = tx39_flush_icache_all;
789 _flush_page_to_ram = r3k_flush_page_to_ram;
790 _flush_icache_page = tx39_flush_icache_all;
791 _flush_icache_range = tx39_flush_icache_all;
792
793 _dma_cache_wback_inv = r3k_dma_cache_wback_inv;
794
795 break;
796 }
797
798 printk("Primary instruction cache %dkb, linesize %d bytes\n",
799 (int) (icache_size >> 10), (int) icache_lsize);
800 printk("Primary data cache %dkb, linesize %d bytes\n",
801 (int) (dcache_size >> 10), (int) dcache_lsize);
802
803 flush_tlb_all();
804 }
805