1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* Copyright (C) 2017 Andes Technology Corporation */ 3 4 #include <linux/init.h> 5 #include <linux/linkage.h> 6 #include <linux/export.h> 7 #include <asm/asm.h> 8 #include <asm/csr.h> 9 #include <asm/unistd.h> 10 #include <asm/thread_info.h> 11 #include <asm/asm-offsets.h> 12 #include <asm/ftrace.h> 13 14 .text 15 16 #define FENTRY_RA_OFFSET 8 17 #define ABI_SIZE_ON_STACK 80 18 #define ABI_A0 0 19 #define ABI_A1 8 20 #define ABI_A2 16 21 #define ABI_A3 24 22 #define ABI_A4 32 23 #define ABI_A5 40 24 #define ABI_A6 48 25 #define ABI_A7 56 26 #define ABI_T0 64 27 #define ABI_RA 72 28 29 .macro SAVE_ABI 30 addi sp, sp, -ABI_SIZE_ON_STACK 31 32 REG_S a0, ABI_A0(sp) 33 REG_S a1, ABI_A1(sp) 34 REG_S a2, ABI_A2(sp) 35 REG_S a3, ABI_A3(sp) 36 REG_S a4, ABI_A4(sp) 37 REG_S a5, ABI_A5(sp) 38 REG_S a6, ABI_A6(sp) 39 REG_S a7, ABI_A7(sp) 40 REG_S t0, ABI_T0(sp) 41 REG_S ra, ABI_RA(sp) 42 .endm 43 44 .macro RESTORE_ABI 45 REG_L a0, ABI_A0(sp) 46 REG_L a1, ABI_A1(sp) 47 REG_L a2, ABI_A2(sp) 48 REG_L a3, ABI_A3(sp) 49 REG_L a4, ABI_A4(sp) 50 REG_L a5, ABI_A5(sp) 51 REG_L a6, ABI_A6(sp) 52 REG_L a7, ABI_A7(sp) 53 REG_L t0, ABI_T0(sp) 54 REG_L ra, ABI_RA(sp) 55 56 addi sp, sp, ABI_SIZE_ON_STACK 57 .endm 58 59 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS 60 61 /** 62 * SAVE_ABI_REGS - save regs against the ftrace_regs struct 63 * 64 * After the stack is established, 65 * 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. 69 * 70 * 8(sp) stores the function return address (i.e. parent IP) that 71 * can be accessed by &(fregs)->ra in tracing function. 72 * 73 * The other regs are saved at the respective localtion and accessed 74 * by the respective ftrace_regs member. 75 * 76 * Here is the layout of stack for your reference. 77 * 78 * PT_SIZE_ON_STACK -> +++++++++ 79 * + ..... + 80 * + a0-a7 + --++++-> ftrace_caller saved 81 * + t1 + --++++-> direct tramp address 82 * + s0 + --+ // frame pointer 83 * + sp + + 84 * + ra + --+ // parent IP 85 * sp -> + epc + --+ // PC 86 * +++++++++ 87 **/ 88 .macro SAVE_ABI_REGS 89 mv t4, sp // Save original SP in T4 90 addi sp, sp, -FREGS_SIZE_ON_STACK 91 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) 97 #endif 98 REG_S x6, FREGS_T1(sp) 99 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) 109 .endm 110 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) 116 #endif 117 REG_L x6, FREGS_T1(sp) 118 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) 128 129 addi sp, sp, FREGS_SIZE_ON_STACK 130 .endm 131 132 .macro PREPARE_ARGS 133 addi a0, t0, -FENTRY_RA_OFFSET 134 la a1, function_trace_op 135 REG_L a2, 0(a1) 136 mv a1, ra 137 mv a3, sp 138 .endm 139 140 #endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */ 141 142 #ifndef CONFIG_DYNAMIC_FTRACE_WITH_ARGS 143 SYM_FUNC_START(ftrace_caller) 144 SAVE_ABI 145 146 addi a0, t0, -FENTRY_RA_OFFSET 147 la a1, function_trace_op 148 REG_L a2, 0(a1) 149 mv a1, ra 150 mv a3, sp 151 152 SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) 153 call ftrace_stub 154 155 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 156 addi a0, sp, ABI_RA 157 REG_L a1, ABI_T0(sp) 158 addi a1, a1, -FENTRY_RA_OFFSET 159 #ifdef HAVE_FUNCTION_GRAPH_FP_TEST 160 mv a2, s0 161 #endif 162 SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL) 163 call ftrace_stub 164 #endif 165 RESTORE_ABI 166 jr t0 167 SYM_FUNC_END(ftrace_caller) 168 169 #else /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */ 170 SYM_FUNC_START(ftrace_caller) 171 mv t1, zero 172 SAVE_ABI_REGS 173 PREPARE_ARGS 174 175 SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) 176 call ftrace_stub 177 178 RESTORE_ABI_REGS 179 bnez t1, .Ldirect 180 jr t0 181 .Ldirect: 182 jr t1 183 SYM_FUNC_END(ftrace_caller) 184 185 #endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */ 186 187 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS 188 SYM_CODE_START(ftrace_stub_direct_tramp) 189 jr t0 190 SYM_CODE_END(ftrace_stub_direct_tramp) 191 #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.