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