aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/mm/fault_64.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index a9e474bf6385..1a786abdada3 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -19,6 +19,7 @@
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/kprobes.h> 20#include <linux/kprobes.h>
21#include <linux/kdebug.h> 21#include <linux/kdebug.h>
22#include <linux/percpu.h>
22 23
23#include <asm/page.h> 24#include <asm/page.h>
24#include <asm/pgtable.h> 25#include <asm/pgtable.h>
@@ -244,8 +245,14 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
244 (fault_code & FAULT_CODE_DTLB)) 245 (fault_code & FAULT_CODE_DTLB))
245 BUG(); 246 BUG();
246 247
248 if (test_thread_flag(TIF_32BIT)) {
249 if (!(regs->tstate & TSTATE_PRIV))
250 regs->tpc &= 0xffffffff;
251 address &= 0xffffffff;
252 }
253
247 if (regs->tstate & TSTATE_PRIV) { 254 if (regs->tstate & TSTATE_PRIV) {
248 unsigned long tpc = regs->tpc; 255 unsigned long eaddr, tpc = regs->tpc;
249 256
250 /* Sanity check the PC. */ 257 /* Sanity check the PC. */
251 if ((tpc >= KERNBASE && tpc < (unsigned long) __init_end) || 258 if ((tpc >= KERNBASE && tpc < (unsigned long) __init_end) ||
@@ -255,6 +262,16 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
255 bad_kernel_pc(regs, address); 262 bad_kernel_pc(regs, address);
256 return; 263 return;
257 } 264 }
265
266 insn = get_fault_insn(regs, insn);
267 eaddr = compute_effective_address(regs, insn, 0);
268 if (WARN_ON_ONCE((eaddr & PAGE_MASK) != (address & PAGE_MASK))){
269 printk(KERN_ERR "FAULT: Mismatch kernel fault "
270 "address: addr[%lx] eaddr[%lx] TPC[%lx]\n",
271 address, eaddr, tpc);
272 show_regs(regs);
273 goto handle_kernel_fault;
274 }
258 } 275 }
259 276
260 /* 277 /*
@@ -264,12 +281,6 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
264 if (in_atomic() || !mm) 281 if (in_atomic() || !mm)
265 goto intr_or_no_mm; 282 goto intr_or_no_mm;
266 283
267 if (test_thread_flag(TIF_32BIT)) {
268 if (!(regs->tstate & TSTATE_PRIV))
269 regs->tpc &= 0xffffffff;
270 address &= 0xffffffff;
271 }
272
273 if (!down_read_trylock(&mm->mmap_sem)) { 284 if (!down_read_trylock(&mm->mmap_sem)) {
274 if ((regs->tstate & TSTATE_PRIV) && 285 if ((regs->tstate & TSTATE_PRIV) &&
275 !search_exception_tables(regs->tpc)) { 286 !search_exception_tables(regs->tpc)) {