Thread (19 messages) 19 messages, 4 authors, 2016-01-28

Re: [PATCH 4/6] MIPS: tlbex: Fix bugs in tlbchange handler

From: Huacai Chen <hidden>
Date: 2016-01-27 04:54:05

When unaligned access triggered, do_ade() will access user address
with EXL=1, and that may trigger tlb refill.

Huacai

On Wed, Jan 27, 2016 at 5:15 AM, David Daney [off-list ref] wrote:
On 01/26/2016 05:26 AM, Huacai Chen wrote:
quoted
If a tlb miss triggered when EXL=1,

How is that possible?  The exception handlers are not in mapped memory, and
we clear EXL very early in the exception handlers.

In valid code, how are you getting TLB related exceptions when EXL=1?

quoted
tlb refill exception is treated as
tlb invalid exception, so tlbp may fails. In this situation, CP0_Index
register doesn't contain a valid value. This may not be a problem for
VTLB since it is fully-associative. However, FTLB is set-associative so
not every tlb entry is valid for a specific address. Thus, we should
use tlbwr instead of tlbwi when tlbp fails.

There is a similar case for huge page, so build_huge_tlb_write_entry()
is also modified. If wmode != tlb_random, that means the caller is tlb
invalid handler, we should select tlbr/tlbi depend on the tlbp result.

Signed-off-by: Huacai Chen <redacted>
---
  arch/mips/mm/tlbex.c | 31 ++++++++++++++++++++++++++++++-
  1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index d0975cd..da68ffb 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -173,7 +173,10 @@ enum label_id {
        label_large_segbits_fault,
  #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        label_tlb_huge_update,
+       label_tail_huge_miss,
+       label_tail_huge_done,
  #endif
+       label_tail_miss,
  };

  UASM_L_LA(_second_part)
@@ -192,7 +195,10 @@ UASM_L_LA(_r3000_write_probe_fail)
  UASM_L_LA(_large_segbits_fault)
  #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
  UASM_L_LA(_tlb_huge_update)
+UASM_L_LA(_tail_huge_miss)
+UASM_L_LA(_tail_huge_done)
  #endif
+UASM_L_LA(_tail_miss)

  static int hazard_instance;
@@ -706,8 +712,24 @@ static void build_huge_tlb_write_entry(u32 **p,
struct uasm_label **l,
        uasm_i_ori(p, tmp, tmp, PM_HUGE_MASK & 0xffff);
        uasm_i_mtc0(p, tmp, C0_PAGEMASK);

-       build_tlb_write_entry(p, l, r, wmode);
+       if (wmode == tlb_random) { /* Caller is TLB Refill Handler */
+               build_tlb_write_entry(p, l, r, wmode);
+               build_restore_pagemask(p, r, tmp, label_leave,
restore_scratch);
+               return;
+       }
+
+       /* Caller is TLB Load/Store/Modify Handler */
+       uasm_i_mfc0(p, tmp, C0_INDEX);
+       uasm_il_bltz(p, r, tmp, label_tail_huge_miss);
+       uasm_i_nop(p);
+       build_tlb_write_entry(p, l, r, tlb_indexed);
+       uasm_il_b(p, r, label_tail_huge_done);
+       uasm_i_nop(p);
+
+       uasm_l_tail_huge_miss(l, *p);
+       build_tlb_write_entry(p, l, r, tlb_random);

+       uasm_l_tail_huge_done(l, *p);
        build_restore_pagemask(p, r, tmp, label_leave, restore_scratch);
  }
@@ -2026,7 +2048,14 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct
uasm_label **l,
        uasm_i_ori(p, ptr, ptr, sizeof(pte_t));
        uasm_i_xori(p, ptr, ptr, sizeof(pte_t));
        build_update_entries(p, tmp, ptr);
+       uasm_i_mfc0(p, ptr, C0_INDEX);
+       uasm_il_bltz(p, r, ptr, label_tail_miss);
+       uasm_i_nop(p);
        build_tlb_write_entry(p, l, r, tlb_indexed);
+       uasm_il_b(p, r, label_leave);
+       uasm_i_nop(p);
+       uasm_l_tail_miss(l, *p);
+       build_tlb_write_entry(p, l, r, tlb_random);
        uasm_l_leave(l, *p);
        build_restore_work_registers(p);
        uasm_i_eret(p); /* return from trap */
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help