diff options
-rw-r--r-- | arch/sparc/include/asm/ptrace_64.h | 8 | ||||
-rw-r--r-- | arch/sparc64/kernel/process.c | 36 | ||||
-rw-r--r-- | arch/sparc64/mm/ultra.S | 7 |
3 files changed, 40 insertions, 11 deletions
diff --git a/arch/sparc/include/asm/ptrace_64.h b/arch/sparc/include/asm/ptrace_64.h index ec6d45c84cd0..390d92ac67cf 100644 --- a/arch/sparc/include/asm/ptrace_64.h +++ b/arch/sparc/include/asm/ptrace_64.h | |||
@@ -134,9 +134,9 @@ struct global_reg_snapshot { | |||
134 | unsigned long tnpc; | 134 | unsigned long tnpc; |
135 | unsigned long o7; | 135 | unsigned long o7; |
136 | unsigned long i7; | 136 | unsigned long i7; |
137 | unsigned long rpc; | ||
137 | struct thread_info *thread; | 138 | struct thread_info *thread; |
138 | unsigned long pad1; | 139 | unsigned long pad1; |
139 | unsigned long pad2; | ||
140 | }; | 140 | }; |
141 | 141 | ||
142 | #define __ARCH_WANT_COMPAT_SYS_PTRACE | 142 | #define __ARCH_WANT_COMPAT_SYS_PTRACE |
@@ -315,9 +315,9 @@ extern void __show_regs(struct pt_regs *); | |||
315 | #define GR_SNAP_TNPC 0x10 | 315 | #define GR_SNAP_TNPC 0x10 |
316 | #define GR_SNAP_O7 0x18 | 316 | #define GR_SNAP_O7 0x18 |
317 | #define GR_SNAP_I7 0x20 | 317 | #define GR_SNAP_I7 0x20 |
318 | #define GR_SNAP_THREAD 0x28 | 318 | #define GR_SNAP_RPC 0x28 |
319 | #define GR_SNAP_PAD1 0x30 | 319 | #define GR_SNAP_THREAD 0x30 |
320 | #define GR_SNAP_PAD2 0x38 | 320 | #define GR_SNAP_PAD1 0x38 |
321 | 321 | ||
322 | #endif /* __KERNEL__ */ | 322 | #endif /* __KERNEL__ */ |
323 | 323 | ||
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 0f60547c24d9..fc8137a21ced 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c | |||
@@ -304,6 +304,19 @@ void show_regs(struct pt_regs *regs) | |||
304 | struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; | 304 | struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; |
305 | static DEFINE_SPINLOCK(global_reg_snapshot_lock); | 305 | static DEFINE_SPINLOCK(global_reg_snapshot_lock); |
306 | 306 | ||
307 | static bool kstack_valid(struct thread_info *tp, struct reg_window *rw) | ||
308 | { | ||
309 | unsigned long thread_base, fp; | ||
310 | |||
311 | thread_base = (unsigned long) tp; | ||
312 | fp = (unsigned long) rw; | ||
313 | |||
314 | if (fp < (thread_base + sizeof(struct thread_info)) || | ||
315 | fp >= (thread_base + THREAD_SIZE)) | ||
316 | return false; | ||
317 | return true; | ||
318 | } | ||
319 | |||
307 | static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, | 320 | static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, |
308 | int this_cpu) | 321 | int this_cpu) |
309 | { | 322 | { |
@@ -315,14 +328,22 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, | |||
315 | global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7]; | 328 | global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7]; |
316 | 329 | ||
317 | if (regs->tstate & TSTATE_PRIV) { | 330 | if (regs->tstate & TSTATE_PRIV) { |
331 | struct thread_info *tp = current_thread_info(); | ||
318 | struct reg_window *rw; | 332 | struct reg_window *rw; |
319 | 333 | ||
320 | rw = (struct reg_window *) | 334 | rw = (struct reg_window *) |
321 | (regs->u_regs[UREG_FP] + STACK_BIAS); | 335 | (regs->u_regs[UREG_FP] + STACK_BIAS); |
322 | global_reg_snapshot[this_cpu].i7 = rw->ins[7]; | 336 | if (kstack_valid(tp, rw)) { |
323 | } else | 337 | global_reg_snapshot[this_cpu].i7 = rw->ins[7]; |
338 | rw = (struct reg_window *) | ||
339 | (rw->ins[6] + STACK_BIAS); | ||
340 | if (kstack_valid(tp, rw)) | ||
341 | global_reg_snapshot[this_cpu].rpc = rw->ins[7]; | ||
342 | } | ||
343 | } else { | ||
324 | global_reg_snapshot[this_cpu].i7 = 0; | 344 | global_reg_snapshot[this_cpu].i7 = 0; |
325 | 345 | global_reg_snapshot[this_cpu].rpc = 0; | |
346 | } | ||
326 | global_reg_snapshot[this_cpu].thread = tp; | 347 | global_reg_snapshot[this_cpu].thread = tp; |
327 | } | 348 | } |
328 | 349 | ||
@@ -375,13 +396,14 @@ static void sysrq_handle_globreg(int key, struct tty_struct *tty) | |||
375 | ((tp && tp->task) ? tp->task->pid : -1)); | 396 | ((tp && tp->task) ? tp->task->pid : -1)); |
376 | 397 | ||
377 | if (gp->tstate & TSTATE_PRIV) { | 398 | if (gp->tstate & TSTATE_PRIV) { |
378 | printk(" TPC[%pS] O7[%pS] I7[%pS]\n", | 399 | printk(" TPC[%pS] O7[%pS] I7[%pS] RPC[%pS]\n", |
379 | (void *) gp->tpc, | 400 | (void *) gp->tpc, |
380 | (void *) gp->o7, | 401 | (void *) gp->o7, |
381 | (void *) gp->i7); | 402 | (void *) gp->i7, |
403 | (void *) gp->rpc); | ||
382 | } else { | 404 | } else { |
383 | printk(" TPC[%lx] O7[%lx] I7[%lx]\n", | 405 | printk(" TPC[%lx] O7[%lx] I7[%lx] RPC[%lx]\n", |
384 | gp->tpc, gp->o7, gp->i7); | 406 | gp->tpc, gp->o7, gp->i7, gp->rpc); |
385 | } | 407 | } |
386 | } | 408 | } |
387 | 409 | ||
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S index 4c8ca131ffaf..77ba88597cc5 100644 --- a/arch/sparc64/mm/ultra.S +++ b/arch/sparc64/mm/ultra.S | |||
@@ -531,6 +531,13 @@ xcall_fetch_glob_regs: | |||
531 | stx %g7, [%g1 + GR_SNAP_TNPC] | 531 | stx %g7, [%g1 + GR_SNAP_TNPC] |
532 | stx %o7, [%g1 + GR_SNAP_O7] | 532 | stx %o7, [%g1 + GR_SNAP_O7] |
533 | stx %i7, [%g1 + GR_SNAP_I7] | 533 | stx %i7, [%g1 + GR_SNAP_I7] |
534 | /* Don't try this at home kids... */ | ||
535 | rdpr %cwp, %g2 | ||
536 | sub %g2, 1, %g7 | ||
537 | wrpr %g7, %cwp | ||
538 | mov %i7, %g7 | ||
539 | wrpr %g2, %cwp | ||
540 | stx %g7, [%g1 + GR_SNAP_RPC] | ||
534 | sethi %hi(trap_block), %g7 | 541 | sethi %hi(trap_block), %g7 |
535 | or %g7, %lo(trap_block), %g7 | 542 | or %g7, %lo(trap_block), %g7 |
536 | sllx %g2, TRAP_BLOCK_SZ_SHIFT, %g2 | 543 | sllx %g2, TRAP_BLOCK_SZ_SHIFT, %g2 |