18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2009 Chen Liqin <liqin.chen@sunplusct.com>
48c2ecf20Sopenharmony_ci * Copyright (C) 2012 Regents of the University of California
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#ifndef _ASM_RISCV_PGALLOC_H
88c2ecf20Sopenharmony_ci#define _ASM_RISCV_PGALLOC_H
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/mm.h>
118c2ecf20Sopenharmony_ci#include <asm/tlb.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#ifdef CONFIG_MMU
148c2ecf20Sopenharmony_ci#include <asm-generic/pgalloc.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistatic inline void pmd_populate_kernel(struct mm_struct *mm,
178c2ecf20Sopenharmony_ci	pmd_t *pmd, pte_t *pte)
188c2ecf20Sopenharmony_ci{
198c2ecf20Sopenharmony_ci	unsigned long pfn = virt_to_pfn(pte);
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	set_pmd(pmd, __pmd((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE));
228c2ecf20Sopenharmony_ci}
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistatic inline void pmd_populate(struct mm_struct *mm,
258c2ecf20Sopenharmony_ci	pmd_t *pmd, pgtable_t pte)
268c2ecf20Sopenharmony_ci{
278c2ecf20Sopenharmony_ci	unsigned long pfn = virt_to_pfn(page_address(pte));
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	set_pmd(pmd, __pmd((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE));
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#ifndef __PAGETABLE_PMD_FOLDED
338c2ecf20Sopenharmony_cistatic inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	unsigned long pfn = virt_to_pfn(pmd);
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	set_pud(pud, __pud((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE));
388c2ecf20Sopenharmony_ci}
398c2ecf20Sopenharmony_ci#endif /* __PAGETABLE_PMD_FOLDED */
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define pmd_pgtable(pmd)	pmd_page(pmd)
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistatic inline pgd_t *pgd_alloc(struct mm_struct *mm)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	pgd_t *pgd;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
488c2ecf20Sopenharmony_ci	if (likely(pgd != NULL)) {
498c2ecf20Sopenharmony_ci		memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
508c2ecf20Sopenharmony_ci		/* Copy kernel mappings */
518c2ecf20Sopenharmony_ci		memcpy(pgd + USER_PTRS_PER_PGD,
528c2ecf20Sopenharmony_ci			init_mm.pgd + USER_PTRS_PER_PGD,
538c2ecf20Sopenharmony_ci			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
548c2ecf20Sopenharmony_ci	}
558c2ecf20Sopenharmony_ci	return pgd;
568c2ecf20Sopenharmony_ci}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci#ifndef __PAGETABLE_PMD_FOLDED
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci#define __pmd_free_tlb(tlb, pmd, addr)  pmd_free((tlb)->mm, pmd)
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#endif /* __PAGETABLE_PMD_FOLDED */
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci#define __pte_free_tlb(tlb, pte, buf)   \
658c2ecf20Sopenharmony_cido {                                    \
668c2ecf20Sopenharmony_ci	pgtable_pte_page_dtor(pte);     \
678c2ecf20Sopenharmony_ci	tlb_remove_page((tlb), pte);    \
688c2ecf20Sopenharmony_ci} while (0)
698c2ecf20Sopenharmony_ci#endif /* CONFIG_MMU */
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci#endif /* _ASM_RISCV_PGALLOC_H */
72