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

arm64: trans_pgd: pass allocator trans_pgd_create_copy

Make trans_pgd_create_copy and its subroutines to use allocator that is
passed as an argument

Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: James Morse <james.morse@arm.com>
Link: https://lore.kernel.org/r/20210125191923.1060122-6-pasha.tatashin@soleen.com
Signed-off-by: Will Deacon <will@kernel.org>

authored by

Pavel Tatashin and committed by
Will Deacon
89d1410f 50f53fb7

+38 -22
+2 -2
arch/arm64/include/asm/trans_pgd.h
··· 27 27 void *trans_alloc_arg; 28 28 }; 29 29 30 - int trans_pgd_create_copy(pgd_t **dst_pgdp, unsigned long start, 31 - unsigned long end); 30 + int trans_pgd_create_copy(struct trans_pgd_info *info, pgd_t **trans_pgd, 31 + unsigned long start, unsigned long end); 32 32 33 33 int trans_pgd_map_page(struct trans_pgd_info *info, pgd_t *trans_pgd, 34 34 void *page, unsigned long dst_addr, pgprot_t pgprot);
+6 -1
arch/arm64/kernel/hibernate.c
··· 437 437 phys_addr_t phys_hibernate_exit; 438 438 void __noreturn (*hibernate_exit)(phys_addr_t, phys_addr_t, void *, 439 439 void *, phys_addr_t, phys_addr_t); 440 + struct trans_pgd_info trans_info = { 441 + .trans_alloc_page = hibernate_page_alloc, 442 + .trans_alloc_arg = (void *)GFP_ATOMIC, 443 + }; 440 444 441 445 /* 442 446 * Restoring the memory image will overwrite the ttbr1 page tables. 443 447 * Create a second copy of just the linear map, and use this when 444 448 * restoring. 445 449 */ 446 - rc = trans_pgd_create_copy(&tmp_pg_dir, PAGE_OFFSET, PAGE_END); 450 + rc = trans_pgd_create_copy(&trans_info, &tmp_pg_dir, PAGE_OFFSET, 451 + PAGE_END); 447 452 if (rc) 448 453 return rc; 449 454
+30 -19
arch/arm64/mm/trans_pgd.c
··· 57 57 } 58 58 } 59 59 60 - static int copy_pte(pmd_t *dst_pmdp, pmd_t *src_pmdp, unsigned long start, 61 - unsigned long end) 60 + static int copy_pte(struct trans_pgd_info *info, pmd_t *dst_pmdp, 61 + pmd_t *src_pmdp, unsigned long start, unsigned long end) 62 62 { 63 63 pte_t *src_ptep; 64 64 pte_t *dst_ptep; 65 65 unsigned long addr = start; 66 66 67 - dst_ptep = (pte_t *)get_safe_page(GFP_ATOMIC); 67 + dst_ptep = trans_alloc(info); 68 68 if (!dst_ptep) 69 69 return -ENOMEM; 70 70 pmd_populate_kernel(&init_mm, dst_pmdp, dst_ptep); ··· 78 78 return 0; 79 79 } 80 80 81 - static int copy_pmd(pud_t *dst_pudp, pud_t *src_pudp, unsigned long start, 82 - unsigned long end) 81 + static int copy_pmd(struct trans_pgd_info *info, pud_t *dst_pudp, 82 + pud_t *src_pudp, unsigned long start, unsigned long end) 83 83 { 84 84 pmd_t *src_pmdp; 85 85 pmd_t *dst_pmdp; ··· 87 87 unsigned long addr = start; 88 88 89 89 if (pud_none(READ_ONCE(*dst_pudp))) { 90 - dst_pmdp = (pmd_t *)get_safe_page(GFP_ATOMIC); 90 + dst_pmdp = trans_alloc(info); 91 91 if (!dst_pmdp) 92 92 return -ENOMEM; 93 93 pud_populate(&init_mm, dst_pudp, dst_pmdp); ··· 102 102 if (pmd_none(pmd)) 103 103 continue; 104 104 if (pmd_table(pmd)) { 105 - if (copy_pte(dst_pmdp, src_pmdp, addr, next)) 105 + if (copy_pte(info, dst_pmdp, src_pmdp, addr, next)) 106 106 return -ENOMEM; 107 107 } else { 108 108 set_pmd(dst_pmdp, ··· 113 113 return 0; 114 114 } 115 115 116 - static int copy_pud(p4d_t *dst_p4dp, p4d_t *src_p4dp, unsigned long start, 116 + static int copy_pud(struct trans_pgd_info *info, p4d_t *dst_p4dp, 117 + p4d_t *src_p4dp, unsigned long start, 117 118 unsigned long end) 118 119 { 119 120 pud_t *dst_pudp; ··· 123 122 unsigned long addr = start; 124 123 125 124 if (p4d_none(READ_ONCE(*dst_p4dp))) { 126 - dst_pudp = (pud_t *)get_safe_page(GFP_ATOMIC); 125 + dst_pudp = trans_alloc(info); 127 126 if (!dst_pudp) 128 127 return -ENOMEM; 129 128 p4d_populate(&init_mm, dst_p4dp, dst_pudp); ··· 138 137 if (pud_none(pud)) 139 138 continue; 140 139 if (pud_table(pud)) { 141 - if (copy_pmd(dst_pudp, src_pudp, addr, next)) 140 + if (copy_pmd(info, dst_pudp, src_pudp, addr, next)) 142 141 return -ENOMEM; 143 142 } else { 144 143 set_pud(dst_pudp, ··· 149 148 return 0; 150 149 } 151 150 152 - static int copy_p4d(pgd_t *dst_pgdp, pgd_t *src_pgdp, unsigned long start, 151 + static int copy_p4d(struct trans_pgd_info *info, pgd_t *dst_pgdp, 152 + pgd_t *src_pgdp, unsigned long start, 153 153 unsigned long end) 154 154 { 155 155 p4d_t *dst_p4dp; ··· 164 162 next = p4d_addr_end(addr, end); 165 163 if (p4d_none(READ_ONCE(*src_p4dp))) 166 164 continue; 167 - if (copy_pud(dst_p4dp, src_p4dp, addr, next)) 165 + if (copy_pud(info, dst_p4dp, src_p4dp, addr, next)) 168 166 return -ENOMEM; 169 167 } while (dst_p4dp++, src_p4dp++, addr = next, addr != end); 170 168 171 169 return 0; 172 170 } 173 171 174 - static int copy_page_tables(pgd_t *dst_pgdp, unsigned long start, 175 - unsigned long end) 172 + static int copy_page_tables(struct trans_pgd_info *info, pgd_t *dst_pgdp, 173 + unsigned long start, unsigned long end) 176 174 { 177 175 unsigned long next; 178 176 unsigned long addr = start; ··· 183 181 next = pgd_addr_end(addr, end); 184 182 if (pgd_none(READ_ONCE(*src_pgdp))) 185 183 continue; 186 - if (copy_p4d(dst_pgdp, src_pgdp, addr, next)) 184 + if (copy_p4d(info, dst_pgdp, src_pgdp, addr, next)) 187 185 return -ENOMEM; 188 186 } while (dst_pgdp++, src_pgdp++, addr = next, addr != end); 189 187 190 188 return 0; 191 189 } 192 190 193 - int trans_pgd_create_copy(pgd_t **dst_pgdp, unsigned long start, 194 - unsigned long end) 191 + /* 192 + * Create trans_pgd and copy linear map. 193 + * info: contains allocator and its argument 194 + * dst_pgdp: new page table that is created, and to which map is copied. 195 + * start: Start of the interval (inclusive). 196 + * end: End of the interval (exclusive). 197 + * 198 + * Returns 0 on success, and -ENOMEM on failure. 199 + */ 200 + int trans_pgd_create_copy(struct trans_pgd_info *info, pgd_t **dst_pgdp, 201 + unsigned long start, unsigned long end) 195 202 { 196 203 int rc; 197 - pgd_t *trans_pgd = (pgd_t *)get_safe_page(GFP_ATOMIC); 204 + pgd_t *trans_pgd = trans_alloc(info); 198 205 199 206 if (!trans_pgd) { 200 207 pr_err("Failed to allocate memory for temporary page tables.\n"); 201 208 return -ENOMEM; 202 209 } 203 210 204 - rc = copy_page_tables(trans_pgd, start, end); 211 + rc = copy_page_tables(info, trans_pgd, start, end); 205 212 if (!rc) 206 213 *dst_pgdp = trans_pgd; 207 214