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@xxxxxxxxxxxxxx> --- 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 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility