From: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>
To: Alexei Starovoitov <alexei.starovoitov@gmail.com>,
Steven Rostedt <rostedt@goodmis.org>,
Florent Revest <revest@chromium.org>
Cc: linux-trace-kernel@vger.kernel.org,
LKML <linux-kernel@vger.kernel.org>,
Martin KaFai Lau <martin.lau@linux.dev>,
bpf <bpf@vger.kernel.org>, Sven Schnelle <svens@linux.ibm.com>,
Alexei Starovoitov <ast@kernel.org>, Jiri Olsa <jolsa@kernel.org>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Alan Maguire <alan.maguire@oracle.com>,
Mark Rutland <mark.rutland@arm.com>,
Peter Zijlstra <peterz@infradead.org>,
Thomas Gleixner <tglx@linutronix.de>, Guo Ren <guoren@kernel.org>
Subject: [RFC PATCH 22/32] function_graph: Add a new entry handler with parent_ip and ftrace_regs
Date: Mon, 6 Nov 2023 01:10:56 +0900 [thread overview]
Message-ID: <169920065596.482486.940814934361190165.stgit@devnote2> (raw)
In-Reply-To: <169920038849.482486.15796387219966662967.stgit@devnote2>
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Add a new entry handler to fgraph_ops as 'entryregfunc' which takes
parent_ip and ftrace_regs. Note that the 'entryfunc' and 'entryregfunc'
are mutual exclusive. You can set only one of them.
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
arch/arm64/kernel/ftrace.c | 8 ++++-
arch/loongarch/kernel/ftrace_dyn.c | 6 +++-
arch/powerpc/kernel/trace/ftrace.c | 2 +
arch/powerpc/kernel/trace/ftrace_64_pg.c | 10 ++++--
arch/x86/kernel/ftrace.c | 50 ++++++++++++++++++++----------
include/linux/ftrace.h | 17 +++++++++-
kernel/trace/fgraph.c | 27 +++++++++++++---
7 files changed, 90 insertions(+), 30 deletions(-)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a650f5e11fc5..e94d9dc13d89 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -481,7 +481,13 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{
- prepare_ftrace_return(ip, &fregs->lr, fregs->fp);
+ if (unlikely(atomic_read(¤t->tracing_graph_pause)))
+ return;
+
+ if (!function_graph_enter_regs(fregs->lr, ip, fregs->fp,
+ (void *)fregs->fp, fregs)) {
+ fregs->lr = (unsigned long)&return_to_handler;
+ }
}
#else
/*
diff --git a/arch/loongarch/kernel/ftrace_dyn.c b/arch/loongarch/kernel/ftrace_dyn.c
index 73858c9029cc..39b3f09a5e0c 100644
--- a/arch/loongarch/kernel/ftrace_dyn.c
+++ b/arch/loongarch/kernel/ftrace_dyn.c
@@ -244,7 +244,11 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
struct pt_regs *regs = &fregs->regs;
unsigned long *parent = (unsigned long *)®s->regs[1];
- prepare_ftrace_return(ip, (unsigned long *)parent);
+ if (unlikely(atomic_read(¤t->tracing_graph_pause)))
+ return;
+
+ if (!function_graph_enter_regs(regs->regs[1], ip, 0, parent, fregs))
+ regs->regs[1] = (unsigned long)&return_to_handler;
}
#else
static int ftrace_modify_graph_caller(bool enable)
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index 82010629cf88..9bf1b6912116 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -422,7 +422,7 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
if (bit < 0)
goto out;
- if (!function_graph_enter(parent_ip, ip, 0, (unsigned long *)sp))
+ if (!function_graph_enter_regs(parent_ip, ip, 0, (unsigned long *)sp, fregs))
parent_ip = ppc_function_entry(return_to_handler);
ftrace_test_recursion_unlock(bit);
diff --git a/arch/powerpc/kernel/trace/ftrace_64_pg.c b/arch/powerpc/kernel/trace/ftrace_64_pg.c
index 7b85c3b460a3..43f6cfaaf7db 100644
--- a/arch/powerpc/kernel/trace/ftrace_64_pg.c
+++ b/arch/powerpc/kernel/trace/ftrace_64_pg.c
@@ -795,7 +795,8 @@ int ftrace_disable_ftrace_graph_caller(void)
* in current thread info. Return the address we want to divert to.
*/
static unsigned long
-__prepare_ftrace_return(unsigned long parent, unsigned long ip, unsigned long sp)
+__prepare_ftrace_return(unsigned long parent, unsigned long ip, unsigned long sp,
+ struct ftrace_regs *fregs)
{
unsigned long return_hooker;
int bit;
@@ -812,7 +813,7 @@ __prepare_ftrace_return(unsigned long parent, unsigned long ip, unsigned long sp
return_hooker = ppc_function_entry(return_to_handler);
- if (!function_graph_enter(parent, ip, 0, (unsigned long *)sp))
+ if (!function_graph_enter_regs(parent, ip, 0, (unsigned long *)sp, fregs))
parent = return_hooker;
ftrace_test_recursion_unlock(bit);
@@ -824,13 +825,14 @@ __prepare_ftrace_return(unsigned long parent, unsigned long ip, unsigned long sp
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{
- fregs->regs.link = __prepare_ftrace_return(parent_ip, ip, fregs->regs.gpr[1]);
+ fregs->regs.link = __prepare_ftrace_return(parent_ip, ip,
+ fregs->regs.gpr[1], fregs);
}
#else
unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip,
unsigned long sp)
{
- return __prepare_ftrace_return(parent, ip, sp);
+ return __prepare_ftrace_return(parent, ip, sp, NULL);
}
#endif
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 12df54ff0e81..85247a8f265b 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -614,16 +614,8 @@ int ftrace_disable_ftrace_graph_caller(void)
}
#endif /* CONFIG_DYNAMIC_FTRACE && !CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS */
-/*
- * Hook the return address and push it in the stack of return addrs
- * in current thread info.
- */
-void prepare_ftrace_return(unsigned long ip, unsigned long *parent,
- unsigned long frame_pointer)
+static inline bool skip_ftrace_return(void)
{
- unsigned long return_hooker = (unsigned long)&return_to_handler;
- int bit;
-
/*
* When resuming from suspend-to-ram, this function can be indirectly
* called from early CPU startup code while the CPU is in real mode,
@@ -633,13 +625,28 @@ void prepare_ftrace_return(unsigned long ip, unsigned long *parent,
* This check isn't as accurate as virt_addr_valid(), but it should be
* good enough for this purpose, and it's fast.
*/
- if (unlikely((long)__builtin_frame_address(0) >= 0))
- return;
+ if ((long)__builtin_frame_address(0) >= 0)
+ return true;
- if (unlikely(ftrace_graph_is_dead()))
- return;
+ if (ftrace_graph_is_dead())
+ return true;
+
+ if (atomic_read(¤t->tracing_graph_pause))
+ return true;
+ return false;
+}
+
+/*
+ * Hook the return address and push it in the stack of return addrs
+ * in current thread info.
+ */
+void prepare_ftrace_return(unsigned long ip, unsigned long *parent,
+ unsigned long frame_pointer)
+{
+ unsigned long return_hooker = (unsigned long)&return_to_handler;
+ int bit;
- if (unlikely(atomic_read(¤t->tracing_graph_pause)))
+ if (unlikely(skip_ftrace_return()))
return;
bit = ftrace_test_recursion_trylock(ip, *parent);
@@ -657,9 +664,20 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{
struct pt_regs *regs = &fregs->regs;
- unsigned long *stack = (unsigned long *)kernel_stack_pointer(regs);
+ unsigned long *parent = (unsigned long *)kernel_stack_pointer(regs);
+ int bit;
- prepare_ftrace_return(ip, (unsigned long *)stack, 0);
+ if (unlikely(skip_ftrace_return()))
+ return;
+
+ bit = ftrace_test_recursion_trylock(ip, *parent);
+ if (bit < 0)
+ return;
+
+ if (!function_graph_enter_regs(*parent, ip, 0, parent, fregs))
+ *parent = (unsigned long)&return_to_handler;
+
+ ftrace_test_recursion_unlock(bit);
}
#endif
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 2e24a2611ca8..a6fd930d3500 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -1037,6 +1037,11 @@ typedef void (*trace_func_graph_ret_t)(struct ftrace_graph_ret *,
typedef int (*trace_func_graph_ent_t)(struct ftrace_graph_ent *,
struct fgraph_ops *); /* entry */
+typedef int (*trace_func_graph_regs_ent_t)(unsigned long func,
+ unsigned long parent_ip,
+ struct ftrace_regs *fregs,
+ struct fgraph_ops *); /* entry w/ regs */
+
extern int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace, struct fgraph_ops *gops);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -1044,6 +1049,7 @@ extern int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace, struct fgraph
struct fgraph_ops {
trace_func_graph_ent_t entryfunc;
trace_func_graph_ret_t retfunc;
+ trace_func_graph_regs_ent_t entryregfunc;
struct ftrace_ops ops; /* for the hash lists */
void *private;
int idx;
@@ -1080,8 +1086,15 @@ struct ftrace_ret_stack {
extern void return_to_handler(void);
extern int
-function_graph_enter(unsigned long ret, unsigned long func,
- unsigned long frame_pointer, unsigned long *retp);
+function_graph_enter_regs(unsigned long ret, unsigned long func,
+ unsigned long frame_pointer, unsigned long *retp,
+ struct ftrace_regs *fregs);
+
+static inline int function_graph_enter(unsigned long ret, unsigned long func,
+ unsigned long fp, unsigned long *retp)
+{
+ return function_graph_enter_regs(ret, func, fp, retp, NULL);
+}
struct ftrace_ret_stack *
ftrace_graph_get_ret_stack(struct task_struct *task, int idx);
diff --git a/kernel/trace/fgraph.c b/kernel/trace/fgraph.c
index e7188c67356e..2623a5987f52 100644
--- a/kernel/trace/fgraph.c
+++ b/kernel/trace/fgraph.c
@@ -512,8 +512,20 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func,
# define MCOUNT_INSN_SIZE 0
#endif
-int function_graph_enter(unsigned long ret, unsigned long func,
- unsigned long frame_pointer, unsigned long *retp)
+static inline int call_entry_func(struct ftrace_graph_ent *trace,
+ unsigned long func, unsigned long ret,
+ struct ftrace_regs *fregs,
+ struct fgraph_ops *gops)
+{
+ if (gops->entryregfunc)
+ return gops->entryregfunc(func, ret, fregs, gops);
+
+ return gops->entryfunc(trace, gops);
+}
+
+int function_graph_enter_regs(unsigned long ret, unsigned long func,
+ unsigned long frame_pointer, unsigned long *retp,
+ struct ftrace_regs *fregs)
{
struct ftrace_graph_ent trace;
int save_curr_ret_stack;
@@ -558,7 +570,7 @@ int function_graph_enter(unsigned long ret, unsigned long func,
}
save_curr_ret_stack = current->curr_ret_stack;
if (ftrace_ops_test(&gops->ops, func, NULL) &&
- gops->entryfunc(&trace, gops)) {
+ call_entry_func(&trace, func, ret, fregs, gops)) {
/* Note, curr_ret_stack could change by enryfunc() */
offset = current->curr_ret_stack;
/* Check the top level stored word */
@@ -876,7 +888,8 @@ void fgraph_init_ops(struct ftrace_ops *dst_ops,
struct ftrace_ops *src_ops)
{
dst_ops->func = ftrace_graph_func;
- dst_ops->flags = FTRACE_OPS_FL_PID | FTRACE_OPS_FL_STUB;
+ dst_ops->flags = FTRACE_OPS_FL_PID | FTRACE_OPS_FL_STUB |
+ FTRACE_OPS_FL_SAVE_ARGS;
#ifdef FTRACE_GRAPH_TRAMP_ADDR
dst_ops->trampoline = FTRACE_GRAPH_TRAMP_ADDR;
@@ -1119,10 +1132,14 @@ int register_ftrace_graph(struct fgraph_ops *gops)
int ret = 0;
int i;
+ if (gops->entryfunc && gops->entryregfunc)
+ return -EINVAL;
+
mutex_lock(&ftrace_lock);
if (!gops->ops.func) {
- gops->ops.flags |= FTRACE_OPS_FL_STUB;
+ gops->ops.flags |=
+ FTRACE_OPS_FL_STUB | FTRACE_OPS_FL_SAVE_ARGS;
gops->ops.func = ftrace_graph_func;
#ifdef FTRACE_GRAPH_TRAMP_ADDR
gops->ops.trampoline = FTRACE_GRAPH_TRAMP_ADDR;
next prev parent reply other threads:[~2023-11-05 16:11 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-05 16:06 [RFC PATCH 00/32] tracing: fprobe: function_graph: Multi-function graph and fprobe on fgraph Masami Hiramatsu (Google)
2023-11-05 16:06 ` [RFC PATCH 01/32] seq_buf: Export seq_buf_puts() Masami Hiramatsu (Google)
2023-11-05 16:06 ` [RFC PATCH 02/32] function_graph: Convert ret_stack to a series of longs Masami Hiramatsu (Google)
2023-11-05 16:07 ` [RFC PATCH 03/32] fgraph: Use BUILD_BUG_ON() to make sure we have structures divisible by long Masami Hiramatsu (Google)
2023-11-05 16:07 ` [RFC PATCH 04/32] function_graph: Add an array structure that will allow multiple callbacks Masami Hiramatsu (Google)
2023-11-05 16:07 ` [RFC PATCH 05/32] function_graph: Allow multiple users to attach to function graph Masami Hiramatsu (Google)
2023-11-05 16:07 ` [RFC PATCH 06/32] function_graph: Remove logic around ftrace_graph_entry and return Masami Hiramatsu (Google)
2023-11-05 16:07 ` [RFC PATCH 07/32] ftrace/function_graph: Pass fgraph_ops to function graph callbacks Masami Hiramatsu (Google)
2023-11-05 16:08 ` [RFC PATCH 08/32] ftrace: Allow function_graph tracer to be enabled in instances Masami Hiramatsu (Google)
2023-11-05 16:08 ` [RFC PATCH 09/32] ftrace: Allow ftrace startup flags exist without dynamic ftrace Masami Hiramatsu (Google)
2023-11-05 16:08 ` [RFC PATCH 10/32] function_graph: Have the instances use their own ftrace_ops for filtering Masami Hiramatsu (Google)
2023-11-07 1:47 ` Masami Hiramatsu
2023-11-05 16:08 ` [RFC PATCH 11/32] function_graph: Add "task variables" per task for fgraph_ops Masami Hiramatsu (Google)
2023-11-05 16:08 ` [RFC PATCH 12/32] function_graph: Move set_graph_function tests to shadow stack global var Masami Hiramatsu (Google)
2023-11-05 16:09 ` [RFC PATCH 13/32] function_graph: Move graph depth stored data " Masami Hiramatsu (Google)
2023-11-05 16:09 ` [RFC PATCH 14/32] function_graph: Move graph notrace bit " Masami Hiramatsu (Google)
2023-11-05 16:09 ` [RFC PATCH 15/32] function_graph: Implement fgraph_reserve_data() and fgraph_retrieve_data() Masami Hiramatsu (Google)
2023-11-05 16:09 ` [RFC PATCH 16/32] function_graph: Add selftest for passing local variables Masami Hiramatsu (Google)
2023-11-05 16:09 ` [RFC PATCH 17/32] function_graph: Fix to update curr_ret_stack with ARRAY entry size Masami Hiramatsu (Google)
2023-11-05 16:10 ` [RFC PATCH 18/32] function_graph: Fix to initalize ftrace_ops for fgraph with ftrace_graph_func Masami Hiramatsu (Google)
2023-11-06 10:04 ` Masami Hiramatsu
2023-11-07 1:49 ` Masami Hiramatsu
2023-11-07 3:07 ` Steven Rostedt
2023-11-05 16:10 ` [RFC PATCH 19/32] function_graph: Fix to check the return value of ftrace_pop_return_trace() Masami Hiramatsu (Google)
2023-11-05 16:10 ` [RFC PATCH 20/32] function_graph: Pass the size of reserved data when retrieving it Masami Hiramatsu (Google)
2023-11-05 16:10 ` [RFC PATCH 21/32] function_graph: Expand the max reserved data size Masami Hiramatsu (Google)
2023-11-05 16:10 ` Masami Hiramatsu (Google) [this message]
2023-11-05 16:11 ` [RFC PATCH 23/32] function_graph: Add a new exit handler with parent_ip and ftrace_regs Masami Hiramatsu (Google)
2023-11-05 16:11 ` [RFC PATCH 24/32] x86/ftrace: Enable HAVE_FUNCTION_GRAPH_FREGS Masami Hiramatsu (Google)
2023-11-05 17:25 ` Peter Zijlstra
2023-11-05 19:11 ` Steven Rostedt
2023-11-05 21:28 ` Steven Rostedt
2023-11-05 23:17 ` Peter Zijlstra
2023-11-05 23:33 ` Steven Rostedt
2023-11-05 23:34 ` Steven Rostedt
2023-11-06 0:38 ` Masami Hiramatsu
2023-11-06 10:19 ` Peter Zijlstra
2023-11-06 12:47 ` Masami Hiramatsu
2023-11-06 12:52 ` Peter Zijlstra
2023-11-06 1:05 ` Masami Hiramatsu
2023-11-06 16:37 ` Steven Rostedt
2023-11-07 0:42 ` Masami Hiramatsu
2023-11-07 3:06 ` Steven Rostedt
2023-11-07 5:43 ` Masami Hiramatsu
2023-11-07 13:48 ` Steven Rostedt
2023-11-07 14:09 ` Steven Rostedt
2023-11-05 16:11 ` [RFC PATCH 25/32] fprobe: Use ftrace_regs in fprobe entry handler Masami Hiramatsu (Google)
2023-11-05 16:11 ` [RFC PATCH 26/32] fprobe: Use ftrace_regs in fprobe exit handler Masami Hiramatsu (Google)
2023-11-05 16:11 ` [RFC PATCH 27/32] tracing: Add ftrace_partial_regs() for converting ftrace_regs to pt_regs Masami Hiramatsu (Google)
2023-11-05 16:12 ` [RFC PATCH 28/32] tracing: Add ftrace_fill_perf_regs() for perf event Masami Hiramatsu (Google)
2023-11-05 16:12 ` [RFC PATCH 29/32] fprobe: Rewrite fprobe on function-graph tracer Masami Hiramatsu (Google)
2023-11-05 16:12 ` [RFC PATCH 30/32] tracing/fprobe: Enable fprobe events with CONFIG_DYNAMIC_FTRACE_WITH_ARGS Masami Hiramatsu (Google)
2023-11-05 16:12 ` [RFC PATCH 31/32] bpf: Enable kprobe_multi feature if CONFIG_FPROBE is enabled Masami Hiramatsu (Google)
2023-11-05 16:12 ` [RFC PATCH 32/32] Documentation: probes: Update fprobe on function-graph tracer Masami Hiramatsu (Google)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=169920065596.482486.940814934361190165.stgit@devnote2 \
--to=mhiramat@kernel.org \
--cc=acme@kernel.org \
--cc=alan.maguire@oracle.com \
--cc=alexei.starovoitov@gmail.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=guoren@kernel.org \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=martin.lau@linux.dev \
--cc=peterz@infradead.org \
--cc=revest@chromium.org \
--cc=rostedt@goodmis.org \
--cc=svens@linux.ibm.com \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.