diff options
Diffstat (limited to 'arch/mips/mm/tlbex.c')
-rw-r--r-- | arch/mips/mm/tlbex.c | 183 |
1 files changed, 113 insertions, 70 deletions
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index afeef93f81a7..9ab0f907a52c 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
@@ -305,6 +305,17 @@ static int check_for_high_segbits __cpuinitdata; | |||
305 | 305 | ||
306 | static unsigned int kscratch_used_mask __cpuinitdata; | 306 | static unsigned int kscratch_used_mask __cpuinitdata; |
307 | 307 | ||
308 | static inline int __maybe_unused c0_kscratch(void) | ||
309 | { | ||
310 | switch (current_cpu_type()) { | ||
311 | case CPU_XLP: | ||
312 | case CPU_XLR: | ||
313 | return 22; | ||
314 | default: | ||
315 | return 31; | ||
316 | } | ||
317 | } | ||
318 | |||
308 | static int __cpuinit allocate_kscratch(void) | 319 | static int __cpuinit allocate_kscratch(void) |
309 | { | 320 | { |
310 | int r; | 321 | int r; |
@@ -334,9 +345,9 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p) | |||
334 | int smp_processor_id_sel; | 345 | int smp_processor_id_sel; |
335 | int smp_processor_id_shift; | 346 | int smp_processor_id_shift; |
336 | 347 | ||
337 | if (scratch_reg > 0) { | 348 | if (scratch_reg >= 0) { |
338 | /* Save in CPU local C0_KScratch? */ | 349 | /* Save in CPU local C0_KScratch? */ |
339 | UASM_i_MTC0(p, 1, 31, scratch_reg); | 350 | UASM_i_MTC0(p, 1, c0_kscratch(), scratch_reg); |
340 | r.r1 = K0; | 351 | r.r1 = K0; |
341 | r.r2 = K1; | 352 | r.r2 = K1; |
342 | r.r3 = 1; | 353 | r.r3 = 1; |
@@ -384,8 +395,8 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p) | |||
384 | 395 | ||
385 | static void __cpuinit build_restore_work_registers(u32 **p) | 396 | static void __cpuinit build_restore_work_registers(u32 **p) |
386 | { | 397 | { |
387 | if (scratch_reg > 0) { | 398 | if (scratch_reg >= 0) { |
388 | UASM_i_MFC0(p, 1, 31, scratch_reg); | 399 | UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); |
389 | return; | 400 | return; |
390 | } | 401 | } |
391 | /* K0 already points to save area, restore $1 and $2 */ | 402 | /* K0 already points to save area, restore $1 and $2 */ |
@@ -673,8 +684,8 @@ static __cpuinit void build_restore_pagemask(u32 **p, | |||
673 | uasm_i_mtc0(p, 0, C0_PAGEMASK); | 684 | uasm_i_mtc0(p, 0, C0_PAGEMASK); |
674 | uasm_il_b(p, r, lid); | 685 | uasm_il_b(p, r, lid); |
675 | } | 686 | } |
676 | if (scratch_reg > 0) | 687 | if (scratch_reg >= 0) |
677 | UASM_i_MFC0(p, 1, 31, scratch_reg); | 688 | UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); |
678 | else | 689 | else |
679 | UASM_i_LW(p, 1, scratchpad_offset(0), 0); | 690 | UASM_i_LW(p, 1, scratchpad_offset(0), 0); |
680 | } else { | 691 | } else { |
@@ -817,7 +828,7 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, | |||
817 | #ifdef CONFIG_MIPS_PGD_C0_CONTEXT | 828 | #ifdef CONFIG_MIPS_PGD_C0_CONTEXT |
818 | if (pgd_reg != -1) { | 829 | if (pgd_reg != -1) { |
819 | /* pgd is in pgd_reg */ | 830 | /* pgd is in pgd_reg */ |
820 | UASM_i_MFC0(p, ptr, 31, pgd_reg); | 831 | UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg); |
821 | } else { | 832 | } else { |
822 | /* | 833 | /* |
823 | * &pgd << 11 stored in CONTEXT [23..63]. | 834 | * &pgd << 11 stored in CONTEXT [23..63]. |
@@ -929,8 +940,8 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, | |||
929 | uasm_i_jr(p, ptr); | 940 | uasm_i_jr(p, ptr); |
930 | 941 | ||
931 | if (mode == refill_scratch) { | 942 | if (mode == refill_scratch) { |
932 | if (scratch_reg > 0) | 943 | if (scratch_reg >= 0) |
933 | UASM_i_MFC0(p, 1, 31, scratch_reg); | 944 | UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); |
934 | else | 945 | else |
935 | UASM_i_LW(p, 1, scratchpad_offset(0), 0); | 946 | UASM_i_LW(p, 1, scratchpad_offset(0), 0); |
936 | } else { | 947 | } else { |
@@ -961,7 +972,7 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) | |||
961 | uasm_i_srl(p, ptr, ptr, 19); | 972 | uasm_i_srl(p, ptr, ptr, 19); |
962 | #else | 973 | #else |
963 | /* | 974 | /* |
964 | * smp_processor_id() << 3 is stored in CONTEXT. | 975 | * smp_processor_id() << 2 is stored in CONTEXT. |
965 | */ | 976 | */ |
966 | uasm_i_mfc0(p, ptr, C0_CONTEXT); | 977 | uasm_i_mfc0(p, ptr, C0_CONTEXT); |
967 | UASM_i_LA_mostly(p, tmp, pgdc); | 978 | UASM_i_LA_mostly(p, tmp, pgdc); |
@@ -1096,7 +1107,7 @@ struct mips_huge_tlb_info { | |||
1096 | static struct mips_huge_tlb_info __cpuinit | 1107 | static struct mips_huge_tlb_info __cpuinit |
1097 | build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, | 1108 | build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, |
1098 | struct uasm_reloc **r, unsigned int tmp, | 1109 | struct uasm_reloc **r, unsigned int tmp, |
1099 | unsigned int ptr, int c0_scratch) | 1110 | unsigned int ptr, int c0_scratch_reg) |
1100 | { | 1111 | { |
1101 | struct mips_huge_tlb_info rv; | 1112 | struct mips_huge_tlb_info rv; |
1102 | unsigned int even, odd; | 1113 | unsigned int even, odd; |
@@ -1110,12 +1121,12 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, | |||
1110 | UASM_i_MFC0(p, tmp, C0_BADVADDR); | 1121 | UASM_i_MFC0(p, tmp, C0_BADVADDR); |
1111 | 1122 | ||
1112 | if (pgd_reg != -1) | 1123 | if (pgd_reg != -1) |
1113 | UASM_i_MFC0(p, ptr, 31, pgd_reg); | 1124 | UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg); |
1114 | else | 1125 | else |
1115 | UASM_i_MFC0(p, ptr, C0_CONTEXT); | 1126 | UASM_i_MFC0(p, ptr, C0_CONTEXT); |
1116 | 1127 | ||
1117 | if (c0_scratch >= 0) | 1128 | if (c0_scratch_reg >= 0) |
1118 | UASM_i_MTC0(p, scratch, 31, c0_scratch); | 1129 | UASM_i_MTC0(p, scratch, c0_kscratch(), c0_scratch_reg); |
1119 | else | 1130 | else |
1120 | UASM_i_SW(p, scratch, scratchpad_offset(0), 0); | 1131 | UASM_i_SW(p, scratch, scratchpad_offset(0), 0); |
1121 | 1132 | ||
@@ -1130,14 +1141,14 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, | |||
1130 | } | 1141 | } |
1131 | } else { | 1142 | } else { |
1132 | if (pgd_reg != -1) | 1143 | if (pgd_reg != -1) |
1133 | UASM_i_MFC0(p, ptr, 31, pgd_reg); | 1144 | UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg); |
1134 | else | 1145 | else |
1135 | UASM_i_MFC0(p, ptr, C0_CONTEXT); | 1146 | UASM_i_MFC0(p, ptr, C0_CONTEXT); |
1136 | 1147 | ||
1137 | UASM_i_MFC0(p, tmp, C0_BADVADDR); | 1148 | UASM_i_MFC0(p, tmp, C0_BADVADDR); |
1138 | 1149 | ||
1139 | if (c0_scratch >= 0) | 1150 | if (c0_scratch_reg >= 0) |
1140 | UASM_i_MTC0(p, scratch, 31, c0_scratch); | 1151 | UASM_i_MTC0(p, scratch, c0_kscratch(), c0_scratch_reg); |
1141 | else | 1152 | else |
1142 | UASM_i_SW(p, scratch, scratchpad_offset(0), 0); | 1153 | UASM_i_SW(p, scratch, scratchpad_offset(0), 0); |
1143 | 1154 | ||
@@ -1242,8 +1253,8 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, | |||
1242 | } | 1253 | } |
1243 | UASM_i_MTC0(p, odd, C0_ENTRYLO1); /* load it */ | 1254 | UASM_i_MTC0(p, odd, C0_ENTRYLO1); /* load it */ |
1244 | 1255 | ||
1245 | if (c0_scratch >= 0) { | 1256 | if (c0_scratch_reg >= 0) { |
1246 | UASM_i_MFC0(p, scratch, 31, c0_scratch); | 1257 | UASM_i_MFC0(p, scratch, c0_kscratch(), c0_scratch_reg); |
1247 | build_tlb_write_entry(p, l, r, tlb_random); | 1258 | build_tlb_write_entry(p, l, r, tlb_random); |
1248 | uasm_l_leave(l, *p); | 1259 | uasm_l_leave(l, *p); |
1249 | rv.restore_scratch = 1; | 1260 | rv.restore_scratch = 1; |
@@ -1286,7 +1297,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void) | |||
1286 | memset(relocs, 0, sizeof(relocs)); | 1297 | memset(relocs, 0, sizeof(relocs)); |
1287 | memset(final_handler, 0, sizeof(final_handler)); | 1298 | memset(final_handler, 0, sizeof(final_handler)); |
1288 | 1299 | ||
1289 | if ((scratch_reg > 0 || scratchpad_available()) && use_bbit_insns()) { | 1300 | if ((scratch_reg >= 0 || scratchpad_available()) && use_bbit_insns()) { |
1290 | htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1, | 1301 | htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1, |
1291 | scratch_reg); | 1302 | scratch_reg); |
1292 | vmalloc_mode = refill_scratch; | 1303 | vmalloc_mode = refill_scratch; |
@@ -1444,27 +1455,25 @@ static void __cpuinit build_r4000_tlb_refill_handler(void) | |||
1444 | dump_handler("r4000_tlb_refill", (u32 *)ebase, 64); | 1455 | dump_handler("r4000_tlb_refill", (u32 *)ebase, 64); |
1445 | } | 1456 | } |
1446 | 1457 | ||
1447 | /* | 1458 | extern u32 handle_tlbl[], handle_tlbl_end[]; |
1448 | * 128 instructions for the fastpath handler is generous and should | 1459 | extern u32 handle_tlbs[], handle_tlbs_end[]; |
1449 | * never be exceeded. | 1460 | extern u32 handle_tlbm[], handle_tlbm_end[]; |
1450 | */ | ||
1451 | #define FASTPATH_SIZE 128 | ||
1452 | 1461 | ||
1453 | u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned; | ||
1454 | u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned; | ||
1455 | u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned; | ||
1456 | #ifdef CONFIG_MIPS_PGD_C0_CONTEXT | 1462 | #ifdef CONFIG_MIPS_PGD_C0_CONTEXT |
1457 | u32 tlbmiss_handler_setup_pgd_array[16] __cacheline_aligned; | 1463 | extern u32 tlbmiss_handler_setup_pgd[], tlbmiss_handler_setup_pgd_end[]; |
1458 | 1464 | ||
1459 | static void __cpuinit build_r4000_setup_pgd(void) | 1465 | static void __cpuinit build_r4000_setup_pgd(void) |
1460 | { | 1466 | { |
1461 | const int a0 = 4; | 1467 | const int a0 = 4; |
1462 | const int a1 = 5; | 1468 | const int a1 = 5; |
1463 | u32 *p = tlbmiss_handler_setup_pgd_array; | 1469 | u32 *p = tlbmiss_handler_setup_pgd_array; |
1470 | const int tlbmiss_handler_setup_pgd_size = | ||
1471 | tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd; | ||
1464 | struct uasm_label *l = labels; | 1472 | struct uasm_label *l = labels; |
1465 | struct uasm_reloc *r = relocs; | 1473 | struct uasm_reloc *r = relocs; |
1466 | 1474 | ||
1467 | memset(tlbmiss_handler_setup_pgd_array, 0, sizeof(tlbmiss_handler_setup_pgd_array)); | 1475 | memset(tlbmiss_handler_setup_pgd, 0, tlbmiss_handler_setup_pgd_size * |
1476 | sizeof(tlbmiss_handler_setup_pgd[0])); | ||
1468 | memset(labels, 0, sizeof(labels)); | 1477 | memset(labels, 0, sizeof(labels)); |
1469 | memset(relocs, 0, sizeof(relocs)); | 1478 | memset(relocs, 0, sizeof(relocs)); |
1470 | 1479 | ||
@@ -1490,17 +1499,17 @@ static void __cpuinit build_r4000_setup_pgd(void) | |||
1490 | } else { | 1499 | } else { |
1491 | /* PGD in c0_KScratch */ | 1500 | /* PGD in c0_KScratch */ |
1492 | uasm_i_jr(&p, 31); | 1501 | uasm_i_jr(&p, 31); |
1493 | UASM_i_MTC0(&p, a0, 31, pgd_reg); | 1502 | UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg); |
1494 | } | 1503 | } |
1495 | if (p - tlbmiss_handler_setup_pgd_array > ARRAY_SIZE(tlbmiss_handler_setup_pgd_array)) | 1504 | if (p >= tlbmiss_handler_setup_pgd_end) |
1496 | panic("tlbmiss_handler_setup_pgd_array space exceeded"); | 1505 | panic("tlbmiss_handler_setup_pgd space exceeded"); |
1506 | |||
1497 | uasm_resolve_relocs(relocs, labels); | 1507 | uasm_resolve_relocs(relocs, labels); |
1498 | pr_debug("Wrote tlbmiss_handler_setup_pgd_array (%u instructions).\n", | 1508 | pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n", |
1499 | (unsigned int)(p - tlbmiss_handler_setup_pgd_array)); | 1509 | (unsigned int)(p - tlbmiss_handler_setup_pgd)); |
1500 | 1510 | ||
1501 | dump_handler("tlbmiss_handler", | 1511 | dump_handler("tlbmiss_handler", tlbmiss_handler_setup_pgd, |
1502 | tlbmiss_handler_setup_pgd_array, | 1512 | tlbmiss_handler_setup_pgd_size); |
1503 | ARRAY_SIZE(tlbmiss_handler_setup_pgd_array)); | ||
1504 | } | 1513 | } |
1505 | #endif | 1514 | #endif |
1506 | 1515 | ||
@@ -1745,10 +1754,11 @@ build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte, | |||
1745 | static void __cpuinit build_r3000_tlb_load_handler(void) | 1754 | static void __cpuinit build_r3000_tlb_load_handler(void) |
1746 | { | 1755 | { |
1747 | u32 *p = handle_tlbl; | 1756 | u32 *p = handle_tlbl; |
1757 | const int handle_tlbl_size = handle_tlbl_end - handle_tlbl; | ||
1748 | struct uasm_label *l = labels; | 1758 | struct uasm_label *l = labels; |
1749 | struct uasm_reloc *r = relocs; | 1759 | struct uasm_reloc *r = relocs; |
1750 | 1760 | ||
1751 | memset(handle_tlbl, 0, sizeof(handle_tlbl)); | 1761 | memset(handle_tlbl, 0, handle_tlbl_size * sizeof(handle_tlbl[0])); |
1752 | memset(labels, 0, sizeof(labels)); | 1762 | memset(labels, 0, sizeof(labels)); |
1753 | memset(relocs, 0, sizeof(relocs)); | 1763 | memset(relocs, 0, sizeof(relocs)); |
1754 | 1764 | ||
@@ -1762,23 +1772,24 @@ static void __cpuinit build_r3000_tlb_load_handler(void) | |||
1762 | uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff); | 1772 | uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff); |
1763 | uasm_i_nop(&p); | 1773 | uasm_i_nop(&p); |
1764 | 1774 | ||
1765 | if ((p - handle_tlbl) > FASTPATH_SIZE) | 1775 | if (p >= handle_tlbl_end) |
1766 | panic("TLB load handler fastpath space exceeded"); | 1776 | panic("TLB load handler fastpath space exceeded"); |
1767 | 1777 | ||
1768 | uasm_resolve_relocs(relocs, labels); | 1778 | uasm_resolve_relocs(relocs, labels); |
1769 | pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", | 1779 | pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", |
1770 | (unsigned int)(p - handle_tlbl)); | 1780 | (unsigned int)(p - handle_tlbl)); |
1771 | 1781 | ||
1772 | dump_handler("r3000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl)); | 1782 | dump_handler("r3000_tlb_load", handle_tlbl, handle_tlbl_size); |
1773 | } | 1783 | } |
1774 | 1784 | ||
1775 | static void __cpuinit build_r3000_tlb_store_handler(void) | 1785 | static void __cpuinit build_r3000_tlb_store_handler(void) |
1776 | { | 1786 | { |
1777 | u32 *p = handle_tlbs; | 1787 | u32 *p = handle_tlbs; |
1788 | const int handle_tlbs_size = handle_tlbs_end - handle_tlbs; | ||
1778 | struct uasm_label *l = labels; | 1789 | struct uasm_label *l = labels; |
1779 | struct uasm_reloc *r = relocs; | 1790 | struct uasm_reloc *r = relocs; |
1780 | 1791 | ||
1781 | memset(handle_tlbs, 0, sizeof(handle_tlbs)); | 1792 | memset(handle_tlbs, 0, handle_tlbs_size * sizeof(handle_tlbs[0])); |
1782 | memset(labels, 0, sizeof(labels)); | 1793 | memset(labels, 0, sizeof(labels)); |
1783 | memset(relocs, 0, sizeof(relocs)); | 1794 | memset(relocs, 0, sizeof(relocs)); |
1784 | 1795 | ||
@@ -1792,23 +1803,24 @@ static void __cpuinit build_r3000_tlb_store_handler(void) | |||
1792 | uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); | 1803 | uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); |
1793 | uasm_i_nop(&p); | 1804 | uasm_i_nop(&p); |
1794 | 1805 | ||
1795 | if ((p - handle_tlbs) > FASTPATH_SIZE) | 1806 | if (p >= handle_tlbs) |
1796 | panic("TLB store handler fastpath space exceeded"); | 1807 | panic("TLB store handler fastpath space exceeded"); |
1797 | 1808 | ||
1798 | uasm_resolve_relocs(relocs, labels); | 1809 | uasm_resolve_relocs(relocs, labels); |
1799 | pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", | 1810 | pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", |
1800 | (unsigned int)(p - handle_tlbs)); | 1811 | (unsigned int)(p - handle_tlbs)); |
1801 | 1812 | ||
1802 | dump_handler("r3000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs)); | 1813 | dump_handler("r3000_tlb_store", handle_tlbs, handle_tlbs_size); |
1803 | } | 1814 | } |
1804 | 1815 | ||
1805 | static void __cpuinit build_r3000_tlb_modify_handler(void) | 1816 | static void __cpuinit build_r3000_tlb_modify_handler(void) |
1806 | { | 1817 | { |
1807 | u32 *p = handle_tlbm; | 1818 | u32 *p = handle_tlbm; |
1819 | const int handle_tlbm_size = handle_tlbm_end - handle_tlbm; | ||
1808 | struct uasm_label *l = labels; | 1820 | struct uasm_label *l = labels; |
1809 | struct uasm_reloc *r = relocs; | 1821 | struct uasm_reloc *r = relocs; |
1810 | 1822 | ||
1811 | memset(handle_tlbm, 0, sizeof(handle_tlbm)); | 1823 | memset(handle_tlbm, 0, handle_tlbm_size * sizeof(handle_tlbm[0])); |
1812 | memset(labels, 0, sizeof(labels)); | 1824 | memset(labels, 0, sizeof(labels)); |
1813 | memset(relocs, 0, sizeof(relocs)); | 1825 | memset(relocs, 0, sizeof(relocs)); |
1814 | 1826 | ||
@@ -1822,14 +1834,14 @@ static void __cpuinit build_r3000_tlb_modify_handler(void) | |||
1822 | uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); | 1834 | uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); |
1823 | uasm_i_nop(&p); | 1835 | uasm_i_nop(&p); |
1824 | 1836 | ||
1825 | if ((p - handle_tlbm) > FASTPATH_SIZE) | 1837 | if (p >= handle_tlbm_end) |
1826 | panic("TLB modify handler fastpath space exceeded"); | 1838 | panic("TLB modify handler fastpath space exceeded"); |
1827 | 1839 | ||
1828 | uasm_resolve_relocs(relocs, labels); | 1840 | uasm_resolve_relocs(relocs, labels); |
1829 | pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", | 1841 | pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", |
1830 | (unsigned int)(p - handle_tlbm)); | 1842 | (unsigned int)(p - handle_tlbm)); |
1831 | 1843 | ||
1832 | dump_handler("r3000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm)); | 1844 | dump_handler("r3000_tlb_modify", handle_tlbm, handle_tlbm_size); |
1833 | } | 1845 | } |
1834 | #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ | 1846 | #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ |
1835 | 1847 | ||
@@ -1893,11 +1905,12 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l, | |||
1893 | static void __cpuinit build_r4000_tlb_load_handler(void) | 1905 | static void __cpuinit build_r4000_tlb_load_handler(void) |
1894 | { | 1906 | { |
1895 | u32 *p = handle_tlbl; | 1907 | u32 *p = handle_tlbl; |
1908 | const int handle_tlbl_size = handle_tlbl_end - handle_tlbl; | ||
1896 | struct uasm_label *l = labels; | 1909 | struct uasm_label *l = labels; |
1897 | struct uasm_reloc *r = relocs; | 1910 | struct uasm_reloc *r = relocs; |
1898 | struct work_registers wr; | 1911 | struct work_registers wr; |
1899 | 1912 | ||
1900 | memset(handle_tlbl, 0, sizeof(handle_tlbl)); | 1913 | memset(handle_tlbl, 0, handle_tlbl_size * sizeof(handle_tlbl[0])); |
1901 | memset(labels, 0, sizeof(labels)); | 1914 | memset(labels, 0, sizeof(labels)); |
1902 | memset(relocs, 0, sizeof(relocs)); | 1915 | memset(relocs, 0, sizeof(relocs)); |
1903 | 1916 | ||
@@ -1935,6 +1948,19 @@ static void __cpuinit build_r4000_tlb_load_handler(void) | |||
1935 | uasm_i_nop(&p); | 1948 | uasm_i_nop(&p); |
1936 | 1949 | ||
1937 | uasm_i_tlbr(&p); | 1950 | uasm_i_tlbr(&p); |
1951 | |||
1952 | switch (current_cpu_type()) { | ||
1953 | default: | ||
1954 | if (cpu_has_mips_r2) { | ||
1955 | uasm_i_ehb(&p); | ||
1956 | |||
1957 | case CPU_CAVIUM_OCTEON: | ||
1958 | case CPU_CAVIUM_OCTEON_PLUS: | ||
1959 | case CPU_CAVIUM_OCTEON2: | ||
1960 | break; | ||
1961 | } | ||
1962 | } | ||
1963 | |||
1938 | /* Examine entrylo 0 or 1 based on ptr. */ | 1964 | /* Examine entrylo 0 or 1 based on ptr. */ |
1939 | if (use_bbit_insns()) { | 1965 | if (use_bbit_insns()) { |
1940 | uasm_i_bbit0(&p, wr.r2, ilog2(sizeof(pte_t)), 8); | 1966 | uasm_i_bbit0(&p, wr.r2, ilog2(sizeof(pte_t)), 8); |
@@ -1989,6 +2015,19 @@ static void __cpuinit build_r4000_tlb_load_handler(void) | |||
1989 | uasm_i_nop(&p); | 2015 | uasm_i_nop(&p); |
1990 | 2016 | ||
1991 | uasm_i_tlbr(&p); | 2017 | uasm_i_tlbr(&p); |
2018 | |||
2019 | switch (current_cpu_type()) { | ||
2020 | default: | ||
2021 | if (cpu_has_mips_r2) { | ||
2022 | uasm_i_ehb(&p); | ||
2023 | |||
2024 | case CPU_CAVIUM_OCTEON: | ||
2025 | case CPU_CAVIUM_OCTEON_PLUS: | ||
2026 | case CPU_CAVIUM_OCTEON2: | ||
2027 | break; | ||
2028 | } | ||
2029 | } | ||
2030 | |||
1992 | /* Examine entrylo 0 or 1 based on ptr. */ | 2031 | /* Examine entrylo 0 or 1 based on ptr. */ |
1993 | if (use_bbit_insns()) { | 2032 | if (use_bbit_insns()) { |
1994 | uasm_i_bbit0(&p, wr.r2, ilog2(sizeof(pte_t)), 8); | 2033 | uasm_i_bbit0(&p, wr.r2, ilog2(sizeof(pte_t)), 8); |
@@ -2036,24 +2075,25 @@ static void __cpuinit build_r4000_tlb_load_handler(void) | |||
2036 | uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff); | 2075 | uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff); |
2037 | uasm_i_nop(&p); | 2076 | uasm_i_nop(&p); |
2038 | 2077 | ||
2039 | if ((p - handle_tlbl) > FASTPATH_SIZE) | 2078 | if (p >= handle_tlbl_end) |
2040 | panic("TLB load handler fastpath space exceeded"); | 2079 | panic("TLB load handler fastpath space exceeded"); |
2041 | 2080 | ||
2042 | uasm_resolve_relocs(relocs, labels); | 2081 | uasm_resolve_relocs(relocs, labels); |
2043 | pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", | 2082 | pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", |
2044 | (unsigned int)(p - handle_tlbl)); | 2083 | (unsigned int)(p - handle_tlbl)); |
2045 | 2084 | ||
2046 | dump_handler("r4000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl)); | 2085 | dump_handler("r4000_tlb_load", handle_tlbl, handle_tlbl_size); |
2047 | } | 2086 | } |
2048 | 2087 | ||
2049 | static void __cpuinit build_r4000_tlb_store_handler(void) | 2088 | static void __cpuinit build_r4000_tlb_store_handler(void) |
2050 | { | 2089 | { |
2051 | u32 *p = handle_tlbs; | 2090 | u32 *p = handle_tlbs; |
2091 | const int handle_tlbs_size = handle_tlbs_end - handle_tlbs; | ||
2052 | struct uasm_label *l = labels; | 2092 | struct uasm_label *l = labels; |
2053 | struct uasm_reloc *r = relocs; | 2093 | struct uasm_reloc *r = relocs; |
2054 | struct work_registers wr; | 2094 | struct work_registers wr; |
2055 | 2095 | ||
2056 | memset(handle_tlbs, 0, sizeof(handle_tlbs)); | 2096 | memset(handle_tlbs, 0, handle_tlbs_size * sizeof(handle_tlbs[0])); |
2057 | memset(labels, 0, sizeof(labels)); | 2097 | memset(labels, 0, sizeof(labels)); |
2058 | memset(relocs, 0, sizeof(relocs)); | 2098 | memset(relocs, 0, sizeof(relocs)); |
2059 | 2099 | ||
@@ -2090,24 +2130,25 @@ static void __cpuinit build_r4000_tlb_store_handler(void) | |||
2090 | uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); | 2130 | uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); |
2091 | uasm_i_nop(&p); | 2131 | uasm_i_nop(&p); |
2092 | 2132 | ||
2093 | if ((p - handle_tlbs) > FASTPATH_SIZE) | 2133 | if (p >= handle_tlbs_end) |
2094 | panic("TLB store handler fastpath space exceeded"); | 2134 | panic("TLB store handler fastpath space exceeded"); |
2095 | 2135 | ||
2096 | uasm_resolve_relocs(relocs, labels); | 2136 | uasm_resolve_relocs(relocs, labels); |
2097 | pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", | 2137 | pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", |
2098 | (unsigned int)(p - handle_tlbs)); | 2138 | (unsigned int)(p - handle_tlbs)); |
2099 | 2139 | ||
2100 | dump_handler("r4000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs)); | 2140 | dump_handler("r4000_tlb_store", handle_tlbs, handle_tlbs_size); |
2101 | } | 2141 | } |
2102 | 2142 | ||
2103 | static void __cpuinit build_r4000_tlb_modify_handler(void) | 2143 | static void __cpuinit build_r4000_tlb_modify_handler(void) |
2104 | { | 2144 | { |
2105 | u32 *p = handle_tlbm; | 2145 | u32 *p = handle_tlbm; |
2146 | const int handle_tlbm_size = handle_tlbm_end - handle_tlbm; | ||
2106 | struct uasm_label *l = labels; | 2147 | struct uasm_label *l = labels; |
2107 | struct uasm_reloc *r = relocs; | 2148 | struct uasm_reloc *r = relocs; |
2108 | struct work_registers wr; | 2149 | struct work_registers wr; |
2109 | 2150 | ||
2110 | memset(handle_tlbm, 0, sizeof(handle_tlbm)); | 2151 | memset(handle_tlbm, 0, handle_tlbm_size * sizeof(handle_tlbm[0])); |
2111 | memset(labels, 0, sizeof(labels)); | 2152 | memset(labels, 0, sizeof(labels)); |
2112 | memset(relocs, 0, sizeof(relocs)); | 2153 | memset(relocs, 0, sizeof(relocs)); |
2113 | 2154 | ||
@@ -2145,14 +2186,28 @@ static void __cpuinit build_r4000_tlb_modify_handler(void) | |||
2145 | uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); | 2186 | uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); |
2146 | uasm_i_nop(&p); | 2187 | uasm_i_nop(&p); |
2147 | 2188 | ||
2148 | if ((p - handle_tlbm) > FASTPATH_SIZE) | 2189 | if (p >= handle_tlbm_end) |
2149 | panic("TLB modify handler fastpath space exceeded"); | 2190 | panic("TLB modify handler fastpath space exceeded"); |
2150 | 2191 | ||
2151 | uasm_resolve_relocs(relocs, labels); | 2192 | uasm_resolve_relocs(relocs, labels); |
2152 | pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", | 2193 | pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", |
2153 | (unsigned int)(p - handle_tlbm)); | 2194 | (unsigned int)(p - handle_tlbm)); |
2154 | 2195 | ||
2155 | dump_handler("r4000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm)); | 2196 | dump_handler("r4000_tlb_modify", handle_tlbm, handle_tlbm_size); |
2197 | } | ||
2198 | |||
2199 | static void __cpuinit flush_tlb_handlers(void) | ||
2200 | { | ||
2201 | local_flush_icache_range((unsigned long)handle_tlbl, | ||
2202 | (unsigned long)handle_tlbl_end); | ||
2203 | local_flush_icache_range((unsigned long)handle_tlbs, | ||
2204 | (unsigned long)handle_tlbs_end); | ||
2205 | local_flush_icache_range((unsigned long)handle_tlbm, | ||
2206 | (unsigned long)handle_tlbm_end); | ||
2207 | #ifdef CONFIG_MIPS_PGD_C0_CONTEXT | ||
2208 | local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd, | ||
2209 | (unsigned long)tlbmiss_handler_setup_pgd_end); | ||
2210 | #endif | ||
2156 | } | 2211 | } |
2157 | 2212 | ||
2158 | void __cpuinit build_tlb_refill_handler(void) | 2213 | void __cpuinit build_tlb_refill_handler(void) |
@@ -2187,6 +2242,7 @@ void __cpuinit build_tlb_refill_handler(void) | |||
2187 | build_r3000_tlb_load_handler(); | 2242 | build_r3000_tlb_load_handler(); |
2188 | build_r3000_tlb_store_handler(); | 2243 | build_r3000_tlb_store_handler(); |
2189 | build_r3000_tlb_modify_handler(); | 2244 | build_r3000_tlb_modify_handler(); |
2245 | flush_tlb_handlers(); | ||
2190 | run_once++; | 2246 | run_once++; |
2191 | } | 2247 | } |
2192 | #else | 2248 | #else |
@@ -2214,23 +2270,10 @@ void __cpuinit build_tlb_refill_handler(void) | |||
2214 | build_r4000_tlb_modify_handler(); | 2270 | build_r4000_tlb_modify_handler(); |
2215 | if (!cpu_has_local_ebase) | 2271 | if (!cpu_has_local_ebase) |
2216 | build_r4000_tlb_refill_handler(); | 2272 | build_r4000_tlb_refill_handler(); |
2273 | flush_tlb_handlers(); | ||
2217 | run_once++; | 2274 | run_once++; |
2218 | } | 2275 | } |
2219 | if (cpu_has_local_ebase) | 2276 | if (cpu_has_local_ebase) |
2220 | build_r4000_tlb_refill_handler(); | 2277 | build_r4000_tlb_refill_handler(); |
2221 | } | 2278 | } |
2222 | } | 2279 | } |
2223 | |||
2224 | void __cpuinit flush_tlb_handlers(void) | ||
2225 | { | ||
2226 | local_flush_icache_range((unsigned long)handle_tlbl, | ||
2227 | (unsigned long)handle_tlbl + sizeof(handle_tlbl)); | ||
2228 | local_flush_icache_range((unsigned long)handle_tlbs, | ||
2229 | (unsigned long)handle_tlbs + sizeof(handle_tlbs)); | ||
2230 | local_flush_icache_range((unsigned long)handle_tlbm, | ||
2231 | (unsigned long)handle_tlbm + sizeof(handle_tlbm)); | ||
2232 | #ifdef CONFIG_MIPS_PGD_C0_CONTEXT | ||
2233 | local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd_array, | ||
2234 | (unsigned long)tlbmiss_handler_setup_pgd_array + sizeof(handle_tlbm)); | ||
2235 | #endif | ||
2236 | } | ||