linux/kernel/trace/trace_kdb.c
<<
>>
Prefs
   1/*
   2 * kdb helper for dumping the ftrace buffer
   3 *
   4 * Copyright (C) 2010 Jason Wessel <jason.wessel@windriver.com>
   5 *
   6 * ftrace_dump_buf based on ftrace_dump:
   7 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
   8 * Copyright (C) 2008 Ingo Molnar <mingo@redhat.com>
   9 *
  10 */
  11#include <linux/init.h>
  12#include <linux/kgdb.h>
  13#include <linux/kdb.h>
  14#include <linux/ftrace.h>
  15
  16#include "trace.h"
  17#include "trace_output.h"
  18
  19static void ftrace_dump_buf(int skip_lines, long cpu_file)
  20{
  21        /* use static because iter can be a bit big for the stack */
  22        static struct trace_iterator iter;
  23        unsigned int old_userobj;
  24        int cnt = 0, cpu;
  25
  26        trace_init_global_iter(&iter);
  27
  28        for_each_tracing_cpu(cpu) {
  29                atomic_inc(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);
  30        }
  31
  32        old_userobj = trace_flags;
  33
  34        /* don't look at user memory in panic mode */
  35        trace_flags &= ~TRACE_ITER_SYM_USEROBJ;
  36
  37        kdb_printf("Dumping ftrace buffer:\n");
  38
  39        /* reset all but tr, trace, and overruns */
  40        memset(&iter.seq, 0,
  41                   sizeof(struct trace_iterator) -
  42                   offsetof(struct trace_iterator, seq));
  43        iter.iter_flags |= TRACE_FILE_LAT_FMT;
  44        iter.pos = -1;
  45
  46        if (cpu_file == RING_BUFFER_ALL_CPUS) {
  47                for_each_tracing_cpu(cpu) {
  48                        iter.buffer_iter[cpu] =
  49                        ring_buffer_read_prepare(iter.trace_buffer->buffer, cpu);
  50                        ring_buffer_read_start(iter.buffer_iter[cpu]);
  51                        tracing_iter_reset(&iter, cpu);
  52                }
  53        } else {
  54                iter.cpu_file = cpu_file;
  55                iter.buffer_iter[cpu_file] =
  56                        ring_buffer_read_prepare(iter.trace_buffer->buffer, cpu_file);
  57                ring_buffer_read_start(iter.buffer_iter[cpu_file]);
  58                tracing_iter_reset(&iter, cpu_file);
  59        }
  60        if (!trace_empty(&iter))
  61                trace_find_next_entry_inc(&iter);
  62        while (!trace_empty(&iter)) {
  63                if (!cnt)
  64                        kdb_printf("---------------------------------\n");
  65                cnt++;
  66
  67                if (trace_find_next_entry_inc(&iter) != NULL && !skip_lines)
  68                        print_trace_line(&iter);
  69                if (!skip_lines)
  70                        trace_printk_seq(&iter.seq);
  71                else
  72                        skip_lines--;
  73                if (KDB_FLAG(CMD_INTERRUPT))
  74                        goto out;
  75        }
  76
  77        if (!cnt)
  78                kdb_printf("   (ftrace buffer empty)\n");
  79        else
  80                kdb_printf("---------------------------------\n");
  81
  82out:
  83        trace_flags = old_userobj;
  84
  85        for_each_tracing_cpu(cpu) {
  86                atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);
  87        }
  88
  89        for_each_tracing_cpu(cpu)
  90                if (iter.buffer_iter[cpu])
  91                        ring_buffer_read_finish(iter.buffer_iter[cpu]);
  92}
  93
  94/*
  95 * kdb_ftdump - Dump the ftrace log buffer
  96 */
  97static int kdb_ftdump(int argc, const char **argv)
  98{
  99        int skip_lines = 0;
 100        long cpu_file;
 101        char *cp;
 102
 103        if (argc > 2)
 104                return KDB_ARGCOUNT;
 105
 106        if (argc) {
 107                skip_lines = simple_strtol(argv[1], &cp, 0);
 108                if (*cp)
 109                        skip_lines = 0;
 110        }
 111
 112        if (argc == 2) {
 113                cpu_file = simple_strtol(argv[2], &cp, 0);
 114                if (*cp || cpu_file >= NR_CPUS || cpu_file < 0 ||
 115                    !cpu_online(cpu_file))
 116                        return KDB_BADINT;
 117        } else {
 118                cpu_file = RING_BUFFER_ALL_CPUS;
 119        }
 120
 121        kdb_trap_printk++;
 122        ftrace_dump_buf(skip_lines, cpu_file);
 123        kdb_trap_printk--;
 124
 125        return 0;
 126}
 127
 128static __init int kdb_ftrace_register(void)
 129{
 130        kdb_register_repeat("ftdump", kdb_ftdump, "[skip_#lines] [cpu]",
 131                            "Dump ftrace log", 0, KDB_REPEAT_NONE);
 132        return 0;
 133}
 134
 135late_initcall(kdb_ftrace_register);
 136