>This patch adds virtual to physical address translation support >for vmalloc region in PPC64 architecture. > >Signed-off-by: Hari Bathini <hbathini at linux.vnet.ibm.com> >--- > arch/ppc64.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++------- > makedumpfile.h | 3 ++ > 2 files changed, 91 insertions(+), 12 deletions(-) > >diff --git a/arch/ppc64.c b/arch/ppc64.c >index 8c7eaa7..8bb90d9 100644 >--- a/arch/ppc64.c >+++ b/arch/ppc64.c >@@ -24,6 +24,8 @@ > #include "../elf_info.h" > #include "../makedumpfile.h" > >+static char *page_buf; /* Page buffer to read page tables */ >+ > /* > * This function traverses vmemmap list to get the count of vmemmap regions > * and populates the regions' info in info->vmemmap_list[] >@@ -224,6 +226,83 @@ ppc64_vmemmap_to_phys(unsigned long vaddr) > return paddr; > } > >+static unsigned long long >+ppc64_vtop_level4(unsigned long vaddr) >+{ >+ ulong *level4, *level4_dir; >+ ulong *page_dir, *page_middle; >+ ulong *page_table; >+ unsigned long long level4_pte, pgd_pte; >+ unsigned long long pmd_pte, pte; >+ unsigned long long paddr = NOT_PADDR; >+ >+ if (page_buf == NULL) { >+ /* >+ * This is the first vmalloc address translation request >+ */ >+ page_buf = (char *)calloc(1, PAGESIZE()); Hmm, the v2 way can't free this buffer at the appropriate time, sorry. Could you put it back in struct DumpInfo like v1 and free it at the end of main() ? Thanks Atsushi Kumagai >+ if (page_buf == NULL) { >+ ERRMSG("Can't allocate memory to read page tables. %s\n", >+ strerror(errno)); >+ return NOT_PADDR; >+ } >+ } >+ >+ level4 = (ulong *)info->kernel_pgd; >+ level4_dir = (ulong *)((ulong *)level4 + L4_OFFSET(vaddr)); >+ if (!readmem(VADDR, PAGEBASE(level4), page_buf, PAGESIZE())) { >+ ERRMSG("Can't read level4 page: 0x%llx\n", PAGEBASE(level4)); >+ return NOT_PADDR; >+ } >+ level4_pte = ULONG((page_buf + PAGEOFFSET(level4_dir))); >+ if (!level4_pte) >+ return NOT_PADDR; >+ >+ /* >+ * Sometimes we don't have level3 pagetable entries >+ */ >+ if (info->l3_index_size != 0) { >+ page_dir = (ulong *)((ulong *)level4_pte + PGD_OFFSET_L4(vaddr)); >+ if (!readmem(VADDR, PAGEBASE(level4_pte), page_buf, PAGESIZE())) { >+ ERRMSG("Can't read PGD page: 0x%llx\n", PAGEBASE(level4_pte)); >+ return NOT_PADDR; >+ } >+ pgd_pte = ULONG((page_buf + PAGEOFFSET(page_dir))); >+ if (!pgd_pte) >+ return NOT_PADDR; >+ } else { >+ pgd_pte = level4_pte; >+ } >+ >+ page_middle = (ulong *)((ulong *)pgd_pte + PMD_OFFSET_L4(vaddr)); >+ if (!readmem(VADDR, PAGEBASE(pgd_pte), page_buf, PAGESIZE())) { >+ ERRMSG("Can't read PMD page: 0x%llx\n", PAGEBASE(pgd_pte)); >+ return NOT_PADDR; >+ } >+ pmd_pte = ULONG((page_buf + PAGEOFFSET(page_middle))); >+ if (!(pmd_pte)) >+ return NOT_PADDR; >+ >+ page_table = (ulong *)(pmd_pte & ~(info->l2_masked_bits)) >+ + (BTOP(vaddr) & (info->ptrs_per_l1 - 1)); >+ if (!readmem(VADDR, PAGEBASE(pmd_pte), page_buf, PAGESIZE())) { >+ ERRMSG("Can't read page table: 0x%llx\n", PAGEBASE(pmd_pte)); >+ return NOT_PADDR; >+ } >+ pte = ULONG((page_buf + PAGEOFFSET(page_table))); >+ if (!(pte & _PAGE_PRESENT)) { >+ ERRMSG("Page not present!\n"); >+ return NOT_PADDR; >+ } >+ >+ if (!pte) >+ return NOT_PADDR; >+ >+ paddr = PAGEBASE(PTOB(pte >> info->pte_shift)) + PAGEOFFSET(vaddr); >+ >+ return paddr; >+} >+ > int > set_ppc64_max_physmem_bits(void) > { >@@ -347,10 +426,18 @@ vaddr_to_paddr_ppc64(unsigned long vaddr) > { > unsigned long long paddr; > >+ if ((info->flag_vmemmap) >+ && (vaddr >= info->vmemmap_start)) { >+ return ppc64_vmemmap_to_phys(vaddr); >+ } >+ > paddr = vaddr_to_paddr_general(vaddr); > if (paddr != NOT_PADDR) > return paddr; > >+ if (!is_vmalloc_addr_ppc64(vaddr)) >+ return (vaddr - info->kernel_start); >+ > if ((SYMBOL(vmap_area_list) == NOT_FOUND_SYMBOL) > || (OFFSET(vmap_area.va_start) == NOT_FOUND_STRUCTURE) > || (OFFSET(vmap_area.list) == NOT_FOUND_STRUCTURE)) { >@@ -360,19 +447,8 @@ vaddr_to_paddr_ppc64(unsigned long vaddr) > return NOT_PADDR; > } > } >- if (!is_vmalloc_addr_ppc64(vaddr)) >- return (vaddr - info->kernel_start); > >- if ((info->flag_vmemmap) >- && (vaddr >= info->vmemmap_start)) { >- return ppc64_vmemmap_to_phys(vaddr); >- } >- >- /* >- * TODO: Support vmalloc translation. >- */ >- ERRMSG("This makedumpfile does not support vmalloc translation.\n"); >- return NOT_PADDR; >+ return ppc64_vtop_level4(vaddr); > } > > #endif /* powerpc64 */ >diff --git a/makedumpfile.h b/makedumpfile.h >index 8510b8f..dba3a0c 100644 >--- a/makedumpfile.h >+++ b/makedumpfile.h >@@ -158,6 +158,9 @@ isAnon(unsigned long mapping) > return ((unsigned long)mapping & PAGE_MAPPING_ANON) != 0; > } > >+#define PTOB(X) (((unsigned long long)(X)) << PAGESHIFT()) >+#define BTOP(X) (((unsigned long long)(X)) >> PAGESHIFT()) >+ > #define PAGESIZE() (info->page_size) > #define PAGESHIFT() (info->page_shift) > #define PAGEOFFSET(X) (((unsigned long long)(X)) & (PAGESIZE() - 1))