aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mm/tlbex.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-10-29 15:19:15 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-10-29 15:19:15 -0400
commite9d52234e35b27ea4ea5f2ab64ca47b1a0c740ab (patch)
tree318d37a7d55c79e6f7d86163fb28e0eccbb0fe83 /arch/mips/mm/tlbex.c
parent955c5038823748e529a49f0e33ab635d92843500 (diff)
parent09af7b443c257460d45cb6c1896d29f173fef35b (diff)
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
Diffstat (limited to 'arch/mips/mm/tlbex.c')
-rw-r--r--arch/mips/mm/tlbex.c245
1 files changed, 123 insertions, 122 deletions
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 6569be3983c7..0f9485806bac 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -6,6 +6,7 @@
6 * Synthesize TLB refill handlers at runtime. 6 * Synthesize TLB refill handlers at runtime.
7 * 7 *
8 * Copyright (C) 2004,2005 by Thiemo Seufer 8 * Copyright (C) 2004,2005 by Thiemo Seufer
9 * Copyright (C) 2005 Maciej W. Rozycki
9 */ 10 */
10 11
11#include <stdarg.h> 12#include <stdarg.h>
@@ -91,7 +92,7 @@ enum opcode {
91 insn_addu, insn_addiu, insn_and, insn_andi, insn_beq, 92 insn_addu, insn_addiu, insn_and, insn_andi, insn_beq,
92 insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, 93 insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
93 insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0, 94 insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0,
94 insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, 95 insn_dsll, insn_dsll32, insn_dsra, insn_dsrl,
95 insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld, 96 insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld,
96 insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0, 97 insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0,
97 insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, 98 insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
@@ -134,7 +135,6 @@ static __initdata struct insn insn_table[] = {
134 { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE }, 135 { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE },
135 { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE }, 136 { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE },
136 { insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE }, 137 { insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE },
137 { insn_dsrl32, M(spec_op,0,0,0,0,dsrl32_op), RT | RD | RE },
138 { insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD }, 138 { insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD },
139 { insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 }, 139 { insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 },
140 { insn_j, M(j_op,0,0,0,0,0), JIMM }, 140 { insn_j, M(j_op,0,0,0,0,0), JIMM },
@@ -366,7 +366,6 @@ I_u2u1u3(_dsll);
366I_u2u1u3(_dsll32); 366I_u2u1u3(_dsll32);
367I_u2u1u3(_dsra); 367I_u2u1u3(_dsra);
368I_u2u1u3(_dsrl); 368I_u2u1u3(_dsrl);
369I_u2u1u3(_dsrl32);
370I_u3u1u2(_dsubu); 369I_u3u1u2(_dsubu);
371I_0(_eret); 370I_0(_eret);
372I_u1(_j); 371I_u1(_j);
@@ -412,7 +411,6 @@ enum label_id {
412 label_nopage_tlbm, 411 label_nopage_tlbm,
413 label_smp_pgtable_change, 412 label_smp_pgtable_change,
414 label_r3000_write_probe_fail, 413 label_r3000_write_probe_fail,
415 label_r3000_write_probe_ok
416}; 414};
417 415
418struct label { 416struct label {
@@ -445,7 +443,6 @@ L_LA(_nopage_tlbs)
445L_LA(_nopage_tlbm) 443L_LA(_nopage_tlbm)
446L_LA(_smp_pgtable_change) 444L_LA(_smp_pgtable_change)
447L_LA(_r3000_write_probe_fail) 445L_LA(_r3000_write_probe_fail)
448L_LA(_r3000_write_probe_ok)
449 446
450/* convenience macros for instructions */ 447/* convenience macros for instructions */
451#ifdef CONFIG_64BIT 448#ifdef CONFIG_64BIT
@@ -490,7 +487,7 @@ L_LA(_r3000_write_probe_ok)
490static __init int __attribute__((unused)) in_compat_space_p(long addr) 487static __init int __attribute__((unused)) in_compat_space_p(long addr)
491{ 488{
492 /* Is this address in 32bit compat space? */ 489 /* Is this address in 32bit compat space? */
493 return (((addr) & 0xffffffff00000000) == 0xffffffff00000000); 490 return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L);
494} 491}
495 492
496static __init int __attribute__((unused)) rel_highest(long val) 493static __init int __attribute__((unused)) rel_highest(long val)
@@ -734,7 +731,7 @@ static void __init build_r3000_tlb_refill_handler(void)
734 if (p > tlb_handler + 32) 731 if (p > tlb_handler + 32)
735 panic("TLB refill handler space exceeded"); 732 panic("TLB refill handler space exceeded");
736 733
737 printk("Synthesized TLB handler (%u instructions).\n", 734 printk("Synthesized TLB refill handler (%u instructions).\n",
738 (unsigned int)(p - tlb_handler)); 735 (unsigned int)(p - tlb_handler));
739#ifdef DEBUG_TLB 736#ifdef DEBUG_TLB
740 { 737 {
@@ -746,7 +743,6 @@ static void __init build_r3000_tlb_refill_handler(void)
746#endif 743#endif
747 744
748 memcpy((void *)CAC_BASE, tlb_handler, 0x80); 745 memcpy((void *)CAC_BASE, tlb_handler, 0x80);
749 flush_icache_range(CAC_BASE, CAC_BASE + 0x80);
750} 746}
751 747
752/* 748/*
@@ -783,6 +779,8 @@ static __initdata u32 final_handler[64];
783static __init void __attribute__((unused)) build_tlb_probe_entry(u32 **p) 779static __init void __attribute__((unused)) build_tlb_probe_entry(u32 **p)
784{ 780{
785 switch (current_cpu_data.cputype) { 781 switch (current_cpu_data.cputype) {
782 /* Found by experiment: R4600 v2.0 needs this, too. */
783 case CPU_R4600:
786 case CPU_R5000: 784 case CPU_R5000:
787 case CPU_R5000A: 785 case CPU_R5000A:
788 case CPU_NEVADA: 786 case CPU_NEVADA:
@@ -834,12 +832,20 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
834 case CPU_R4700: 832 case CPU_R4700:
835 case CPU_R5000: 833 case CPU_R5000:
836 case CPU_R5000A: 834 case CPU_R5000A:
835 i_nop(p);
836 tlbw(p);
837 i_nop(p);
838 break;
839
840 case CPU_R4300:
837 case CPU_5KC: 841 case CPU_5KC:
838 case CPU_TX49XX: 842 case CPU_TX49XX:
839 case CPU_AU1000: 843 case CPU_AU1000:
840 case CPU_AU1100: 844 case CPU_AU1100:
841 case CPU_AU1500: 845 case CPU_AU1500:
842 case CPU_AU1550: 846 case CPU_AU1550:
847 case CPU_AU1200:
848 case CPU_PR4450:
843 i_nop(p); 849 i_nop(p);
844 tlbw(p); 850 tlbw(p);
845 break; 851 break;
@@ -848,6 +854,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
848 case CPU_R12000: 854 case CPU_R12000:
849 case CPU_4KC: 855 case CPU_4KC:
850 case CPU_SB1: 856 case CPU_SB1:
857 case CPU_SB1A:
851 case CPU_4KSC: 858 case CPU_4KSC:
852 case CPU_20KC: 859 case CPU_20KC:
853 case CPU_25KF: 860 case CPU_25KF:
@@ -875,6 +882,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
875 882
876 case CPU_4KEC: 883 case CPU_4KEC:
877 case CPU_24K: 884 case CPU_24K:
885 case CPU_34K:
878 i_ehb(p); 886 i_ehb(p);
879 tlbw(p); 887 tlbw(p);
880 break; 888 break;
@@ -911,6 +919,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
911 919
912 case CPU_VR4131: 920 case CPU_VR4131:
913 case CPU_VR4133: 921 case CPU_VR4133:
922 case CPU_R5432:
914 i_nop(p); 923 i_nop(p);
915 i_nop(p); 924 i_nop(p);
916 tlbw(p); 925 tlbw(p);
@@ -942,34 +951,29 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r,
942 /* No i_nop needed here, since the next insn doesn't touch TMP. */ 951 /* No i_nop needed here, since the next insn doesn't touch TMP. */
943 952
944#ifdef CONFIG_SMP 953#ifdef CONFIG_SMP
954# ifdef CONFIG_BUILD_ELF64
945 /* 955 /*
946 * 64 bit SMP has the lower part of &pgd_current[smp_processor_id()] 956 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
947 * stored in CONTEXT. 957 * stored in CONTEXT.
948 */ 958 */
949 if (in_compat_space_p(pgdc)) { 959 i_dmfc0(p, ptr, C0_CONTEXT);
950 i_dmfc0(p, ptr, C0_CONTEXT); 960 i_dsrl(p, ptr, ptr, 23);
951 i_dsra(p, ptr, ptr, 23); 961 i_LA_mostly(p, tmp, pgdc);
952 i_ld(p, ptr, 0, ptr); 962 i_daddu(p, ptr, ptr, tmp);
953 } else { 963 i_dmfc0(p, tmp, C0_BADVADDR);
954#ifdef CONFIG_BUILD_ELF64 964 i_ld(p, ptr, rel_lo(pgdc), ptr);
955 i_dmfc0(p, ptr, C0_CONTEXT); 965# else
956 i_dsrl(p, ptr, ptr, 23); 966 /*
957 i_dsll(p, ptr, ptr, 3); 967 * 64 bit SMP running in compat space has the lower part of
958 i_LA_mostly(p, tmp, pgdc); 968 * &pgd_current[smp_processor_id()] stored in CONTEXT.
959 i_daddu(p, ptr, ptr, tmp); 969 */
960 i_dmfc0(p, tmp, C0_BADVADDR); 970 if (!in_compat_space_p(pgdc))
961 i_ld(p, ptr, rel_lo(pgdc), ptr); 971 panic("Invalid page directory address!");
962#else 972
963 i_dmfc0(p, ptr, C0_CONTEXT); 973 i_dmfc0(p, ptr, C0_CONTEXT);
964 i_lui(p, tmp, rel_highest(pgdc)); 974 i_dsra(p, ptr, ptr, 23);
965 i_dsll(p, ptr, ptr, 9); 975 i_ld(p, ptr, 0, ptr);
966 i_daddiu(p, tmp, tmp, rel_higher(pgdc)); 976# endif
967 i_dsrl32(p, ptr, ptr, 0);
968 i_and(p, ptr, ptr, tmp);
969 i_dmfc0(p, tmp, C0_BADVADDR);
970 i_ld(p, ptr, 0, ptr);
971#endif
972 }
973#else 977#else
974 i_LA_mostly(p, ptr, pgdc); 978 i_LA_mostly(p, ptr, pgdc);
975 i_ld(p, ptr, rel_lo(pgdc), ptr); 979 i_ld(p, ptr, rel_lo(pgdc), ptr);
@@ -1026,7 +1030,6 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
1026 i_mfc0(p, ptr, C0_CONTEXT); 1030 i_mfc0(p, ptr, C0_CONTEXT);
1027 i_LA_mostly(p, tmp, pgdc); 1031 i_LA_mostly(p, tmp, pgdc);
1028 i_srl(p, ptr, ptr, 23); 1032 i_srl(p, ptr, ptr, 23);
1029 i_sll(p, ptr, ptr, 2);
1030 i_addu(p, ptr, tmp, ptr); 1033 i_addu(p, ptr, tmp, ptr);
1031#else 1034#else
1032 i_LA_mostly(p, ptr, pgdc); 1035 i_LA_mostly(p, ptr, pgdc);
@@ -1245,13 +1248,19 @@ static void __init build_r4000_tlb_refill_handler(void)
1245 { 1248 {
1246 int i; 1249 int i;
1247 1250
1248 for (i = 0; i < 64; i++) 1251 f = final_handler;
1249 printk("%08x\n", final_handler[i]); 1252#ifdef CONFIG_64BIT
1253 if (final_len > 32)
1254 final_len = 64;
1255 else
1256 f = final_handler + 32;
1257#endif /* CONFIG_64BIT */
1258 for (i = 0; i < final_len; i++)
1259 printk("%08x\n", f[i]);
1250 } 1260 }
1251#endif 1261#endif
1252 1262
1253 memcpy((void *)CAC_BASE, final_handler, 0x100); 1263 memcpy((void *)CAC_BASE, final_handler, 0x100);
1254 flush_icache_range(CAC_BASE, CAC_BASE + 0x100);
1255} 1264}
1256 1265
1257/* 1266/*
@@ -1277,37 +1286,41 @@ u32 __tlb_handler_align handle_tlbs[FASTPATH_SIZE];
1277u32 __tlb_handler_align handle_tlbm[FASTPATH_SIZE]; 1286u32 __tlb_handler_align handle_tlbm[FASTPATH_SIZE];
1278 1287
1279static void __init 1288static void __init
1280iPTE_LW(u32 **p, struct label **l, unsigned int pte, int offset, 1289iPTE_LW(u32 **p, struct label **l, unsigned int pte, unsigned int ptr)
1281 unsigned int ptr)
1282{ 1290{
1283#ifdef CONFIG_SMP 1291#ifdef CONFIG_SMP
1284# ifdef CONFIG_64BIT_PHYS_ADDR 1292# ifdef CONFIG_64BIT_PHYS_ADDR
1285 if (cpu_has_64bits) 1293 if (cpu_has_64bits)
1286 i_lld(p, pte, offset, ptr); 1294 i_lld(p, pte, 0, ptr);
1287 else 1295 else
1288# endif 1296# endif
1289 i_LL(p, pte, offset, ptr); 1297 i_LL(p, pte, 0, ptr);
1290#else 1298#else
1291# ifdef CONFIG_64BIT_PHYS_ADDR 1299# ifdef CONFIG_64BIT_PHYS_ADDR
1292 if (cpu_has_64bits) 1300 if (cpu_has_64bits)
1293 i_ld(p, pte, offset, ptr); 1301 i_ld(p, pte, 0, ptr);
1294 else 1302 else
1295# endif 1303# endif
1296 i_LW(p, pte, offset, ptr); 1304 i_LW(p, pte, 0, ptr);
1297#endif 1305#endif
1298} 1306}
1299 1307
1300static void __init 1308static void __init
1301iPTE_SW(u32 **p, struct reloc **r, unsigned int pte, int offset, 1309iPTE_SW(u32 **p, struct reloc **r, unsigned int pte, unsigned int ptr,
1302 unsigned int ptr) 1310 unsigned int mode)
1303{ 1311{
1312#ifdef CONFIG_64BIT_PHYS_ADDR
1313 unsigned int hwmode = mode & (_PAGE_VALID | _PAGE_DIRTY);
1314#endif
1315
1316 i_ori(p, pte, pte, mode);
1304#ifdef CONFIG_SMP 1317#ifdef CONFIG_SMP
1305# ifdef CONFIG_64BIT_PHYS_ADDR 1318# ifdef CONFIG_64BIT_PHYS_ADDR
1306 if (cpu_has_64bits) 1319 if (cpu_has_64bits)
1307 i_scd(p, pte, offset, ptr); 1320 i_scd(p, pte, 0, ptr);
1308 else 1321 else
1309# endif 1322# endif
1310 i_SC(p, pte, offset, ptr); 1323 i_SC(p, pte, 0, ptr);
1311 1324
1312 if (r10000_llsc_war()) 1325 if (r10000_llsc_war())
1313 il_beqzl(p, r, pte, label_smp_pgtable_change); 1326 il_beqzl(p, r, pte, label_smp_pgtable_change);
@@ -1318,7 +1331,7 @@ iPTE_SW(u32 **p, struct reloc **r, unsigned int pte, int offset,
1318 if (!cpu_has_64bits) { 1331 if (!cpu_has_64bits) {
1319 /* no i_nop needed */ 1332 /* no i_nop needed */
1320 i_ll(p, pte, sizeof(pte_t) / 2, ptr); 1333 i_ll(p, pte, sizeof(pte_t) / 2, ptr);
1321 i_ori(p, pte, pte, _PAGE_VALID); 1334 i_ori(p, pte, pte, hwmode);
1322 i_sc(p, pte, sizeof(pte_t) / 2, ptr); 1335 i_sc(p, pte, sizeof(pte_t) / 2, ptr);
1323 il_beqz(p, r, pte, label_smp_pgtable_change); 1336 il_beqz(p, r, pte, label_smp_pgtable_change);
1324 /* no i_nop needed */ 1337 /* no i_nop needed */
@@ -1331,15 +1344,15 @@ iPTE_SW(u32 **p, struct reloc **r, unsigned int pte, int offset,
1331#else 1344#else
1332# ifdef CONFIG_64BIT_PHYS_ADDR 1345# ifdef CONFIG_64BIT_PHYS_ADDR
1333 if (cpu_has_64bits) 1346 if (cpu_has_64bits)
1334 i_sd(p, pte, offset, ptr); 1347 i_sd(p, pte, 0, ptr);
1335 else 1348 else
1336# endif 1349# endif
1337 i_SW(p, pte, offset, ptr); 1350 i_SW(p, pte, 0, ptr);
1338 1351
1339# ifdef CONFIG_64BIT_PHYS_ADDR 1352# ifdef CONFIG_64BIT_PHYS_ADDR
1340 if (!cpu_has_64bits) { 1353 if (!cpu_has_64bits) {
1341 i_lw(p, pte, sizeof(pte_t) / 2, ptr); 1354 i_lw(p, pte, sizeof(pte_t) / 2, ptr);
1342 i_ori(p, pte, pte, _PAGE_VALID); 1355 i_ori(p, pte, pte, hwmode);
1343 i_sw(p, pte, sizeof(pte_t) / 2, ptr); 1356 i_sw(p, pte, sizeof(pte_t) / 2, ptr);
1344 i_lw(p, pte, 0, ptr); 1357 i_lw(p, pte, 0, ptr);
1345 } 1358 }
@@ -1359,7 +1372,7 @@ build_pte_present(u32 **p, struct label **l, struct reloc **r,
1359 i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ); 1372 i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
1360 i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ); 1373 i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
1361 il_bnez(p, r, pte, lid); 1374 il_bnez(p, r, pte, lid);
1362 iPTE_LW(p, l, pte, 0, ptr); 1375 iPTE_LW(p, l, pte, ptr);
1363} 1376}
1364 1377
1365/* Make PTE valid, store result in PTR. */ 1378/* Make PTE valid, store result in PTR. */
@@ -1367,8 +1380,9 @@ static void __init
1367build_make_valid(u32 **p, struct reloc **r, unsigned int pte, 1380build_make_valid(u32 **p, struct reloc **r, unsigned int pte,
1368 unsigned int ptr) 1381 unsigned int ptr)
1369{ 1382{
1370 i_ori(p, pte, pte, _PAGE_VALID | _PAGE_ACCESSED); 1383 unsigned int mode = _PAGE_VALID | _PAGE_ACCESSED;
1371 iPTE_SW(p, r, pte, 0, ptr); 1384
1385 iPTE_SW(p, r, pte, ptr, mode);
1372} 1386}
1373 1387
1374/* 1388/*
@@ -1382,7 +1396,7 @@ build_pte_writable(u32 **p, struct label **l, struct reloc **r,
1382 i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE); 1396 i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
1383 i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE); 1397 i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
1384 il_bnez(p, r, pte, lid); 1398 il_bnez(p, r, pte, lid);
1385 iPTE_LW(p, l, pte, 0, ptr); 1399 iPTE_LW(p, l, pte, ptr);
1386} 1400}
1387 1401
1388/* Make PTE writable, update software status bits as well, then store 1402/* Make PTE writable, update software status bits as well, then store
@@ -1392,9 +1406,10 @@ static void __init
1392build_make_write(u32 **p, struct reloc **r, unsigned int pte, 1406build_make_write(u32 **p, struct reloc **r, unsigned int pte,
1393 unsigned int ptr) 1407 unsigned int ptr)
1394{ 1408{
1395 i_ori(p, pte, pte, 1409 unsigned int mode = (_PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID
1396 _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY); 1410 | _PAGE_DIRTY);
1397 iPTE_SW(p, r, pte, 0, ptr); 1411
1412 iPTE_SW(p, r, pte, ptr, mode);
1398} 1413}
1399 1414
1400/* 1415/*
@@ -1407,41 +1422,48 @@ build_pte_modifiable(u32 **p, struct label **l, struct reloc **r,
1407{ 1422{
1408 i_andi(p, pte, pte, _PAGE_WRITE); 1423 i_andi(p, pte, pte, _PAGE_WRITE);
1409 il_beqz(p, r, pte, lid); 1424 il_beqz(p, r, pte, lid);
1410 iPTE_LW(p, l, pte, 0, ptr); 1425 iPTE_LW(p, l, pte, ptr);
1411} 1426}
1412 1427
1413/* 1428/*
1414 * R3000 style TLB load/store/modify handlers. 1429 * R3000 style TLB load/store/modify handlers.
1415 */ 1430 */
1416 1431
1417/* This places the pte in the page table at PTR into ENTRYLO0. */ 1432/*
1433 * This places the pte into ENTRYLO0 and writes it with tlbwi.
1434 * Then it returns.
1435 */
1418static void __init 1436static void __init
1419build_r3000_pte_reload(u32 **p, unsigned int ptr) 1437build_r3000_pte_reload_tlbwi(u32 **p, unsigned int pte, unsigned int tmp)
1420{ 1438{
1421 i_lw(p, ptr, 0, ptr); 1439 i_mtc0(p, pte, C0_ENTRYLO0); /* cp0 delay */
1422 i_nop(p); /* load delay */ 1440 i_mfc0(p, tmp, C0_EPC); /* cp0 delay */
1423 i_mtc0(p, ptr, C0_ENTRYLO0); 1441 i_tlbwi(p);
1424 i_nop(p); /* cp0 delay */ 1442 i_jr(p, tmp);
1443 i_rfe(p); /* branch delay */
1425} 1444}
1426 1445
1427/* 1446/*
1428 * The index register may have the probe fail bit set, 1447 * This places the pte into ENTRYLO0 and writes it with tlbwi
1429 * because we would trap on access kseg2, i.e. without refill. 1448 * or tlbwr as appropriate. This is because the index register
1449 * may have the probe fail bit set as a result of a trap on a
1450 * kseg2 access, i.e. without refill. Then it returns.
1430 */ 1451 */
1431static void __init 1452static void __init
1432build_r3000_tlb_write(u32 **p, struct label **l, struct reloc **r, 1453build_r3000_tlb_reload_write(u32 **p, struct label **l, struct reloc **r,
1433 unsigned int tmp) 1454 unsigned int pte, unsigned int tmp)
1434{ 1455{
1435 i_mfc0(p, tmp, C0_INDEX); 1456 i_mfc0(p, tmp, C0_INDEX);
1436 i_nop(p); /* cp0 delay */ 1457 i_mtc0(p, pte, C0_ENTRYLO0); /* cp0 delay */
1437 il_bltz(p, r, tmp, label_r3000_write_probe_fail); 1458 il_bltz(p, r, tmp, label_r3000_write_probe_fail); /* cp0 delay */
1438 i_nop(p); /* branch delay */ 1459 i_mfc0(p, tmp, C0_EPC); /* branch delay */
1439 i_tlbwi(p); 1460 i_tlbwi(p); /* cp0 delay */
1440 il_b(p, r, label_r3000_write_probe_ok); 1461 i_jr(p, tmp);
1441 i_nop(p); /* branch delay */ 1462 i_rfe(p); /* branch delay */
1442 l_r3000_write_probe_fail(l, *p); 1463 l_r3000_write_probe_fail(l, *p);
1443 i_tlbwr(p); 1464 i_tlbwr(p); /* cp0 delay */
1444 l_r3000_write_probe_ok(l, *p); 1465 i_jr(p, tmp);
1466 i_rfe(p); /* branch delay */
1445} 1467}
1446 1468
1447static void __init 1469static void __init
@@ -1461,17 +1483,7 @@ build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte,
1461 i_andi(p, pte, pte, 0xffc); /* load delay */ 1483 i_andi(p, pte, pte, 0xffc); /* load delay */
1462 i_addu(p, ptr, ptr, pte); 1484 i_addu(p, ptr, ptr, pte);
1463 i_lw(p, pte, 0, ptr); 1485 i_lw(p, pte, 0, ptr);
1464 i_nop(p); /* load delay */ 1486 i_tlbp(p); /* load delay */
1465 i_tlbp(p);
1466}
1467
1468static void __init
1469build_r3000_tlbchange_handler_tail(u32 **p, unsigned int tmp)
1470{
1471 i_mfc0(p, tmp, C0_EPC);
1472 i_nop(p); /* cp0 delay */
1473 i_jr(p, tmp);
1474 i_rfe(p); /* branch delay */
1475} 1487}
1476 1488
1477static void __init build_r3000_tlb_load_handler(void) 1489static void __init build_r3000_tlb_load_handler(void)
@@ -1486,10 +1498,9 @@ static void __init build_r3000_tlb_load_handler(void)
1486 1498
1487 build_r3000_tlbchange_handler_head(&p, K0, K1); 1499 build_r3000_tlbchange_handler_head(&p, K0, K1);
1488 build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl); 1500 build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl);
1501 i_nop(&p); /* load delay */
1489 build_make_valid(&p, &r, K0, K1); 1502 build_make_valid(&p, &r, K0, K1);
1490 build_r3000_pte_reload(&p, K1); 1503 build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
1491 build_r3000_tlb_write(&p, &l, &r, K0);
1492 build_r3000_tlbchange_handler_tail(&p, K0);
1493 1504
1494 l_nopage_tlbl(&l, p); 1505 l_nopage_tlbl(&l, p);
1495 i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff); 1506 i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
@@ -1506,13 +1517,10 @@ static void __init build_r3000_tlb_load_handler(void)
1506 { 1517 {
1507 int i; 1518 int i;
1508 1519
1509 for (i = 0; i < FASTPATH_SIZE; i++) 1520 for (i = 0; i < (p - handle_tlbl); i++)
1510 printk("%08x\n", handle_tlbl[i]); 1521 printk("%08x\n", handle_tlbl[i]);
1511 } 1522 }
1512#endif 1523#endif
1513
1514 flush_icache_range((unsigned long)handle_tlbl,
1515 (unsigned long)handle_tlbl + FASTPATH_SIZE * sizeof(u32));
1516} 1524}
1517 1525
1518static void __init build_r3000_tlb_store_handler(void) 1526static void __init build_r3000_tlb_store_handler(void)
@@ -1527,10 +1535,9 @@ static void __init build_r3000_tlb_store_handler(void)
1527 1535
1528 build_r3000_tlbchange_handler_head(&p, K0, K1); 1536 build_r3000_tlbchange_handler_head(&p, K0, K1);
1529 build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs); 1537 build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs);
1538 i_nop(&p); /* load delay */
1530 build_make_write(&p, &r, K0, K1); 1539 build_make_write(&p, &r, K0, K1);
1531 build_r3000_pte_reload(&p, K1); 1540 build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
1532 build_r3000_tlb_write(&p, &l, &r, K0);
1533 build_r3000_tlbchange_handler_tail(&p, K0);
1534 1541
1535 l_nopage_tlbs(&l, p); 1542 l_nopage_tlbs(&l, p);
1536 i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); 1543 i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
@@ -1547,13 +1554,10 @@ static void __init build_r3000_tlb_store_handler(void)
1547 { 1554 {
1548 int i; 1555 int i;
1549 1556
1550 for (i = 0; i < FASTPATH_SIZE; i++) 1557 for (i = 0; i < (p - handle_tlbs); i++)
1551 printk("%08x\n", handle_tlbs[i]); 1558 printk("%08x\n", handle_tlbs[i]);
1552 } 1559 }
1553#endif 1560#endif
1554
1555 flush_icache_range((unsigned long)handle_tlbs,
1556 (unsigned long)handle_tlbs + FASTPATH_SIZE * sizeof(u32));
1557} 1561}
1558 1562
1559static void __init build_r3000_tlb_modify_handler(void) 1563static void __init build_r3000_tlb_modify_handler(void)
@@ -1568,10 +1572,9 @@ static void __init build_r3000_tlb_modify_handler(void)
1568 1572
1569 build_r3000_tlbchange_handler_head(&p, K0, K1); 1573 build_r3000_tlbchange_handler_head(&p, K0, K1);
1570 build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm); 1574 build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm);
1575 i_nop(&p); /* load delay */
1571 build_make_write(&p, &r, K0, K1); 1576 build_make_write(&p, &r, K0, K1);
1572 build_r3000_pte_reload(&p, K1); 1577 build_r3000_pte_reload_tlbwi(&p, K0, K1);
1573 i_tlbwi(&p);
1574 build_r3000_tlbchange_handler_tail(&p, K0);
1575 1578
1576 l_nopage_tlbm(&l, p); 1579 l_nopage_tlbm(&l, p);
1577 i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); 1580 i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
@@ -1588,13 +1591,10 @@ static void __init build_r3000_tlb_modify_handler(void)
1588 { 1591 {
1589 int i; 1592 int i;
1590 1593
1591 for (i = 0; i < FASTPATH_SIZE; i++) 1594 for (i = 0; i < (p - handle_tlbm); i++)
1592 printk("%08x\n", handle_tlbm[i]); 1595 printk("%08x\n", handle_tlbm[i]);
1593 } 1596 }
1594#endif 1597#endif
1595
1596 flush_icache_range((unsigned long)handle_tlbm,
1597 (unsigned long)handle_tlbm + FASTPATH_SIZE * sizeof(u32));
1598} 1598}
1599 1599
1600/* 1600/*
@@ -1620,7 +1620,7 @@ build_r4000_tlbchange_handler_head(u32 **p, struct label **l,
1620#ifdef CONFIG_SMP 1620#ifdef CONFIG_SMP
1621 l_smp_pgtable_change(l, *p); 1621 l_smp_pgtable_change(l, *p);
1622# endif 1622# endif
1623 iPTE_LW(p, l, pte, 0, ptr); /* get even pte */ 1623 iPTE_LW(p, l, pte, ptr); /* get even pte */
1624 build_tlb_probe_entry(p); 1624 build_tlb_probe_entry(p);
1625} 1625}
1626 1626
@@ -1680,13 +1680,10 @@ static void __init build_r4000_tlb_load_handler(void)
1680 { 1680 {
1681 int i; 1681 int i;
1682 1682
1683 for (i = 0; i < FASTPATH_SIZE; i++) 1683 for (i = 0; i < (p - handle_tlbl); i++)
1684 printk("%08x\n", handle_tlbl[i]); 1684 printk("%08x\n", handle_tlbl[i]);
1685 } 1685 }
1686#endif 1686#endif
1687
1688 flush_icache_range((unsigned long)handle_tlbl,
1689 (unsigned long)handle_tlbl + FASTPATH_SIZE * sizeof(u32));
1690} 1687}
1691 1688
1692static void __init build_r4000_tlb_store_handler(void) 1689static void __init build_r4000_tlb_store_handler(void)
@@ -1719,13 +1716,10 @@ static void __init build_r4000_tlb_store_handler(void)
1719 { 1716 {
1720 int i; 1717 int i;
1721 1718
1722 for (i = 0; i < FASTPATH_SIZE; i++) 1719 for (i = 0; i < (p - handle_tlbs); i++)
1723 printk("%08x\n", handle_tlbs[i]); 1720 printk("%08x\n", handle_tlbs[i]);
1724 } 1721 }
1725#endif 1722#endif
1726
1727 flush_icache_range((unsigned long)handle_tlbs,
1728 (unsigned long)handle_tlbs + FASTPATH_SIZE * sizeof(u32));
1729} 1723}
1730 1724
1731static void __init build_r4000_tlb_modify_handler(void) 1725static void __init build_r4000_tlb_modify_handler(void)
@@ -1759,13 +1753,10 @@ static void __init build_r4000_tlb_modify_handler(void)
1759 { 1753 {
1760 int i; 1754 int i;
1761 1755
1762 for (i = 0; i < FASTPATH_SIZE; i++) 1756 for (i = 0; i < (p - handle_tlbm); i++)
1763 printk("%08x\n", handle_tlbm[i]); 1757 printk("%08x\n", handle_tlbm[i]);
1764 } 1758 }
1765#endif 1759#endif
1766
1767 flush_icache_range((unsigned long)handle_tlbm,
1768 (unsigned long)handle_tlbm + FASTPATH_SIZE * sizeof(u32));
1769} 1760}
1770 1761
1771void __init build_tlb_refill_handler(void) 1762void __init build_tlb_refill_handler(void)
@@ -1813,3 +1804,13 @@ void __init build_tlb_refill_handler(void)
1813 } 1804 }
1814 } 1805 }
1815} 1806}
1807
1808void __init flush_tlb_handlers(void)
1809{
1810 flush_icache_range((unsigned long)handle_tlbl,
1811 (unsigned long)handle_tlbl + sizeof(handle_tlbl));
1812 flush_icache_range((unsigned long)handle_tlbs,
1813 (unsigned long)handle_tlbs + sizeof(handle_tlbs));
1814 flush_icache_range((unsigned long)handle_tlbm,
1815 (unsigned long)handle_tlbm + sizeof(handle_tlbm));
1816}