All of lore.kernel.org
 help / color / mirror / Atom feed
From: Shuai Xue <xueshuai@linux.alibaba.com>
To: Martin Kaiser <martin@kaiser.cx>
Cc: palmer@dabbelt.com, pjw@kernel.org, aou@eecs.berkeley.edu,
	alex@ghiti.fr, linux-riscv@lists.infradead.org, oleg@redhat.com,
	rostedt@goodmis.org, mhiramat@kernel.org, mark.rutland@arm.com,
	peterz@infradead.org, mingo@redhat.com, acme@kernel.org,
	namhyung@kernel.org, alexander.shishkin@linux.intel.com,
	jolsa@kernel.org, irogers@google.com, adrian.hunter@intel.com,
	james.clark@linaro.org, jpoimboe@kernel.org, jikos@kernel.org,
	mbenes@suse.cz, pmladek@suse.com, joe.lawrence@redhat.com,
	shuah@kernel.org, mpdesouza@suse.com,
	oliver.yang@linux.alibaba.com, zhuo.song@linux.alibaba.com,
	jkchen@linux.alibaba.com, linux-kernel@vger.kernel.org,
	linux-trace-kernel@vger.kernel.org,
	linux-perf-users@vger.kernel.org, live-patching@vger.kernel.org,
	linux-kselftest@vger.kernel.org
Subject: Re: [PATCH v6 5/7] riscv: stacktrace: switch to frame-pointer based unwinder
Date: Wed, 14 Oct 2026 21:09:51 +0800	[thread overview]
Message-ID: <3bd83dc6-1206-4af2-bfcf-5894b1029907@linux.alibaba.com> (raw)
In-Reply-To: <as6SEF4v6wt5GmVD@nb282.user.codasip.com>



