linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] Support ftrace on NDS32 architecture
@ 2018-08-15  9:35 Zong Li
  2018-08-15  9:35 ` [PATCH 1/6] nds32/ftrace: Support static function tracer Zong Li
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Zong Li @ 2018-08-15  9:35 UTC (permalink / raw)
  To: green.hu, deanbo422, rostedt, mingo, arnd, linux-kernel
  Cc: zongbox, greentime, Zong Li

This patch set implements the ftrace function and function graph tracer
on NDS32 architecture. We try to use C code to do everything, so we don't
need to separate the implementation to assembly code and C code, we just
need one ftrace.c file.

In mcount function, we use the prologue/epilogue which generated by compiler
to help us to save/restore the status. On the other hand, we use naked
attribute of gcc to avoid to generate the prologue/epilogue when we don't
need it(such as ftrace_stub and return_to_handler).

We pass the following tests:

1. FTRACE_STARTUP_TEST: PASS

2. tools/testing/selftests/ftrace/:
 # of passed:  28
 # of failed:  1
 # of unresolved:  0
 # of untested:  0
 # of unsupported:  38
 # of xfailed:  0
 # of undefined(test bug):  0

The failed case is func-filter-glob.tc.
When setting the '*aw*lock' to the set_ftrace_filter in this test case,
we got the error because we have no these functions such as _raw_spin_lock,
_raw_spin_trylock and so on in our kernel.

Zong Li (6):
  nds32/ftrace: Support static function tracer
  nds32/ftrace: Support static function graph tracer
  nds32/ftrace: Add RECORD_MCOUNT support
  nds32/ftrace: Support dynamic function tracer
  nds32/ftrace: Support dynamic function graph tracer
  nds32/stack: Get real return address by using ftrace_graph_ret_addr

 arch/nds32/Kconfig              |   4 +
 arch/nds32/Makefile             |   4 +
 arch/nds32/include/asm/ftrace.h |  46 +++++++
 arch/nds32/kernel/Makefile      |   6 +
 arch/nds32/kernel/ftrace.c      | 297 ++++++++++++++++++++++++++++++++++++++++
 arch/nds32/kernel/stacktrace.c  |   4 +
 arch/nds32/kernel/traps.c       |  30 +---
 scripts/recordmcount.pl         |   3 +
 8 files changed, 370 insertions(+), 24 deletions(-)
 create mode 100644 arch/nds32/include/asm/ftrace.h
 create mode 100644 arch/nds32/kernel/ftrace.c

-- 
2.7.4


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/6] nds32/ftrace: Support static function tracer
  2018-08-15  9:35 [PATCH 0/6] Support ftrace on NDS32 architecture Zong Li
@ 2018-08-15  9:35 ` Zong Li
  2018-08-15 20:11   ` Steven Rostedt
  2018-08-15  9:35 ` [PATCH 2/6] nds32/ftrace: Support static function graph tracer Zong Li
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 9+ messages in thread
From: Zong Li @ 2018-08-15  9:35 UTC (permalink / raw)
  To: green.hu, deanbo422, rostedt, mingo, arnd, linux-kernel
  Cc: zongbox, greentime, Zong Li

This patch support the static function tracer. On nds32 ABI, we need to
always push return address to stack for __builtin_return_address can
work correctly, otherwise, it will get the wrong value of $lp at leaf
function.

Signed-off-by: Zong Li <zong@andestech.com>
---
 arch/nds32/Kconfig              |  1 +
 arch/nds32/Makefile             |  4 ++++
 arch/nds32/include/asm/ftrace.h | 20 ++++++++++++++++++++
 arch/nds32/kernel/Makefile      |  6 ++++++
 arch/nds32/kernel/ftrace.c      | 28 ++++++++++++++++++++++++++++
 5 files changed, 59 insertions(+)
 create mode 100644 arch/nds32/include/asm/ftrace.h
 create mode 100644 arch/nds32/kernel/ftrace.c

diff --git a/arch/nds32/Kconfig b/arch/nds32/Kconfig
index 34f7222..af30e1a 100644
--- a/arch/nds32/Kconfig
+++ b/arch/nds32/Kconfig
@@ -40,6 +40,7 @@ config NDS32
 	select NO_IOPORT_MAP
 	select RTC_LIB
 	select THREAD_INFO_IN_TASK
+	select HAVE_FUNCTION_TRACER
 	help
 	  Andes(nds32) Linux support.
 
diff --git a/arch/nds32/Makefile b/arch/nds32/Makefile
index 031c676..3ca8172 100644
--- a/arch/nds32/Makefile
+++ b/arch/nds32/Makefile
@@ -5,6 +5,10 @@ KBUILD_DEFCONFIG := defconfig
 
 comma = ,
 
+ifdef CONFIG_FUNCTION_TRACER
+arch-y += -malways-save-lp -mno-relax
+endif
+
 KBUILD_CFLAGS	+= $(call cc-option, -mno-sched-prolog-epilog)
 KBUILD_CFLAGS	+= -mcmodel=large
 
diff --git a/arch/nds32/include/asm/ftrace.h b/arch/nds32/include/asm/ftrace.h
new file mode 100644
index 0000000..bac7657
--- /dev/null
+++ b/arch/nds32/include/asm/ftrace.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_NDS32_FTRACE_H
+#define __ASM_NDS32_FTRACE_H
+
+#ifdef CONFIG_FUNCTION_TRACER
+
+#define HAVE_FUNCTION_GRAPH_FP_TEST
+
+#define MCOUNT_ADDR ((unsigned long)(_mcount))
+/* mcount call is composed of three instructions:
+ * sethi + ori + jral
+ */
+#define MCOUNT_INSN_SIZE 12
+
+extern void _mcount(unsigned long parent_ip);
+
+#endif /* CONFIG_FUNCTION_TRACER */
+
+#endif /* __ASM_NDS32_FTRACE_H */
diff --git a/arch/nds32/kernel/Makefile b/arch/nds32/kernel/Makefile
index 4279274..27cded3 100644
--- a/arch/nds32/kernel/Makefile
+++ b/arch/nds32/kernel/Makefile
@@ -21,3 +21,9 @@ extra-y := head.o vmlinux.lds
 
 
 obj-y				+= vdso/
