1
0
Fork 0

arm64 fixes for -rc6

- Fix kernel oops when attemping kexec_file() with a NULL cmdline
 
 - Fix page table output in debugfs when CONFIG_ARM64_USER_VA_BITS_52=y
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEPxTL6PPUbjXGY88ct6xw3ITBYzQFAlxdeK4ACgkQt6xw3ITB
 YzTwrwgArV1AHQTG6HG0Xz86zNbjA25XHr1HFTl75Q7SRu8lufxUXJ/JbIfE5v/v
 D/a40PDsWQeXMHvZT0C/DyByfbfSSigLAwS/psZxmjT5KDgfQCor01UjtWvh+DS+
 U7DnXjLxJFZZ13dJmMPGn3JGmNB5VoKv6w3+9f2rZgECZXdVBQzGPopmjhjmVx5/
 ncGLF4ecxQ1+ldIGGTIC5NSYsFPyhcKxYRlQ/sT/d5oN3wIJNixj7yL14jzx3izG
 OEsu967q3Ajn5lMs2j3k1ixopeOLWYOsSB27oWczJ/XAB4EGU9bbuHOz4alDpE5X
 oDIFuJGrD6s6Ba5E62XtHfp62Iy5pg==
 =UCO2
 -----END PGP SIGNATURE-----

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
hifive-unleashed-5.1
Linus Torvalds 2019-02-08 16:21:33 -08:00
commit 5bb513ed83
2 changed files with 32 additions and 31 deletions

View File

@ -120,10 +120,12 @@ static int create_dtb(struct kimage *image,
{
void *buf;
size_t buf_size;
size_t cmdline_len;
int ret;
cmdline_len = cmdline ? strlen(cmdline) : 0;
buf_size = fdt_totalsize(initial_boot_params)
+ strlen(cmdline) + DTB_EXTRA_SPACE;
+ cmdline_len + DTB_EXTRA_SPACE;
for (;;) {
buf = vmalloc(buf_size);

View File

@ -286,74 +286,73 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
}
static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start)
static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start,
unsigned long end)
{
pte_t *ptep = pte_offset_kernel(pmdp, 0UL);
unsigned long addr;
unsigned i;
unsigned long addr = start;
pte_t *ptep = pte_offset_kernel(pmdp, start);
for (i = 0; i < PTRS_PER_PTE; i++, ptep++) {
addr = start + i * PAGE_SIZE;
do {
note_page(st, addr, 4, READ_ONCE(pte_val(*ptep)));
}
} while (ptep++, addr += PAGE_SIZE, addr != end);
}
static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start)
static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start,
unsigned long end)
{
pmd_t *pmdp = pmd_offset(pudp, 0UL);
unsigned long addr;
unsigned i;
unsigned long next, addr = start;
pmd_t *pmdp = pmd_offset(pudp, start);
for (i = 0; i < PTRS_PER_PMD; i++, pmdp++) {
do {
pmd_t pmd = READ_ONCE(*pmdp);
next = pmd_addr_end(addr, end);
addr = start + i * PMD_SIZE;
if (pmd_none(pmd) || pmd_sect(pmd)) {
note_page(st, addr, 3, pmd_val(pmd));
} else {
BUG_ON(pmd_bad(pmd));
walk_pte(st, pmdp, addr);
walk_pte(st, pmdp, addr, next);
}
}
} while (pmdp++, addr = next, addr != end);
}
static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start)
static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start,
unsigned long end)
{
pud_t *pudp = pud_offset(pgdp, 0UL);
unsigned long addr;
unsigned i;
unsigned long next, addr = start;
pud_t *pudp = pud_offset(pgdp, start);
for (i = 0; i < PTRS_PER_PUD; i++, pudp++) {
do {
pud_t pud = READ_ONCE(*pudp);
next = pud_addr_end(addr, end);
addr = start + i * PUD_SIZE;
if (pud_none(pud) || pud_sect(pud)) {
note_page(st, addr, 2, pud_val(pud));
} else {
BUG_ON(pud_bad(pud));
walk_pmd(st, pudp, addr);
walk_pmd(st, pudp, addr, next);
}
}
} while (pudp++, addr = next, addr != end);
}
static void walk_pgd(struct pg_state *st, struct mm_struct *mm,
unsigned long start)
{
pgd_t *pgdp = pgd_offset(mm, 0UL);
unsigned i;
unsigned long addr;
unsigned long end = (start < TASK_SIZE_64) ? TASK_SIZE_64 : 0;
unsigned long next, addr = start;
pgd_t *pgdp = pgd_offset(mm, start);
for (i = 0; i < PTRS_PER_PGD; i++, pgdp++) {
do {
pgd_t pgd = READ_ONCE(*pgdp);
next = pgd_addr_end(addr, end);
addr = start + i * PGDIR_SIZE;
if (pgd_none(pgd)) {
note_page(st, addr, 1, pgd_val(pgd));
} else {
BUG_ON(pgd_bad(pgd));
walk_pud(st, pgdp, addr);
walk_pud(st, pgdp, addr, next);
}
}
} while (pgdp++, addr = next, addr != end);
}
void ptdump_walk_pgd(struct seq_file *m, struct ptdump_info *info)