linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] tracing / arch: Remove direct use of curr_ret_stack
@ 2018-12-10 19:30 Steven Rostedt
  2018-12-10 19:30 ` [PATCH 1/6] fgraph: Add comment to describe ftrace_graph_get_ret_stack Steven Rostedt
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Steven Rostedt @ 2018-12-10 19:30 UTC (permalink / raw)
  To: linux-kernel, linux-arch; +Cc: Ingo Molnar, Andrew Morton


Folks, I'm working on rewriting the function graph tracer. In order to
do so, some changes need to be done that affect architecture specific
code. I'm only able to compile test these changes. I would like to
have folks check out my repo and give them a test.

The shadow stack of ret_stack is going to be modified to allow multiple
users of function graph tracer. It can no longer be referenced directly
as an array. A new utility "ftrace_graph_ret_stack()" is available to
get the ret_stack entry of a given frame of the shadow stack that
architectures can now use. This series converts all users to use the
new interface.


  git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
ftrace/core

Head SHA1: 51584396cff54aaf57ed0bd353767d71429f77b4


Steven Rostedt (VMware) (6):
      fgraph: Add comment to describe ftrace_graph_get_ret_stack
      x86/ftrace: Do not call function graph from dynamic trampolines
      powerpc/frace: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack
      sparc64: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack
      sh: ftrace: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack
      arm64: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack

----
 arch/arm64/kernel/perf_callchain.c |  2 +-
 arch/arm64/kernel/process.c        |  2 +-
 arch/arm64/kernel/return_address.c |  2 +-
 arch/arm64/kernel/stacktrace.c     | 12 +++++++-----
 arch/arm64/kernel/time.c           |  2 +-
 arch/arm64/kernel/traps.c          |  2 +-
 arch/powerpc/kernel/process.c      | 13 +++++++++----
 arch/sh/kernel/dumpstack.c         | 11 +++++++----
 arch/sh/kernel/dwarf.c             |  9 +++++----
 arch/sparc/kernel/perf_event.c     |  8 +++++---
 arch/sparc/kernel/stacktrace.c     |  8 +++++---
 arch/sparc/kernel/traps_64.c       |  7 ++++---
 arch/x86/kernel/ftrace.c           | 40 +++++++++++++++++++++-----------------
 arch/x86/kernel/ftrace_64.S        |  8 ++++----
 kernel/trace/fgraph.c              | 11 +++++++++++
 15 files changed, 84 insertions(+), 53 deletions(-)

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

* [PATCH 1/6] fgraph: Add comment to describe ftrace_graph_get_ret_stack
  2018-12-10 19:30 [PATCH 0/6] tracing / arch: Remove direct use of curr_ret_stack Steven Rostedt
@ 2018-12-10 19:30 ` Steven Rostedt
  2018-12-10 19:30 ` [PATCH 2/6] x86/ftrace: Do not call function graph from dynamic trampolines Steven Rostedt
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Steven Rostedt @ 2018-12-10 19:30 UTC (permalink / raw)
  To: linux-kernel, linux-arch; +Cc: Ingo Molnar, Andrew Morton

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

The ret_stack should not be accessed directly via the curr_ret_stack
variable on the task_struct. This is because the ret_stack is going to be
converted into a series of longs and not an array of ret_stack structures.
The way that a ret_stack should be retrieved is via the
ftrace_graph_get_ret_stack structure, but it needs to be documented on how
to use it.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 kernel/trace/fgraph.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/kernel/trace/fgraph.c b/kernel/trace/fgraph.c
index a3704ec8b599..d4f04f0ca646 100644
--- a/kernel/trace/fgraph.c
+++ b/kernel/trace/fgraph.c
@@ -232,6 +232,17 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
 	return ret;
 }
 
+/**
+ * ftrace_graph_get_ret_stack - return the entry of the shadow stack
+ * @task: The task to read the shadow stack from
+ * @idx: Index down the shadow stack
+ *
+ * Return the ret_struct on the shadow stack of the @task at the
+ * call graph at @idx starting with zero. If @idx is zero, it
+ * will return the last saved ret_stack entry. If it is greater than
+ * zero, it will return the corresponding ret_stack for the depth
+ * of saved return addresses.
+ */
 struct ftrace_ret_stack *
 ftrace_graph_get_ret_stack(struct task_struct *task, int idx)
 {
-- 
2.19.1



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

* [PATCH 2/6] x86/ftrace: Do not call function graph from dynamic trampolines
  2018-12-10 19:30 [PATCH 0/6] tracing / arch: Remove direct use of curr_ret_stack Steven Rostedt
  2018-12-10 19:30 ` [PATCH 1/6] fgraph: Add comment to describe ftrace_graph_get_ret_stack Steven Rostedt
@ 2018-12-10 19:30 ` Steven Rostedt
  2018-12-10 19:30 ` [PATCH 3/6] powerpc/frace: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack Steven Rostedt
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Steven Rostedt @ 2018-12-10 19:30 UTC (permalink / raw)
  To: linux-kernel, linux-arch
  Cc: Ingo Molnar, Andrew Morton, Thomas Gleixner, Borislav Petkov,
	H. Peter Anvin, x86

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

Since commit 79922b8009c07 ("ftrace: Optimize function graph to be
called directly"), dynamic trampolines should not be calling the
function graph tracer at the end. If they do, it could cause the function
graph tracer to trace functions that it filtered out.

Right now it does not cause a problem because there's a test to check if
the function graph tracer is attached to the same function as the
function tracer, which for now is true. But the function graph tracer is
undergoing changes that can make this no longer true which will cause
the function graph tracer to trace other functions.

 For example:

 # cd /sys/kernel/tracing/
 # echo do_IRQ > set_ftrace_filter
 # mkdir instances/foo
 # echo ip_rcv > instances/foo/set_ftrace_filter
 # echo function_graph > current_tracer
 # echo function > instances/foo/current_tracer

Would cause the function graph tracer to trace both do_IRQ and ip_rcv,
if the current tests change.

As the current tests prevent this from being a problem, this code does
not need to be backported. But it does make the code cleaner.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Borislav Petkov <bp@alien8.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 arch/x86/kernel/ftrace.c    | 40 ++++++++++++++++++++-----------------
 arch/x86/kernel/ftrace_64.S |  8 ++++----
 2 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 7ee8067cbf45..2015937b1e91 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -733,6 +733,8 @@ union ftrace_op_code_union {
 	} __attribute__((packed));
 };
 
+#define RET_SIZE		1
+
 static unsigned long
 create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 {
@@ -742,9 +744,10 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 	unsigned long op_offset;
 	unsigned long offset;
 	unsigned long size;
-	unsigned long ip;
+	unsigned long retq;
 	unsigned long *ptr;
 	void *trampoline;
+	void *ip;
 	/* 48 8b 15 <offset> is movq <offset>(%rip), %rdx */
 	unsigned const char op_ref[] = { 0x48, 0x8b, 0x15 };
 	union ftrace_op_code_union op_ptr;
@@ -764,27 +767,27 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 
 	/*
 	 * Allocate enough size to store the ftrace_caller code,
-	 * the jmp to ftrace_epilogue, as well as the address of
-	 * the ftrace_ops this trampoline is used for.
+	 * the iret , as well as the address of the ftrace_ops this
+	 * trampoline is used for.
 	 */
-	trampoline = alloc_tramp(size + MCOUNT_INSN_SIZE + sizeof(void *));
+	trampoline = alloc_tramp(size + RET_SIZE + sizeof(void *));
 	if (!trampoline)
 		return 0;
 
-	*tramp_size = size + MCOUNT_INSN_SIZE + sizeof(void *);
+	*tramp_size = size + RET_SIZE + sizeof(void *);
 
 	/* Copy ftrace_caller onto the trampoline memory */
 	ret = probe_kernel_read(trampoline, (void *)start_offset, size);
-	if (WARN_ON(ret < 0)) {
-		tramp_free(trampoline, *tramp_size);
-		return 0;
-	}
+	if (WARN_ON(ret < 0))
+		goto fail;
 
-	ip = (unsigned long)trampoline + size;
+	ip = trampoline + size;
 
-	/* The trampoline ends with a jmp to ftrace_epilogue */
-	jmp = ftrace_jmp_replace(ip, (unsigned long)ftrace_epilogue);
-	memcpy(trampoline + size, jmp, MCOUNT_INSN_SIZE);
+	/* The trampoline ends with ret(q) */
+	retq = (unsigned long)ftrace_stub;
+	ret = probe_kernel_read(ip, (void *)retq, RET_SIZE);
+	if (WARN_ON(ret < 0))
+		goto fail;
 
 	/*
 	 * The address of the ftrace_ops that is used for this trampoline
@@ -794,17 +797,15 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 	 * the global function_trace_op variable.
 	 */
 
-	ptr = (unsigned long *)(trampoline + size + MCOUNT_INSN_SIZE);
+	ptr = (unsigned long *)(trampoline + size + RET_SIZE);
 	*ptr = (unsigned long)ops;
 
 	op_offset -= start_offset;
 	memcpy(&op_ptr, trampoline + op_offset, OP_REF_SIZE);
 
 	/* Are we pointing to the reference? */
-	if (WARN_ON(memcmp(op_ptr.op, op_ref, 3) != 0)) {
-		tramp_free(trampoline, *tramp_size);
-		return 0;
-	}
+	if (WARN_ON(memcmp(op_ptr.op, op_ref, 3) != 0))
+		goto fail;
 
 	/* Load the contents of ptr into the callback parameter */
 	offset = (unsigned long)ptr;
@@ -819,6 +820,9 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 	ops->flags |= FTRACE_OPS_FL_ALLOC_TRAMP;
 
 	return (unsigned long)trampoline;
+fail:
+	tramp_free(trampoline, *tramp_size);
+	return 0;
 }
 
 static unsigned long calc_trampoline_call_offset(bool save_regs)
