pgalloc.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __ASM_GENERIC_PGALLOC_H
  3. #define __ASM_GENERIC_PGALLOC_H
  4. #ifdef CONFIG_MMU
  5. #define GFP_PGTABLE_KERNEL (GFP_KERNEL | __GFP_ZERO)
  6. #define GFP_PGTABLE_USER (GFP_PGTABLE_KERNEL | __GFP_ACCOUNT)
  7. /**
  8. * __pte_alloc_one_kernel - allocate memory for a PTE-level kernel page table
  9. * @mm: the mm_struct of the current context
  10. *
  11. * This function is intended for architectures that need
  12. * anything beyond simple page allocation.
  13. *
  14. * Return: pointer to the allocated memory or %NULL on error
  15. */
  16. static inline pte_t *__pte_alloc_one_kernel_noprof(struct mm_struct *mm)
  17. {
  18. struct ptdesc *ptdesc = pagetable_alloc_noprof(GFP_PGTABLE_KERNEL &
  19. ~__GFP_HIGHMEM, 0);
  20. if (!ptdesc)
  21. return NULL;
  22. return ptdesc_address(ptdesc);
  23. }
  24. #define __pte_alloc_one_kernel(...) alloc_hooks(__pte_alloc_one_kernel_noprof(__VA_ARGS__))
  25. #ifndef __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL
  26. /**
  27. * pte_alloc_one_kernel - allocate memory for a PTE-level kernel page table
  28. * @mm: the mm_struct of the current context
  29. *
  30. * Return: pointer to the allocated memory or %NULL on error
  31. */
  32. static inline pte_t *pte_alloc_one_kernel_noprof(struct mm_struct *mm)
  33. {
  34. return __pte_alloc_one_kernel_noprof(mm);
  35. }
  36. #define pte_alloc_one_kernel(...) alloc_hooks(pte_alloc_one_kernel_noprof(__VA_ARGS__))
  37. #endif
  38. /**
  39. * pte_free_kernel - free PTE-level kernel page table memory
  40. * @mm: the mm_struct of the current context
  41. * @pte: pointer to the memory containing the page table
  42. */
  43. static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
  44. {
  45. pagetable_free(virt_to_ptdesc(pte));
  46. }
  47. /**
  48. * __pte_alloc_one - allocate memory for a PTE-level user page table
  49. * @mm: the mm_struct of the current context
  50. * @gfp: GFP flags to use for the allocation
  51. *
  52. * Allocate memory for a page table and ptdesc and runs pagetable_pte_ctor().
  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` referencing the ptdesc or %NULL on error
  58. */
  59. static inline pgtable_t __pte_alloc_one_noprof(struct mm_struct *mm, gfp_t gfp)
  60. {
  61. struct ptdesc *ptdesc;
  62. ptdesc = pagetable_alloc_noprof(gfp, 0);
  63. if (!ptdesc)
  64. return NULL;
  65. if (!pagetable_pte_ctor(ptdesc)) {
  66. pagetable_free(ptdesc);
  67. return NULL;
  68. }
  69. return ptdesc_page(ptdesc);
  70. }
  71. #define __pte_alloc_one(...) alloc_hooks(__pte_alloc_one_noprof(__VA_ARGS__))
  72. #ifndef __HAVE_ARCH_PTE_ALLOC_ONE
  73. /**
  74. * pte_alloc_one - allocate a page for PTE-level user page table
  75. * @mm: the mm_struct of the current context
  76. *
  77. * Allocate memory for a page table and ptdesc and runs pagetable_pte_ctor().
  78. *
  79. * Return: `struct page` referencing the ptdesc or %NULL on error
  80. */
  81. static inline pgtable_t pte_alloc_one_noprof(struct mm_struct *mm)
  82. {
  83. return __pte_alloc_one_noprof(mm, GFP_PGTABLE_USER);
  84. }
  85. #define pte_alloc_one(...) alloc_hooks(pte_alloc_one_noprof(__VA_ARGS__))
  86. #endif
  87. /*
  88. * Should really implement gc for free page table pages. This could be
  89. * done with a reference count in struct page.
  90. */
  91. /**
  92. * pte_free - free PTE-level user page table memory
  93. * @mm: the mm_struct of the current context
  94. * @pte_page: the `struct page` referencing the ptdesc
  95. */
  96. static inline void pte_free(struct mm_struct *mm, struct page *pte_page)
  97. {
  98. struct ptdesc *ptdesc = page_ptdesc(pte_page);
  99. pagetable_pte_dtor(ptdesc);
  100. pagetable_free(ptdesc);
  101. }
  102. #if CONFIG_PGTABLE_LEVELS > 2
  103. #ifndef __HAVE_ARCH_PMD_ALLOC_ONE
  104. /**
  105. * pmd_alloc_one - allocate memory for a PMD-level page table
  106. * @mm: the mm_struct of the current context
  107. *
  108. * Allocate memory for a page table and ptdesc and runs pagetable_pmd_ctor().
  109. *
  110. * Allocations use %GFP_PGTABLE_USER in user context and
  111. * %GFP_PGTABLE_KERNEL in kernel context.
  112. *
  113. * Return: pointer to the allocated memory or %NULL on error
  114. */
  115. static inline pmd_t *pmd_alloc_one_noprof(struct mm_struct *mm, unsigned long addr)
  116. {
  117. struct ptdesc *ptdesc;
  118. gfp_t gfp = GFP_PGTABLE_USER;
  119. if (mm == &init_mm)
  120. gfp = GFP_PGTABLE_KERNEL;
  121. ptdesc = pagetable_alloc_noprof(gfp, 0);
  122. if (!ptdesc)
  123. return NULL;
  124. if (!pagetable_pmd_ctor(ptdesc)) {
  125. pagetable_free(ptdesc);
  126. return NULL;
  127. }
  128. return ptdesc_address(ptdesc);
  129. }
  130. #define pmd_alloc_one(...) alloc_hooks(pmd_alloc_one_noprof(__VA_ARGS__))
  131. #endif
  132. #ifndef __HAVE_ARCH_PMD_FREE
  133. static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
  134. {
  135. struct ptdesc *ptdesc = virt_to_ptdesc(pmd);
  136. BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
  137. pagetable_pmd_dtor(ptdesc);
  138. pagetable_free(ptdesc);
  139. }
  140. #endif
  141. #endif /* CONFIG_PGTABLE_LEVELS > 2 */
  142. #if CONFIG_PGTABLE_LEVELS > 3
  143. static inline pud_t *__pud_alloc_one_noprof(struct mm_struct *mm, unsigned long addr)
  144. {
  145. gfp_t gfp = GFP_PGTABLE_USER;
  146. struct ptdesc *ptdesc;
  147. if (mm == &init_mm)
  148. gfp = GFP_PGTABLE_KERNEL;
  149. gfp &= ~__GFP_HIGHMEM;
  150. ptdesc = pagetable_alloc_noprof(gfp, 0);
  151. if (!ptdesc)
  152. return NULL;
  153. pagetable_pud_ctor(ptdesc);
  154. return ptdesc_address(ptdesc);
  155. }
  156. #define __pud_alloc_one(...) alloc_hooks(__pud_alloc_one_noprof(__VA_ARGS__))
  157. #ifndef __HAVE_ARCH_PUD_ALLOC_ONE
  158. /**
  159. * pud_alloc_one - allocate memory for a PUD-level page table
  160. * @mm: the mm_struct of the current context
  161. *
  162. * Allocate memory for a page table using %GFP_PGTABLE_USER for user context
  163. * and %GFP_PGTABLE_KERNEL for kernel context.
  164. *
  165. * Return: pointer to the allocated memory or %NULL on error
  166. */
  167. static inline pud_t *pud_alloc_one_noprof(struct mm_struct *mm, unsigned long addr)
  168. {
  169. return __pud_alloc_one_noprof(mm, addr);
  170. }
  171. #define pud_alloc_one(...) alloc_hooks(pud_alloc_one_noprof(__VA_ARGS__))
  172. #endif
  173. static inline void __pud_free(struct mm_struct *mm, pud_t *pud)
  174. {
  175. struct ptdesc *ptdesc = virt_to_ptdesc(pud);
  176. BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
  177. pagetable_pud_dtor(ptdesc);
  178. pagetable_free(ptdesc);
  179. }
  180. #ifndef __HAVE_ARCH_PUD_FREE
  181. static inline void pud_free(struct mm_struct *mm, pud_t *pud)
  182. {
  183. __pud_free(mm, pud);
  184. }
  185. #endif
  186. #endif /* CONFIG_PGTABLE_LEVELS > 3 */
  187. #ifndef __HAVE_ARCH_PGD_FREE
  188. static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
  189. {
  190. pagetable_free(virt_to_ptdesc(pgd));
  191. }
  192. #endif
  193. #endif /* CONFIG_MMU */
  194. #endif /* __ASM_GENERIC_PGALLOC_H */