[Crash-utility] [PATCH v2 5/6] x86_64: Add 5-level paging support for x86_64_k/uvtop()

Dou Liyang douly.fnst at cn.fujitsu.com
Fri Jan 12 10:12:55 UTC 2018


Add the support for x86_64 5-level page tables. Squeeze the 5-level support
into the currently existing x86_64_kvtop() and x86_64_uvtop() functions instead
of using the new xxx_5level() function placeholders.

Signed-off-by: Dou Liyang <douly.fnst at cn.fujitsu.com>
---
 x86_64.c | 90 +++++++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 63 insertions(+), 27 deletions(-)

diff --git a/x86_64.c b/x86_64.c
index 8914830..944c7ee 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -19,13 +19,11 @@
 #ifdef X86_64
 
 static int x86_64_kvtop(struct task_context *, ulong, physaddr_t *, int);
-static int x86_64_kvtop_5level(struct task_context *, ulong, physaddr_t *, int);
 static int x86_64_kvtop_xen_wpt(struct task_context *, ulong, physaddr_t *, int);
 static int x86_64_uvtop(struct task_context *, ulong, physaddr_t *, int);
 static int x86_64_uvtop_level4(struct task_context *, ulong, physaddr_t *, int);
 static int x86_64_uvtop_level4_xen_wpt(struct task_context *, ulong, physaddr_t *, int);
 static int x86_64_uvtop_level4_rhel4_xen_wpt(struct task_context *, ulong, physaddr_t *, int);
-static int x86_64_uvtop_5level(struct task_context *, ulong, physaddr_t *, int);
 static int x86_64_task_uses_5level(struct task_context *);
 static ulong x86_64_vmalloc_start(void);
 static int x86_64_is_task_addr(ulong);
@@ -80,6 +78,7 @@ static int x86_64_is_kvaddr(ulong);
 static int x86_64_is_uvaddr(ulong, struct task_context *);
 static ulong *x86_64_kpgd_offset(ulong, int, int);
 static ulong x86_64_upgd_offset(struct task_context *, ulong, int, int);
+static ulong x86_64_p4d_offset(ulong, ulong, int, int);
 static ulong x86_64_pud_offset(ulong, ulong, int, int);
 static ulong x86_64_pmd_offset(ulong, ulong, int, int);
 static ulong x86_64_pte_offset(ulong, ulong, int, int);
@@ -1613,6 +1612,31 @@ x86_64_upgd_offset(struct task_context *tc, ulong uvaddr, int verbose , int IS_X
 	return pgd_pte;
 }
 