diff --git a/arch/x86/kernel/ftrace_64.S b/arch/x86/kernel/ftrace_64.S
index 91b2cff4b79a..75f2b36b41a6 100644
--- a/arch/x86/kernel/ftrace_64.S
+++ b/arch/x86/kernel/ftrace_64.S
@@ -171,9 +171,6 @@ GLOBAL(ftrace_call)
 	restore_mcount_regs
 
 	/*
-	 * The copied trampoline must call ftrace_epilogue as it
-	 * still may need to call the function graph tracer.
-	 *
 	 * The code up to this label is copied into trampolines so
 	 * think twice before adding any new code or changing the
 	 * layout here.
@@ -185,7 +182,10 @@ GLOBAL(ftrace_graph_call)
 	jmp ftrace_stub
 #endif
 
-/* This is weak to keep gas from relaxing the jumps */
+/*
+ * This is weak to keep gas from relaxing the jumps.
+ * It is also used to copy the retq for trampolines.
+ */
 WEAK(ftrace_stub)
 	retq
 ENDPROC(ftrace_caller)
-- 
2.19.1



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

* [PATCH 3/6] powerpc/frace: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack
  2018-12-10 19:30 [PATCH 0/6] tracing / arch: Remove direct use of curr_ret_stack Steven Rostedt
  2018-12-10 19:30 ` [PATCH 1/6] fgraph: Add comment to describe ftrace_graph_get_ret_stack Steven Rostedt
  2018-12-10 19:30 ` [PATCH 2/6] x86/ftrace: Do not call function graph from dynamic trampolines Steven Rostedt
@ 2018-12-10 19:30 ` Steven Rostedt
  2018-12-10 19:30 ` [PATCH 4/6] sparc64: " Steven Rostedt
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Steven Rostedt @ 2018-12-10 19:30 UTC (permalink / raw)
  To: linux-kernel, linux-arch
  Cc: Ingo Molnar, Andrew Morton, Benjamin Herrenschmidt,
	Paul Mackerras, Michael Ellerman, linuxppc-dev

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

[
  Folks, I'm working on rewriting the function graph tracer. In order to
  do so, some changes need to be done that affect architecture specific
  code. I'm only able to compile test these changes. I would like to
  have folks check out my repo and give them a test.

    git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
  ftrace/core

  Head SHA1: 51584396cff54aaf57ed0bd353767d71429f77b4
]

The structure of the ret_stack array on the task struct is going to
change, and accessing it directly via the curr_ret_stack index will no
longer give the ret_stack entry that holds the return address. To access
that, architectures must now use ftrace_graph_get_ret_stack() to get the
associated ret_stack that matches the saved return address.

Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 arch/powerpc/kernel/process.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 96f34730010f..ce393df243aa 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -2061,9 +2061,10 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
 	int count = 0;
 	int firstframe = 1;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	int curr_frame = current->curr_ret_stack;
+	struct ftrace_ret_stack *ret_stack;
 	extern void return_to_handler(void);
 	unsigned long rth = (unsigned long)return_to_handler;
+	int curr_frame = 0;
 #endif
 
 	sp = (unsigned long) stack;
@@ -2089,9 +2090,13 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
 			printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip);
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 			if ((ip == rth) && curr_frame >= 0) {
-				pr_cont(" (%pS)",
-				       (void *)current->ret_stack[curr_frame].ret);
-				curr_frame--;
+				ret_stack = ftrace_graph_get_ret_stack(current,
+								  curr_frame++);
+				if (ret_stack)
+					pr_cont(" (%pS)",
+						(void *)ret_stack->ret);
+				else
+					curr_frame = -1;
 			}
 #endif
 			if (firstframe)
-- 
2.19.1



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

* [PATCH 4/6] sparc64: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack
  2018-12-10 19:30 [PATCH 0/6] tracing / arch: Remove direct use of curr_ret_stack Steven Rostedt
                   ` (2 preceding siblings ...)
  2018-12-10 19:30 ` [PATCH 3/6] powerpc/frace: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack Steven Rostedt
