summaryrefslogtreecommitdiff
path: root/arch/powerpc/mm/tlb-radix.c
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2017-10-24 16:06:54 +0300
committerMichael Ellerman <mpe@ellerman.id.au>2017-11-06 08:48:10 +0300
commit30b49ec798f0984b905fd94d1957d62530f08578 (patch)
treed54f99c79fb2ec242b8af62b87405fe550db0683 /arch/powerpc/mm/tlb-radix.c
parentdffe8449c5dd63ff18b47709de75553586582cd8 (diff)
downloadlinux-30b49ec798f0984b905fd94d1957d62530f08578.tar.xz
powerpc/64s/radix: Fix process table entry cache invalidation
According to the architecture, the process table entry cache must be flushed with tlbie RIC=2. Currently the process table entry is set to invalid right before the PID is returned to the allocator, with no invalidation. This works on existing implementations that are known to not cache the process table entry for any except the current PIDR. It is architecturally correct and cleaner to invalidate with RIC=2 after clearing the process table entry and before the PID is returned to the allocator. This can be done in arch_exit_mmap that runs before the final flush, and to ensure the final flush (fullmm) is always a RIC=2 variant. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/mm/tlb-radix.c')
-rw-r--r--arch/powerpc/mm/tlb-radix.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c
index 67191fe63283..63e277b6e60c 100644
--- a/arch/powerpc/mm/tlb-radix.c
+++ b/arch/powerpc/mm/tlb-radix.c
@@ -298,10 +298,14 @@ void radix__tlb_flush(struct mmu_gather *tlb)
psize = radix_get_mmu_psize(page_size);
/*
* if page size is not something we understand, do a full mm flush
+ *
+ * A "fullmm" flush must always do a flush_all_mm (RIC=2) flush
+ * that flushes the process table entry cache upon process teardown.
+ * See the comment for radix in arch_exit_mmap().
*/
if (psize != -1 && !tlb->fullmm && !tlb->need_flush_all)
radix__flush_tlb_range_psize(mm, tlb->start, tlb->end, psize);
- else if (tlb->need_flush_all) {
+ else if (tlb->fullmm || tlb->need_flush_all) {
tlb->need_flush_all = 0;
radix__flush_all_mm(mm);
} else