+
+obj-$(CONFIG_FUNCTION_TRACER)   += ftrace.o
+
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
+endif
diff --git a/arch/nds32/kernel/ftrace.c b/arch/nds32/kernel/ftrace.c
new file mode 100644
index 0000000..563f64c
--- /dev/null
+++ b/arch/nds32/kernel/ftrace.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/ftrace.h>
+#include <linux/uaccess.h>
+#include <asm/cacheflush.h>
+
+extern void (*ftrace_trace_function)(unsigned long, unsigned long,
+				     struct ftrace_ops*, struct pt_regs*);
+
+noinline void __naked ftrace_stub(unsigned long ip, unsigned long parent_ip,
+				  struct ftrace_ops *op, struct pt_regs *regs)
+{
+	__asm__ ("");  /* avoid to optimize as pure function */
+}
+
+noinline void _mcount(unsigned long parent_ip)
+{
+	/* save all state by the compiler prologue */
+
+	unsigned long ip = (unsigned long)__builtin_return_address(0);
+
+	if (ftrace_trace_function != ftrace_stub)
+		ftrace_trace_function(ip - MCOUNT_INSN_SIZE, parent_ip,
+				      NULL, NULL);
+
+	/* restore all state by the compiler epilogue */
+}
+EXPORT_SYMBOL(_mcount);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/6] nds32/ftrace: Support static function graph tracer
  2018-08-15  9:35 [PATCH 0/6] Support ftrace on NDS32 architecture Zong Li
  2018-08-15  9:35 ` [PATCH 1/6] nds32/ftrace: Support static function tracer Zong Li
@ 2018-08-15  9:35 ` Zong Li
  2018-08-15  9:35 ` [PATCH 3/6] nds32/ftrace: Add RECORD_MCOUNT support Zong Li
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Zong Li @ 2018-08-15  9:35 UTC (permalink / raw)
  To: green.hu, deanbo422, rostedt, mingo, arnd, linux-kernel
  Cc: zongbox, greentime, Zong Li

This patch contains implementation of static function graph tracer.

Signed-off-by: Zong Li <zong@andestech.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(&current->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


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/6] nds32/ftrace: Add RECORD_MCOUNT support
  2018-08-15  9:35 [PATCH 0/6] Support ftrace on NDS32 architecture Zong Li
  2018-08-15  9:35 ` [PATCH 1/6] nds32/ftrace: Support static function tracer Zong Li
  2018-08-15  9:35 ` [PATCH 2/6] nds32/ftrace: Support static function graph tracer Zong Li
@ 2018-08-15  9:35 ` Zong Li
  2018-08-15  9:35 ` [PATCH 4/6] nds32/ftrace: Support dynamic function tracer Zong Li
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Zong Li @ 2018-08-15  9:35 UTC (permalink / raw)
  To: green.hu, deanbo422, rostedt, mingo, arnd, linux-kernel
  Cc: zongbox, greentime, Zong Li

Recognize NDS32 object files in recordmcount.pl.

Signed-off-by: Zong Li <zong@andestech.com>
---
 arch/nds32/Kconfig      | 1 +
 scripts/recordmcount.pl | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/arch/nds32/Kconfig b/arch/nds32/Kconfig
index ae1a94ca..66d507d 100644
--- a/arch/nds32/Kconfig
+++ b/arch/nds32/Kconfig
@@ -42,6 +42,7 @@ config NDS32
 	select THREAD_INFO_IN_TASK
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
+	select HAVE_FTRACE_MCOUNT_RECORD
 	help
 	  Andes(nds32) Linux support.
 
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index fe06e77..f599031 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -389,6 +389,9 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\sR_RISCV_CALL\\s_mcount\$";
     $type = ".quad";
     $alignment = 2;
+} elsif ($arch eq "nds32") {
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_NDS32_HI20_RELA\\s+_mcount\$";
+    $alignment = 2;
 } else {
     die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
 }
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/6] nds32/ftrace: Support dynamic function tracer
  2018-08-15  9:35 [PATCH 0/6] Support ftrace on NDS32 architecture Zong Li
                   ` (2 preceding siblings ...)
  2018-08-15  9:35 ` [PATCH 3/6] nds32/ftrace: Add RECORD_MCOUNT support Zong Li
@ 2018-08-15  9:35 ` Zong Li
  2018-08-15  9:35 ` [PATCH 5/6] nds32/ftrace: Support dynamic function graph tracer Zong Li
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Zong Li @ 2018-08-15  9:35 UTC (permalink / raw)
  To: green.hu, deanbo422, rostedt, mingo, arnd, linux-kernel
  Cc: zongbox, greentime, Zong Li

This patch contains the implementation of dynamic function tracer.
The mcount call is composed of three instructions, so there are three
nop for enough placeholder.

Signed-off-by: Zong Li <zong@andestech.com>
---
 arch/nds32/Kconfig              |   1 +
 arch/nds32/include/asm/ftrace.h |  26 +++++++
 arch/nds32/kernel/ftrace.c      | 164 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 191 insertions(+)

diff --git a/arch/nds32/Kconfig b/arch/nds32/Kconfig
index 66d507d..9db36c2 100644
--- a/arch/nds32/Kconfig
+++ b/arch/nds32/Kconfig
@@ -43,6 +43,7 @@ config NDS32
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_DYNAMIC_FTRACE
 	help
 	  Andes(nds32) Linux support.
 
diff --git a/arch/nds32/include/asm/ftrace.h b/arch/nds32/include/asm/ftrace.h
index bac7657..2f96cc9 100644
--- a/arch/nds32/include/asm/ftrace.h
+++ b/arch/nds32/include/asm/ftrace.h
@@ -15,6 +15,32 @@
 
 extern void _mcount(unsigned long parent_ip);
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+#define FTRACE_ADDR ((unsigned long)_ftrace_caller)
+
+#ifdef __NDS32_EL__
+#define INSN_NOP		0x09000040
+#define INSN_SIZE(insn)		(((insn & 0x00000080) == 0) ? 4 : 2)
+#define IS_SETHI(insn)		((insn & 0x000000fe) == 0x00000046)
+#define ENDIAN_CONVERT(insn)	be32_to_cpu(insn)
+#else /* __NDS32_EB__ */
+#define INSN_NOP		0x40000009
+#define INSN_SIZE(insn)		(((insn & 0x80000000) == 0) ? 4 : 2)
+#define IS_SETHI(insn)		((insn & 0xfe000000) == 0x46000000)
+#define ENDIAN_CONVERT(insn)	(insn)
+#endif
+
+extern void _ftrace_caller(unsigned long parent_ip);
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	return addr;
+}
+struct dyn_arch_ftrace {
+};
+
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #endif /* CONFIG_FUNCTION_TRACER */
 
 #endif /* __ASM_NDS32_FTRACE_H */
diff --git a/arch/nds32/kernel/ftrace.c b/arch/nds32/kernel/ftrace.c
index 707fce7..3ca676b 100644
--- a/arch/nds32/kernel/ftrace.c
+++ b/arch/nds32/kernel/ftrace.c
@@ -4,6 +4,7 @@
 #include <linux/uaccess.h>
 #include <asm/cacheflush.h>
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 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);
@@ -35,6 +36,168 @@ noinline void _mcount(unsigned long parent_ip)
 }
 EXPORT_SYMBOL(_mcount);
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+
+noinline void __naked ftrace_stub(unsigned long ip, unsigned long parent_ip,
+				  struct ftrace_ops *op, struct pt_regs *regs)
+{
+	__asm__ ("");  /* avoid to optimize as pure function */
+}
+
+noinline void __naked _mcount(unsigned long parent_ip)
+{
+	__asm__ ("");  /* avoid to optimize as pure function */
+}
+EXPORT_SYMBOL(_mcount);
+
+#define XSTR(s) STR(s)
+#define STR(s) #s
+void _ftrace_caller(unsigned long parent_ip)
+{
+	/* save all state needed by the compiler prologue */
+
+	/*
+	 * prepare arguments for real tracing function
+	 * first  arg : __builtin_return_address(0) - MCOUNT_INSN_SIZE
+	 * second arg : parent_ip
+	 */
+	__asm__ __volatile__ (
+		"move $r1, %0				   \n\t"
+		"addi $r0, %1, #-" XSTR(MCOUNT_INSN_SIZE) "\n\t"
+		:
+		: "r" (parent_ip), "r" (__builtin_return_address(0)));
+
+	/* a placeholder for the call to a real tracing function */
+	__asm__ __volatile__ (
+		"ftrace_call:		\n\t"
+		"nop			\n\t"
+		"nop			\n\t"
+		"nop			\n\t");
+
+	/* restore all state needed by the compiler epilogue */
+}
+
+int __init ftrace_dyn_arch_init(void)
+{
+	return 0;
+}
+
+int ftrace_arch_code_modify_prepare(void)
+{
+	set_all_modules_text_rw();
+	return 0;
+}
+
+int ftrace_arch_code_modify_post_process(void)
+{
+	set_all_modules_text_ro();
+	return 0;
+}
+
+static unsigned long gen_sethi_insn(unsigned long addr)
+{
+	unsigned long opcode = 0x46000000;
+	unsigned long imm = addr >> 12;
+	unsigned long rt_num = 0xf << 20;
+
+	return ENDIAN_CONVERT(opcode | rt_num | imm);
+}
+
+static unsigned long gen_ori_insn(unsigned long addr)
+{
+	unsigned long opcode = 0x58000000;
+	unsigned long imm = addr & 0x0000fff;
+	unsigned long rt_num = 0xf << 20;
+	unsigned long ra_num = 0xf << 15;
+
+	return ENDIAN_CONVERT(opcode | rt_num | ra_num | imm);
+}
+
+static unsigned long gen_jral_insn(unsigned long addr)
+{
+	unsigned long opcode = 0x4a000001;
+	unsigned long rt_num = 0x1e << 20;
+	unsigned long rb_num = 0xf << 10;
+
+	return ENDIAN_CONVERT(opcode | rt_num | rb_num);
+}
+
+static void ftrace_gen_call_insn(unsigned long *call_insns,
+				 unsigned long addr)
+{
+	call_insns[0] = gen_sethi_insn(addr); /* sethi $r15, imm20u       */
+	call_insns[1] = gen_ori_insn(addr);   /* ori   $r15, $r15, imm15u */
+	call_insns[2] = gen_jral_insn(addr);  /* jral  $lp,  $r15         */
+}
+
+static int __ftrace_modify_code(unsigned long pc, unsigned long *old_insn,
+				unsigned long *new_insn, bool validate)
+{
+	unsigned long orig_insn[3];
+
+	if (validate) {
+		if (probe_kernel_read(orig_insn, (void *)pc, MCOUNT_INSN_SIZE))
+			return -EFAULT;
+		if (memcmp(orig_insn, old_insn, MCOUNT_INSN_SIZE))
+			return -EINVAL;
+	}
+
+	if (probe_kernel_write((void *)pc, new_insn, MCOUNT_INSN_SIZE))
+		return -EPERM;
+
+	return 0;
+}
+
+static int ftrace_modify_code(unsigned long pc, unsigned long *old_insn,
+			      unsigned long *new_insn, bool validate)
+{
+	int ret;
+
+	ret = __ftrace_modify_code(pc, old_insn, new_insn, validate);
+	if (ret)
+		return ret;
+
+	flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
+
+	return ret;
+}
+
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc = (unsigned long)&ftrace_call;
+	unsigned long old_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
+	unsigned long new_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
+
+	if (func != ftrace_stub)
+		ftrace_gen_call_insn(new_insn, (unsigned long)func);
+
+	return ftrace_modify_code(pc, old_insn, new_insn, false);
+}
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned long nop_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
+	unsigned long call_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
+
+	ftrace_gen_call_insn(call_insn, addr);
+
+	return ftrace_modify_code(pc, nop_insn, call_insn, true);
+}
+
+int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
+		    unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned long nop_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
+	unsigned long call_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
+
+	ftrace_gen_call_insn(call_insn, addr);
+
+	return ftrace_modify_code(pc, call_insn, nop_insn, true);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 			   unsigned long frame_pointer)
@@ -94,4 +257,5 @@ void __naked return_to_handler(void)
 		/* restore state nedded by the ABI  */
 		"lmw.bim $r0,[$sp],$r1,#0x0  \n\t");
 }
+
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/6] nds32/ftrace: Support dynamic function graph tracer
  2018-08-15  9:35 [PATCH 0/6] Support ftrace on NDS32 architecture Zong Li
                   ` (3 preceding siblings ...)
  2018-08-15  9:35 ` [PATCH 4/6] nds32/ftrace: Support dynamic function tracer Zong Li
@ 2018-08-15  9:35 ` Zong Li
  2018-08-15  9:35 ` [PATCH 6/6] nds32/stack: Get real return address by using ftrace_graph_ret_addr Zong Li
  2018-08-21  7:03 ` [PATCH 0/6] Support ftrace on NDS32 architecture Greentime Hu
  6 siblings, 0 replies; 9+ messages in thread
From: Zong Li @ 2018-08-15  9:35 UTC (permalink / raw)
  To: green.hu, deanbo422, rostedt, mingo, arnd, linux-kernel
  Cc: zongbox, greentime, Zong Li

This patch contains the implementation of dynamic function graph tracer.

Signed-off-by: Zong Li <zong@andestech.com>
---
 arch/nds32/kernel/ftrace.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/nds32/kernel/ftrace.c b/arch/nds32/kernel/ftrace.c
index 3ca676b..a646a83 100644
--- a/arch/nds32/kernel/ftrace.c
+++ b/arch/nds32/kernel/ftrace.c
@@ -74,6 +74,14 @@ void _ftrace_caller(unsigned long parent_ip)
 		"nop			\n\t"
 		"nop			\n\t");
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	/* a placeholder for the call to ftrace_graph_caller */
+	__asm__ __volatile__ (
+		"ftrace_graph_call:	\n\t"
+		"nop			\n\t"
+		"nop			\n\t"
+		"nop			\n\t");
+#endif
 	/* restore all state needed by the compiler epilogue */
 }
 
@@ -258,4 +266,32 @@ void __naked return_to_handler(void)
 		"lmw.bim $r0,[$sp],$r1,#0x0  \n\t");
 }
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+extern unsigned long ftrace_graph_call;
+
+static int ftrace_modify_graph_caller(bool enable)
+{
+	unsigned long pc = (unsigned long)&ftrace_graph_call;
+	unsigned long nop_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
+	unsigned long call_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
+
+	ftrace_gen_call_insn(call_insn, (unsigned long)ftrace_graph_caller);
+
+	if (enable)
+		return ftrace_modify_code(pc, nop_insn, call_insn, true);
+	else
+		return ftrace_modify_code(pc, call_insn, nop_insn, true);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/6] nds32/stack: Get real return address by using ftrace_graph_ret_addr
  2018-08-15  9:35 [PATCH 0/6] Support ftrace on NDS32 architecture Zong Li
                   ` (4 preceding siblings ...)
  2018-08-15  9:35 ` [PATCH 5/6] nds32/ftrace: Support dynamic function graph tracer Zong Li
@ 2018-08-15  9:35 ` Zong Li
  2018-08-21  7:03 ` [PATCH 0/6] Support ftrace on NDS32 architecture Greentime Hu
  6 siblings, 0 replies; 9+ messages in thread
From: Zong Li @ 2018-08-15  9:35 UTC (permalink / raw)
  To: green.hu, deanbo422, rostedt, mingo, arnd, linux-kernel
  Cc: zongbox, greentime, Zong Li

Function graph tracer has modified the return address to
'return_to_handler' on stack, and provide the 'ftrace_graph_ret_addr' to
get the real return address.

Signed-off-by: Zong Li <zong@andestech.com>
---
 arch/nds32/kernel/stacktrace.c |  4 ++++
 arch/nds32/kernel/traps.c      | 30 ++++++------------------------
 2 files changed, 10 insertions(+), 24 deletions(-)

diff --git a/arch/nds32/kernel/stacktrace.c b/arch/nds32/kernel/stacktrace.c
index 8b231e9..36bc870 100644
--- a/arch/nds32/kernel/stacktrace.c
+++ b/arch/nds32/kernel/stacktrace.c
@@ -4,6 +4,7 @@
 #include <linux/sched/debug.h>
 #include <linux/sched/task_stack.h>
 #include <linux/stacktrace.h>
