Linux Trace Kernel
 help / color / mirror / Atom feed
From: "Rui Qi" <qirui.001@bytedance.com>
To: <rostedt@goodmis.org>
Cc: "Albert Ou" <aou@eecs.berkeley.edu>,
	"Alexandre Ghiti" <alex@ghiti.fr>,
	"Björn Töpel" <bjorn@rivosinc.com>,
	"Chunyan Zhang" <zhangchunyan@iscas.ac.cn>,
	"Guo Ren" <guoren@kernel.org>,
	"Jiakai Xu" <xujiakai2025@iscas.ac.cn>,
	linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org,
	linux-trace-kernel@vger.kernel.org,
	"Mark Rutland" <mark.rutland@arm.com>,
	"Masami Hiramatsu" <mhiramat@kernel.org>,
	"Mathieu Desnoyers" <mathieu.desnoyers@efficios.com>,
	"Palmer Dabbelt" <palmer@dabbelt.com>,
	"Paul Walmsley" <pjw@kernel.org>,
	"Song Shuai" <suagrfillet@gmail.com>
Subject: [PATCH 2/2] riscv: ftrace: Use frame CFA for function graph retp
Date: Sat, 19 Sep 2026 11:37:26 +0800	[thread overview]
Message-ID: <20260919033726.1361382-3-qirui.001@bytedance.com> (raw)
In-Reply-To: <20260919033726.1361382-1-qirui.001@bytedance.com>

RISC-V dynamic function graph tracing currently uses &fregs->ra for two
different purposes. As the parent argument, it is the temporary slot where
ftrace_caller saved the incoming ra. Reading that slot and replacing it
with return_to_handler is correct, because ftrace_caller reloads the slot
into the hardware ra register before returning to the traced function.

It is wrong to save the same address as the function graph retp. The retp
is not used to patch the return address later; ftrace_graph_ret_addr()
uses it as a lookup key for the shadow stack entry. Once ftrace_caller
returns, its temporary fregs frame is gone. Later stack unwinding finds
return_to_handler in the traced function's own frame, so the unwinder
cannot match a key that points back into the vanished ftrace_caller frame.

This also breaks function_get_true_parent_ip(), which looks up the
original parent with ftrace_regs_get_stack_pointer(fregs). On RISC-V that
is the saved entry SP, not &fregs->ra, so ftrace_graph_ret_addr() cannot
match the graph return entry.

Use the frame CFA as the RISC-V graph retp identity instead. The static
_mcount path derives it from &frame->ra, the dynamic ftrace path uses the
saved entry SP, and the frame-pointer unwinder uses the same CFA when
recovering graph return addresses.

Fixes: 35e61e8827ee ("riscv: ftrace: Make function graph use ftrace directly")
Signed-off-by: Rui Qi <qirui.001@bytedance.com>
---
 arch/riscv/kernel/ftrace.c     | 10 ++++++++--
 arch/riscv/kernel/stacktrace.c |  2 +-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
index be8b68514417..faad2608216f 100644
--- a/arch/riscv/kernel/ftrace.c
+++ b/arch/riscv/kernel/ftrace.c
@@ -229,11 +229,16 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * Most of this function is copied from arm64.
+ *
+ * Use the frame CFA as the RISC-V graph return address identity: static
+ * _mcount derives it from &frame->ra, dynamic ftrace uses the saved entry
+ * SP, and the unwinder tracks the same value when walking frame records.
  */
 void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 			   unsigned long frame_pointer)
 {
 	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long *retp = parent + 1;
 	unsigned long old;
 
 	if (unlikely(atomic_read(&current->tracing_graph_pause)))
@@ -245,7 +250,7 @@ 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, retp))
 		*parent = return_hooker;
 }
 
@@ -256,6 +261,7 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
 	unsigned long return_hooker = (unsigned long)&return_to_handler;
 	unsigned long frame_pointer = arch_ftrace_regs(fregs)->s0;
 	unsigned long *parent = &arch_ftrace_regs(fregs)->ra;
+	unsigned long *retp = (unsigned long *)arch_ftrace_regs(fregs)->sp;
 	unsigned long old;
 
 	if (unlikely(atomic_read(&current->tracing_graph_pause)))
@@ -267,7 +273,7 @@ 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, retp, fregs))
 		*parent = return_hooker;
 }
 #endif /* CONFIG_DYNAMIC_FTRACE */
diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c
index c7555447149b..96fb7d29ebb1 100644
--- a/arch/riscv/kernel/stacktrace.c
+++ b/arch/riscv/kernel/stacktrace.c
@@ -88,7 +88,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
 			fp = READ_ONCE_TASK_STACK(task, frame->fp);
 			pc = READ_ONCE_TASK_STACK(task, frame->ra);
 			pc = ftrace_graph_ret_addr(task, &graph_idx, pc,
-						   &frame->ra);
+						   (unsigned long *)sp);
 			if (pc >= (unsigned long)handle_exception &&
 			    pc < (unsigned long)&ret_from_exception_end) {
 				if (unlikely(!fn(arg, pc)))
-- 
2.20.1

      parent reply	other threads:[~2026-09-19  3:38 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-19  3:37 [PATCH 0/2] riscv: ftrace: use frame CFA as the function graph retp identity Rui Qi
2026-09-19  3:37 ` [PATCH 1/2] ftrace: Clarify " Rui Qi
2026-09-19  3:37 ` Rui Qi [this message]

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=20260919033726.1361382-3-qirui.001@bytedance.com \
    --to=qirui.001@bytedance.com \
    --cc=alex@ghiti.fr \
    --cc=aou@eecs.berkeley.edu \
    --cc=bjorn@rivosinc.com \
    --cc=guoren@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=mhiramat@kernel.org \
    --cc=palmer@dabbelt.com \
    --cc=pjw@kernel.org \
    --cc=rostedt@goodmis.org \
    --cc=suagrfillet@gmail.com \
    --cc=xujiakai2025@iscas.ac.cn \
    --cc=zhangchunyan@iscas.ac.cn \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox