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 <[email protected]>
---
 x86_64.c | 90 +++++++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 63 insertions(+), 27 deletions(-)

diff --git a/x86_64.c b/x86_64.c
index c8c6819..d3d5ab9 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);
@@ -81,6 +79,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);
@@ -1649,6 +1648,31 @@ x86_64_upgd_offset(struct task_context *tc, ulong 
uvaddr, int verbose, int IS_XE
        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);
@@ -1770,17 +1794,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;
 
@@ -1839,13 +1876,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)
 {
@@ -2175,9 +2205,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);
                 */
@@ -2188,7 +2215,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;
 
@@ -2238,13 +2281,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



--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to