|
@@ -52,8 +52,6 @@
|
|
|
#include <asm/irq_regs.h>
|
|
|
#include <asm/smp.h>
|
|
|
|
|
|
-/* #define VERBOSE_SHOWREGS */
|
|
|
-
|
|
|
static void sparc64_yield(int cpu)
|
|
|
{
|
|
|
if (tlb_type != hypervisor)
|
|
@@ -213,22 +211,8 @@ static void show_regwindow(struct pt_regs *regs)
|
|
|
printk("I7: <%pS>\n", (void *) rwk->ins[7]);
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_SMP
|
|
|
-static DEFINE_SPINLOCK(regdump_lock);
|
|
|
-#endif
|
|
|
-
|
|
|
-void __show_regs(struct pt_regs * regs)
|
|
|
+void show_regs(struct pt_regs *regs)
|
|
|
{
|
|
|
-#ifdef CONFIG_SMP
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- /* Protect against xcall ipis which might lead to livelock on the lock */
|
|
|
- __asm__ __volatile__("rdpr %%pstate, %0\n\t"
|
|
|
- "wrpr %0, %1, %%pstate"
|
|
|
- : "=r" (flags)
|
|
|
- : "i" (PSTATE_IE));
|
|
|
- spin_lock(®dump_lock);
|
|
|
-#endif
|
|
|
printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x %s\n", regs->tstate,
|
|
|
regs->tpc, regs->tnpc, regs->y, print_tainted());
|
|
|
printk("TPC: <%pS>\n", (void *) regs->tpc);
|
|
@@ -246,64 +230,24 @@ void __show_regs(struct pt_regs * regs)
|
|
|
regs->u_regs[15]);
|
|
|
printk("RPC: <%pS>\n", (void *) regs->u_regs[15]);
|
|
|
show_regwindow(regs);
|
|
|
-#ifdef CONFIG_SMP
|
|
|
- spin_unlock(®dump_lock);
|
|
|
- __asm__ __volatile__("wrpr %0, 0, %%pstate"
|
|
|
- : : "r" (flags));
|
|
|
-#endif
|
|
|
}
|
|
|
|
|
|
-#ifdef VERBOSE_SHOWREGS
|
|
|
-static void idump_from_user (unsigned int *pc)
|
|
|
-{
|
|
|
- int i;
|
|
|
- int code;
|
|
|
-
|
|
|
- if((((unsigned long) pc) & 3))
|
|
|
- return;
|
|
|
-
|
|
|
- pc -= 3;
|
|
|
- for(i = -3; i < 6; i++) {
|
|
|
- get_user(code, pc);
|
|
|
- printk("%c%08x%c",i?' ':'<',code,i?' ':'>');
|
|
|
- pc++;
|
|
|
- }
|
|
|
- printk("\n");
|
|
|
-}
|
|
|
-#endif
|
|
|
+struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
|
|
|
+static DEFINE_SPINLOCK(global_reg_snapshot_lock);
|
|
|
|
|
|
-void show_regs(struct pt_regs *regs)
|
|
|
+static bool kstack_valid(struct thread_info *tp, struct reg_window *rw)
|
|
|
{
|
|
|
-#ifdef VERBOSE_SHOWREGS
|
|
|
- extern long etrap, etraptl1;
|
|
|
-#endif
|
|
|
- __show_regs(regs);
|
|
|
-#if 0
|
|
|
-#ifdef CONFIG_SMP
|
|
|
- {
|
|
|
- extern void smp_report_regs(void);
|
|
|
+ unsigned long thread_base, fp;
|
|
|
|
|
|
- smp_report_regs();
|
|
|
- }
|
|
|
-#endif
|
|
|
-#endif
|
|
|
+ thread_base = (unsigned long) tp;
|
|
|
+ fp = (unsigned long) rw;
|
|
|
|
|
|
-#ifdef VERBOSE_SHOWREGS
|
|
|
- if (regs->tpc >= &etrap && regs->tpc < &etraptl1 &&
|
|
|
- regs->u_regs[14] >= (long)current - PAGE_SIZE &&
|
|
|
- regs->u_regs[14] < (long)current + 6 * PAGE_SIZE) {
|
|
|
- printk ("*********parent**********\n");
|
|
|
- __show_regs((struct pt_regs *)(regs->u_regs[14] + PTREGS_OFF));
|
|
|
- idump_from_user(((struct pt_regs *)(regs->u_regs[14] + PTREGS_OFF))->tpc);
|
|
|
- printk ("*********endpar**********\n");
|
|
|
- }
|
|
|
-#endif
|
|
|
+ if (fp < (thread_base + sizeof(struct thread_info)) ||
|
|
|
+ fp >= (thread_base + THREAD_SIZE))
|
|
|
+ return false;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_MAGIC_SYSRQ
|
|
|
-struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
|
|
|
-static DEFINE_SPINLOCK(global_reg_snapshot_lock);
|
|
|
-
|
|
|
static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
|
|
|
int this_cpu)
|
|
|
{
|
|
@@ -315,14 +259,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[6];
|
|
|
- } 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;
|
|
|
}
|
|
|
|
|
@@ -341,7 +293,7 @@ static void __global_reg_poll(struct global_reg_snapshot *gp)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void sysrq_handle_globreg(int key, struct tty_struct *tty)
|
|
|
+void __trigger_all_cpu_backtrace(void)
|
|
|
{
|
|
|
struct thread_info *tp = current_thread_info();
|
|
|
struct pt_regs *regs = get_irq_regs();
|
|
@@ -375,13 +327,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);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -390,6 +343,13 @@ static void sysrq_handle_globreg(int key, struct tty_struct *tty)
|
|
|
spin_unlock_irqrestore(&global_reg_snapshot_lock, flags);
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_MAGIC_SYSRQ
|
|
|
+
|
|
|
+static void sysrq_handle_globreg(int key, struct tty_struct *tty)
|
|
|
+{
|
|
|
+ __trigger_all_cpu_backtrace();
|
|
|
+}
|
|
|
+
|
|
|
static struct sysrq_key_op sparc_globalreg_op = {
|
|
|
.handler = sysrq_handle_globreg,
|
|
|
.help_msg = "Globalregs",
|