1 /* SPDX-License-Identifier: GPL-2.0 */ !! 1 /* 2 /* Copyright (C) 2017 Andes Technology Corpora !! 2 * MIPS specific _mcount support >> 3 * >> 4 * This file is subject to the terms and conditions of the GNU General Public >> 5 * License. See the file "COPYING" in the main directory of this archive for >> 6 * more details. >> 7 * >> 8 * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China >> 9 * Copyright (C) 2010 DSLab, Lanzhou University, China >> 10 * Author: Wu Zhangjin <wuzhangjin@gmail.com> >> 11 */ 3 12 4 #include <linux/init.h> << 5 #include <linux/linkage.h> << 6 #include <linux/cfi_types.h> << 7 #include <linux/export.h> 13 #include <linux/export.h> 8 #include <asm/asm.h> !! 14 #include <asm/regdef.h> 9 #include <asm/csr.h> !! 15 #include <asm/stackframe.h> 10 #include <asm/unistd.h> << 11 #include <asm/thread_info.h> << 12 #include <asm/asm-offsets.h> << 13 #include <asm/ftrace.h> 16 #include <asm/ftrace.h> 14 17 15 .text 18 .text >> 19 .set noreorder >> 20 .set noat 16 21 17 .macro SAVE_ABI_STATE !! 22 .macro MCOUNT_SAVE_REGS 18 addi sp, sp, -16 !! 23 PTR_SUBU sp, PT_SIZE 19 REG_S s0, 0*SZREG(sp) !! 24 PTR_S ra, PT_R31(sp) 20 REG_S ra, 1*SZREG(sp) !! 25 PTR_S AT, PT_R1(sp) 21 addi s0, sp, 16 !! 26 PTR_S a0, PT_R4(sp) >> 27 PTR_S a1, PT_R5(sp) >> 28 PTR_S a2, PT_R6(sp) >> 29 PTR_S a3, PT_R7(sp) >> 30 #ifdef CONFIG_64BIT >> 31 PTR_S a4, PT_R8(sp) >> 32 PTR_S a5, PT_R9(sp) >> 33 PTR_S a6, PT_R10(sp) >> 34 PTR_S a7, PT_R11(sp) >> 35 #endif 22 .endm 36 .endm 23 37 24 /* !! 38 .macro MCOUNT_RESTORE_REGS 25 * The call to ftrace_return_to_handle !! 39 PTR_L ra, PT_R31(sp) 26 * register if a0 was not saved. !! 40 PTR_L AT, PT_R1(sp) 27 */ !! 41 PTR_L a0, PT_R4(sp) 28 .macro SAVE_RET_ABI_STATE !! 42 PTR_L a1, PT_R5(sp) 29 addi sp, sp, -4*SZREG !! 43 PTR_L a2, PT_R6(sp) 30 REG_S s0, 2*SZREG(sp) !! 44 PTR_L a3, PT_R7(sp) 31 REG_S ra, 3*SZREG(sp) !! 45 #ifdef CONFIG_64BIT 32 REG_S a0, 1*SZREG(sp) !! 46 PTR_L a4, PT_R8(sp) 33 REG_S a1, 0*SZREG(sp) !! 47 PTR_L a5, PT_R9(sp) 34 addi s0, sp, 4*SZREG !! 48 PTR_L a6, PT_R10(sp) >> 49 PTR_L a7, PT_R11(sp) >> 50 #endif >> 51 PTR_ADDIU sp, PT_SIZE 35 .endm 52 .endm 36 53 37 .macro RESTORE_ABI_STATE !! 54 .macro RETURN_BACK 38 REG_L ra, 1*SZREG(sp) !! 55 jr ra 39 REG_L s0, 0*SZREG(sp) !! 56 move ra, AT 40 addi sp, sp, 16 << 41 .endm 57 .endm 42 58 43 .macro RESTORE_RET_ABI_STATE !! 59 /* 44 REG_L ra, 3*SZREG(sp) !! 60 * The -mmcount-ra-address option of gcc 4.5 uses register $12 to pass 45 REG_L s0, 2*SZREG(sp) !! 61 * the location of the parent's return address. 46 REG_L a0, 1*SZREG(sp) !! 62 */ 47 REG_L a1, 0*SZREG(sp) !! 63 #define MCOUNT_RA_ADDRESS_REG $12 48 addi sp, sp, 4*SZREG << 49 .endm << 50 64 51 SYM_TYPED_FUNC_START(ftrace_stub) << 52 #ifdef CONFIG_DYNAMIC_FTRACE 65 #ifdef CONFIG_DYNAMIC_FTRACE 53 .global _mcount !! 66 54 .set _mcount, ftrace_stub !! 67 NESTED(ftrace_caller, PT_SIZE, ra) 55 #endif !! 68 .globl _mcount 56 ret !! 69 _mcount: 57 SYM_FUNC_END(ftrace_stub) !! 70 EXPORT_SYMBOL(_mcount) >> 71 b ftrace_stub >> 72 #ifdef CONFIG_32BIT >> 73 addiu sp,sp,8 >> 74 #else >> 75 nop >> 76 #endif >> 77 >> 78 /* When tracing is activated, it calls ftrace_caller+8 (aka here) */ >> 79 MCOUNT_SAVE_REGS >> 80 #ifdef KBUILD_MCOUNT_RA_ADDRESS >> 81 PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp) >> 82 #endif >> 83 >> 84 PTR_SUBU a0, ra, 8 /* arg1: self address */ >> 85 PTR_LA t1, _stext >> 86 sltu t2, a0, t1 /* t2 = (a0 < _stext) */ >> 87 PTR_LA t1, _etext >> 88 sltu t3, t1, a0 /* t3 = (a0 > _etext) */ >> 89 or t1, t2, t3 >> 90 beqz t1, ftrace_call >> 91 nop >> 92 #if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) >> 93 PTR_SUBU a0, a0, 16 /* arg1: adjust to module's recorded callsite */ >> 94 #else >> 95 PTR_SUBU a0, a0, 12 >> 96 #endif >> 97 >> 98 .globl ftrace_call >> 99 ftrace_call: >> 100 nop /* a placeholder for the call to a real tracing function */ >> 101 move a1, AT /* arg2: parent's return address */ 58 102 59 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 103 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 60 SYM_TYPED_FUNC_START(ftrace_stub_graph) !! 104 .globl ftrace_graph_call 61 ret !! 105 ftrace_graph_call: 62 SYM_FUNC_END(ftrace_stub_graph) !! 106 nop >> 107 nop >> 108 #endif 63 109 64 SYM_FUNC_START(return_to_handler) !! 110 MCOUNT_RESTORE_REGS 65 /* !! 111 .globl ftrace_stub 66 * On implementing the frame point test, the i !! 112 ftrace_stub: 67 * s0 (frame pointer, if enabled) on entry and !! 113 RETURN_BACK 68 * However, the psABI of variable-length-argum !! 114 END(ftrace_caller) 69 * !! 115 70 * So alternatively we check the *old* frame p !! 116 #else /* ! CONFIG_DYNAMIC_FTRACE */ 71 * value stored in -16(s0) on entry, and the s !! 117 72 */ !! 118 NESTED(_mcount, PT_SIZE, ra) 73 SAVE_RET_ABI_STATE !! 119 EXPORT_SYMBOL(_mcount) 74 mv a0, sp !! 120 PTR_LA t1, ftrace_stub 75 call ftrace_return_to_handler !! 121 PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */ 76 mv a2, a0 !! 122 beq t1, t2, fgraph_trace 77 RESTORE_RET_ABI_STATE !! 123 nop 78 jalr a2 !! 124 79 SYM_FUNC_END(return_to_handler) !! 125 MCOUNT_SAVE_REGS >> 126 >> 127 move a0, ra /* arg1: self return address */ >> 128 jalr t2 /* (1) call *ftrace_trace_function */ >> 129 move a1, AT /* arg2: parent's return address */ >> 130 >> 131 MCOUNT_RESTORE_REGS >> 132 >> 133 fgraph_trace: >> 134 #ifdef CONFIG_FUNCTION_GRAPH_TRACER >> 135 PTR_LA t1, ftrace_stub >> 136 PTR_L t3, ftrace_graph_return >> 137 bne t1, t3, ftrace_graph_caller >> 138 nop >> 139 PTR_LA t1, ftrace_graph_entry_stub >> 140 PTR_L t3, ftrace_graph_entry >> 141 bne t1, t3, ftrace_graph_caller >> 142 nop 80 #endif 143 #endif 81 144 82 #ifndef CONFIG_DYNAMIC_FTRACE !! 145 #ifdef CONFIG_32BIT 83 SYM_FUNC_START(_mcount) !! 146 addiu sp, sp, 8 84 la t4, ftrace_stub !! 147 #endif 85 #ifdef CONFIG_FUNCTION_GRAPH_TRACER !! 148 86 la t0, ftrace_graph_return !! 149 .globl ftrace_stub 87 REG_L t1, 0(t0) !! 150 ftrace_stub: 88 bne t1, t4, .Ldo_ftrace_graph_call !! 151 RETURN_BACK 89 !! 152 END(_mcount) 90 la t3, ftrace_graph_entry !! 153 91 REG_L t2, 0(t3) !! 154 #endif /* ! CONFIG_DYNAMIC_FTRACE */ 92 la t6, ftrace_graph_entry_stub << 93 bne t2, t6, .Ldo_ftrace_graph_call << 94 #endif << 95 la t3, ftrace_trace_function << 96 REG_L t5, 0(t3) << 97 bne t5, t4, .Ldo_trace << 98 ret << 99 155 100 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 156 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 101 /* !! 157 102 * A pseudo representation for the function gr !! 158 NESTED(ftrace_graph_caller, PT_SIZE, ra) 103 * prepare_to_return(&ra_to_caller_of_caller, !! 159 #ifndef CONFIG_DYNAMIC_FTRACE 104 */ !! 160 MCOUNT_SAVE_REGS 105 .Ldo_ftrace_graph_caller: << 106 addi a0, s0, -SZREG << 107 mv a1, ra << 108 #ifdef HAVE_FUNCTION_GRAPH_FP_TEST << 109 REG_L a2, -2*SZREG(s0) << 110 #endif << 111 SAVE_ABI_STATE << 112 call prepare_ftrace_return << 113 RESTORE_ABI_STATE << 114 ret << 115 #endif 161 #endif 116 162 117 /* !! 163 /* arg1: Get the location of the parent's return address */ 118 * A pseudo representation for the function tr !! 164 #ifdef KBUILD_MCOUNT_RA_ADDRESS 119 * (*ftrace_trace_function)(ra_to_caller, ra_t !! 165 #ifdef CONFIG_DYNAMIC_FTRACE 120 */ !! 166 PTR_L a0, PT_R12(sp) 121 .Ldo_trace: !! 167 #else 122 REG_L a1, -SZREG(s0) !! 168 move a0, MCOUNT_RA_ADDRESS_REG 123 mv a0, ra << 124 << 125 SAVE_ABI_STATE << 126 jalr t5 << 127 RESTORE_ABI_STATE << 128 ret << 129 SYM_FUNC_END(_mcount) << 130 #endif 169 #endif 131 EXPORT_SYMBOL(_mcount) !! 170 bnez a0, 1f /* non-leaf func: stored in MCOUNT_RA_ADDRESS_REG */ >> 171 nop >> 172 #endif >> 173 PTR_LA a0, PT_R1(sp) /* leaf func: the location in current stack */ >> 174 1: >> 175 >> 176 /* arg2: Get self return address */ >> 177 #ifdef CONFIG_DYNAMIC_FTRACE >> 178 PTR_L a1, PT_R31(sp) >> 179 #else >> 180 move a1, ra >> 181 #endif >> 182 >> 183 /* arg3: Get frame pointer of current stack */ >> 184 #ifdef CONFIG_64BIT >> 185 PTR_LA a2, PT_SIZE(sp) >> 186 #else >> 187 PTR_LA a2, (PT_SIZE+8)(sp) >> 188 #endif >> 189 >> 190 jal prepare_ftrace_return >> 191 nop >> 192 MCOUNT_RESTORE_REGS >> 193 #ifndef CONFIG_DYNAMIC_FTRACE >> 194 #ifdef CONFIG_32BIT >> 195 addiu sp, sp, 8 >> 196 #endif >> 197 #endif >> 198 RETURN_BACK >> 199 END(ftrace_graph_caller) >> 200 >> 201 .align 2 >> 202 .globl return_to_handler >> 203 return_to_handler: >> 204 PTR_SUBU sp, PT_SIZE >> 205 PTR_S v0, PT_R2(sp) >> 206 >> 207 jal ftrace_return_to_handler >> 208 PTR_S v1, PT_R3(sp) >> 209 >> 210 /* restore the real parent address: v0 -> ra */ >> 211 move ra, v0 >> 212 >> 213 PTR_L v0, PT_R2(sp) >> 214 PTR_L v1, PT_R3(sp) >> 215 jr ra >> 216 PTR_ADDIU sp, PT_SIZE >> 217 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ >> 218 >> 219 .set at >> 220 .set reorder
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.