+/*
+ * Find an entry in the fourth-level page table..
+ * p4d = p4d_offset(pgd, address);
+ */
+static ulong 
+x86_64_p4d_offset(ulong pgd_pte, ulong vaddr, int verbose ,int IS_XEN)
+{
+	ulong *p4d;
+	ulong p4d_paddr;
+	ulong p4d_pte;
+
+	p4d_paddr = pgd_pte & PHYSICAL_PAGE_MASK;
+	FILL_P4D(p4d_paddr, PHYSADDR, PAGESIZE());
+	p4d = ((ulong *)p4d_paddr) + p4d_index(vaddr);
+	p4d_pte = ULONG(machdep->machspec->p4d + PAGEOFFSET(p4d));
+        if (verbose) {
+		if(IS_XEN)
+			fprintf(fp, "   P4D: %lx => %lx [machine]\n", (ulong)p4d, p4d_pte);
+		else
+			fprintf(fp, "   P4D: %lx => %lx\n", (ulong)p4d, p4d_pte);
+        }
+
+	return p4d_pte;
+}
+
 /*
  * Find an entry in the third-level page table..
  * pud = pud_offset(pgd, address);
@@ -1734,17 +1758,30 @@ x86_64_uvtop_level4(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, in
 	if (IS_KVADDR(uvaddr))
 		return x86_64_kvtop(tc, uvaddr, paddr, verbose);
 
-	if ((machdep->flags & VM_5LEVEL) && x86_64_task_uses_5level(tc))
-		return x86_64_uvtop_5level(tc, uvaddr, paddr, verbose);
-
         pgd_pte = x86_64_upgd_offset(tc, uvaddr, verbose, FALSE);
 	if (!(pgd_pte & _PAGE_PRESENT))
 		goto no_upage;
 
-	/*
-         *  pud = pud_offset(pgd, address);
-	 */
-	pud_pte = x86_64_pud_offset(pgd_pte, uvaddr, verbose, FALSE);
+	/* If the VM is in 5-level page table*/
+	if (machdep->flags & VM_5LEVEL && x86_64_task_uses_5level(tc)) {
+		ulong p4d_pte;
+		/*
+		 *  p4d = p4d_offset(pgd, address);
+		 */
+		p4d_pte = x86_64_p4d_offset(pgd_pte, uvaddr, verbose, FALSE);
+		if (!(p4d_pte & _PAGE_PRESENT))
+			goto no_upage;
+		/*
+		 *  pud = pud_offset(p4d, address);
+		 */
+		pud_pte = x86_64_pud_offset(p4d_pte, uvaddr, verbose, FALSE);
+	} else {
+		/*
+		 *  pud = pud_offset(pgd, address);
+		 */
+		pud_pte = x86_64_pud_offset(pgd_pte, uvaddr, verbose, FALSE);
+	}
+
 	if (!(pud_pte & _PAGE_PRESENT))
 		goto no_upage;
 
@@ -1803,13 +1840,6 @@ x86_64_task_uses_5level(struct task_context *tc)
 	return FALSE;
 }
 
-static int
-x86_64_uvtop_5level(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, int verbose)
-{
-	error(INFO, "support for 5-level page tables TBD\n");
-	return FALSE;
-}
-
 static int
 x86_64_uvtop_level4_xen_wpt(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, int verbose)
 {
@@ -2139,9 +2169,6 @@ x86_64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbo
 		if (XEN() && (kt->xen_flags & WRITABLE_PAGE_TABLES))
 			return (x86_64_kvtop_xen_wpt(tc, kvaddr, paddr, verbose));
 
-		if (machdep->flags & VM_5LEVEL)
-			return (x86_64_kvtop_5level(tc, kvaddr, paddr, verbose));
-
  		/*	
 		 *  pgd = pgd_offset_k(addr);
 		 */
@@ -2152,7 +2179,23 @@ start_vtop_with_pagetable:
 	if (!(*pgd & _PAGE_PRESENT))
 		goto no_kpage;
 
-	pud_pte = x86_64_pud_offset(*pgd, kvaddr, verbose, FALSE);
+	/* If the VM is in 5-level page table*/
+	if (machdep->flags & VM_5LEVEL) {
+		ulong p4d_pte;
+		/*
+		 *  p4d = p4d_offset(pgd, address);
+		 */
+		p4d_pte = x86_64_p4d_offset(*pgd, kvaddr, verbose, FALSE);
+		if (!(p4d_pte & _PAGE_PRESENT))
+			goto no_kpage;
+		/*
+		 *  pud = pud_offset(p4d, address);
+		 */
+		pud_pte = x86_64_pud_offset(p4d_pte, kvaddr, verbose, FALSE);
+	} else {
+		pud_pte = x86_64_pud_offset(*pgd, kvaddr, verbose, FALSE);
+	}
+
 	if (!(pud_pte & _PAGE_PRESENT))
 		goto no_kpage;
 
@@ -2202,13 +2245,6 @@ no_kpage:
         return FALSE;
 }
 
-static int
-x86_64_kvtop_5level(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbose)
-{
-	error(INFO, "support for 5-level page tables TBD\n");
-	return FALSE;
-}
-
 static int
 x86_64_kvtop_xen_wpt(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbose)
 {
-- 
2.14.3






More information about the Crash-utility mailing list