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 <[email protected]>
---

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


Reply via email to