diff options
Diffstat (limited to 'arch/sparc64/mm/fault.c')
-rw-r--r-- | arch/sparc64/mm/fault.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 6f0539aa44d0..63b6cc0cd5d5 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/lsu.h> | 29 | #include <asm/lsu.h> |
30 | #include <asm/sections.h> | 30 | #include <asm/sections.h> |
31 | #include <asm/kdebug.h> | 31 | #include <asm/kdebug.h> |
32 | #include <asm/mmu_context.h> | ||
32 | 33 | ||
33 | /* | 34 | /* |
34 | * To debug kernel to catch accesses to certain virtual/physical addresses. | 35 | * To debug kernel to catch accesses to certain virtual/physical addresses. |
@@ -91,12 +92,13 @@ static void __kprobes unhandled_fault(unsigned long address, | |||
91 | die_if_kernel("Oops", regs); | 92 | die_if_kernel("Oops", regs); |
92 | } | 93 | } |
93 | 94 | ||
94 | static void bad_kernel_pc(struct pt_regs *regs) | 95 | static void bad_kernel_pc(struct pt_regs *regs, unsigned long vaddr) |
95 | { | 96 | { |
96 | unsigned long *ksp; | 97 | unsigned long *ksp; |
97 | 98 | ||
98 | printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n", | 99 | printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n", |
99 | regs->tpc); | 100 | regs->tpc); |
101 | printk(KERN_CRIT "OOPS: Fault was to vaddr[%lx]\n", vaddr); | ||
100 | __asm__("mov %%sp, %0" : "=r" (ksp)); | 102 | __asm__("mov %%sp, %0" : "=r" (ksp)); |
101 | show_stack(current, ksp); | 103 | show_stack(current, ksp); |
102 | unhandled_fault(regs->tpc, current, regs); | 104 | unhandled_fault(regs->tpc, current, regs); |
@@ -137,7 +139,7 @@ static unsigned int get_user_insn(unsigned long tpc) | |||
137 | if (!pte_present(pte)) | 139 | if (!pte_present(pte)) |
138 | goto out; | 140 | goto out; |
139 | 141 | ||
140 | pa = (pte_val(pte) & _PAGE_PADDR); | 142 | pa = (pte_pfn(pte) << PAGE_SHIFT); |
141 | pa += (tpc & ~PAGE_MASK); | 143 | pa += (tpc & ~PAGE_MASK); |
142 | 144 | ||
143 | /* Use phys bypass so we don't pollute dtlb/dcache. */ | 145 | /* Use phys bypass so we don't pollute dtlb/dcache. */ |
@@ -257,7 +259,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | |||
257 | struct vm_area_struct *vma; | 259 | struct vm_area_struct *vma; |
258 | unsigned int insn = 0; | 260 | unsigned int insn = 0; |
259 | int si_code, fault_code; | 261 | int si_code, fault_code; |
260 | unsigned long address; | 262 | unsigned long address, mm_rss; |
261 | 263 | ||
262 | fault_code = get_thread_fault_code(); | 264 | fault_code = get_thread_fault_code(); |
263 | 265 | ||
@@ -280,7 +282,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | |||
280 | (tpc >= MODULES_VADDR && tpc < MODULES_END)) { | 282 | (tpc >= MODULES_VADDR && tpc < MODULES_END)) { |
281 | /* Valid, no problems... */ | 283 | /* Valid, no problems... */ |
282 | } else { | 284 | } else { |
283 | bad_kernel_pc(regs); | 285 | bad_kernel_pc(regs, address); |
284 | return; | 286 | return; |
285 | } | 287 | } |
286 | } | 288 | } |
@@ -406,6 +408,11 @@ good_area: | |||
406 | } | 408 | } |
407 | 409 | ||
408 | up_read(&mm->mmap_sem); | 410 | up_read(&mm->mmap_sem); |
411 | |||
412 | mm_rss = get_mm_rss(mm); | ||
413 | if (unlikely(mm_rss >= mm->context.tsb_rss_limit)) | ||
414 | tsb_grow(mm, mm_rss); | ||
415 | |||
409 | return; | 416 | return; |
410 | 417 | ||
411 | /* | 418 | /* |