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_REGS 60 61/** 62* SAVE_ABI_REGS - save regs against the pt_regs struct 63* 64* @all: tell if saving all the regs 65* 66* If all is set, all the regs will be saved, otherwise only ABI 67* related regs (a0-a7,epc,ra and optional s0) will be saved. 68* 69* After the stack is established, 70* 71* 0(sp) stores the PC of the traced function which can be accessed 72* by &(fregs)->regs->epc in tracing function. Note that the real 73* function entry address should be computed with -FENTRY_RA_OFFSET. 74* 75* 8(sp) stores the function return address (i.e. parent IP) that 76* can be accessed by &(fregs)->regs->ra in tracing function. 77* 78* The other regs are saved at the respective localtion and accessed 79* by the respective pt_regs member. 80* 81* Here is the layout of stack for your reference. 82* 83* PT_SIZE_ON_STACK -> +++++++++ 84* + ..... + 85* + t3-t6 + 86* + s2-s11+ 87* + a0-a7 + --++++-> ftrace_caller saved 88* + s1 + + 89* + s0 + --+ 90* + t0-t2 + + 91* + tp + + 92* + gp + + 93* + sp + + 94* + ra + --+ // parent IP 95* sp -> + epc + --+ // PC 96* +++++++++ 97**/ 98 .macro SAVE_ABI_REGS, all=0 99 addi sp, sp, -PT_SIZE_ON_STACK 100 101 REG_S t0, PT_EPC(sp) 102 REG_S x1, PT_RA(sp) 103 104 // save the ABI regs 105 106 REG_S x10, PT_A0(sp) 107 REG_S x11, PT_A1(sp) 108 REG_S x12, PT_A2(sp) 109 REG_S x13, PT_A3(sp) 110 REG_S x14, PT_A4(sp) 111 REG_S x15, PT_A5(sp) 112 REG_S x16, PT_A6(sp) 113 REG_S x17, PT_A7(sp) 114 115 // save the leftover regs 116 117 .if \all == 1 118 REG_S x2, PT_SP(sp) 119 REG_S x3, PT_GP(sp) 120 REG_S x4, PT_TP(sp) 121 REG_S x5, PT_T0(sp) 122 REG_S x6, PT_T1(sp) 123 REG_S x7, PT_T2(sp) 124 REG_S x8, PT_S0(sp) 125 REG_S x9, PT_S1(sp) 126 REG_S x18, PT_S2(sp) 127 REG_S x19, PT_S3(sp) 128 REG_S x20, PT_S4(sp) 129 REG_S x21, PT_S5(sp) 130 REG_S x22, PT_S6(sp) 131 REG_S x23, PT_S7(sp) 132 REG_S x24, PT_S8(sp) 133 REG_S x25, PT_S9(sp) 134 REG_S x26, PT_S10(sp) 135 REG_S x27, PT_S11(sp) 136 REG_S x28, PT_T3(sp) 137 REG_S x29, PT_T4(sp) 138 REG_S x30, PT_T5(sp) 139 REG_S x31, PT_T6(sp) 140 141 // save s0 if FP_TEST defined 142 143 .else 144#ifdef HAVE_FUNCTION_GRAPH_FP_TEST 145 REG_S x8, PT_S0(sp) 146#endif 147 .endif 148 .endm 149 150 .macro RESTORE_ABI_REGS, all=0 151 REG_L t0, PT_EPC(sp) 152 REG_L x1, PT_RA(sp) 153 REG_L x10, PT_A0(sp) 154 REG_L x11, PT_A1(sp) 155 REG_L x12, PT_A2(sp) 156 REG_L x13, PT_A3(sp) 157 REG_L x14, PT_A4(sp) 158 REG_L x15, PT_A5(sp) 159 REG_L x16, PT_A6(sp) 160 REG_L x17, PT_A7(sp) 161 162 .if \all == 1 163 REG_L x2, PT_SP(sp) 164 REG_L x3, PT_GP(sp) 165 REG_L x4, PT_TP(sp) 166 REG_L x6, PT_T1(sp) 167 REG_L x7, PT_T2(sp) 168 REG_L x8, PT_S0(sp) 169 REG_L x9, PT_S1(sp) 170 REG_L x18, PT_S2(sp) 171 REG_L x19, PT_S3(sp) 172 REG_L x20, PT_S4(sp) 173 REG_L x21, PT_S5(sp) 174 REG_L x22, PT_S6(sp) 175 REG_L x23, PT_S7(sp) 176 REG_L x24, PT_S8(sp) 177 REG_L x25, PT_S9(sp) 178 REG_L x26, PT_S10(sp) 179 REG_L x27, PT_S11(sp) 180 REG_L x28, PT_T3(sp) 181 REG_L x29, PT_T4(sp) 182 REG_L x30, PT_T5(sp) 183 REG_L x31, PT_T6(sp) 184 185 .else 186#ifdef HAVE_FUNCTION_GRAPH_FP_TEST 187 REG_L x8, PT_S0(sp) 188#endif 189 .endif 190 addi sp, sp, PT_SIZE_ON_STACK 191 .endm 192 193 .macro PREPARE_ARGS 194 addi a0, t0, -FENTRY_RA_OFFSET 195 la a1, function_trace_op 196 REG_L a2, 0(a1) 197 mv a1, ra 198 mv a3, sp 199 .endm 200 201#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */ 202 203#ifndef CONFIG_DYNAMIC_FTRACE_WITH_REGS 204SYM_FUNC_START(ftrace_caller) 205 SAVE_ABI 206 207 addi a0, t0, -FENTRY_RA_OFFSET 208 la a1, function_trace_op 209 REG_L a2, 0(a1) 210 mv a1, ra 211 mv a3, sp 212 213SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) 214 call ftrace_stub 215 216#ifdef CONFIG_FUNCTION_GRAPH_TRACER 217 addi a0, sp, ABI_RA 218 REG_L a1, ABI_T0(sp) 219 addi a1, a1, -FENTRY_RA_OFFSET 220#ifdef HAVE_FUNCTION_GRAPH_FP_TEST 221 mv a2, s0 222#endif 223SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL) 224 call ftrace_stub 225#endif 226 RESTORE_ABI 227 jr t0 228SYM_FUNC_END(ftrace_caller) 229 230#else /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */ 231SYM_FUNC_START(ftrace_regs_caller) 232 mv t1, zero 233 SAVE_ABI_REGS 1 234 PREPARE_ARGS 235 236SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL) 237 call ftrace_stub 238 239 RESTORE_ABI_REGS 1 240 bnez t1, .Ldirect 241 jr t0 242.Ldirect: 243 jr t1 244SYM_FUNC_END(ftrace_regs_caller) 245 246SYM_FUNC_START(ftrace_caller) 247 SAVE_ABI_REGS 0 248 PREPARE_ARGS 249 250SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) 251 call ftrace_stub 252 253 RESTORE_ABI_REGS 0 254 jr t0 255SYM_FUNC_END(ftrace_caller) 256#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */ 257 258#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS 259SYM_CODE_START(ftrace_stub_direct_tramp) 260 jr t0 261SYM_CODE_END(ftrace_stub_direct_tramp) 262#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ 263