This patch looks good -- if it wasn't layered on top of the KASLR patch,
I would check it into github.
This patch is almost independent from KASLR support, except that
adding new flags, VM_L4_4K and NEW_VMEMMAP, is conflicting.
When you merge it, please make a change.
-Takahiro AKASHI
Thanks,
Dave
----- Original Message -----
> From: AKASHI Takahiro <akax.hiro(a)gmail.com>
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi(a)linaro.org>
> ---
> arm64.c | 120
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
> defs.h | 25 +++++++++++++-
> 2 files changed, 137 insertions(+), 8 deletions(-)
>
> diff --git a/arm64.c b/arm64.c
> index c16ea67..b6bfbf3 100644
> --- a/arm64.c
> +++ b/arm64.c
> @@ -36,6 +36,7 @@ static int arm64_uvtop(struct task_context *, ulong,
> physaddr_t *, int);
> static int arm64_vtop_2level_64k(ulong, ulong, physaddr_t *, int);
> static int arm64_vtop_3level_64k(ulong, ulong, physaddr_t *, int);
> static int arm64_vtop_3level_4k(ulong, ulong, physaddr_t *, int);
> +static int arm64_vtop_4level_4k(ulong, ulong, physaddr_t *, int);
> static ulong arm64_get_task_pgd(ulong);
> static void arm64_irq_stack_init(void);
> static void arm64_stackframe_init(void);
> @@ -233,18 +234,26 @@ arm64_init(int when)
> switch (machdep->pagesize)
> {
> case 4096:
> - machdep->flags |= VM_L3_4K;
> machdep->ptrs_per_pgd = PTRS_PER_PGD_L3_4K;
> if ((machdep->pgd =
> (char *)malloc(PTRS_PER_PGD_L3_4K * 8)) == NULL)
> error(FATAL, "cannot malloc pgd space.");
> + if (machdep->machspec->VA_BITS > PGDIR_SHIFT_L4_4K) {
> + machdep->flags |= VM_L4_4K;
> + if ((machdep->pud =
> + (char *)malloc(PTRS_PER_PUD_L4_4K * 8))
> + == NULL)
> + error(FATAL, "cannot malloc pud space.");
> + } else {
> + machdep->flags |= VM_L3_4K;
> + machdep->pud = NULL; /* not used */
> + }
> if ((machdep->pmd =
> (char *)malloc(PTRS_PER_PMD_L3_4K * 8)) == NULL)
> error(FATAL, "cannot malloc pmd space.");
> if ((machdep->ptbl =
> (char *)malloc(PTRS_PER_PTE_L3_4K * 8)) == NULL)
> error(FATAL, "cannot malloc ptbl space.");
> - machdep->pud = NULL; /* not used */
> break;
>
> case 65536:
> @@ -282,8 +291,8 @@ arm64_init(int when)
> error(FATAL, "cannot determine page size\n");
> }
>
> - machdep->last_pud_read = 0; /* not used */
> machdep->last_pgd_read = 0;
> + machdep->last_pud_read = 0;
> machdep->last_pmd_read = 0;
> machdep->last_ptbl_read = 0;
> machdep->clear_machdep_cache = arm64_clear_machdep_cache;
> @@ -462,6 +471,8 @@ arm64_dump_machdep_table(ulong arg)
> fprintf(fp, "%sVM_L3_64K", others++ ? "|" : "");
> if (machdep->flags & VM_L3_4K)
> fprintf(fp, "%sVM_L3_4K", others++ ? "|" : "");
> + if (machdep->flags & VM_L4_4K)
> + fprintf(fp, "%sVM_L4_4K", others++ ? "|" : "");
> if (machdep->flags & VMEMMAP)
> fprintf(fp, "%sVMEMMAP", others++ ? "|" : "");
> if (machdep->flags & KDUMP_ENABLED)
> @@ -494,11 +505,15 @@ arm64_dump_machdep_table(ulong arg)
> fprintf(fp, " uvtop: arm64_uvtop()->%s()\n",
> machdep->flags & VM_L3_4K ?
> "arm64_vtop_3level_4k" :
> + machdep->flags & VM_L4_4K ?
> + "arm64_vtop_4level_4k" :
> machdep->flags & VM_L3_64K ?
> "arm64_vtop_3level_64k" : "arm64_vtop_2level_64k");
> fprintf(fp, " kvtop: arm64_kvtop()->%s()\n",
> machdep->flags & VM_L3_4K ?
> "arm64_vtop_3level_4k" :
> + machdep->flags & VM_L4_4K ?
> + "arm64_vtop_4level_4k" :
> machdep->flags & VM_L3_64K ?
> "arm64_vtop_3level_64k" : "arm64_vtop_2level_64k");
> fprintf(fp, " get_task_pgd: arm64_get_task_pgd()\n");
> @@ -531,8 +546,13 @@ arm64_dump_machdep_table(ulong arg)
> fprintf(fp, " xendump_panic_task: (n/a)\n");
> fprintf(fp, " get_xendump_regs: (n/a)\n");
> fprintf(fp, " line_number_hooks: (not used)\n");
> - fprintf(fp, " last_pud_read: (not used)\n");
> fprintf(fp, " last_pgd_read: %lx\n", machdep->last_pgd_read);
> + fprintf(fp, " last_pud_read: ");
> + if ((PAGESIZE() == 65536) ||
> + ((PAGESIZE() == 4096) && !(machdep->flags & VM_L4_4K)))
> + fprintf(fp, "(not used)\n");
> + else
> + fprintf(fp, "%lx\n", machdep->last_pud_read);
> fprintf(fp, " last_pmd_read: ");
> if (PAGESIZE() == 65536)
> fprintf(fp, "(not used)\n");
> @@ -541,6 +561,7 @@ arm64_dump_machdep_table(ulong arg)
> fprintf(fp, " last_ptbl_read: %lx\n", machdep->last_ptbl_read);
> fprintf(fp, " clear_machdep_cache: arm64_clear_machdep_cache()\n");
> fprintf(fp, " pgd: %lx\n", (ulong)machdep->pgd);
> + fprintf(fp, " pud: %lx\n", (ulong)machdep->pud);
> fprintf(fp, " pmd: %lx\n", (ulong)machdep->pmd);
> fprintf(fp, " ptbl: %lx\n", (ulong)machdep->ptbl);
> fprintf(fp, " ptrs_per_pgd: %d\n", machdep->ptrs_per_pgd);
> @@ -843,7 +864,7 @@ arm64_kvtop(struct task_context *tc, ulong kvaddr,
> physaddr_t *paddr, int verbos
> kernel_pgd = vt->kernel_pgd[0];
> *paddr = 0;
>
> - switch (machdep->flags & (VM_L2_64K|VM_L3_64K|VM_L3_4K))
> + switch (machdep->flags & (VM_L2_64K|VM_L3_64K|VM_L3_4K|VM_L4_4K))
> {
> case VM_L2_64K:
> return arm64_vtop_2level_64k(kernel_pgd, kvaddr, paddr, verbose);
> @@ -851,6 +872,8 @@ arm64_kvtop(struct task_context *tc, ulong kvaddr,
> physaddr_t *paddr, int verbos
> return arm64_vtop_3level_64k(kernel_pgd, kvaddr, paddr, verbose);
> case VM_L3_4K:
> return arm64_vtop_3level_4k(kernel_pgd, kvaddr, paddr, verbose);
> + case VM_L4_4K:
> + return arm64_vtop_4level_4k(kernel_pgd, kvaddr, paddr, verbose);
> default:
> return FALSE;
> }
> @@ -866,7 +889,7 @@ arm64_uvtop(struct task_context *tc, ulong uvaddr,
> physaddr_t *paddr, int verbos
>
> *paddr = 0;
>
> - switch (machdep->flags & (VM_L2_64K|VM_L3_64K|VM_L3_4K))
> + switch (machdep->flags & (VM_L2_64K|VM_L3_64K|VM_L3_4K|VM_L4_4K))
> {
> case VM_L2_64K:
> return arm64_vtop_2level_64k(user_pgd, uvaddr, paddr, verbose);
> @@ -874,6 +897,8 @@ arm64_uvtop(struct task_context *tc, ulong uvaddr,
> physaddr_t *paddr, int verbos
> return arm64_vtop_3level_64k(user_pgd, uvaddr, paddr, verbose);
> case VM_L3_4K:
> return arm64_vtop_3level_4k(user_pgd, uvaddr, paddr, verbose);
> + case VM_L4_4K:
> + return arm64_vtop_4level_4k(user_pgd, uvaddr, paddr, verbose);
> default:
> return FALSE;
> }
> @@ -1092,6 +1117,85 @@ no_page:
> return FALSE;
> }
>
> +static int
> +arm64_vtop_4level_4k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose)
> +{
> + ulong *pgd_base, *pgd_ptr, pgd_val;
> + ulong *pud_base, *pud_ptr, pud_val;
> + ulong *pmd_base, *pmd_ptr, pmd_val;
> + ulong *pte_base, *pte_ptr, pte_val;
> +
> + if (verbose)
> + fprintf(fp, "PAGE DIRECTORY: %lx\n", pgd);
> +
> + pgd_base = (ulong *)pgd;
> + FILL_PGD(pgd_base, KVADDR, PTRS_PER_PGD_L4_4K * sizeof(ulong));
> + pgd_ptr = pgd_base + (((vaddr) >> PGDIR_SHIFT_L4_4K) &
(PTRS_PER_PGD_L4_4K
> - 1));
> + pgd_val = ULONG(machdep->pgd + PGDIR_OFFSET(pgd_ptr));
> + if (verbose)
> + fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr,
> pgd_val);
> + if (!pgd_val)
> + goto no_page;
> +
> + pud_base = (ulong *)PTOV(pgd_val & PHYS_MASK & PGDIR_MASK);
> +
> + FILL_PUD(pud_base, KVADDR, PTRS_PER_PUD_L4_4K * sizeof(ulong));
> + pud_ptr = pud_base + (((vaddr) >> PUD_SHIFT_L4_4K) & (PTRS_PER_PUD_L4_4K
-
> 1));
> + pud_val = ULONG(machdep->pud + PAGEOFFSET(pud_ptr));
> + if (verbose)
> + fprintf(fp, " PUD: %lx => %lx\n", (ulong)pud_ptr,
> pud_val);
> + if (!pud_val)
> + goto no_page;
> +
> + pmd_base = (ulong *)PTOV(pud_val & PHYS_MASK &
(s32)machdep->pagemask);
> + FILL_PMD(pmd_base, KVADDR, PTRS_PER_PMD_L4_4K * sizeof(ulong));
> + pmd_ptr = pmd_base + (((vaddr) >> PMD_SHIFT_L4_4K) & (PTRS_PER_PMD_L4_4K
-
> 1));
> + pmd_val = ULONG(machdep->pmd + PAGEOFFSET(pmd_ptr));
> + if (verbose)
> + fprintf(fp, " PMD: %lx => %lx\n", (ulong)pmd_ptr,
> pmd_val);
> + if (!pmd_val)
> + goto no_page;
> +
> + if ((pmd_val & PMD_TYPE_MASK) == PMD_TYPE_SECT) {
> + ulong sectionbase = (pmd_val & SECTION_PAGE_MASK_2MB) & PHYS_MASK;
> + if (verbose) {
> + fprintf(fp, " PAGE: %lx (2MB)\n\n", sectionbase);
> + arm64_translate_pte(pmd_val, 0, 0);
> + }
> + *paddr = sectionbase + (vaddr & ~SECTION_PAGE_MASK_2MB);
> + return TRUE;
> + }
> +
> + pte_base = (ulong *)PTOV(pmd_val & PHYS_MASK &
(s32)machdep->pagemask);
> + FILL_PTBL(pte_base, KVADDR, PTRS_PER_PTE_L4_4K * sizeof(ulong));
> + pte_ptr = pte_base + (((vaddr) >> machdep->pageshift) &
(PTRS_PER_PTE_L4_4K
> - 1));
> + pte_val = ULONG(machdep->ptbl + PAGEOFFSET(pte_ptr));
> + if (verbose)
> + fprintf(fp, " PTE: %lx => %lx\n", (ulong)pte_ptr,
> pte_val);
> + if (!pte_val)
> + goto no_page;
> +
> + if (pte_val & PTE_VALID) {
> + *paddr = (PAGEBASE(pte_val) & PHYS_MASK) + PAGEOFFSET(vaddr);
> + if (verbose) {
> + fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr));
> + arm64_translate_pte(pte_val, 0, 0);
> + }
> + } else {
> + if (IS_UVADDR(vaddr, NULL))
> + *paddr = pte_val;
> + if (verbose) {
> + fprintf(fp, "\n");
> + arm64_translate_pte(pte_val, 0, 0);
> + }
> + goto no_page;
> + }
> +
> + return TRUE;
> +no_page:
> + return FALSE;
> +}
> +
> static ulong
> arm64_get_task_pgd(ulong task)
> {
> @@ -2556,7 +2660,7 @@ arm64_calc_virtual_memory_ranges(void)
>
> STRUCT_SIZE_INIT(page, "page");
>
> - switch (machdep->flags & (VM_L2_64K|VM_L3_64K|VM_L3_4K))
> + switch (machdep->flags & (VM_L2_64K|VM_L3_64K|VM_L3_4K|VM_L4_4K))
> {
> case VM_L2_64K:
> case VM_L3_64K:
> @@ -2564,6 +2668,8 @@ arm64_calc_virtual_memory_ranges(void)
> break;
> case VM_L3_4K:
> PUD_SIZE = PGDIR_SIZE_L3_4K;
> + case VM_L4_4K:
> + PUD_SIZE = PUD_SIZE_L4_4K;
> break;
> }
>
> diff --git a/defs.h b/defs.h
> index 406a865..17a4fbd 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -1054,7 +1054,7 @@ extern struct machdep_table *machdep;
> readmem((ulonglong)((ulong)(PGD)), TYPE, machdep->pgd,
> \
> SIZE, "pgd page", FAULT_ON_ERROR);
> \
> machdep->last_pgd_read = (ulong)(PGD);
> \
> - }
> + }
>
> #define FILL_PUD(PUD, TYPE, SIZE) \
> if (!IS_LAST_PUD_READ(PUD)) {
> \
> @@ -2884,6 +2884,28 @@ typedef signed int s32;
> #define PMD_MASK_L3_4K (~(PMD_SIZE_L3_4K-1))
>
> /*
> + * 4-levels / 4K pages
> + * 48-bit VA
> + */
> +#define PTRS_PER_PGD_L4_4K ((1UL) << (48 - 39))
> +#define PTRS_PER_PUD_L4_4K (512)
> +#define PTRS_PER_PMD_L4_4K (512)
> +#define PTRS_PER_PTE_L4_4K (512)
> +#define PGDIR_SHIFT_L4_4K (39)
> +#define PGDIR_SIZE_L4_4K ((1UL) << PGDIR_SHIFT_L4_4K)
> +#define PGDIR_MASK_L4_4K (~(PGDIR_SIZE_L4_4K-1))
> +#define PUD_SHIFT_L4_4K (30)
> +#define PUD_SIZE_L4_4K ((1UL) << PUD_SHIFT_L4_4K)
> +#define PUD_MASK_L4_4K (~(PUD_SIZE_L4_4K-1))
> +#define PMD_SHIFT_L4_4K (21)
> +#define PMD_SIZE_L4_4K (1UL << PMD_SHIFT_L4_4K)
> +#define PMD_MASK_L4_4K (~(PMD_SIZE_L4_4K-1))
> +
> +#define PGDIR_SIZE (1UL << ((48 - 39) + 3))
> +#define PGDIR_MASK (~(PGDIR_SIZE - 1))
> +#define PGDIR_OFFSET(X) (((ulong)(X)) & (PGDIR_SIZE - 1))
> +
> +/*
> * 3-levels / 64K pages
> */
> #define PTRS_PER_PGD_L3_64K (64)
> @@ -2941,6 +2963,7 @@ typedef signed int s32;
> #define KDUMP_ENABLED (0x20)
> #define IRQ_STACKS (0x40)
> #define NEW_VMEMMAP (0x80)
> +#define VM_L4_4K (0x100)
>
> /*
> * sources: Documentation/arm64/memory.txt
> --
> 2.8.1
>
> --
> Crash-utility mailing list
> Crash-utility(a)redhat.com
>
https://www.redhat.com/mailman/listinfo/crash-utility
>
--
Crash-utility mailing list
Crash-utility(a)redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility