162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  arch/arm/include/asm/tlb.h
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (C) 2002 Russell King
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *  Experimentation shows that on a StrongARM, it appears to be faster
862306a36Sopenharmony_ci *  to use the "invalidate whole tlb" rather than "invalidate single
962306a36Sopenharmony_ci *  tlb" for this.
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci *  This appears true for both the process fork+exit case, as well as
1262306a36Sopenharmony_ci *  the munmap-large-area case.
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci#ifndef __ASMARM_TLB_H
1562306a36Sopenharmony_ci#define __ASMARM_TLB_H
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <asm/cacheflush.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#ifndef CONFIG_MMU
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include <linux/pagemap.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define tlb_flush(tlb)	((void) tlb)
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include <asm-generic/tlb.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#else /* !CONFIG_MMU */
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#include <linux/swap.h>
3062306a36Sopenharmony_ci#include <asm/tlbflush.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistatic inline void __tlb_remove_table(void *_table)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	free_page_and_swap_cache((struct page *)_table);
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#include <asm-generic/tlb.h>
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistatic inline void
4062306a36Sopenharmony_ci__pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, unsigned long addr)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	struct ptdesc *ptdesc = page_ptdesc(pte);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	pagetable_pte_dtor(ptdesc);
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#ifndef CONFIG_ARM_LPAE
4762306a36Sopenharmony_ci	/*
4862306a36Sopenharmony_ci	 * With the classic ARM MMU, a pte page has two corresponding pmd
4962306a36Sopenharmony_ci	 * entries, each covering 1MB.
5062306a36Sopenharmony_ci	 */
5162306a36Sopenharmony_ci	addr = (addr & PMD_MASK) + SZ_1M;
5262306a36Sopenharmony_ci	__tlb_adjust_range(tlb, addr - PAGE_SIZE, 2 * PAGE_SIZE);
5362306a36Sopenharmony_ci#endif
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	tlb_remove_ptdesc(tlb, ptdesc);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic inline void
5962306a36Sopenharmony_ci__pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci#ifdef CONFIG_ARM_LPAE
6262306a36Sopenharmony_ci	struct ptdesc *ptdesc = virt_to_ptdesc(pmdp);
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	pagetable_pmd_dtor(ptdesc);
6562306a36Sopenharmony_ci	tlb_remove_ptdesc(tlb, ptdesc);
6662306a36Sopenharmony_ci#endif
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#endif /* CONFIG_MMU */
7062306a36Sopenharmony_ci#endif
71