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 143SYM_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 152SYM_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 162SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL) 163 call ftrace_stub 164#endif 165 RESTORE_ABI 166 jr t0 167SYM_FUNC_END(ftrace_caller) 168 169#else /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */ 170SYM_FUNC_START(ftrace_caller) 171 mv t1, zero 172 SAVE_ABI_REGS 173 PREPARE_ARGS 174 175SYM_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 183SYM_FUNC_END(ftrace_caller) 184 185#endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */ 186 187#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS 188SYM_CODE_START(ftrace_stub_direct_tramp) 189 jr t0 190SYM_CODE_END(ftrace_stub_direct_tramp) 191#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ 192