aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-23 09:13:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-23 09:13:05 -0400
commit5e2204832b20ef9db859dd6a2e955ac3e33eef27 (patch)
tree2e056f8d1c22a1b71ba1087b480a5585b6f5a0bc
parent7ab366e44208d393e9e5b15c416eeaa5fb74681b (diff)
parentfadd03c615922d8521a2e76d4ba2335891cb2790 (diff)
Merge tag 'powerpc-4.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman: - a fix for hugetlb with 4K pages, broken by our recent changes for split PMD PTL. - set the correct assembler machine type on e500mc, needed since binutils 2.26 introduced two forms for the "wait" instruction. - a fix for potential missed TLB flushes with MADV_[FREE|DONTNEED] etc. and THP on Power9 Radix. - three fixes to try and make our panic handling more robust by hard disabling interrupts, and not marking stopped CPUs as offline because they haven't been properly offlined. - three other minor fixes. Thanks to: Aneesh Kumar K.V, Michael Jeanson, Nicholas Piggin. * tag 'powerpc-4.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/mm/hash/4k: Free hugetlb page table caches correctly. powerpc/64s/radix: Fix radix_kvm_prefetch_workaround paca access of not possible CPU powerpc/64s: Fix build failures with CONFIG_NMI_IPI=n powerpc/64: hard disable irqs on the panic()ing CPU powerpc: smp_send_stop do not offline stopped CPUs powerpc/64: hard disable irqs in panic_smp_self_stop powerpc/64s: Fix DT CPU features Power9 DD2.1 logic powerpc/64s/radix: Fix MADV_[FREE|DONTNEED] TLB flush miss problem with THP powerpc/e500mc: Set assembler machine type to e500mc
-rw-r--r--arch/powerpc/Makefile1
-rw-r--r--arch/powerpc/include/asm/book3s/32/pgalloc.h1
-rw-r--r--arch/powerpc/include/asm/book3s/64/pgtable-4k.h21
-rw-r--r--arch/powerpc/include/asm/book3s/64/pgtable-64k.h9
-rw-r--r--arch/powerpc/include/asm/book3s/64/pgtable.h5
-rw-r--r--arch/powerpc/include/asm/nmi.h2
-rw-r--r--arch/powerpc/include/asm/nohash/32/pgalloc.h1
-rw-r--r--arch/powerpc/include/asm/nohash/64/pgalloc.h1
-rw-r--r--arch/powerpc/kernel/dt_cpu_ftrs.c3
-rw-r--r--arch/powerpc/kernel/setup-common.c12
-rw-r--r--arch/powerpc/kernel/setup_64.c8
-rw-r--r--arch/powerpc/kernel/smp.c6
-rw-r--r--arch/powerpc/kernel/stacktrace.c4
-rw-r--r--arch/powerpc/mm/hugetlbpage.c3
-rw-r--r--arch/powerpc/mm/pgtable-book3s64.c12
-rw-r--r--arch/powerpc/mm/tlb-radix.c98
16 files changed, 153 insertions, 34 deletions
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index bd06a3ccda31..2ea575cb3401 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -244,6 +244,7 @@ cpu-as-$(CONFIG_4xx) += -Wa,-m405
244cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec) 244cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec)
245cpu-as-$(CONFIG_E200) += -Wa,-me200 245cpu-as-$(CONFIG_E200) += -Wa,-me200
246cpu-as-$(CONFIG_PPC_BOOK3S_64) += -Wa,-mpower4 246cpu-as-$(CONFIG_PPC_BOOK3S_64) += -Wa,-mpower4
247cpu-as-$(CONFIG_PPC_E500MC) += $(call as-option,-Wa$(comma)-me500mc)
247 248
248KBUILD_AFLAGS += $(cpu-as-y) 249KBUILD_AFLAGS += $(cpu-as-y)
249KBUILD_CFLAGS += $(cpu-as-y) 250KBUILD_CFLAGS += $(cpu-as-y)
diff --git a/arch/powerpc/include/asm/book3s/32/pgalloc.h b/arch/powerpc/include/asm/book3s/32/pgalloc.h
index 6a6673907e45..e4633803fe43 100644
--- a/arch/powerpc/include/asm/book3s/32/pgalloc.h
+++ b/arch/powerpc/include/asm/book3s/32/pgalloc.h
@@ -108,6 +108,7 @@ static inline void pgtable_free(void *table, unsigned index_size)
108} 108}
109 109
110#define check_pgt_cache() do { } while (0) 110#define check_pgt_cache() do { } while (0)
111#define get_hugepd_cache_index(x) (x)
111 112
112#ifdef CONFIG_SMP 113#ifdef CONFIG_SMP
113static inline void pgtable_free_tlb(struct mmu_gather *tlb, 114static inline void pgtable_free_tlb(struct mmu_gather *tlb,
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable-4k.h b/arch/powerpc/include/asm/book3s/64/pgtable-4k.h
index af5f2baac80f..a069dfcac9a9 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable-4k.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable-4k.h
@@ -49,6 +49,27 @@ static inline int hugepd_ok(hugepd_t hpd)
49} 49}
50#define is_hugepd(hpd) (hugepd_ok(hpd)) 50#define is_hugepd(hpd) (hugepd_ok(hpd))
51 51
52/*
53 * 16M and 16G huge page directory tables are allocated from slab cache
54 *
55 */
56#define H_16M_CACHE_INDEX (PAGE_SHIFT + H_PTE_INDEX_SIZE + H_PMD_INDEX_SIZE - 24)
57#define H_16G_CACHE_INDEX \
58 (PAGE_SHIFT + H_PTE_INDEX_SIZE + H_PMD_INDEX_SIZE + H_PUD_INDEX_SIZE - 34)
59
60static inline int get_hugepd_cache_index(int index)
61{
62 switch (index) {
63 case H_16M_CACHE_INDEX:
64 return HTLB_16M_INDEX;
65 case H_16G_CACHE_INDEX:
66 return HTLB_16G_INDEX;
67 default:
68 BUG();
69 }
70 /* should not reach */
71}
72
52#else /* !CONFIG_HUGETLB_PAGE */ 73#else /* !CONFIG_HUGETLB_PAGE */
53static inline int pmd_huge(pmd_t pmd) { return 0; } 74static inline int pmd_huge(pmd_t pmd) { return 0; }
54static inline int pud_huge(pud_t pud) { return 0; } 75static inline int pud_huge(pud_t pud) { return 0; }
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable-64k.h b/arch/powerpc/include/asm/book3s/64/pgtable-64k.h
index fb4b3ba52339..d7ee249d6890 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable-64k.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable-64k.h
@@ -45,8 +45,17 @@ static inline int hugepd_ok(hugepd_t hpd)
45{ 45{
46 return 0; 46 return 0;
47} 47}
48
48#define is_hugepd(pdep) 0 49#define is_hugepd(pdep) 0
49 50
51/*
52 * This should never get called
53 */
54static inline int get_hugepd_cache_index(int index)
55{
56 BUG();
57}
58
50#else /* !CONFIG_HUGETLB_PAGE */ 59#else /* !CONFIG_HUGETLB_PAGE */
51static inline int pmd_huge(pmd_t pmd) { return 0; } 60static inline int pmd_huge(pmd_t pmd) { return 0; }
52static inline int pud_huge(pud_t pud) { return 0; } 61static inline int pud_huge(pud_t pud) { return 0; }
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
index 63cee159022b..42aafba7a308 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
@@ -287,6 +287,11 @@ enum pgtable_index {
287 PMD_INDEX, 287 PMD_INDEX,
288 PUD_INDEX, 288 PUD_INDEX,
289 PGD_INDEX, 289 PGD_INDEX,
290 /*
291 * Below are used with 4k page size and hugetlb
292 */
293 HTLB_16M_INDEX,
294 HTLB_16G_INDEX,
290}; 295};
291 296
292extern unsigned long __vmalloc_start; 297extern unsigned long __vmalloc_start;
diff --git a/arch/powerpc/include/asm/nmi.h b/arch/powerpc/include/asm/nmi.h
index 0f571e0ebca1..bd9ba8defd72 100644
--- a/arch/powerpc/include/asm/nmi.h
+++ b/arch/powerpc/include/asm/nmi.h
@@ -8,7 +8,7 @@ extern void arch_touch_nmi_watchdog(void);
8static inline void arch_touch_nmi_watchdog(void) {} 8static inline void arch_touch_nmi_watchdog(void) {}
9#endif 9#endif
10 10
11#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_STACKTRACE) 11#if defined(CONFIG_NMI_IPI) && defined(CONFIG_STACKTRACE)
12extern void arch_trigger_cpumask_backtrace(const cpumask_t *mask, 12extern void arch_trigger_cpumask_backtrace(const cpumask_t *mask,
13 bool exclude_self); 13 bool exclude_self);
14#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace 14#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace
diff --git a/arch/powerpc/include/asm/nohash/32/pgalloc.h b/arch/powerpc/include/asm/nohash/32/pgalloc.h
index 1707781d2f20..9de40eb614da 100644
--- a/arch/powerpc/include/asm/nohash/32/pgalloc.h
+++ b/arch/powerpc/include/asm/nohash/32/pgalloc.h
@@ -109,6 +109,7 @@ static inline void pgtable_free(void *table, unsigned index_size)
109} 109}
110 110
111#define check_pgt_cache() do { } while (0) 111#define check_pgt_cache() do { } while (0)
112#define get_hugepd_cache_index(x) (x)
112 113
113#ifdef CONFIG_SMP 114#ifdef CONFIG_SMP
114static inline void pgtable_free_tlb(struct mmu_gather *tlb, 115static inline void pgtable_free_tlb(struct mmu_gather *tlb,
diff --git a/arch/powerpc/include/asm/nohash/64/pgalloc.h b/arch/powerpc/include/asm/nohash/64/pgalloc.h
index 0e693f322cb2..e2d62d033708 100644
--- a/arch/powerpc/include/asm/nohash/64/pgalloc.h
+++ b/arch/powerpc/include/asm/nohash/64/pgalloc.h
@@ -141,6 +141,7 @@ static inline void pgtable_free(void *table, int shift)
141 } 141 }
142} 142}
143 143
144#define get_hugepd_cache_index(x) (x)
144#ifdef CONFIG_SMP 145#ifdef CONFIG_SMP
145static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift) 146static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift)
146{ 147{
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
index 4be1c0de9406..96dd3d871986 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -711,7 +711,8 @@ static __init void cpufeatures_cpu_quirks(void)
711 cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_HV_ASSIST; 711 cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_HV_ASSIST;
712 cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_XER_SO_BUG; 712 cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_XER_SO_BUG;
713 cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1; 713 cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1;
714 } else /* DD2.1 and up have DD2_1 */ 714 } else if ((version & 0xffff0000) == 0x004e0000)
715 /* DD2.1 and up have DD2_1 */
715 cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1; 716 cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1;
716 717
717 if ((version & 0xffff0000) == 0x004e0000) { 718 if ((version & 0xffff0000) == 0x004e0000) {
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 62b1a40d8957..40b44bb53a4e 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -701,11 +701,18 @@ static int ppc_panic_event(struct notifier_block *this,
701 unsigned long event, void *ptr) 701 unsigned long event, void *ptr)
702{ 702{
703 /* 703 /*
704 * panic does a local_irq_disable, but we really
705 * want interrupts to be hard disabled.
706 */
707 hard_irq_disable();
708
709 /*
704 * If firmware-assisted dump has been registered then trigger 710 * If firmware-assisted dump has been registered then trigger
705 * firmware-assisted dump and let firmware handle everything else. 711 * firmware-assisted dump and let firmware handle everything else.
706 */ 712 */
707 crash_fadump(NULL, ptr); 713 crash_fadump(NULL, ptr);
708 ppc_md.panic(ptr); /* May not return */ 714 if (ppc_md.panic)
715 ppc_md.panic(ptr); /* May not return */
709 return NOTIFY_DONE; 716 return NOTIFY_DONE;
710} 717}
711 718
@@ -716,7 +723,8 @@ static struct notifier_block ppc_panic_block = {
716 723
717void __init setup_panic(void) 724void __init setup_panic(void)
718{ 725{
719 if (!ppc_md.panic) 726 /* PPC64 always does a hard irq disable in its panic handler */
727 if (!IS_ENABLED(CONFIG_PPC64) && !ppc_md.panic)
720 return; 728 return;
721 atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block); 729 atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block);
722} 730}
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 7a7ce8ad455e..225bc5f91049 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -387,6 +387,14 @@ void early_setup_secondary(void)
387 387
388#endif /* CONFIG_SMP */ 388#endif /* CONFIG_SMP */
389 389
390void panic_smp_self_stop(void)
391{
392 hard_irq_disable();
393 spin_begin();
394 while (1)
395 spin_cpu_relax();
396}
397
390#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE) 398#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE)
391static bool use_spinloop(void) 399static bool use_spinloop(void)
392{ 400{
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 5eadfffabe35..4794d6b4f4d2 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -600,9 +600,6 @@ static void nmi_stop_this_cpu(struct pt_regs *regs)
600 nmi_ipi_busy_count--; 600 nmi_ipi_busy_count--;
601 nmi_ipi_unlock(); 601 nmi_ipi_unlock();
602 602
603 /* Remove this CPU */
604 set_cpu_online(smp_processor_id(), false);
605
606 spin_begin(); 603 spin_begin();
607 while (1) 604 while (1)
608 spin_cpu_relax(); 605 spin_cpu_relax();
@@ -617,9 +614,6 @@ void smp_send_stop(void)
617 614
618static void stop_this_cpu(void *dummy) 615static void stop_this_cpu(void *dummy)
619{ 616{
620 /* Remove this CPU */
621 set_cpu_online(smp_processor_id(), false);
622
623 hard_irq_disable(); 617 hard_irq_disable();
624 spin_begin(); 618 spin_begin();
625 while (1) 619 while (1)
diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
index 07e97f289c52..e2c50b55138f 100644
--- a/arch/powerpc/kernel/stacktrace.c
+++ b/arch/powerpc/kernel/stacktrace.c
@@ -196,7 +196,7 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,
196EXPORT_SYMBOL_GPL(save_stack_trace_tsk_reliable); 196EXPORT_SYMBOL_GPL(save_stack_trace_tsk_reliable);
197#endif /* CONFIG_HAVE_RELIABLE_STACKTRACE */ 197#endif /* CONFIG_HAVE_RELIABLE_STACKTRACE */
198 198
199#ifdef CONFIG_PPC_BOOK3S_64 199#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_NMI_IPI)
200static void handle_backtrace_ipi(struct pt_regs *regs) 200static void handle_backtrace_ipi(struct pt_regs *regs)
201{ 201{
202 nmi_cpu_backtrace(regs); 202 nmi_cpu_backtrace(regs);
@@ -242,4 +242,4 @@ void arch_trigger_cpumask_backtrace(const cpumask_t *mask, bool exclude_self)
242{ 242{
243 nmi_trigger_cpumask_backtrace(mask, exclude_self, raise_backtrace_ipi); 243 nmi_trigger_cpumask_backtrace(mask, exclude_self, raise_backtrace_ipi);
244} 244}
245#endif /* CONFIG_PPC64 */ 245#endif /* defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_NMI_IPI) */
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 7c5f479c5c00..8a9a49c13865 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -337,7 +337,8 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif
337 if (shift >= pdshift) 337 if (shift >= pdshift)
338 hugepd_free(tlb, hugepte); 338 hugepd_free(tlb, hugepte);
339 else 339 else
340 pgtable_free_tlb(tlb, hugepte, pdshift - shift); 340 pgtable_free_tlb(tlb, hugepte,
341 get_hugepd_cache_index(pdshift - shift));
341} 342}
342 343
343static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, 344static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
diff --git a/arch/powerpc/mm/pgtable-book3s64.c b/arch/powerpc/mm/pgtable-book3s64.c
index c1f4ca45c93a..4afbfbb64bfd 100644
--- a/arch/powerpc/mm/pgtable-book3s64.c
+++ b/arch/powerpc/mm/pgtable-book3s64.c
@@ -409,6 +409,18 @@ static inline void pgtable_free(void *table, int index)
409 case PUD_INDEX: 409 case PUD_INDEX:
410 kmem_cache_free(PGT_CACHE(PUD_CACHE_INDEX), table); 410 kmem_cache_free(PGT_CACHE(PUD_CACHE_INDEX), table);
411 break; 411 break;
412#if defined(CONFIG_PPC_4K_PAGES) && defined(CONFIG_HUGETLB_PAGE)
413 /* 16M hugepd directory at pud level */
414 case HTLB_16M_INDEX:
415 BUILD_BUG_ON(H_16M_CACHE_INDEX <= 0);
416 kmem_cache_free(PGT_CACHE(H_16M_CACHE_INDEX), table);
417 break;
418 /* 16G hugepd directory at the pgd level */
419 case HTLB_16G_INDEX:
420 BUILD_BUG_ON(H_16G_CACHE_INDEX <= 0);
421 kmem_cache_free(PGT_CACHE(H_16G_CACHE_INDEX), table);
422 break;
423#endif
412 /* We don't free pgd table via RCU callback */ 424 /* We don't free pgd table via RCU callback */
413 default: 425 default:
414 BUG(); 426 BUG();
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c
index 67a6e86d3e7e..1135b43a597c 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
@@ -1043,6 +1097,8 @@ extern void radix_kvm_prefetch_workaround(struct mm_struct *mm)
1043 for (; sib <= cpu_last_thread_sibling(cpu) && !flush; sib++) { 1097 for (; sib <= cpu_last_thread_sibling(cpu) && !flush; sib++) {
1044 if (sib == cpu) 1098 if (sib == cpu)
1045 continue; 1099 continue;
1100 if (!cpu_possible(sib))
1101 continue;
1046 if (paca_ptrs[sib]->kvm_hstate.kvm_vcpu) 1102 if (paca_ptrs[sib]->kvm_hstate.kvm_vcpu)
1047 flush = true; 1103 flush = true;
1048 } 1104 }