@ 2018-12-10 19:30 ` Steven Rostedt
  2018-12-10 19:30 ` [PATCH 5/6] sh: ftrace: " Steven Rostedt
  2018-12-10 19:30 ` [PATCH 6/6] arm64: " Steven Rostedt
  5 siblings, 0 replies; 10+ messages in thread
From: Steven Rostedt @ 2018-12-10 19:30 UTC (permalink / raw)
  To: linux-kernel, linux-arch
  Cc: Ingo Molnar, Andrew Morton, sparclinux, David S. Miller

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

[
  Folks, I'm working on rewriting the function graph tracer. In order to
  do so, some changes need to be done that affect architecture specific
  code. I'm only able to compile test these changes. I would like to
  have folks check out my repo and give them a test.

    git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
  ftrace/core

  Head SHA1: 51584396cff54aaf57ed0bd353767d71429f77b4
]

The structure of the ret_stack array on the task struct is going to
change, and accessing it directly via the curr_ret_stack index will no
longer give the ret_stack entry that holds the return address. To access
that, architectures must now use ftrace_graph_get_ret_stack() to get the
associated ret_stack that matches the saved return address.

Cc: sparclinux@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 arch/sparc/kernel/perf_event.c | 8 +++++---
 arch/sparc/kernel/stacktrace.c | 8 +++++---
 arch/sparc/kernel/traps_64.c   | 7 ++++---
 3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 47c871394ccb..6de7c684c29f 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -1767,9 +1767,11 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
 		perf_callchain_store(entry, pc);
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 		if ((pc + 8UL) == (unsigned long) &return_to_handler) {
-			int index = current->curr_ret_stack;
-			if (current->ret_stack && index >= graph) {
-				pc = current->ret_stack[index - graph].ret;
+			struct ftrace_ret_stack *ret_stack;
+			ret_stack = ftrace_graph_get_ret_stack(current,
+							       graph);
+			if (ret_stack) {
+				pc = ret_stack->ret;
 				perf_callchain_store(entry, pc);
 				graph++;
 			}
diff --git a/arch/sparc/kernel/stacktrace.c b/arch/sparc/kernel/stacktrace.c
index be4c14cccc05..dd654e651500 100644
--- a/arch/sparc/kernel/stacktrace.c
+++ b/arch/sparc/kernel/stacktrace.c
@@ -57,9 +57,11 @@ static void __save_stack_trace(struct thread_info *tp,
 			trace->entries[trace->nr_entries++] = pc;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 			if ((pc + 8UL) == (unsigned long) &return_to_handler) {
-				int index = t->curr_ret_stack;
-				if (t->ret_stack && index >= graph) {
-					pc = t->ret_stack[index - graph].ret;
+				struct ftrace_ret_stack *ret_stack;
+				ret_stack = ftrace_graph_get_ret_stack(t,
+								       graph);
+				if (ret_stack) {
+					pc = ret_stack->ret;
 					if (trace->nr_entries <
 					    trace->max_entries)
 						trace->entries[trace->nr_entries++] = pc;
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index aa624ed79db1..0cd02a64a451 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -2502,9 +2502,10 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
 		printk(" [%016lx] %pS\n", pc, (void *) pc);
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 		if ((pc + 8UL) == (unsigned long) &return_to_handler) {
-			int index = tsk->curr_ret_stack;
-			if (tsk->ret_stack && index >= graph) {
-				pc = tsk->ret_stack[index - graph].ret;
+			struct ftrace_ret_stack *ret_stack;
+			ret_stack = ftrace_graph_get_ret_stack(tsk, graph);
+			if (ret_stack) {
+				pc = ret_stack->ret;
 				printk(" [%016lx] %pS\n", pc, (void *) pc);
 				graph++;
 			}
-- 
2.19.1



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

* [PATCH 5/6] sh: ftrace: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack
  2018-12-10 19:30 [PATCH 0/6] tracing / arch: Remove direct use of curr_ret_stack Steven Rostedt
                   ` (3 preceding siblings ...)
  2018-12-10 19:30 ` [PATCH 4/6] sparc64: " Steven Rostedt
@ 2018-12-10 19:30 ` Steven Rostedt
  2018-12-10 19:30 ` [PATCH 6/6] arm64: " Steven Rostedt
  5 siblings, 0 replies; 10+ messages in thread
From: Steven Rostedt @ 2018-12-10 19:30 UTC (permalink / raw)
  To: linux-kernel, linux-arch
  Cc: Ingo Molnar, Andrew Morton, linux-sh, Yoshinori Sato, Rich Felker

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

[
  Folks, I'm working on rewriting the function graph tracer. In order to
  do so, some changes need to be done that affect architecture specific
  code. I'm only able to compile test these changes. I would like to
  have folks check out my repo and give them a test.

    git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
  ftrace/core

  Head SHA1: 51584396cff54aaf57ed0bd353767d71429f77b4
]

The structure of the ret_stack array on the task struct is going to
change, and accessing it directly via the curr_ret_stack index will no
longer give the ret_stack entry that holds the return address. To access
that, architectures must now use ftrace_graph_get_ret_stack() to get the
associated ret_stack that matches the saved return address.

Cc: linux-sh@vger.kernel.org
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Cc: Rich Felker <dalias@libc.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 arch/sh/kernel/dumpstack.c | 11 +++++++----
 arch/sh/kernel/dwarf.c     |  9 +++++----
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/arch/sh/kernel/dumpstack.c b/arch/sh/kernel/dumpstack.c
index b564b1eae4ae..2c2e151bf39e 100644
--- a/arch/sh/kernel/dumpstack.c
+++ b/arch/sh/kernel/dumpstack.c
@@ -59,17 +59,20 @@ print_ftrace_graph_addr(unsigned long addr, void *data,
 			struct thread_info *tinfo, int *graph)
 {
 	struct task_struct *task = tinfo->task;
+	struct ftrace_ret_stack *ret_stack;
 	unsigned long ret_addr;
-	int index = task->curr_ret_stack;
 
 	if (addr != (unsigned long)return_to_handler)
 		return;
 
-	if (!task->ret_stack || index < *graph)
+	if (!task->ret_stack)
 		return;
 
-	index -= *graph;
-	ret_addr = task->ret_stack[index].ret;
+	ret_stack = ftrace_graph_get_ret_stack(task, *graph);
+	if (!ret_stack)
+		return;
+
+	ret_addr = ret_stack->ret;
 
 	ops->address(data, ret_addr, 1);
 
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
index bb511e2d9d68..df0fd6efe758 100644
--- a/arch/sh/kernel/dwarf.c
+++ b/arch/sh/kernel/dwarf.c
@@ -608,17 +608,18 @@ struct dwarf_frame *dwarf_unwind_stack(unsigned long pc,
 	 * expected to find the real return address.
 	 */
 	if (pc == (unsigned long)&return_to_handler) {
-		int index = current->curr_ret_stack;
+		struct ftrace_ret_stack *ret_stack;
 
+		ret_stack = ftrace_graph_get_ret_stack(current, 0);
+		if (ret_stack)
+			pc = ret_stack->ret;
 		/*
 		 * We currently have no way of tracking how many
 		 * return_to_handler()'s we've seen. If there is more
 		 * than one patched return address on our stack,
 		 * complain loudly.
 		 */
-		WARN_ON(index > 0);
-
-		pc = current->ret_stack[index].ret;
+		WARN_ON(ftrace_graph_get_ret_stack(current, 1);
 	}
 #endif
 
-- 
2.19.1



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

* [PATCH 6/6] arm64: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack
  2018-12-10 19:30 [PATCH 0/6] tracing / arch: Remove direct use of curr_ret_stack Steven Rostedt
                   ` (4 preceding siblings ...)
  2018-12-10 19:30 ` [PATCH 5/6] sh: ftrace: " Steven Rostedt
@ 2018-12-10 19:30 ` Steven Rostedt
  2018-12-13 17:09   ` James Morse
  5 siblings, 1 reply; 10+ messages in thread
From: Steven Rostedt @ 2018-12-10 19:30 UTC (permalink / raw)
  To: linux-kernel, linux-arch
  Cc: Ingo Molnar, Andrew Morton, linux-arm-kernel, Will Deacon,
	Mark Rutland, Catalin Marinas

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

[
  Folks, I'm working on rewriting the function graph tracer. In order to
  do so, some changes need to be done that affect architecture specific
  code. I'm only able to compile test these changes. I would like to
  have folks check out my repo and give them a test.

    git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
  ftrace/core

  Head SHA1: 51584396cff54aaf57ed0bd353767d71429f77b4
]

The structure of the ret_stack array on the task struct is going to
change, and accessing it directly via the curr_ret_stack index will no
longer give the ret_stack entry that holds the return address. To access
that, architectures must now use ftrace_graph_get_ret_stack() to get the
associated ret_stack that matches the saved return address.

Cc: linux-arm-kernel@lists.infradead.org
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 arch/arm64/kernel/perf_callchain.c |  2 +-
 arch/arm64/kernel/process.c        |  2 +-
 arch/arm64/kernel/return_address.c |  2 +-
 arch/arm64/kernel/stacktrace.c     | 12 +++++++-----
 arch/arm64/kernel/time.c           |  2 +-
 arch/arm64/kernel/traps.c          |  2 +-
 6 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/kernel/perf_callchain.c b/arch/arm64/kernel/perf_callchain.c
index bcafd7dcfe8b..1b792b46604e 100644
--- a/arch/arm64/kernel/perf_callchain.c
+++ b/arch/arm64/kernel/perf_callchain.c
@@ -164,7 +164,7 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
 	frame.fp = regs->regs[29];
 	frame.pc = regs->pc;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	frame.graph = current->curr_ret_stack;
+	frame.graph = 0;
 #endif
 
 	walk_stackframe(current, &frame, callchain_trace, entry);
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index d9a4c2d6dd8b..37a66394b07d 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -459,7 +459,7 @@ unsigned long get_wchan(struct task_struct *p)
 	frame.fp = thread_saved_fp(p);
 	frame.pc = thread_saved_pc(p);
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	frame.graph = p->curr_ret_stack;
+	frame.graph = 0;
 #endif
 	do {
 		if (unwind_frame(p, &frame))
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
index 933adbc0f654..53c40196b607 100644
--- a/arch/arm64/kernel/return_address.c
+++ b/arch/arm64/kernel/return_address.c
@@ -44,7 +44,7 @@ void *return_address(unsigned int level)
 	frame.fp = (unsigned long)__builtin_frame_address(0);
 	frame.pc = (unsigned long)return_address; /* dummy */
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	frame.graph = current->curr_ret_stack;
+	frame.graph = 0;
 #endif
 
 	walk_stackframe(current, &frame, save_return_addr, &data);
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 7723dadf25be..1a29f2695ff2 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -59,15 +59,17 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	if (tsk->ret_stack &&
 			(frame->pc == (unsigned long)return_to_handler)) {
-		if (WARN_ON_ONCE(frame->graph == -1))
-			return -EINVAL;
+		struct ftrace_ret_stack *ret_stack;
 		/*
 		 * This is a case where function graph tracer has
 		 * modified a return address (LR) in a stack frame
 		 * to hook a function return.
 		 * So replace it to an original value.
 		 */
-		frame->pc = tsk->ret_stack[frame->graph--].ret;
+		ret_stack = ftrace_graph_get_ret_stack(tsk, frame->graph++);
+		if (WARN_ON_ONCE(!ret_stack))
+			return -EINVAL;
+		frame->pc = ret_stack->ret;
 	}
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
@@ -134,7 +136,7 @@ void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
 	frame.fp = regs->regs[29];
 	frame.pc = regs->pc;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	frame.graph = current->curr_ret_stack;
+	frame.graph = 0;
 #endif
 
 	walk_stackframe(current, &frame, save_trace, &data);
@@ -165,7 +167,7 @@ static noinline void __save_stack_trace(struct task_struct *tsk,
 		frame.pc = (unsigned long)__save_stack_trace;
 	}
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	frame.graph = tsk->curr_ret_stack;
+	frame.graph = 0;
 #endif
 
 	walk_stackframe(tsk, &frame, save_trace, &data);
diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index f258636273c9..a777ae90044d 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -52,7 +52,7 @@ unsigned long profile_pc(struct pt_regs *regs)
 	frame.fp = regs->regs[29];
 	frame.pc = regs->pc;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	frame.graph = current->curr_ret_stack;
+	frame.graph = 0;
 #endif
 	do {
 		int ret = unwind_frame(NULL, &frame);
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 5f4d9acb32f5..49ebf3771391 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -122,7 +122,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
 		frame.pc = thread_saved_pc(tsk);
 	}
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	frame.graph = tsk->curr_ret_stack;
+	frame.graph = 0;
 #endif
 
 	skip = !!regs;
-- 
2.19.1



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

* Re: [PATCH 6/6] arm64: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack
  2018-12-10 19:30 ` [PATCH 6/6] arm64: " Steven Rostedt
