----- 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@xxxxxxxxxx> > Signed-off-by: Liu Hua <sdu.liu@xxxxxxxxxx> > --- > 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 > > -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility