]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - kernel/trace/trace_selftest.c
ftrace: remove printks from irqsoff trace
[mv-sheeva.git] / kernel / trace / trace_selftest.c
index ef4d3cc009f55e966a89a99e115f8266f3dae5b0..18c5423bc9777390c9442a5b461b5b67ba1d71f1 100644 (file)
@@ -1,12 +1,16 @@
 /* Include in trace.c */
 
 #include <linux/kthread.h>
+#include <linux/delay.h>
 
 static inline int trace_valid_entry(struct trace_entry *entry)
 {
        switch (entry->type) {
        case TRACE_FN:
        case TRACE_CTX:
+       case TRACE_WAKE:
+       case TRACE_STACK:
+       case TRACE_SPECIAL:
                return 1;
        }
        return 0;
@@ -15,28 +19,30 @@ static inline int trace_valid_entry(struct trace_entry *entry)
 static int
 trace_test_buffer_cpu(struct trace_array *tr, struct trace_array_cpu *data)
 {
-       struct page *page;
        struct trace_entry *entries;
+       struct page *page;
        int idx = 0;
        int i;
 
+       BUG_ON(list_empty(&data->trace_pages));
        page = list_entry(data->trace_pages.next, struct page, lru);
        entries = page_address(page);
 
-       if (data->trace != entries)
+       check_pages(data);
+       if (head_page(data) != entries)
                goto failed;
 
        /*
         * The starting trace buffer always has valid elements,
-        * if any element exits.
+        * if any element exists.
         */
-       entries = data->trace;
+       entries = head_page(data);
 
        for (i = 0; i < tr->entries; i++) {
 
-               if (i < data->trace_idx &&
-                   !trace_valid_entry(&entries[idx])) {
-                       printk(KERN_CONT ".. invalid entry %d ", entries[idx].type);
+               if (i < data->trace_idx && !trace_valid_entry(&entries[idx])) {
+                       printk(KERN_CONT ".. invalid entry %d ",
+                               entries[idx].type);
                        goto failed;
                }
 
@@ -65,6 +71,8 @@ trace_test_buffer_cpu(struct trace_array *tr, struct trace_array_cpu *data)
        return 0;
 
  failed:
+       /* disable tracing */
+       tracing_disabled = 1;
        printk(KERN_CONT ".. corrupted trace buffer .. ");
        return -1;
 }
@@ -75,21 +83,24 @@ trace_test_buffer_cpu(struct trace_array *tr, struct trace_array_cpu *data)
  */
 static int trace_test_buffer(struct trace_array *tr, unsigned long *count)
 {
-       unsigned long cnt = 0;
-       int cpu;
-       int ret = 0;
+       unsigned long flags, cnt = 0;
+       int cpu, ret = 0;
 
+       /* Don't allow flipping of max traces now */
+       raw_local_irq_save(flags);
+       __raw_spin_lock(&ftrace_max_lock);
        for_each_possible_cpu(cpu) {
-               if (!tr->data[cpu]->trace)
+               if (!head_page(tr->data[cpu]))
                        continue;
 
                cnt += tr->data[cpu]->trace_idx;
-               printk("%d: count = %ld\n", cpu, cnt);
 
                ret = trace_test_buffer_cpu(tr, tr->data[cpu]);
                if (ret)
                        break;
        }
+       __raw_spin_unlock(&ftrace_max_lock);
+       raw_local_irq_restore(flags);
 
        if (count)
                *count = cnt;
@@ -98,6 +109,101 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count)
 }
 
 #ifdef CONFIG_FTRACE
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+#define __STR(x) #x
+#define STR(x) __STR(x)
+
+/* Test dynamic code modification and ftrace filters */
+int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
+                                          struct trace_array *tr,
+                                          int (*func)(void))
+{
+       unsigned long count;
+       int ret;
+       int save_ftrace_enabled = ftrace_enabled;
+       int save_tracer_enabled = tracer_enabled;
+       char *func_name;
+
+       /* The ftrace test PASSED */
+       printk(KERN_CONT "PASSED\n");
+       pr_info("Testing dynamic ftrace: ");
+
+       /* enable tracing, and record the filter function */
+       ftrace_enabled = 1;
+       tracer_enabled = 1;
+
+       /* passed in by parameter to fool gcc from optimizing */
+       func();
+
+       /* update the records */
+       ret = ftrace_force_update();
+       if (ret) {
+               printk(KERN_CONT ".. ftraced failed .. ");
+               return ret;
+       }
+
+       /*
+        * Some archs *cough*PowerPC*cough* add charachters to the
+        * start of the function names. We simply put a '*' to
+        * accomodate them.
+        */
+       func_name = "*" STR(DYN_FTRACE_TEST_NAME);
+
+       /* filter only on our function */
+       ftrace_set_filter(func_name, strlen(func_name), 1);
+
+       /* enable tracing */
+       tr->ctrl = 1;
+       trace->init(tr);
+       /* Sleep for a 1/10 of a second */
+       msleep(100);
+
+       /* we should have nothing in the buffer */
+       ret = trace_test_buffer(tr, &count);
+       if (ret)
+               goto out;
+
+       if (count) {
+               ret = -1;
+               printk(KERN_CONT ".. filter did not filter .. ");
+               goto out;
+       }
+
+       /* call our function again */
+       func();
+
+       /* sleep again */
+       msleep(100);
+
+       /* stop the tracing. */
+       tr->ctrl = 0;
+       trace->ctrl_update(tr);
+       ftrace_enabled = 0;
+
+       /* check the trace buffer */
+       ret = trace_test_buffer(tr, &count);
+       trace->reset(tr);
+
+       /* we should only have one item */
+       if (!ret && count != 1) {
+               printk(KERN_CONT ".. filter failed count=%ld ..", count);
+               ret = -1;
+               goto out;
+       }
+ out:
+       ftrace_enabled = save_ftrace_enabled;
+       tracer_enabled = save_tracer_enabled;
+
+       /* Enable tracing on all functions again */
+       ftrace_set_filter(NULL, 0, 1);
+
+       return ret;
+}
+#else
+# define trace_selftest_startup_dynamic_tracing(trace, tr, func) ({ 0; })
+#endif /* CONFIG_DYNAMIC_FTRACE */
 /*
  * Simple verification test of ftrace function tracer.
  * Enable ftrace, sleep 1/10 second, and then read the trace
@@ -108,8 +214,13 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
 {
        unsigned long count;
        int ret;
+       int save_ftrace_enabled = ftrace_enabled;
+       int save_tracer_enabled = tracer_enabled;
+
+       /* make sure msleep has been recorded */
+       msleep(1);
 
-       /* make sure functions have been recorded */
+       /* force the recorded functions to be traced */
        ret = ftrace_force_update();
        if (ret) {
                printk(KERN_CONT ".. ftraced failed .. ");
@@ -117,6 +228,9 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
        }
 
        /* start the tracing */
+       ftrace_enabled = 1;
+       tracer_enabled = 1;
+
        tr->ctrl = 1;
        trace->init(tr);
        /* Sleep for a 1/10 of a second */
@@ -124,6 +238,8 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
        /* stop the tracing. */
        tr->ctrl = 0;
        trace->ctrl_update(tr);
+       ftrace_enabled = 0;
+
        /* check the trace buffer */
        ret = trace_test_buffer(tr, &count);
        trace->reset(tr);
@@ -131,8 +247,20 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
        if (!ret && !count) {
                printk(KERN_CONT ".. no entries found ..");
                ret = -1;
+               goto out;
        }
 
+       ret = trace_selftest_startup_dynamic_tracing(trace, tr,
+                                                    DYN_FTRACE_TEST_NAME);
+
+ out:
+       ftrace_enabled = save_ftrace_enabled;
+       tracer_enabled = save_tracer_enabled;
+
+       /* kill ftrace totally if we failed */
+       if (ret)
+               ftrace_kill();
+
        return ret;
 }
 #endif /* CONFIG_FTRACE */