On 10/14/26 4:18 AM, Martin Kaiser wrote:
> Thus wrote Shuai Xue (xueshuai@linux.alibaba.com):
> 
>> From: Wang Han <wanghan@linux.alibaba.com>
> 
>> Replace the open-coded frame-pointer walker in arch_stack_walk() with a
>> robust kunwind state machine, modelled on arch/arm64/kernel/stacktrace.c
>> and retargeted to the RISC-V {fp, ra} frame record convention. The new
>> walker tracks stack bounds, consumes frame records monotonically,
>> understands the metadata pt_regs records added in the previous frame
>> record metadata patch, and recovers return addresses replaced by
>> function graph tracing and kretprobes.
> 
>> This commit introduces arch_stack_walk_reliable() but does not yet
>> select HAVE_RELIABLE_STACKTRACE; that is done in a follow-up Kconfig
>> patch so this commit can be reviewed and bisected as a pure unwinder
>> replacement. Until that Kconfig change lands, livepatch is not yet
>> enabled and arch_stack_walk_reliable() has no in-tree caller.
> 
>> Three related callers are updated to keep the same frame-record
>> assumptions everywhere:
> 
>>    * Function graph tracing: the old RISC-V unwinder matched function
>>      graph return-stack entries by the saved return-address slot. That
>>      was consistent with the static mcount path, but not with the dynamic
>>      ftrace path where the parent slot is ftrace_regs::ra. Use the
>>      architectural frame pointer as the function graph return-address
>>      cookie, matching the kunwind walker.
> 
>>    * Perf callchains: route kernel callchain collection through
>>      arch_stack_walk() so perf sees the same frame-pointer unwind
>>      behaviour as dump_stack() and the upcoming livepatch path.
> 
>>    * dump_backtrace() / __get_wchan() / show_stack(): these now go
>>      through arch_stack_walk(); the explicit "Call Trace:" header is
>>      moved into dump_backtrace() to preserve the original output.
> 
>> The non-frame-pointer fallback walker is kept untouched for
>> !CONFIG_FRAME_POINTER builds.
> 
>> Assisted-by: Qoder:Qwen-3.8-MAX-Preview
>> Signed-off-by: Wang Han <wanghan@linux.alibaba.com>
>> Signed-off-by: Shuai Xue <xueshuai@linux.alibaba.com>
>> ---
>>   arch/riscv/kernel/ftrace.c         |   6 +-
>>   arch/riscv/kernel/perf_callchain.c |   2 +-
>>   arch/riscv/kernel/stacktrace.c     | 561 ++++++++++++++++++++++++-----
>>   3 files changed, 473 insertions(+), 96 deletions(-)
> 
>> diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
>> index be8b685144174..0facd824c911d 100644
>> --- a/arch/riscv/kernel/ftrace.c
>> +++ b/arch/riscv/kernel/ftrace.c
>> @@ -245,7 +245,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
>>   	 */
>>   	old = *parent;
> 
>> -	if (!function_graph_enter(old, self_addr, frame_pointer, parent))
>> +	if (!function_graph_enter(old, self_addr, frame_pointer,
>> +				  (void *)frame_pointer))
>>   		*parent = return_hooker;
>>   }
> 
>> @@ -267,7 +268,8 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
>>   	 */
>>   	old = *parent;
> 
>> -	if (!function_graph_enter_regs(old, ip, frame_pointer, parent, fregs))
>> +	if (!function_graph_enter_regs(old, ip, frame_pointer,
>> +				       (void *)frame_pointer, fregs))
>>   		*parent = return_hooker;
>>   }
> 
> 
> Are these two changes fixing a bug in the current code (that is independent
> from the rest of this patch)?
> 
> Without your changes, function_graph_enter_regs writes a struct ftrace_ret_stack
> with retp == the saved ra.
> 
> And the only place where retp is fetched and checked is
> 
> function_get_true_parent_ip
>     ftrace_graph_ret_addr(..., (uintptr_t *)ftrace_regs_get_stack_pointer(fregs));
> 
> The stored retp is checked against the stack pointer.
> 
> Your changes store fp instead of ra, this seems the right thing to do. (And
> it's in line with other archs.)
> 
> Should those two changes be in a separate patch (that can be backported to
> stable kernels)?

Hi, Martin,

Thanks for the sharp question.

You are right that the stored cookie is broken. What
ftrace_graph_func() passes as retp is &arch_ftrace_regs(fregs)->ra,
i.e. the slot inside the transient ftrace trampoline frame, which is
popped as soon as the callback returns. That has been the case since
35e61e8827ee8 ("riscv: ftrace: Make function graph use ftrace
directly") introduced ftrace_graph_func() in v6.8. (The code was
copied from arm64's ftrace_graph_func(), but arm64 passes
(void *)frame_pointer there - see 41705c4262aac for the current
shape.)

Since distro kernels only ever use the dynamic path, the net effect
is that the shadow stack is never consulted during unwinding:
whenever the function graph tracer is running, dump_stack(), perf
callchains and __get_wchan() report return_to_handler instead of the
real caller.

I will split these two changes into a separate patch and cc stable.

Thanks.
Shuai

WARNING: multiple messages have this Message-ID (diff)
From: Shuai Xue <xueshuai@linux.alibaba.com>
To: Martin Kaiser <martin@kaiser.cx>
Cc: palmer@dabbelt.com, pjw@kernel.org, aou@eecs.berkeley.edu,
	alex@ghiti.fr, linux-riscv@lists.infradead.org, oleg@redhat.com,
	rostedt@goodmis.org, mhiramat@kernel.org, mark.rutland@arm.com,
	peterz@infradead.org, mingo@redhat.com, acme@kernel.org,
	namhyung@kernel.org, alexander.shishkin@linux.intel.com,
	jolsa@kernel.org, irogers@google.com, adrian.hunter@intel.com,
	james.clark@linaro.org, jpoimboe@kernel.org, jikos@kernel.org,
	mbenes@suse.cz, pmladek@suse.com, joe.lawrence@redhat.com,
	shuah@kernel.org, mpdesouza@suse.com,
	oliver.yang@linux.alibaba.com, zhuo.song@linux.alibaba.com,
	jkchen@linux.alibaba.com, linux-kernel@vger.kernel.org,
	linux-trace-kernel@vger.kernel.org,
	linux-perf-users@vger.kernel.org, live-patching@vger.kernel.org,
	linux-kselftest@vger.kernel.org
Subject: Re: [PATCH v6 5/7] riscv: stacktrace: switch to frame-pointer based unwinder
Date: Wed, 14 Oct 2026 21:09:51 +0800	[thread overview]
Message-ID: <3bd83dc6-1206-4af2-bfcf-5894b1029907@linux.alibaba.com> (raw)
In-Reply-To: <as6SEF4v6wt5GmVD@nb282.user.codasip.com>



On 10/14/26 4:18 AM, Martin Kaiser wrote:
> Thus wrote Shuai Xue (xueshuai@linux.alibaba.com):
> 
>> From: Wang Han <wanghan@linux.alibaba.com>
> 
>> Replace the open-coded frame-pointer walker in arch_stack_walk() with a
>> robust kunwind state machine, modelled on arch/arm64/kernel/stacktrace.c
>> and retargeted to the RISC-V {fp, ra} frame record convention. The new
>> walker tracks stack bounds, consumes frame records monotonically,
>> understands the metadata pt_regs records added in the previous frame
>> record metadata patch, and recovers return addresses replaced by
>> function graph tracing and kretprobes.
> 
>> This commit introduces arch_stack_walk_reliable() but does not yet
>> select HAVE_RELIABLE_STACKTRACE; that is done in a follow-up Kconfig
>> patch so this commit can be reviewed and bisected as a pure unwinder
>> replacement. Until that Kconfig change lands, livepatch is not yet
>> enabled and arch_stack_walk_reliable() has no in-tree caller.
> 
>> Three related callers are updated to keep the same frame-record
>> assumptions everywhere:
> 
>>    * Function graph tracing: the old RISC-V unwinder matched function
>>      graph return-stack entries by the saved return-address slot. That
>>      was consistent with the static mcount path, but not with the dynamic
>>      ftrace path where the parent slot is ftrace_regs::ra. Use the
>>      architectural frame pointer as the function graph return-address
>>      cookie, matching the kunwind walker.
> 
>>    * Perf callchains: route kernel callchain collection through
>>      arch_stack_walk() so perf sees the same frame-pointer unwind
>>      behaviour as dump_stack() and the upcoming livepatch path.
> 
>>    * dump_backtrace() / __get_wchan() / show_stack(): these now go
>>      through arch_stack_walk(); the explicit "Call Trace:" header is
>>      moved into dump_backtrace() to preserve the original output.
> 
>> The non-frame-pointer fallback walker is kept untouched for
>> !CONFIG_FRAME_POINTER builds.
> 
>> Assisted-by: Qoder:Qwen-3.8-MAX-Preview
>> Signed-off-by: Wang Han <wanghan@linux.alibaba.com>
>> Signed-off-by: Shuai Xue <xueshuai@linux.alibaba.com>
>> ---
>>   arch/riscv/kernel/ftrace.c         |   6 +-
>>   arch/riscv/kernel/perf_callchain.c |   2 +-
>>   arch/riscv/kernel/stacktrace.c     | 561 ++++++++++++++++++++++++-----
>>   3 files changed, 473 insertions(+), 96 deletions(-)
> 
>> diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
>> index be8b685144174..0facd824c911d 100644
>> --- a/arch/riscv/kernel/ftrace.c
>> +++ b/arch/riscv/kernel/ftrace.c
>> @@ -245,7 +245,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
>>   	 */
>>   	old = *parent;
> 
>> -	if (!function_graph_enter(old, self_addr, frame_pointer, parent))
>> +	if (!function_graph_enter(old, self_addr, frame_pointer,
>> +				  (void *)frame_pointer))
>>   		*parent = return_hooker;
>>   }
> 
>> @@ -267,7 +268,8 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
>>   	 */
>>   	old = *parent;
> 
>> -	if (!function_graph_enter_regs(old, ip, frame_pointer, parent, fregs))
>> +	if (!function_graph_enter_regs(old, ip, frame_pointer,
>> +				       (void *)frame_pointer, fregs))
>>   		*parent = return_hooker;
>>   }
> 
> 
> Are these two changes fixing a bug in the current code (that is independent
> from the rest of this patch)?
> 
> Without your changes, function_graph_enter_regs writes a struct ftrace_ret_stack
> with retp == the saved ra.
> 
> And the only place where retp is fetched and checked is
> 
> function_get_true_parent_ip
>     ftrace_graph_ret_addr(..., (uintptr_t *)ftrace_regs_get_stack_pointer(fregs));
> 
> The stored retp is checked against the stack pointer.
> 
> Your changes store fp instead of ra, this seems the right thing to do. (And
> it's in line with other archs.)
> 
> Should those two changes be in a separate patch (that can be backported to
> stable kernels)?

Hi, Martin,

Thanks for the sharp question.

You are right that the stored cookie is broken. What
ftrace_graph_func() passes as retp is &arch_ftrace_regs(fregs)->ra,
i.e. the slot inside the transient ftrace trampoline frame, which is
popped as soon as the callback returns. That has been the case since
35e61e8827ee8 ("riscv: ftrace: Make function graph use ftrace
directly") introduced ftrace_graph_func() in v6.8. (The code was
copied from arm64's ftrace_graph_func(), but arm64 passes
(void *)frame_pointer there - see 41705c4262aac for the current
shape.)

Since distro kernels only ever use the dynamic path, the net effect
is that the shadow stack is never consulted during unwinding:
whenever the function graph tracer is running, dump_stack(), perf
callchains and __get_wchan() report return_to_handler instead of the
real caller.

I will split these two changes into a separate patch and cc stable.

Thanks.
Shuai

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

  reply	other threads:[~2026-10-14 13:10 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-14  9:26 [PATCH v6 0/7] riscv: Add reliable stack unwinding for livepatch Shuai Xue
2026-09-14  9:26 ` Shuai Xue
2026-09-14  9:26 ` [PATCH v6 1/7] riscv: stacktrace: Add frame record metadata Shuai Xue
2026-09-14  9:26   ` Shuai Xue
2026-09-14  9:40   ` sashiko-bot
2026-09-14  9:26 ` [PATCH v6 2/7] riscv: stacktrace: disable KASAN and KCOV instrumentation for stacktrace.o Shuai Xue
2026-09-14  9:26   ` Shuai Xue
2026-09-14  9:32   ` sashiko-bot
2026-09-14  9:26 ` [PATCH v6 3/7] riscv: ftrace: always preserve s0 in dynamic ftrace register frame Shuai Xue
2026-09-14  9:26   ` Shuai Xue
2026-09-14  9:32   ` sashiko-bot
2026-09-14  9:26 ` [PATCH v6 4/7] riscv: stacktrace: introduce stack-bound tracking helpers Shuai Xue
2026-09-14  9:26   ` Shuai Xue
2026-09-14  9:33   ` sashiko-bot
2026-09-14  9:26 ` [PATCH v6 5/7] riscv: stacktrace: switch to frame-pointer based unwinder Shuai Xue
2026-09-14  9:26   ` Shuai Xue
2026-09-14  9:39   ` sashiko-bot
2026-10-09 18:59   ` Karl Mehltretter
2026-10-09 18:59     ` Karl Mehltretter
2026-10-10  3:38     ` Shuai Xue
2026-10-10  3:38       ` Shuai Xue
2026-10-13 20:18   ` Martin Kaiser
2026-10-13 20:18     ` Martin Kaiser
2026-10-14 13:09     ` Shuai Xue [this message]
2026-10-14 13:09       ` Shuai Xue
2026-09-14  9:26 ` [PATCH v6 6/7] riscv: Kconfig: enable HAVE_RELIABLE_STACKTRACE and HAVE_LIVEPATCH Shuai Xue
2026-09-14  9:26   ` Shuai Xue
2026-09-14  9:38   ` sashiko-bot
2026-09-14  9:26 ` [PATCH v6 7/7] selftests/livepatch: Add RISC-V syscall wrapper prefix Shuai Xue
2026-09-14  9:26   ` Shuai Xue
2026-09-14  9:38   ` sashiko-bot
2026-09-29  7:28 ` [PATCH v6 0/7] riscv: Add reliable stack unwinding for livepatch Martin Kaiser
2026-09-29  7:28   ` Martin Kaiser
2026-10-08 11:42   ` Shuai Xue
2026-10-08 11:42     ` Shuai Xue
2026-10-12  8:44     ` Martin Kaiser
2026-10-12  8:44       ` Martin Kaiser

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=3bd83dc6-1206-4af2-bfcf-5894b1029907@linux.alibaba.com \
    --to=xueshuai@linux.alibaba.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alex@ghiti.fr \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=aou@eecs.berkeley.edu \
    --cc=irogers@google.com \
    --cc=james.clark@linaro.org \
    --cc=jikos@kernel.org \
    --cc=jkchen@linux.alibaba.com \
    --cc=joe.lawrence@redhat.com \
    --cc=jolsa@kernel.org \
    --cc=jpoimboe@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=martin@kaiser.cx \
    --cc=mbenes@suse.cz \
    --cc=mhiramat@kernel.org \
    --cc=mingo@redhat.com \
    --cc=mpdesouza@suse.com \
    --cc=namhyung@kernel.org \
    --cc=oleg@redhat.com \
    --cc=oliver.yang@linux.alibaba.com \
    --cc=palmer@dabbelt.com \
    --cc=peterz@infradead.org \
    --cc=pjw@kernel.org \
    --cc=pmladek@suse.com \
    --cc=rostedt@goodmis.org \
    --cc=shuah@kernel.org \
    --cc=zhuo.song@linux.alibaba.com \
    /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.