aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/mm/fault_64.c49
1 files changed, 35 insertions, 14 deletions
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index 1a786abdada3..4ab8993b0863 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -225,6 +225,30 @@ cannot_handle:
225 unhandled_fault (address, current, regs); 225 unhandled_fault (address, current, regs);
226} 226}
227 227
228static void noinline bogus_32bit_fault_tpc(struct pt_regs *regs)
229{
230 static int times;
231
232 if (times++ < 10)
233 printk(KERN_ERR "FAULT[%s:%d]: 32-bit process reports "
234 "64-bit TPC [%lx]\n",
235 current->comm, current->pid,
236 regs->tpc);
237 show_regs(regs);
238}
239
240static void noinline bogus_32bit_fault_address(struct pt_regs *regs,
241 unsigned long addr)
242{
243 static int times;
244
245 if (times++ < 10)
246 printk(KERN_ERR "FAULT[%s:%d]: 32-bit process "
247 "reports 64-bit fault address [%lx]\n",
248 current->comm, current->pid, addr);
249 show_regs(regs);
250}
251
228asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) 252asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
229{ 253{
230 struct mm_struct *mm = current->mm; 254 struct mm_struct *mm = current->mm;
@@ -246,13 +270,20 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
246 BUG(); 270 BUG();
247 271
248 if (test_thread_flag(TIF_32BIT)) { 272 if (test_thread_flag(TIF_32BIT)) {
249 if (!(regs->tstate & TSTATE_PRIV)) 273 if (!(regs->tstate & TSTATE_PRIV)) {
250 regs->tpc &= 0xffffffff; 274 if (unlikely((regs->tpc >> 32) != 0)) {
251 address &= 0xffffffff; 275 bogus_32bit_fault_tpc(regs);
276 goto intr_or_no_mm;
277 }
278 }
279 if (unlikely((address >> 32) != 0)) {
280 bogus_32bit_fault_address(regs, address);
281 goto intr_or_no_mm;
282 }
252 } 283 }
253 284
254 if (regs->tstate & TSTATE_PRIV) { 285 if (regs->tstate & TSTATE_PRIV) {
255 unsigned long eaddr, tpc = regs->tpc; 286 unsigned long tpc = regs->tpc;
256 287
257 /* Sanity check the PC. */ 288 /* Sanity check the PC. */
258 if ((tpc >= KERNBASE && tpc < (unsigned long) __init_end) || 289 if ((tpc >= KERNBASE && tpc < (unsigned long) __init_end) ||
@@ -262,16 +293,6 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
262 bad_kernel_pc(regs, address); 293 bad_kernel_pc(regs, address);
263 return; 294 return;
264 } 295 }
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 }
275 } 296 }
276 297
277 /* 298 /*