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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <ddaney.cavm@xxxxxxxxx> wrote:
> On 01/26/2016 05:26 AM, Huacai Chen wrote:
>>
>> 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?
>
>
>> 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 <chenhc@xxxxxxxxxx>
>> ---
>>   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 */
>>
>
>




[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux