1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (C) 2017 Andes Technology Corporation */
4 #include <linux/init.h>
5 #include <linux/linkage.h>
6 #include <linux/export.h>
9 #include <asm/unistd.h>
10 #include <asm/thread_info.h>
11 #include <asm/asm-offsets.h>
12 #include <asm/ftrace.h>
16 #define FENTRY_RA_OFFSET 8
17 #define ABI_SIZE_ON_STACK 80
30 addi sp, sp, -ABI_SIZE_ON_STACK
56 addi sp, sp, ABI_SIZE_ON_STACK
59 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
62 * SAVE_ABI_REGS - save regs against the ftrace_regs struct
64 * After the stack is established,
66 * 0(sp) stores the PC of the traced function which can be accessed
67 * by &(fregs)->epc in tracing function. Note that the real
68 * function entry address should be computed with -FENTRY_RA_OFFSET.
70 * 8(sp) stores the function return address (i.e. parent IP) that
71 * can be accessed by &(fregs)->ra in tracing function.
73 * The other regs are saved at the respective localtion and accessed
74 * by the respective ftrace_regs member.
76 * Here is the layout of stack for your reference.
78 * PT_SIZE_ON_STACK -> +++++++++
80 * + a0-a7 + --++++-> ftrace_caller saved
81 * + t1 + --++++-> direct tramp address
82 * + s0 + --+ // frame pointer
84 * + ra + --+ // parent IP
85 * sp -> + epc + --+ // PC
89 mv t4, sp // Save original SP in T4
90 addi sp, sp, -FREGS_SIZE_ON_STACK
92 REG_S t0, FREGS_EPC(sp)
93 REG_S x1, FREGS_RA(sp)
94 REG_S t4, FREGS_SP(sp) // Put original SP on stack
95 #ifdef HAVE_FUNCTION_GRAPH_FP_TEST
96 REG_S x8, FREGS_S0(sp)
98 REG_S x6, FREGS_T1(sp)
100 // save the arguments
101 REG_S x10, FREGS_A0(sp)
102 REG_S x11, FREGS_A1(sp)
103 REG_S x12, FREGS_A2(sp)
104 REG_S x13, FREGS_A3(sp)
105 REG_S x14, FREGS_A4(sp)
106 REG_S x15, FREGS_A5(sp)
107 REG_S x16, FREGS_A6(sp)
108 REG_S x17, FREGS_A7(sp)
111 .macro RESTORE_ABI_REGS, all=0
112 REG_L t0, FREGS_EPC(sp)
113 REG_L x1, FREGS_RA(sp)
114 #ifdef HAVE_FUNCTION_GRAPH_FP_TEST
115 REG_L x8, FREGS_S0(sp)
117 REG_L x6, FREGS_T1(sp)
119 // restore the arguments
120 REG_L x10, FREGS_A0(sp)
121 REG_L x11, FREGS_A1(sp)
122 REG_L x12, FREGS_A2(sp)
123 REG_L x13, FREGS_A3(sp)
124 REG_L x14, FREGS_A4(sp)
125 REG_L x15, FREGS_A5(sp)
126 REG_L x16, FREGS_A6(sp)
127 REG_L x17, FREGS_A7(sp)
129 addi sp, sp, FREGS_SIZE_ON_STACK
133 addi a0, t0, -FENTRY_RA_OFFSET
134 la a1, function_trace_op
140 #endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
142 #ifndef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
143 SYM_FUNC_START(ftrace_caller)
146 addi a0, t0, -FENTRY_RA_OFFSET
147 la a1, function_trace_op
152 SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
155 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
158 addi a1, a1, -FENTRY_RA_OFFSET
159 #ifdef HAVE_FUNCTION_GRAPH_FP_TEST
162 SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL)
167 SYM_FUNC_END(ftrace_caller)
169 #else /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
170 SYM_FUNC_START(ftrace_caller)
175 SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
183 SYM_FUNC_END(ftrace_caller)
185 #endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
187 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
188 SYM_CODE_START(ftrace_stub_direct_tramp)
190 SYM_CODE_END(ftrace_stub_direct_tramp)
191 #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */