summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-07-31 06:57:59 +0200
committerDavid S. Miller <davem@davemloft.net>2008-07-31 06:57:59 +0200
commit5afe27380bc42454254c9c83c045240249c15e35 (patch)
treee7bdb90ea5e42b779b9ddeea9d945638da33eb23
parentsparc: Ignore drivers/video/console/promcon_tbl.c conmakehash generated file (diff)
downloadlinux-5afe27380bc42454254c9c83c045240249c15e35.tar.xz
linux-5afe27380bc42454254c9c83c045240249c15e35.zip
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>
-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 {
unsigned long tnpc;
unsigned long o7;
unsigned long i7;
+ unsigned long rpc;
struct thread_info *thread;
unsigned long pad1;
- unsigned long pad2;
};
#define __ARCH_WANT_COMPAT_SYS_PTRACE
@@ -315,9 +315,9 @@ extern void __show_regs(struct pt_regs *);
#define GR_SNAP_TNPC 0x10
#define GR_SNAP_O7 0x18
#define GR_SNAP_I7 0x20
-#define GR_SNAP_THREAD 0x28
-#define GR_SNAP_PAD1 0x30
-#define GR_SNAP_PAD2 0x38
+#define GR_SNAP_RPC 0x28
+#define GR_SNAP_THREAD 0x30
+#define GR_SNAP_PAD1 0x38
#endif /* __KERNEL__ */
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)
struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
static DEFINE_SPINLOCK(global_reg_snapshot_lock);
+static bool kstack_valid(struct thread_info *tp, struct reg_window *rw)
+{
+ unsigned long thread_base, fp;
+
+ thread_base = (unsigned long) tp;
+ fp = (unsigned long) rw;
+
+ if (fp < (thread_base + sizeof(struct thread_info)) ||
+ fp >= (thread_base + THREAD_SIZE))
+ return false;
+ return true;
+}
+
static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
int this_cpu)
{
@@ -315,14 +328,22 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7];
if (regs->tstate & TSTATE_PRIV) {
+ struct thread_info *tp = current_thread_info();
struct reg_window *rw;
rw = (struct reg_window *)
(regs->u_regs[UREG_FP] + STACK_BIAS);
- global_reg_snapshot[this_cpu].i7 = rw->ins[7];
- } else
+ if (kstack_valid(tp, rw)) {
+ global_reg_snapshot[this_cpu].i7 = rw->ins[7];
+ rw = (struct reg_window *)
+ (rw->ins[6] + STACK_BIAS);
+ if (kstack_valid(tp, rw))
+ global_reg_snapshot[this_cpu].rpc = rw->ins[7];
+ }
+ } else {
global_reg_snapshot[this_cpu].i7 = 0;
-
+ global_reg_snapshot[this_cpu].rpc = 0;
+ }
global_reg_snapshot[this_cpu].thread = tp;
}
@@ -375,13 +396,14 @@ static void sysrq_handle_globreg(int key, struct tty_struct *tty)
((tp && tp->task) ? tp->task->pid : -1));
if (gp->tstate & TSTATE_PRIV) {
- printk(" TPC[%pS] O7[%pS] I7[%pS]\n",
+ printk(" TPC[%pS] O7[%pS] I7[%pS] RPC[%pS]\n",
(void *) gp->tpc,
(void *) gp->o7,
- (void *) gp->i7);
+ (void *) gp->i7,
+ (void *) gp->rpc);
} else {
- printk(" TPC[%lx] O7[%lx] I7[%lx]\n",
- gp->tpc, gp->o7, gp->i7);
+ printk(" TPC[%lx] O7[%lx] I7[%lx] RPC[%lx]\n",
+ gp->tpc, gp->o7, gp->i7, gp->rpc);
}
}
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:
stx %g7, [%g1 + GR_SNAP_TNPC]
stx %o7, [%g1 + GR_SNAP_O7]
stx %i7, [%g1 + GR_SNAP_I7]
+ /* Don't try this at home kids... */
+ rdpr %cwp, %g2
+ sub %g2, 1, %g7
+ wrpr %g7, %cwp
+ mov %i7, %g7
+ wrpr %g2, %cwp
+ stx %g7, [%g1 + GR_SNAP_RPC]
sethi %hi(trap_block), %g7
or %g7, %lo(trap_block), %g7
sllx %g2, TRAP_BLOCK_SZ_SHIFT, %g2