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 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


Reply via email to