@ 2018-12-13 17:09   ` James Morse
  2018-12-15  3:00     ` Steven Rostedt
  0 siblings, 1 reply; 10+ messages in thread
From: James Morse @ 2018-12-13 17:09 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-kernel, linux-arch, Ingo Molnar, Andrew Morton,
	linux-arm-kernel, Will Deacon, Mark Rutland, Catalin Marinas

Hi Steven,

On 10/12/2018 19:30, Steven Rostedt wrote:
> From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>
> 
> [
>   Folks, I'm working on rewriting the function graph tracer. In order to
>   do so, some changes need to be done that affect architecture specific
>   code. I'm only able to compile test these changes. I would like to
>   have folks check out my repo and give them a test.
> 
>     git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
>   ftrace/core
> 
>   Head SHA1: 51584396cff54aaf57ed0bd353767d71429f77b4
> ]
> 
> The structure of the ret_stack array on the task struct is going to
> change, and accessing it directly via the curr_ret_stack index will no
> longer give the ret_stack entry that holds the return address. To access
> that, architectures must now use ftrace_graph_get_ret_stack() to get the
> associated ret_stack that matches the saved return address.

I gave this branch a spin, but I hit the WARN_ON() fairly easily:

root@debian-guest:~# echo function_graph > /sys/kernel/debug/tracing/current_tracer
root@debian-guest:~# ps
[   27.744824] WARNING: CPU: 0 PID: 2457 at arch/arm64/kernel/stacktrace.c:70
unwind_frame+0x78/0x128
[   27.745174] Modules linked in:
[   27.745375] CPU: 0 PID: 2457 Comm: ps Not tainted
4.20.0-rc3-00038-g51584396cff5 #10814
[   27.745697] Hardware name: linux,dummy-virt (DT)
[   27.745918] pstate: 80400005 (Nzcv daif +PAN -UAO)
[   27.746151] pc : unwind_frame+0x78/0x128
[   27.746337] lr : unwind_frame+0x114/0x128
[   27.746511] sp : ffff00000c893a80
[   27.746685] x29: ffff00000c893a80 x28: 0000000000000000
[   27.746914] x27: ffffffffffffffff x26: 0000000000000001
[   27.747150] x25: 0000000000000049 x24: ffff000009662940
[   27.747375] x23: 0000000000000001 x22: ffff0000096496c8
[   27.747622] x21: ffff0000096496c8 x20: 000000000000000f
[   27.747851] x19: ffff00000c893ad0 x18: 0000000000000000
[   27.748078] x17: 0000000000000000 x16: 0000000000000000
[   27.748337] x15: 0000000000000000 x14: 0000000000000000
[   27.748563] x13: ffff80000a6b2500 x12: 0000000000300000
[   27.748790] x11: 0000000000281bad x10: 0000000000000528
[   27.749322] x9 : ffff80000c808400 x8 : 0000000000000030
[   27.749557] x7 : ffff80000a503520 x6 : 0000000000000528
[   27.749790] x5 : 0000000000019a3b x4 : ffff80000a6b2580
[   27.750010] x3 : ffff80000c1a0d80 x2 : 0000000000000001
[   27.750236] x1 : 000000000000000a x0 : 0000000000000000
[   27.750460] Call trace:
[   27.750587]  unwind_frame+0x78/0x128
[   27.750761]  get_wchan+0xa4/0x110
[   27.750926]  do_task_stat+0x8d4/0x9e8
[   27.751097]  proc_tgid_stat+0x40/0x50
[   27.751271]  proc_single_show+0x5c/0xb8
[   27.751448]  seq_read+0x138/0x450
[   27.751614]  __vfs_read+0x60/0x170
[   27.751782]  vfs_read+0x94/0x150
[   27.751948]  ksys_read+0x6c/0xd0
[   27.752129]  __arm64_sys_read+0x24/0x30
[   27.752309]  el0_svc_common+0x94/0xe8
[   27.752479]  el0_svc_handler+0x38/0x78
[   27.752642]  el0_svc+0x8/0xc
[   27.752804] ---[ end trace fdae6e80cafbfff9 ]---
  PID TTY          TIME CMD
 2401 hvc0     00:00:00 login
 2451 hvc0     00:00:00 bash
 2457 hvc0     00:00:00 ps

