linux-trace-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
@ 2026-01-07  9:32 Jiri Olsa
  2026-01-07  9:32 ` [PATCH bpf-next 2/2] selftests/bpf: Add test for bpf_override_return helper Jiri Olsa
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Jiri Olsa @ 2026-01-07  9:32 UTC (permalink / raw)
  To: Masami Hiramatsu, Steven Rostedt, Will Deacon
  Cc: Mahe Tardy, Peter Zijlstra, bpf, linux-trace-kernel,
	linux-arm-kernel, x86, Yonghong Song, Song Liu, Andrii Nakryiko,
	Mark Rutland

Mahe reported issue with bpf_override_return helper not working when
executed from kprobe.multi bpf program on arm.

The problem is that on arm we use alternate storage for pt_regs object
that is passed to bpf_prog_run and if any register is changed (which
is the case of bpf_override_return) it's not propagated back to actual
pt_regs object.

Fixing this by introducing and calling ftrace_partial_regs_update function
to propagate the values of changed registers (ip and stack).

Fixes: b9b55c8912ce ("tracing: Add ftrace_partial_regs() for converting ftrace_regs to pt_regs")
Reported-by: Mahe Tardy <mahe.tardy@gmail.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
v1 changes:
 - used ftrace_partial_regs_update with comments from Steven

 arch/arm64/include/asm/ftrace.h | 24 ++++++++++++++++++++++++
 include/linux/ftrace.h          |  3 +++
 kernel/trace/bpf_trace.c        |  1 +
 3 files changed, 28 insertions(+)

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 1621c84f44b3..177c7bbf3b84 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -157,6 +157,30 @@ ftrace_partial_regs(const struct ftrace_regs *fregs, struct pt_regs *regs)
 	return regs;
 }
 
+/*
+ * ftrace_partial_regs_update - update the original ftrace_regs from regs
+ * @fregs: The ftrace_regs to update from @regs
+ * @regs: The partial regs from ftrace_partial_regs() that was updated
+ *
+ * Some architectures have the partial regs living in the ftrace_regs
+ * structure, whereas other architectures need to make a different copy
+ * of the @regs. If a partial @regs is retrieved by ftrace_partial_regs() and
+ * if the code using @regs updates a field (like the instruction pointer or
+ * stack pointer) it may need to propagate that change to the original @fregs
+ * it retrieved the partial @regs from. Use this function to guarantee that
+ * update happens.
+ */
+static __always_inline void
+ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
+{
+	struct __arch_ftrace_regs *afregs = arch_ftrace_regs(fregs);
+
+	if (afregs->pc != regs->pc) {
+		afregs->pc = regs->pc;
+		afregs->regs[0] = regs->regs[0];
+	}
+}
+
 #define arch_ftrace_fill_perf_regs(fregs, _regs) do {		\
 		(_regs)->pc = arch_ftrace_regs(fregs)->pc;			\
 		(_regs)->regs[29] = arch_ftrace_regs(fregs)->fp;		\
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 770f0dc993cc..ae22559b4099 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -213,6 +213,9 @@ ftrace_partial_regs(struct ftrace_regs *fregs, struct pt_regs *regs)
 	return regs;
 }
 
+static __always_inline void
+ftrace_partial_regs_update(struct ftrace_regs *fregs, struct pt_regs *regs) { }
+
 #endif /* !CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS || CONFIG_HAVE_FTRACE_REGS_HAVING_PT_REGS */
 
 #ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 6e076485bf70..3a17f79b20c2 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -2564,6 +2564,7 @@ kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link,
 	old_run_ctx = bpf_set_run_ctx(&run_ctx.session_ctx.run_ctx);
 	err = bpf_prog_run(link->link.prog, regs);
 	bpf_reset_run_ctx(old_run_ctx);
+	ftrace_partial_regs_update(fregs, bpf_kprobe_multi_pt_regs_ptr());
 	rcu_read_unlock();
 
  out:
-- 
2.52.0


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

* [PATCH bpf-next 2/2] selftests/bpf: Add test for bpf_override_return helper
  2026-01-07  9:32 [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Jiri Olsa
@ 2026-01-07  9:32 ` Jiri Olsa
  2026-01-07 14:16 ` [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Will Deacon
  2026-01-07 16:03 ` Steven Rostedt
  2 siblings, 0 replies; 9+ messages in thread
