All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/6] Add dynamic ftrace support for RISC-V platforms
@ 2018-01-15  6:47 Alan Kao
  2018-01-15  6:47 ` [PATCH v2 1/6] riscv/ftrace: Add RECORD_MCOUNT support Alan Kao
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Alan Kao @ 2018-01-15  6:47 UTC (permalink / raw)
  To: Palmer Dabbelt, Albert Ou, Christoph Hellwig, Steven Rostedt,
	Ingo Molnar, Masahiro Yamada, Kamil Rytarowski, Andrew Morton,
	patches, linux-kernel
  Cc: Alan Kao, Greentime Hu

This patch set includes the building blocks of dynamic ftrace features
for RISC-V machines.

Changes in v2:
 - Fix the return value as writing to kernel text goes wrong (2/6)
 - Replace manual comparisons by calling memcmp (2/6)
 - Simplify the conditional assignment in the Makefile (1/6)

Alan Kao (6):
  riscv/ftrace: Add RECORD_MCOUNT support
  riscv/ftrace: Add dynamic function tracer support
  riscv/ftrace: Add dynamic function graph tracer support
  riscv/ftrace: Add ARCH_SUPPORTS_FTRACE_OPS support
  riscv/ftrace: Add DYNAMIC_FTRACE_WITH_REGS support
  riscv/ftrace: Add HAVE_FUNCTION_GRAPH_RET_ADDR_PTR support

 arch/riscv/Kconfig              |   3 +
 arch/riscv/Makefile             |   3 +
 arch/riscv/include/asm/ftrace.h |  47 ++++++++
 arch/riscv/kernel/Makefile      |   5 +-
 arch/riscv/kernel/ftrace.c      | 142 ++++++++++++++++++++++-
 arch/riscv/kernel/mcount-dyn.S  | 244 ++++++++++++++++++++++++++++++++++++++++
 arch/riscv/kernel/mcount.S      |  22 ++--
 arch/riscv/kernel/stacktrace.c  |   6 +
 scripts/recordmcount.pl         |   5 +
 9 files changed, 464 insertions(+), 13 deletions(-)
 create mode 100644 arch/riscv/kernel/mcount-dyn.S

-- 
2.15.1

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

* [PATCH v2 1/6] riscv/ftrace: Add RECORD_MCOUNT support
  2018-01-15  6:47 [PATCH v2 0/6] Add dynamic ftrace support for RISC-V platforms Alan Kao
@ 2018-01-15  6:47 ` Alan Kao
  2018-01-15  6:47 ` [PATCH v2 2/6] riscv/ftrace: Add dynamic function tracer support Alan Kao
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Alan Kao @ 2018-01-15  6:47 UTC (permalink / raw)
  To: Palmer Dabbelt, Albert Ou, Christoph Hellwig, Steven Rostedt,
	Ingo Molnar, Masahiro Yamada, Kamil Rytarowski, Andrew Morton,
	patches, linux-kernel
  Cc: Alan Kao, Greentime Hu

Now recordmcount.pl recognizes RISC-V object files. For the mechanism to
work, we have to disable the linker relaxation.

Cc: Greentime Hu <greentime@andestech.com>
Signed-off-by: Alan Kao <alankao@andestech.com>
---
 arch/riscv/Kconfig      | 1 +
 arch/riscv/Makefile     | 3 +++
 scripts/recordmcount.pl | 5 +++++
 3 files changed, 9 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 40a67fc12328..1f45a76f412e 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -117,6 +117,7 @@ config ARCH_RV64I
 	select 64BIT
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
+	select HAVE_FTRACE_MCOUNT_RECORD
 
 endchoice
 
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 6719dd30ec5b..899226e0da7d 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -11,6 +11,9 @@
 LDFLAGS         :=
 OBJCOPYFLAGS    := -O binary
 LDFLAGS_vmlinux :=
+ifeq ($(CONFIG_DYNAMIC_FTRACE),y)
+	LDFLAGS_vmlinux := --no-relax
+endif
 KBUILD_AFLAGS_MODULE += -fPIC
 KBUILD_CFLAGS_MODULE += -fPIC
 
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 2033af758173..d44d55db7c06 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -376,6 +376,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$";
     $type = ".quad";
     $alignment = 8;
+} elsif ($arch eq "riscv") {
+    $function_regex = "^([0-9a-fA-F]+)\\s+<([^.0-9][0-9a-zA-Z_\\.]+)>:";
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\sR_RISCV_CALL\\s_mcount\$";
+    $type = ".quad";
+    $alignment = 2;
 } else {
     die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
 }
-- 
2.15.1

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

* [PATCH v2 2/6] riscv/ftrace: Add dynamic function tracer support
  2018-01-15  6:47 [PATCH v2 0/6] Add dynamic ftrace support for RISC-V platforms Alan Kao
  2018-01-15  6:47 ` [PATCH v2 1/6] riscv/ftrace: Add RECORD_MCOUNT support Alan Kao
