x86: Enable the deferred unwinding infrastructure
Subsystems (5)
v2 cover x86: Enable the deferred unwinding infrastructure
This enables deferred unwinding for x86.
Changes since v1: https://lore.kernel.org/linux-trace-kernel/[email protected]
- Added #include <linux/compat.h> to use user_64bit_mode() in unwind_user.h. When adding this to the ftrace code, it failed to build due to the missing header.
Josh Poimboeuf (1):
unwind_user/x86: Enable frame pointer unwinding on x86
Steven Rostedt (1):
unwind deferred/x86: Do not defer stack tracing for compat tasks
----
arch/x86/Kconfig | 1 + arch/x86/include/asm/unwind_user.h | 23 +++++++++++++++++++++++ include/linux/unwind_deferred.h | 5 +++++ kernel/unwind/deferred.c | 3 +++ 4 files changed, 32 insertions(+) create mode 100644 arch/x86/include/asm/unwind_user.h
PATCH v2 1/2 unwind_user/x86: Enable frame pointer unwinding on x86
From: Josh Poimboeuf <[email protected]>
Use ARCH_INIT_USER_FP_FRAME to describe how frame pointers are unwound on x86, and enable CONFIG_HAVE_UNWIND_USER_FP accordingly so the unwind_user interfaces can be used.
--- arch/x86/Kconfig | 1 + arch/x86/include/asm/unwind_user.h | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 arch/x86/include/asm/unwind_user.h
arch/x86/Kconfig +1 -0
@@ -299,6 +299,7 @@ config X86 select HAVE_SYSCALL_TRACEPOINTS select HAVE_UACCESS_VALIDATION if HAVE_OBJTOOL select HAVE_UNSTABLE_SCHED_CLOCK + select HAVE_UNWIND_USER_FP if X86_64 select HAVE_USER_RETURN_NOTIFIER select HAVE_GENERIC_VDSO select VDSO_GETRANDOM if X86_64
arch/x86/include/asm/unwind_user.h new file +11 -0
@@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_UNWIND_USER_H +#define _ASM_X86_UNWIND_USER_H + +#define ARCH_INIT_USER_FP_FRAME \ + .cfa_off = (s32)sizeof(long) * 2, \ + .ra_off = (s32)sizeof(long) * -1, \ + .fp_off = (s32)sizeof(long) * -2, \ + .use_fp = true, + +#endif /* _ASM_X86_UNWIND_USER_H */
Signature · 1 line
2.50.1
Peter Zijlstra
maintainerRe: [PATCH v2 1/2] unwind_user/x86: Enable frame pointer unwinding on x86
Quoted 33 lines · Steven Rostedt
From: Josh Poimboeuf <[email protected]>
Use
ARCH_INIT_USER_FP_FRAMEto describe how frame pointers are unwound on x86, and enableCONFIG_HAVE_UNWIND_USER_FPaccordingly so theunwind_userinterfaces can be used.Signed-off-by Josh Poimboeuf <[email protected]>Signed-off-by Steven Rostedt (Google) <[email protected]>--- arch/x86/Kconfig | 1 + arch/x86/include/asm/unwind_user.h | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 arch/x86/include/asm/unwind_user.harch/x86/Kconfig +1
-0@@ -299,6 +299,7 @@ config X86 select HAVE_SYSCALL_TRACEPOINTS select HAVE_UACCESS_VALIDATION if HAVE_OBJTOOL select HAVE_UNSTABLE_SCHED_CLOCK + select HAVE_UNWIND_USER_FP if X86_64 select HAVE_USER_RETURN_NOTIFIER select HAVE_GENERIC_VDSO select VDSO_GETRANDOM if X86_64arch/x86/include/asm/unwind_user.h new file +1
-0@@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */
arch/x86/include/asm/unwind_user.h line 11
Quoted 10 lines
arch/x86/include/asm/unwind_user.h new file +10
-0+#ifndef _ASM_X86_UNWIND_USER_H +#define _ASM_X86_UNWIND_USER_H + +#define ARCH_INIT_USER_FP_FRAME \ + .cfa_off = (s32)sizeof(long) * 2, \ + .ra_off = (s32)sizeof(long) * -1, \ + .fp_off = (s32)sizeof(long) * -2, \ + .use_fp = true, + +#endif /* _ASM_X86_UNWIND_USER_H */
Moo, and now you have me look at unwind/user.c:
/* Make sure that the address is word aligned */
shift = sizeof(long) == 4 ? 2 : 3;
if (cfa & ((1 << shift) - 1))
return -EINVAL;Isn't that just:
if (cfa & (sizeof(long) - 1))
?
Let me go add a patch to clean that up...
Re: [PATCH v2 1/2] unwind_user/x86: Enable frame pointer unwinding on x86
Quoted 7 lines · On Tue, 23 Sep 2025 12:51:30 +0200 Peter Zijlstra <[email protected]> wrote:
Moo, and now you have me look at
unwind/user.c:/* Make sure that the address is word aligned */ shift = sizeof(long) == 4 ? 2 : 3; if (cfa & ((1 << shift) - 1)) return -EINVAL;
Quoted 7 lines
Isn't that just:
if (cfa & (sizeof(long) - 1))?
Let me go add a patch to clean that up...
Sure, as long as it's commented.
Thanks,
-- Steve
[tip: perf/core] unwind_user/x86: Enable frame pointer unwinding on x86
In reply to Steven RostedtThe following commit has been merged into the perf/core branch of tip:
The following commit has been merged into the perf/core branch of tip:
Commit-ID: 49cf34c0815f93fb2ea3ab5cfbac1124bd9b45d0 Gitweb: https://git.kernel.org/tip/49cf34c0815f93fb2ea3ab5cfbac1124bd9b45d0 Author: Josh Poimboeuf <[email protected]> AuthorDate: Wed, 27 Aug 2025 15:36:45 -04:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Wed, 29 Oct 2025 10:29:58 +01:00
unwind_user/x86: Enable frame pointer unwinding on x86
Use ARCH_INIT_USER_FP_FRAME to describe how frame pointers are unwound on x86, and enable CONFIG_HAVE_UNWIND_USER_FP accordingly so the unwind_user interfaces can be used.
--- arch/x86/Kconfig | 1 + arch/x86/include/asm/unwind_user.h | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 arch/x86/include/asm/unwind_user.h
arch/x86/Kconfig +1 -0
@@ -297,6 +297,7 @@ config X86 select HAVE_SYSCALL_TRACEPOINTS select HAVE_UACCESS_VALIDATION if HAVE_OBJTOOL select HAVE_UNSTABLE_SCHED_CLOCK + select HAVE_UNWIND_USER_FP if X86_64 select HAVE_USER_RETURN_NOTIFIER select HAVE_GENERIC_VDSO select VDSO_GETRANDOM if X86_64
arch/x86/include/asm/unwind_user.h new file +25 -0
@@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_UNWIND_USER_H +#define _ASM_X86_UNWIND_USER_H + +#include <asm/ptrace.h> + +#define ARCH_INIT_USER_FP_FRAME (ws) \ + .cfa_off = 2*(ws), \ + .ra_off = -1*(ws), \ + .fp_off = -2*(ws), \ + .use_fp = true, + +static inline int unwind_user_word_size (struct pt_regs *regs) +{ +/* We can't unwind VM86 stacks */ +if (regs->flags &X86_VM_MASK ) +return 0 ; +#ifdef CONFIG_X86_64 +if (!user_64bit_mode (regs)) +return sizeof (int ); +#endif +return sizeof (long ); +} + +#endif /* _ASM_X86_UNWIND_USER_H */
PATCH v2 2/2 unwind deferred/x86: Do not defer stack tracing for compat tasks
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
Currently compat tasks are not supported. If a deferred user space stack trace is requested on a compat task, it should fail and return an error so that the profiler can use an alternative approach (whatever it uses today).
Add a arch_unwind_can_defer() macro that is called in unwind_deferred_request(). Have x86 define it to a function that makes sure that the current task is running in 64bit mode, and if it is not, it returns false. This will cause unwind_deferred_request() to error out and the caller can use the current method of user space stack tracing.
---
Changes since v1: https://lore.kernel.org/[email protected]
- Added #include <linux/compat.h> to use user_64bit_mode() in unwind_user.h. When adding this to the ftrace code, it failed to build due to the missing header.
arch/x86/include/asm/unwind_user.h | 12 ++++++++++++ include/linux/unwind_deferred.h | 5 +++++ kernel/unwind/deferred.c | 3 +++ 3 files changed, 20 insertions(+)
arch/x86/include/asm/unwind_user.h +12 -0
@@ -2,6 +2,18 @@#ifndef _ASM_X86_UNWIND_USER_H#define _ASM_X86_UNWIND_USER_H +#ifdef CONFIG_IA32_EMULATION +#include <linux/compat.h> +/* Currently compat mode is not supported for deferred stack trace */ +static inline bool arch_unwind_can_defer (void ) +{ +struct pt_regs *regs =task_pt_regs (current); + +return user_64bit_mode (regs); +} +# define arch_unwind_can_defer arch_unwind_can_defer +#endif /* CONFIG_IA32_EMULATION */ +#define ARCH_INIT_USER_FP_FRAME \ .cfa_off = (s32)sizeof(long) * 2, \ .ra_off = (s32)sizeof(long) * -1, \
include/linux/unwind_deferred.h +5 -0
@@ -16,6 +16,11 @@ struct unwind_work {int bit; }; +/* Architectures can add a test to not defer unwinding */ +#ifndef arch_unwind_can_defer +# define arch_unwind_can_defer () (true) +#endif +#ifdef CONFIG_UNWIND_USER enum {
kernel/unwind/deferred.c +3 -0
@@ -237,6 +237,9 @@ int unwind_deferred_request(struct unwind_work *work, u64 *cookie) *cookie =0 ; +if (!arch_unwind_can_defer ()) +return -EINVAL ; +if ((current->flags & (PF_KTHREAD |PF_EXITING )) || !user_mode (task_pt_regs (current)))return -EINVAL ;
Signature · 1 line
2.50.1
Peter Zijlstra
maintainerRe: [PATCH v2 2/2] unwind deferred/x86: Do not defer stack tracing for compat tasks
Quoted 7 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
Currently compat tasks are not supported. If a deferred user space stack trace is requested on a compat task, it should fail and return an error so that the profiler can use an alternative approach (whatever it uses today).
Quoted 5 lines
Add a
arch_unwind_can_defer()macro that is called inunwind_deferred_request(). Have x86 define it to a function that makes sure that the current task is running in 64bit mode, and if it is not, it returns false. This will causeunwind_deferred_request()to error out and the caller can use the current method of user space stack tracing.
Changelog seems to forget mentioning *why* we can't unwind compat.
I'm sure I've seen compat FP unwind support at some point in this series. Did that go missing somewhere?
Also, these two patches are in the wrong order, first you enable things, including compat tasks, and then you go 'whoopsie, no compats'.
Quoted 57 lines
Signed-off-by Steven Rostedt (Google) <[email protected]>---
Changes since v1: https://lore.kernel.org/[email protected]- Added #include <
linux/compat.h> to useuser_64bit_mode()inunwind_user.h. When adding this to the ftrace code, it failed to build due to the missing header.arch/x86/include/asm/unwind_user.h | 12 ++++++++++++ include/linux/unwind_deferred.h | 5 +++++ kernel/unwind/deferred.c | 3 +++ 3 files changed, 20 insertions(+)arch/x86/include/asm/unwind_user.h +12
-0@@ -2,6 +2,18 @@#ifndef _ASM_X86_UNWIND_USER_H#define _ASM_X86_UNWIND_USER_H +#ifdef CONFIG_IA32_EMULATION +#include <linux/compat.h> +/* Currently compat mode is not supported for deferred stack trace */ +static inline bool arch_unwind_can_defer (void ) +{ +struct pt_regs *regs =task_pt_regs (current); + +return user_64bit_mode (regs); +} +# define arch_unwind_can_defer arch_unwind_can_defer +#endif /* CONFIG_IA32_EMULATION */ +#define ARCH_INIT_USER_FP_FRAME \ .cfa_off = (s32)sizeof(long) * 2, \ .ra_off = (s32)sizeof(long) * -1, \include/linux/unwind_deferred.h +5
-0@@ -16,6 +16,11 @@ struct unwind_work {int bit; }; +/* Architectures can add a test to not defer unwinding */ +#ifndef arch_unwind_can_defer +# define arch_unwind_can_defer () (true) +#endif +#ifdef CONFIG_UNWIND_USER enum {kernel/unwind/deferred.c +0
-0
kernel/unwind/deferred.c int unwind_deferred_request(struct unwind_work *work, u64 *cookie) · line 245
Quoted 9 lines
kernel/unwind/deferred.c +3
-0@@ -237,6 +237,9 @@ int unwind_deferred_request(struct unwind_work *work, u64 *cookie) *cookie =0 ; +if (!arch_unwind_can_defer ()) +return -EINVAL ; +if ((current->flags & (PF_KTHREAD |PF_EXITING )) || !user_mode (task_pt_regs (current)))return -EINVAL ;
Should not this arch hook be after all the 'normal' early exits?
Peter Zijlstra
maintainerRe: [PATCH v2 2/2] unwind deferred/x86: Do not defer stack tracing for compat tasks
Quoted 14 lines · Peter Zijlstra
Quoted 7 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
Currently compat tasks are not supported. If a deferred user space stack trace is requested on a compat task, it should fail and return an error so that the profiler can use an alternative approach (whatever it uses today).
Quoted 5 lines
Add a
arch_unwind_can_defer()macro that is called inunwind_deferred_request(). Have x86 define it to a function that makes sure that the current task is running in 64bit mode, and if it is not, it returns false. This will causeunwind_deferred_request()to error out and the caller can use the current method of user space stack tracing.
Quoted 4 lines
Changelog seems to forget mentioning *why* we can't unwind compat.
I'm sure I've seen compat FP unwind support at some point in this series. Did that go missing somewhere?
I'm thinking something like the below ought to work. That's just about as complicated as not supporting compat.
---
Subject: unwind: Implement compat fp unwind
From: Peter Zijlstra <[email protected]>
Date: Tue Sep 23 13:27:34 CEST 2025
--- include/linux/unwind_user_types.h | 1 + kernel/unwind/user.c | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-)
include/linux/unwind_user_types.h +1 -0
@@ -36,6 +36,7 @@ struct unwind_user_state {unsigned long ip;unsigned long sp;unsigned long fp; +unsigned int ws;enum unwind_user_type current_type;unsigned int available_types;bool done;
kernel/unwind/user.c +21 -4
@@ -15,6 +15,20 @@ static const struct unwind_user_frame fp#define for_each_user_frame (state) \ for (unwind_user_start(state); !(state)->done; unwind_user_next(state)) +static __always_inline int +get_user_word (unsigned long *word,unsigned long __user *addr,int size) +{ +#ifdef CONFIG_COMPAT +if (size ==sizeof (int )) { +unsigned int data; +int ret =get_user (data, (unsigned int __user *)addr); + *word = data; +return ret; + } +#endif +return get_user (*word, addr); +} +static int unwind_user_next_fp (struct unwind_user_state *state) {const struct unwind_user_frame *frame = &fp_frame;
@@ -29,21 +43,23 @@ static int unwind_user_next_fp(struct un }/* Get the Canonical Frame Address (CFA) */ - cfa += frame->cfa_off; + cfa += state->ws * frame->cfa_off;/* stack going in wrong direction? */ if (cfa <= state->sp)return -EINVAL ;/* Make sure that the address is word aligned */ -if (cfa & (sizeof (long ) -1 )) +if (cfa & (state->ws -1 ))return -EINVAL ;/* Find the Return Address (RA) */ -if (get_user (ra, (unsigned long *)(cfa + frame->ra_off))) +if (get_user_word (&ra, (void __user *)cfa + (state->ws * frame->ra_off), + state->ws))return -EINVAL ; -if (frame->fp_off &&get_user (fp, (unsigned long __user *)(cfa + frame->fp_off))) +if (frame->fp_off &&get_user_word (&fp, (void __user *)cfa + + (state->ws * frame->fp_off), state->ws))return -EINVAL ; state->ip = ra;
@@ -100,6 +116,7 @@ static int unwind_user_start(struct unwi state->ip =instruction_pointer (regs); state->sp =user_stack_pointer (regs); state->fp =frame_pointer (regs); + state->ws =compat_user_mode (regs) ?sizeof (int ) :sizeof (long );return 0 ; }
---
Subject: unwind_user/x86: Enable frame pointer unwinding on x86
From: Josh Poimboeuf <[email protected]>
Date: Wed, 27 Aug 2025 15:36:45 -0400
From: Josh Poimboeuf <[email protected]>
Use ARCH_INIT_USER_FP_FRAME to describe how frame pointers are unwound on x86, and enable CONFIG_HAVE_UNWIND_USER_FP accordingly so the unwind_user interfaces can be used.
--- arch/x86/Kconfig | 1 + arch/x86/include/asm/ptrace.h | 9 +++++++++ arch/x86/include/asm/unwind_user.h | 11 +++++++++++ 3 files changed, 21 insertions(+) create mode 100644 arch/x86/include/asm/unwind_user.h
arch/x86/Kconfig +1 -0
@@ -297,6 +297,7 @@ config X86 select HAVE_SYSCALL_TRACEPOINTS select HAVE_UACCESS_VALIDATION if HAVE_OBJTOOL select HAVE_UNSTABLE_SCHED_CLOCK + select HAVE_UNWIND_USER_FP if X86_64 select HAVE_USER_RETURN_NOTIFIER select HAVE_GENERIC_VDSO select VDSO_GETRANDOM if X86_64
arch/x86/include/asm/ptrace.h +9 -0
@@ -255,6 +255,15 @@ static inline bool any_64bit_mode(struct#endif } +static inline bool compat_user_mode (struct pt_regs *regs) +{ +#ifdef CONFIG_X86_64 +return !user_64bit_mode (regs); +#else +return false; +#endif +} +#ifdef CONFIG_X86_64 #define current_user_stack_pointer () current_pt_regs()->sp#define compat_user_stack_pointer () current_pt_regs()->sp
arch/x86/include/asm/unwind_user.h new file +11 -0
@@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_UNWIND_USER_H +#define _ASM_X86_UNWIND_USER_H + +#define ARCH_INIT_USER_FP_FRAME \ + .cfa_off = 2, \ + .ra_off = -1, \ + .fp_off = -2, \ + .use_fp = true, + +#endif /* _ASM_X86_UNWIND_USER_H */
Re: [PATCH v2 2/2] unwind deferred/x86: Do not defer stack tracing for compat tasks
In reply to Peter ZijlstraQuoted 7 lines · On Tue, 23 Sep 2025 12:45:15 +0200 Peter Zijlstra <[email protected]> wrote:
Changelog seems to forget mentioning *why* we can't unwind compat.
I'm sure I've seen compat FP unwind support at some point in this series. Did that go missing somewhere?
Also, these two patches are in the wrong order, first you enable things, including compat tasks, and then you go 'whoopsie, no compats'.
Sure, we can swap it. Yes, we had patches to support it, but they were a bit complicated and when I tested them, they didn't work. But then I also noticed that the current stack tracing didn't work on compat either. Instead of adding complicated code that wasn't working on my machine, I decided to remove the patches. But after I did that, I realized I needed to make sure it wasn't even tried, which is this patch.
I'm not sure who needs profiling on compat code, and I figured we can not add the new deferred work to it if it's not needed. If in the future we need it, we can add it then.
-- Steve