aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel
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/sparc64/kernel
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/sparc64/kernel')
-rw-r--r--arch/sparc64/kernel/process.c36
1 files changed, 29 insertions, 7 deletions
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