@ 2018-01-15  6:47 ` Alan Kao
  2018-01-15  7:24   ` [patches] " Stefan O'Rear
  2018-01-15  6:47 ` [PATCH v2 3/6] riscv/ftrace: Add dynamic function graph " Alan Kao
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Alan Kao @ 2018-01-15  6:47 UTC (permalink / raw)
  To: Palmer Dabbelt, Albert Ou, Christoph Hellwig, Steven Rostedt,
	Ingo Molnar, Masahiro Yamada, Kamil Rytarowski, Andrew Morton,
	patches, linux-kernel
  Cc: Alan Kao, Greentime Hu

We now have dynamic ftrace with the following added items:

* ftrace_make_call, ftrace_make_nop (in kernel/ftrace.c)
  The two functions turns any recorded call site of filtered functions
  into a call to ftrace_caller or nops

* ftracce_update_ftrace_func (in kernel/ftrace.c)
  turns the nops at ftrace_call into a call to a generic entry for
  function tracers.

* ftrace_caller (in kernel/mcount-dyn.S)
  The entry where each _mcount call sites calls to once they are
  filtered to be traced.

Also, this patch fixes the semantic problems in mcount.S, which will be
treated as only a reference implementation once we have the dynamic
ftrace.

Cc: Greentime Hu <greentime@andestech.com>
Signed-off-by: Alan Kao <alankao@andestech.com>
---
 arch/riscv/Kconfig              |   1 +
 arch/riscv/include/asm/ftrace.h |  45 ++++++++++++++++++
 arch/riscv/kernel/Makefile      |   5 +-
 arch/riscv/kernel/ftrace.c      | 100 +++++++++++++++++++++++++++++++++++++++-
 arch/riscv/kernel/mcount-dyn.S  |  52 +++++++++++++++++++++
 arch/riscv/kernel/mcount.S      |  22 +++++----
 6 files changed, 213 insertions(+), 12 deletions(-)
 create mode 100644 arch/riscv/kernel/mcount-dyn.S

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 1f45a76f412e..a5c5c88700d4 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -118,6 +118,7 @@ config ARCH_RV64I
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_DYNAMIC_FTRACE
 
 endchoice
 
diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h
index 66d4175eb13e..acf0c7d001f3 100644
--- a/arch/riscv/include/asm/ftrace.h
+++ b/arch/riscv/include/asm/ftrace.h
@@ -8,3 +8,48 @@
 #if defined(CONFIG_FUNCTION_GRAPH_TRACER) && defined(CONFIG_FRAME_POINTER)
 #define HAVE_FUNCTION_GRAPH_FP_TEST
 #endif
+
+#ifndef __ASSEMBLY__
+void _mcount(void);
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	return addr;
+}
+
+struct dyn_arch_ftrace {
+};
+#endif
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * A general call in RISC-V is a pair of insts:
+ * 1) auipc: setting high-20 pc-related bits to ra register
+ * 2) jalr: setting low-12 offset to ra, jump to ra, and set ra to
+ *          return address (original pc + 4)
+ *
+ * Dynamic ftrace generates probes to call sites, so we must deal with
+ * both auipc and jalr at the same time.
+ */
+
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define JALR_SIGN_MASK		(0x00000800)
+#define JALR_OFFSET_MASK	(0x00000fff)
+#define AUIPC_OFFSET_MASK	(0xfffff000)
+#define AUIPC_PAD		(0x00001000)
+#define JALR_SHIFT		20
+#define JALR_BASIC		(0x000080e7)
+#define AUIPC_BASIC		(0x00000097)
+#define NOP4			(0x00000013)
+
+#define to_jalr_insn(_offset) \
+	(((_offset & JALR_OFFSET_MASK) << JALR_SHIFT) | JALR_BASIC)
+
+#define to_auipc_insn(_offset) ((_offset & JALR_SIGN_MASK) ? \
+	(((_offset & AUIPC_OFFSET_MASK) + AUIPC_PAD) | AUIPC_BASIC) : \
+	((_offset & AUIPC_OFFSET_MASK) | AUIPC_BASIC))
+
+/*
+ * Let auipc+jalr be the basic *mcount unit*, so we make it 8 bytes here.
+ */
+#define MCOUNT_INSN_SIZE 8
+#endif
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index 196f62ffc428..d7bdf888f1ca 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -34,7 +34,8 @@ CFLAGS_setup.o := -mcmodel=medany
 obj-$(CONFIG_SMP)		+= smpboot.o
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_MODULES)		+= module.o
-obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o
-obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o
+
+obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o ftrace.o
+obj-$(CONFIG_DYNAMIC_FTRACE)	+= mcount-dyn.o
 
 clean:
diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
index d0de68d144cb..311c287433c9 100644
--- a/arch/riscv/kernel/ftrace.c
+++ b/arch/riscv/kernel/ftrace.c
@@ -6,9 +6,107 @@
  */
 
 #include <linux/ftrace.h>
+#include <linux/uaccess.h>
+#include <asm/cacheflush.h>
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+static int ftrace_check_current_call(unsigned long hook_pos,
+				     unsigned int *expected)
+{
+	unsigned int replaced[2];
+	unsigned int nops[2] = {NOP4, NOP4};
+
+	/* we expect nops at the hook position */
+	if (!expected)
+		expected = nops;
+
+	/*
+	 * Read the text we want to modify;
+	 * return must be -EFAULT on read error
+	 */
+	if (probe_kernel_read(replaced, (void *)hook_pos, MCOUNT_INSN_SIZE))
+		return -EFAULT;
+
+	/*
+	 * Make sure it is what we expect it to be;
+	 * return must be -EINVAL on failed comparison
+	 */
+	if (memcmp(expected, replaced, sizeof(replaced))) {
+		pr_err("%p: expected (%08x %08x) but get (%08x %08x)",
+		       (void *)hook_pos, expected[0], expected[1], replaced[0],
+		       replaced[1]);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int __ftrace_modify_call(unsigned long hook_pos, unsigned long target,
+				bool enable)
+{
+	unsigned int offset = (unsigned int)(target - hook_pos);
+	unsigned int auipc_call = to_auipc_insn(offset);
+	unsigned int jalr_call = to_jalr_insn(offset);
+	unsigned int calls[2] = {auipc_call, jalr_call};
+	unsigned int nops[2] = {NOP4, NOP4};
+	int ret = 0;
+
+	/* when ftrace_make_nop is called */
+	if (!enable)
+		ret = ftrace_check_current_call(hook_pos, calls);
+
+	if (ret)
+		return ret;
+
+	/* replace the auipc-jalr pair at once */
+	ret = probe_kernel_write((void *)hook_pos, enable ? calls : nops,
+				 MCOUNT_INSN_SIZE);
+	/* return must be -EPERM on write error */
+	if (ret)
+		return -EPERM;
+
+	smp_mb();
+	flush_icache_range((void *)hook_pos, (void *)hook_pos + MCOUNT_INSN_SIZE);
+
+	return 0;
+}
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	int ret = ftrace_check_current_call(rec->ip, NULL);
+
+	if (ret)
+		return ret;
+
+	return __ftrace_modify_call(rec->ip, addr, true);
+}
+
+int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
+		    unsigned long addr)
+{
+	return __ftrace_modify_call(rec->ip, addr, false);
+}
+
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	int ret = __ftrace_modify_call((unsigned long)&ftrace_call,
+				       (unsigned long)func, true);
+	if (!ret) {
+		ret = __ftrace_modify_call((unsigned long)&ftrace_regs_call,
+					   (unsigned long)func, true);
+	}
+
+	return ret;
+}
+
+int __init ftrace_dyn_arch_init(void)
+{
+	return 0;
+}
+#endif
 
 /*
- * Most of this file is copied from arm64.
+ * Most of this function is copied from arm64.
  */
 void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 			   unsigned long frame_pointer)
diff --git a/arch/riscv/kernel/mcount-dyn.S b/arch/riscv/kernel/mcount-dyn.S
new file mode 100644
index 000000000000..57f80fe09cbd
--- /dev/null
+++ b/arch/riscv/kernel/mcount-dyn.S
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2017 Andes Technology Corporation */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <asm/asm.h>
+#include <asm/csr.h>
+#include <asm/unistd.h>
+#include <asm/thread_info.h>
+#include <asm/asm-offsets.h>
+#include <asm-generic/export.h>
+#include <asm/ftrace.h>
+
+	.text
+
+	.macro SAVE_ABI_STATE
+	addi	sp, sp, -16
+	sd	s0, 0(sp)
+	sd	ra, 8(sp)
+	addi	s0, sp, 16
+	.endm
+
+	.macro RESTORE_ABI_STATE
+	ld	ra, 8(sp)
+	ld	s0, 0(sp)
+	addi	sp, sp, 16
+	.endm
+
+ENTRY(ftrace_caller)
+	/*
+	 * a0: the address in the caller when calling ftrace_caller
+	 * a1: the caller's return address
+	 */
+	ld	a1, -8(s0)
+	addi	a0, ra, -MCOUNT_INSN_SIZE
+	SAVE_ABI_STATE
+ftrace_call:
+	.global ftrace_call
+	/*
+	 * For the dynamic ftrace to work, here we should reserve at least
+	 * 8 bytes for a functional auipc-jalr pair. Pseudo inst nop may be
+	 * interpreted as different length in different models, so we manually
+	 * *expand* two 4-byte nops here.
+	 *
+	 * Calling ftrace_update_ftrace_func would overwrite the nops below.
+	 * Check ftrace_modify_all_code for details.
+	 */
+	addi	x0, x0, 0
+	addi	x0, x0, 0
+	RESTORE_ABI_STATE
+	ret
+ENDPROC(ftrace_caller)
diff --git a/arch/riscv/kernel/mcount.S b/arch/riscv/kernel/mcount.S
index c46a778627be..ce9bdc57a2a1 100644
--- a/arch/riscv/kernel/mcount.S
+++ b/arch/riscv/kernel/mcount.S
@@ -32,13 +32,13 @@
 	addi	s0, sp, 32
 	.endm
 
-	.macro STORE_ABI_STATE
+	.macro RESTORE_ABI_STATE
 	ld	ra, 8(sp)
 	ld	s0, 0(sp)
 	addi	sp, sp, 16
 	.endm
 
-	.macro STORE_RET_ABI_STATE
+	.macro RESTORE_RET_ABI_STATE
 	ld	ra, 24(sp)
 	ld	s0, 16(sp)
 	ld	a0, 8(sp)
@@ -46,6 +46,10 @@
 	.endm
 
 ENTRY(ftrace_stub)
+#ifdef CONFIG_DYNAMIC_FTRACE
+       .global _mcount
+       .set    _mcount, ftrace_stub
+#endif
 	ret
 ENDPROC(ftrace_stub)
 
@@ -66,15 +70,15 @@ ENTRY(return_to_handler)
 #ifdef HAVE_FUNCTION_GRAPH_FP_TEST
 	mv	a0, t6
 #endif
-	la	t0, ftrace_return_to_handler
-	jalr	t0
+	call	ftrace_return_to_handler
 	mv	a1, a0
-	STORE_RET_ABI_STATE
+	RESTORE_RET_ABI_STATE
 	jalr	a1
 ENDPROC(return_to_handler)
 EXPORT_SYMBOL(return_to_handler)
 #endif
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 ENTRY(_mcount)
 	la	t4, ftrace_stub
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -104,9 +108,8 @@ do_ftrace_graph_caller:
 	ld	a2, -16(s0)
 #endif
 	SAVE_ABI_STATE
-	la	t0, prepare_ftrace_return
-	jalr	t0
-	STORE_ABI_STATE
+	call	prepare_ftrace_return
+	RESTORE_ABI_STATE
 	ret
 #endif
 
@@ -120,7 +123,8 @@ do_trace:
 
 	SAVE_ABI_STATE
 	jalr	t5
-	STORE_ABI_STATE
+	RESTORE_ABI_STATE
 	ret
 ENDPROC(_mcount)
 EXPORT_SYMBOL(_mcount)
+#endif
-- 
2.15.1

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

* [PATCH v2 3/6] riscv/ftrace: Add dynamic function graph tracer support
  2018-01-15  6:47 [PATCH v2 0/6] Add dynamic ftrace support for RISC-V platforms Alan Kao
  2018-01-15  6:47 ` [PATCH v2 1/6] riscv/ftrace: Add RECORD_MCOUNT support Alan Kao
  2018-01-15  6:47 ` [PATCH v2 2/6] riscv/ftrace: Add dynamic function tracer support Alan Kao
@ 2018-01-15  6:47 ` Alan Kao
  2018-01-15  6:47 ` [PATCH v2 4/6] riscv/ftrace: Add ARCH_SUPPORTS_FTRACE_OPS support Alan Kao
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Alan Kao @ 2018-01-15  6:47 UTC (permalink / raw)
  To: Palmer Dabbelt, Albert Ou, Christoph Hellwig, Steven Rostedt,
	Ingo Molnar, Masahiro Yamada, Kamil Rytarowski, Andrew Morton,
	patches, linux-kernel
  Cc: Alan Kao, Greentime Hu

Once the function_graph tracer is enabled, a filtered function has the
following call sequence:

* ftracer_caller         ==> on/off by ftrace_make_call/ftrace_make_nop
* ftrace_graph_caller
* ftrace_graph_call      ==> on/off by ftrace_en/disable_ftrace_graph_caller
* prepare_ftrace_return

Considering the following DYNAMIC_FTRACE_WITH_REGS feature, it would be
more extendable to have a ftrace_graph_caller function, instead of
calling prepare_ftrace_return directly in ftrace_caller.

Cc: Greentime Hu <greentime@andestech.com>
Signed-off-by: Alan Kao <alankao@andestech.com>
---
 arch/riscv/kernel/ftrace.c     | 25 +++++++++++++++-
 arch/riscv/kernel/mcount-dyn.S | 65 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
index 311c287433c9..dce1286af9b0 100644
--- a/arch/riscv/kernel/ftrace.c
+++ b/arch/riscv/kernel/ftrace.c
@@ -51,7 +51,7 @@ static int __ftrace_modify_call(unsigned long hook_pos, unsigned long target,
 	unsigned int nops[2] = {NOP4, NOP4};
 	int ret = 0;
 
-	/* when ftrace_make_nop is called */
+	/* for ftrace_make_nop and ftrace_disable_ftrace_graph_caller */
 	if (!enable)
 		ret = ftrace_check_current_call(hook_pos, calls);
 
@@ -105,6 +105,7 @@ int __init ftrace_dyn_arch_init(void)
 }
 #endif
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * Most of this function is copied from arm64.
  */
@@ -137,3 +138,25 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	*parent = return_hooker;
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+extern void ftrace_graph_call(void);
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	int ret = ftrace_check_current_call((unsigned long)&ftrace_graph_call,
+					    NULL);
+
+	if (ret)
+		return ret;
+
+	return __ftrace_modify_call((unsigned long)&ftrace_graph_call,
+				    (unsigned long)&prepare_ftrace_return, true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return __ftrace_modify_call((unsigned long)&ftrace_graph_call,
+				    (unsigned long)&prepare_ftrace_return, false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/riscv/kernel/mcount-dyn.S b/arch/riscv/kernel/mcount-dyn.S
index 57f80fe09cbd..64e715d4e180 100644
--- a/arch/riscv/kernel/mcount-dyn.S
+++ b/arch/riscv/kernel/mcount-dyn.S
@@ -14,18 +14,63 @@
 	.text
 
 	.macro SAVE_ABI_STATE
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	addi    sp, sp, -48
+	sd      s0, 32(sp)
+	sd      ra, 40(sp)
+	addi    s0, sp, 48
+	sd      t0, 24(sp)
+	sd      t1, 16(sp)
+#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
+	sd      t2, 8(sp)
+#endif
+#else
 	addi	sp, sp, -16
 	sd	s0, 0(sp)
 	sd	ra, 8(sp)
 	addi	s0, sp, 16
+#endif
 	.endm
 
 	.macro RESTORE_ABI_STATE
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	ld	s0, 32(sp)
+	ld	ra, 40(sp)
+	addi	sp, sp, 48
+#else
 	ld	ra, 8(sp)
 	ld	s0, 0(sp)
 	addi	sp, sp, 16
+#endif
 	.endm
 
+	.macro RESTORE_GRAPH_ARGS
+	ld	a0, 24(sp)
+	ld	a1, 16(sp)
+#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
+	ld	a2, 8(sp)
+#endif
+	.endm
+
+ENTRY(ftrace_graph_caller)
+	addi	sp, sp, -16
+	sd	s0, 0(sp)
+	sd	ra, 8(sp)
+	addi	s0, sp, 16
+ftrace_graph_call:
+	.global ftrace_graph_call
+	/*
+	 * Calling ftrace_enable/disable_ftrace_graph_caller would overwrite the
+	 * nops below.  Check ftrace_modify_all_code for details.
+	 */
+	addi	x0, x0, 0
+	addi	x0, x0, 0
+	ld	ra, 8(sp)
+	ld	s0, 0(sp)
+	addi	sp, sp, 16
+	ret
+ENDPROC(ftrace_graph_caller)
+
 ENTRY(ftrace_caller)
 	/*
 	 * a0: the address in the caller when calling ftrace_caller
@@ -33,6 +78,20 @@ ENTRY(ftrace_caller)
 	 */
 	ld	a1, -8(s0)
 	addi	a0, ra, -MCOUNT_INSN_SIZE
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	/*
+	 * the graph tracer (specifically, prepare_ftrace_return) needs these
+	 * arguments but for now the function tracer occupies the regs, so we
+	 * save them in temporary regs to recover later.
+	 */
+	addi	t0, s0, -8
+	mv	t1, a0
+#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
+	ld	t2, -16(s0)
+#endif
+#endif
+
 	SAVE_ABI_STATE
 ftrace_call:
 	.global ftrace_call
@@ -47,6 +106,12 @@ ftrace_call:
 	 */
 	addi	x0, x0, 0
 	addi	x0, x0, 0
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	RESTORE_GRAPH_ARGS
+	call	ftrace_graph_caller
+#endif
+
 	RESTORE_ABI_STATE
 	ret
 ENDPROC(ftrace_caller)
-- 
2.15.1

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

* [PATCH v2 4/6] riscv/ftrace: Add ARCH_SUPPORTS_FTRACE_OPS support
  2018-01-15  6:47 [PATCH v2 0/6] Add dynamic ftrace support for RISC-V platforms Alan Kao
                   ` (2 preceding siblings ...)
  2018-01-15  6:47 ` [PATCH v2 3/6] riscv/ftrace: Add dynamic function graph " Alan Kao
@ 2018-01-15  6:47 ` Alan Kao
  2018-01-15  6:47 ` [PATCH v2 5/6] riscv/ftrace: Add DYNAMIC_FTRACE_WITH_REGS support Alan Kao
  2018-01-15  6:47 ` [PATCH v2 6/6] riscv/ftrace: Add HAVE_FUNCTION_GRAPH_RET_ADDR_PTR support Alan Kao
  5 siblings, 0 replies; 9+ messages in thread
