aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-07-31 00:57:59 -0400
committerDavid S. Miller <davem@davemloft.net>2008-07-31 00:57:59 -0400
commit5afe27380bc42454254c9c83c045240249c15e35 (patch)
treee7bdb90ea5e42b779b9ddeea9d945638da33eb23 /arch
parentc9b23e0c302377ccff700bee663b878d04e4ef3a (diff)
sparc64: Make global reg dumping even more useful.
Record one more level of stack frame program counter. Particularly when lockdep and all sorts of spinlock debugging is enabled, figuring out the caller of spin_lock() is difficult when the cpu is stuck on the lock. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc/include/asm/ptrace_64.h8
-rw-r--r--arch/sparc64/kernel/process.c36
-rw-r--r--arch/sparc64/mm/ultra.S7
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)
304struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; 304struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
305static DEFINE_SPINLOCK(global_reg_snapshot_lock); 305static DEFINE_SPINLOCK(global_reg_snapshot_lock);
306 306
307static 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
307static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, 320static 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