Thread (13 messages) flat view 13 messages, 1 author, 2026-01-27
STALE221d

Revision v4 of 4 in this series.

Revisions (4)
  1. v1 [diff vs current]
  2. v2 [diff vs current]
  3. v3 [diff vs current]
  4. v4 current

[PATCH v4 11/12] unwind_user/fp: Use arch-specific helper to initialize FP frame

From: Jens Remus <hidden>
Date: 2026-01-27 15:20:00
Also in: bpf, linux-s390, lkml
Subsystem: the rest, userspace stack unwinding, x86 architecture (32-bit and 64-bit), x86 stack unwinding · Maintainers: Linus Torvalds, Josh Poimboeuf, Steven Rostedt, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, Peter Zijlstra

This enables more sophisticated initialization of the FP frame, for
instance to implement support for unwinding of user space using back
chain on s390 with a subsequent commit.

Signed-off-by: Jens Remus <redacted>
---

Notes (jremus):
    Changes in v4:
    - Remove superfluous unwind_user_fp_get_frame defines.
    
    Changes in RFC v3:
    - New patch.  Prerequirement to implement unwind user fp using back
      chain on s390.

 arch/x86/include/asm/unwind_user.h | 19 ++++++++++++++++---
 include/linux/unwind_user.h        | 19 ++++++-------------
 kernel/unwind/user.c               | 16 ++++------------
 3 files changed, 26 insertions(+), 28 deletions(-)
diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwind_user.h
index 0650bcfae461..f5e9fbcdae28 100644
--- a/arch/x86/include/asm/unwind_user.h
+++ b/arch/x86/include/asm/unwind_user.h
@@ -84,11 +84,24 @@ static inline int unwind_user_get_reg(unsigned long *val, unsigned int regnum)
 	.sp_off		= 0,				\
 	.outermost	= false,
 
-static inline bool unwind_user_at_function_start(struct pt_regs *regs)
+static inline int unwind_user_fp_get_frame(struct unwind_user_state *state,
+					   struct unwind_user_frame *frame)
 {
-	return is_uprobe_at_func_entry(regs);
+	struct pt_regs *regs = task_pt_regs(current);
+
+	if (state->topmost && is_uprobe_at_func_entry(regs)) {
+		const struct unwind_user_frame fp_entry_frame = {
+			ARCH_INIT_USER_FP_ENTRY_FRAME(state->ws)
+		};
+		*frame = fp_entry_frame;
+	} else {
+		const struct unwind_user_frame fp_frame = {
+			ARCH_INIT_USER_FP_FRAME(state->ws)
+		};
+		*frame = fp_frame;
+	}
+	return 0;
 }
-#define unwind_user_at_function_start unwind_user_at_function_start
 
 #endif /* CONFIG_HAVE_UNWIND_USER_FP */
 
diff --git a/include/linux/unwind_user.h b/include/linux/unwind_user.h
index 92cdf38c8ade..f65b0573b3a5 100644
--- a/include/linux/unwind_user.h
+++ b/include/linux/unwind_user.h
@@ -7,21 +7,14 @@
 
 #ifndef CONFIG_HAVE_UNWIND_USER_FP
 
-#define ARCH_INIT_USER_FP_FRAME(ws)
-
-#endif
-
-#ifndef ARCH_INIT_USER_FP_ENTRY_FRAME
-#define ARCH_INIT_USER_FP_ENTRY_FRAME(ws)
-#endif
-
-#ifndef unwind_user_at_function_start
-static inline bool unwind_user_at_function_start(struct pt_regs *regs)
+static inline int unwind_user_fp_get_frame(struct unwind_user_state *state,
+					   struct unwind_user_frame *frame)
 {
-	return false;
+	WARN_ON_ONCE(1);
+	return -EINVAL;
 }
-#define unwind_user_at_function_start unwind_user_at_function_start
-#endif
+
+#endif /* CONFIG_HAVE_UNWIND_USER_FP */
 
 #ifndef unwind_user_get_ra_reg
 static inline int unwind_user_get_ra_reg(unsigned long *val)
diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c
index 036328cb9ee8..a64ceb4a2bf6 100644
--- a/kernel/unwind/user.c
+++ b/kernel/unwind/user.c
@@ -135,19 +135,11 @@ static int unwind_user_next_common(struct unwind_user_state *state,
 
 static int unwind_user_next_fp(struct unwind_user_state *state)
 {
-	struct pt_regs *regs = task_pt_regs(current);
-
-	if (state->topmost && unwind_user_at_function_start(regs)) {
-		const struct unwind_user_frame fp_entry_frame = {
-			ARCH_INIT_USER_FP_ENTRY_FRAME(state->ws)
-		};
-		return unwind_user_next_common(state, &fp_entry_frame);
-	}
+	struct unwind_user_frame frame;
 
-	const struct unwind_user_frame fp_frame = {
-		ARCH_INIT_USER_FP_FRAME(state->ws)
-	};
-	return unwind_user_next_common(state, &fp_frame);
+	if (unwind_user_fp_get_frame(state, &frame))
+		return -ENOENT;
+	return unwind_user_next_common(state, &frame);
 }
 
 static int unwind_user_next_sframe(struct unwind_user_state *state)
-- 
2.51.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help