Commit 3f3fbc0d authored by Paul Mackerras's avatar Paul Mackerras

PPC32: Add kallsyms support in stack tracing functions.

parent ca647a02
...@@ -150,11 +150,11 @@ struct hw_interrupt_type open_pic_ipi = { ...@@ -150,11 +150,11 @@ struct hw_interrupt_type open_pic_ipi = {
if (irq < open_pic_irq_offset || irq >= NumSources+open_pic_irq_offset \ if (irq < open_pic_irq_offset || irq >= NumSources+open_pic_irq_offset \
|| ISR[irq - open_pic_irq_offset] == 0) { \ || ISR[irq - open_pic_irq_offset] == 0) { \
printk("open_pic.c:%d: illegal irq %d\n", __LINE__, irq); \ printk("open_pic.c:%d: illegal irq %d\n", __LINE__, irq); \
show_stack(NULL); } dump_stack(); }
#define check_arg_cpu(cpu) \ #define check_arg_cpu(cpu) \
if (cpu < 0 || cpu >= NumProcessors){ \ if (cpu < 0 || cpu >= NumProcessors){ \
printk("open_pic.c:%d: illegal cpu %d\n", __LINE__, cpu); \ printk("open_pic.c:%d: illegal cpu %d\n", __LINE__, cpu); \
show_stack(NULL); } dump_stack(); }
#else #else
#define check_arg_ipi(ipi) do {} while (0) #define check_arg_ipi(ipi) do {} while (0)
#define check_arg_timer(timer) do {} while (0) #define check_arg_timer(timer) do {} while (0)
...@@ -317,7 +317,7 @@ void __init openpic_init(int linux_irq_offset) ...@@ -317,7 +317,7 @@ void __init openpic_init(int linux_irq_offset)
openpic_reset(); openpic_reset();
#endif #endif
if (ppc_md.progress) ppc_md.progress("openpic enter", 0x122); if (ppc_md.progress) ppc_md.progress("openpic: enter", 0x122);
t = openpic_read(&OpenPIC->Global.Feature_Reporting0); t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
switch (t & OPENPIC_FEATURE_VERSION_MASK) { switch (t & OPENPIC_FEATURE_VERSION_MASK) {
...@@ -351,7 +351,7 @@ void __init openpic_init(int linux_irq_offset) ...@@ -351,7 +351,7 @@ void __init openpic_init(int linux_irq_offset)
open_pic_irq_offset = linux_irq_offset; open_pic_irq_offset = linux_irq_offset;
/* Initialize timer interrupts */ /* Initialize timer interrupts */
if ( ppc_md.progress ) ppc_md.progress("openpic timer",0x3ba); if ( ppc_md.progress ) ppc_md.progress("openpic: timer",0x3ba);
for (i = 0; i < OPENPIC_NUM_TIMERS; i++) { for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
/* Disabled, Priority 0 */ /* Disabled, Priority 0 */
openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i+linux_irq_offset); openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i+linux_irq_offset);
...@@ -361,7 +361,7 @@ void __init openpic_init(int linux_irq_offset) ...@@ -361,7 +361,7 @@ void __init openpic_init(int linux_irq_offset)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* Initialize IPI interrupts */ /* Initialize IPI interrupts */
if ( ppc_md.progress ) ppc_md.progress("openpic ipi",0x3bb); if ( ppc_md.progress ) ppc_md.progress("openpic: ipi",0x3bb);
for (i = 0; i < OPENPIC_NUM_IPI; i++) { for (i = 0; i < OPENPIC_NUM_IPI; i++) {
/* Disabled, Priority 10..13 */ /* Disabled, Priority 10..13 */
openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+linux_irq_offset); openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+linux_irq_offset);
...@@ -374,7 +374,7 @@ void __init openpic_init(int linux_irq_offset) ...@@ -374,7 +374,7 @@ void __init openpic_init(int linux_irq_offset)
#endif #endif
/* Initialize external interrupts */ /* Initialize external interrupts */
if (ppc_md.progress) ppc_md.progress("openpic ext",0x3bc); if (ppc_md.progress) ppc_md.progress("openpic: external",0x3bc);
openpic_set_priority(0xf); openpic_set_priority(0xf);
...@@ -389,7 +389,7 @@ void __init openpic_init(int linux_irq_offset) ...@@ -389,7 +389,7 @@ void __init openpic_init(int linux_irq_offset)
openpic_disable_irq(i+linux_irq_offset); openpic_disable_irq(i+linux_irq_offset);
/* /*
* We find the vale from either the InitSenses table * We find the value from either the InitSenses table
* or assume a negative polarity level interrupt. * or assume a negative polarity level interrupt.
*/ */
sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: 1; sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: 1;
...@@ -410,7 +410,7 @@ void __init openpic_init(int linux_irq_offset) ...@@ -410,7 +410,7 @@ void __init openpic_init(int linux_irq_offset)
irq_desc[i].handler = &open_pic; irq_desc[i].handler = &open_pic;
/* Initialize the spurious interrupt */ /* Initialize the spurious interrupt */
if (ppc_md.progress) ppc_md.progress("openpic spurious",0x3bd); if (ppc_md.progress) ppc_md.progress("openpic: spurious",0x3bd);
openpic_set_spurious(OPENPIC_VEC_SPURIOUS+linux_irq_offset); openpic_set_spurious(OPENPIC_VEC_SPURIOUS+linux_irq_offset);
/* Initialize the cascade */ /* Initialize the cascade */
...@@ -426,7 +426,7 @@ void __init openpic_init(int linux_irq_offset) ...@@ -426,7 +426,7 @@ void __init openpic_init(int linux_irq_offset)
#endif #endif
openpic_set_priority(0); openpic_set_priority(0);
if (ppc_md.progress) ppc_md.progress("openpic exit",0x222); if (ppc_md.progress) ppc_md.progress("openpic: exit",0x222);
} }
#ifdef notused #ifdef notused
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/prctl.h> #include <linux/prctl.h>
#include <linux/init_task.h> #include <linux/init_task.h>
#include <linux/module.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -69,6 +70,8 @@ struct task_struct init_task = INIT_TASK(init_task); ...@@ -69,6 +70,8 @@ struct task_struct init_task = INIT_TASK(init_task);
/* only used to get secondary processor up */ /* only used to get secondary processor up */
struct task_struct *current_set[NR_CPUS] = {&init_task, }; struct task_struct *current_set[NR_CPUS] = {&init_task, };
static void show_tsk_stack(struct task_struct *tsk, unsigned long sp);
#undef SHOW_TASK_SWITCHES #undef SHOW_TASK_SWITCHES
#undef CHECK_STACK #undef CHECK_STACK
...@@ -264,15 +267,15 @@ void show_regs(struct pt_regs * regs) ...@@ -264,15 +267,15 @@ void show_regs(struct pt_regs * regs)
printk("TASK = %p[%d] '%s' ", printk("TASK = %p[%d] '%s' ",
current, current->pid, current->comm); current, current->pid, current->comm);
printk("Last syscall: %ld ", current->thread.last_syscall); printk("Last syscall: %ld ", current->thread.last_syscall);
printk("\nlast math %p last altivec %p", last_task_used_math,
last_task_used_altivec);
#if defined(CONFIG_4xx) && defined(DCRN_PLB0_BEAR) #if defined(CONFIG_4xx) && defined(DCRN_PLB0_BEAR)
printk("\nPLB0: bear= 0x%8.8x acr= 0x%8.8x besr= 0x%8.8x\n", printk("\nPLB0: bear= 0x%8.8x acr= 0x%8.8x besr= 0x%8.8x\n",
mfdcr(DCRN_POB0_BEAR), mfdcr(DCRN_PLB0_ACR), mfdcr(DCRN_PLB0_BEAR), mfdcr(DCRN_PLB0_ACR),
mfdcr(DCRN_PLB0_BESR)); mfdcr(DCRN_PLB0_BESR));
#endif
#if defined(CONFIG_4xx) && defined(DCRN_POB0_BEAR)
printk("PLB0 to OPB: bear= 0x%8.8x besr0= 0x%8.8x besr1= 0x%8.8x\n", printk("PLB0 to OPB: bear= 0x%8.8x besr0= 0x%8.8x besr1= 0x%8.8x\n",
mfdcr(DCRN_PLB0_BEAR), mfdcr(DCRN_POB0_BESR0), mfdcr(DCRN_POB0_BEAR), mfdcr(DCRN_POB0_BESR0),
mfdcr(DCRN_POB0_BESR1)); mfdcr(DCRN_POB0_BESR1));
#endif #endif
...@@ -291,7 +294,7 @@ void show_regs(struct pt_regs * regs) ...@@ -291,7 +294,7 @@ void show_regs(struct pt_regs * regs)
break; break;
} }
printk("\n"); printk("\n");
show_stack((unsigned long *)regs->gpr[1]); show_tsk_stack(current, regs->gpr[1]);
} }
void exit_thread(void) void exit_thread(void)
...@@ -489,50 +492,61 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, ...@@ -489,50 +492,61 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
return error; return error;
} }
void void show_trace_task(struct task_struct *tsk)
show_stack(unsigned long *sp)
{ {
int cnt = 0; show_tsk_stack(tsk, tsk->thread.ksp);
unsigned long i;
if (sp == NULL)
sp = (unsigned long *)_get_SP();
printk("Call backtrace: ");
for (;;) {
if (__get_user(sp, (unsigned long **)sp))
break;
if (sp == NULL)
break;
if (__get_user(i, &sp[1]))
break;
if (cnt++ % 7 == 0)
printk("\n");
printk("%08lX ", i);
if (cnt > 32)
break;
}
printk("\n");
} }
void show_trace_task(struct task_struct *tsk) void dump_stack(void)
{
show_tsk_stack(current, _get_SP());
}
static void show_tsk_stack(struct task_struct *tsk, unsigned long sp)
{ {
unsigned long stack_top = (unsigned long) tsk->thread_info + THREAD_SIZE; unsigned long stack_top, prev_sp, ret;
unsigned long sp, prev_sp;
int count = 0; int count = 0;
unsigned long next_exc = 0;
struct pt_regs *regs;
extern char ret_from_except, ret_from_except_full, ret_from_syscall;
if (tsk == NULL) if (tsk == NULL)
return; return;
sp = (unsigned long) &tsk->thread.ksp; prev_sp = (unsigned long) (tsk->thread_info + 1);
do { stack_top = (unsigned long) tsk->thread_info + THREAD_SIZE;
prev_sp = sp; while (count < 16 && sp > prev_sp && sp < stack_top && (sp & 3) == 0) {
if (count == 0) {
printk("Call trace:");
#if CONFIG_KALLSYMS
printk("\n");
#endif
} else {
if (next_exc) {
ret = next_exc;
next_exc = 0;
} else
ret = *(unsigned long *)(sp + 4);
printk(" [%08lx] ", ret);
#if CONFIG_KALLSYMS
print_symbol("%s", ret);
printk("\n");
#endif
if (ret == (unsigned long) &ret_from_except
|| ret == (unsigned long) &ret_from_except_full
|| ret == (unsigned long) &ret_from_syscall) {
/* sp + 16 points to an exception frame */
regs = (struct pt_regs *) (sp + 16);
if (sp + 16 + sizeof(*regs) <= stack_top)
next_exc = regs->nip;
}
}
++count;
sp = *(unsigned long *)sp; sp = *(unsigned long *)sp;
if (sp <= prev_sp || sp >= stack_top || (sp & 3) != 0) }
break; #if !CONFIG_KALLSYMS
if (count > 0) if (count > 0)
printk("[%08lx] ", *(unsigned long *)(sp + 4));
} while (++count < 16);
if (count > 1)
printk("\n"); printk("\n");
#endif
} }
#if 0 #if 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment