18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#ifndef __ASM_CSKY_PGALLOC_H
58c2ecf20Sopenharmony_ci#define __ASM_CSKY_PGALLOC_H
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/highmem.h>
88c2ecf20Sopenharmony_ci#include <linux/mm.h>
98c2ecf20Sopenharmony_ci#include <linux/sched.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL
128c2ecf20Sopenharmony_ci#include <asm-generic/pgalloc.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistatic inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
158c2ecf20Sopenharmony_ci					pte_t *pte)
168c2ecf20Sopenharmony_ci{
178c2ecf20Sopenharmony_ci	set_pmd(pmd, __pmd(__pa(pte)));
188c2ecf20Sopenharmony_ci}
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistatic inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
218c2ecf20Sopenharmony_ci					pgtable_t pte)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	set_pmd(pmd, __pmd(__pa(page_address(pte))));
248c2ecf20Sopenharmony_ci}
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define pmd_pgtable(pmd) pmd_page(pmd)
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ciextern void pgd_init(unsigned long *p);
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	pte_t *pte;
338c2ecf20Sopenharmony_ci	unsigned long i;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	pte = (pte_t *) __get_free_page(GFP_KERNEL);
368c2ecf20Sopenharmony_ci	if (!pte)
378c2ecf20Sopenharmony_ci		return NULL;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	for (i = 0; i < PAGE_SIZE/sizeof(pte_t); i++)
408c2ecf20Sopenharmony_ci		(pte + i)->pte_low = _PAGE_GLOBAL;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	return pte;
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic inline pgd_t *pgd_alloc(struct mm_struct *mm)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	pgd_t *ret;
488c2ecf20Sopenharmony_ci	pgd_t *init;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	ret = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ORDER);
518c2ecf20Sopenharmony_ci	if (ret) {
528c2ecf20Sopenharmony_ci		init = pgd_offset(&init_mm, 0UL);
538c2ecf20Sopenharmony_ci		pgd_init((unsigned long *)ret);
548c2ecf20Sopenharmony_ci		memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
558c2ecf20Sopenharmony_ci			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
568c2ecf20Sopenharmony_ci		/* prevent out of order excute */
578c2ecf20Sopenharmony_ci		smp_mb();
588c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_NEED_TLBSYNC
598c2ecf20Sopenharmony_ci		dcache_wb_range((unsigned int)ret,
608c2ecf20Sopenharmony_ci				(unsigned int)(ret + PTRS_PER_PGD));
618c2ecf20Sopenharmony_ci#endif
628c2ecf20Sopenharmony_ci	}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	return ret;
658c2ecf20Sopenharmony_ci}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#define __pte_free_tlb(tlb, pte, address)		\
688c2ecf20Sopenharmony_cido {							\
698c2ecf20Sopenharmony_ci	pgtable_pte_page_dtor(pte);			\
708c2ecf20Sopenharmony_ci	tlb_remove_page(tlb, pte);			\
718c2ecf20Sopenharmony_ci} while (0)
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ciextern void pagetable_init(void);
748c2ecf20Sopenharmony_ciextern void pre_mmu_init(void);
758c2ecf20Sopenharmony_ciextern void pre_trap_init(void);
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci#endif /* __ASM_CSKY_PGALLOC_H */
78