aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/mm/tlb-radix.c96
1 files changed, 75 insertions, 21 deletions
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c
index 67a6e86d3e7e..a734e486664d 100644
--- a/arch/powerpc/mm/tlb-radix.c
+++ b/arch/powerpc/mm/tlb-radix.c
@@ -689,22 +689,17 @@ EXPORT_SYMBOL(radix__flush_tlb_kernel_range);
689static unsigned long tlb_single_page_flush_ceiling __read_mostly = 33; 689static unsigned long tlb_single_page_flush_ceiling __read_mostly = 33;
690static unsigned long tlb_local_single_page_flush_ceiling __read_mostly = POWER9_TLB_SETS_RADIX * 2; 690static unsigned long tlb_local_single_page_flush_ceiling __read_mostly = POWER9_TLB_SETS_RADIX * 2;
691 691
692void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 692static inline void __radix__flush_tlb_range(struct mm_struct *mm,
693 unsigned long end) 693 unsigned long start, unsigned long end,
694 bool flush_all_sizes)
694 695
695{ 696{
696 struct mm_struct *mm = vma->vm_mm;
697 unsigned long pid; 697 unsigned long pid;
698 unsigned int page_shift = mmu_psize_defs[mmu_virtual_psize].shift; 698 unsigned int page_shift = mmu_psize_defs[mmu_virtual_psize].shift;
699 unsigned long page_size = 1UL << page_shift; 699 unsigned long page_size = 1UL << page_shift;
700 unsigned long nr_pages = (end - start) >> page_shift; 700 unsigned long nr_pages = (end - start) >> page_shift;
701 bool local, full; 701 bool local, full;
702 702
703#ifdef CONFIG_HUGETLB_PAGE
704 if (is_vm_hugetlb_page(vma))
705 return radix__flush_hugetlb_tlb_range(vma, start, end);
706#endif
707
708 pid = mm->context.id; 703 pid = mm->context.id;
709 if (unlikely(pid == MMU_NO_CONTEXT)) 704 if (unlikely(pid == MMU_NO_CONTEXT))
710 return; 705 return;
@@ -738,37 +733,64 @@ is_local:
738 _tlbie_pid(pid, RIC_FLUSH_TLB); 733 _tlbie_pid(pid, RIC_FLUSH_TLB);
739 } 734 }
740 } else { 735 } else {
741 bool hflush = false; 736 bool hflush = flush_all_sizes;
737 bool gflush = flush_all_sizes;
742 unsigned long hstart, hend; 738 unsigned long hstart, hend;
739 unsigned long gstart, gend;
743 740
744#ifdef CONFIG_TRANSPARENT_HUGEPAGE 741 if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
745 hstart = (start + HPAGE_PMD_SIZE - 1) >> HPAGE_PMD_SHIFT;
746 hend = end >> HPAGE_PMD_SHIFT;
747 if (hstart < hend) {
748 hstart <<= HPAGE_PMD_SHIFT;
749 hend <<= HPAGE_PMD_SHIFT;
750 hflush = true; 742 hflush = true;
743
744 if (hflush) {
745 hstart = (start + PMD_SIZE - 1) & PMD_MASK;
746 hend = end & PMD_MASK;
747 if (hstart == hend)
748 hflush = false;
749 }
750
751 if (gflush) {
752 gstart = (start + PUD_SIZE - 1) & PUD_MASK;
753 gend = end & PUD_MASK;
754 if (gstart == gend)
755 gflush = false;
751 } 756 }
752#endif
753 757
754 asm volatile("ptesync": : :"memory"); 758 asm volatile("ptesync": : :"memory");
755 if (local) { 759 if (local) {
756 __tlbiel_va_range(start, end, pid, page_size, mmu_virtual_psize); 760 __tlbiel_va_range(start, end, pid, page_size, mmu_virtual_psize);
757 if (hflush) 761 if (hflush)
758 __tlbiel_va_range(hstart, hend, pid, 762 __tlbiel_va_range(hstart, hend, pid,
759 HPAGE_PMD_SIZE, MMU_PAGE_2M); 763 PMD_SIZE, MMU_PAGE_2M);
764 if (gflush)
765 __tlbiel_va_range(gstart, gend, pid,
766 PUD_SIZE, MMU_PAGE_1G);
760 asm volatile("ptesync": : :"memory"); 767 asm volatile("ptesync": : :"memory");
761 } else { 768 } else {
762 __tlbie_va_range(start, end, pid, page_size, mmu_virtual_psize); 769 __tlbie_va_range(start, end, pid, page_size, mmu_virtual_psize);
763 if (hflush) 770 if (hflush)
764 __tlbie_va_range(hstart, hend, pid, 771 __tlbie_va_range(hstart, hend, pid,
765 HPAGE_PMD_SIZE, MMU_PAGE_2M); 772 PMD_SIZE, MMU_PAGE_2M);
773 if (gflush)
774 __tlbie_va_range(gstart, gend, pid,
775 PUD_SIZE, MMU_PAGE_1G);
766 fixup_tlbie(); 776 fixup_tlbie();
767 asm volatile("eieio; tlbsync; ptesync": : :"memory"); 777 asm volatile("eieio; tlbsync; ptesync": : :"memory");
768 } 778 }
769 } 779 }
770 preempt_enable(); 780 preempt_enable();
771} 781}
782
783void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
784 unsigned long end)
785
786{
787#ifdef CONFIG_HUGETLB_PAGE
788 if (is_vm_hugetlb_page(vma))
789 return radix__flush_hugetlb_tlb_range(vma, start, end);
790#endif
791
792 __radix__flush_tlb_range(vma->vm_mm, start, end, false);
793}
772EXPORT_SYMBOL(radix__flush_tlb_range); 794EXPORT_SYMBOL(radix__flush_tlb_range);
773 795
774static int radix_get_mmu_psize(int page_size) 796static int radix_get_mmu_psize(int page_size)
@@ -837,6 +859,8 @@ void radix__tlb_flush(struct mmu_gather *tlb)
837 int psize = 0; 859 int psize = 0;
838 struct mm_struct *mm = tlb->mm; 860 struct mm_struct *mm = tlb->mm;
839 int page_size = tlb->page_size; 861 int page_size = tlb->page_size;
862 unsigned long start = tlb->start;
863 unsigned long end = tlb->end;
840 864
841 /* 865 /*
842 * if page size is not something we understand, do a full mm flush 866 * if page size is not something we understand, do a full mm flush
@@ -847,15 +871,45 @@ void radix__tlb_flush(struct mmu_gather *tlb)
847 */ 871 */
848 if (tlb->fullmm) { 872 if (tlb->fullmm) {
849 __flush_all_mm(mm, true); 873 __flush_all_mm(mm, true);
874#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLB_PAGE)
875 } else if (mm_tlb_flush_nested(mm)) {
876 /*
877 * If there is a concurrent invalidation that is clearing ptes,
878 * then it's possible this invalidation will miss one of those
879 * cleared ptes and miss flushing the TLB. If this invalidate
880 * returns before the other one flushes TLBs, that can result
881 * in it returning while there are still valid TLBs inside the
882 * range to be invalidated.
883 *
884 * See mm/memory.c:tlb_finish_mmu() for more details.
885 *
886 * The solution to this is ensure the entire range is always
887 * flushed here. The problem for powerpc is that the flushes
888 * are page size specific, so this "forced flush" would not
889 * do the right thing if there are a mix of page sizes in
890 * the range to be invalidated. So use __flush_tlb_range
891 * which invalidates all possible page sizes in the range.
892 *
893 * PWC flush probably is not be required because the core code
894 * shouldn't free page tables in this path, but accounting
895 * for the possibility makes us a bit more robust.
896 *
897 * need_flush_all is an uncommon case because page table
898 * teardown should be done with exclusive locks held (but
899 * after locks are dropped another invalidate could come
900 * in), it could be optimized further if necessary.
901 */
902 if (!tlb->need_flush_all)
903 __radix__flush_tlb_range(mm, start, end, true);
904 else
905 radix__flush_all_mm(mm);
906#endif
850 } else if ( (psize = radix_get_mmu_psize(page_size)) == -1) { 907 } else if ( (psize = radix_get_mmu_psize(page_size)) == -1) {
851 if (!tlb->need_flush_all) 908 if (!tlb->need_flush_all)
852 radix__flush_tlb_mm(mm); 909 radix__flush_tlb_mm(mm);
853 else 910 else
854 radix__flush_all_mm(mm); 911 radix__flush_all_mm(mm);
855 } else { 912 } else {
856 unsigned long start = tlb->start;
857 unsigned long end = tlb->end;
858
859 if (!tlb->need_flush_all) 913 if (!tlb->need_flush_all)
860 radix__flush_tlb_range_psize(mm, start, end, psize); 914 radix__flush_tlb_range_psize(mm, start, end, psize);
861 else 915 else