Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pgalloc: convert various functions to use ptdescs

As part of the conversions to replace pgtable constructor/destructors with
ptdesc equivalents, convert various page table functions to use ptdescs.

Some of the functions use the *get*page*() helper functions. Convert
these to use pagetable_alloc() and ptdesc_address() instead to help
standardize page tables further.

Link: https://lkml.kernel.org/r/20230807230513.102486-17-vishal.moola@gmail.com
Signed-off-by: Vishal Moola (Oracle) <vishal.moola@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: Claudio Imbrenda <imbrenda@linux.ibm.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Dinh Nguyen <dinguyen@kernel.org>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Guo Ren <guoren@kernel.org>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Cc: Jonas Bonn <jonas@southpole.se>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Mike Rapoport (IBM) <rppt@kernel.org>
Cc: Palmer Dabbelt <palmer@rivosinc.com>
Cc: Paul Walmsley <paul.walmsley@sifive.com>
Cc: Richard Weinberger <richard@nod.at>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Vishal Moola (Oracle) and committed by
Andrew Morton
c787ae5b 4f054c28

+52 -36
+52 -36
include/asm-generic/pgalloc.h
··· 8 8 #define GFP_PGTABLE_USER (GFP_PGTABLE_KERNEL | __GFP_ACCOUNT) 9 9 10 10 /** 11 - * __pte_alloc_one_kernel - allocate a page for PTE-level kernel page table 11 + * __pte_alloc_one_kernel - allocate memory for a PTE-level kernel page table 12 12 * @mm: the mm_struct of the current context 13 13 * 14 14 * This function is intended for architectures that need ··· 18 18 */ 19 19 static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm) 20 20 { 21 - return (pte_t *)__get_free_page(GFP_PGTABLE_KERNEL); 21 + struct ptdesc *ptdesc = pagetable_alloc(GFP_PGTABLE_KERNEL & 22 + ~__GFP_HIGHMEM, 0); 23 + 24 + if (!ptdesc) 25 + return NULL; 26 + return ptdesc_address(ptdesc); 22 27 } 23 28 24 29 #ifndef __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL 25 30 /** 26 - * pte_alloc_one_kernel - allocate a page for PTE-level kernel page table 31 + * pte_alloc_one_kernel - allocate memory for a PTE-level kernel page table 27 32 * @mm: the mm_struct of the current context 28 33 * 29 34 * Return: pointer to the allocated memory or %NULL on error ··· 40 35 #endif 41 36 42 37 /** 43 - * pte_free_kernel - free PTE-level kernel page table page 38 + * pte_free_kernel - free PTE-level kernel page table memory 44 39 * @mm: the mm_struct of the current context 45 40 * @pte: pointer to the memory containing the page table 46 41 */ 47 42 static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 48 43 { 49 - free_page((unsigned long)pte); 44 + pagetable_free(virt_to_ptdesc(pte)); 50 45 } 51 46 52 47 /** 53 - * __pte_alloc_one - allocate a page for PTE-level user page table 48 + * __pte_alloc_one - allocate memory for a PTE-level user page table 54 49 * @mm: the mm_struct of the current context 55 50 * @gfp: GFP flags to use for the allocation 56 51 * 57 - * Allocates a page and runs the pgtable_pte_page_ctor(). 52 + * Allocate memory for a page table and ptdesc and runs pagetable_pte_ctor(). 58 53 * 59 54 * This function is intended for architectures that need 60 55 * anything beyond simple page allocation or must have custom GFP flags. 61 56 * 62 - * Return: `struct page` initialized as page table or %NULL on error 57 + * Return: `struct page` referencing the ptdesc or %NULL on error 63 58 */ 64 59 static inline pgtable_t __pte_alloc_one(struct mm_struct *mm, gfp_t gfp) 65 60 { 66 - struct page *pte; 61 + struct ptdesc *ptdesc; 67 62 68 - pte = alloc_page(gfp); 69 - if (!pte) 63 + ptdesc = pagetable_alloc(gfp, 0); 64 + if (!ptdesc) 70 65 return NULL; 71 - if (!pgtable_pte_page_ctor(pte)) { 72 - __free_page(pte); 66 + if (!pagetable_pte_ctor(ptdesc)) { 67 + pagetable_free(ptdesc); 73 68 return NULL; 74 69 } 75 70 76 - return pte; 71 + return ptdesc_page(ptdesc); 77 72 } 78 73 79 74 #ifndef __HAVE_ARCH_PTE_ALLOC_ONE ··· 81 76 * pte_alloc_one - allocate a page for PTE-level user page table 82 77 * @mm: the mm_struct of the current context 83 78 * 84 - * Allocates a page and runs the pgtable_pte_page_ctor(). 79 + * Allocate memory for a page table and ptdesc and runs pagetable_pte_ctor(). 85 80 * 86 - * Return: `struct page` initialized as page table or %NULL on error 81 + * Return: `struct page` referencing the ptdesc or %NULL on error 87 82 */ 88 83 static inline pgtable_t pte_alloc_one(struct mm_struct *mm) 89 84 { ··· 97 92 */ 98 93 99 94 /** 100 - * pte_free - free PTE-level user page table page 95 + * pte_free - free PTE-level user page table memory 101 96 * @mm: the mm_struct of the current context 102 - * @pte_page: the `struct page` representing the page table 97 + * @pte_page: the `struct page` referencing the ptdesc 103 98 */ 104 99 static inline void pte_free(struct mm_struct *mm, struct page *pte_page) 105 100 { 106 - pgtable_pte_page_dtor(pte_page); 107 - __free_page(pte_page); 101 + struct ptdesc *ptdesc = page_ptdesc(pte_page); 102 + 103 + pagetable_pte_dtor(ptdesc); 104 + pagetable_free(ptdesc); 108 105 } 109 106 110 107 ··· 114 107 115 108 #ifndef __HAVE_ARCH_PMD_ALLOC_ONE 116 109 /** 117 - * pmd_alloc_one - allocate a page for PMD-level page table 110 + * pmd_alloc_one - allocate memory for a PMD-level page table 118 111 * @mm: the mm_struct of the current context 119 112 * 120 - * Allocates a page and runs the pgtable_pmd_page_ctor(). 113 + * Allocate memory for a page table and ptdesc and runs pagetable_pmd_ctor(). 114 + * 121 115 * Allocations use %GFP_PGTABLE_USER in user context and 122 116 * %GFP_PGTABLE_KERNEL in kernel context. 123 117 * ··· 126 118 */ 127 119 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) 128 120 { 129 - struct page *page; 121 + struct ptdesc *ptdesc; 130 122 gfp_t gfp = GFP_PGTABLE_USER; 131 123 132 124 if (mm == &init_mm) 133 125 gfp = GFP_PGTABLE_KERNEL; 134 - page = alloc_page(gfp); 135 - if (!page) 126 + ptdesc = pagetable_alloc(gfp, 0); 127 + if (!ptdesc) 136 128 return NULL; 137 - if (!pgtable_pmd_page_ctor(page)) { 138 - __free_page(page); 129 + if (!pagetable_pmd_ctor(ptdesc)) { 130 + pagetable_free(ptdesc); 139 131 return NULL; 140 132 } 141 - return (pmd_t *)page_address(page); 133 + return ptdesc_address(ptdesc); 142 134 } 143 135 #endif 144 136 145 137 #ifndef __HAVE_ARCH_PMD_FREE 146 138 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) 147 139 { 140 + struct ptdesc *ptdesc = virt_to_ptdesc(pmd); 141 + 148 142 BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); 149 - pgtable_pmd_page_dtor(virt_to_page(pmd)); 150 - free_page((unsigned long)pmd); 143 + pagetable_pmd_dtor(ptdesc); 144 + pagetable_free(ptdesc); 151 145 } 152 146 #endif 153 147 ··· 160 150 static inline pud_t *__pud_alloc_one(struct mm_struct *mm, unsigned long addr) 161 151 { 162 152 gfp_t gfp = GFP_PGTABLE_USER; 153 + struct ptdesc *ptdesc; 163 154 164 155 if (mm == &init_mm) 165 156 gfp = GFP_PGTABLE_KERNEL; 166 - return (pud_t *)get_zeroed_page(gfp); 157 + gfp &= ~__GFP_HIGHMEM; 158 + 159 + ptdesc = pagetable_alloc(gfp, 0); 160 + if (!ptdesc) 161 + return NULL; 162 + return ptdesc_address(ptdesc); 167 163 } 168 164 169 165 #ifndef __HAVE_ARCH_PUD_ALLOC_ONE 170 166 /** 171 - * pud_alloc_one - allocate a page for PUD-level page table 167 + * pud_alloc_one - allocate memory for a PUD-level page table 172 168 * @mm: the mm_struct of the current context 173 169 * 174 - * Allocates a page using %GFP_PGTABLE_USER for user context and 175 - * %GFP_PGTABLE_KERNEL for kernel context. 170 + * Allocate memory for a page table using %GFP_PGTABLE_USER for user context 171 + * and %GFP_PGTABLE_KERNEL for kernel context. 176 172 * 177 173 * Return: pointer to the allocated memory or %NULL on error 178 174 */ ··· 191 175 static inline void __pud_free(struct mm_struct *mm, pud_t *pud) 192 176 { 193 177 BUG_ON((unsigned long)pud & (PAGE_SIZE-1)); 194 - free_page((unsigned long)pud); 178 + pagetable_free(virt_to_ptdesc(pud)); 195 179 } 196 180 197 181 #ifndef __HAVE_ARCH_PUD_FREE ··· 206 190 #ifndef __HAVE_ARCH_PGD_FREE 207 191 static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) 208 192 { 209 - free_page((unsigned long)pgd); 193 + pagetable_free(virt_to_ptdesc(pgd)); 210 194 } 211 195 #endif 212 196