fprobe: Use ftrace_regs in fprobe entry handler
authorMasami Hiramatsu (Google) <mhiramat@kernel.org>
Thu, 26 Dec 2024 05:12:20 +0000 (14:12 +0900)
committerSteven Rostedt (Google) <rostedt@goodmis.org>
Thu, 26 Dec 2024 15:50:03 +0000 (10:50 -0500)
This allows fprobes to be available with CONFIG_DYNAMIC_FTRACE_WITH_ARGS
instead of CONFIG_DYNAMIC_FTRACE_WITH_REGS, then we can enable fprobe
on arm64.

Cc: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: Martin KaFai Lau <martin.lau@linux.dev>
Cc: bpf <bpf@vger.kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Alan Maguire <alan.maguire@oracle.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Link: https://lore.kernel.org/173518994037.391279.2786805566359674586.stgit@devnote2
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Acked-by: Florent Revest <revest@chromium.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
include/linux/fprobe.h
kernel/trace/Kconfig
kernel/trace/bpf_trace.c
kernel/trace/fprobe.c
kernel/trace/trace_fprobe.c
lib/test_fprobe.c
samples/fprobe/fprobe_example.c

index f3986958811751c3956be23495ad08b7ee72e031..ca64ee5e45d2c500383b47058c799a21e00fcf89 100644 (file)
@@ -10,7 +10,7 @@
 struct fprobe;
 
 typedef int (*fprobe_entry_cb)(struct fprobe *fp, unsigned long entry_ip,
-                              unsigned long ret_ip, struct pt_regs *regs,
+                              unsigned long ret_ip, struct ftrace_regs *regs,
                               void *entry_data);
 
 typedef void (*fprobe_exit_cb)(struct fprobe *fp, unsigned long entry_ip,
index c5ab2a561272d7e677e4c5f687d7a84ab474a94d..f10ca86fbfad2f3e7e526a2fe8ae19bed9fe3921 100644 (file)
@@ -297,7 +297,7 @@ config DYNAMIC_FTRACE_WITH_ARGS
 config FPROBE
        bool "Kernel Function Probe (fprobe)"
        depends on FUNCTION_TRACER
-       depends on DYNAMIC_FTRACE_WITH_REGS
+       depends on DYNAMIC_FTRACE_WITH_REGS || DYNAMIC_FTRACE_WITH_ARGS
        depends on HAVE_RETHOOK
        select RETHOOK
        default n
@@ -682,6 +682,7 @@ config FPROBE_EVENTS
        select TRACING
        select PROBE_EVENTS
        select DYNAMIC_EVENTS
+       depends on DYNAMIC_FTRACE_WITH_REGS
        default y
        help
          This allows user to add tracing events on the function entry and
index 1b8db5aee9d38cb76f9e7e604fafca297ee24efa..7bb2e6ecd31f1ff67d2273b833b96fcc4181e39e 100644 (file)
@@ -2561,7 +2561,7 @@ struct bpf_session_run_ctx {
        void *data;
 };
 
-#ifdef CONFIG_FPROBE
+#if defined(CONFIG_FPROBE) && defined(CONFIG_DYNAMIC_FTRACE_WITH_REGS)
 struct bpf_kprobe_multi_link {
        struct bpf_link link;
        struct fprobe fp;
@@ -2813,12 +2813,16 @@ kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link,
 
 static int
 kprobe_multi_link_handler(struct fprobe *fp, unsigned long fentry_ip,
-                         unsigned long ret_ip, struct pt_regs *regs,
+                         unsigned long ret_ip, struct ftrace_regs *fregs,
                          void *data)
 {
+       struct pt_regs *regs = ftrace_get_regs(fregs);
        struct bpf_kprobe_multi_link *link;
        int err;
 
+       if (!regs)
+               return 0;
+
        link = container_of(fp, struct bpf_kprobe_multi_link, fp);
        err = kprobe_multi_link_prog_run(link, get_entry_ip(fentry_ip), regs, false, data);
        return is_kprobe_session(link->link.prog) ? err : 0;
@@ -3093,7 +3097,7 @@ error:
        kvfree(cookies);
        return err;
 }
-#else /* !CONFIG_FPROBE */
+#else /* !CONFIG_FPROBE || !CONFIG_DYNAMIC_FTRACE_WITH_REGS */
 int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
 {
        return -EOPNOTSUPP;
index 9ff0182458408438ddc5d7c720d866d0adc02dfd..3d37892838739dc3a2319d3a419304ea0fb0a541 100644 (file)
@@ -46,7 +46,7 @@ static inline void __fprobe_handler(unsigned long ip, unsigned long parent_ip,
        }
 
        if (fp->entry_handler)
-               ret = fp->entry_handler(fp, ip, parent_ip, ftrace_get_regs(fregs), entry_data);
+               ret = fp->entry_handler(fp, ip, parent_ip, fregs, entry_data);
 
        /* If entry_handler returns !0, nmissed is not counted. */
        if (rh) {
@@ -182,6 +182,7 @@ static void fprobe_init(struct fprobe *fp)
                fp->ops.func = fprobe_kprobe_handler;
        else
                fp->ops.func = fprobe_handler;
+
        fp->ops.flags |= FTRACE_OPS_FL_SAVE_REGS;
 }
 
index c62d1629cffecd72f01b54f8586b7b02ed671a5d..0f254685e26abf8c9ea76310cedefc290027b5f6 100644 (file)
@@ -217,12 +217,13 @@ NOKPROBE_SYMBOL(fentry_trace_func);
 
 /* function exit handler */
 static int trace_fprobe_entry_handler(struct fprobe *fp, unsigned long entry_ip,
-                               unsigned long ret_ip, struct pt_regs *regs,
+                               unsigned long ret_ip, struct ftrace_regs *fregs,
                                void *entry_data)
 {
        struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp);
+       struct pt_regs *regs = ftrace_get_regs(fregs);
 
-       if (tf->tp.entry_arg)
+       if (regs && tf->tp.entry_arg)
                store_trace_entry_data(entry_data, &tf->tp, regs);
 
        return 0;
@@ -339,12 +340,16 @@ NOKPROBE_SYMBOL(fexit_perf_func);
 #endif /* CONFIG_PERF_EVENTS */
 
 static int fentry_dispatcher(struct fprobe *fp, unsigned long entry_ip,
-                            unsigned long ret_ip, struct pt_regs *regs,
+                            unsigned long ret_ip, struct ftrace_regs *fregs,
                             void *entry_data)
 {
        struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp);
+       struct pt_regs *regs = ftrace_get_regs(fregs);
        int ret = 0;
 
+       if (!regs)
+               return 0;
+
        if (trace_probe_test_flag(&tf->tp, TP_FLAG_TRACE))
                fentry_trace_func(tf, entry_ip, regs);
 #ifdef CONFIG_PERF_EVENTS
index 24de0e5ff85998c9d927719f4452b129e1cc0e62..ff607babba1890b974f8d11d7c814a1a29b519c7 100644 (file)
@@ -40,7 +40,7 @@ static noinline u32 fprobe_selftest_nest_target(u32 value, u32 (*nest)(u32))
 
 static notrace int fp_entry_handler(struct fprobe *fp, unsigned long ip,
                                    unsigned long ret_ip,
-                                   struct pt_regs *regs, void *data)
+                                   struct ftrace_regs *fregs, void *data)
 {
        KUNIT_EXPECT_FALSE(current_test, preemptible());
        /* This can be called on the fprobe_selftest_target and the fprobe_selftest_target2 */
@@ -81,7 +81,7 @@ static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip,
 
 static notrace int nest_entry_handler(struct fprobe *fp, unsigned long ip,
                                      unsigned long ret_ip,
-                                     struct pt_regs *regs, void *data)
+                                     struct ftrace_regs *fregs, void *data)
 {
        KUNIT_EXPECT_FALSE(current_test, preemptible());
        return 0;
index 0a50b05add9694564ca82c49e417b1bf9533dfef..c234afae52d6f5966126e619e80618441ce6cb7a 100644 (file)
@@ -50,7 +50,7 @@ static void show_backtrace(void)
 
 static int sample_entry_handler(struct fprobe *fp, unsigned long ip,
                                unsigned long ret_ip,
-                               struct pt_regs *regs, void *data)
+                               struct ftrace_regs *fregs, void *data)
 {
        if (use_trace)
                /*