summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkos Chandras <markos.chandras@imgtec.com>2014-11-17 09:31:07 +0000
committerRalf Baechle <ralf@linux-mips.org>2014-11-19 18:22:08 +0100
commit6a8dff6ab16c903b0d8ef5fbf21543f39bf5d675 (patch)
tree3faa8cc35a0550e326af511bce32ae69013b4830
parent58563817cfed0432e9a54476d5fc6c3aeba475e4 (diff)
downloadlinux-6a8dff6ab16c903b0d8ef5fbf21543f39bf5d675.tar.gz
linux-6a8dff6ab16c903b0d8ef5fbf21543f39bf5d675.tar.bz2
linux-6a8dff6ab16c903b0d8ef5fbf21543f39bf5d675.zip
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: Markos 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: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/mm/tlb-r4k.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index fa6ebd4bc9e9..c3917e251f59 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -299,6 +299,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
local_irq_save(flags);
+ htw_stop();
pid = read_c0_entryhi() & ASID_MASK;
address &= (PAGE_MASK << 1);
write_c0_entryhi(address | pid);
@@ -346,6 +347,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
tlb_write_indexed();
}
tlbw_use_hazard();
+ htw_start();
flush_itlb_vm(vma);
local_irq_restore(flags);
}
@@ -422,6 +424,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
local_irq_save(flags);
/* Save old context and create impossible VPN2 value */
+ htw_stop();
old_ctx = read_c0_entryhi();
old_pagemask = read_c0_pagemask();
wired = read_c0_wired();
@@ -443,6 +446,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
write_c0_entryhi(old_ctx);
write_c0_pagemask(old_pagemask);
+ htw_start();
out:
local_irq_restore(flags);
return ret;