From 301930759f64ae006702b07de02fe215cf8fc9a1 Mon Sep 17 00:00:00 2001
From: Philippe Langlais <philippe.langlais@stericsson.com>
Date: Thu, 26 May 2011 10:46:02 +0200
Subject: [PATCH 2/3] trace: add hardware trace hooks in tracing
 infrastructure

for printk, trace_printk, functions tracing, stacks tracing,
scheduler wakeup/context switch tracing, IO blocks tracing, MMIO tracing
and branch tracing

Signed-off-by: Philippe Langlais <philippe.langlais@linaro.org>
---
 kernel/printk.c                      |    4 ++++
 kernel/trace/blktrace.c              |    3 +++
 kernel/trace/trace.c                 |   13 +++++++++++++
 kernel/trace/trace_branch.c          |    3 +++
 kernel/trace/trace_events.c          |    3 +++
 kernel/trace/trace_functions_graph.c |    8 ++++++++
 kernel/trace/trace_mmiotrace.c       |    5 +++++
 kernel/trace/trace_sched_switch.c    |   10 ++++++++++
 8 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/kernel/printk.c b/kernel/printk.c
index 3518539..89a80e6 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -41,6 +41,7 @@
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/rculist.h>
+#include <linux/hwtrace.h>
 
 #include <asm/uaccess.h>
 
@@ -874,6 +875,9 @@ asmlinkage int vprintk(const char *fmt, va_list args)
 
 	p = printk_buf;
 
+	/* Send printk buffer to trace hardware if any */
+	hwtrace_dup_printk(printk_buf, printed_len);
+
 	/* Read log level and handle special printk prefix */
 	plen = log_prefix(p, &current_log_level, &special);
 	if (plen) {
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index 6957aa2..160b8c5 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -25,6 +25,7 @@
 #include <linux/debugfs.h>
 #include <linux/time.h>
 #include <linux/uaccess.h>
+#include <linux/hwtrace.h>
 
 #include <trace/events/block.h>
 
@@ -97,6 +98,8 @@ record_it:
 		t->pdu_len = len;
 		memcpy((void *) t + sizeof(*t), data, len);
 
+		hwtrace_blk_trace(t);
+
 		if (blk_tracer)
 			trace_buffer_unlock_commit(buffer, event, 0, pc);
 	}
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index ee9c921..6b4cbf2 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -37,6 +37,7 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/fs.h>
+#include <linux/hwtrace.h>
 
 #include "trace.h"
 #include "trace_output.h"
@@ -1222,6 +1223,8 @@ trace_function(struct trace_array *tr,
 
 	if (!filter_check_discard(call, entry, buffer, event))
 		ring_buffer_unlock_commit(buffer, event);
+
+	hwtrace_ftrace(ip, parent_ip);
 }
 
 void
@@ -1256,8 +1259,12 @@ static void __ftrace_trace_stack(struct ring_buffer *buffer,
 	trace.entries		= entry->caller;
 
 	save_stack_trace(&trace);
+
+	hwtrace_stack_trace(0, trace.nr_entries, trace.entries);
+
 	if (!filter_check_discard(call, entry, buffer, event))
 		ring_buffer_unlock_commit(buffer, event);
+
 }
 
 void ftrace_trace_stack(struct ring_buffer *buffer, unsigned long flags,
@@ -1339,6 +1346,8 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)
 	if (!filter_check_discard(call, entry, buffer, event))
 		ring_buffer_unlock_commit(buffer, event);
 
+	hwtrace_stack_trace(true, trace.nr_entries, trace.entries);
+
  out_drop_count:
 	__this_cpu_dec(user_stack_count);
  out:
@@ -1413,6 +1422,8 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
 		ftrace_trace_stack(buffer, flags, 6, pc);
 	}
 
+	hwtrace_trace_bprintk_buf(ip, fmt, trace_buf, sizeof(u32) * len);
+
 out_unlock:
 	arch_spin_unlock(&trace_buf_lock);
 	local_irq_restore(flags);
@@ -1489,6 +1500,8 @@ int trace_array_vprintk(struct trace_array *tr,
 		ftrace_trace_stack(buffer, irq_flags, 6, pc);
 	}
 
+	hwtrace_trace_printk_buf(ip, trace_buf, len);
+
  out_unlock:
 	arch_spin_unlock(&trace_buf_lock);
 	raw_local_irq_restore(irq_flags);
diff --git a/kernel/trace/trace_branch.c b/kernel/trace/trace_branch.c
index 8d3538b..9b74a69 100644
--- a/kernel/trace/trace_branch.c
+++ b/kernel/trace/trace_branch.c
@@ -13,6 +13,7 @@
 #include <linux/ftrace.h>
 #include <linux/hash.h>
 #include <linux/fs.h>