+#include <linux/ftrace.h>
 
 void save_stack_trace(struct stack_trace *trace)
 {
@@ -16,6 +17,7 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 	unsigned long *fpn;
 	int skip = trace->skip;
 	int savesched;
+	int graph_idx = 0;
 
 	if (tsk == current) {
 		__asm__ __volatile__("\tori\t%0, $fp, #0\n":"=r"(fpn));
@@ -33,6 +35,8 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 		fpp = fpn[FP_OFFSET];
 		if (!__kernel_text_address(lpp))
 			break;
+		else
+			lpp = ftrace_graph_ret_addr(tsk, &graph_idx, lpp, NULL);
 
 		if (savesched || !in_sched_functions(lpp)) {
 			if (skip) {
diff --git a/arch/nds32/kernel/traps.c b/arch/nds32/kernel/traps.c
index f0e9743..7684c8f 100644
--- a/arch/nds32/kernel/traps.c
+++ b/arch/nds32/kernel/traps.c
@@ -8,6 +8,7 @@
 #include <linux/kdebug.h>
 #include <linux/sched/task_stack.h>
 #include <linux/uaccess.h>
+#include <linux/ftrace.h>
 
 #include <asm/proc-fns.h>
 #include <asm/unistd.h>
@@ -94,28 +95,6 @@ static void dump_instr(struct pt_regs *regs)
 	set_fs(fs);
 }
 
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-#include <linux/ftrace.h>
-static void
-get_real_ret_addr(unsigned long *addr, struct task_struct *tsk, int *graph)
-{
-	if (*addr == (unsigned long)return_to_handler) {
-		int index = tsk->curr_ret_stack;
-
-		if (tsk->ret_stack && index >= *graph) {
-			index -= *graph;
-			*addr = tsk->ret_stack[index].ret;
-			(*graph)++;
-		}
-	}
-}
-#else
-static inline void
-get_real_ret_addr(unsigned long *addr, struct task_struct *tsk, int *graph)
-{
-}
-#endif
-
 #define LOOP_TIMES (100)
 static void __dump(struct task_struct *tsk, unsigned long *base_reg)
 {
@@ -126,7 +105,8 @@ static void __dump(struct task_struct *tsk, unsigned long *base_reg)
 		while (!kstack_end(base_reg)) {
 			ret_addr = *base_reg++;
 			if (__kernel_text_address(ret_addr)) {
-				get_real_ret_addr(&ret_addr, tsk, &graph);
+				ret_addr = ftrace_graph_ret_addr(
+						tsk, &graph, ret_addr, NULL);
 				print_ip_sym(ret_addr);
 			}
 			if (--cnt < 0)
@@ -145,7 +125,9 @@ static void __dump(struct task_struct *tsk, unsigned long *base_reg)
 			next_fp = base_reg[FP_OFFSET];
 #endif
 			if (__kernel_text_address(ret_addr)) {
-				get_real_ret_addr(&ret_addr, tsk, &graph);
+
+				ret_addr = ftrace_graph_ret_addr(
+						tsk, &graph, ret_addr, NULL);
 				print_ip_sym(ret_addr);
 			}
 			if (--cnt < 0)
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/6] nds32/ftrace: Support static function tracer
  2018-08-15  9:35 ` [PATCH 1/6] nds32/ftrace: Support static function tracer Zong Li
@ 2018-08-15 20:11   ` Steven Rostedt
  0 siblings, 0 replies; 9+ messages in thread
From: Steven Rostedt @ 2018-08-15 20:11 UTC (permalink / raw)
  To: Zong Li
  Cc: green.hu, deanbo422, mingo, arnd, linux-kernel, zongbox, greentime

On Wed, 15 Aug 2018 17:35:18 +0800
Zong Li <zong@andestech.com> wrote:

> This patch support the static function tracer. On nds32 ABI, we need to
> always push return address to stack for __builtin_return_address can
> work correctly, otherwise, it will get the wrong value of $lp at leaf
> function.
> 
> Signed-off-by: Zong Li <zong@andestech.com>
> ---
>  arch/nds32/Kconfig              |  1 +
>  arch/nds32/Makefile             |  4 ++++
>  arch/nds32/include/asm/ftrace.h | 20 ++++++++++++++++++++
>  arch/nds32/kernel/Makefile      |  6 ++++++
>  arch/nds32/kernel/ftrace.c      | 28 ++++++++++++++++++++++++++++
>  5 files changed, 59 insertions(+)
>  create mode 100644 arch/nds32/include/asm/ftrace.h
>  create mode 100644 arch/nds32/kernel/ftrace.c
> 
> diff --git a/arch/nds32/Kconfig b/arch/nds32/Kconfig
> index 34f7222..af30e1a 100644
> --- a/arch/nds32/Kconfig
> +++ b/arch/nds32/Kconfig
> @@ -40,6 +40,7 @@ config NDS32
>  	select NO_IOPORT_MAP
>  	select RTC_LIB
>  	select THREAD_INFO_IN_TASK
> +	select HAVE_FUNCTION_TRACER
>  	help
>  	  Andes(nds32) Linux support.
>  
> diff --git a/arch/nds32/Makefile b/arch/nds32/Makefile
> index 031c676..3ca8172 100644
> --- a/arch/nds32/Makefile
> +++ b/arch/nds32/Makefile
> @@ -5,6 +5,10 @@ KBUILD_DEFCONFIG := defconfig
>  
>  comma = ,
>  
> +ifdef CONFIG_FUNCTION_TRACER
> +arch-y += -malways-save-lp -mno-relax
> +endif
> +
>  KBUILD_CFLAGS	+= $(call cc-option, -mno-sched-prolog-epilog)
>  KBUILD_CFLAGS	+= -mcmodel=large
>  
> diff --git a/arch/nds32/include/asm/ftrace.h b/arch/nds32/include/asm/ftrace.h
> new file mode 100644
> index 0000000..bac7657
> --- /dev/null
> +++ b/arch/nds32/include/asm/ftrace.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#ifndef __ASM_NDS32_FTRACE_H
> +#define __ASM_NDS32_FTRACE_H
> +
> +#ifdef CONFIG_FUNCTION_TRACER
> +
> +#define HAVE_FUNCTION_GRAPH_FP_TEST
> +
> +#define MCOUNT_ADDR ((unsigned long)(_mcount))
> +/* mcount call is composed of three instructions:
> + * sethi + ori + jral
> + */
> +#define MCOUNT_INSN_SIZE 12
> +
> +extern void _mcount(unsigned long parent_ip);
> +
> +#endif /* CONFIG_FUNCTION_TRACER */
> +
> +#endif /* __ASM_NDS32_FTRACE_H */
> diff --git a/arch/nds32/kernel/Makefile b/arch/nds32/kernel/Makefile
> index 4279274..27cded3 100644
> --- a/arch/nds32/kernel/Makefile
> +++ b/arch/nds32/kernel/Makefile
> @@ -21,3 +21,9 @@ extra-y := head.o vmlinux.lds
>  
>  
>  obj-y				+= vdso/
> +
> +obj-$(CONFIG_FUNCTION_TRACER)   += ftrace.o
> +
> +ifdef CONFIG_FUNCTION_TRACER
> +CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
> +endif
> diff --git a/arch/nds32/kernel/ftrace.c b/arch/nds32/kernel/ftrace.c
> new file mode 100644
> index 0000000..563f64c
> --- /dev/null
> +++ b/arch/nds32/kernel/ftrace.c
> @@ -0,0 +1,28 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/ftrace.h>
> +#include <linux/uaccess.h>
> +#include <asm/cacheflush.h>
> +
> +extern void (*ftrace_trace_function)(unsigned long, unsigned long,
> +				     struct ftrace_ops*, struct pt_regs*);
> +
> +noinline void __naked ftrace_stub(unsigned long ip, unsigned long parent_ip,
> +				  struct ftrace_ops *op, struct pt_regs *regs)
> +{
> +	__asm__ ("");  /* avoid to optimize as pure function */
> +}
> +
> +noinline void _mcount(unsigned long parent_ip)
> +{

Wow! The NDS32 arch allows for _mcount to be a C function! That's
nice :-)

-- Steve

> +	/* save all state by the compiler prologue */
> +
> +	unsigned long ip = (unsigned long)__builtin_return_address(0);
> +
> +	if (ftrace_trace_function != ftrace_stub)
> +		ftrace_trace_function(ip - MCOUNT_INSN_SIZE, parent_ip,
> +				      NULL, NULL);
> +
> +	/* restore all state by the compiler epilogue */
> +}
> +EXPORT_SYMBOL(_mcount);


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/6] Support ftrace on NDS32 architecture
  2018-08-15  9:35 [PATCH 0/6] Support ftrace on NDS32 architecture Zong Li
                   ` (5 preceding siblings ...)
  2018-08-15  9:35 ` [PATCH 6/6] nds32/stack: Get real return address by using ftrace_graph_ret_addr Zong Li
@ 2018-08-21  7:03 ` Greentime Hu
  6 siblings, 0 replies; 9+ messages in thread
From: Greentime Hu @ 2018-08-21  7:03 UTC (permalink / raw)
  To: Zong Li
  Cc: Vincent Chen, Steven Rostedt, mingo, Arnd Bergmann,
	Linux Kernel Mailing List, Zong Li, Greentime

Zong Li <zong@andestech.com> 於 2018年8月15日 週三 下午5:35寫道:
>
> This patch set implements the ftrace function and function graph tracer
> on NDS32 architecture. We try to use C code to do everything, so we don't
> need to separate the implementation to assembly code and C code, we just
> need one ftrace.c file.
>
> In mcount function, we use the prologue/epilogue which generated by compiler
> to help us to save/restore the status. On the other hand, we use naked
> attribute of gcc to avoid to generate the prologue/epilogue when we don't
> need it(such as ftrace_stub and return_to_handler).
>
> We pass the following tests:
>
> 1. FTRACE_STARTUP_TEST: PASS
>
> 2. tools/testing/selftests/ftrace/:
>  # of passed:  28
>  # of failed:  1
>  # of unresolved:  0
>  # of untested:  0
>  # of unsupported:  38
>  # of xfailed:  0
>  # of undefined(test bug):  0
>
> The failed case is func-filter-glob.tc.
> When setting the '*aw*lock' to the set_ftrace_filter in this test case,
> we got the error because we have no these functions such as _raw_spin_lock,
> _raw_spin_trylock and so on in our kernel.
>
> Zong Li (6):
>   nds32/ftrace: Support static function tracer
>   nds32/ftrace: Support static function graph tracer
>   nds32/ftrace: Add RECORD_MCOUNT support
>   nds32/ftrace: Support dynamic function tracer
>   nds32/ftrace: Support dynamic function graph tracer
>   nds32/stack: Get real return address by using ftrace_graph_ret_addr
>
>  arch/nds32/Kconfig              |   4 +
>  arch/nds32/Makefile             |   4 +
>  arch/nds32/include/asm/ftrace.h |  46 +++++++
>  arch/nds32/kernel/Makefile      |   6 +
>  arch/nds32/kernel/ftrace.c      | 297 ++++++++++++++++++++++++++++++++++++++++
>  arch/nds32/kernel/stacktrace.c  |   4 +
>  arch/nds32/kernel/traps.c       |  30 +---
>  scripts/recordmcount.pl         |   3 +
>  8 files changed, 370 insertions(+), 24 deletions(-)
>  create mode 100644 arch/nds32/include/asm/ftrace.h
>  create mode 100644 arch/nds32/kernel/ftrace.c

Acked-by: Greentime Hu <greentime@andestech.com>

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-08-21  7:04 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-15  9:35 [PATCH 0/6] Support ftrace on NDS32 architecture Zong Li
2018-08-15  9:35 ` [PATCH 1/6] nds32/ftrace: Support static function tracer Zong Li
2018-08-15 20:11   ` Steven Rostedt
2018-08-15  9:35 ` [PATCH 2/6] nds32/ftrace: Support static function graph tracer Zong Li
2018-08-15  9:35 ` [PATCH 3/6] nds32/ftrace: Add RECORD_MCOUNT support Zong Li
2018-08-15  9:35 ` [PATCH 4/6] nds32/ftrace: Support dynamic function tracer Zong Li
2018-08-15  9:35 ` [PATCH 5/6] nds32/ftrace: Support dynamic function graph tracer Zong Li
2018-08-15  9:35 ` [PATCH 6/6] nds32/stack: Get real return address by using ftrace_graph_ret_addr Zong Li
2018-08-21  7:03 ` [PATCH 0/6] Support ftrace on NDS32 architecture Greentime Hu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).