--- arch/arm/Kconfig.debug | 2 1 + 1 - 0 ! arch/arm/include/asm/hardirq.h | 2 1 + 1 - 0 ! arch/arm/include/asm/irq.h | 3 3 + 0 - 0 ! arch/arm/include/asm/smp.h | 2 2 + 0 - 0 ! arch/arm/kernel/process.c | 15 15 + 0 - 0 ! arch/arm/kernel/smp.c | 60 60 + 0 - 0 ! 6 files changed, 82 insertions(+), 2 deletions(-) Index: b/arch/arm/include/asm/irq.h =================================================================== --- a/arch/arm/include/asm/irq.h +++ b/arch/arm/include/asm/irq.h @@ -25,6 +25,9 @@ extern void migrate_irqs(void); extern void asm_do_IRQ(unsigned int, struct pt_regs *); void init_IRQ(void); +void arch_trigger_all_cpu_backtrace(void); +#define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace + #endif #endif Index: b/arch/arm/kernel/process.c =================================================================== --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -62,6 +62,21 @@ static volatile int hlt_counter; #include +#ifdef CONFIG_SMP + +void arch_trigger_all_cpu_backtrace(void) +{ + smp_send_all_cpu_backtrace(); +} + +#else + +void arch_trigger_all_cpu_backtrace(void) +{ +} + +#endif + void disable_hlt(void) { hlt_counter++; Index: b/arch/arm/include/asm/smp.h =================================================================== --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -93,4 +93,6 @@ extern void arch_send_call_function_ipi_ */ extern void show_local_irqs(struct seq_file *, int); +extern void smp_send_all_cpu_backtrace(void); + #endif /* ifndef __ASM_ARM_SMP_H */ Index: b/arch/arm/kernel/smp.c =================================================================== --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -53,6 +53,7 @@ enum ipi_msg_type { IPI_CALL_FUNC, IPI_CALL_FUNC_SINGLE, IPI_CPU_STOP, + IPI_ALL_CPU_BACKTRACE, }; int __cpuinit __cpu_up(unsigned int cpu) @@ -405,6 +406,7 @@ static const char *ipi_types[NR_IPI] = { S(IPI_CALL_FUNC, "Function call interrupts"), S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"), S(IPI_CPU_STOP, "CPU stop interrupts"), + S(IPI_ALL_CPU_BACKTRACE, "All cpu backtrace"), }; void show_ipi_list(struct seq_file *p, int prec) @@ -555,6 +557,60 @@ static void ipi_cpu_stop(unsigned int cp cpu_relax(); } +static cpumask_t backtrace_mask; + +/* "in progress" flag of arch_trigger_all_cpu_backtrace */ +static unsigned long backtrace_flag; + +void smp_send_all_cpu_backtrace(void) +{ + int i; + cpumask_t this_cpu_mask; + + if (test_and_set_bit(0, &backtrace_flag)) + /* + * If there is already a trigger_all_cpu_backtrace() in progress + * (backtrace_flag == 1), don't output double cpu dump infos. + */ + return; + + backtrace_mask = cpu_online_map; + cpus_clear(this_cpu_mask); + cpu_set(smp_processor_id(), this_cpu_mask); + + printk(KERN_INFO "sending IPI to all CPUs:\n"); + smp_cross_call(&backtrace_mask, IPI_ALL_CPU_BACKTRACE); + + + /* Wait for up to 10 seconds for all other CPUs to do the backtrace */ + for (i = 0; i < 10 * 1000; i++) { + if (cpus_equal(backtrace_mask, this_cpu_mask)) + break; + mdelay(1); + } + + clear_bit(0, &backtrace_flag); + smp_mb__after_clear_bit(); +} + + +/* + * ipi_all_cpu_backtrace - handle IPI from smp_send_all_cpu_backtrace() + */ +static void ipi_all_cpu_backtrace(unsigned int cpu, struct pt_regs *regs) +{ + if (cpu_isset(cpu, backtrace_mask)) { + static arch_spinlock_t lock = __ARCH_SPIN_LOCK_UNLOCKED; + + arch_spin_lock(&lock); + printk(KERN_WARNING "IPI backtrace for cpu %d\n", cpu); +printk("regs 0x%p\n", regs); + show_regs(regs); + arch_spin_unlock(&lock); + cpu_clear(cpu, backtrace_mask); + } +} + /* * Main handler for inter-processor interrupts */ @@ -587,6 +643,10 @@ asmlinkage void __exception_irq_entry do ipi_cpu_stop(cpu); break; + case IPI_ALL_CPU_BACKTRACE: + ipi_all_cpu_backtrace(cpu, regs); + break; + default: printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); Index: b/arch/arm/Kconfig.debug =================================================================== --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -21,7 +21,7 @@ config STRICT_DEVMEM # traces, you can get a slightly smaller kernel by setting this option to # n, but then RMK will have to kill you ;). config FRAME_POINTER - bool + bool "frame pointer support" depends on !THUMB2_KERNEL default y if !ARM_UNWIND || FUNCTION_GRAPH_TRACER help Index: b/arch/arm/include/asm/hardirq.h =================================================================== --- a/arch/arm/include/asm/hardirq.h +++ b/arch/arm/include/asm/hardirq.h @@ -5,7 +5,7 @@ #include #include -#define NR_IPI 5 +#define NR_IPI 6 typedef struct { unsigned int __softirq_pending;