Patches contributed by Eötvös Lorand University
commit b53dde9d34f2df396540988ebc65c33400f57b04
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 12 21:20:51 2008 +0200
ftrace: disable -pg for the tracer itself
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 3fec653d6533..c25a6cd6a529 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -1,3 +1,11 @@
+
+# Do not instrument the tracer itself:
+
+ifdef CONFIG_FTRACE
+ORIG_CFLAGS := $(KBUILD_CFLAGS)
+KBUILD_CFLAGS = $(subst -pg,,$(ORIG_CFLAGS))
+endif
+
obj-$(CONFIG_FTRACE) += libftrace.o
obj-$(CONFIG_TRACING) += trace.o
commit 9ff9cdb2d3b0971f89e899b3420aadd91bddc215
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 12 21:20:50 2008 +0200
ftrace: cleanups
clean up recent code.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index ff42345dd78e..425b1fec3d83 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -197,8 +197,8 @@ static int ftrace_record_suspend;
static struct dyn_ftrace *ftrace_free_records;
-static inline int
-notrace ftrace_ip_in_hash(unsigned long ip, unsigned long key)
+static inline int notrace
+ftrace_ip_in_hash(unsigned long ip, unsigned long key)
{
struct dyn_ftrace *p;
struct hlist_node *t;
@@ -1249,6 +1249,7 @@ static int __init notrace ftrace_dynamic_init(void)
int ret;
addr = (unsigned long)ftrace_record_ip;
+
stop_machine_run(ftrace_dyn_arch_init, &addr, NR_CPUS);
/* ftrace_dyn_arch_init places the return code in addr */
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index 3269f4ff5172..2ac0d09db6fb 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -309,7 +309,7 @@ void trace_softirqs_off(unsigned long ip)
{
}
-inline void print_irqtrace_events(struct task_struct *curr)
+inline notrace void print_irqtrace_events(struct task_struct *curr)
{
}
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index 85715b86a342..546307de6e3d 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -3,7 +3,7 @@
#include <linux/kthread.h>
#include <linux/delay.h>
-static inline int trace_valid_entry(struct trace_entry *entry)
+static notrace inline int trace_valid_entry(struct trace_entry *entry)
{
switch (entry->type) {
case TRACE_FN:
commit aeaee8a2c9cb4489f166ca0e39c568e8254faaa6
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 12 21:20:49 2008 +0200
ftrace: build fix
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 4650a3160b7f..08fbef1744cc 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -58,9 +58,6 @@ struct dyn_ftrace {
int ftrace_force_update(void);
void ftrace_set_filter(unsigned char *buf, int len, int reset);
-/* totally disable ftrace - can not re-enable after this */
-void ftrace_kill(void);
-
/* defined in arch */
extern int ftrace_ip_converted(unsigned long ip);
extern unsigned char *ftrace_nop_replace(void);
@@ -74,10 +71,13 @@ extern void ftrace_caller(void);
extern void ftrace_call(void);
extern void mcount_call(void);
#else
-# define ftrace_force_update() ({ 0; })
-# define ftrace_set_filter(buf, len, reset) do { } while (0)
+# define ftrace_force_update() ({ 0; })
+# define ftrace_set_filter(buf, len, reset) do { } while (0)
#endif
+/* totally disable ftrace - can not re-enable after this */
+void ftrace_kill(void);
+
static inline void tracer_disable(void)
{
#ifdef CONFIG_FTRACE
commit 2577046740fe6d77864128c6187c11125c2449ea
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 12 21:20:49 2008 +0200
ftrace: build fix
no need to backmerge, only affects ftrace-enabled kernels. (which is
not the default)
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 6974b212e938..958c4d77a67b 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1965,7 +1965,9 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
static cpumask_t mask;
static int start;
unsigned long flags;
+#ifdef CONFIG_FTRACE
int ftrace_save;
+#endif
int read = 0;
int cpu;
int len;
@@ -2044,8 +2046,10 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
cpus_clear(mask);
local_irq_save(flags);
+#ifdef CONFIG_FTRACE
ftrace_save = ftrace_enabled;
ftrace_enabled = 0;
+#endif
smp_wmb();
for_each_possible_cpu(cpu) {
data = iter->tr->data[cpu];
@@ -2087,7 +2091,9 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
data = iter->tr->data[cpu];
atomic_dec(&data->disabled);
}
+#ifdef CONFIG_FTRACE
ftrace_enabled = ftrace_save;
+#endif
local_irq_restore(flags);
/* Now copy what we have to the user */
commit 5e3ca0ec76fce92daa4eed0d02de9c79b1fe3920
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 12 21:20:49 2008 +0200
ftrace: introduce the "hex" output method
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 71b25b79b3de..6974b212e938 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -103,7 +103,8 @@ enum trace_iterator_flags {
TRACE_ITER_SYM_ADDR = 0x04,
TRACE_ITER_VERBOSE = 0x08,
TRACE_ITER_RAW = 0x10,
- TRACE_ITER_BIN = 0x20,
+ TRACE_ITER_HEX = 0x20,
+ TRACE_ITER_BIN = 0x40,
};
#define TRACE_ITER_SYM_MASK \
@@ -116,6 +117,7 @@ static const char *trace_options[] = {
"sym-addr",
"verbose",
"raw",
+ "hex",
"bin",
NULL
};
@@ -238,6 +240,47 @@ trace_seq_putmem(struct trace_seq *s, void *mem, size_t len)
return len;
}
+#define HEX_CHARS 17
+
+static notrace int
+trace_seq_putmem_hex(struct trace_seq *s, void *mem, size_t len)
+{
+ unsigned char hex[HEX_CHARS];
+ unsigned char *data;
+ unsigned char byte;
+ int i, j;
+
+ BUG_ON(len >= HEX_CHARS);
+
+ data = mem;
+
+#ifdef __BIG_ENDIAN
+ for (i = 0, j = 0; i < len; i++) {
+#else
+ for (i = len-1, j = 0; i >= 0; i--) {
+#endif
+ byte = data[i];
+
+ hex[j] = byte & 0x0f;
+ if (hex[j] >= 10)
+ hex[j] += 'a' - 10;
+ else
+ hex[j] += '0';
+ j++;
+
+ hex[j] = byte >> 4;
+ if (hex[j] >= 10)
+ hex[j] += 'a' - 10;
+ else
+ hex[j] += '0';
+ j++;
+ }
+ hex[j] = ' ';
+ j++;
+
+ return trace_seq_putmem(s, hex, j);
+}
+
static notrace void
trace_seq_reset(struct trace_seq *s)
{
@@ -1274,6 +1317,51 @@ do { \
return 0; \
} while (0)
+#define SEQ_PUT_HEX_FIELD_RET(s, x) \
+do { \
+ if (!trace_seq_putmem_hex(s, &(x), sizeof(x))) \
+ return 0; \
+} while (0)
+
+static notrace int print_hex_fmt(struct trace_iterator *iter)
+{
+ struct trace_seq *s = &iter->seq;
+ unsigned char newline = '\n';
+ struct trace_entry *entry;
+ int S;
+
+ entry = iter->ent;
+
+ SEQ_PUT_HEX_FIELD_RET(s, entry->pid);
+ SEQ_PUT_HEX_FIELD_RET(s, iter->cpu);
+ SEQ_PUT_HEX_FIELD_RET(s, entry->t);
+
+ switch (entry->type) {
+ case TRACE_FN:
+ SEQ_PUT_HEX_FIELD_RET(s, entry->fn.ip);
+ SEQ_PUT_HEX_FIELD_RET(s, entry->fn.parent_ip);
+ break;
+ case TRACE_CTX:
+ S = entry->ctx.prev_state < sizeof(state_to_char) ?
+ state_to_char[entry->ctx.prev_state] : 'X';
+ SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.prev_pid);
+ SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.prev_prio);
+ SEQ_PUT_HEX_FIELD_RET(s, S);
+ SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.next_pid);
+ SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.next_prio);
+ SEQ_PUT_HEX_FIELD_RET(s, entry->fn.parent_ip);
+ break;
+ case TRACE_SPECIAL:
+ SEQ_PUT_HEX_FIELD_RET(s, entry->special.arg1);
+ SEQ_PUT_HEX_FIELD_RET(s, entry->special.arg2);
+ SEQ_PUT_HEX_FIELD_RET(s, entry->special.arg3);
+ break;
+ }
+ SEQ_PUT_FIELD_RET(s, newline);
+
+ return 1;
+}
+
static notrace int print_bin_fmt(struct trace_iterator *iter)
{
struct trace_seq *s = &iter->seq;
@@ -1327,6 +1415,9 @@ static int print_trace_line(struct trace_iterator *iter)
if (trace_flags & TRACE_ITER_BIN)
return print_bin_fmt(iter);
+ if (trace_flags & TRACE_ITER_HEX)
+ return print_hex_fmt(iter);
+
if (trace_flags & TRACE_ITER_RAW)
return print_raw_fmt(iter);
commit 2e0f57618529a2739a5e1570e6c445c9c966b595
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 12 21:20:49 2008 +0200
ftrace: build fix
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index d74c039305ad..71b25b79b3de 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -432,47 +432,6 @@ notrace void tracing_reset(struct trace_array_cpu *data)
data->trace_tail_idx = 0;
}
-#ifdef CONFIG_FTRACE
-static notrace void
-function_trace_call(unsigned long ip, unsigned long parent_ip)
-{
- struct trace_array *tr = &global_trace;
- struct trace_array_cpu *data;
- unsigned long flags;
- long disabled;
- int cpu;
-
- if (unlikely(!tracer_enabled))
- return;
-
- local_irq_save(flags);
- cpu = raw_smp_processor_id();
- data = tr->data[cpu];
- disabled = atomic_inc_return(&data->disabled);
-
- if (likely(disabled == 1))
- ftrace(tr, data, ip, parent_ip, flags);
-
- atomic_dec(&data->disabled);
- local_irq_restore(flags);
-}
-
-static struct ftrace_ops trace_ops __read_mostly =
-{
- .func = function_trace_call,
-};
-#endif
-
-notrace void tracing_start_function_trace(void)
-{
- register_ftrace_function(&trace_ops);
-}
-
-notrace void tracing_stop_function_trace(void)
-{
- unregister_ftrace_function(&trace_ops);
-}
-
#define SAVED_CMDLINES 128
static unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1];
static unsigned map_cmdline_to_pid[SAVED_CMDLINES];
@@ -635,8 +594,8 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags)
}
notrace void
-ftrace(struct trace_array *tr, struct trace_array_cpu *data,
- unsigned long ip, unsigned long parent_ip, unsigned long flags)
+__ftrace(struct trace_array *tr, struct trace_array_cpu *data,
+ unsigned long ip, unsigned long parent_ip, unsigned long flags)
{
struct trace_entry *entry;
unsigned long irq_flags;
@@ -650,6 +609,14 @@ ftrace(struct trace_array *tr, struct trace_array_cpu *data,
spin_unlock_irqrestore(&data->lock, irq_flags);
}
+notrace void
+ftrace(struct trace_array *tr, struct trace_array_cpu *data,
+ unsigned long ip, unsigned long parent_ip, unsigned long flags)
+{
+ if (likely(!atomic_read(&data->disabled)))
+ __ftrace(tr, data, ip, parent_ip, flags);
+}
+
notrace void
trace_special(struct trace_array *tr, struct trace_array_cpu *data,
unsigned long arg1, unsigned long arg2, unsigned long arg3)
@@ -688,6 +655,47 @@ tracing_sched_switch_trace(struct trace_array *tr,
spin_unlock_irqrestore(&data->lock, irq_flags);
}
+#ifdef CONFIG_FTRACE
+static notrace void
+function_trace_call(unsigned long ip, unsigned long parent_ip)
+{
+ struct trace_array *tr = &global_trace;
+ struct trace_array_cpu *data;
+ unsigned long flags;
+ long disabled;
+ int cpu;
+
+ if (unlikely(!tracer_enabled))
+ return;
+
+ local_irq_save(flags);
+ cpu = raw_smp_processor_id();
+ data = tr->data[cpu];
+ disabled = atomic_inc_return(&data->disabled);
+
+ if (likely(disabled == 1))
+ __ftrace(tr, data, ip, parent_ip, flags);
+
+ atomic_dec(&data->disabled);
+ local_irq_restore(flags);
+}
+
+static struct ftrace_ops trace_ops __read_mostly =
+{
+ .func = function_trace_call,
+};
+
+notrace void tracing_start_function_trace(void)
+{
+ register_ftrace_function(&trace_ops);
+}
+
+notrace void tracing_stop_function_trace(void)
+{
+ unregister_ftrace_function(&trace_ops);
+}
+#endif
+
enum trace_file_type {
TRACE_FILE_LAT_FMT = 1,
};
@@ -722,7 +730,7 @@ trace_entry_idx(struct trace_array *tr, struct trace_array_cpu *data,
return &array[iter->next_page_idx[cpu]];
}
-static struct notrace trace_entry *
+static struct trace_entry * notrace
find_next_entry(struct trace_iterator *iter, int *ent_cpu)
{
struct trace_array *tr = iter->tr;
@@ -1866,6 +1874,7 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
static cpumask_t mask;
static int start;
unsigned long flags;
+ int ftrace_save;
int read = 0;
int cpu;
int len;
@@ -1944,6 +1953,9 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
cpus_clear(mask);
local_irq_save(flags);
+ ftrace_save = ftrace_enabled;
+ ftrace_enabled = 0;
+ smp_wmb();
for_each_possible_cpu(cpu) {
data = iter->tr->data[cpu];
@@ -1951,10 +1963,14 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
continue;
atomic_inc(&data->disabled);
- spin_lock(&data->lock);
cpu_set(cpu, mask);
}
+ for_each_cpu_mask(cpu, mask) {
+ data = iter->tr->data[cpu];
+ spin_lock(&data->lock);
+ }
+
while (find_next_entry_inc(iter) != NULL) {
int len = iter->seq.len;
@@ -1974,8 +1990,13 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
for_each_cpu_mask(cpu, mask) {
data = iter->tr->data[cpu];
spin_unlock(&data->lock);
+ }
+
+ for_each_cpu_mask(cpu, mask) {
+ data = iter->tr->data[cpu];
atomic_dec(&data->disabled);
}
+ ftrace_enabled = ftrace_save;
local_irq_restore(flags);
/* Now copy what we have to the user */
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index e5d34b78fc99..69a0eb00a0a5 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -9,10 +9,10 @@
* Copyright (C) 2004-2006 Ingo Molnar
* Copyright (C) 2004 William Lee Irwin III
*/
-#include <linux/fs.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/ftrace.h>
+#include <linux/fs.h>
#include "trace.h"
commit 0fd9e0dac9026df09986a4b201518ae015814aef
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 12 21:20:48 2008 +0200
ftrace: use cpu clock again
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 3dc6eac85b11..d74c039305ad 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -42,61 +42,9 @@ ns2usecs(cycle_t nsec)
return nsec;
}
-static const int time_sync_freq_max = 128;
-static const cycle_t time_sync_thresh = 100000;
-
-static DEFINE_PER_CPU(cycle_t, time_offset);
-static DEFINE_PER_CPU(cycle_t, prev_cpu_time);
-static DEFINE_PER_CPU(int, time_sync_count);
-static DEFINE_PER_CPU(int, time_sync_freq);
-
-/*
- * Global lock which we take every now and then to synchronize
- * the CPUs time. This method is not warp-safe, but it's good
- * enough to synchronize slowly diverging time sources and thus
- * it's good enough for tracing:
- */
-static DEFINE_SPINLOCK(time_sync_lock);
-static cycle_t prev_global_time;
-
-static notrace cycle_t __ftrace_now_sync(cycles_t time, int cpu)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&time_sync_lock, flags);
-
- /*
- * Update the synchronization frequency:
- */
- if (per_cpu(time_sync_freq, cpu) < time_sync_freq_max)
- per_cpu(time_sync_freq, cpu) *= 2;
- per_cpu(time_sync_count, cpu) = per_cpu(time_sync_freq, cpu);
-
- if (time < prev_global_time) {
- per_cpu(time_offset, cpu) += prev_global_time - time;
- time = prev_global_time;
- } else {
- prev_global_time = time;
- }
-
- spin_unlock_irqrestore(&time_sync_lock, flags);
-
- return time;
-}
-
notrace cycle_t ftrace_now(int cpu)
{
- cycle_t prev_cpu_time, time, delta_time;
-
- prev_cpu_time = per_cpu(prev_cpu_time, cpu);
- time = sched_clock() + per_cpu(time_offset, cpu);
- delta_time = time-prev_cpu_time;
-
- if (unlikely(delta_time > time_sync_thresh ||
- --per_cpu(time_sync_count, cpu) <= 0))
- time = __ftrace_now_sync(time, cpu);
-
- return time;
+ return cpu_clock(cpu);
}
static struct trace_array global_trace;
commit dcb6308f2b56720599f6b9d5a01c33e67e69bde4
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 12 21:20:48 2008 +0200
ftrace, locking fix
should be an irq-safe lock ...
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index fa13059eb462..70f94fa92c10 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -691,14 +691,15 @@ ftrace(struct trace_array *tr, struct trace_array_cpu *data,
unsigned long ip, unsigned long parent_ip, unsigned long flags)
{
struct trace_entry *entry;
+ unsigned long irq_flags;
- spin_lock(&data->lock);
+ spin_lock_irqsave(&data->lock, irq_flags);
entry = tracing_get_trace_entry(tr, data);
tracing_generic_entry_update(entry, flags);
entry->type = TRACE_FN;
entry->fn.ip = ip;
entry->fn.parent_ip = parent_ip;
- spin_unlock(&data->lock);
+ spin_unlock_irqrestore(&data->lock, irq_flags);
}
notrace void
@@ -706,15 +707,16 @@ trace_special(struct trace_array *tr, struct trace_array_cpu *data,
unsigned long arg1, unsigned long arg2, unsigned long arg3)
{
struct trace_entry *entry;
+ unsigned long irq_flags;
- spin_lock(&data->lock);
+ spin_lock_irqsave(&data->lock, irq_flags);
entry = tracing_get_trace_entry(tr, data);
tracing_generic_entry_update(entry, 0);
entry->type = TRACE_SPECIAL;
entry->special.arg1 = arg1;
entry->special.arg2 = arg2;
entry->special.arg3 = arg3;
- spin_unlock(&data->lock);
+ spin_unlock_irqrestore(&data->lock, irq_flags);
}
notrace void
@@ -724,8 +726,9 @@ tracing_sched_switch_trace(struct trace_array *tr,
unsigned long flags)
{
struct trace_entry *entry;
+ unsigned long irq_flags;
- spin_lock(&data->lock);
+ spin_lock_irqsave(&data->lock, irq_flags);
entry = tracing_get_trace_entry(tr, data);
tracing_generic_entry_update(entry, flags);
entry->type = TRACE_CTX;
@@ -734,7 +737,7 @@ tracing_sched_switch_trace(struct trace_array *tr,
entry->ctx.prev_state = prev->state;
entry->ctx.next_pid = next->pid;
entry->ctx.next_prio = next->prio;
- spin_unlock(&data->lock);
+ spin_unlock_irqrestore(&data->lock, irq_flags);
}
enum trace_file_type {
commit f0a920d5752e1788c0cba2add103076bcc0f7a49
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 12 21:20:47 2008 +0200
ftrace: add trace_special()
for ad-hoc tracing.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index d78cbc4fc519..fa13059eb462 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -137,6 +137,7 @@ enum trace_type {
TRACE_FN,
TRACE_CTX,
+ TRACE_SPECIAL,
__TRACE_LAST_TYPE
};
@@ -700,6 +701,22 @@ ftrace(struct trace_array *tr, struct trace_array_cpu *data,
spin_unlock(&data->lock);
}
+notrace void
+trace_special(struct trace_array *tr, struct trace_array_cpu *data,
+ unsigned long arg1, unsigned long arg2, unsigned long arg3)
+{
+ struct trace_entry *entry;
+
+ spin_lock(&data->lock);
+ entry = tracing_get_trace_entry(tr, data);
+ tracing_generic_entry_update(entry, 0);
+ entry->type = TRACE_SPECIAL;
+ entry->special.arg1 = arg1;
+ entry->special.arg2 = arg2;
+ entry->special.arg3 = arg3;
+ spin_unlock(&data->lock);
+}
+
notrace void
tracing_sched_switch_trace(struct trace_array *tr,
struct trace_array_cpu *data,
@@ -1167,6 +1184,12 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
entry->ctx.next_prio,
comm);
break;
+ case TRACE_SPECIAL:
+ trace_seq_printf(s, " %lx %lx %lx\n",
+ entry->special.arg1,
+ entry->special.arg2,
+ entry->special.arg3);
+ break;
default:
trace_seq_printf(s, "Unknown type %d\n", entry->type);
}
@@ -1234,6 +1257,14 @@ static notrace int print_trace_fmt(struct trace_iterator *iter)
if (!ret)
return 0;
break;
+ case TRACE_SPECIAL:
+ ret = trace_seq_printf(s, " %lx %lx %lx\n",
+ entry->special.arg1,
+ entry->special.arg2,
+ entry->special.arg3);
+ if (!ret)
+ return 0;
+ break;
}
return 1;
}
@@ -1271,6 +1302,14 @@ static notrace int print_raw_fmt(struct trace_iterator *iter)
if (!ret)
return 0;
break;
+ case TRACE_SPECIAL:
+ ret = trace_seq_printf(s, " %lx %lx %lx\n",
+ entry->special.arg1,
+ entry->special.arg2,
+ entry->special.arg3);
+ if (!ret)
+ return 0;
+ break;
}
return 1;
}
@@ -1304,6 +1343,11 @@ static notrace int print_bin_fmt(struct trace_iterator *iter)
SEQ_PUT_FIELD_RET(s, entry->ctx.next_pid);
SEQ_PUT_FIELD_RET(s, entry->ctx.next_prio);
break;
+ case TRACE_SPECIAL:
+ SEQ_PUT_FIELD_RET(s, entry->special.arg1);
+ SEQ_PUT_FIELD_RET(s, entry->special.arg2);
+ SEQ_PUT_FIELD_RET(s, entry->special.arg3);
+ break;
}
return 1;
}
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 27fa2d06f499..7bdfef35c05a 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -25,6 +25,15 @@ struct ctx_switch_entry {
unsigned char next_prio;
};
+/*
+ * Special (free-form) trace entry:
+ */
+struct special_entry {
+ unsigned long arg1;
+ unsigned long arg2;
+ unsigned long arg3;
+};
+
/*
* The trace entry - the most basic unit of tracing. This is what
* is printed in the end as a single line in the trace output, such as:
@@ -41,6 +50,7 @@ struct trace_entry {
union {
struct ftrace_entry fn;
struct ctx_switch_entry ctx;
+ struct special_entry special;
};
};
@@ -154,6 +164,11 @@ void tracing_sched_switch_trace(struct trace_array *tr,
struct task_struct *next,
unsigned long flags);
void tracing_record_cmdline(struct task_struct *tsk);
+void trace_special(struct trace_array *tr,
+ struct trace_array_cpu *data,
+ unsigned long arg1,
+ unsigned long arg2,
+ unsigned long arg3);
void tracing_start_function_trace(void);
void tracing_stop_function_trace(void);
commit cb0f12aae8d085140d37ada351aa5a8e76c3f9b0
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 12 21:20:47 2008 +0200
ftrace: bin-output
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index bebd263f582f..d78cbc4fc519 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -154,6 +154,7 @@ enum trace_iterator_flags {
TRACE_ITER_SYM_ADDR = 0x04,
TRACE_ITER_VERBOSE = 0x08,
TRACE_ITER_RAW = 0x10,
+ TRACE_ITER_BIN = 0x20,
};
#define TRACE_ITER_SYM_MASK \
@@ -166,6 +167,7 @@ static const char *trace_options[] = {
"sym-addr",
"verbose",
"raw",
+ "bin",
NULL
};
@@ -275,6 +277,18 @@ trace_seq_putc(struct trace_seq *s, unsigned char c)
return 1;
}
+static notrace int
+trace_seq_putmem(struct trace_seq *s, void *mem, size_t len)
+{
+ if (len > ((PAGE_SIZE - 1) - s->len))
+ return 0;
+
+ memcpy(s->buffer + s->len, mem, len);
+ s->len += len;
+
+ return len;
+}
+
static notrace void
trace_seq_reset(struct trace_seq *s)
{
@@ -1261,6 +1275,39 @@ static notrace int print_raw_fmt(struct trace_iterator *iter)
return 1;
}
+#define SEQ_PUT_FIELD_RET(s, x) \
+do { \
+ if (!trace_seq_putmem(s, &(x), sizeof(x))) \
+ return 0; \
+} while (0)
+
+static notrace int print_bin_fmt(struct trace_iterator *iter)
+{
+ struct trace_seq *s = &iter->seq;
+ struct trace_entry *entry;
+
+ entry = iter->ent;
+
+ SEQ_PUT_FIELD_RET(s, entry->pid);
+ SEQ_PUT_FIELD_RET(s, entry->cpu);
+ SEQ_PUT_FIELD_RET(s, entry->t);
+
+ switch (entry->type) {
+ case TRACE_FN:
+ SEQ_PUT_FIELD_RET(s, entry->fn.ip);
+ SEQ_PUT_FIELD_RET(s, entry->fn.parent_ip);
+ break;
+ case TRACE_CTX:
+ SEQ_PUT_FIELD_RET(s, entry->ctx.prev_pid);
+ SEQ_PUT_FIELD_RET(s, entry->ctx.prev_prio);
+ SEQ_PUT_FIELD_RET(s, entry->ctx.prev_state);
+ SEQ_PUT_FIELD_RET(s, entry->ctx.next_pid);
+ SEQ_PUT_FIELD_RET(s, entry->ctx.next_prio);
+ break;
+ }
+ return 1;
+}
+
static int trace_empty(struct trace_iterator *iter)
{
struct trace_array_cpu *data;
@@ -1279,6 +1326,9 @@ static int trace_empty(struct trace_iterator *iter)
static int print_trace_line(struct trace_iterator *iter)
{
+ if (trace_flags & TRACE_ITER_BIN)
+ return print_bin_fmt(iter);
+
if (trace_flags & TRACE_ITER_RAW)
return print_raw_fmt(iter);