[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <86f20b97f95b0e9ab6301368acb0f6f31b9ae276.1534323834.git.zong@andestech.com>
Date: Wed, 15 Aug 2018 17:35:19 +0800
From: Zong Li <zong@...estech.com>
To: <green.hu@...il.com>, <deanbo422@...il.com>, <rostedt@...dmis.org>,
<mingo@...hat.com>, <arnd@...db.de>, <linux-kernel@...r.kernel.org>
CC: <zongbox@...il.com>, <greentime@...estech.com>,
Zong Li <zong@...estech.com>
Subject: [PATCH 2/6] nds32/ftrace: Support static function graph tracer
This patch contains implementation of static function graph tracer.
Signed-off-by: Zong Li <zong@...estech.com>
---
arch/nds32/Kconfig | 1 +
arch/nds32/kernel/ftrace.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+)
diff --git a/arch/nds32/Kconfig b/arch/nds32/Kconfig
index af30e1a..ae1a94ca 100644
--- a/arch/nds32/Kconfig
+++ b/arch/nds32/Kconfig
@@ -41,6 +41,7 @@ config NDS32
select RTC_LIB
select THREAD_INFO_IN_TASK
select HAVE_FUNCTION_TRACER
+ select HAVE_FUNCTION_GRAPH_TRACER
help
Andes(nds32) Linux support.
diff --git a/arch/nds32/kernel/ftrace.c b/arch/nds32/kernel/ftrace.c
index 563f64c..707fce7 100644
--- a/arch/nds32/kernel/ftrace.c
+++ b/arch/nds32/kernel/ftrace.c
@@ -6,6 +6,8 @@
extern void (*ftrace_trace_function)(unsigned long, unsigned long,
struct ftrace_ops*, struct pt_regs*);
+extern int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace);
+extern void ftrace_graph_caller(void);
noinline void __naked ftrace_stub(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct pt_regs *regs)
@@ -23,6 +25,73 @@ noinline void _mcount(unsigned long parent_ip)
ftrace_trace_function(ip - MCOUNT_INSN_SIZE, parent_ip,
NULL, NULL);
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ if (ftrace_graph_return != (trace_func_graph_ret_t)ftrace_stub
+ || ftrace_graph_entry != ftrace_graph_entry_stub)
+ ftrace_graph_caller();
+#endif
+
/* restore all state by the compiler epilogue */
}
EXPORT_SYMBOL(_mcount);
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+ unsigned long frame_pointer)
+{
+ unsigned long return_hooker = (unsigned long)&return_to_handler;
+ struct ftrace_graph_ent trace;
+ unsigned long old;
+ int err;
+
+ if (unlikely(atomic_read(¤t->tracing_graph_pause)))
+ return;
+
+ old = *parent;
+
+ trace.func = self_addr;
+ trace.depth = current->curr_ret_stack + 1;
+
+ /* Only trace if the calling function expects to */
+ if (!ftrace_graph_entry(&trace))
+ return;
+
+ err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+ frame_pointer, NULL);
+
+ if (err == -EBUSY)
+ return;
+
+ *parent = return_hooker;
+}
+
+noinline void ftrace_graph_caller(void)
+{
+ unsigned long *parent_ip =
+ (unsigned long *)(__builtin_frame_address(2) - 4);
+
+ unsigned long selfpc =
+ (unsigned long)(__builtin_return_address(1) - MCOUNT_INSN_SIZE);
+
+ unsigned long frame_pointer =
+ (unsigned long)__builtin_frame_address(3);
+
+ prepare_ftrace_return(parent_ip, selfpc, frame_pointer);
+}
+
+extern unsigned long ftrace_return_to_handler(unsigned long frame_pointer);
+void __naked return_to_handler(void)
+{
+ __asm__ __volatile__ (
+ /* save state needed by the ABI */
+ "smw.adm $r0,[$sp],$r1,#0x0 \n\t"
+
+ /* get original return address */
+ "move $r0, $fp \n\t"
+ "bal ftrace_return_to_handler\n\t"
+ "move $lp, $r0 \n\t"
+
+ /* restore state nedded by the ABI */
+ "lmw.bim $r0,[$sp],$r1,#0x0 \n\t");
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
--
2.7.4
Powered by blists - more mailing lists