From: Jiri Olsa @ 2026-01-07  9:32 UTC (permalink / raw)
  To: Masami Hiramatsu, Steven Rostedt, Will Deacon
  Cc: Song Liu, Peter Zijlstra, bpf, linux-trace-kernel,
	linux-arm-kernel, x86, Yonghong Song, Song Liu, Andrii Nakryiko,
	Mark Rutland, Mahe Tardy

We do not actually test the bpf_override_return helper functionality
itself at the moment, only the bpf program being able to attach it.

Adding test that override prctl syscall return value on top of
kprobe and kprobe.multi.

Acked-by: Song Liu <song@kernel.org>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
v1 changes:
- added ack from Song
- moved SYS_PREFIX to trace_helpers.h

 .../bpf/prog_tests/kprobe_multi_test.c        | 44 +++++++++++++++++++
 .../bpf/progs/kprobe_multi_override.c         | 15 +++++++
 tools/testing/selftests/bpf/trace_helpers.h   | 12 +++++
 3 files changed, 71 insertions(+)

diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
index 6cfaa978bc9a..9caef222e528 100644
--- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
+++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
@@ -1,4 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <errno.h>
+#include <sys/prctl.h>
 #include <test_progs.h>
 #include "kprobe_multi.skel.h"
 #include "trace_helpers.h"
@@ -540,6 +542,46 @@ static void test_attach_override(void)
 	kprobe_multi_override__destroy(skel);
 }
 
