]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'tracing/sysprof' into auto-ftrace-next
authorIngo Molnar <mingo@elte.hu>
Thu, 10 Jul 2008 09:43:08 +0000 (11:43 +0200)
committerIngo Molnar <mingo@elte.hu>
Thu, 10 Jul 2008 09:43:08 +0000 (11:43 +0200)
1  2 
kernel/trace/Makefile
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_selftest.c

diff --combined kernel/trace/Makefile
index c44a7dce9086a783f0245d16aad8726ba2bd3df4,7aec123ec1d8b2afbec6767166c1142f79cf3a0f..71d17de172886b5841a246b2505555cd13d9a981
@@@ -14,10 -14,10 +14,11 @@@ obj-$(CONFIG_FTRACE) += libftrace.
  
  obj-$(CONFIG_TRACING) += trace.o
  obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
+ obj-$(CONFIG_SYSPROF_TRACER) += trace_sysprof.o
  obj-$(CONFIG_FTRACE) += trace_functions.o
  obj-$(CONFIG_IRQSOFF_TRACER) += trace_irqsoff.o
  obj-$(CONFIG_PREEMPT_TRACER) += trace_irqsoff.o
  obj-$(CONFIG_SCHED_TRACER) += trace_sched_wakeup.o
 +obj-$(CONFIG_MMIOTRACE) += trace_mmiotrace.o
  
  libftrace-y := ftrace.o
diff --combined kernel/trace/trace.c
index 4a875600733b13654d03251a254a51d0b4f2c248,95b7c48a9a1d4d77f369e3f40a7ce164fc9f1c5f..e46de641ea44e03ff7646f070fe7f594f0596559
@@@ -27,7 -27,6 +27,7 @@@
  #include <linux/poll.h>
  #include <linux/gfp.h>
  #include <linux/fs.h>
 +#include <linux/kprobes.h>
  #include <linux/writeback.h>
  
  #include <linux/stacktrace.h>
@@@ -43,6 -42,11 +43,6 @@@ static cpumask_t __read_mostly               tracing
  #define for_each_tracing_cpu(cpu)     \
        for_each_cpu_mask(cpu, tracing_buffer_mask)
  
 -/* dummy trace to disable tracing */
 -static struct tracer no_tracer __read_mostly = {
 -      .name           = "none",
 -};
 -
  static int trace_alloc_page(void);
  static int trace_free_page(void);
  
