aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2005-06-13 16:24:00 -0400
committerRalf Baechle <ralf@linux-mips.org>2005-10-29 14:31:22 -0400
commitfded2e508a1d3c26ab477ab3b98f13274d4359ba (patch)
treea720d2799e7ea32cb96d664bc55b2aa149b77550
parentd925c262dd8bee2202b0d1b85ce0b332f48dd34b (diff)
Optimize R3k TLB Load/Store/Modified handlers, by scheduling
delay slots properly and avoiding an unnecessary jump to a jump. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/mm/tlbex.c70
1 files changed, 30 insertions, 40 deletions
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 68d24b80053b..48546d18a5a3 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>
@@ -410,7 +411,6 @@ enum label_id {
410 label_nopage_tlbm, 411 label_nopage_tlbm,
411 label_smp_pgtable_change, 412 label_smp_pgtable_change,
412 label_r3000_write_probe_fail, 413 label_r3000_write_probe_fail,
413 label_r3000_write_probe_ok
414}; 414};
415 415
416struct label { 416struct label {
@@ -443,7 +443,6 @@ L_LA(_nopage_tlbs)
443L_LA(_nopage_tlbm) 443L_LA(_nopage_tlbm)
444L_LA(_smp_pgtable_change) 444L_LA(_smp_pgtable_change)
445L_LA(_r3000_write_probe_fail) 445L_LA(_r3000_write_probe_fail)
446L_LA(_r3000_write_probe_ok)
447 446
448/* convenience macros for instructions */ 447/* convenience macros for instructions */
449#ifdef CONFIG_64BIT 448#ifdef CONFIG_64BIT
@@ -1414,34 +1413,41 @@ build_pte_modifiable(u32 **p, struct label **l, struct reloc **r,
1414 * R3000 style TLB load/store/modify handlers. 1413 * R3000 style TLB load/store/modify handlers.
1415 */ 1414 */
1416 1415
1417/* This places the pte in the page table at PTR into ENTRYLO0. */ 1416/*
1417 * This places the pte into ENTRYLO0 and writes it with tlbwi.
1418 * Then it returns.
1419 */
1418static void __init 1420static void __init
1419build_r3000_pte_reload(u32 **p, unsigned int ptr) 1421build_r3000_pte_reload_tlbwi(u32 **p, unsigned int pte, unsigned int tmp)
1420{ 1422{
1421 i_lw(p, ptr, 0, ptr); 1423 i_mtc0(p, pte, C0_ENTRYLO0); /* cp0 delay */
1422 i_nop(p); /* load delay */ 1424 i_mfc0(p, tmp, C0_EPC); /* cp0 delay */
1423 i_mtc0(p, ptr, C0_ENTRYLO0); 1425 i_tlbwi(p);
1424 i_nop(p); /* cp0 delay */ 1426 i_jr(p, tmp);
1427 i_rfe(p); /* branch delay */
1425} 1428}
1426 1429
1427/* 1430/*
1428 * The index register may have the probe fail bit set, 1431 * This places the pte into ENTRYLO0 and writes it with tlbwi
1429 * because we would trap on access kseg2, i.e. without refill. 1432 * or tlbwr as appropriate. This is because the index register
1433 * may have the probe fail bit set as a result of a trap on a
1434 * kseg2 access, i.e. without refill. Then it returns.
1430 */ 1435 */
1431static void __init 1436static void __init
1432build_r3000_tlb_write(u32 **p, struct label **l, struct reloc **r, 1437build_r3000_tlb_reload_write(u32 **p, struct label **l, struct reloc **r,
1433 unsigned int tmp) 1438 unsigned int pte, unsigned int tmp)
1434{ 1439{
1435 i_mfc0(p, tmp, C0_INDEX); 1440 i_mfc0(p, tmp, C0_INDEX);
1436 i_nop(p); /* cp0 delay */ 1441 i_mtc0(p, pte, C0_ENTRYLO0); /* cp0 delay */
1437 il_bltz(p, r, tmp, label_r3000_write_probe_fail); 1442 il_bltz(p, r, tmp, label_r3000_write_probe_fail); /* cp0 delay */
1438 i_nop(p); /* branch delay */ 1443 i_mfc0(p, tmp, C0_EPC); /* branch delay */
1439 i_tlbwi(p); 1444 i_tlbwi(p); /* cp0 delay */
1440 il_b(p, r, label_r3000_write_probe_ok); 1445 i_jr(p, tmp);
1441 i_nop(p); /* branch delay */ 1446 i_rfe(p); /* branch delay */
1442 l_r3000_write_probe_fail(l, *p); 1447 l_r3000_write_probe_fail(l, *p);
1443 i_tlbwr(p); 1448 i_tlbwr(p); /* cp0 delay */
1444 l_r3000_write_probe_ok(l, *p); 1449 i_jr(p, tmp);
1450 i_rfe(p); /* branch delay */
1445} 1451}
1446 1452
1447static void __init 1453static void __init
@@ -1461,17 +1467,7 @@ build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte,
1461 i_andi(p, pte, pte, 0xffc); /* load delay */ 1467 i_andi(p, pte, pte, 0xffc); /* load delay */
1462 i_addu(p, ptr, ptr, pte); 1468 i_addu(p, ptr, ptr, pte);
1463 i_lw(p, pte, 0, ptr); 1469 i_lw(p, pte, 0, ptr);
1464 i_nop(p); /* load delay */ 1470 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} 1471}
1476 1472
1477static void __init build_r3000_tlb_load_handler(void) 1473static void __init build_r3000_tlb_load_handler(void)
@@ -1488,9 +1484,7 @@ static void __init build_r3000_tlb_load_handler(void)
1488 build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl); 1484 build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl);
1489 i_nop(&p); /* load delay */ 1485 i_nop(&p); /* load delay */
1490 build_make_valid(&p, &r, K0, K1); 1486 build_make_valid(&p, &r, K0, K1);
1491 build_r3000_pte_reload(&p, K1); 1487 build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
1492 build_r3000_tlb_write(&p, &l, &r, K0);
1493 build_r3000_tlbchange_handler_tail(&p, K0);
1494 1488
1495 l_nopage_tlbl(&l, p); 1489 l_nopage_tlbl(&l, p);
1496 i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff); 1490 i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
@@ -1530,9 +1524,7 @@ static void __init build_r3000_tlb_store_handler(void)
1530 build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs); 1524 build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs);
1531 i_nop(&p); /* load delay */ 1525 i_nop(&p); /* load delay */
1532 build_make_write(&p, &r, K0, K1); 1526 build_make_write(&p, &r, K0, K1);
1533 build_r3000_pte_reload(&p, K1); 1527 build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
1534 build_r3000_tlb_write(&p, &l, &r, K0);
1535 build_r3000_tlbchange_handler_tail(&p, K0);
1536 1528
1537 l_nopage_tlbs(&l, p); 1529 l_nopage_tlbs(&l, p);
1538 i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); 1530 i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
@@ -1572,9 +1564,7 @@ static void __init build_r3000_tlb_modify_handler(void)
1572 build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm); 1564 build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm);
1573 i_nop(&p); /* load delay */ 1565 i_nop(&p); /* load delay */
1574 build_make_write(&p, &r, K0, K1); 1566 build_make_write(&p, &r, K0, K1);
1575 build_r3000_pte_reload(&p, K1); 1567 build_r3000_pte_reload_tlbwi(&p, K0, K1);
1576 i_tlbwi(&p);
1577 build_r3000_tlbchange_handler_tail(&p, K0);
1578 1568
1579 l_nopage_tlbm(&l, p); 1569 l_nopage_tlbm(&l, p);
1580 i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); 1570 i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);