All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.