aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-08-17 20:47:13 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2008-08-20 11:05:11 -0700
commit664d412a9fcdbc6cb62bfa7299978c088db28bd2 (patch)
treed61147bfffbd61f1fef9770827a3de347a467f07
parentfbcd513d29df1398572db0b5bd1cc6cfecd4b2fd (diff)
sparc64: Make global reg dumping even more useful.
[ Upstream commit 5afe27380bc42454254c9c83c045240249c15e35 ] 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> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--arch/sparc64/kernel/process.c35
-rw-r--r--arch/sparc64/mm/ultra.S7
-rw-r--r--include/asm-sparc64/ptrace.h8
3 files changed, 40 insertions, 10 deletions
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index df54391b657..32774433177 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -305,6 +305,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)
{
@@ -316,14 +329,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;
}
@@ -384,12 +405,14 @@ static void sysrq_handle_globreg(int key, struct tty_struct *tty)
sprint_symbol(buffer, gp->o7);
printk("O7[%s] ", buffer);
sprint_symbol(buffer, gp->i7);
- printk("I7[%s]\n", buffer);
+ printk("I7[%s] ", buffer);
+ sprint_symbol(buffer, gp->rpc);
+ printk("RPC[%s]\n", buffer);
} else
#endif
{
- 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 9bb2d90a9df..db5768671e0 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
diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h
index b163da79bb6..4f18096736c 100644
--- a/include/asm-sparc64/ptrace.h
+++ b/include/asm-sparc64/ptrace.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
@@ -314,9 +314,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__ */