linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/2] riscv: stacktrace: Add USER_STACKTRACE support
@ 2024-07-08  3:28 Jinjie Ruan
  2024-07-08  3:28 ` [PATCH v3 1/2] riscv: Fix fp alignment bug in perf_callchain_user() Jinjie Ruan
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Jinjie Ruan @ 2024-07-08  3:28 UTC (permalink / raw)
  To: bjorn, paul.walmsley, palmer, aou, peterz, mingo, acme, namhyung,
	mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	kan.liang, dev.mbstr, samuel.holland, linux-riscv, linux-kernel,
	linux-perf-users
  Cc: ruanjinjie

Add RISC-V USER_STACKTRACE support, and fix the fp alignment bug
in perf_callchain_user() by the way as Björn pointed out.

Changes in v3:
- Fix the fp alignment bug in perf_callchain_user().
- Remove the LTP message as Björn suggested.
- Add the userstack trace test info.

Jinjie Ruan (2):
  riscv: Fix fp alignment bug in perf_callchain_user()
  riscv: stacktrace: Add USER_STACKTRACE support

 arch/riscv/Kconfig                 |  1 +
 arch/riscv/kernel/perf_callchain.c | 46 ++----------------------------
 arch/riscv/kernel/stacktrace.c     | 43 ++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 43 deletions(-)

-- 
2.34.1


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

* [PATCH v3 1/2] riscv: Fix fp alignment bug in perf_callchain_user()
  2024-07-08  3:28 [PATCH v3 0/2] riscv: stacktrace: Add USER_STACKTRACE support Jinjie Ruan
@ 2024-07-08  3:28 ` Jinjie Ruan
  2024-07-08  3:28 ` [PATCH v3 2/2] riscv: stacktrace: Add USER_STACKTRACE support Jinjie Ruan
  2024-09-17 13:00 ` [PATCH v3 0/2] " patchwork-bot+linux-riscv
  2 siblings, 0 replies; 5+ messages in thread
From: Jinjie Ruan @ 2024-07-08  3:28 UTC (permalink / raw)
  To: bjorn, paul.walmsley, palmer, aou, peterz, mingo, acme, namhyung,
	mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	kan.liang, dev.mbstr, samuel.holland, linux-riscv, linux-kernel,
	linux-perf-users
  Cc: ruanjinjie

The standard RISC-V calling convention said:
	"The stack grows downward and the stack pointer is always
	kept 16-byte aligned".

So perf_callchain_user() should check whether 16-byte aligned for fp.

Link: https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf

Fixes: dbeb90b0c1eb ("riscv: Add perf callchain support")
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
Cc: Björn Töpel <bjorn@kernel.org>
---
 arch/riscv/kernel/perf_callchain.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/riscv/kernel/perf_callchain.c b/arch/riscv/kernel/perf_callchain.c
index 3348a61de7d9..2932791e9388 100644
--- a/arch/riscv/kernel/perf_callchain.c
+++ b/arch/riscv/kernel/perf_callchain.c
@@ -62,7 +62,7 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
 	perf_callchain_store(entry, regs->epc);
 
 	fp = user_backtrace(entry, fp, regs->ra);
-	while (fp && !(fp & 0x3) && entry->nr < entry->max_stack)
+	while (fp && !(fp & 0x7) && entry->nr < entry->max_stack)
 		fp = user_backtrace(entry, fp, 0);
 }
 
-- 
2.34.1


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

* [PATCH v3 2/2] riscv: stacktrace: Add USER_STACKTRACE support
  2024-07-08  3:28 [PATCH v3 0/2] riscv: stacktrace: Add USER_STACKTRACE support Jinjie Ruan
  2024-07-08  3:28 ` [PATCH v3 1/2] riscv: Fix fp alignment bug in perf_callchain_user() Jinjie Ruan
@ 2024-07-08  3:28 ` Jinjie Ruan
  2024-07-23  1:40   ` Jinjie Ruan
  2024-09-17 13:00 ` [PATCH v3 0/2] " patchwork-bot+linux-riscv
  2 siblings, 1 reply; 5+ messages in thread
