18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _ASM_PGALLOC_H
38c2ecf20Sopenharmony_ci#define _ASM_PGALLOC_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/gfp.h>
68c2ecf20Sopenharmony_ci#include <linux/mm.h>
78c2ecf20Sopenharmony_ci#include <linux/threads.h>
88c2ecf20Sopenharmony_ci#include <asm/processor.h>
98c2ecf20Sopenharmony_ci#include <asm/fixmap.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <asm/cache.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMD_ALLOC_ONE
148c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMD_FREE
158c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PGD_FREE
168c2ecf20Sopenharmony_ci#include <asm-generic/pgalloc.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/* Allocate the top level pgd (page directory) */
198c2ecf20Sopenharmony_cistatic inline pgd_t *pgd_alloc(struct mm_struct *mm)
208c2ecf20Sopenharmony_ci{
218c2ecf20Sopenharmony_ci	pgd_t *pgd;
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	pgd = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ORDER);
248c2ecf20Sopenharmony_ci	if (unlikely(pgd == NULL))
258c2ecf20Sopenharmony_ci		return NULL;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	memset(pgd, 0, PAGE_SIZE << PGD_ORDER);
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	return pgd;
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	free_pages((unsigned long)pgd, PGD_ORDER);
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#if CONFIG_PGTABLE_LEVELS == 3
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci/* Three Level Page Table Support for pmd's */
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	set_pud(pud, __pud((PxD_FLAG_PRESENT | PxD_FLAG_VALID) +
448c2ecf20Sopenharmony_ci			(__u32)(__pa((unsigned long)pmd) >> PxD_VALUE_SHIFT)));
458c2ecf20Sopenharmony_ci}
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	pmd_t *pmd;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	pmd = (pmd_t *)__get_free_pages(GFP_PGTABLE_KERNEL, PMD_ORDER);
528c2ecf20Sopenharmony_ci	if (likely(pmd))
538c2ecf20Sopenharmony_ci		memset ((void *)pmd, 0, PAGE_SIZE << PMD_ORDER);
548c2ecf20Sopenharmony_ci	return pmd;
558c2ecf20Sopenharmony_ci}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistatic inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	free_pages((unsigned long)pmd, PMD_ORDER);
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci#endif
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic inline void
648c2ecf20Sopenharmony_cipmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	set_pmd(pmd, __pmd((PxD_FLAG_PRESENT | PxD_FLAG_VALID)
678c2ecf20Sopenharmony_ci		+ (__u32)(__pa((unsigned long)pte) >> PxD_VALUE_SHIFT)));
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci#define pmd_populate(mm, pmd, pte_page) \
718c2ecf20Sopenharmony_ci	pmd_populate_kernel(mm, pmd, page_address(pte_page))
728c2ecf20Sopenharmony_ci#define pmd_pgtable(pmd) pmd_page(pmd)
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci#endif
75