Commit 6a8dff6a authored by Markos Chandras's avatar Markos Chandras Committed by Ralf Baechle

MIPS: tlb-r4k: Add missing HTW stop/start sequences

HTW needs to stop and start again whenever the EntryHI register
changes otherwise an inflight HTW operation might use the new
EntryHI register for updating an old entry and that could lead
to crashes or even a machine check exception. We fix this by
ensuring the HTW has stop whenever the EntryHI register is about
to change
Signed-off-by: default avatarMarkos Chandras <markos.chandras@imgtec.com>
Cc: <stable@vger.kernel.org> # v3.17+
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/8511/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 58563817
...@@ -299,6 +299,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) ...@@ -299,6 +299,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
local_irq_save(flags); local_irq_save(flags);
htw_stop();
pid = read_c0_entryhi() & ASID_MASK; pid = read_c0_entryhi() & ASID_MASK;
address &= (PAGE_MASK << 1); address &= (PAGE_MASK << 1);
write_c0_entryhi(address | pid); write_c0_entryhi(address | pid);
...@@ -346,6 +347,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) ...@@ -346,6 +347,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
tlb_write_indexed(); tlb_write_indexed();
} }
tlbw_use_hazard(); tlbw_use_hazard();
htw_start();
flush_itlb_vm(vma); flush_itlb_vm(vma);
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -422,6 +424,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, ...@@ -422,6 +424,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
local_irq_save(flags); local_irq_save(flags);
/* Save old context and create impossible VPN2 value */ /* Save old context and create impossible VPN2 value */
htw_stop();
old_ctx = read_c0_entryhi(); old_ctx = read_c0_entryhi();
old_pagemask = read_c0_pagemask(); old_pagemask = read_c0_pagemask();
wired = read_c0_wired(); wired = read_c0_wired();
...@@ -443,6 +446,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, ...@@ -443,6 +446,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
write_c0_entryhi(old_ctx); write_c0_entryhi(old_ctx);
write_c0_pagemask(old_pagemask); write_c0_pagemask(old_pagemask);
htw_start();
out: out:
local_irq_restore(flags); local_irq_restore(flags);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment