arm64: ftrace: Enable HAVE_FUNCTION_GRAPH_RETVAL
authorDonglin Peng <pengdonglin@sangfor.com.cn>
Sat, 8 Apr 2023 12:42:18 +0000 (05:42 -0700)
committerSteven Rostedt (Google) <rostedt@goodmis.org>
Tue, 20 Jun 2023 22:38:37 +0000 (18:38 -0400)
The previous patch ("function_graph: Support recording and printing
the return value of function") has laid the groundwork for the for
the funcgraph-retval, and this modification makes it available on
the ARM64 platform.

We introduce a new structure called fgraph_ret_regs for the ARM64
platform to hold return registers and the frame pointer. We then
fill its content in the return_to_handler and pass its address to
the function ftrace_return_to_handler to record the return value.

Link: https://lkml.kernel.org/r/c78366416ce93f704ae7000c4ee60eb4258c38f7.1680954589.git.pengdonglin@sangfor.com.cn
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Donglin Peng <pengdonglin@sangfor.com.cn>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
arch/arm64/Kconfig
arch/arm64/include/asm/ftrace.h
arch/arm64/kernel/asm-offsets.c
arch/arm64/kernel/entry-ftrace.S

index b1201d2..f90b178 100644 (file)
@@ -201,6 +201,7 @@ config ARM64
        select HAVE_FTRACE_MCOUNT_RECORD
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_ERROR_INJECTION
+       select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_GCC_PLUGINS
        select HAVE_HW_BREAKPOINT if PERF_EVENTS
index b87d70b..21ac1c5 100644 (file)
@@ -192,4 +192,26 @@ static inline bool arch_syscall_match_sym_name(const char *sym,
 }
 #endif /* ifndef __ASSEMBLY__ */
 
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+struct fgraph_ret_regs {
+       /* x0 - x7 */
+       unsigned long regs[8];
+
+       unsigned long fp;
+       unsigned long __unused;
+};
+
+static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs)
+{
+       return ret_regs->regs[0];
+}
+
+static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs)
+{
+       return ret_regs->fp;
+}
+#endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER  */
+#endif
+
 #endif /* __ASM_FTRACE_H */
index 0996094..757d01a 100644 (file)
@@ -200,6 +200,19 @@ int main(void)
 #endif
 #ifdef CONFIG_FUNCTION_TRACER
   DEFINE(FTRACE_OPS_FUNC,              offsetof(struct ftrace_ops, func));
+#endif
+  BLANK();
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+  DEFINE(FGRET_REGS_X0,                        offsetof(struct fgraph_ret_regs, regs[0]));
+  DEFINE(FGRET_REGS_X1,                        offsetof(struct fgraph_ret_regs, regs[1]));
+  DEFINE(FGRET_REGS_X2,                        offsetof(struct fgraph_ret_regs, regs[2]));
+  DEFINE(FGRET_REGS_X3,                        offsetof(struct fgraph_ret_regs, regs[3]));
+  DEFINE(FGRET_REGS_X4,                        offsetof(struct fgraph_ret_regs, regs[4]));
+  DEFINE(FGRET_REGS_X5,                        offsetof(struct fgraph_ret_regs, regs[5]));
+  DEFINE(FGRET_REGS_X6,                        offsetof(struct fgraph_ret_regs, regs[6]));
+  DEFINE(FGRET_REGS_X7,                        offsetof(struct fgraph_ret_regs, regs[7]));
+  DEFINE(FGRET_REGS_FP,                        offsetof(struct fgraph_ret_regs, fp));
+  DEFINE(FGRET_REGS_SIZE,              sizeof(struct fgraph_ret_regs));
 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
   DEFINE(FTRACE_OPS_DIRECT_CALL,       offsetof(struct ftrace_ops, direct_call));
 #endif
index 1c38a60..f0c1664 100644 (file)
@@ -330,22 +330,23 @@ SYM_FUNC_END(ftrace_stub_graph)
  */
 SYM_CODE_START(return_to_handler)
        /* save return value regs */
-       sub sp, sp, #64
-       stp x0, x1, [sp]
-       stp x2, x3, [sp, #16]
-       stp x4, x5, [sp, #32]
-       stp x6, x7, [sp, #48]
+       sub sp, sp, #FGRET_REGS_SIZE
+       stp x0, x1, [sp, #FGRET_REGS_X0]
+       stp x2, x3, [sp, #FGRET_REGS_X2]
+       stp x4, x5, [sp, #FGRET_REGS_X4]
+       stp x6, x7, [sp, #FGRET_REGS_X6]
+       str x29,    [sp, #FGRET_REGS_FP]        // parent's fp
 
-       mov     x0, x29                 //     parent's fp
-       bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
-       mov     x30, x0                 // restore the original return address
+       mov     x0, sp
+       bl      ftrace_return_to_handler        // addr = ftrace_return_to_hander(regs);
+       mov     x30, x0                         // restore the original return address
 
        /* restore return value regs */
-       ldp x0, x1, [sp]
-       ldp x2, x3, [sp, #16]
-       ldp x4, x5, [sp, #32]
-       ldp x6, x7, [sp, #48]
-       add sp, sp, #64
+       ldp x0, x1, [sp, #FGRET_REGS_X0]
+       ldp x2, x3, [sp, #FGRET_REGS_X2]
+       ldp x4, x5, [sp, #FGRET_REGS_X4]
+       ldp x6, x7, [sp, #FGRET_REGS_X6]
+       add sp, sp, #FGRET_REGS_SIZE
 
        ret
 SYM_CODE_END(return_to_handler)