[Crash-utility] [PATCH 2/2] ARM: add support for the new page table format introduced in 2.6.38

Dave Anderson anderson at redhat.com
Fri Jan 28 15:19:46 UTC 2011



----- Original Message -----
> Starting from 2.6.38 ARM hardware and Linux page tables switched place. There
> were also some smaller changes to the PTE bits. This patch makes crash to cope
> with those changes.
> 
> Signed-off-by: Mika Westerberg <ext-mika.1.westerberg at nokia.com>
> ---

Queued for the next release.

> Dave,
> 
> Are you interested in having a reference vmlinux/vmcore pair for .38 ARM
> kernels? I can try to arrange such if needed and provide download url in
> a private email.

Yes pease, another small one would be great.

Thanks,
  Dave
 
> Regards,
> MW
> 
> 
> arm.c | 63
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
> defs.h | 1 +
> 2 files changed, 55 insertions(+), 9 deletions(-)
> 
> diff --git a/arm.c b/arm.c
> index 1752f62..0347166 100644
> --- a/arm.c
> +++ b/arm.c
> @@ -6,7 +6,7 @@
> * Jan Karlsson <jan.karlsson at sonyericsson.com>
> * Mika Westerberg <ext-mika.1.westerberg at nokia.com>
> *
> - * Copyright (C) 2010 Nokia Corporation
> + * Copyright (C) 2010-2011 Nokia Corporation
> * Copyright (C) 2010 Sony Ericsson. All rights reserved.
> *
> * This program is free software; you can redistribute it and/or modify
> @@ -88,8 +88,12 @@ pmd_page_addr(ulong pmd)
> {
> ulong ptr;
> 
> - ptr = pmd & ~(PTRS_PER_PTE * sizeof(void *) - 1);
> - ptr += PTRS_PER_PTE * sizeof(void *);
> + if (machdep->flags & PGTABLE_V2) {
> + ptr = PAGEBASE(pmd);
> + } else {
> + ptr = pmd & ~(PTRS_PER_PTE * sizeof(void *) - 1);
> + ptr += PTRS_PER_PTE * sizeof(void *);
> + }
> 
> return (ulong *)ptr;
> }
> @@ -102,16 +106,21 @@ pmd_page_addr(ulong pmd)
> #define L_PTE_FILE (1 << 2)
> #define L_PTE_DIRTY (1 << 6)
> #define L_PTE_WRITE (1 << 7)
> +#define L_PTE_RDONLY L_PTE_WRITE
> #define L_PTE_USER (1 << 8)
> #define L_PTE_EXEC (1 << 9)
> +#define L_PTE_XN L_PTE_EXEC
> #define L_PTE_SHARED (1 << 10)
> 
> #define pte_val(pte) (pte)
> 
> #define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT)
> #define pte_write(pte) (pte_val(pte) & L_PTE_WRITE)
> +#define pte_rdonly(pte) (pte_val(pte) & L_PTE_RDONLY)
> #define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
> #define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
> +#define pte_exec(pte) (pte_val(pte) & L_PTE_EXEC)
> +#define pte_xn(pte) (pte_val(pte) & L_PTE_XN)
> 
> /*
> * Following stuff is taken directly from the kernel sources. These are
> used in
> @@ -241,6 +250,16 @@ arm_init(int when)
> break;
> 
> case POST_GDB:
> + /*
> + * Starting from 2.6.38 hardware and Linux page tables
> + * were reordered. See also mainline kernel commit
> + * d30e45eeabe (ARM: pgtable: switch order of Linux vs
> + * hardware page tables).
> + */
> + if (THIS_KERNEL_VERSION > LINUX(2,6,37) ||
> + STRUCT_EXISTS("pteval_t"))
> + machdep->flags |= PGTABLE_V2;
> +
> if (symbol_exists("irq_desc"))
> ARRAY_LENGTH_INIT(machdep->nr_irqs, irq_desc,
> "irq_desc", NULL, 0);
> @@ -313,6 +332,8 @@ arm_dump_machdep_table(ulong arg)
> fprintf(fp, "%sKSYMS_START", others++ ? "|" : "");
> if (machdep->flags & PHYS_BASE)
> fprintf(fp, "%sPHYS_BASE", others++ ? "|" : "");
> + if (machdep->flags & PGTABLE_V2)
> + fprintf(fp, "%sPGTABLE_V2", others++ ? "|" : "");
> fprintf(fp, ")\n");
> 
> fprintf(fp, " kvbase: %lx\n", machdep->kvbase);
> @@ -823,12 +844,21 @@ arm_translate_pte(ulong pte, void *physaddr,
> ulonglong pae_pte)
> if (pte) {
> if (pte_present(pte))
> fprintf(fp, "%sPRESENT", others++ ? "|" : "");
> - if (pte_write(pte))
> - fprintf(fp, "%sWRITE", others++ ? "|" : "");
> if (pte_dirty(pte))
> fprintf(fp, "%sDIRTY", others++ ? "|" : "");
> if (pte_young(pte))
> fprintf(fp, "%sYOUNG", others++ ? "|" : "");
> + if (machdep->flags & PGTABLE_V2) {
> + if (!pte_rdonly(pte))
> + fprintf(fp, "%sWRITE", others++ ? "|" : "");
> + if (!pte_xn(pte))
> + fprintf(fp, "%sEXEC", others++ ? "|" : "");
> + } else {
> + if (pte_write(pte))
> + fprintf(fp, "%sWRITE", others++ ? "|" : "");
> + if (pte_exec(pte))
> + fprintf(fp, "%sEXEC", others++ ? "|" : "");
> + }
> } else {
> fprintf(fp, "no mapping");
> }
> @@ -863,6 +893,8 @@ arm_vtop(ulong vaddr, ulong *pgd, physaddr_t
> *paddr, int verbose)
> * that in ARM Linux we have following setup (see also
> * arch/arm/include/asm/pgtable.h)
> *
> + * Before 2.6.38
> + *
> * PGD PTE
> * +---------+
> * | | 0 ----> +------------+
> @@ -875,15 +907,28 @@ arm_vtop(ulong vaddr, ulong *pgd, physaddr_t
> *paddr, int verbose)
> * | | 4095 | Linux pt 1 |
> * +---------+ +------------+ +4096
> *
> + * Starting from 2.6.38
> + *
> + * PGD PTE
> + * +---------+
> + * | | 0 ----> +------------+
> + * +- - - - -+ | Linux pt 0 |
> + * | | 4 ----> +------------+ +1024
> + * +- - - - -+ | Linux pt 1 |
> + * . . +------------+ +2048
> + * . . | h/w pt 0 |
> + * . . +------------+ +3072
> + * | | 4095 | h/w pt 1 |
> + * +---------+ +------------+ +4096
> + *
> * So in Linux implementation we have two hardware pointers to second
> - * level page tables. After these come "Linux" versions of the page
> - * tables.
> + * level page tables. Depending on the kernel version, the "Linux"
> page
> + * tables either follow or precede the hardware tables.
> *
> * Linux PT entries contain bits that are not supported on hardware,
> for
> * example "young" and "dirty" flags.
> *
> - * Our translation scheme only uses Linux PTEs here. Hardware entries
> - * are 1024 bytes below Linux versions.
> + * Our translation scheme only uses Linux PTEs here.
> */
> 
> if (verbose)
> diff --git a/defs.h b/defs.h
> index 22f876b..e1b7d01 100755
> --- a/defs.h
> +++ b/defs.h
> @@ -4097,6 +4097,7 @@ struct arm_pt_regs {
> 
> #define KSYMS_START (0x1)
> #define PHYS_BASE (0x2)
> +#define PGTABLE_V2 (0x4)
> 
> struct machine_specific {
> ulong phys_base;
> --
> 1.7.3.2
> 
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility




More information about the Crash-utility mailing list