From: Alan Kao @ 2018-01-15  6:47 UTC (permalink / raw)
  To: Palmer Dabbelt, Albert Ou, Christoph Hellwig, Steven Rostedt,
	Ingo Molnar, Masahiro Yamada, Kamil Rytarowski, Andrew Morton,
	patches, linux-kernel
  Cc: Alan Kao, Greentime Hu

Cc: Greentime Hu <greentime@andestech.com>
Signed-off-by: Alan Kao <alankao@andestech.com>
---
 arch/riscv/include/asm/ftrace.h | 1 +
 arch/riscv/kernel/mcount-dyn.S  | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h
index acf0c7d001f3..429a6a156645 100644
--- a/arch/riscv/include/asm/ftrace.h
+++ b/arch/riscv/include/asm/ftrace.h
@@ -9,6 +9,7 @@
 #define HAVE_FUNCTION_GRAPH_FP_TEST
 #endif
 
+#define ARCH_SUPPORTS_FTRACE_OPS 1
 #ifndef __ASSEMBLY__
 void _mcount(void);
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
diff --git a/arch/riscv/kernel/mcount-dyn.S b/arch/riscv/kernel/mcount-dyn.S
index 64e715d4e180..627478571c7a 100644
--- a/arch/riscv/kernel/mcount-dyn.S
+++ b/arch/riscv/kernel/mcount-dyn.S
@@ -75,9 +75,12 @@ ENTRY(ftrace_caller)
 	/*
 	 * a0: the address in the caller when calling ftrace_caller
 	 * a1: the caller's return address
+	 * a2: the address of global variable function_trace_op
 	 */
 	ld	a1, -8(s0)
 	addi	a0, ra, -MCOUNT_INSN_SIZE
