diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-17 20:47:13 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-08-20 11:05:11 -0700 |
commit | 664d412a9fcdbc6cb62bfa7299978c088db28bd2 (patch) | |
tree | d61147bfffbd61f1fef9770827a3de347a467f07 | |
parent | fbcd513d29df1398572db0b5bd1cc6cfecd4b2fd (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.c | 35 | ||||
-rw-r--r-- | arch/sparc64/mm/ultra.S | 7 | ||||
-rw-r--r-- | include/asm-sparc64/ptrace.h | 8 |
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__ */ |