162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _ASM_POWERPC_BOOK3S_64_TLBFLUSH_HASH_H
362306a36Sopenharmony_ci#define _ASM_POWERPC_BOOK3S_64_TLBFLUSH_HASH_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci/*
662306a36Sopenharmony_ci * TLB flushing for 64-bit hash-MMU CPUs
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/percpu.h>
1062306a36Sopenharmony_ci#include <asm/page.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define PPC64_TLB_BATCH_NR 192
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistruct ppc64_tlb_batch {
1562306a36Sopenharmony_ci	int			active;
1662306a36Sopenharmony_ci	unsigned long		index;
1762306a36Sopenharmony_ci	struct mm_struct	*mm;
1862306a36Sopenharmony_ci	real_pte_t		pte[PPC64_TLB_BATCH_NR];
1962306a36Sopenharmony_ci	unsigned long		vpn[PPC64_TLB_BATCH_NR];
2062306a36Sopenharmony_ci	unsigned int		psize;
2162306a36Sopenharmony_ci	int			ssize;
2262306a36Sopenharmony_ci};
2362306a36Sopenharmony_ciDECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ciextern void __flush_tlb_pending(struct ppc64_tlb_batch *batch);
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistatic inline void arch_enter_lazy_mmu_mode(void)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	struct ppc64_tlb_batch *batch;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	if (radix_enabled())
3462306a36Sopenharmony_ci		return;
3562306a36Sopenharmony_ci	/*
3662306a36Sopenharmony_ci	 * apply_to_page_range can call us this preempt enabled when
3762306a36Sopenharmony_ci	 * operating on kernel page tables.
3862306a36Sopenharmony_ci	 */
3962306a36Sopenharmony_ci	preempt_disable();
4062306a36Sopenharmony_ci	batch = this_cpu_ptr(&ppc64_tlb_batch);
4162306a36Sopenharmony_ci	batch->active = 1;
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic inline void arch_leave_lazy_mmu_mode(void)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	struct ppc64_tlb_batch *batch;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	if (radix_enabled())
4962306a36Sopenharmony_ci		return;
5062306a36Sopenharmony_ci	batch = this_cpu_ptr(&ppc64_tlb_batch);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	if (batch->index)
5362306a36Sopenharmony_ci		__flush_tlb_pending(batch);
5462306a36Sopenharmony_ci	batch->active = 0;
5562306a36Sopenharmony_ci	preempt_enable();
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#define arch_flush_lazy_mmu_mode()      do {} while (0)
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ciextern void hash__tlbiel_all(unsigned int action);
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ciextern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize,
6362306a36Sopenharmony_ci			    int ssize, unsigned long flags);
6462306a36Sopenharmony_ciextern void flush_hash_range(unsigned long number, int local);
6562306a36Sopenharmony_ciextern void flush_hash_hugepage(unsigned long vsid, unsigned long addr,
6662306a36Sopenharmony_ci				pmd_t *pmdp, unsigned int psize, int ssize,
6762306a36Sopenharmony_ci				unsigned long flags);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistruct mmu_gather;
7062306a36Sopenharmony_ciextern void hash__tlb_flush(struct mmu_gather *tlb);
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci#ifdef CONFIG_PPC_64S_HASH_MMU
7362306a36Sopenharmony_ci/* Private function for use by PCI IO mapping code */
7462306a36Sopenharmony_ciextern void __flush_hash_table_range(unsigned long start, unsigned long end);
7562306a36Sopenharmony_civoid flush_hash_table_pmd_range(struct mm_struct *mm, pmd_t *pmd, unsigned long addr);
7662306a36Sopenharmony_ci#else
7762306a36Sopenharmony_cistatic inline void __flush_hash_table_range(unsigned long start, unsigned long end) { }
7862306a36Sopenharmony_ci#endif
7962306a36Sopenharmony_ci#endif /*  _ASM_POWERPC_BOOK3S_64_TLBFLUSH_HASH_H */
80