+	la	t5, function_trace_op
+	ld	a2, 0(t5)
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	/*
-- 
2.15.1

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

* [PATCH v2 5/6] riscv/ftrace: Add DYNAMIC_FTRACE_WITH_REGS support
  2018-01-15  6:47 [PATCH v2 0/6] Add dynamic ftrace support for RISC-V platforms Alan Kao
                   ` (3 preceding siblings ...)
  2018-01-15  6:47 ` [PATCH v2 4/6] riscv/ftrace: Add ARCH_SUPPORTS_FTRACE_OPS support Alan Kao
@ 2018-01-15  6:47 ` Alan Kao
  2018-01-15  6:47 ` [PATCH v2 6/6] riscv/ftrace: Add HAVE_FUNCTION_GRAPH_RET_ADDR_PTR support Alan Kao
  5 siblings, 0 replies; 9+ messages in thread
From: Alan Kao @ 2018-01-15  6:47 UTC (permalink / raw)
  To: Palmer Dabbelt, Albert Ou, Christoph Hellwig, Steven Rostedt,
	Ingo Molnar, Masahiro Yamada, Kamil Rytarowski, Andrew Morton,
	patches, linux-kernel
  Cc: Alan Kao, Greentime Hu

Cc: Greentime Hu <greentime@andestech.com>
Signed-off-by: Alan Kao <alankao@andestech.com>
---
 arch/riscv/Kconfig             |   1 +
 arch/riscv/kernel/ftrace.c     |  17 ++++++
 arch/riscv/kernel/mcount-dyn.S | 124 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 142 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index a5c5c88700d4..bb2c64976583 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -119,6 +119,7 @@ config ARCH_RV64I
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_DYNAMIC_FTRACE
+	select HAVE_DYNAMIC_FTRACE_WITH_REGS
 
 endchoice
 
diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
index dce1286af9b0..3922b29c107b 100644
--- a/arch/riscv/kernel/ftrace.c
+++ b/arch/riscv/kernel/ftrace.c
@@ -105,6 +105,23 @@ int __init ftrace_dyn_arch_init(void)
 }
 #endif
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
+		       unsigned long addr)
+{
+	unsigned int offset = (unsigned int)(old_addr - rec->ip);
+	unsigned int auipc_call = to_auipc_insn(offset);
+	unsigned int jalr_call = to_jalr_insn(offset);
+	unsigned int calls[2] = {auipc_call, jalr_call};
+	int ret = ftrace_check_current_call(rec->ip, calls);
+
+	if (ret)
+		return ret;
+
+	return __ftrace_modify_call(rec->ip, addr, true);
+}
+#endif
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * Most of this function is copied from arm64.
diff --git a/arch/riscv/kernel/mcount-dyn.S b/arch/riscv/kernel/mcount-dyn.S
index 627478571c7a..3ec3ddbfb5e7 100644
--- a/arch/riscv/kernel/mcount-dyn.S
+++ b/arch/riscv/kernel/mcount-dyn.S
@@ -118,3 +118,127 @@ ftrace_call:
 	RESTORE_ABI_STATE
 	ret
 ENDPROC(ftrace_caller)
+
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+	.macro SAVE_ALL
+	addi	sp, sp, -(PT_SIZE_ON_STACK+16)
+	sd	s0, (PT_SIZE_ON_STACK)(sp)
+	sd	ra, (PT_SIZE_ON_STACK+8)(sp)
+	addi	s0, sp, (PT_SIZE_ON_STACK+16)
+
+	sd x1,  PT_RA(sp)
+	sd x2,  PT_SP(sp)
+	sd x3,  PT_GP(sp)
+	sd x4,  PT_TP(sp)
+	sd x5,  PT_T0(sp)
+	sd x6,  PT_T1(sp)
+	sd x7,  PT_T2(sp)
+	sd x8,  PT_S0(sp)
+	sd x9,  PT_S1(sp)
+	sd x10, PT_A0(sp)
+	sd x11, PT_A1(sp)
+	sd x12, PT_A2(sp)
+	sd x13, PT_A3(sp)
+	sd x14, PT_A4(sp)
+	sd x15, PT_A5(sp)
+	sd x16, PT_A6(sp)
+	sd x17, PT_A7(sp)
+	sd x18, PT_S2(sp)
+	sd x19, PT_S3(sp)
+	sd x20, PT_S4(sp)
+	sd x21, PT_S5(sp)
+	sd x22, PT_S6(sp)
+	sd x23, PT_S7(sp)
+	sd x24, PT_S8(sp)
+	sd x25, PT_S9(sp)
+	sd x26, PT_S10(sp)
+	sd x27, PT_S11(sp)
+	sd x28, PT_T3(sp)
+	sd x29, PT_T4(sp)
+	sd x30, PT_T5(sp)
+	sd x31, PT_T6(sp)
+	.endm
+
+	.macro RESTORE_ALL
+	ld x1,  PT_RA(sp)
+	ld x2,  PT_SP(sp)
+	ld x3,  PT_GP(sp)
+	ld x4,  PT_TP(sp)
+	ld x5,  PT_T0(sp)
+	ld x6,  PT_T1(sp)
+	ld x7,  PT_T2(sp)
+	ld x8,  PT_S0(sp)
+	ld x9,  PT_S1(sp)
+	ld x10, PT_A0(sp)
+	ld x11, PT_A1(sp)
+	ld x12, PT_A2(sp)
+	ld x13, PT_A3(sp)
+	ld x14, PT_A4(sp)
+	ld x15, PT_A5(sp)
+	ld x16, PT_A6(sp)
+	ld x17, PT_A7(sp)
+	ld x18, PT_S2(sp)
+	ld x19, PT_S3(sp)
+	ld x20, PT_S4(sp)
+	ld x21, PT_S5(sp)
+	ld x22, PT_S6(sp)
+	ld x23, PT_S7(sp)
+	ld x24, PT_S8(sp)
+	ld x25, PT_S9(sp)
+	ld x26, PT_S10(sp)
+	ld x27, PT_S11(sp)
+	ld x28, PT_T3(sp)
+	ld x29, PT_T4(sp)
+	ld x30, PT_T5(sp)
+	ld x31, PT_T6(sp)
+
+	ld	s0, (PT_SIZE_ON_STACK)(sp)
+	ld	ra, (PT_SIZE_ON_STACK+8)(sp)
+	addi	sp, sp, (PT_SIZE_ON_STACK+16)
+	.endm
+
+	.macro RESTORE_GRAPH_REG_ARGS
+	ld	a0, PT_T0(sp)
+	ld	a1, PT_T1(sp)
+#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
+	ld	a2, PT_T2(sp)
+#endif
+	.endm
+
+/*
+ * Most of the contents are the same as ftrace_caller.
+ */
+ENTRY(ftrace_regs_caller)
+	/*
+	 * a3: the address of all registers in the stack
+	 */
+	ld	a1, -8(s0)
+	addi	a0, ra, -MCOUNT_INSN_SIZE
+	la	t5, function_trace_op
+	ld	a2, 0(t5)
+	addi	a3, sp, -(PT_SIZE_ON_STACK+16)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	addi	t0, s0, -8
+	mv	t1, a0
+#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
+	ld	t2, -16(s0)
+#endif
+#endif
+	SAVE_ALL
+
+ftrace_regs_call:
+	.global ftrace_regs_call
+	addi	x0, x0, 0
+	addi	x0, x0, 0
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	RESTORE_GRAPH_REG_ARGS
+	call	ftrace_graph_caller
+#endif
+
+	RESTORE_ALL
+	ret
+ENDPROC(ftrace_regs_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
-- 
2.15.1

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

* [PATCH v2 6/6] riscv/ftrace: Add HAVE_FUNCTION_GRAPH_RET_ADDR_PTR support
  2018-01-15  6:47 [PATCH v2 0/6] Add dynamic ftrace support for RISC-V platforms Alan Kao
                   ` (4 preceding siblings ...)
  2018-01-15  6:47 ` [PATCH v2 5/6] riscv/ftrace: Add DYNAMIC_FTRACE_WITH_REGS support Alan Kao
@ 2018-01-15  6:47 ` Alan Kao
  5 siblings, 0 replies; 9+ messages in thread
From: Alan Kao @ 2018-01-15  6:47 UTC (permalink / raw)
  To: Palmer Dabbelt, Albert Ou, Christoph Hellwig, Steven Rostedt,
	Ingo Molnar, Masahiro Yamada, Kamil Rytarowski, Andrew Morton,
	patches, linux-kernel
  Cc: Alan Kao, Greentime Hu

In walk_stackframe, the pc now receives the address from calling
ftrace_graph_ret_addr instead of manual calculation.

Note that the original calculation,
	pc = frame->ra - 4
is buggy when the instruction at the return address happened to be a
compressed inst. But since it is not a critical part of ftrace, it is
ignored for now to ease the review process.

Cc: Greentime Hu <greentime@andestech.com>
Signed-off-by: Alan Kao <alankao@andestech.com>
---
 arch/riscv/include/asm/ftrace.h | 1 +
 arch/riscv/kernel/ftrace.c      | 2 +-
 arch/riscv/kernel/stacktrace.c  | 6 ++++++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h
index 429a6a156645..6e4b4c96b63e 100644
--- a/arch/riscv/include/asm/ftrace.h
+++ b/arch/riscv/include/asm/ftrace.h
@@ -8,6 +8,7 @@
 #if defined(CONFIG_FUNCTION_GRAPH_TRACER) && defined(CONFIG_FRAME_POINTER)
 #define HAVE_FUNCTION_GRAPH_FP_TEST
 #endif
+#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
 
 #define ARCH_SUPPORTS_FTRACE_OPS 1
 #ifndef __ASSEMBLY__
diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
index 3922b29c107b..ded8ab25f4ad 100644
--- a/arch/riscv/kernel/ftrace.c
+++ b/arch/riscv/kernel/ftrace.c
@@ -150,7 +150,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 
 	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
-				       frame_pointer, NULL);
+				       frame_pointer, parent);
 	if (err == -EBUSY)
 		return;
 	*parent = return_hooker;
diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c
index 559aae781154..a4b1d94371a0 100644
--- a/arch/riscv/kernel/stacktrace.c
+++ b/arch/riscv/kernel/stacktrace.c
@@ -18,6 +18,7 @@
 #include <linux/sched/debug.h>
 #include <linux/sched/task_stack.h>
 #include <linux/stacktrace.h>
+#include <linux/ftrace.h>
 
 #ifdef CONFIG_FRAME_POINTER
 
@@ -63,7 +64,12 @@ static void notrace walk_stackframe(struct task_struct *task,
 		frame = (struct stackframe *)fp - 1;
 		sp = fp;
 		fp = frame->fp;
+#ifdef HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
+		pc = ftrace_graph_ret_addr(current, NULL, frame->ra,
+					   (unsigned long *)(fp - 8));
+#else
 		pc = frame->ra - 0x4;
+#endif
 	}
 }
 
-- 
2.15.1

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

* Re: [patches] [PATCH v2 2/6] riscv/ftrace: Add dynamic function tracer support
  2018-01-15  6:47 ` [PATCH v2 2/6] riscv/ftrace: Add dynamic function tracer support Alan Kao
@ 2018-01-15  7:24   ` Stefan O'Rear
  2018-01-15  7:38     ` Alan Kao
  0 siblings, 1 reply; 9+ messages in thread
From: Stefan O'Rear @ 2018-01-15  7:24 UTC (permalink / raw)
  To: patches
  Cc: Palmer Dabbelt, Albert Ou, Christoph Hellwig, Steven Rostedt,
	Ingo Molnar, Masahiro Yamada, Kamil Rytarowski, Andrew Morton,
	linux-kernel, Alan Kao, Greentime Hu

On Sun, Jan 14, 2018 at 10:47 PM, Alan Kao <nonerkao@gmail.com> wrote:
> +       /*
> +        * For the dynamic ftrace to work, here we should reserve at least
> +        * 8 bytes for a functional auipc-jalr pair. Pseudo inst nop may be
> +        * interpreted as different length in different models, so we manually
> +        * *expand* two 4-byte nops here.
> +        *
> +        * Calling ftrace_update_ftrace_func would overwrite the nops below.
> +        * Check ftrace_modify_all_code for details.
> +        */
> +       addi    x0, x0, 0
> +       addi    x0, x0, 0

This relies on behavior of the assembler which is undocumented and, if
my reading of the specification is correct, a bug.

The documented way to assemble an sequence of 2 4-byte NOPs regardless
of subtarget is as follows:

.option push
.option norvc
    nop
    nop
.option pop

I have filed https://github.com/riscv/riscv-binutils-gdb/issues/135 to
get clarity on the assembler behavior; the explicit approach may be
preferable even if the assembler behavior turns out to be correct.

-s

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

* Re: [patches] [PATCH v2 2/6] riscv/ftrace: Add dynamic function tracer support
  2018-01-15  7:24   ` [patches] " Stefan O'Rear
@ 2018-01-15  7:38     ` Alan Kao
  0 siblings, 0 replies; 9+ messages in thread
From: Alan Kao @ 2018-01-15  7:38 UTC (permalink / raw)
  To: patches
  Cc: Palmer Dabbelt, Albert Ou, Christoph Hellwig, Steven Rostedt,
	Ingo Molnar, Masahiro Yamada, Kamil Rytarowski, Andrew Morton,
	linux-kernel, Alan Kao, Greentime Hu

On Sun, Jan 14, 2018 at 11:24:53PM -0800, Stefan O'Rear wrote:
> On Sun, Jan 14, 2018 at 10:47 PM, Alan Kao <nonerkao@gmail.com> wrote:
> > +       /*
> > +        * For the dynamic ftrace to work, here we should reserve at least
> > +        * 8 bytes for a functional auipc-jalr pair. Pseudo inst nop may be
> > +        * interpreted as different length in different models, so we manually
> > +        * *expand* two 4-byte nops here.
> > +        *
> > +        * Calling ftrace_update_ftrace_func would overwrite the nops below.
> > +        * Check ftrace_modify_all_code for details.
> > +        */
> > +       addi    x0, x0, 0
> > +       addi    x0, x0, 0
> 
> This relies on behavior of the assembler which is undocumented and, if
> my reading of the specification is correct, a bug.
> 
> The documented way to assemble an sequence of 2 4-byte NOPs regardless
> of subtarget is as follows:
> 
> .option push
> .option norvc
>     nop
>     nop
> .option pop
> 
> I have filed https://github.com/riscv/riscv-binutils-gdb/issues/135 to
> get clarity on the assembler behavior; the explicit approach may be
> preferable even if the assembler behavior turns out to be correct.
> 
> -s
> 

Thanks for pointing this out.

After checking the way other architectures have done this, I think we can 
just put a 

	call ftrace_stub

here.  Currently we don't support linker relaxing with ftrace, so this
macro will be expand to 8-byte inst-pair.

Alan

> -- 
> You received this message because you are subscribed to the Google Groups "RISC-V Patches" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to patches+unsubscribe@groups.riscv.org.
> To post to this group, send email to patches@groups.riscv.org.
> Visit this group at https://groups.google.com/a/groups.riscv.org/group/patches/.
> To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/patches/CADJ6UvOZz%3DWZ18wYVhZcH0u58u_snDxmgbwsfTOS2ski-4O7tg%40mail.gmail.com.
> For more options, visit https://groups.google.com/a/groups.riscv.org/d/optout.

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

end of thread, other threads:[~2018-01-15  7:38 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-15  6:47 [PATCH v2 0/6] Add dynamic ftrace support for RISC-V platforms Alan Kao
2018-01-15  6:47 ` [PATCH v2 1/6] riscv/ftrace: Add RECORD_MCOUNT support Alan Kao
2018-01-15  6:47 ` [PATCH v2 2/6] riscv/ftrace: Add dynamic function tracer support Alan Kao
2018-01-15  7:24   ` [patches] " Stefan O'Rear
2018-01-15  7:38     ` Alan Kao
2018-01-15  6:47 ` [PATCH v2 3/6] riscv/ftrace: Add dynamic function graph " Alan Kao
2018-01-15  6:47 ` [PATCH v2 4/6] riscv/ftrace: Add ARCH_SUPPORTS_FTRACE_OPS support Alan Kao
2018-01-15  6:47 ` [PATCH v2 5/6] riscv/ftrace: Add DYNAMIC_FTRACE_WITH_REGS support Alan Kao
2018-01-15  6:47 ` [PATCH v2 6/6] riscv/ftrace: Add HAVE_FUNCTION_GRAPH_RET_ADDR_PTR support Alan Kao

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.