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 --- Notes (jremus): Changes in RFC v3: - New patch. Prerequirement to implement unwind user fp using back chain on s390. arch/x86/include/asm/unwind_user.h | 20 +++++++++++++++++--- include/linux/unwind_user.h | 20 +++++++------------- kernel/unwind/user.c | 16 ++++------------ 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwind_user.h index 2480d86a405e..ca581edecb9d 100644 --- a/arch/x86/include/asm/unwind_user.h +++ b/arch/x86/include/asm/unwind_user.h @@ -46,11 +46,25 @@ static inline int unwind_user_word_size(struct pt_regs *regs) .use_fp = false, \ .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 +#define unwind_user_fp_get_frame unwind_user_fp_get_frame #endif /* CONFIG_HAVE_UNWIND_USER_FP */ diff --git a/include/linux/unwind_user.h b/include/linux/unwind_user.h index 61fd5c05d0f0..4adab1a612a6 100644 --- a/include/linux/unwind_user.h +++ b/include/linux/unwind_user.h @@ -7,21 +7,15 @@ #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 +#define unwind_user_fp_get_frame unwind_user_fp_get_frame + +#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 7d06bdbc7f0d..6877242ceae3 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -111,19 +111,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