[PATCH 2/2] makedumpfile: vtop address translation support for vmalloc region in PPC64 arch

Hari Bathini hbathini at linux.vnet.ibm.com
Thu Jul 17 07:19:15 PDT 2014


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   |   84 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 makedumpfile.h |    3 ++
 2 files changed, 75 insertions(+), 12 deletions(-)

diff --git a/arch/ppc64.c b/arch/ppc64.c
index dabf2e7..609aaa2 100644
--- a/arch/ppc64.c
+++ b/arch/ppc64.c
@@ -224,6 +224,69 @@ 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;
+
+	level4 = (ulong *)info->kernel_pgd;
+	level4_dir = (ulong *)((ulong *)level4 + L4_OFFSET(vaddr));
+	if (!readmem(VADDR, PAGEBASE(level4), info->page_buf, PAGESIZE())) {
+		ERRMSG("Can't read level4 page: 0x%llx\n", PAGEBASE(level4));
+		return NOT_PADDR;
+	}
+	level4_pte = ULONG((info->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), info->page_buf, PAGESIZE())) {
+			ERRMSG("Can't read PGD page: 0x%llx\n", PAGEBASE(level4_pte));
+			return NOT_PADDR;
+		}
+                pgd_pte = ULONG((info->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), info->page_buf, PAGESIZE())) {
+		ERRMSG("Can't read PMD page: 0x%llx\n", PAGEBASE(pgd_pte));
+		return NOT_PADDR;
+	}
+        pmd_pte = ULONG((info->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), info->page_buf, PAGESIZE())) {
+		ERRMSG("Can't read page table: 0x%llx\n", PAGEBASE(pmd_pte));
+		return NOT_PADDR;
+	}
+        pte = ULONG((info->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 +410,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 +431,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 7816241..778f36f 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)) << info->page_shift)
+#define BTOP(X)			(((unsigned long long)(X)) >> info->page_shift)
+
 #define PAGESIZE()		(info->page_size)
 #define PAGESHIFT()		(info->page_shift)
 #define PAGEOFFSET(X)		(((unsigned long long)(X)) & (PAGESIZE() - 1))




More information about the kexec mailing list