This is single cpu kvm guest, with arm64's defconfig and:
| CONFIG_GENERIC_TRACER=y
| CONFIG_FUNCTION_TRACER=y
| CONFIG_FUNCTION_GRAPH_TRACER=y

This doesn't happen with the same configuration on v4.20-rc4.


> diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
> index 7723dadf25be..1a29f2695ff2 100644
> --- a/arch/arm64/kernel/stacktrace.c
> +++ b/arch/arm64/kernel/stacktrace.c
> @@ -59,15 +59,17 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
>  #ifdef CONFIG_FUNCTION_GRAPH_TRACER
>  	if (tsk->ret_stack &&
>  			(frame->pc == (unsigned long)return_to_handler)) {
> -		if (WARN_ON_ONCE(frame->graph == -1))
> -			return -EINVAL;
> +		struct ftrace_ret_stack *ret_stack;
>  		/*
>  		 * This is a case where function graph tracer has
>  		 * modified a return address (LR) in a stack frame
>  		 * to hook a function return.
>  		 * So replace it to an original value.
>  		 */
> -		frame->pc = tsk->ret_stack[frame->graph--].ret;
> +		ret_stack = ftrace_graph_get_ret_stack(tsk, frame->graph++);
> +		if (WARN_ON_ONCE(!ret_stack))
> +			return -EINVAL;
> +		frame->pc = ret_stack->ret;
>  	}
>  #endif /* CONFIG_FUNCTION_GRAPH_TRACER */


