--- linux-2.6.15.1/include/linux/ipipe_trace.h.orig 2006-01-19 10:16:43.000000000 +0100 +++ linux-2.6.15.1/include/linux/ipipe_trace.h 2006-01-19 13:13:07.000000000 +0100 @@ -31,4 +31,7 @@ void ipipe_trace_special(unsigned char s int ipipe_trace_max_reset(void); int ipipe_trace_frozen_reset(void); +void ipipe_trace_panic_freeze(void); +void ipipe_trace_panic_dump(void); + #endif /* !__LINUX_IPIPE_H */ --- linux-2.6.15.1/kernel/ipipe/tracer.c.orig 2006-01-19 10:26:31.000000000 +0100 +++ linux-2.6.15.1/kernel/ipipe/tracer.c 2006-01-20 11:31:58.000000000 +0100 @@ -107,10 +107,17 @@ static int verbose_trace = 0; static DECLARE_MUTEX(out_mutex); static struct ipipe_trace_path *print_path; +static struct ipipe_trace_path *panic_path; static int print_pre_trace; static int print_post_trace; +static long __ipipe_signed_tsc2us(long long tsc); +static void +__ipipe_trace_point_type(char *buf, struct ipipe_trace_point *point); +static void __ipipe_print_symname(struct seq_file *m, unsigned long eip); + + static notrace int __ipipe_get_free_trace_path(int old, int cpu_id) { int new_active = old; @@ -498,6 +505,61 @@ int ipipe_trace_frozen_reset(void) } EXPORT_SYMBOL(ipipe_trace_frozen_reset); +void ipipe_trace_panic_freeze(void) +{ + unsigned long flags; + int cpu_id; + + ipipe_trace_enable = 0; + local_irq_save_hw_notrace(flags); + + cpu_id = raw_smp_processor_id(); + + panic_path = &trace_paths[cpu_id][active_path[cpu_id]]; + + local_irq_restore_hw(flags); +} +EXPORT_SYMBOL(ipipe_trace_panic_freeze); + +void ipipe_trace_panic_dump(void) +{ + int cnt = back_trace; + int start, pos; + + printk("I-pipe tracer log (%d points):\n", cnt); + + start = pos = WRAP_POINT_NO(panic_path->trace_pos-1); + + while (cnt-- > 0) { + struct ipipe_trace_point *point = &panic_path->point[pos]; + long time; + char buf[16]; + + if (!point->eip) + printk("--\n"); + else { + __ipipe_trace_point_type(buf, point); + printk(buf); + + if (point->type != IPIPE_TRACE_FN) + printk("0x%08lx ", point->v); + else + printk(" "); + + time = __ipipe_signed_tsc2us(point->timestamp - + panic_path->point[start].timestamp); + printk(" %5ld ", time); + + __ipipe_print_symname(NULL, point->eip); + printk(" ("); + __ipipe_print_symname(NULL, point->parent_eip); + printk(")\n"); + } + pos = WRAP_POINT_NO(pos - 1); + } +} +EXPORT_SYMBOL(ipipe_trace_panic_dump); + /* --- /proc output --- */ @@ -510,6 +572,46 @@ static notrace int __ipipe_in_critical_t print_post_trace))); } +static long __ipipe_signed_tsc2us(long long tsc) +{ + unsigned long long abs_tsc; + long us; + + /* ipipe_tsc2us works on unsigned => handle sign separately */ + abs_tsc = (tsc >= 0) ? tsc : -tsc; + us = ipipe_tsc2us(abs_tsc); + if (tsc < 0) + return -us; + else + return us; +} + +static void +__ipipe_trace_point_type(char *buf, struct ipipe_trace_point *point) +{ + switch (point->type) { + case IPIPE_TRACE_FN: + strcpy(buf, "fn "); + break; + + case IPIPE_TRACE_BEGIN: + strcpy(buf, "begin "); + break; + + case IPIPE_TRACE_END: + strcpy(buf, "end "); + break; + + case IPIPE_TRACE_FREEZE: + strcpy(buf, "freeze "); + break; + + default: /* IPIPE_TRACE_SPECIAL */ + sprintf(buf, "(0x%02x) ", + point->type - IPIPE_TRACE_SPECIAL); + } +} + static void __ipipe_print_pathmark(struct seq_file *m, struct ipipe_trace_point *point) { @@ -562,15 +664,26 @@ static void __ipipe_print_symname(struct char *modname; sym_name = kallsyms_lookup(eip, &size, &offset, &modname, namebuf); - if (sym_name) { - if (verbose_trace) { - seq_printf(m, "%s+0x%lx", sym_name, offset); - if (modname) - seq_printf(m, " [%s]", modname); + + /* printing to /proc? */ + if (m) { + if (sym_name) { + if (verbose_trace) { + seq_printf(m, "%s+0x%lx", sym_name, offset); + if (modname) + seq_printf(m, " [%s]", modname); + } else + seq_puts(m, sym_name); } else - seq_puts(m, sym_name); - } else - seq_printf(m, "<%08lx>", eip); + seq_printf(m, "<%08lx>", eip); + } else { + /* panic dump */ + if (sym_name) { + printk("%s+0x%lx", sym_name, offset); + if (modname) + printk(" [%s]", modname); + } + } } #if defined(CONFIG_XENO_OPT_DEBUG) || defined(CONFIG_DEBUG_PREEMPT) @@ -690,52 +803,28 @@ static void __ipipe_prtrace_stop(struct static int __ipipe_prtrace_show(struct seq_file *m, void *p) { long time; - long long delta; - unsigned long long abs_delta; struct ipipe_trace_point *point = p; + char buf[16]; if (!point->eip) { seq_puts(m, "--\n"); return 0; } - /* ipipe_tsc2us works on unsigned => handle sign separately */ - delta = point->timestamp - - print_path->point[print_path->begin].timestamp; - abs_delta = (delta >= 0) ? delta : -delta; - time = ipipe_tsc2us(abs_delta); - if (delta < 0) - time = -time; - __ipipe_print_pathmark(m, point); - switch (point->type) { - case IPIPE_TRACE_FN: - seq_puts(m, "fn "); - break; - - case IPIPE_TRACE_BEGIN: - seq_puts(m, "begin "); - break; - - case IPIPE_TRACE_END: - seq_puts(m, "end "); - break; - - case IPIPE_TRACE_FREEZE: - seq_puts(m, "freeze "); - break; - - default: /* IPIPE_TRACE_SPECIAL */ - seq_printf(m, "(0x%02x) ", - point->type - IPIPE_TRACE_SPECIAL); - } + __ipipe_trace_point_type(buf, point); + seq_puts(m, buf); if (verbose_trace) { if (point->type != IPIPE_TRACE_FN) seq_printf(m, "0x%08lx ", point->v); else seq_puts(m, " "); } + + time = __ipipe_signed_tsc2us(point->timestamp - + print_path->point[print_path->begin].timestamp); seq_printf(m, "%5ld", time); + __ipipe_print_delay(m, point); __ipipe_print_symname(m, point->eip); seq_puts(m, " (");