Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
5c01b46b AB |
2 | #ifndef __ASM_GENERIC_PGALLOC_H |
3 | #define __ASM_GENERIC_PGALLOC_H | |
5fba4af4 | 4 | |
5c01b46b | 5 | #ifdef CONFIG_MMU |
5fba4af4 MR |
6 | |
7 | #define GFP_PGTABLE_KERNEL (GFP_KERNEL | __GFP_ZERO) | |
8 | #define GFP_PGTABLE_USER (GFP_PGTABLE_KERNEL | __GFP_ACCOUNT) | |
9 | ||
10 | /** | |
11 | * __pte_alloc_one_kernel - allocate a page for PTE-level kernel page table | |
12 | * @mm: the mm_struct of the current context | |
13 | * | |
14 | * This function is intended for architectures that need | |
15 | * anything beyond simple page allocation. | |
16 | * | |
17 | * Return: pointer to the allocated memory or %NULL on error | |
18 | */ | |
19 | static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm) | |
20 | { | |
21 | return (pte_t *)__get_free_page(GFP_PGTABLE_KERNEL); | |
22 | } | |
23 | ||
24 | #ifndef __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL | |
25 | /** | |
26 | * pte_alloc_one_kernel - allocate a page for PTE-level kernel page table | |
27 | * @mm: the mm_struct of the current context | |
28 | * | |
29 | * Return: pointer to the allocated memory or %NULL on error | |
30 | */ | |
31 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm) | |
32 | { | |
33 | return __pte_alloc_one_kernel(mm); | |
34 | } | |
35 | #endif | |
36 | ||
37 | /** | |
38 | * pte_free_kernel - free PTE-level kernel page table page | |
39 | * @mm: the mm_struct of the current context | |
40 | * @pte: pointer to the memory containing the page table | |
41 | */ | |
42 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | |
43 | { | |
44 | free_page((unsigned long)pte); | |
45 | } | |
46 | ||
47 | /** | |
48 | * __pte_alloc_one - allocate a page for PTE-level user page table | |
49 | * @mm: the mm_struct of the current context | |
50 | * @gfp: GFP flags to use for the allocation | |
51 | * | |
b4ed71f5 | 52 | * Allocates a page and runs the pgtable_pte_page_ctor(). |
5fba4af4 MR |
53 | * |
54 | * This function is intended for architectures that need | |
55 | * anything beyond simple page allocation or must have custom GFP flags. | |
56 | * | |
57 | * Return: `struct page` initialized as page table or %NULL on error | |
58 | */ | |
59 | static inline pgtable_t __pte_alloc_one(struct mm_struct *mm, gfp_t gfp) | |
60 | { | |
61 | struct page *pte; | |
62 | ||
63 | pte = alloc_page(gfp); | |
64 | if (!pte) | |
65 | return NULL; | |
b4ed71f5 | 66 | if (!pgtable_pte_page_ctor(pte)) { |
5fba4af4 MR |
67 | __free_page(pte); |
68 | return NULL; | |
69 | } | |
70 | ||
71 | return pte; | |
72 | } | |
73 | ||
74 | #ifndef __HAVE_ARCH_PTE_ALLOC_ONE | |
75 | /** | |
76 | * pte_alloc_one - allocate a page for PTE-level user page table | |
77 | * @mm: the mm_struct of the current context | |
78 | * | |
b4ed71f5 | 79 | * Allocates a page and runs the pgtable_pte_page_ctor(). |
5fba4af4 MR |
80 | * |
81 | * Return: `struct page` initialized as page table or %NULL on error | |
82 | */ | |
83 | static inline pgtable_t pte_alloc_one(struct mm_struct *mm) | |
84 | { | |
85 | return __pte_alloc_one(mm, GFP_PGTABLE_USER); | |
86 | } | |
5c01b46b AB |
87 | #endif |
88 | ||
5fba4af4 MR |
89 | /* |
90 | * Should really implement gc for free page table pages. This could be | |
91 | * done with a reference count in struct page. | |
92 | */ | |
93 | ||
94 | /** | |
95 | * pte_free - free PTE-level user page table page | |
96 | * @mm: the mm_struct of the current context | |
97 | * @pte_page: the `struct page` representing the page table | |
98 | */ | |
99 | static inline void pte_free(struct mm_struct *mm, struct page *pte_page) | |
100 | { | |
b4ed71f5 | 101 | pgtable_pte_page_dtor(pte_page); |
5fba4af4 MR |
102 | __free_page(pte_page); |
103 | } | |
104 | ||
5fba4af4 MR |
105 | #endif /* CONFIG_MMU */ |
106 | ||
5c01b46b | 107 | #endif /* __ASM_GENERIC_PGALLOC_H */ |