diff options
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/mm/fault_64.c | 25 |
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)) { |