162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _ASM_POWERPC_NOHASH_PGALLOC_H
362306a36Sopenharmony_ci#define _ASM_POWERPC_NOHASH_PGALLOC_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/mm.h>
662306a36Sopenharmony_ci#include <linux/slab.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ciextern void tlb_remove_table(struct mmu_gather *tlb, void *table);
962306a36Sopenharmony_ci#ifdef CONFIG_PPC64
1062306a36Sopenharmony_ciextern void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address);
1162306a36Sopenharmony_ci#else
1262306a36Sopenharmony_ci/* 44x etc which is BOOKE not BOOK3E */
1362306a36Sopenharmony_cistatic inline void tlb_flush_pgtable(struct mmu_gather *tlb,
1462306a36Sopenharmony_ci				     unsigned long address)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci}
1862306a36Sopenharmony_ci#endif /* !CONFIG_PPC_BOOK3E_64 */
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic inline pgd_t *pgd_alloc(struct mm_struct *mm)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE),
2362306a36Sopenharmony_ci			pgtable_gfp_flags(mm, GFP_KERNEL));
2462306a36Sopenharmony_ci}
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd);
2962306a36Sopenharmony_ci}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#ifdef CONFIG_PPC64
3262306a36Sopenharmony_ci#include <asm/nohash/64/pgalloc.h>
3362306a36Sopenharmony_ci#else
3462306a36Sopenharmony_ci#include <asm/nohash/32/pgalloc.h>
3562306a36Sopenharmony_ci#endif
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic inline void pgtable_free(void *table, int shift)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	if (!shift) {
4062306a36Sopenharmony_ci		pte_fragment_free((unsigned long *)table, 0);
4162306a36Sopenharmony_ci	} else {
4262306a36Sopenharmony_ci		BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE);
4362306a36Sopenharmony_ci		kmem_cache_free(PGT_CACHE(shift), table);
4462306a36Sopenharmony_ci	}
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define get_hugepd_cache_index(x)	(x)
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	unsigned long pgf = (unsigned long)table;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE);
5462306a36Sopenharmony_ci	pgf |= shift;
5562306a36Sopenharmony_ci	tlb_remove_table(tlb, (void *)pgf);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic inline void __tlb_remove_table(void *_table)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	void *table = (void *)((unsigned long)_table & ~MAX_PGTABLE_INDEX_SIZE);
6162306a36Sopenharmony_ci	unsigned shift = (unsigned long)_table & MAX_PGTABLE_INDEX_SIZE;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	pgtable_free(table, shift);
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistatic inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
6762306a36Sopenharmony_ci				  unsigned long address)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	tlb_flush_pgtable(tlb, address);
7062306a36Sopenharmony_ci	pgtable_free_tlb(tlb, table, 0);
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci#endif /* _ASM_POWERPC_NOHASH_PGALLOC_H */
73