1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __ASM_GENERIC_PGALLOC_H
3 #define __ASM_GENERIC_PGALLOC_H
7 #define GFP_PGTABLE_KERNEL (GFP_KERNEL | __GFP_ZERO)
8 #define GFP_PGTABLE_USER (GFP_PGTABLE_KERNEL | __GFP_ACCOUNT)
11 * __pte_alloc_one_kernel - allocate memory for a PTE-level kernel page table
12 * @mm: the mm_struct of the current context
14 * This function is intended for architectures that need
15 * anything beyond simple page allocation.
17 * Return: pointer to the allocated memory or %NULL on error
19 static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm)
21 struct ptdesc *ptdesc = pagetable_alloc(GFP_PGTABLE_KERNEL &
26 return ptdesc_address(ptdesc);
29 #ifndef __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL
31 * pte_alloc_one_kernel - allocate memory for a PTE-level kernel page table
32 * @mm: the mm_struct of the current context
34 * Return: pointer to the allocated memory or %NULL on error
36 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
38 return __pte_alloc_one_kernel(mm);
43 * pte_free_kernel - free PTE-level kernel page table memory
44 * @mm: the mm_struct of the current context
45 * @pte: pointer to the memory containing the page table
47 static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
49 pagetable_free(virt_to_ptdesc(pte));
53 * __pte_alloc_one - allocate memory for a PTE-level user page table
54 * @mm: the mm_struct of the current context
55 * @gfp: GFP flags to use for the allocation
57 * Allocate memory for a page table and ptdesc and runs pagetable_pte_ctor().
59 * This function is intended for architectures that need
60 * anything beyond simple page allocation or must have custom GFP flags.
62 * Return: `struct page` referencing the ptdesc or %NULL on error
64 static inline pgtable_t __pte_alloc_one(struct mm_struct *mm, gfp_t gfp)
66 struct ptdesc *ptdesc;
68 ptdesc = pagetable_alloc(gfp, 0);
71 if (!pagetable_pte_ctor(ptdesc)) {
72 pagetable_free(ptdesc);
76 return ptdesc_page(ptdesc);
79 #ifndef __HAVE_ARCH_PTE_ALLOC_ONE
81 * pte_alloc_one - allocate a page for PTE-level user page table
82 * @mm: the mm_struct of the current context
84 * Allocate memory for a page table and ptdesc and runs pagetable_pte_ctor().
86 * Return: `struct page` referencing the ptdesc or %NULL on error
88 static inline pgtable_t pte_alloc_one(struct mm_struct *mm)
90 return __pte_alloc_one(mm, GFP_PGTABLE_USER);
95 * Should really implement gc for free page table pages. This could be
96 * done with a reference count in struct page.
100 * pte_free - free PTE-level user page table memory
101 * @mm: the mm_struct of the current context
102 * @pte_page: the `struct page` referencing the ptdesc
104 static inline void pte_free(struct mm_struct *mm, struct page *pte_page)
106 struct ptdesc *ptdesc = page_ptdesc(pte_page);
108 pagetable_pte_dtor(ptdesc);
109 pagetable_free(ptdesc);
113 #if CONFIG_PGTABLE_LEVELS > 2
115 #ifndef __HAVE_ARCH_PMD_ALLOC_ONE
117 * pmd_alloc_one - allocate memory for a PMD-level page table
118 * @mm: the mm_struct of the current context
120 * Allocate memory for a page table and ptdesc and runs pagetable_pmd_ctor().
122 * Allocations use %GFP_PGTABLE_USER in user context and
123 * %GFP_PGTABLE_KERNEL in kernel context.
125 * Return: pointer to the allocated memory or %NULL on error
127 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
129 struct ptdesc *ptdesc;
130 gfp_t gfp = GFP_PGTABLE_USER;
133 gfp = GFP_PGTABLE_KERNEL;
134 ptdesc = pagetable_alloc(gfp, 0);
137 if (!pagetable_pmd_ctor(ptdesc)) {
138 pagetable_free(ptdesc);
141 return ptdesc_address(ptdesc);
145 #ifndef __HAVE_ARCH_PMD_FREE
146 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
148 struct ptdesc *ptdesc = virt_to_ptdesc(pmd);
150 BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
151 pagetable_pmd_dtor(ptdesc);
152 pagetable_free(ptdesc);
156 #endif /* CONFIG_PGTABLE_LEVELS > 2 */
158 #if CONFIG_PGTABLE_LEVELS > 3
160 static inline pud_t *__pud_alloc_one(struct mm_struct *mm, unsigned long addr)
162 gfp_t gfp = GFP_PGTABLE_USER;
163 struct ptdesc *ptdesc;
166 gfp = GFP_PGTABLE_KERNEL;
167 gfp &= ~__GFP_HIGHMEM;
169 ptdesc = pagetable_alloc(gfp, 0);
172 return ptdesc_address(ptdesc);
175 #ifndef __HAVE_ARCH_PUD_ALLOC_ONE
177 * pud_alloc_one - allocate memory for a PUD-level page table
178 * @mm: the mm_struct of the current context
180 * Allocate memory for a page table using %GFP_PGTABLE_USER for user context
181 * and %GFP_PGTABLE_KERNEL for kernel context.
183 * Return: pointer to the allocated memory or %NULL on error
185 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
187 return __pud_alloc_one(mm, addr);
191 static inline void __pud_free(struct mm_struct *mm, pud_t *pud)
193 BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
194 pagetable_free(virt_to_ptdesc(pud));
197 #ifndef __HAVE_ARCH_PUD_FREE
198 static inline void pud_free(struct mm_struct *mm, pud_t *pud)
204 #endif /* CONFIG_PGTABLE_LEVELS > 3 */
206 #ifndef __HAVE_ARCH_PGD_FREE
207 static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
209 pagetable_free(virt_to_ptdesc(pgd));
213 #endif /* CONFIG_MMU */
215 #endif /* __ASM_GENERIC_PGALLOC_H */