----- Original Message -----
 Hi Dave,
 
 This patch introduces LPAE support for ARM32 platform. 
Nicely done -- I appreciate your efforts!
I can only test that this doesn't affect non-PAE dumpfiles.
Would it be possible for you to create a sample vmcore and
make it available to me to download for future testing?
Thanks again,
  Dave
 
 main description:
 
 (1) identify LPAE enabled vmcores:
 	PG_DIR_SIZE(LPAE:20K,other:16K)
 
 (2) section mapping size changed to 2MiB
 (3) virtual to physical address converting:
    (a)
 	#define PTRS_PER_PTE            512
 	#define PTRS_PER_PMD            512
 	#define PTRS_PER_PGD            4
 
    (b) Each ptr are 8-bit long, so we need sevel new
        macros to deal with them: FILL_PGD_LPAE ...
    (c) arm_translate_pte changed as x86_translate_pte
    (d) arm_lpae_vtop doing this converting
 
 Signed-off-by: Wei Jitao <weijitao(a)huawei.com>
 Signed-off-by: Liu Hua <sdu.liu(a)huawei.com>
 ---
  arm.c  | 134
  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
  defs.h |  77 +++++++++++++++++++++++++++++++++++++
  2 files changed, 200 insertions(+), 11 deletions(-)
 
 diff --git a/arm.c b/arm.c
 index 84dd3ec..001fe6b 100644
 --- a/arm.c
 +++ b/arm.c
 @@ -83,6 +83,7 @@ static struct arm_pt_regs *panic_task_regs;
  #define PMD_TYPE_MASK   3
  #define PMD_TYPE_SECT   2
  #define PMD_TYPE_TABLE  1
 +#define PMD_TYPE_SECT_LPAE 1
  
  static inline ulong *
  pmd_page_addr(ulong pmd)
 @@ -219,12 +220,19 @@ arm_init(int when)
  	case PRE_GDB:
  		if ((machdep->pgd = (char *)malloc(PGDIR_SIZE())) == NULL)
  			error(FATAL, "cannot malloc pgd space.");
 +		if ((machdep->pmd = (char *)malloc(PMDSIZE())) == NULL)
 +			error(FATAL, "cannot malloc pmd space.");
  		if ((machdep->ptbl = (char *)malloc(PAGESIZE())) == NULL)
  			error(FATAL, "cannot malloc ptbl space.");
  
  		/*
 -		 * Kernel text starts 16k after PAGE_OFFSET.
 +		 *LPAE requires an additional page for the PGD;
 +		 *So PG_DIR_SIZE =  0x5000 for LPAE
  		 */
 +
 +		if (symbol_value("_text") - symbol_value("swapper_pg_dir")
 +				== 0x5000)
 +			machdep->flags |= PAE;
  		machdep->kvbase = symbol_value("_stext") & ~KVBASE_MASK;
  		machdep->identity_map_base = machdep->kvbase;
  		machdep->is_kvaddr = arm_is_kvaddr;
 @@ -269,9 +277,13 @@ arm_init(int when)
  		if (THIS_KERNEL_VERSION >= LINUX(3,3,0) ||
  		    symbol_exists("idmap_pgd"))
  			machdep->flags |= IDMAP_PGD;
 -
 -		machdep->section_size_bits = _SECTION_SIZE_BITS;
 -		machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
 +		if (machdep->flags & PAE) {
 +			machdep->section_size_bits = _SECTION_SIZE_BITS_LPAE;
 +			machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_LPAE;
 +		} else {
 +			machdep->section_size_bits = _SECTION_SIZE_BITS;
 +			machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
 +		}
  
  		if (symbol_exists("irq_desc"))
  			ARRAY_LENGTH_INIT(machdep->nr_irqs, irq_desc,
 @@ -834,24 +846,32 @@ arm_processor_speed(void)
   * is passed in, don't print anything.
   */
  static int
 -arm_translate_pte(ulong pte, void *physaddr, ulonglong pae_pte)
 +arm_translate_pte(ulong pte, void *physaddr, ulonglong lpae_pte)
  {
  	char ptebuf[BUFSIZE];
  	char physbuf[BUFSIZE];
  	char buf[BUFSIZE];
  	int page_present;
 -	ulong paddr;
 +	ulonglong paddr;
  	int len1, len2, others;
  
 +	if (machdep->flags & PAE) {
 +		paddr = LPAE_PAGEBASE(lpae_pte);
 +		sprintf(ptebuf, "%llx", lpae_pte);
 +		pte = (ulong)lpae_pte;
 +	} else {
 +		paddr = PAGEBASE(pte);
 +		sprintf(ptebuf, "%lx", pte);
 +	}
  	page_present = pte_present(pte);
 -	paddr = PAGEBASE(pte);
 -
  	if (physaddr) {
 -		*((ulong *)physaddr) = paddr;
 +		if (machdep->flags & PAE)
 +			*((ulonglong *)physaddr) = paddr;
 +		else
 +			*((ulong *)physaddr) = (ulong)paddr;
  		return page_present;
  	}
  
 -	sprintf(ptebuf, "%lx", pte);
  	len1 = MAX(strlen(ptebuf), strlen("PTE"));
  	fprintf(fp, "%s  ", mkstring(buf, len1, CENTER | LJUST, "PTE"));
  
 @@ -860,7 +880,7 @@ arm_translate_pte(ulong pte, void *physaddr, ulonglong
 pae_pte)
  		return page_present;
  	}
  
 -	sprintf(physbuf, "%lx", paddr);
 +	sprintf(physbuf, "%llx", paddr);
  	len2 = MAX(strlen(physbuf), strlen("PHYSICAL"));
  	fprintf(fp, "%s  ", mkstring(buf, len2, CENTER | LJUST,
"PHYSICAL"));
  
 @@ -1049,6 +1069,91 @@ arm_vtop(ulong vaddr, ulong *pgd, physaddr_t *paddr,
 int verbose)
  }
  
  /*
 + *Virtual to physical memory translation when "CONFIG_ARM_LPAE=y".
 + *This function will be called by both arm_kvtop() and arm_uvtop().
 + */
 +static int
 +arm_lpae_vtop(ulong vaddr, ulong *pgd, physaddr_t *paddr, int verbose)
 +{
 +	char buf[BUFSIZE];
 +	physaddr_t page_dir;
 +	physaddr_t page_middle;
 +	physaddr_t page_table;
 +	pgd_t pgd_pmd;
 +	pmd_t pmd_pte;
 +	pte_t pte;
 +
 +	if (verbose)
 +		fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
 +
 +	/*
 +	 * pgd_offset(pgd, vaddr)
 +	 */
 +	page_dir = LPAE_VTOP((ulong)pgd + LPAE_PGD_OFFSET(vaddr) * 8);
 +	FILL_PGD_LPAE(LPAE_VTOP(pgd), PHYSADDR, LPAE_PGDIR_SIZE());
 +	pgd_pmd = ULONGLONG(machdep->pgd + LPAE_PGDIR_OFFSET(page_dir));
 +
 +	if (verbose)
 +		fprintf(fp, "  PGD: %8llx => %llx\n",
 +				(ulonglong)page_dir, pgd_pmd);
 +
 +	if (!pgd_pmd)
 +		return FALSE;
 +
 +	/*
 +	 * pmd_offset(pgd, vaddr)
 +	 */
 +	page_middle = LPAE_PAGEBASE(pgd_pmd) + LPAE_PMD_OFFSET(vaddr) * 8;
 +	FILL_PMD_LPAE(LPAE_PAGEBASE(pgd_pmd), PHYSADDR, LPAE_PMDIR_SIZE());
 +	pmd_pte = ULONGLONG(machdep->pmd + LPAE_PMDIR_OFFSET(page_middle));
 +
 +	if (!pmd_pte)
 +		return FALSE;
 +
 +	if ((pmd_pte & PMD_TYPE_MASK) == PMD_TYPE_SECT_LPAE) {
 +		ulonglong sectionbase = LPAE_PAGEBASE(pmd_pte)
 +					& LPAE_SECTION_PAGE_MASK;
 +
 +		if (verbose) {
 +				fprintf(fp, " PAGE: %8llx  (2MB)\n\n",
 +					(ulonglong)sectionbase);
 +		}
 +
 +		*paddr = sectionbase + (vaddr & ~LPAE_SECTION_PAGE_MASK);
 +		return TRUE;
 +	}
 +	/*
 +	 * pte_offset_map(pmd, vaddr)
 +	 */
 +	page_table = LPAE_PAGEBASE(pmd_pte) + PTE_OFFSET(vaddr) * 8;
 +	FILL_PTBL_LPAE(LPAE_PAGEBASE(pmd_pte), PHYSADDR, LPAE_PTEDIR_SIZE());
 +	pte = ULONGLONG(machdep->ptbl + LPAE_PTEDIR_OFFSET(page_table));
 +
 +	if (verbose) {
 +		fprintf(fp, "  PTE: %8llx => %llx\n\n",
 +			(ulonglong)page_table, pte);
 +	}
 +
 +	if (!pte_present(pte)) {
 +		if (pte && verbose) {
 +			fprintf(fp, "\n");
 +			arm_translate_pte(0, 0, pte);
 +		}
 +		return FALSE;
 +	}
 +
 +	*paddr = LPAE_PAGEBASE(pte) + PAGEOFFSET(vaddr);
 +
 +	if (verbose) {
 +		fprintf(fp, " PAGE: %s\n\n",
 +		mkstring(buf, VADDR_PRLEN, RJUST | LONG_HEX,
 +					MKSTR(PAGEBASE(pte))));
 +		arm_translate_pte(0, 0, pte);
 +	}
 +	return TRUE;
 +}
 +
 +/*
   * Translates a user virtual address to its physical address. cmd_vtop()
   sets
   * the verbose flag so that the pte translation gets displayed; all other
   * callers quietly accept the translation.
 @@ -1098,6 +1203,9 @@ arm_uvtop(struct task_context *tc, ulong uvaddr,
 physaddr_t *paddr, int verbose)
  				FAULT_ON_ERROR);
  	}
  
 +	if (machdep->flags & PAE)
 +		return arm_lpae_vtop(uvaddr, pgd, paddr, verbose);
 +
  	return arm_vtop(uvaddr, pgd, paddr, verbose);
  }
  
 @@ -1123,6 +1231,10 @@ arm_kvtop(struct task_context *tc, ulong kvaddr,
 physaddr_t *paddr, int verbose)
  			return TRUE;
  	}
  
 +	if (machdep->flags & PAE)
 +		return arm_lpae_vtop(kvaddr,
 +				(ulong *)vt->kernel_pgd[0], paddr, verbose);
 +
  	return arm_vtop(kvaddr, (ulong *)vt->kernel_pgd[0], paddr, verbose);
  }
  
 diff --git a/defs.h b/defs.h
 index 0ae4e48..44df6ae 100644
 --- a/defs.h
 +++ b/defs.h
 @@ -2647,6 +2647,80 @@ struct load_module {
  #define _SECTION_SIZE_BITS	28
  #define _MAX_PHYSMEM_BITS	32
  
 +/*add for LPAE*/
 +typedef unsigned long long u64;
 +typedef signed int         s32;
 +typedef u64 pgd_t;
 +typedef u64 pmd_t;
 +typedef u64 pte_t;
 +
 +#define PMDSIZE()		(PAGESIZE())
 +#define LPAE_PGDIR_SHIFT	(30)
 +#define LPAE_PMDIR_SHIFT	(21)
 +
 +#define LPAE_PGD_OFFSET(vaddr)  ((vaddr) >> LPAE_PGDIR_SHIFT)
 +#define LPAE_PMD_OFFSET(vaddr)  (((vaddr) >> LPAE_PMDIR_SHIFT) & \
 +				((1<<(LPAE_PGDIR_SHIFT-LPAE_PMDIR_SHIFT))-1))
 +
 +#define _SECTION_SIZE_BITS_LPAE	28
 +#define _MAX_PHYSMEM_BITS_LPAE	36
 +
 +/*
 + * #define PTRS_PER_PTE            512
 + * #define PTRS_PER_PMD            512
 + * #define PTRS_PER_PGD            4
 + *
 + */
 +
 +#define LPAE_PGDIR_SIZE()	32
 +#define LPAE_PGDIR_OFFSET(X)	(((ulong)(X)) & (LPAE_PGDIR_SIZE() - 1))
 +
 +#define LPAE_PMDIR_SIZE()	4096
 +#define LPAE_PMDIR_OFFSET(X)	(((ulong)(X)) & (LPAE_PMDIR_SIZE() - 1))
 +
 +#define LPAE_PTEDIR_SIZE()	4096
 +#define LPAE_PTEDIR_OFFSET(X)	(((ulong)(X)) & (LPAE_PTEDIR_SIZE() - 1))
 +
 +/*section size for LPAE is 2MiB*/
 +#define LPAE_SECTION_PAGE_MASK	(~((MEGABYTES(2))-1))
 +
 +#define _PHYSICAL_MASK_LPAE         ((1ULL << _MAX_PHYSMEM_BITS_LPAE) - 1)
 +#define PAGE_BASE_MASK    ((u64)((s32)machdep->pagemask &
 _PHYSICAL_MASK_LPAE))
 +#define LPAE_PAGEBASE(X)                (((ulonglong)(X)) & PAGE_BASE_MASK)
 +
 +#define LPAE_VTOP(X) \
 +	((unsigned long long)(unsigned long)(X) - \
 +			(machdep->kvbase) + (machdep->machspec->phys_base))
 +
 +#define IS_LAST_PGD_READ_LPAE(pgd)     ((pgd) == \
 +					machdep->machspec->last_pgd_read_lpae)
 +#define IS_LAST_PMD_READ_LPAE(pmd)     ((pmd) == \
 +					machdep->machspec->last_pmd_read_lpae)
 +#define IS_LAST_PTBL_READ_LPAE(ptbl)   ((ptbl) == \
 +					machdep->machspec->last_ptbl_read_lpae)
 +
 +#define FILL_PGD_LPAE(PGD, TYPE, SIZE)			                    \
 +	if (!IS_LAST_PGD_READ_LPAE(PGD)) {                                  \
 +		readmem((ulonglong)(PGD), TYPE, machdep->pgd,               \
 +			SIZE, "pmd page", FAULT_ON_ERROR);                   \
 +		machdep->machspec->last_pgd_read_lpae \
 +						= (ulonglong)(PGD);        \
 +	}
 +#define FILL_PMD_LPAE(PMD, TYPE, SIZE)			                    \
 +	if (!IS_LAST_PMD_READ_LPAE(PMD)) {                                  \
 +		readmem((ulonglong)(PMD), TYPE, machdep->pmd,               \
 +			SIZE, "pmd page", FAULT_ON_ERROR);                  \
 +		machdep->machspec->last_pmd_read_lpae \
 +						= (ulonglong)(PMD);        \
 +	}
 +
 +#define FILL_PTBL_LPAE(PTBL, TYPE, SIZE)		          	    \
 +	if (!IS_LAST_PTBL_READ_LPAE(PTBL)) {                                \
 +		readmem((ulonglong)(PTBL), TYPE, machdep->ptbl,              \
 +			SIZE, "page table", FAULT_ON_ERROR);                 \
 +		machdep->machspec->last_ptbl_read_lpae \
 +						= (ulonglong)(PTBL); 	    \
 +	}
  #endif  /* ARM */
  
  #ifndef EM_AARCH64
 @@ -4979,6 +5053,9 @@ struct machine_specific {
  	ulong kernel_text_end;
  	ulong exception_text_start;
  	ulong exception_text_end;
 +	ulonglong last_pgd_read_lpae;
 +	ulonglong last_pmd_read_lpae;
 +	ulonglong last_ptbl_read_lpae;
  	struct arm_pt_regs *crash_task_regs;
  	int unwind_index_prel31;
  };
 --
 1.9.0