diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-23 09:13:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-23 09:13:05 -0400 |
commit | 5e2204832b20ef9db859dd6a2e955ac3e33eef27 (patch) | |
tree | 2e056f8d1c22a1b71ba1087b480a5585b6f5a0bc | |
parent | 7ab366e44208d393e9e5b15c416eeaa5fb74681b (diff) | |
parent | fadd03c615922d8521a2e76d4ba2335891cb2790 (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/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/book3s/32/pgalloc.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/book3s/64/pgtable-4k.h | 21 | ||||
-rw-r--r-- | arch/powerpc/include/asm/book3s/64/pgtable-64k.h | 9 | ||||
-rw-r--r-- | arch/powerpc/include/asm/book3s/64/pgtable.h | 5 | ||||
-rw-r--r-- | arch/powerpc/include/asm/nmi.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/nohash/32/pgalloc.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/nohash/64/pgalloc.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/dt_cpu_ftrs.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup-common.c | 12 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 8 | ||||
-rw-r--r-- | arch/powerpc/kernel/smp.c | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/stacktrace.c | 4 | ||||
-rw-r--r-- | arch/powerpc/mm/hugetlbpage.c | 3 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable-book3s64.c | 12 | ||||
-rw-r--r-- | arch/powerpc/mm/tlb-radix.c | 98 |
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 | |||
244 | cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec) | 244 | cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec) |
245 | cpu-as-$(CONFIG_E200) += -Wa,-me200 | 245 | cpu-as-$(CONFIG_E200) += -Wa,-me200 |
246 | cpu-as-$(CONFIG_PPC_BOOK3S_64) += -Wa,-mpower4 | 246 | cpu-as-$(CONFIG_PPC_BOOK3S_64) += -Wa,-mpower4 |
247 | cpu-as-$(CONFIG_PPC_E500MC) += $(call as-option,-Wa$(comma)-me500mc) | ||
247 | 248 | ||
248 | KBUILD_AFLAGS += $(cpu-as-y) | 249 | KBUILD_AFLAGS += $(cpu-as-y) |
249 | KBUILD_CFLAGS += $(cpu-as-y) | 250 | KBUILD_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 |
113 | static inline void pgtable_free_tlb(struct mmu_gather *tlb, | 114 | static 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 | |||
60 | static 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 */ |
53 | static inline int pmd_huge(pmd_t pmd) { return 0; } | 74 | static inline int pmd_huge(pmd_t pmd) { return 0; } |
54 | static inline int pud_huge(pud_t pud) { return 0; } | 75 | static 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 | */ | ||
54 | static inline int get_hugepd_cache_index(int index) | ||
55 | { | ||
56 | BUG(); | ||
57 | } | ||
58 | |||
50 | #else /* !CONFIG_HUGETLB_PAGE */ | 59 | #else /* !CONFIG_HUGETLB_PAGE */ |
51 | static inline int pmd_huge(pmd_t pmd) { return 0; } | 60 | static inline int pmd_huge(pmd_t pmd) { return 0; } |
52 | static inline int pud_huge(pud_t pud) { return 0; } | 61 | static 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 | ||
292 | extern unsigned long __vmalloc_start; | 297 | extern 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); | |||
8 | static inline void arch_touch_nmi_watchdog(void) {} | 8 | static 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) |
12 | extern void arch_trigger_cpumask_backtrace(const cpumask_t *mask, | 12 | extern 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 |
114 | static inline void pgtable_free_tlb(struct mmu_gather *tlb, | 115 | static 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 |
145 | static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift) | 146 | static 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 | ||
717 | void __init setup_panic(void) | 724 | void __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 | ||
390 | void 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) |
391 | static bool use_spinloop(void) | 399 | static 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 | ||
618 | static void stop_this_cpu(void *dummy) | 615 | static 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, | |||
196 | EXPORT_SYMBOL_GPL(save_stack_trace_tsk_reliable); | 196 | EXPORT_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) |
200 | static void handle_backtrace_ipi(struct pt_regs *regs) | 200 | static 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 | ||
343 | static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, | 344 | static 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); | |||
689 | static unsigned long tlb_single_page_flush_ceiling __read_mostly = 33; | 689 | static unsigned long tlb_single_page_flush_ceiling __read_mostly = 33; |
690 | static unsigned long tlb_local_single_page_flush_ceiling __read_mostly = POWER9_TLB_SETS_RADIX * 2; | 690 | static unsigned long tlb_local_single_page_flush_ceiling __read_mostly = POWER9_TLB_SETS_RADIX * 2; |
691 | 691 | ||
692 | void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | 692 | static 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 | |||
783 | void 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 | } | ||
772 | EXPORT_SYMBOL(radix__flush_tlb_range); | 794 | EXPORT_SYMBOL(radix__flush_tlb_range); |
773 | 795 | ||
774 | static int radix_get_mmu_psize(int page_size) | 796 | static 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 | } |