@@@ -130,23 -134,6 +130,23 @@@ static DECLARE_WAIT_QUEUE_HEAD(trace_wa
  /* trace_flags holds iter_ctrl options */
  unsigned long trace_flags = TRACE_ITER_PRINT_PARENT;
  
 +static notrace void no_trace_init(struct trace_array *tr)
 +{
 +      int cpu;
 +
 +      if(tr->ctrl)
 +              for_each_online_cpu(cpu)
 +                      tracing_reset(tr->data[cpu]);
 +      tracer_enabled = 0;
 +}
 +
 +/* dummy trace to disable tracing */
 +static struct tracer no_tracer __read_mostly = {
 +      .name           = "none",
 +      .init           = no_trace_init
 +};
 +
 +
  /**
   * trace_wake_up - wake up tasks waiting for trace input
   *
@@@ -262,32 -249,24 +262,32 @@@ __update_max_tr(struct trace_array *tr
        tracing_record_cmdline(current);
  }
  
 +#define CHECK_COND(cond)                      \
 +      if (unlikely(cond)) {                   \
 +              tracing_disabled = 1;           \
 +              WARN_ON(1);                     \
 +              return -1;                      \
 +      }
 +
  /**
   * check_pages - integrity check of trace buffers
   *
   * As a safty measure we check to make sure the data pages have not
 - * been corrupted. TODO: configure to disable this because it adds
 - * a bit of overhead.
 + * been corrupted.
   */
 -void check_pages(struct trace_array_cpu *data)
 +int check_pages(struct trace_array_cpu *data)
  {
        struct page *page, *tmp;
  
 -      BUG_ON(data->trace_pages.next->prev != &data->trace_pages);
 -      BUG_ON(data->trace_pages.prev->next != &data->trace_pages);
 +      CHECK_COND(data->trace_pages.next->prev != &data->trace_pages);
 +      CHECK_COND(data->trace_pages.prev->next != &data->trace_pages);
  
        list_for_each_entry_safe(page, tmp, &data->trace_pages, lru) {
 -              BUG_ON(page->lru.next->prev != &page->lru);
 -              BUG_ON(page->lru.prev->next != &page->lru);
 +              CHECK_COND(page->lru.next->prev != &page->lru);
 +              CHECK_COND(page->lru.prev->next != &page->lru);
        }
 +
 +      return 0;
  }
  
  /**
@@@ -301,6 -280,7 +301,6 @@@ void *head_page(struct trace_array_cpu 
  {
        struct page *page;
  
 -      check_pages(data);
        if (list_empty(&data->trace_pages))
                return NULL;
  
@@@ -665,6 -645,9 +665,6 @@@ static char saved_cmdlines[SAVED_CMDLIN
  static int cmdline_idx;
  static DEFINE_SPINLOCK(trace_cmdline_lock);
  
 -/* trace in all context switches */
 -atomic_t trace_record_cmdline_enabled __read_mostly;
 -
  /* temporary disable recording */
  atomic_t trace_record_cmdline_disabled __read_mostly;
  
@@@ -848,48 -831,6 +848,48 @@@ ftrace(struct trace_array *tr, struct t
                trace_function(tr, data, ip, parent_ip, flags);
  }
  
 +#ifdef CONFIG_MMIOTRACE
 +void __trace_mmiotrace_rw(struct trace_array *tr, struct trace_array_cpu *data,
 +                                              struct mmiotrace_rw *rw)
 +{
 +      struct trace_entry *entry;
 +      unsigned long irq_flags;
 +
 +      raw_local_irq_save(irq_flags);
 +      __raw_spin_lock(&data->lock);
 +
 +      entry                   = tracing_get_trace_entry(tr, data);
 +      tracing_generic_entry_update(entry, 0);
 +      entry->type             = TRACE_MMIO_RW;
 +      entry->mmiorw           = *rw;
 +
 +      __raw_spin_unlock(&data->lock);
 +      raw_local_irq_restore(irq_flags);
 +
 +      trace_wake_up();
 +}
 +
 +void __trace_mmiotrace_map(struct trace_array *tr, struct trace_array_cpu *data,
 +                                              struct mmiotrace_map *map)
 +{
 +      struct trace_entry *entry;
 +      unsigned long irq_flags;
 +
 +      raw_local_irq_save(irq_flags);
 +      __raw_spin_lock(&data->lock);
 +
 +      entry                   = tracing_get_trace_entry(tr, data);
 +      tracing_generic_entry_update(entry, 0);
 +      entry->type             = TRACE_MMIO_MAP;
 +      entry->mmiomap          = *map;
 +
 +      __raw_spin_unlock(&data->lock);
 +      raw_local_irq_restore(irq_flags);
 +
 +      trace_wake_up();
 +}
 +#endif
 +
  void __trace_stack(struct trace_array *tr,
                   struct trace_array_cpu *data,
                   unsigned long flags,
@@@ -993,30 -934,6 +993,30 @@@ tracing_sched_wakeup_trace(struct trace
        trace_wake_up();
  }
  
 +void
 +ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3)
 +{
 +      struct trace_array *tr = &global_trace;
 +      struct trace_array_cpu *data;
 +      unsigned long flags;
 +      long disabled;
 +      int cpu;
 +
 +      if (tracing_disabled || current_trace == &no_tracer || !tr->ctrl)
 +              return;
 +
 +      local_irq_save(flags);
 +      cpu = raw_smp_processor_id();
 +      data = tr->data[cpu];
 +      disabled = atomic_inc_return(&data->disabled);
 +
 +      if (likely(disabled == 1))
 +              __trace_special(tr, data, arg1, arg2, arg3);
 +
 +      atomic_dec(&data->disabled);
 +      local_irq_restore(flags);
 +}
 +
  #ifdef CONFIG_FTRACE
  static void
  function_trace_call(unsigned long ip, unsigned long parent_ip)
        if (unlikely(!tracer_enabled))
                return;
  
 +      if (skip_trace(ip))
 +              return;
 +
        local_irq_save(flags);
        cpu = raw_smp_processor_id();
        data = tr->data[cpu];
@@@ -1257,20 -1171,6 +1257,20 @@@ static void s_stop(struct seq_file *m, 
        mutex_unlock(&trace_types_lock);
  }
  
 +#define KRETPROBE_MSG "[unknown/kretprobe'd]"
 +
 +#ifdef CONFIG_KRETPROBES
 +static inline int kretprobed(unsigned long addr)
 +{
 +      return addr == (unsigned long)kretprobe_trampoline;
 +}
 +#else
 +static inline int kretprobed(unsigned long addr)
 +{
 +      return 0;
 +}
 +#endif /* CONFIG_KRETPROBES */
 +
  static int
  seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address)
  {
@@@ -1506,10 -1406,7 +1506,10 @@@ print_lat_fmt(struct trace_iterator *it
        case TRACE_FN:
                seq_print_ip_sym(s, entry->fn.ip, sym_flags);
                trace_seq_puts(s, " (");
 -              seq_print_ip_sym(s, entry->fn.parent_ip, sym_flags);
 +              if (kretprobed(entry->fn.parent_ip))
 +                      trace_seq_puts(s, KRETPROBE_MSG);
 +              else
 +                      seq_print_ip_sym(s, entry->fn.parent_ip, sym_flags);
                trace_seq_puts(s, ")\n");
                break;
        case TRACE_CTX:
@@@ -1589,11 -1486,8 +1589,11 @@@ static int print_trace_fmt(struct trace
                        ret = trace_seq_printf(s, " <-");
                        if (!ret)
                                return 0;
 -                      ret = seq_print_ip_sym(s, entry->fn.parent_ip,
 -                                             sym_flags);
 +                      if (kretprobed(entry->fn.parent_ip))
 +                              ret = trace_seq_puts(s, KRETPROBE_MSG);
 +                      else
 +                              ret = seq_print_ip_sym(s, entry->fn.parent_ip,
 +                                                     sym_flags);
                        if (!ret)
                                return 0;
                }
@@@ -2672,7 -2566,7 +2672,7 @@@ tracing_entries_write(struct file *filp
  {
        unsigned long val;
        char buf[64];
 -      int ret;
 +      int i, ret;
  
        if (cnt >= sizeof(buf))
                return -EINVAL;
                        trace_free_page();
        }
  
 +      /* check integrity */
 +      for_each_tracing_cpu(i)
 +              check_pages(global_trace.data[i]);
 +
        filp->f_pos += cnt;
  
 +      /* If check pages failed, return ENOMEM */
 +      if (tracing_disabled)
 +              cnt = -ENOMEM;
   out:
        max_tr.entries = global_trace.entries;
        mutex_unlock(&trace_types_lock);
@@@ -2913,6 -2800,9 +2913,9 @@@ static __init void tracer_init_debugfs(
                pr_warning("Could not create debugfs "
                           "'dyn_ftrace_total_info' entry\n");
  #endif
+ #ifdef CONFIG_SYSPROF_TRACER
+       init_tracer_sysprof_debugfs(d_tracer);
+ #endif
  }
  
  static int trace_alloc_page(void)
@@@ -3040,6 -2930,8 +3043,6 @@@ __init static int tracer_alloc_buffers(
        int ret = -ENOMEM;
        int i;
  
 -      global_trace.ctrl = tracer_enabled;
 -
        /* TODO: make the number of buffers hot pluggable with CPUS */
        tracing_nr_buffers = num_possible_cpus();
        tracing_buffer_mask = cpu_possible_map;
        }
        max_tr.entries = global_trace.entries;
  
 -      pr_info("tracer: %d pages allocated for %ld",
 -              pages, trace_nr_entries);
 -      pr_info(" entries of %ld bytes\n", (long)TRACE_ENTRY_SIZE);
 +      pr_info("tracer: %d pages allocated for %ld entries of %ld bytes\n",
 +              pages, trace_nr_entries, (long)TRACE_ENTRY_SIZE);
        pr_info("   actual entries %ld\n", global_trace.entries);
  
        tracer_init_debugfs();
        current_trace = &no_tracer;
  
        /* All seems OK, enable tracing */
 +      global_trace.ctrl = tracer_enabled;
        tracing_disabled = 0;
  
        return 0;
diff --combined kernel/trace/trace.h
index 4966e6a964fed8c038546bc0306790ada216b218,b7f85d9c80d7ef9b66b8e701adf465dc844e620e..8cb215b239d50f8fa5b46966e9141d9ca8cdfd33
@@@ -5,7 -5,6 +5,7 @@@
  #include <asm/atomic.h>
  #include <linux/sched.h>
  #include <linux/clocksource.h>
 +#include <linux/mmiotrace.h>
  
  enum trace_type {
        __TRACE_FIRST_TYPE = 0,
@@@ -15,8 -14,6 +15,8 @@@
        TRACE_WAKE,
        TRACE_STACK,
        TRACE_SPECIAL,
 +      TRACE_MMIO_RW,
 +      TRACE_MMIO_MAP,
  
        __TRACE_LAST_TYPE
  };
@@@ -78,8 -75,6 +78,8 @@@ struct trace_entry 
                struct ctx_switch_entry         ctx;
                struct special_entry            special;
                struct stack_entry              stack;
 +              struct mmiotrace_rw             mmiorw;
 +              struct mmiotrace_map            mmiomap;
        };
  };
  
@@@ -193,6 -188,8 +193,8 @@@ struct trace_iterator 
  void tracing_reset(struct trace_array_cpu *data);
  int tracing_open_generic(struct inode *inode, struct file *filp);
  struct dentry *tracing_init_dentry(void);
+ void init_tracer_sysprof_debugfs(struct dentry *d_tracer);
  void ftrace(struct trace_array *tr,
                            struct trace_array_cpu *data,
                            unsigned long ip,
@@@ -223,8 -220,6 +225,8 @@@ void trace_function(struct trace_array 
  
  void tracing_start_function_trace(void);
  void tracing_stop_function_trace(void);
 +void tracing_start_cmdline_record(void);
 +void tracing_stop_cmdline_record(void);
  int register_tracer(struct tracer *type);
  void unregister_tracer(struct tracer *type);
  
@@@ -233,6 -228,8 +235,6 @@@ extern unsigned long nsecs_to_usecs(uns
  extern unsigned long tracing_max_latency;
  extern unsigned long tracing_thresh;
  
 -extern atomic_t trace_record_cmdline_enabled;
 -
  void update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu);
  void update_max_tr_single(struct trace_array *tr,
                          struct task_struct *tsk, int cpu);
@@@ -260,15 -257,6 +262,15 @@@ extern unsigned long ftrace_update_tot_
  extern int DYN_FTRACE_TEST_NAME(void);
  #endif
  
 +#ifdef CONFIG_MMIOTRACE
 +extern void __trace_mmiotrace_rw(struct trace_array *tr,
 +                              struct trace_array_cpu *data,
 +                              struct mmiotrace_rw *rw);
 +extern void __trace_mmiotrace_map(struct trace_array *tr,
 +                              struct trace_array_cpu *data,
 +                              struct mmiotrace_map *map);
 +#endif
 +
  #ifdef CONFIG_FTRACE_STARTUP_TEST
  #ifdef CONFIG_FTRACE
  extern int trace_selftest_startup_function(struct tracer *trace,
@@@ -294,6 -282,10 +296,10 @@@ extern int trace_selftest_startup_wakeu
  extern int trace_selftest_startup_sched_switch(struct tracer *trace,
                                               struct trace_array *tr);
  #endif
+ #ifdef CONFIG_SYSPROF_TRACER
+ extern int trace_selftest_startup_sysprof(struct tracer *trace,
+                                              struct trace_array *tr);
+ #endif
  #endif /* CONFIG_FTRACE_STARTUP_TEST */
  
  extern void *head_page(struct trace_array_cpu *data);
index 18c5423bc9777390c9442a5b461b5b67ba1d71f1,5588ecc40985fb394c66fe19f0fa99cab28e8122..0911b7e073bf197b021ba77c75f6777a03910aa7
@@@ -28,7 -28,6 +28,7 @@@ trace_test_buffer_cpu(struct trace_arra
        page = list_entry(data->trace_pages.next, struct page, lru);
        entries = page_address(page);
  
 +      check_pages(data);
        if (head_page(data) != entries)
                goto failed;
  
@@@ -538,3 -537,26 +538,26 @@@ trace_selftest_startup_sched_switch(str
        return ret;
  }
  #endif /* CONFIG_CONTEXT_SWITCH_TRACER */
+ #ifdef CONFIG_SYSPROF_TRACER
+ int
+ trace_selftest_startup_sysprof(struct tracer *trace, struct trace_array *tr)
+ {
+       unsigned long count;
+       int ret;
+       /* start the tracing */
+       tr->ctrl = 1;
+       trace->init(tr);
+       /* Sleep for a 1/10 of a second */
+       msleep(100);
+       /* stop the tracing. */
+       tr->ctrl = 0;
+       trace->ctrl_update(tr);
+       /* check the trace buffer */
+       ret = trace_test_buffer(tr, &count);
+       trace->reset(tr);
+       return ret;
+ }
+ #endif /* CONFIG_SYSPROF_TRACER */