From: Jinjie Ruan @ 2024-07-08  3:28 UTC (permalink / raw)
  To: bjorn, paul.walmsley, palmer, aou, peterz, mingo, acme, namhyung,
	mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	kan.liang, dev.mbstr, samuel.holland, linux-riscv, linux-kernel,
	linux-perf-users
  Cc: ruanjinjie

Currently, userstacktrace is unsupported for riscv. So use the
perf_callchain_user() code as blueprint to implement the
arch_stack_walk_user() which add userstacktrace support on riscv.
Meanwhile, we can use arch_stack_walk_user() to simplify the implementation
of perf_callchain_user().

A ftrace test case is shown as below:

	# cd /sys/kernel/debug/tracing
	# echo 1 > options/userstacktrace
	# echo 1 > options/sym-userobj
	# echo 1 > events/sched/sched_process_fork/enable
	# cat trace
	......
	            bash-178     [000] ...1.    97.968395: sched_process_fork: comm=bash pid=178 child_comm=bash child_pid=231
	            bash-178     [000] ...1.    97.970075: <user stack trace>
	 => /lib/libc.so.6[+0xb5090]

Also a simple perf test is ok as below:

	# perf record -e cpu-clock --call-graph fp top
	# perf report --call-graph

	.....
	[[31m  66.54%[[m     0.00%  top      [kernel.kallsyms]            [k] ret_from_exception
            |
            ---ret_from_exception
               |
               |--[[31m58.97%[[m--do_trap_ecall_u
               |          |
               |          |--[[31m17.34%[[m--__riscv_sys_read
               |          |          ksys_read
               |          |          |
               |          |           --[[31m16.88%[[m--vfs_read
               |          |                     |
               |          |                     |--[[31m10.90%[[m--seq_read

Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
Tested-by: Jinjie Ruan <ruanjinjie@huawei.com>
Cc: Björn Töpel <bjorn@kernel.org>
---
v3:
- Remove the LTP message as Björn suggested.
- Keep fp 16-bytes aligned in arch_stack_walk_user().
- Add the test info.
v2:
- Fix the cocci warning, !A || A && B is equivalent to !A || B.
---
---
 arch/riscv/Kconfig                 |  1 +
 arch/riscv/kernel/perf_callchain.c | 46 ++----------------------------
 arch/riscv/kernel/stacktrace.c     | 43 ++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 43 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 3b44e7b51436..46121dbcf750 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -194,6 +194,7 @@ config RISCV
 	select THREAD_INFO_IN_TASK
 	select TRACE_IRQFLAGS_SUPPORT
 	select UACCESS_MEMCPY if !MMU
+	select USER_STACKTRACE_SUPPORT
 	select ZONE_DMA32 if 64BIT
 
 config CLANG_SUPPORTS_DYNAMIC_FTRACE
diff --git a/arch/riscv/kernel/perf_callchain.c b/arch/riscv/kernel/perf_callchain.c
index 2932791e9388..c7468af77c66 100644
--- a/arch/riscv/kernel/perf_callchain.c
+++ b/arch/riscv/kernel/perf_callchain.c
@@ -6,37 +6,9 @@
 
 #include <asm/stacktrace.h>
 
-/*
- * Get the return address for a single stackframe and return a pointer to the
- * next frame tail.
- */
-static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
-				    unsigned long fp, unsigned long reg_ra)
+static bool fill_callchain(void *entry, unsigned long pc)
 {
-	struct stackframe buftail;
-	unsigned long ra = 0;
-	unsigned long __user *user_frame_tail =
-		(unsigned long __user *)(fp - sizeof(struct stackframe));
-
-	/* Check accessibility of one struct frame_tail beyond */
-	if (!access_ok(user_frame_tail, sizeof(buftail)))
-		return 0;
-	if (__copy_from_user_inatomic(&buftail, user_frame_tail,
-				      sizeof(buftail)))
-		return 0;
-
-	if (reg_ra != 0)
-		ra = reg_ra;
-	else
-		ra = buftail.ra;
-
-	fp = buftail.fp;
-	if (ra != 0)
-		perf_callchain_store(entry, ra);
-	else
-		return 0;
-
-	return fp;
+	return perf_callchain_store(entry, pc) == 0;
 }
 
 /*
@@ -56,19 +28,7 @@ static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
 void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
 			 struct pt_regs *regs)
 {
-	unsigned long fp = 0;
-
-	fp = regs->s0;
-	perf_callchain_store(entry, regs->epc);
-
-	fp = user_backtrace(entry, fp, regs->ra);
-	while (fp && !(fp & 0x7) && entry->nr < entry->max_stack)
-		fp = user_backtrace(entry, fp, 0);
-}
-
-static bool fill_callchain(void *entry, unsigned long pc)
-{
-	return perf_callchain_store(entry, pc) == 0;
+	arch_stack_walk_user(fill_callchain, entry, regs);
 }
 
 void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c
index 0d3f00eb0bae..5480cc11b523 100644
--- a/arch/riscv/kernel/stacktrace.c
+++ b/arch/riscv/kernel/stacktrace.c
@@ -161,3 +161,46 @@ noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry, void
 {
 	walk_stackframe(task, regs, consume_entry, cookie);
 }
+
+/*
+ * Get the return address for a single stackframe and return a pointer to the
+ * next frame tail.
+ */
+static unsigned long unwind_user_frame(stack_trace_consume_fn consume_entry,
+				       void *cookie, unsigned long fp,
+				       unsigned long reg_ra)
+{
+	struct stackframe buftail;
+	unsigned long ra = 0;
+	unsigned long __user *user_frame_tail =
+		(unsigned long __user *)(fp - sizeof(struct stackframe));
+
+	/* Check accessibility of one struct frame_tail beyond */
+	if (!access_ok(user_frame_tail, sizeof(buftail)))
+		return 0;
+	if (__copy_from_user_inatomic(&buftail, user_frame_tail,
+				      sizeof(buftail)))
+		return 0;
+
+	ra = reg_ra ? : buftail.ra;
+
+	fp = buftail.fp;
+	if (!ra || !consume_entry(cookie, ra))
+		return 0;
+
+	return fp;
+}
+
+void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
+			  const struct pt_regs *regs)
+{
+	unsigned long fp = 0;
+
+	fp = regs->s0;
+	if (!consume_entry(cookie, regs->epc))
+		return;
+
+	fp = unwind_user_frame(consume_entry, cookie, fp, regs->ra);
+	while (fp && !(fp & 0x7))
+		fp = unwind_user_frame(consume_entry, cookie, fp, 0);
+}
-- 
2.34.1


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

* Re: [PATCH v3 2/2] riscv: stacktrace: Add USER_STACKTRACE support
  2024-07-08  3:28 ` [PATCH v3 2/2] riscv: stacktrace: Add USER_STACKTRACE support Jinjie Ruan
@ 2024-07-23  1:40   ` Jinjie Ruan
  0 siblings, 0 replies; 5+ messages in thread
From: Jinjie Ruan @ 2024-07-23  1:40 UTC (permalink / raw)
  To: bjorn, paul.walmsley, palmer, aou, peterz, mingo, acme, namhyung,
	mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	kan.liang, dev.mbstr, samuel.holland, linux-riscv, linux-kernel,
	linux-perf-users



On 2024/7/8 11:28, Jinjie Ruan wrote:
> Currently, userstacktrace is unsupported for riscv. So use the
> perf_callchain_user() code as blueprint to implement the
> arch_stack_walk_user() which add userstacktrace support on riscv.
> Meanwhile, we can use arch_stack_walk_user() to simplify the implementation
> of perf_callchain_user().
> 
> A ftrace test case is shown as below:
> 
> 	# cd /sys/kernel/debug/tracing
> 	# echo 1 > options/userstacktrace
> 	# echo 1 > options/sym-userobj
> 	# echo 1 > events/sched/sched_process_fork/enable
> 	# cat trace
> 	......
> 	            bash-178     [000] ...1.    97.968395: sched_process_fork: comm=bash pid=178 child_comm=bash child_pid=231
> 	            bash-178     [000] ...1.    97.970075: <user stack trace>
> 	 => /lib/libc.so.6[+0xb5090]
> 
> Also a simple perf test is ok as below:
> 
> 	# perf record -e cpu-clock --call-graph fp top
> 	# perf report --call-graph
> 
> 	.....
> 	[[31m  66.54%[[m     0.00%  top      [kernel.kallsyms]            [k] ret_from_exception
>             |
>             ---ret_from_exception
>                |
>                |--[[31m58.97%[[m--do_trap_ecall_u
>                |          |
>                |          |--[[31m17.34%[[m--__riscv_sys_read
>                |          |          ksys_read
>                |          |          |
>                |          |           --[[31m16.88%[[m--vfs_read
>                |          |                     |
>                |          |                     |--[[31m10.90%[[m--seq_read

Gentle ping.

> 
> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
> Tested-by: Jinjie Ruan <ruanjinjie@huawei.com>
> Cc: Björn Töpel <bjorn@kernel.org>
> ---
> v3:
> - Remove the LTP message as Björn suggested.
> - Keep fp 16-bytes aligned in arch_stack_walk_user().
> - Add the test info.
> v2:
> - Fix the cocci warning, !A || A && B is equivalent to !A || B.
> ---
> ---
>  arch/riscv/Kconfig                 |  1 +
>  arch/riscv/kernel/perf_callchain.c | 46 ++----------------------------
>  arch/riscv/kernel/stacktrace.c     | 43 ++++++++++++++++++++++++++++
>  3 files changed, 47 insertions(+), 43 deletions(-)
> 
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index 3b44e7b51436..46121dbcf750 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -194,6 +194,7 @@ config RISCV
>  	select THREAD_INFO_IN_TASK
>  	select TRACE_IRQFLAGS_SUPPORT
>  	select UACCESS_MEMCPY if !MMU
> +	select USER_STACKTRACE_SUPPORT
>  	select ZONE_DMA32 if 64BIT
>  
>  config CLANG_SUPPORTS_DYNAMIC_FTRACE
> diff --git a/arch/riscv/kernel/perf_callchain.c b/arch/riscv/kernel/perf_callchain.c
> index 2932791e9388..c7468af77c66 100644
> --- a/arch/riscv/kernel/perf_callchain.c
> +++ b/arch/riscv/kernel/perf_callchain.c
> @@ -6,37 +6,9 @@
>  
>  #include <asm/stacktrace.h>
>  
> -/*
> - * Get the return address for a single stackframe and return a pointer to the
> - * next frame tail.
> - */
> -static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
> -				    unsigned long fp, unsigned long reg_ra)
> +static bool fill_callchain(void *entry, unsigned long pc)
>  {
> -	struct stackframe buftail;
> -	unsigned long ra = 0;
> -	unsigned long __user *user_frame_tail =
> -		(unsigned long __user *)(fp - sizeof(struct stackframe));
> -
> -	/* Check accessibility of one struct frame_tail beyond */
> -	if (!access_ok(user_frame_tail, sizeof(buftail)))
> -		return 0;
> -	if (__copy_from_user_inatomic(&buftail, user_frame_tail,
> -				      sizeof(buftail)))
> -		return 0;
> -
> -	if (reg_ra != 0)
> -		ra = reg_ra;
> -	else
> -		ra = buftail.ra;
> -
> -	fp = buftail.fp;
> -	if (ra != 0)
> -		perf_callchain_store(entry, ra);
> -	else
> -		return 0;
> -
> -	return fp;
> +	return perf_callchain_store(entry, pc) == 0;
>  }
>  
>  /*
> @@ -56,19 +28,7 @@ static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
>  void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
>  			 struct pt_regs *regs)
>  {
> -	unsigned long fp = 0;
> -
> -	fp = regs->s0;
> -	perf_callchain_store(entry, regs->epc);
> -
> -	fp = user_backtrace(entry, fp, regs->ra);
> -	while (fp && !(fp & 0x7) && entry->nr < entry->max_stack)
> -		fp = user_backtrace(entry, fp, 0);
> -}
> -
> -static bool fill_callchain(void *entry, unsigned long pc)
> -{
> -	return perf_callchain_store(entry, pc) == 0;
> +	arch_stack_walk_user(fill_callchain, entry, regs);
>  }
>  
>  void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
> diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c
> index 0d3f00eb0bae..5480cc11b523 100644
> --- a/arch/riscv/kernel/stacktrace.c
> +++ b/arch/riscv/kernel/stacktrace.c
> @@ -161,3 +161,46 @@ noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry, void
>  {
>  	walk_stackframe(task, regs, consume_entry, cookie);
>  }
> +
> +/*
> + * Get the return address for a single stackframe and return a pointer to the
> + * next frame tail.
> + */
> +static unsigned long unwind_user_frame(stack_trace_consume_fn consume_entry,
> +				       void *cookie, unsigned long fp,
> +				       unsigned long reg_ra)
> +{
> +	struct stackframe buftail;
> +	unsigned long ra = 0;
> +	unsigned long __user *user_frame_tail =
> +		(unsigned long __user *)(fp - sizeof(struct stackframe));
> +
> +	/* Check accessibility of one struct frame_tail beyond */
> +	if (!access_ok(user_frame_tail, sizeof(buftail)))
> +		return 0;
> +	if (__copy_from_user_inatomic(&buftail, user_frame_tail,
> +				      sizeof(buftail)))
> +		return 0;
> +
> +	ra = reg_ra ? : buftail.ra;
> +
> +	fp = buftail.fp;
> +	if (!ra || !consume_entry(cookie, ra))
> +		return 0;
> +
> +	return fp;
> +}
> +
> +void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
> +			  const struct pt_regs *regs)
> +{
> +	unsigned long fp = 0;
> +
> +	fp = regs->s0;
> +	if (!consume_entry(cookie, regs->epc))
> +		return;
> +
> +	fp = unwind_user_frame(consume_entry, cookie, fp, regs->ra);
> +	while (fp && !(fp & 0x7))
> +		fp = unwind_user_frame(consume_entry, cookie, fp, 0);
> +}

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

* Re: [PATCH v3 0/2] riscv: stacktrace: Add USER_STACKTRACE support
  2024-07-08  3:28 [PATCH v3 0/2] riscv: stacktrace: Add USER_STACKTRACE support Jinjie Ruan
  2024-07-08  3:28 ` [PATCH v3 1/2] riscv: Fix fp alignment bug in perf_callchain_user() Jinjie Ruan
  2024-07-08  3:28 ` [PATCH v3 2/2] riscv: stacktrace: Add USER_STACKTRACE support Jinjie Ruan
@ 2024-09-17 13:00 ` patchwork-bot+linux-riscv
  2 siblings, 0 replies; 5+ messages in thread
From: patchwork-bot+linux-riscv @ 2024-09-17 13:00 UTC (permalink / raw)
  To: Jinjie Ruan
  Cc: linux-riscv, bjorn, paul.walmsley, palmer, aou, peterz, mingo,
	acme, namhyung, mark.rutland, alexander.shishkin, jolsa, irogers,
	adrian.hunter, kan.liang, dev.mbstr, samuel.holland, linux-kernel,
	linux-perf-users

Hello:

This series was applied to riscv/linux.git (for-next)
by Palmer Dabbelt <palmer@rivosinc.com>:

On Mon, 8 Jul 2024 11:28:45 +0800 you wrote:
> Add RISC-V USER_STACKTRACE support, and fix the fp alignment bug
> in perf_callchain_user() by the way as Björn pointed out.
> 
> Changes in v3:
> - Fix the fp alignment bug in perf_callchain_user().
> - Remove the LTP message as Björn suggested.
> - Add the userstack trace test info.
> 
> [...]

Here is the summary with links:
  - [v3,1/2] riscv: Fix fp alignment bug in perf_callchain_user()
    https://git.kernel.org/riscv/c/22ab08955ea1
  - [v3,2/2] riscv: stacktrace: Add USER_STACKTRACE support
    https://git.kernel.org/riscv/c/1a7483318274

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2024-09-17 13:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-08  3:28 [PATCH v3 0/2] riscv: stacktrace: Add USER_STACKTRACE support Jinjie Ruan
2024-07-08  3:28 ` [PATCH v3 1/2] riscv: Fix fp alignment bug in perf_callchain_user() Jinjie Ruan
2024-07-08  3:28 ` [PATCH v3 2/2] riscv: stacktrace: Add USER_STACKTRACE support Jinjie Ruan
2024-07-23  1:40   ` Jinjie Ruan
2024-09-17 13:00 ` [PATCH v3 0/2] " patchwork-bot+linux-riscv

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