18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _ASM_POWERPC_BOOK3S_64_TLBFLUSH_H
38c2ecf20Sopenharmony_ci#define _ASM_POWERPC_BOOK3S_64_TLBFLUSH_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#define MMU_NO_CONTEXT	~0UL
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/mm_types.h>
88c2ecf20Sopenharmony_ci#include <asm/book3s/64/tlbflush-hash.h>
98c2ecf20Sopenharmony_ci#include <asm/book3s/64/tlbflush-radix.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/* TLB flush actions. Used as argument to tlbiel_all() */
128c2ecf20Sopenharmony_cienum {
138c2ecf20Sopenharmony_ci	TLB_INVAL_SCOPE_GLOBAL = 0,	/* invalidate all TLBs */
148c2ecf20Sopenharmony_ci	TLB_INVAL_SCOPE_LPID = 1,	/* invalidate TLBs for current LPID */
158c2ecf20Sopenharmony_ci};
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_NATIVE
188c2ecf20Sopenharmony_cistatic inline void tlbiel_all(void)
198c2ecf20Sopenharmony_ci{
208c2ecf20Sopenharmony_ci	/*
218c2ecf20Sopenharmony_ci	 * This is used for host machine check and bootup.
228c2ecf20Sopenharmony_ci	 *
238c2ecf20Sopenharmony_ci	 * This uses early_radix_enabled and implementations use
248c2ecf20Sopenharmony_ci	 * early_cpu_has_feature etc because that works early in boot
258c2ecf20Sopenharmony_ci	 * and this is the machine check path which is not performance
268c2ecf20Sopenharmony_ci	 * critical.
278c2ecf20Sopenharmony_ci	 */
288c2ecf20Sopenharmony_ci	if (early_radix_enabled())
298c2ecf20Sopenharmony_ci		radix__tlbiel_all(TLB_INVAL_SCOPE_GLOBAL);
308c2ecf20Sopenharmony_ci	else
318c2ecf20Sopenharmony_ci		hash__tlbiel_all(TLB_INVAL_SCOPE_GLOBAL);
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ci#else
348c2ecf20Sopenharmony_cistatic inline void tlbiel_all(void) { BUG(); };
358c2ecf20Sopenharmony_ci#endif
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic inline void tlbiel_all_lpid(bool radix)
388c2ecf20Sopenharmony_ci{
398c2ecf20Sopenharmony_ci	/*
408c2ecf20Sopenharmony_ci	 * This is used for guest machine check.
418c2ecf20Sopenharmony_ci	 */
428c2ecf20Sopenharmony_ci	if (radix)
438c2ecf20Sopenharmony_ci		radix__tlbiel_all(TLB_INVAL_SCOPE_LPID);
448c2ecf20Sopenharmony_ci	else
458c2ecf20Sopenharmony_ci		hash__tlbiel_all(TLB_INVAL_SCOPE_LPID);
468c2ecf20Sopenharmony_ci}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
508c2ecf20Sopenharmony_cistatic inline void flush_pmd_tlb_range(struct vm_area_struct *vma,
518c2ecf20Sopenharmony_ci				       unsigned long start, unsigned long end)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	if (radix_enabled())
548c2ecf20Sopenharmony_ci		return radix__flush_pmd_tlb_range(vma, start, end);
558c2ecf20Sopenharmony_ci	return hash__flush_tlb_range(vma, start, end);
568c2ecf20Sopenharmony_ci}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci#define __HAVE_ARCH_FLUSH_HUGETLB_TLB_RANGE
598c2ecf20Sopenharmony_cistatic inline void flush_hugetlb_tlb_range(struct vm_area_struct *vma,
608c2ecf20Sopenharmony_ci					   unsigned long start,
618c2ecf20Sopenharmony_ci					   unsigned long end)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	if (radix_enabled())
648c2ecf20Sopenharmony_ci		return radix__flush_hugetlb_tlb_range(vma, start, end);
658c2ecf20Sopenharmony_ci	return hash__flush_tlb_range(vma, start, end);
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic inline void flush_tlb_range(struct vm_area_struct *vma,
698c2ecf20Sopenharmony_ci				   unsigned long start, unsigned long end)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	if (radix_enabled())
728c2ecf20Sopenharmony_ci		return radix__flush_tlb_range(vma, start, end);
738c2ecf20Sopenharmony_ci	return hash__flush_tlb_range(vma, start, end);
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cistatic inline void flush_tlb_kernel_range(unsigned long start,
778c2ecf20Sopenharmony_ci					  unsigned long end)
788c2ecf20Sopenharmony_ci{
798c2ecf20Sopenharmony_ci	if (radix_enabled())
808c2ecf20Sopenharmony_ci		return radix__flush_tlb_kernel_range(start, end);
818c2ecf20Sopenharmony_ci	return hash__flush_tlb_kernel_range(start, end);
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistatic inline void local_flush_tlb_mm(struct mm_struct *mm)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	if (radix_enabled())
878c2ecf20Sopenharmony_ci		return radix__local_flush_tlb_mm(mm);
888c2ecf20Sopenharmony_ci	return hash__local_flush_tlb_mm(mm);
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic inline void local_flush_tlb_page(struct vm_area_struct *vma,
928c2ecf20Sopenharmony_ci					unsigned long vmaddr)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	if (radix_enabled())
958c2ecf20Sopenharmony_ci		return radix__local_flush_tlb_page(vma, vmaddr);
968c2ecf20Sopenharmony_ci	return hash__local_flush_tlb_page(vma, vmaddr);
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic inline void local_flush_all_mm(struct mm_struct *mm)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	if (radix_enabled())
1028c2ecf20Sopenharmony_ci		return radix__local_flush_all_mm(mm);
1038c2ecf20Sopenharmony_ci	return hash__local_flush_all_mm(mm);
1048c2ecf20Sopenharmony_ci}
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_cistatic inline void tlb_flush(struct mmu_gather *tlb)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	if (radix_enabled())
1098c2ecf20Sopenharmony_ci		return radix__tlb_flush(tlb);
1108c2ecf20Sopenharmony_ci	return hash__tlb_flush(tlb);
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
1148c2ecf20Sopenharmony_cistatic inline void flush_tlb_mm(struct mm_struct *mm)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	if (radix_enabled())
1178c2ecf20Sopenharmony_ci		return radix__flush_tlb_mm(mm);
1188c2ecf20Sopenharmony_ci	return hash__flush_tlb_mm(mm);
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic inline void flush_tlb_page(struct vm_area_struct *vma,
1228c2ecf20Sopenharmony_ci				  unsigned long vmaddr)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	if (radix_enabled())
1258c2ecf20Sopenharmony_ci		return radix__flush_tlb_page(vma, vmaddr);
1268c2ecf20Sopenharmony_ci	return hash__flush_tlb_page(vma, vmaddr);
1278c2ecf20Sopenharmony_ci}
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_cistatic inline void flush_all_mm(struct mm_struct *mm)
1308c2ecf20Sopenharmony_ci{
1318c2ecf20Sopenharmony_ci	if (radix_enabled())
1328c2ecf20Sopenharmony_ci		return radix__flush_all_mm(mm);
1338c2ecf20Sopenharmony_ci	return hash__flush_all_mm(mm);
1348c2ecf20Sopenharmony_ci}
1358c2ecf20Sopenharmony_ci#else
1368c2ecf20Sopenharmony_ci#define flush_tlb_mm(mm)		local_flush_tlb_mm(mm)
1378c2ecf20Sopenharmony_ci#define flush_tlb_page(vma, addr)	local_flush_tlb_page(vma, addr)
1388c2ecf20Sopenharmony_ci#define flush_all_mm(mm)		local_flush_all_mm(mm)
1398c2ecf20Sopenharmony_ci#endif /* CONFIG_SMP */
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci#define flush_tlb_fix_spurious_fault flush_tlb_fix_spurious_fault
1428c2ecf20Sopenharmony_cistatic inline void flush_tlb_fix_spurious_fault(struct vm_area_struct *vma,
1438c2ecf20Sopenharmony_ci						unsigned long address)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	/* See ptep_set_access_flags comment */
1468c2ecf20Sopenharmony_ci	if (atomic_read(&vma->vm_mm->context.copros) > 0)
1478c2ecf20Sopenharmony_ci		flush_tlb_page(vma, address);
1488c2ecf20Sopenharmony_ci}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ciextern bool tlbie_capable;
1518c2ecf20Sopenharmony_ciextern bool tlbie_enabled;
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_cistatic inline bool cputlb_use_tlbie(void)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	return tlbie_enabled;
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci#endif /*  _ASM_POWERPC_BOOK3S_64_TLBFLUSH_H */
159