aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm
diff options
context:
space:
mode:
authorStuart Menefy <stuart.menefy@st.com>2012-04-19 04:25:03 -0400
committerPaul Mundt <lethal@linux-sh.org>2012-04-19 04:25:03 -0400
commit45c0e0e25eae2c5e8bb9e2dfaf73afb396e0928d (patch)
treed28db9a7ec6225746689b43f11b94733fe0b89db /arch/sh/mm
parent8d9a784d1e2c75e0dcae06f77a02f5e7bb547f3a (diff)
sh: Improve oops error reporting
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>
Diffstat (limited to 'arch/sh/mm')
-rw-r--r--arch/sh/mm/fault_32.c97
1 files changed, 74 insertions, 23 deletions
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c
index e99b104d967a..c5cd87868c73 100644
--- a/arch/sh/mm/fault_32.c
+++ b/arch/sh/mm/fault_32.c
@@ -35,6 +35,74 @@ static inline int notify_page_fault(struct pt_regs *regs, int trap)
35 return ret; 35 return ret;
36} 36}
37 37
38/*
39 * This is useful to dump out the page tables associated with
40 * 'addr' in mm 'mm'.
41 */
42static void show_pte(struct mm_struct *mm, unsigned long addr)
43{
44 pgd_t *pgd;
45
46 if (mm)
47 pgd = mm->pgd;
48 else
49 pgd = get_TTB();
50
51 printk(KERN_ALERT "pgd = %p\n", pgd);
52 pgd += pgd_index(addr);
53 printk(KERN_ALERT "[%08lx] *pgd=%0*Lx", addr,
54 sizeof(*pgd) * 2, (u64)pgd_val(*pgd));
55
56 do {
57 pud_t *pud;
58 pmd_t *pmd;
59 pte_t *pte;
60
61 if (pgd_none(*pgd))
62 break;
63
64 if (pgd_bad(*pgd)) {
65 printk("(bad)");
66 break;
67 }
68
69 pud = pud_offset(pgd, addr);
70 if (PTRS_PER_PUD != 1)
71 printk(", *pud=%0*Lx", sizeof(*pud) * 2,
72 (u64)pud_val(*pud));
73
74 if (pud_none(*pud))
75 break;
76
77 if (pud_bad(*pud)) {
78 printk("(bad)");
79 break;
80 }
81
82 pmd = pmd_offset(pud, addr);
83 if (PTRS_PER_PMD != 1)
84 printk(", *pmd=%0*Lx", sizeof(*pmd) * 2,
85 (u64)pmd_val(*pmd));
86
87 if (pmd_none(*pmd))
88 break;
89
90 if (pmd_bad(*pmd)) {
91 printk("(bad)");
92 break;
93 }
94
95 /* We must not map this if we have highmem enabled */
96 if (PageHighMem(pfn_to_page(pmd_val(*pmd) >> PAGE_SHIFT)))
97 break;
98
99 pte = pte_offset_kernel(pmd, addr);
100 printk(", *pte=%0*Lx", sizeof(*pte) * 2, (u64)pte_val(*pte));
101 } while (0);
102
103 printk("\n");
104}
105
38static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) 106static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
39{ 107{
40 unsigned index = pgd_index(address); 108 unsigned index = pgd_index(address);
@@ -254,29 +322,12 @@ no_context:
254 bust_spinlocks(1); 322 bust_spinlocks(1);
255 323
256 if (oops_may_print()) { 324 if (oops_may_print()) {
257 unsigned long page; 325 printk(KERN_ALERT
258 326 "Unable to handle kernel %s at virtual address %08lx\n",
259 if (address < PAGE_SIZE) 327 (address < PAGE_SIZE) ? "NULL pointer dereference" :
260 printk(KERN_ALERT "Unable to handle kernel NULL " 328 "paging request", address);
261 "pointer dereference"); 329
262 else 330 show_pte(mm, address);
263 printk(KERN_ALERT "Unable to handle kernel paging "
264 "request");
265 printk(" at virtual address %08lx\n", address);
266 printk(KERN_ALERT "pc = %08lx\n", regs->pc);
267 page = (unsigned long)get_TTB();
268 if (page) {
269 page = ((__typeof__(page) *)page)[address >> PGDIR_SHIFT];
270 printk(KERN_ALERT "*pde = %08lx\n", page);
271 if (page & _PAGE_PRESENT) {
272 page &= PAGE_MASK;
273 address &= 0x003ff000;
274 page = ((__typeof__(page) *)
275 __va(page))[address >>
276 PAGE_SHIFT];
277 printk(KERN_ALERT "*pte = %08lx\n", page);
278 }
279 }
280 } 331 }
281 332
282 die("Oops", regs, writeaccess); 333 die("Oops", regs, writeaccess);