From: Steven Rostedt <rostedt@kernel.org>
To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
bpf@vger.kernel.org, x86@kernel.org
Cc: Masami Hiramatsu <mhiramat@kernel.org>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
Josh Poimboeuf <jpoimboe@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@kernel.org>, Jiri Olsa <jolsa@kernel.org>,
Namhyung Kim <namhyung@kernel.org>,
Thomas Gleixner <tglx@linutronix.de>,
Andrii Nakryiko <andrii@kernel.org>,
Indu Bhagat <indu.bhagat@oracle.com>,
"Jose E. Marchesi" <jemarch@gnu.org>,
Beau Belgrave <beaub@linux.microsoft.com>,
Jens Remus <jremus@linux.ibm.com>,
Linus Torvalds <torvalds@linux-foundation.org>,
Andrew Morton <akpm@linux-foundation.org>,
Jens Axboe <axboe@kernel.dk>, Florian Weimer <fweimer@redhat.com>,
Sam James <sam@gentoo.org>
Subject: [PATCH v13 02/14] unwind_user: Add frame pointer support
Date: Mon, 07 Jul 2025 21:22:41 -0400 [thread overview]
Message-ID: <20250708012357.982692711@kernel.org> (raw)
In-Reply-To: 20250708012239.268642741@kernel.org
From: Josh Poimboeuf <jpoimboe@kernel.org>
Add optional support for user space frame pointer unwinding. If
supported, the arch needs to enable CONFIG_HAVE_UNWIND_USER_FP and
define ARCH_INIT_USER_FP_FRAME.
By encoding the frame offsets in struct unwind_user_frame, much of this
code can also be reused for future unwinder implementations like sframe.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Co-developed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
Changes since v12: https://lore.kernel.org/20250701005450.888492528@goodmis.org
- Added test when use_fp is true to make sure fp < sp (Jens Remus)
- Make sure the address read is word aligned (Linus Torvalds)
arch/Kconfig | 4 ++
include/asm-generic/Kbuild | 1 +
include/asm-generic/unwind_user.h | 5 +++
include/linux/unwind_user.h | 5 +++
include/linux/unwind_user_types.h | 1 +
kernel/unwind/user.c | 65 ++++++++++++++++++++++++++++++-
6 files changed, 79 insertions(+), 2 deletions(-)
create mode 100644 include/asm-generic/unwind_user.h
diff --git a/arch/Kconfig b/arch/Kconfig
index ea59e5d7cc69..8e3fd723bd74 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -438,6 +438,10 @@ config HAVE_HARDLOCKUP_DETECTOR_ARCH
config UNWIND_USER
bool
+config HAVE_UNWIND_USER_FP
+ bool
+ select UNWIND_USER
+
config HAVE_PERF_REGS
bool
help
diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild
index 8675b7b4ad23..295c94a3ccc1 100644
--- a/include/asm-generic/Kbuild
+++ b/include/asm-generic/Kbuild
@@ -59,6 +59,7 @@ mandatory-y += tlbflush.h
mandatory-y += topology.h
mandatory-y += trace_clock.h
mandatory-y += uaccess.h
+mandatory-y += unwind_user.h
mandatory-y += vermagic.h
mandatory-y += vga.h
mandatory-y += video.h
diff --git a/include/asm-generic/unwind_user.h b/include/asm-generic/unwind_user.h
new file mode 100644
index 000000000000..b8882b909944
--- /dev/null
+++ b/include/asm-generic/unwind_user.h
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_GENERIC_UNWIND_USER_H
+#define _ASM_GENERIC_UNWIND_USER_H
+
+#endif /* _ASM_GENERIC_UNWIND_USER_H */
diff --git a/include/linux/unwind_user.h b/include/linux/unwind_user.h
index 1d77bed8de2c..7f7282516bf5 100644
--- a/include/linux/unwind_user.h
+++ b/include/linux/unwind_user.h
@@ -3,6 +3,11 @@
#define _LINUX_UNWIND_USER_H
#include <linux/unwind_user_types.h>
+#include <asm/unwind_user.h>
+
+#ifndef ARCH_INIT_USER_FP_FRAME
+ #define ARCH_INIT_USER_FP_FRAME
+#endif
int unwind_user(struct unwind_stacktrace *trace, unsigned int max_entries);
diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_types.h
index 6ed1b4ae74e1..65bd070eb6b0 100644
--- a/include/linux/unwind_user_types.h
+++ b/include/linux/unwind_user_types.h
@@ -6,6 +6,7 @@
enum unwind_user_type {
UNWIND_USER_TYPE_NONE,
+ UNWIND_USER_TYPE_FP,
};
struct unwind_stacktrace {
diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c
index d0cf3ee2706d..62b3ef37d71b 100644
--- a/kernel/unwind/user.c
+++ b/kernel/unwind/user.c
@@ -6,13 +6,71 @@
#include <linux/sched.h>
#include <linux/sched/task_stack.h>
#include <linux/unwind_user.h>
+#include <linux/uaccess.h>
+
+static struct unwind_user_frame fp_frame = {
+ ARCH_INIT_USER_FP_FRAME
+};
+
+static inline bool fp_state(struct unwind_user_state *state)
+{
+ return IS_ENABLED(CONFIG_HAVE_UNWIND_USER_FP) &&
+ state->type == UNWIND_USER_TYPE_FP;
+}
#define for_each_user_frame(state) \
for (unwind_user_start(state); !(state)->done; unwind_user_next(state))
static int unwind_user_next(struct unwind_user_state *state)
{
- /* no implementation yet */
+ struct unwind_user_frame *frame;
+ unsigned long cfa = 0, fp, ra = 0;
+ unsigned int shift;
+
+ if (state->done)
+ return -EINVAL;
+
+ if (fp_state(state))
+ frame = &fp_frame;
+ else
+ goto done;
+
+ if (frame->use_fp) {
+ if (state->fp < state->sp)
+ goto done;
+ cfa = state->fp;
+ } else {
+ cfa = state->sp;
+ }
+
+ /* Get the Canonical Frame Address (CFA) */
+ cfa += frame->cfa_off;
+
+ /* stack going in wrong direction? */
+ if (cfa <= state->sp)
+ goto done;
+
+ /* Make sure that the address is word aligned */
+ shift = sizeof(long) == 4 ? 2 : 3;
+ if ((cfa + frame->ra_off) & ((1 << shift) - 1))
+ goto done;
+
+ /* Find the Return Address (RA) */
+ if (get_user(ra, (unsigned long *)(cfa + frame->ra_off)))
+ goto done;
+
+ if (frame->fp_off && get_user(fp, (unsigned long __user *)(cfa + frame->fp_off)))
+ goto done;
+
+ state->ip = ra;
+ state->sp = cfa;
+ if (frame->fp_off)
+ state->fp = fp;
+
+ return 0;
+
+done:
+ state->done = true;
return -EINVAL;
}
@@ -27,7 +85,10 @@ static int unwind_user_start(struct unwind_user_state *state)
return -EINVAL;
}
- state->type = UNWIND_USER_TYPE_NONE;
+ if (IS_ENABLED(CONFIG_HAVE_UNWIND_USER_FP))
+ state->type = UNWIND_USER_TYPE_FP;
+ else
+ state->type = UNWIND_USER_TYPE_NONE;
state->ip = instruction_pointer(regs);
state->sp = user_stack_pointer(regs);
--
2.47.2
next prev parent reply other threads:[~2025-07-08 1:23 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-08 1:22 [PATCH v13 00/14] unwind_user: x86: Deferred unwinding infrastructure Steven Rostedt
2025-07-08 1:22 ` [PATCH v13 01/14] unwind_user: Add user space unwinding API Steven Rostedt
2025-07-08 1:22 ` Steven Rostedt [this message]
2025-07-09 10:01 ` [PATCH v13 02/14] unwind_user: Add frame pointer support Jens Remus
2025-07-10 12:28 ` Jens Remus
2025-07-10 15:21 ` Steven Rostedt
2025-07-10 15:41 ` Jens Remus
2025-07-10 17:08 ` Steven Rostedt
2025-07-14 12:52 ` Jens Remus
2025-07-08 1:22 ` [PATCH v13 03/14] unwind_user: Add compat mode " Steven Rostedt
2025-07-08 1:22 ` [PATCH v13 04/14] unwind_user/deferred: Add unwind_user_faultable() Steven Rostedt
2025-07-08 1:22 ` [PATCH v13 05/14] unwind_user/deferred: Add unwind cache Steven Rostedt
2025-07-08 1:22 ` [PATCH v13 06/14] unwind_user/deferred: Add deferred unwinding interface Steven Rostedt
2025-07-08 1:22 ` [PATCH v13 07/14] unwind_user/deferred: Make unwind deferral requests NMI-safe Steven Rostedt
2025-07-14 13:29 ` Peter Zijlstra
2025-07-14 14:19 ` Steven Rostedt
2025-07-14 15:05 ` Peter Zijlstra
2025-07-14 15:11 ` Steven Rostedt
2025-07-15 9:09 ` Peter Zijlstra
2025-07-15 12:35 ` Steven Rostedt
2025-07-08 1:22 ` [PATCH v13 08/14] unwind deferred: Use bitmask to determine which callbacks to call Steven Rostedt
2025-07-08 1:22 ` [PATCH v13 09/14] unwind deferred: Use SRCU unwind_deferred_task_work() Steven Rostedt
2025-07-14 13:56 ` Peter Zijlstra
2025-07-14 14:21 ` Steven Rostedt
2025-07-14 15:03 ` Peter Zijlstra
2025-07-08 1:22 ` [PATCH v13 10/14] unwind: Clear unwind_mask on exit back to user space Steven Rostedt
2025-07-15 10:29 ` Peter Zijlstra
2025-07-15 12:49 ` Steven Rostedt
2025-07-15 18:06 ` Steven Rostedt
2025-07-15 18:10 ` Steven Rostedt
2025-07-15 18:26 ` Steven Rostedt
2025-07-15 19:04 ` Peter Zijlstra
2025-07-15 19:01 ` Peter Zijlstra
2025-07-15 17:20 ` Steven Rostedt
2025-07-15 19:07 ` Peter Zijlstra
2025-07-15 22:01 ` Steven Rostedt
2025-07-16 18:26 ` Steven Rostedt
2025-07-16 18:33 ` Steven Rostedt
2025-07-16 19:25 ` Steven Rostedt
2025-07-08 1:22 ` [PATCH v13 11/14] unwind: Add USED bit to only have one conditional on way " Steven Rostedt
2025-07-08 1:22 ` [PATCH v13 12/14] unwind: Finish up unwind when a task exits Steven Rostedt
2025-07-08 1:22 ` [PATCH v13 13/14] unwind_user/x86: Enable frame pointer unwinding on x86 Steven Rostedt
2025-07-11 8:43 ` David Laight
2025-07-11 16:11 ` Steven Rostedt
2025-07-08 1:22 ` [PATCH v13 14/14] unwind_user/x86: Enable compat mode " Steven Rostedt
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=20250708012357.982692711@kernel.org \
--to=rostedt@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=andrii@kernel.org \
--cc=axboe@kernel.dk \
--cc=beaub@linux.microsoft.com \
--cc=bpf@vger.kernel.org \
--cc=fweimer@redhat.com \
--cc=indu.bhagat@oracle.com \
--cc=jemarch@gnu.org \
--cc=jolsa@kernel.org \
--cc=jpoimboe@kernel.org \
--cc=jremus@linux.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mhiramat@kernel.org \
--cc=mingo@kernel.org \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=sam@gentoo.org \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
--cc=x86@kernel.org \
/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.