sparc64: Make global reg dumping even more useful.
[linux-2.6.git] / arch / sparc64 / kernel / process.c
index 0f60547..fc8137a 100644 (file)
@@ -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);
                }
        }