Thanks,

James

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

* Re: [PATCH 6/6] arm64: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack
  2018-12-13 17:09   ` James Morse
@ 2018-12-15  3:00     ` Steven Rostedt
  2018-12-17 13:30       ` James Morse
  0 siblings, 1 reply; 10+ messages in thread
From: Steven Rostedt @ 2018-12-15  3:00 UTC (permalink / raw)
  To: James Morse
  Cc: linux-kernel, linux-arch, Ingo Molnar, Andrew Morton,
	linux-arm-kernel, Will Deacon, Mark Rutland, Catalin Marinas

On Thu, 13 Dec 2018 17:09:35 +0000
James Morse <james.morse@arm.com> wrote:

> Hi Steven,
> 

> I gave this branch a spin, but I hit the WARN_ON() fairly easily:

Thanks for testing!

Can you see if this patch fixes it for you?

-- Steve

diff --git a/kernel/trace/fgraph.c b/kernel/trace/fgraph.c
index d4f04f0ca646..8dfd5021b933 100644
--- a/kernel/trace/fgraph.c
+++ b/kernel/trace/fgraph.c
@@ -246,10 +246,10 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
 struct ftrace_ret_stack *
 ftrace_graph_get_ret_stack(struct task_struct *task, int idx)
 {
-	idx = current->curr_ret_stack - idx;
+	idx = task->curr_ret_stack - idx;
 
 	if (idx >= 0 && idx <= task->curr_ret_stack)
-		return &current->ret_stack[idx];
+		return &task->ret_stack[idx];
 
 	return NULL;
 }


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

* Re: [PATCH 6/6] arm64: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack
  2018-12-15  3:00     ` Steven Rostedt
