Use the page_start and page_end fields of mmu_gather to implement more precise TLB flushing. (start, end) covers the entire TLB and page table range that has been invalidated, for architectures that do not have explicit page walk cache management. page_start and page_end are just for ranges that may have TLB entries. A tlb_flush may have no pages in this range, but still requires PWC to be flushed. That is handled properly. This brings the number of tlbiel instructions required by a kernel compile from 33M to 25M, most avoided from exec->shift_arg_pages. Signed-off-by: Nicholas Piggin <npiggin@xxxxxxxxx> --- arch/powerpc/mm/tlb-radix.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c index 67a6e86d3e7e..06452ad701cf 100644 --- a/arch/powerpc/mm/tlb-radix.c +++ b/arch/powerpc/mm/tlb-radix.c @@ -853,8 +853,11 @@ void radix__tlb_flush(struct mmu_gather *tlb) else radix__flush_all_mm(mm); } else { - unsigned long start = tlb->start; - unsigned long end = tlb->end; + unsigned long start = tlb->page_start; + unsigned long end = tlb->page_end; + + if (end < start) + end = start; if (!tlb->need_flush_all) radix__flush_tlb_range_psize(mm, start, end, psize); -- 2.17.0