+#include <linux/hwtrace.h>
 #include <asm/local.h>
 
 #include "trace.h"
@@ -76,6 +77,8 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
 	entry->line = f->line;
 	entry->correct = val == expect;
 
+	hwtrace_branch(entry->line, entry->func, entry->file, entry->correct);
+
 	if (!filter_check_discard(call, entry, buffer, event))
 		ring_buffer_unlock_commit(buffer, event);
 
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 2fe1103..7612977 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -17,6 +17,7 @@
 #include <linux/ctype.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/hwtrace.h>
 
 #include <asm/setup.h>
 
@@ -1645,6 +1646,8 @@ function_test_events_call(unsigned long ip, unsigned long parent_ip)
 
 	trace_nowake_buffer_unlock_commit(buffer, event, flags, pc);
 
+	hwtrace_ftrace(ip, parent_ip);
+
  out:
 	atomic_dec(&per_cpu(ftrace_test_event_disable, cpu));
 	preempt_enable_notrace();
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 962cdb2..4da10e8 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -11,6 +11,7 @@
 #include <linux/ftrace.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
+#include <linux/hwtrace.h>
 
 #include "trace.h"
 #include "trace_output.h"
@@ -205,6 +206,9 @@ int __trace_graph_entry(struct trace_array *tr,
 		return 0;
 	entry	= ring_buffer_event_data(event);
 	entry->graph_ent			= *trace;
+
+	hwtrace_func_graph(trace->func, trace->depth, 0, 0, 0);
+
 	if (!filter_current_check_discard(buffer, call, entry, event))
 		ring_buffer_unlock_commit(buffer, event);
 
@@ -309,6 +313,10 @@ void __trace_graph_return(struct trace_array *tr,
 		return;
 	entry	= ring_buffer_event_data(event);
 	entry->ret				= *trace;
+
+	hwtrace_func_graph(trace->func, trace->depth, trace->calltime,
+			trace->rettime, trace->overrun);
+
 	if (!filter_current_check_discard(buffer, call, entry, event))
 		ring_buffer_unlock_commit(buffer, event);
 }
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c
index 017fa37..02ebed9 100644
--- a/kernel/trace/trace_mmiotrace.c
+++ b/kernel/trace/trace_mmiotrace.c
@@ -11,6 +11,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/time.h>
+#include <linux/hwtrace.h>
 
 #include <asm/atomic.h>
 
@@ -323,6 +324,8 @@ static void __trace_mmiotrace_rw(struct trace_array *tr,
 	entry	= ring_buffer_event_data(event);
 	entry->rw			= *rw;
 
+	hwtrace_mmio(rw, sizeof(*rw));
+
 	if (!filter_check_discard(call, entry, buffer, event))
 		trace_buffer_unlock_commit(buffer, event, 0, pc);
 }
@@ -353,6 +356,8 @@ static void __trace_mmiotrace_map(struct trace_array *tr,
 	entry	= ring_buffer_event_data(event);
 	entry->map			= *map;
 
+	hwtrace_mmio(map, sizeof(*map));
+
 	if (!filter_check_discard(call, entry, buffer, event))
 		trace_buffer_unlock_commit(buffer, event, 0, pc);
 }
diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c
index 7e62c0a..3a6e5a6 100644
--- a/kernel/trace/trace_sched_switch.c
+++ b/kernel/trace/trace_sched_switch.c
@@ -10,6 +10,7 @@
 #include <linux/kallsyms.h>
 #include <linux/uaccess.h>
 #include <linux/ftrace.h>
+#include <linux/hwtrace.h>
 #include <trace/events/sched.h>
 
 #include "trace.h"
@@ -47,6 +48,10 @@ tracing_sched_switch_trace(struct trace_array *tr,
 
 	if (!filter_check_discard(call, entry, buffer, event))
 		trace_buffer_unlock_commit(buffer, event, flags, pc);
+
+	hwtrace_sched(false, entry->prev_pid, entry->prev_prio,
+			entry->prev_state, entry->next_pid, entry->next_prio,
+			entry->next_state, entry->next_cpu);
 }
 
 static void
@@ -103,6 +108,11 @@ tracing_sched_wakeup_trace(struct trace_array *tr,
 
 	if (!filter_check_discard(call, entry, buffer, event))
 		ring_buffer_unlock_commit(buffer, event);
+
+	hwtrace_sched(true, entry->prev_pid, entry->prev_prio,
+			entry->prev_state, entry->next_pid, entry->next_prio,
+			entry->next_state, entry->next_cpu);
+
 	ftrace_trace_stack(tr->buffer, flags, 6, pc);
 	ftrace_trace_userstack(tr->buffer, flags, pc);
 }
-- 
1.7.5