@ 2018-12-17 13:30       ` James Morse
  0 siblings, 0 replies; 10+ messages in thread
From: James Morse @ 2018-12-17 13:30 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-kernel, linux-arch, Ingo Molnar, Andrew Morton,
	linux-arm-kernel, Will Deacon, Mark Rutland, Catalin Marinas

Hi Steve,

On 15/12/2018 03:00, Steven Rostedt wrote:
> On Thu, 13 Dec 2018 17:09:35 +0000
> James Morse <james.morse@arm.com> wrote:
>> I gave this branch a spin, but I hit the WARN_ON() fairly easily:
> 
> Thanks for testing!
> 
> Can you see if this patch fixes it for you?

> diff --git a/kernel/trace/fgraph.c b/kernel/trace/fgraph.c
> index d4f04f0ca646..8dfd5021b933 100644
> --- a/kernel/trace/fgraph.c
> +++ b/kernel/trace/fgraph.c
> @@ -246,10 +246,10 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
>  struct ftrace_ret_stack *
>  ftrace_graph_get_ret_stack(struct task_struct *task, int idx)
>  {
> -	idx = current->curr_ret_stack - idx;
> +	idx = task->curr_ret_stack - idx;
>  
>  	if (idx >= 0 && idx <= task->curr_ret_stack)
> -		return &current->ret_stack[idx];
> +		return &task->ret_stack[idx];
>  
>  	return NULL;
>  }
> 

Heh, yes that fixes it:

Tested-by: James Morse <james.morse@arm.com>


Thanks,

James

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

end of thread, other threads:[~2018-12-17 13:31 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-10 19:30 [PATCH 0/6] tracing / arch: Remove direct use of curr_ret_stack Steven Rostedt
2018-12-10 19:30 ` [PATCH 1/6] fgraph: Add comment to describe ftrace_graph_get_ret_stack Steven Rostedt
2018-12-10 19:30 ` [PATCH 2/6] x86/ftrace: Do not call function graph from dynamic trampolines Steven Rostedt
2018-12-10 19:30 ` [PATCH 3/6] powerpc/frace: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack Steven Rostedt
2018-12-10 19:30 ` [PATCH 4/6] sparc64: " Steven Rostedt
2018-12-10 19:30 ` [PATCH 5/6] sh: ftrace: " Steven Rostedt
2018-12-10 19:30 ` [PATCH 6/6] arm64: " Steven Rostedt
2018-12-13 17:09   ` James Morse
2018-12-15  3:00     ` Steven Rostedt
2018-12-17 13:30       ` James Morse

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).