[PATCH v1 2/4] [makedumpfile][ppc] Generic vmalloc translation support

Suzuki K. Poulose suzuki at in.ibm.com
Wed Feb 15 22:36:18 EST 2012


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__




More information about the kexec mailing list