]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/commitdiff
sparc64: Make global reg dumping even more useful.
authorDavid S. Miller <davem@davemloft.net>
Mon, 18 Aug 2008 03:47:13 +0000 (20:47 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 20 Aug 2008 18:05:11 +0000 (11:05 -0700)
[ 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>
arch/sparc64/kernel/process.c
arch/sparc64/mm/ultra.S
include/asm-sparc64/ptrace.h

index df54391b6573aaf0801ca5486646489562a0f4d1..3277443317799509908aef57ad1346c448584100 100644 (file)
@@ -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);
                }
        }
 
index 9bb2d90a9df6ba948e566f6c7c11d92a0a437837..db5768671e0928b5bfdca9bfcea9c607d407e5d8 100644 (file)
@@ -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
index b163da79bb6d276a0d8128094f5de5fc74e2d026..4f18096736c33c023228a719f9bf6bb475f6a600 100644 (file)
@@ -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__  */