2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * r4xx0.c: R4000 processor variant specific MMU/Cache routines.
8 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
9 * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle ralf@gnu.org
11 #include <linux/config.h>
12 #include <asm/addrspace.h>
14 #include <asm/regdef.h>
15 #include <asm/cacheops.h>
16 #include <asm/mipsregs.h>
17 #include <asm/offset.h>
19 #ifdef CONFIG_64BIT_PHYS_ADDR
20 #define PGD_SIZE 0x2000
22 #define PGD_SIZE 0x1000
29 * Zero an entire page. Basically a simple unrolled loop should do the
30 * job but we want more performance by saving memory bus bandwidth. We
31 * have five flavours of the routine available for:
33 * - 16byte cachelines and no second level cache
34 * - 32byte cachelines second level cache
35 * - a version which handles the buggy R4600 v1.x
36 * - a version which handles the buggy R4600 v2.0
37 * - Finally a last version without fancy cache games for the SC and MC
38 * versions of R4000 and R4400.
41 LEAF(r4k_clear_page32_d16)
43 addiu AT, a0, _PAGE_SIZE
44 1: cache Create_Dirty_Excl_D, (a0)
50 cache Create_Dirty_Excl_D, -16(a0)
57 END(r4k_clear_page32_d16)
59 LEAF(r4k_clear_page32_d32)
61 addiu AT, a0, _PAGE_SIZE
62 1: cache Create_Dirty_Excl_D, (a0)
74 END(r4k_clear_page32_d32)
76 LEAF(r4k_clear_page_d16)
78 addiu AT, a0, _PAGE_SIZE
79 1: cache Create_Dirty_Excl_D, (a0)
82 cache Create_Dirty_Excl_D, 16(a0)
86 cache Create_Dirty_Excl_D, -32(a0)
89 cache Create_Dirty_Excl_D, -16(a0)
94 END(r4k_clear_page_d16)
96 LEAF(r4k_clear_page_d32)
98 addiu AT, a0, _PAGE_SIZE
99 1: cache Create_Dirty_Excl_D, (a0)
105 cache Create_Dirty_Excl_D, -32(a0)
112 END(r4k_clear_page_d32)
115 * This flavour of r4k_clear_page is for the R4600 V1.x. Cite from the
116 * IDT R4600 V1.7 errata:
118 * 18. The CACHE instructions Hit_Writeback_Invalidate_D, Hit_Writeback_D,
119 * Hit_Invalidate_D and Create_Dirty_Excl_D should only be
120 * executed if there is no other dcache activity. If the dcache is
121 * accessed for another instruction immeidately preceding when these
122 * cache instructions are executing, it is possible that the dcache
123 * tag match outputs used by these cache instructions will be
124 * incorrect. These cache instructions should be preceded by at least
125 * four instructions that are not any kind of load or store
128 * This is not allowed: lw
132 * cache Hit_Writeback_Invalidate_D
134 * This is allowed: lw
139 * cache Hit_Writeback_Invalidate_D
142 LEAF(r4k_clear_page_r4600_v1)
144 addiu AT, a0, _PAGE_SIZE
149 cache Create_Dirty_Excl_D, (a0)
158 cache Create_Dirty_Excl_D, -32(a0)
165 END(r4k_clear_page_r4600_v1)
167 LEAF(r4k_clear_page_r4600_v2)
182 addiu AT, a0, _PAGE_SIZE
183 1: cache Create_Dirty_Excl_D, (a0)
189 cache Create_Dirty_Excl_D, -32(a0)
196 mfc0 AT, CP0_STATUS # local_irq_restore
207 END(r4k_clear_page_r4600_v2)
210 * The next 4 versions are optimized for all possible scache configurations
211 * of the SC / MC versions of R4000 and R4400 ...
213 * Todo: For even better performance we should have a routine optimized for
214 * every legal combination of dcache / scache linesize. When I (Ralf) tried
215 * this the kernel crashed shortly after mounting the root filesystem. CPU
216 * bug? Weirdo cache instruction semantics?
219 LEAF(r4k_clear_page_s16)
221 addiu AT, a0, _PAGE_SIZE
222 1: cache Create_Dirty_Excl_SD, (a0)
225 cache Create_Dirty_Excl_SD, 16(a0)
229 cache Create_Dirty_Excl_SD, -32(a0)
232 cache Create_Dirty_Excl_SD, -16(a0)
237 END(r4k_clear_page_s16)
239 LEAF(r4k_clear_page_s32)
241 addiu AT, a0, _PAGE_SIZE
242 1: cache Create_Dirty_Excl_SD, (a0)
248 cache Create_Dirty_Excl_SD, -32(a0)
255 END(r4k_clear_page_s32)
257 LEAF(r4k_clear_page_s64)
259 addiu AT, a0, _PAGE_SIZE
260 1: cache Create_Dirty_Excl_SD, (a0)
272 END(r4k_clear_page_s64)
274 LEAF(r4k_clear_page_s128)
276 addiu AT, a0, _PAGE_SIZE
277 1: cache Create_Dirty_Excl_SD, (a0)
297 END(r4k_clear_page_s128)
300 * This is suboptimal for 32-bit kernels; we assume that R10000 is only used
301 * with 64-bit kernels. The prefetch offsets have been experimentally tuned
304 LEAF(andes_clear_page)
306 LONG_ADDIU AT, a0, _PAGE_SIZE
312 LONG_ADDIU a0, a0, 8*SZREG
313 sd zero, -4*SZREG(a0)
314 sd zero, -3*SZREG(a0)
315 sd zero, -2*SZREG(a0)
316 sd zero, -1*SZREG(a0)
319 END(andes_clear_page)
323 * This is still inefficient. We only can do better if we know the
324 * virtual address where the copy will be accessed.
327 LEAF(r4k_copy_page_d16)
329 addiu AT, a0, _PAGE_SIZE
330 1: cache Create_Dirty_Excl_D, (a0)
339 cache Create_Dirty_Excl_D, 16(a0)
348 cache Create_Dirty_Excl_D, 32(a0)
359 cache Create_Dirty_Excl_D, -16(a0)
370 END(r4k_copy_page_d16)
372 LEAF(r4k_copy_page_d32)
374 addiu AT, a0, _PAGE_SIZE
375 1: cache Create_Dirty_Excl_D, (a0)
392 cache Create_Dirty_Excl_D, 32(a0)
413 END(r4k_copy_page_d32)
416 * Again a special version for the R4600 V1.x
419 LEAF(r4k_copy_page_r4600_v1)
421 addiu AT, a0, _PAGE_SIZE
426 cache Create_Dirty_Excl_D, (a0)
447 cache Create_Dirty_Excl_D, 32(a0)
468 END(r4k_copy_page_r4600_v1)
470 LEAF(r4k_copy_page_r4600_v2)
481 addiu AT, a0, _PAGE_SIZE
486 cache Create_Dirty_Excl_D, (a0)
507 cache Create_Dirty_Excl_D, 32(a0)
528 mfc0 AT, CP0_STATUS # local_irq_restore
538 END(r4k_copy_page_r4600_v2)
541 * These are for R4000SC / R4400MC
544 LEAF(r4k_copy_page_s16)
546 addiu AT, a0, _PAGE_SIZE
547 1: cache Create_Dirty_Excl_SD, (a0)
556 cache Create_Dirty_Excl_SD, 16(a0)
565 cache Create_Dirty_Excl_SD, 32(a0)
576 cache Create_Dirty_Excl_SD, -16(a0)
587 END(r4k_copy_page_s16)
589 LEAF(r4k_copy_page_s32)
591 addiu AT, a0, _PAGE_SIZE
592 1: cache Create_Dirty_Excl_SD, (a0)
609 cache Create_Dirty_Excl_SD, 32(a0)
630 END(r4k_copy_page_s32)
632 LEAF(r4k_copy_page_s64)
634 addiu AT, a0, _PAGE_SIZE
635 1: cache Create_Dirty_Excl_SD, (a0)
672 END(r4k_copy_page_s64)
674 LEAF(r4k_copy_page_s128)
676 addiu AT, a0, _PAGE_SIZE
677 1: cache Create_Dirty_Excl_SD, (a0)
746 END(r4k_copy_page_s128)
755 * This is suboptimal for 32-bit kernels; we assume that R10000 is only used
756 * with 64-bit kernels. The prefetch offsets have been experimentally tuned
759 LEAF(andes_copy_page)
761 LONG_ADDIU AT, a0, _PAGE_SIZE
764 LONG_L a3, 0*SZREG(a1)
765 LONG_L a2, 1*SZREG(a1)
766 LONG_L v1, 2*SZREG(a1)
767 LONG_L v0, 3*SZREG(a1)
768 LONG_S a3, 0*SZREG(a0)
769 LONG_S a2, 1*SZREG(a0)
770 LONG_S v1, 2*SZREG(a0)
771 LONG_S v0, 3*SZREG(a0)
772 LONG_ADDIU a0, a0, 8*SZREG
773 LONG_ADDIU a1, a1, 8*SZREG
774 LONG_L a3, -4*SZREG(a1)
775 LONG_L a2, -3*SZREG(a1)
776 LONG_L v1, -2*SZREG(a1)
777 LONG_L v0, -1*SZREG(a1)
778 LONG_S a3, -4*SZREG(a0)
779 LONG_S a2, -3*SZREG(a0)
780 LONG_S v1, -2*SZREG(a0)
781 LONG_S v0, -1*SZREG(a0)