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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux

Pull arm64 fixes from Will Deacon:
"Two arm64 fixes for -rc6. They resolve a kernel NULL dereference in
kexec and bogus kernel page table dumping when userspace is configured
for 52-bit virtual addressing.

Summary:

- Fix kernel oops when attemping kexec_file() with a NULL cmdline

- Fix page table output in debugfs when ARM64_USER_VA_BITS_52=y"

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: kexec_file: handle empty command-line
arm64: ptdump: Don't iterate kernel page tables using PTRS_PER_PXX

+32 -31
+3 -1
arch/arm64/kernel/machine_kexec_file.c
··· 120 120 { 121 121 void *buf; 122 122 size_t buf_size; 123 + size_t cmdline_len; 123 124 int ret; 124 125 126 + cmdline_len = cmdline ? strlen(cmdline) : 0; 125 127 buf_size = fdt_totalsize(initial_boot_params) 126 - + strlen(cmdline) + DTB_EXTRA_SPACE; 128 + + cmdline_len + DTB_EXTRA_SPACE; 127 129 128 130 for (;;) { 129 131 buf = vmalloc(buf_size);
+29 -30
arch/arm64/mm/dump.c
··· 286 286 287 287 } 288 288 289 - static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start) 289 + static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start, 290 + unsigned long end) 290 291 { 291 - pte_t *ptep = pte_offset_kernel(pmdp, 0UL); 292 - unsigned long addr; 293 - unsigned i; 292 + unsigned long addr = start; 293 + pte_t *ptep = pte_offset_kernel(pmdp, start); 294 294 295 - for (i = 0; i < PTRS_PER_PTE; i++, ptep++) { 296 - addr = start + i * PAGE_SIZE; 295 + do { 297 296 note_page(st, addr, 4, READ_ONCE(pte_val(*ptep))); 298 - } 297 + } while (ptep++, addr += PAGE_SIZE, addr != end); 299 298 } 300 299 301 - static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start) 300 + static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start, 301 + unsigned long end) 302 302 { 303 - pmd_t *pmdp = pmd_offset(pudp, 0UL); 304 - unsigned long addr; 305 - unsigned i; 303 + unsigned long next, addr = start; 304 + pmd_t *pmdp = pmd_offset(pudp, start); 306 305 307 - for (i = 0; i < PTRS_PER_PMD; i++, pmdp++) { 306 + do { 308 307 pmd_t pmd = READ_ONCE(*pmdp); 308 + next = pmd_addr_end(addr, end); 309 309 310 - addr = start + i * PMD_SIZE; 311 310 if (pmd_none(pmd) || pmd_sect(pmd)) { 312 311 note_page(st, addr, 3, pmd_val(pmd)); 313 312 } else { 314 313 BUG_ON(pmd_bad(pmd)); 315 - walk_pte(st, pmdp, addr); 314 + walk_pte(st, pmdp, addr, next); 316 315 } 317 - } 316 + } while (pmdp++, addr = next, addr != end); 318 317 } 319 318 320 - static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start) 319 + static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start, 320 + unsigned long end) 321 321 { 322 - pud_t *pudp = pud_offset(pgdp, 0UL); 323 - unsigned long addr; 324 - unsigned i; 322 + unsigned long next, addr = start; 323 + pud_t *pudp = pud_offset(pgdp, start); 325 324 326 - for (i = 0; i < PTRS_PER_PUD; i++, pudp++) { 325 + do { 327 326 pud_t pud = READ_ONCE(*pudp); 327 + next = pud_addr_end(addr, end); 328 328 329 - addr = start + i * PUD_SIZE; 330 329 if (pud_none(pud) || pud_sect(pud)) { 331 330 note_page(st, addr, 2, pud_val(pud)); 332 331 } else { 333 332 BUG_ON(pud_bad(pud)); 334 - walk_pmd(st, pudp, addr); 333 + walk_pmd(st, pudp, addr, next); 335 334 } 336 - } 335 + } while (pudp++, addr = next, addr != end); 337 336 } 338 337 339 338 static void walk_pgd(struct pg_state *st, struct mm_struct *mm, 340 339 unsigned long start) 341 340 { 342 - pgd_t *pgdp = pgd_offset(mm, 0UL); 343 - unsigned i; 344 - unsigned long addr; 341 + unsigned long end = (start < TASK_SIZE_64) ? TASK_SIZE_64 : 0; 342 + unsigned long next, addr = start; 343 + pgd_t *pgdp = pgd_offset(mm, start); 345 344 346 - for (i = 0; i < PTRS_PER_PGD; i++, pgdp++) { 345 + do { 347 346 pgd_t pgd = READ_ONCE(*pgdp); 347 + next = pgd_addr_end(addr, end); 348 348 349 - addr = start + i * PGDIR_SIZE; 350 349 if (pgd_none(pgd)) { 351 350 note_page(st, addr, 1, pgd_val(pgd)); 352 351 } else { 353 352 BUG_ON(pgd_bad(pgd)); 354 - walk_pud(st, pgdp, addr); 353 + walk_pud(st, pgdp, addr, next); 355 354 } 356 - } 355 + } while (pgdp++, addr = next, addr != end); 357 356 } 358 357 359 358 void ptdump_walk_pgd(struct seq_file *m, struct ptdump_info *info)