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 | } |
