This patch adds the generic vmalloc address translation support for PPC32. There are different types of platforms under PPC32 and the vmalloc translation requires the knowledge about the page translation bits for each of them. This patch introduces a generic translation routine with some default values which may work well for most of the platforms. Later patches in this series would add an infrastructure to identify the platforms and dynamically change the translation based on the platform definition. Signed-off-by: Suzuki K. Poulose <suzuki at in.ibm.com> --- arch/ppc.c | 40 ++++++++++++++++++++++++++++++++++++---- makedumpfile.h | 6 ++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/arch/ppc.c b/arch/ppc.c index 2bc8d5f..2ca0dc5 100644 --- a/arch/ppc.c +++ b/arch/ppc.c @@ -77,7 +77,9 @@ vaddr_to_paddr_ppc(unsigned long vaddr) { unsigned long *pgd, *pmd; unsigned long long pte; + unsigned long pte_32; unsigned long long paddr; + int res = 0; paddr = vaddr_to_paddr_general(vaddr); if (paddr != NOT_PADDR) @@ -91,10 +93,40 @@ vaddr_to_paddr_ppc(unsigned long vaddr) if (!is_vmalloc_addr_ppc(vaddr)) return (vaddr - info->kernel_start); - /* - * TODO: Support vmalloc translation. - */ - ERRMSG("This makedumpfile does not support vmalloc translation.\n"); + if ((SYMBOL(swapper_pg_dir) == NOT_FOUND_SYMBOL) && + !readmem(VADDR, SYMBOL(swapper_pg_dir), &pgd, sizeof(pgd))) { + ERRMSG("Can't get the PGD for vmalloc translation. \n"); + return NOT_PADDR; + } + + pgd += vaddr >> PGDIR_SHIFT; + DEBUG_MSG("vaddr: 0x%lx , PGD = 0x%lx\n", vaddr, (unsigned long)pgd); + if (!readmem(VADDR, (unsigned long)pgd, &pmd, sizeof(pmd))) { + ERRMSG("Can't get the PMD for address 0x%lx\n.", vaddr); + return NOT_PADDR; + } + + pmd += (PAGEBASE(vaddr) & (PTRS_PER_PTE - 1)); + DEBUG_MSG("vaddr: 0x%lx , PMD = 0x%lx\n", vaddr, (unsigned long)pmd); + + if (PTE_SIZE == sizeof(unsigned long long)) + res = readmem(VADDR, (unsigned long)pmd, &pte, sizeof(pte)); + else { + res = readmem(VADDR, (unsigned long)pmd, &pte_32, sizeof(pte_32)); + pte = pte_32; + } + + if (!res) { + ERRMSG("Can't get PTE for address 0x%lx\n", vaddr); + return NOT_PADDR; + } + + DEBUG_MSG("vaddr: 0x%lx , PTE = 0x%llx\n", vaddr, (unsigned long long)pte); + if (pte & _PAGE_PRESENT) { + paddr = PAGEBASE(pte) | PAGEOFFSET(vaddr); + return paddr; + } + return NOT_PADDR; } diff --git a/makedumpfile.h b/makedumpfile.h index 9dc254e..f7603d7 100644 --- a/makedumpfile.h +++ b/makedumpfile.h @@ -539,6 +539,12 @@ do { \ #define _SECTION_SIZE_BITS (24) #define _MAX_PHYSMEM_BITS (44) +#define PGDIR_SHIFT (22) +#define PTRS_PER_PTE (1024) +#define PTE_SIZE (sizeof(unsigned long)) + +#define _PAGE_PRESENT (0x1) + #endif #ifdef __s390x__