From: Masami Hiramatsu (Google) <mhira...@kernel.org>

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.

Signed-off-by: Masami Hiramatsu (Google) <mhira...@kernel.org>
Acked-by: Florent Revest <rev...@chromium.org>
---
 Changes in v6:
  - Keep using SAVE_REGS flag to avoid breaking bpf kprobe-multi test.
---
 include/linux/fprobe.h          |    2 +-
 kernel/trace/Kconfig            |    3 ++-
 kernel/trace/bpf_trace.c        |   10 +++++++---
 kernel/trace/fprobe.c           |    3 ++-
 kernel/trace/trace_fprobe.c     |    6 +++++-
 lib/test_fprobe.c               |    4 ++--
 samples/fprobe/fprobe_example.c |    2 +-
 7 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/include/linux/fprobe.h b/include/linux/fprobe.h
index 3e03758151f4..36c0595f7b93 100644
--- a/include/linux/fprobe.h
+++ b/include/linux/fprobe.h
@@ -35,7 +35,7 @@ struct fprobe {
        int                     nr_maxactive;
 
        int (*entry_handler)(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);
        void (*exit_handler)(struct fprobe *fp, unsigned long entry_ip,
                             unsigned long ret_ip, struct pt_regs *regs,
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 308b3bec01b1..805d72ab77c6 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -290,7 +290,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
@@ -675,6 +675,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
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 7ac6c52b25eb..2f04777330e0 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -2577,7 +2577,7 @@ static int __init bpf_event_init(void)
 fs_initcall(bpf_event_init);
 #endif /* CONFIG_MODULES */
 
-#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;
@@ -2807,10 +2807,14 @@ 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 bpf_kprobe_multi_link *link;
+       struct pt_regs *regs = ftrace_get_regs(fregs);
+
+       if (!regs)
+               return 0;
 
        link = container_of(fp, struct bpf_kprobe_multi_link, fp);
        kprobe_multi_link_prog_run(link, get_entry_ip(fentry_ip), regs);
@@ -3084,7 +3088,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr 
*attr, struct bpf_prog *pr
        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;
diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c
index 6cd2a4e3afb8..a932c3a79e8f 100644
--- a/kernel/trace/fprobe.c
+++ b/kernel/trace/fprobe.c
@@ -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;
 }
 
diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c
index 7d2ddbcfa377..ef6b36fd05ae 100644
--- a/kernel/trace/trace_fprobe.c
+++ b/kernel/trace/trace_fprobe.c
@@ -320,12 +320,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
diff --git a/lib/test_fprobe.c b/lib/test_fprobe.c
index 24de0e5ff859..ff607babba18 100644
--- a/lib/test_fprobe.c
+++ b/lib/test_fprobe.c
@@ -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;
diff --git a/samples/fprobe/fprobe_example.c b/samples/fprobe/fprobe_example.c
index 64e715e7ed11..1545a1aac616 100644
--- a/samples/fprobe/fprobe_example.c
+++ b/samples/fprobe/fprobe_example.c
@@ -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)
                /*


Reply via email to