return ret;
 }
 
+/*
+ * This is useful to dump out the page tables associated with
+ * 'addr' in mm 'mm'.
+ */
+static void show_pte(struct mm_struct *mm, unsigned long addr)
+{
+       pgd_t *pgd;
+
+       if (mm)
+               pgd = mm->pgd;
+       else
+               pgd = get_TTB();
+
+       printk(KERN_ALERT "pgd = %p\n", pgd);
+       pgd += pgd_index(addr);
+       printk(KERN_ALERT "[%08lx] *pgd=%0*Lx", addr,
+              sizeof(*pgd) * 2, (u64)pgd_val(*pgd));
+
+       do {
+               pud_t *pud;
+               pmd_t *pmd;
+               pte_t *pte;
+
+               if (pgd_none(*pgd))
+                       break;
+
+               if (pgd_bad(*pgd)) {
+                       printk("(bad)");
+                       break;
+               }
+
+               pud = pud_offset(pgd, addr);
+               if (PTRS_PER_PUD != 1)
+                       printk(", *pud=%0*Lx", sizeof(*pud) * 2,
+                              (u64)pud_val(*pud));
+
+               if (pud_none(*pud))
+                       break;
+
+               if (pud_bad(*pud)) {
+                       printk("(bad)");
+                       break;
+               }
+
+               pmd = pmd_offset(pud, addr);
+               if (PTRS_PER_PMD != 1)
+                       printk(", *pmd=%0*Lx", sizeof(*pmd) * 2,
+                              (u64)pmd_val(*pmd));
+
+               if (pmd_none(*pmd))
+                       break;
+
+               if (pmd_bad(*pmd)) {
+                       printk("(bad)");
+                       break;
+               }
+
+               /* We must not map this if we have highmem enabled */
+               if (PageHighMem(pfn_to_page(pmd_val(*pmd) >> PAGE_SHIFT)))
+                       break;
+
+               pte = pte_offset_kernel(pmd, addr);
+               printk(", *pte=%0*Lx", sizeof(*pte) * 2, (u64)pte_val(*pte));
+       } while (0);
+
+       printk("\n");
+}
+
 static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
 {
        unsigned index = pgd_index(address);
        bust_spinlocks(1);
 
        if (oops_may_print()) {
-               unsigned long page;
-
-               if (address < PAGE_SIZE)
-                       printk(KERN_ALERT "Unable to handle kernel NULL "
-                                         "pointer dereference");
-               else
-                       printk(KERN_ALERT "Unable to handle kernel paging "
-                                         "request");
-               printk(" at virtual address %08lx\n", address);
-               printk(KERN_ALERT "pc = %08lx\n", regs->pc);
-               page = (unsigned long)get_TTB();
-               if (page) {
-                       page = ((__typeof__(page) *)page)[address >> PGDIR_SHIFT];
-                       printk(KERN_ALERT "*pde = %08lx\n", page);
-                       if (page & _PAGE_PRESENT) {
-                               page &= PAGE_MASK;
-                               address &= 0x003ff000;
-                               page = ((__typeof__(page) *)
-                                               __va(page))[address >>
-                                                           PAGE_SHIFT];
-                               printk(KERN_ALERT "*pte = %08lx\n", page);
-                       }
-               }
+               printk(KERN_ALERT
+                      "Unable to handle kernel %s at virtual address %08lx\n",
+                      (address < PAGE_SIZE) ? "NULL pointer dereference" :
+                      "paging request", address);
+
+               show_pte(mm, address);
        }
 
        die("Oops", regs, writeaccess);