+static void test_override(void)
+{
+	struct kprobe_multi_override *skel = NULL;
+	int err;
+
+	skel = kprobe_multi_override__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load"))
+		goto cleanup;
+
+	skel->bss->pid = getpid();
+
+	/* no override */
+	err = prctl(0xffff, 0);
+	ASSERT_EQ(err, -1, "err");
+
+	/* kprobe.multi override */
+	skel->links.test_override = bpf_program__attach_kprobe_multi_opts(skel->progs.test_override,
+						SYS_PREFIX "sys_prctl", NULL);
+	if (!ASSERT_OK_PTR(skel->links.test_override, "bpf_program__attach_kprobe_multi_opts"))
+		goto cleanup;
+
+	err = prctl(0xffff, 0);
+	ASSERT_EQ(err, 123, "err");
+
+	bpf_link__destroy(skel->links.test_override);
+	skel->links.test_override = NULL;
+
+	/* kprobe override */
+	skel->links.test_kprobe_override = bpf_program__attach_kprobe(skel->progs.test_kprobe_override,
+							false, SYS_PREFIX "sys_prctl");
+	if (!ASSERT_OK_PTR(skel->links.test_kprobe_override, "bpf_program__attach_kprobe"))
+		goto cleanup;
+
+	err = prctl(0xffff, 0);
+	ASSERT_EQ(err, 123, "err");
+
+cleanup:
+	kprobe_multi_override__destroy(skel);
+}
+
 #ifdef __x86_64__
 static void test_attach_write_ctx(void)
 {
@@ -597,6 +639,8 @@ void test_kprobe_multi_test(void)
 		test_attach_api_fails();
 	if (test__start_subtest("attach_override"))
 		test_attach_override();
+	if (test__start_subtest("override"))
+		test_override();
 	if (test__start_subtest("session"))
 		test_session_skel_api();
 	if (test__start_subtest("session_cookie"))
diff --git a/tools/testing/selftests/bpf/progs/kprobe_multi_override.c b/tools/testing/selftests/bpf/progs/kprobe_multi_override.c
index 28f8487c9059..14f39fa6d515 100644
--- a/tools/testing/selftests/bpf/progs/kprobe_multi_override.c
+++ b/tools/testing/selftests/bpf/progs/kprobe_multi_override.c
@@ -5,9 +5,24 @@
 
 char _license[] SEC("license") = "GPL";
 
+int pid = 0;
+
 SEC("kprobe.multi")
 int test_override(struct pt_regs *ctx)
 {
+	if (bpf_get_current_pid_tgid() >> 32 != pid)
+		return 0;
+
+	bpf_override_return(ctx, 123);
+	return 0;
+}
+
+SEC("kprobe")
+int test_kprobe_override(struct pt_regs *ctx)
+{
+	if (bpf_get_current_pid_tgid() >> 32 != pid)
+		return 0;
+
 	bpf_override_return(ctx, 123);
 	return 0;
 }
diff --git a/tools/testing/selftests/bpf/trace_helpers.h b/tools/testing/selftests/bpf/trace_helpers.h
index 9437bdd4afa5..a5576b2dfc26 100644
--- a/tools/testing/selftests/bpf/trace_helpers.h
+++ b/tools/testing/selftests/bpf/trace_helpers.h
@@ -4,6 +4,18 @@
 
 #include <bpf/libbpf.h>
 
+#ifdef __x86_64__
+#define SYS_PREFIX "__x64_"
+#elif defined(__s390x__)
+#define SYS_PREFIX "__s390x_"
+#elif defined(__aarch64__)
+#define SYS_PREFIX "__arm64_"
+#elif defined(__riscv)
+#define SYS_PREFIX "__riscv_"
+#else
+#define SYS_PREFIX ""
+#endif
+
 #define __ALIGN_MASK(x, mask)	(((x)+(mask))&~(mask))
 #define ALIGN(x, a)		__ALIGN_MASK(x, (typeof(x))(a)-1)
 
-- 
2.52.0


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

* Re: [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
  2026-01-07  9:32 [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Jiri Olsa
  2026-01-07  9:32 ` [PATCH bpf-next 2/2] selftests/bpf: Add test for bpf_override_return helper Jiri Olsa
@ 2026-01-07 14:16 ` Will Deacon
  2026-01-07 16:08   ` Steven Rostedt
  2026-01-07 16:03 ` Steven Rostedt
  2 siblings, 1 reply; 9+ messages in thread
From: Will Deacon @ 2026-01-07 14:16 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Masami Hiramatsu, Steven Rostedt, Mahe Tardy, Peter Zijlstra, bpf,
	linux-trace-kernel, linux-arm-kernel, x86, Yonghong Song,
	Song Liu, Andrii Nakryiko, Mark Rutland

On Wed, Jan 07, 2026 at 10:32:55AM +0100, Jiri Olsa wrote:
> Mahe reported issue with bpf_override_return helper not working when
> executed from kprobe.multi bpf program on arm.
> 
> The problem is that on arm we use alternate storage for pt_regs object
> that is passed to bpf_prog_run and if any register is changed (which
> is the case of bpf_override_return) it's not propagated back to actual
> pt_regs object.
> 
> Fixing this by introducing and calling ftrace_partial_regs_update function
> to propagate the values of changed registers (ip and stack).
> 
> Fixes: b9b55c8912ce ("tracing: Add ftrace_partial_regs() for converting ftrace_regs to pt_regs")
> Reported-by: Mahe Tardy <mahe.tardy@gmail.com>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
> v1 changes:
>  - used ftrace_partial_regs_update with comments from Steven
> 
>  arch/arm64/include/asm/ftrace.h | 24 ++++++++++++++++++++++++
>  include/linux/ftrace.h          |  3 +++
>  kernel/trace/bpf_trace.c        |  1 +
>  3 files changed, 28 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> index 1621c84f44b3..177c7bbf3b84 100644
> --- a/arch/arm64/include/asm/ftrace.h
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -157,6 +157,30 @@ ftrace_partial_regs(const struct ftrace_regs *fregs, struct pt_regs *regs)
>  	return regs;
>  }
>  
> +/*
> + * ftrace_partial_regs_update - update the original ftrace_regs from regs
> + * @fregs: The ftrace_regs to update from @regs
> + * @regs: The partial regs from ftrace_partial_regs() that was updated
> + *
> + * Some architectures have the partial regs living in the ftrace_regs
> + * structure, whereas other architectures need to make a different copy
> + * of the @regs. If a partial @regs is retrieved by ftrace_partial_regs() and
> + * if the code using @regs updates a field (like the instruction pointer or
> + * stack pointer) it may need to propagate that change to the original @fregs
> + * it retrieved the partial @regs from. Use this function to guarantee that
> + * update happens.
> + */
> +static __always_inline void
> +ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
> +{
> +	struct __arch_ftrace_regs *afregs = arch_ftrace_regs(fregs);
> +
> +	if (afregs->pc != regs->pc) {
> +		afregs->pc = regs->pc;
> +		afregs->regs[0] = regs->regs[0];
> +	}
> +}

I still don't understand why we need anything new in the arch code for this.

We've selected HAVE_ARCH_FTRACE_REGS and we implement
ftrace_regs_set_instruction_pointer() and ftrace_regs_set_return_value()
so the core code already has everything it needs to make this work
without additional arch support.

Will

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

* Re: [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
  2026-01-07  9:32 [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Jiri Olsa
  2026-01-07  9:32 ` [PATCH bpf-next 2/2] selftests/bpf: Add test for bpf_override_return helper Jiri Olsa
  2026-01-07 14:16 ` [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Will Deacon
@ 2026-01-07 16:03 ` Steven Rostedt
  2026-01-08 14:32   ` Jiri Olsa
  2 siblings, 1 reply; 9+ messages in thread
From: Steven Rostedt @ 2026-01-07 16:03 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Masami Hiramatsu, Will Deacon, Mahe Tardy, Peter Zijlstra, bpf,
	linux-trace-kernel, linux-arm-kernel, x86, Yonghong Song,
	Song Liu, Andrii Nakryiko, Mark Rutland

On Wed,  7 Jan 2026 10:32:55 +0100
Jiri Olsa <jolsa@kernel.org> wrote:

> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> index 1621c84f44b3..177c7bbf3b84 100644
> --- a/arch/arm64/include/asm/ftrace.h
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -157,6 +157,30 @@ ftrace_partial_regs(const struct ftrace_regs *fregs, struct pt_regs *regs)
>  	return regs;
>  }
>  

See my reply in the other email thread:

  https://lore.kernel.org/all/20260107105316.2b70a308@gandalf.local.home/

-- Steve


> +/*
> + * ftrace_partial_regs_update - update the original ftrace_regs from regs
> + * @fregs: The ftrace_regs to update from @regs
> + * @regs: The partial regs from ftrace_partial_regs() that was updated
> + *
> + * Some architectures have the partial regs living in the ftrace_regs
> + * structure, whereas other architectures need to make a different copy
> + * of the @regs. If a partial @regs is retrieved by ftrace_partial_regs() and
> + * if the code using @regs updates a field (like the instruction pointer or
> + * stack pointer) it may need to propagate that change to the original @fregs
> + * it retrieved the partial @regs from. Use this function to guarantee that
> + * update happens.
> + */
> +static __always_inline void
> +ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
> +{
> +	struct __arch_ftrace_regs *afregs = arch_ftrace_regs(fregs);
> +
> +	if (afregs->pc != regs->pc) {
> +		afregs->pc = regs->pc;
> +		afregs->regs[0] = regs->regs[0];
> +	}
> +}

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

* Re: [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
  2026-01-07 14:16 ` [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Will Deacon
@ 2026-01-07 16:08   ` Steven Rostedt
  2026-01-07 16:52     ` Will Deacon
  0 siblings, 1 reply; 9+ messages in thread
From: Steven Rostedt @ 2026-01-07 16:08 UTC (permalink / raw)
  To: Will Deacon
  Cc: Jiri Olsa, Masami Hiramatsu, Mahe Tardy, Peter Zijlstra, bpf,
	linux-trace-kernel, linux-arm-kernel, x86, Yonghong Song,
	Song Liu, Andrii Nakryiko, Mark Rutland

On Wed, 7 Jan 2026 14:16:05 +0000
Will Deacon <will@kernel.org> wrote:

> I still don't understand why we need anything new in the arch code for this.
> 
> We've selected HAVE_ARCH_FTRACE_REGS and we implement
> ftrace_regs_set_instruction_pointer() and ftrace_regs_set_return_value()
> so the core code already has everything it needs to make this work
> without additional arch support.

I believe the issue is that the BPF code takes a pt_regs and does the
update directly with that, and not the ftrace_regs.

I'm guessing this is due to BPF programs modifying the pt_regs directly,
and BPF programs do not yet understand ftrace_regs?

Because arm64 requires making a copy of pt_regs as the ftrace_regs has a
different layout, and the ftrace_regs is what does the changes, if the
pt_regs passed to the BPF program modifies the values it needs a way to
propagate that back to the ftrace_regs.

-- Steve

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

* Re: [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
  2026-01-07 16:08   ` Steven Rostedt
@ 2026-01-07 16:52     ` Will Deacon
  2026-01-07 17:14       ` Steven Rostedt
  0 siblings, 1 reply; 9+ messages in thread
From: Will Deacon @ 2026-01-07 16:52 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Jiri Olsa, Masami Hiramatsu, Mahe Tardy, Peter Zijlstra, bpf,
	linux-trace-kernel, linux-arm-kernel, x86, Yonghong Song,
	Song Liu, Andrii Nakryiko, Mark Rutland

On Wed, Jan 07, 2026 at 11:08:14AM -0500, Steven Rostedt wrote:
> On Wed, 7 Jan 2026 14:16:05 +0000
> Will Deacon <will@kernel.org> wrote:
> 
> > I still don't understand why we need anything new in the arch code for this.
> > 
> > We've selected HAVE_ARCH_FTRACE_REGS and we implement
> > ftrace_regs_set_instruction_pointer() and ftrace_regs_set_return_value()
> > so the core code already has everything it needs to make this work
> > without additional arch support.
> 
> I believe the issue is that the BPF code takes a pt_regs and does the
> update directly with that, and not the ftrace_regs.
> 
> I'm guessing this is due to BPF programs modifying the pt_regs directly,
> and BPF programs do not yet understand ftrace_regs?
> 
> Because arm64 requires making a copy of pt_regs as the ftrace_regs has a
> different layout, and the ftrace_regs is what does the changes, if the
> pt_regs passed to the BPF program modifies the values it needs a way to
> propagate that back to the ftrace_regs.

Sure, but isn't that exactly what selecting HAVE_ARCH_FTRACE_REGS says,
and so any other architecture (i.e. riscv) using a separate structure
will run into the same problem?

In other words, add the helper to the core code along the lines of the
diff below (purely untested, just to illustrate what I'm trying to get
at).

Will

--->8

diff --git a/include/linux/ftrace_regs.h b/include/linux/ftrace_regs.h
index 15627ceea9bc..3ebd8cdac7c6 100644
--- a/include/linux/ftrace_regs.h
+++ b/include/linux/ftrace_regs.h
@@ -33,6 +33,15 @@ struct ftrace_regs;
 #define ftrace_regs_get_frame_pointer(fregs) \
        frame_pointer(&arch_ftrace_regs(fregs)->regs)
 
+#else
+
+static __always_inline void
+ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
+{
+       ftrace_regs_set_instruction_pointer(fregs, instruction_pointer(regs));
+       ftrace_regs_set_return_value(fregs, regs_return_value(regs));
+}
+
 #endif /* HAVE_ARCH_FTRACE_REGS */
 
 /* This can be overridden by the architectures */


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

* Re: [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
  2026-01-07 16:52     ` Will Deacon
@ 2026-01-07 17:14       ` Steven Rostedt
  2026-01-08  9:20         ` Jiri Olsa
  0 siblings, 1 reply; 9+ messages in thread
From: Steven Rostedt @ 2026-01-07 17:14 UTC (permalink / raw)
  To: Will Deacon
  Cc: Jiri Olsa, Masami Hiramatsu, Mahe Tardy, Peter Zijlstra, bpf,
	linux-trace-kernel, linux-arm-kernel, x86, Yonghong Song,
	Song Liu, Andrii Nakryiko, Mark Rutland

On Wed, 7 Jan 2026 16:52:52 +0000
Will Deacon <will@kernel.org> wrote:

> diff --git a/include/linux/ftrace_regs.h b/include/linux/ftrace_regs.h
> index 15627ceea9bc..3ebd8cdac7c6 100644
> --- a/include/linux/ftrace_regs.h
> +++ b/include/linux/ftrace_regs.h
> @@ -33,6 +33,15 @@ struct ftrace_regs;
>  #define ftrace_regs_get_frame_pointer(fregs) \
>         frame_pointer(&arch_ftrace_regs(fregs)->regs)
>  
> +#else
> +
> +static __always_inline void
> +ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
> +{
> +       ftrace_regs_set_instruction_pointer(fregs, instruction_pointer(regs));
> +       ftrace_regs_set_return_value(fregs, regs_return_value(regs));
> +}
> +
>  #endif /* HAVE_ARCH_FTRACE_REGS */
>  
>  /* This can be overridden by the architectures */

Hmm, maybe that would work. Of course you forgot to add the helper for the
!HAVE_ARCH_FTRACE_REGS case ;-)

-- Steve

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

* Re: [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
  2026-01-07 17:14       ` Steven Rostedt
@ 2026-01-08  9:20         ` Jiri Olsa
  0 siblings, 0 replies; 9+ messages in thread
From: Jiri Olsa @ 2026-01-08  9:20 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Will Deacon, Masami Hiramatsu, Mahe Tardy, Peter Zijlstra, bpf,
	linux-trace-kernel, linux-arm-kernel, x86, Yonghong Song,
	Song Liu, Andrii Nakryiko, Mark Rutland

On Wed, Jan 07, 2026 at 12:14:32PM -0500, Steven Rostedt wrote:
> On Wed, 7 Jan 2026 16:52:52 +0000
> Will Deacon <will@kernel.org> wrote:
> 
> > diff --git a/include/linux/ftrace_regs.h b/include/linux/ftrace_regs.h
> > index 15627ceea9bc..3ebd8cdac7c6 100644
> > --- a/include/linux/ftrace_regs.h
> > +++ b/include/linux/ftrace_regs.h
> > @@ -33,6 +33,15 @@ struct ftrace_regs;
> >  #define ftrace_regs_get_frame_pointer(fregs) \
> >         frame_pointer(&arch_ftrace_regs(fregs)->regs)
> >  
> > +#else
> > +
> > +static __always_inline void
> > +ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
> > +{
> > +       ftrace_regs_set_instruction_pointer(fregs, instruction_pointer(regs));
> > +       ftrace_regs_set_return_value(fregs, regs_return_value(regs));
> > +}
> > +
> >  #endif /* HAVE_ARCH_FTRACE_REGS */
> >  
> >  /* This can be overridden by the architectures */
> 
> Hmm, maybe that would work. Of course you forgot to add the helper for the
> !HAVE_ARCH_FTRACE_REGS case ;-)

seems to work, will send new version with that

thanks,
jirka


---
diff --git a/include/linux/ftrace_regs.h b/include/linux/ftrace_regs.h
index 15627ceea9bc..4b053eb4c9d5 100644
--- a/include/linux/ftrace_regs.h
+++ b/include/linux/ftrace_regs.h
@@ -33,6 +33,18 @@ struct ftrace_regs;
 #define ftrace_regs_get_frame_pointer(fregs) \
 	frame_pointer(&arch_ftrace_regs(fregs)->regs)
 
+static __always_inline void
+ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs) { }
+
+#else
+
+static __always_inline void
+ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
+{
+	ftrace_regs_set_instruction_pointer(fregs, instruction_pointer(regs));
+	ftrace_regs_set_return_value(fregs, regs_return_value(regs));
+}
+
 #endif /* HAVE_ARCH_FTRACE_REGS */
 
 /* This can be overridden by the architectures */
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 6e076485bf70..3a17f79b20c2 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -2564,6 +2564,7 @@ kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link,
 	old_run_ctx = bpf_set_run_ctx(&run_ctx.session_ctx.run_ctx);
 	err = bpf_prog_run(link->link.prog, regs);
 	bpf_reset_run_ctx(old_run_ctx);
+	ftrace_partial_regs_update(fregs, bpf_kprobe_multi_pt_regs_ptr());
 	rcu_read_unlock();
 
  out:

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

* Re: [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
  2026-01-07 16:03 ` Steven Rostedt
@ 2026-01-08 14:32   ` Jiri Olsa
  0 siblings, 0 replies; 9+ messages in thread
From: Jiri Olsa @ 2026-01-08 14:32 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Will Deacon, Mahe Tardy, Peter Zijlstra, bpf,
	linux-trace-kernel, linux-arm-kernel, x86, Yonghong Song,
	Song Liu, Andrii Nakryiko, Mark Rutland

On Wed, Jan 07, 2026 at 11:03:52AM -0500, Steven Rostedt wrote:
> On Wed,  7 Jan 2026 10:32:55 +0100
> Jiri Olsa <jolsa@kernel.org> wrote:
> 
> > diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> > index 1621c84f44b3..177c7bbf3b84 100644
> > --- a/arch/arm64/include/asm/ftrace.h
> > +++ b/arch/arm64/include/asm/ftrace.h
> > @@ -157,6 +157,30 @@ ftrace_partial_regs(const struct ftrace_regs *fregs, struct pt_regs *regs)
> >  	return regs;
> >  }
> >  
> 
> See my reply in the other email thread:
> 
>   https://lore.kernel.org/all/20260107105316.2b70a308@gandalf.local.home/

ah ok, thanks

jirka

> 
> -- Steve
> 
> 
> > +/*
> > + * ftrace_partial_regs_update - update the original ftrace_regs from regs
> > + * @fregs: The ftrace_regs to update from @regs
> > + * @regs: The partial regs from ftrace_partial_regs() that was updated
> > + *
> > + * Some architectures have the partial regs living in the ftrace_regs
> > + * structure, whereas other architectures need to make a different copy
> > + * of the @regs. If a partial @regs is retrieved by ftrace_partial_regs() and
> > + * if the code using @regs updates a field (like the instruction pointer or
> > + * stack pointer) it may need to propagate that change to the original @fregs
> > + * it retrieved the partial @regs from. Use this function to guarantee that
> > + * update happens.
> > + */
> > +static __always_inline void
> > +ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
> > +{
> > +	struct __arch_ftrace_regs *afregs = arch_ftrace_regs(fregs);
> > +
> > +	if (afregs->pc != regs->pc) {
> > +		afregs->pc = regs->pc;
> > +		afregs->regs[0] = regs->regs[0];
> > +	}
> > +}

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

end of thread, other threads:[~2026-01-08 14:32 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-07  9:32 [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Jiri Olsa
2026-01-07  9:32 ` [PATCH bpf-next 2/2] selftests/bpf: Add test for bpf_override_return helper Jiri Olsa
2026-01-07 14:16 ` [PATCH bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Will Deacon
2026-01-07 16:08   ` Steven Rostedt
2026-01-07 16:52     ` Will Deacon
2026-01-07 17:14       ` Steven Rostedt
2026-01-08  9:20         ` Jiri Olsa
2026-01-07 16:03 ` Steven Rostedt
2026-01-08 14:32   ` Jiri Olsa

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