Skip to content

Commit

Permalink
sh: Improve oops error reporting
Browse files Browse the repository at this point in the history
In some cases the opps error reporting doesn't give enough information
to diagnose the problem, only printing information if it is thought
to be valid. Replace the current code with more detailed output.

This code is based on the ARM reporting, with minor changes for the SH.

[lethal@linux-sh.org: fixed up for 64-bit PTEs and pte_offset_kernel()]
Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
  • Loading branch information
Stuart Menefy authored and Paul Mundt committed Apr 19, 2012
1 parent 8d9a784 commit 45c0e0e
Showing 1 changed file with 74 additions and 23 deletions.
97 changes: 74 additions & 23 deletions arch/sh/mm/fault_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,74 @@ static inline int notify_page_fault(struct pt_regs *regs, int trap)
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);
Expand Down Expand Up @@ -254,29 +322,12 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
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);
Expand Down

0 comments on commit 45c0e0e

Please sign in to comment.