aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mm/tlbex.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/mm/tlbex.c')
-rw-r--r--arch/mips/mm/tlbex.c119
1 files changed, 90 insertions, 29 deletions
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 0bb4c3b89c78..883cf76fb2bd 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -65,6 +65,18 @@ static inline int __maybe_unused r10000_llsc_war(void)
65 return R10000_LLSC_WAR; 65 return R10000_LLSC_WAR;
66} 66}
67 67
68static int use_bbit_insns(void)
69{
70 switch (current_cpu_type()) {
71 case CPU_CAVIUM_OCTEON:
72 case CPU_CAVIUM_OCTEON_PLUS:
73 case CPU_CAVIUM_OCTEON2:
74 return 1;
75 default:
76 return 0;
77 }
78}
79
68/* 80/*
69 * Found by experiment: At least some revisions of the 4kc throw under 81 * Found by experiment: At least some revisions of the 4kc throw under
70 * some circumstances a machine check exception, triggered by invalid 82 * some circumstances a machine check exception, triggered by invalid
@@ -511,8 +523,12 @@ build_is_huge_pte(u32 **p, struct uasm_reloc **r, unsigned int tmp,
511 unsigned int pmd, int lid) 523 unsigned int pmd, int lid)
512{ 524{
513 UASM_i_LW(p, tmp, 0, pmd); 525 UASM_i_LW(p, tmp, 0, pmd);
514 uasm_i_andi(p, tmp, tmp, _PAGE_HUGE); 526 if (use_bbit_insns()) {
515 uasm_il_bnez(p, r, tmp, lid); 527 uasm_il_bbit1(p, r, tmp, ilog2(_PAGE_HUGE), lid);
528 } else {
529 uasm_i_andi(p, tmp, tmp, _PAGE_HUGE);
530 uasm_il_bnez(p, r, tmp, lid);
531 }
516} 532}
517 533
518static __cpuinit void build_huge_update_entries(u32 **p, 534static __cpuinit void build_huge_update_entries(u32 **p,
@@ -1187,14 +1203,20 @@ build_pte_present(u32 **p, struct uasm_reloc **r,
1187 unsigned int pte, unsigned int ptr, enum label_id lid) 1203 unsigned int pte, unsigned int ptr, enum label_id lid)
1188{ 1204{
1189 if (kernel_uses_smartmips_rixi) { 1205 if (kernel_uses_smartmips_rixi) {
1190 uasm_i_andi(p, pte, pte, _PAGE_PRESENT); 1206 if (use_bbit_insns()) {
1191 uasm_il_beqz(p, r, pte, lid); 1207 uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid);
1208 uasm_i_nop(p);
1209 } else {
1210 uasm_i_andi(p, pte, pte, _PAGE_PRESENT);
1211 uasm_il_beqz(p, r, pte, lid);
1212 iPTE_LW(p, pte, ptr);
1213 }
1192 } else { 1214 } else {
1193 uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ); 1215 uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
1194 uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ); 1216 uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
1195 uasm_il_bnez(p, r, pte, lid); 1217 uasm_il_bnez(p, r, pte, lid);
1218 iPTE_LW(p, pte, ptr);
1196 } 1219 }
1197 iPTE_LW(p, pte, ptr);
1198} 1220}
1199 1221
1200/* Make PTE valid, store result in PTR. */ 1222/* Make PTE valid, store result in PTR. */
@@ -1215,10 +1237,17 @@ static void __cpuinit
1215build_pte_writable(u32 **p, struct uasm_reloc **r, 1237build_pte_writable(u32 **p, struct uasm_reloc **r,
1216 unsigned int pte, unsigned int ptr, enum label_id lid) 1238 unsigned int pte, unsigned int ptr, enum label_id lid)
1217{ 1239{
1218 uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE); 1240 if (use_bbit_insns()) {
1219 uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE); 1241 uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid);
1220 uasm_il_bnez(p, r, pte, lid); 1242 uasm_i_nop(p);
1221 iPTE_LW(p, pte, ptr); 1243 uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid);
1244 uasm_i_nop(p);
1245 } else {
1246 uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
1247 uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
1248 uasm_il_bnez(p, r, pte, lid);
1249 iPTE_LW(p, pte, ptr);
1250 }
1222} 1251}
1223 1252
1224/* Make PTE writable, update software status bits as well, then store 1253/* Make PTE writable, update software status bits as well, then store
@@ -1242,9 +1271,14 @@ static void __cpuinit
1242build_pte_modifiable(u32 **p, struct uasm_reloc **r, 1271build_pte_modifiable(u32 **p, struct uasm_reloc **r,
1243 unsigned int pte, unsigned int ptr, enum label_id lid) 1272 unsigned int pte, unsigned int ptr, enum label_id lid)
1244{ 1273{
1245 uasm_i_andi(p, pte, pte, _PAGE_WRITE); 1274 if (use_bbit_insns()) {
1246 uasm_il_beqz(p, r, pte, lid); 1275 uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid);
1247 iPTE_LW(p, pte, ptr); 1276 uasm_i_nop(p);
1277 } else {
1278 uasm_i_andi(p, pte, pte, _PAGE_WRITE);
1279 uasm_il_beqz(p, r, pte, lid);
1280 iPTE_LW(p, pte, ptr);
1281 }
1248} 1282}
1249 1283
1250#ifndef CONFIG_MIPS_PGD_C0_CONTEXT 1284#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
@@ -1491,14 +1525,23 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
1491 * If the page is not _PAGE_VALID, RI or XI could not 1525 * If the page is not _PAGE_VALID, RI or XI could not
1492 * have triggered it. Skip the expensive test.. 1526 * have triggered it. Skip the expensive test..
1493 */ 1527 */
1494 uasm_i_andi(&p, K0, K0, _PAGE_VALID); 1528 if (use_bbit_insns()) {
1495 uasm_il_beqz(&p, &r, K0, label_tlbl_goaround1); 1529 uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID),
1530 label_tlbl_goaround1);
1531 } else {
1532 uasm_i_andi(&p, K0, K0, _PAGE_VALID);
1533 uasm_il_beqz(&p, &r, K0, label_tlbl_goaround1);
1534 }
1496 uasm_i_nop(&p); 1535 uasm_i_nop(&p);
1497 1536
1498 uasm_i_tlbr(&p); 1537 uasm_i_tlbr(&p);
1499 /* Examine entrylo 0 or 1 based on ptr. */ 1538 /* Examine entrylo 0 or 1 based on ptr. */
1500 uasm_i_andi(&p, K0, K1, sizeof(pte_t)); 1539 if (use_bbit_insns()) {
1501 uasm_i_beqz(&p, K0, 8); 1540 uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8);
1541 } else {
1542 uasm_i_andi(&p, K0, K1, sizeof(pte_t));
1543 uasm_i_beqz(&p, K0, 8);
1544 }
1502 1545
1503 UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/ 1546 UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/
1504 UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */ 1547 UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */
@@ -1506,12 +1549,18 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
1506 * If the entryLo (now in K0) is valid (bit 1), RI or 1549 * If the entryLo (now in K0) is valid (bit 1), RI or
1507 * XI must have triggered it. 1550 * XI must have triggered it.
1508 */ 1551 */
1509 uasm_i_andi(&p, K0, K0, 2); 1552 if (use_bbit_insns()) {
1510 uasm_il_bnez(&p, &r, K0, label_nopage_tlbl); 1553 uasm_il_bbit1(&p, &r, K0, 1, label_nopage_tlbl);
1511 1554 /* Reload the PTE value */
1512 uasm_l_tlbl_goaround1(&l, p); 1555 iPTE_LW(&p, K0, K1);
1513 /* Reload the PTE value */ 1556 uasm_l_tlbl_goaround1(&l, p);
1514 iPTE_LW(&p, K0, K1); 1557 } else {
1558 uasm_i_andi(&p, K0, K0, 2);
1559 uasm_il_bnez(&p, &r, K0, label_nopage_tlbl);
1560 uasm_l_tlbl_goaround1(&l, p);
1561 /* Reload the PTE value */
1562 iPTE_LW(&p, K0, K1);
1563 }
1515 } 1564 }
1516 build_make_valid(&p, &r, K0, K1); 1565 build_make_valid(&p, &r, K0, K1);
1517 build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); 1566 build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
@@ -1531,23 +1580,35 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
1531 * If the page is not _PAGE_VALID, RI or XI could not 1580 * If the page is not _PAGE_VALID, RI or XI could not
1532 * have triggered it. Skip the expensive test.. 1581 * have triggered it. Skip the expensive test..
1533 */ 1582 */
1534 uasm_i_andi(&p, K0, K0, _PAGE_VALID); 1583 if (use_bbit_insns()) {
1535 uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2); 1584 uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID),
1585 label_tlbl_goaround2);
1586 } else {
1587 uasm_i_andi(&p, K0, K0, _PAGE_VALID);
1588 uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
1589 }
1536 uasm_i_nop(&p); 1590 uasm_i_nop(&p);
1537 1591
1538 uasm_i_tlbr(&p); 1592 uasm_i_tlbr(&p);
1539 /* Examine entrylo 0 or 1 based on ptr. */ 1593 /* Examine entrylo 0 or 1 based on ptr. */
1540 uasm_i_andi(&p, K0, K1, sizeof(pte_t)); 1594 if (use_bbit_insns()) {
1541 uasm_i_beqz(&p, K0, 8); 1595 uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8);
1542 1596 } else {
1597 uasm_i_andi(&p, K0, K1, sizeof(pte_t));
1598 uasm_i_beqz(&p, K0, 8);
1599 }
1543 UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/ 1600 UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/
1544 UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */ 1601 UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */
1545 /* 1602 /*
1546 * If the entryLo (now in K0) is valid (bit 1), RI or 1603 * If the entryLo (now in K0) is valid (bit 1), RI or
1547 * XI must have triggered it. 1604 * XI must have triggered it.
1548 */ 1605 */
1549 uasm_i_andi(&p, K0, K0, 2); 1606 if (use_bbit_insns()) {
1550 uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2); 1607 uasm_il_bbit0(&p, &r, K0, 1, label_tlbl_goaround2);
1608 } else {
1609 uasm_i_andi(&p, K0, K0, 2);
1610 uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
1611 }
1551 /* Reload the PTE value */ 1612 /* Reload the PTE value */
1552 iPTE_LW(&p, K0, K1); 1613 iPTE_LW(&p, K0, K1);
1553 1614