1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * include/asm-xtensa/pgalloc.h
4  *
5  * Copyright (C) 2001-2007 Tensilica Inc.
6  */
7 
8 #ifndef _XTENSA_PGALLOC_H
9 #define _XTENSA_PGALLOC_H
10 
11 #ifdef CONFIG_MMU
12 #include <linux/highmem.h>
13 #include <linux/slab.h>
14 
15 #define __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL
16 #define __HAVE_ARCH_PTE_ALLOC_ONE
17 #include <asm-generic/pgalloc.h>
18 
19 /*
20  * Allocating and freeing a pmd is trivial: the 1-entry pmd is
21  * inside the pgd, so has no extra memory associated with it.
22  */
23 
24 #define pmd_populate_kernel(mm, pmdp, ptep)				     \
25 	(pmd_val(*(pmdp)) = ((unsigned long)ptep))
26 #define pmd_populate(mm, pmdp, page)					     \
27 	(pmd_val(*(pmdp)) = ((unsigned long)page_to_virt(page)))
28 #define pmd_pgtable(pmd) pmd_page(pmd)
29 
30 static inline pgd_t*
pgd_alloc(struct mm_struct * mm)31 pgd_alloc(struct mm_struct *mm)
32 {
33 	return (pgd_t*) __get_free_pages(GFP_KERNEL | __GFP_ZERO, PGD_ORDER);
34 }
35 
ptes_clear(pte_t * ptep)36 static inline void ptes_clear(pte_t *ptep)
37 {
38 	int i;
39 
40 	for (i = 0; i < PTRS_PER_PTE; i++)
41 		pte_clear(NULL, 0, ptep + i);
42 }
43 
pte_alloc_one_kernel(struct mm_struct * mm)44 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
45 {
46 	pte_t *ptep;
47 
48 	ptep = (pte_t *)__pte_alloc_one_kernel(mm);
49 	if (!ptep)
50 		return NULL;
51 	ptes_clear(ptep);
52 	return ptep;
53 }
54 
pte_alloc_one(struct mm_struct * mm)55 static inline pgtable_t pte_alloc_one(struct mm_struct *mm)
56 {
57 	struct page *page;
58 
59 	page = __pte_alloc_one(mm, GFP_PGTABLE_USER);
60 	if (!page)
61 		return NULL;
62 	ptes_clear(page_address(page));
63 	return page;
64 }
65 
66 #define pmd_pgtable(pmd) pmd_page(pmd)
67 #endif /* CONFIG_MMU */
68 
69 #endif /* _XTENSA_PGALLOC_H */
70