@@ -290,11 +418,11 @@ trace_selftest_startup_preemptirqsoff(struct tracer *trace, struct trace_array *
 #ifdef CONFIG_SCHED_TRACER
 static int trace_wakeup_test_thread(void *data)
 {
-       struct completion *x = data;
-
        /* Make this a RT thread, doesn't need to be too high */
+       struct sched_param param = { .sched_priority = 5 };
+       struct completion *x = data;
 
-       rt_mutex_setprio(current, MAX_RT_PRIO - 5);
+       sched_setscheduler(current, SCHED_FIFO, &param);
 
        /* Make it know we have a new prio */
        complete(x);
@@ -328,7 +456,7 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr)
 
        /* create a high prio thread */
        p = kthread_run(trace_wakeup_test_thread, &isrt, "ftrace-test");
-       if (!IS_ERR(p)) {
+       if (IS_ERR(p)) {
                printk(KERN_CONT "Failed to create ftrace wakeup test thread ");
                return -1;
        }
@@ -410,6 +538,3 @@ trace_selftest_startup_sched_switch(struct tracer *trace, struct trace_array *tr
        return ret;
 }
 #endif /* CONFIG_CONTEXT_SWITCH_TRACER */
-
-#ifdef CONFIG_DYNAMIC_FTRACE
-#endif /* CONFIG_DYNAMIC_FTRACE */