1 /* SPDX-License-Identifier: GPL-2.0 */ << 2 /* 1 /* 3 * Copyright IBM Corp. 2008, 2009 !! 2 * MIPS specific _mcount support 4 * 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> 5 */ 11 */ 6 12 7 #include <linux/linkage.h> !! 13 #include <asm/export.h> 8 #include <asm/asm-offsets.h> !! 14 #include <asm/regdef.h> >> 15 #include <asm/stackframe.h> 9 #include <asm/ftrace.h> 16 #include <asm/ftrace.h> 10 #include <asm/nospec-insn.h> !! 17 11 #include <asm/ptrace.h> !! 18 .text 12 #include <asm/march.h> !! 19 .set noreorder 13 !! 20 .set noat 14 #define STACK_FRAME_SIZE_PTREGS (STACK !! 21 15 #define STACK_PTREGS (STACK !! 22 .macro MCOUNT_SAVE_REGS 16 #define STACK_PTREGS_GPRS (STACK !! 23 PTR_SUBU sp, PT_SIZE 17 #define STACK_PTREGS_PSW (STACK !! 24 PTR_S ra, PT_R31(sp) 18 !! 25 PTR_S AT, PT_R1(sp) 19 #define STACK_FRAME_SIZE_FREGS (STACK !! 26 PTR_S a0, PT_R4(sp) 20 #define STACK_FREGS (STACK !! 27 PTR_S a1, PT_R5(sp) 21 #define STACK_FREGS_PTREGS (STACK !! 28 PTR_S a2, PT_R6(sp) 22 #define STACK_FREGS_PTREGS_GPRS (STACK !! 29 PTR_S a3, PT_R7(sp) 23 #define STACK_FREGS_PTREGS_PSW (STACK !! 30 #ifdef CONFIG_64BIT 24 #define STACK_FREGS_PTREGS_ORIG_GPR2 (STACK !! 31 PTR_S a4, PT_R8(sp) 25 #define STACK_FREGS_PTREGS_FLAGS (STACK !! 32 PTR_S a5, PT_R9(sp) 26 !! 33 PTR_S a6, PT_R10(sp) 27 /* packed stack: allocate just enough for r14, !! 34 PTR_S a7, PT_R11(sp) 28 #define TRACED_FUNC_FRAME_SIZE 24 !! 35 #endif 29 !! 36 .endm 30 #ifdef CONFIG_FUNCTION_TRACER !! 37 31 !! 38 .macro MCOUNT_RESTORE_REGS 32 GEN_BR_THUNK %r1 !! 39 PTR_L ra, PT_R31(sp) 33 GEN_BR_THUNK %r14 !! 40 PTR_L AT, PT_R1(sp) 34 !! 41 PTR_L a0, PT_R4(sp) 35 .section .kprobes.text, "ax" !! 42 PTR_L a1, PT_R5(sp) 36 !! 43 PTR_L a2, PT_R6(sp) 37 SYM_FUNC_START(ftrace_stub) !! 44 PTR_L a3, PT_R7(sp) 38 BR_EX %r14 !! 45 #ifdef CONFIG_64BIT 39 SYM_FUNC_END(ftrace_stub) !! 46 PTR_L a4, PT_R8(sp) 40 !! 47 PTR_L a5, PT_R9(sp) 41 SYM_CODE_START(ftrace_stub_direct_tramp) !! 48 PTR_L a6, PT_R10(sp) 42 lgr %r1, %r0 !! 49 PTR_L a7, PT_R11(sp) 43 BR_EX %r1 !! 50 #endif 44 SYM_CODE_END(ftrace_stub_direct_tramp) !! 51 PTR_ADDIU sp, PT_SIZE 45 << 46 .macro ftrace_regs_entry, allregs=0 << 47 stg %r14,(__SF_GPRS+8*8)(%r15) << 48 << 49 .if \allregs == 1 << 50 # save psw mask << 51 # don't put any instructions clobberin << 52 epsw %r1,%r14 << 53 risbg %r14,%r1,0,31,32 << 54 .endif << 55 << 56 lgr %r1,%r15 << 57 # allocate stack frame for ftrace_call << 58 aghi %r15,-TRACED_FUNC_FRAME_SIZE << 59 stg %r1,__SF_BACKCHAIN(%r15) << 60 stg %r0,(__SF_GPRS+8*8)(%r15) << 61 stg %r15,(__SF_GPRS+9*8)(%r15) << 62 # allocate ftrace_regs and stack frame << 63 aghi %r15,-STACK_FRAME_SIZE_FREGS << 64 stg %r1,(STACK_FREGS_PTREGS_GPRS+1 << 65 xc STACK_FREGS_PTREGS_ORIG_GPR2(8 << 66 << 67 .if \allregs == 1 << 68 stg %r14,(STACK_FREGS_PTREGS_PSW)( << 69 mvghi STACK_FREGS_PTREGS_FLAGS(%r15) << 70 .else << 71 xc STACK_FREGS_PTREGS_FLAGS(8,%r1 << 72 .endif << 73 << 74 lg %r14,(__SF_GPRS+8*8)(%r1) << 75 aghi %r1,-TRACED_FUNC_FRAME_SIZE << 76 stg %r1,__SF_BACKCHAIN(%r15) << 77 stg %r0,(STACK_FREGS_PTREGS_PSW+8) << 78 stmg %r2,%r14,(STACK_FREGS_PTREGS_G << 79 .endm 52 .endm 80 53 81 SYM_CODE_START(ftrace_regs_caller) !! 54 .macro RETURN_BACK 82 ftrace_regs_entry 1 !! 55 jr ra 83 j ftrace_common !! 56 move ra, AT 84 SYM_CODE_END(ftrace_regs_caller) !! 57 .endm 85 !! 58 86 SYM_CODE_START(ftrace_caller) !! 59 /* 87 ftrace_regs_entry 0 !! 60 * The -mmcount-ra-address option of gcc 4.5 uses register $12 to pass 88 j ftrace_common !! 61 * the location of the parent's return address. 89 SYM_CODE_END(ftrace_caller) !! 62 */ 90 !! 63 #define MCOUNT_RA_ADDRESS_REG $12 91 SYM_CODE_START(ftrace_common) !! 64 92 #ifdef MARCH_HAS_Z196_FEATURES !! 65 #ifdef CONFIG_DYNAMIC_FTRACE 93 aghik %r2,%r0,-MCOUNT_INSN_SIZE !! 66 94 lgrl %r4,function_trace_op !! 67 NESTED(ftrace_caller, PT_SIZE, ra) 95 lgrl %r1,ftrace_func !! 68 .globl _mcount 96 #else !! 69 _mcount: 97 lgr %r2,%r0 !! 70 EXPORT_SYMBOL(_mcount) 98 aghi %r2,-MCOUNT_INSN_SIZE !! 71 b ftrace_stub 99 larl %r4,function_trace_op !! 72 #ifdef CONFIG_32BIT 100 lg %r4,0(%r4) !! 73 addiu sp,sp,8 101 larl %r1,ftrace_func !! 74 #else 102 lg %r1,0(%r1) !! 75 nop 103 #endif !! 76 #endif 104 lgr %r3,%r14 !! 77 105 la %r5,STACK_FREGS(%r15) !! 78 /* When tracing is activated, it calls ftrace_caller+8 (aka here) */ 106 BASR_EX %r14,%r1 !! 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 */ >> 102 107 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 103 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 108 # The j instruction gets runtime patched to a !! 104 .globl ftrace_graph_call 109 # See ftrace_enable_ftrace_graph_caller. !! 105 ftrace_graph_call: 110 SYM_INNER_LABEL(ftrace_graph_caller, SYM_L_GLO !! 106 nop 111 j .Lftrace_graph_caller_end !! 107 nop 112 lmg %r2,%r3,(STACK_FREGS_PTREGS_GP !! 108 #endif 113 lg %r4,(STACK_FREGS_PTREGS_PSW+8) !! 109 114 brasl %r14,prepare_ftrace_return !! 110 MCOUNT_RESTORE_REGS 115 stg %r2,(STACK_FREGS_PTREGS_GPRS+1 !! 111 .globl ftrace_stub 116 .Lftrace_graph_caller_end: !! 112 ftrace_stub: 117 #endif !! 113 RETURN_BACK 118 lg %r0,(STACK_FREGS_PTREGS_PSW+8) !! 114 END(ftrace_caller) 119 #ifdef MARCH_HAS_Z196_FEATURES !! 115 120 ltg %r1,STACK_FREGS_PTREGS_ORIG_GP !! 116 #else /* ! CONFIG_DYNAMIC_FTRACE */ 121 locgrz %r1,%r0 !! 117 122 #else !! 118 NESTED(_mcount, PT_SIZE, ra) 123 lg %r1,STACK_FREGS_PTREGS_ORIG_GP !! 119 EXPORT_SYMBOL(_mcount) 124 ltgr %r1,%r1 !! 120 PTR_LA t1, ftrace_stub 125 jnz 0f !! 121 PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */ 126 lgr %r1,%r0 !! 122 bne t1, t2, static_trace 127 #endif !! 123 nop 128 0: lmg %r2,%r15,(STACK_FREGS_PTREGS_G !! 124 129 BR_EX %r1 !! 125 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 130 SYM_CODE_END(ftrace_common) !! 126 PTR_L t3, ftrace_graph_return >> 127 bne t1, t3, ftrace_graph_caller >> 128 nop >> 129 PTR_LA t1, ftrace_graph_entry_stub >> 130 PTR_L t3, ftrace_graph_entry >> 131 bne t1, t3, ftrace_graph_caller >> 132 nop >> 133 #endif >> 134 b ftrace_stub >> 135 #ifdef CONFIG_32BIT >> 136 addiu sp, sp, 8 >> 137 #else >> 138 nop >> 139 #endif >> 140 >> 141 static_trace: >> 142 MCOUNT_SAVE_REGS >> 143 >> 144 move a0, ra /* arg1: self return address */ >> 145 jalr t2 /* (1) call *ftrace_trace_function */ >> 146 move a1, AT /* arg2: parent's return address */ >> 147 >> 148 MCOUNT_RESTORE_REGS >> 149 #ifdef CONFIG_32BIT >> 150 addiu sp, sp, 8 >> 151 #endif >> 152 .globl ftrace_stub >> 153 ftrace_stub: >> 154 RETURN_BACK >> 155 END(_mcount) >> 156 >> 157 #endif /* ! CONFIG_DYNAMIC_FTRACE */ 131 158 132 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 159 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 133 160 134 SYM_FUNC_START(return_to_handler) !! 161 NESTED(ftrace_graph_caller, PT_SIZE, ra) 135 stmg %r2,%r5,32(%r15) !! 162 #ifndef CONFIG_DYNAMIC_FTRACE 136 lgr %r1,%r15 !! 163 MCOUNT_SAVE_REGS 137 aghi %r15,-(STACK_FRAME_OVERHEAD+__ !! 164 #endif 138 stg %r1,__SF_BACKCHAIN(%r15) !! 165 139 la %r3,STACK_FRAME_OVERHEAD(%r15) !! 166 /* arg1: Get the location of the parent's return address */ 140 stg %r1,__FGRAPH_RET_FP(%r3) !! 167 #ifdef KBUILD_MCOUNT_RA_ADDRESS 141 stg %r2,__FGRAPH_RET_GPR2(%r3) !! 168 #ifdef CONFIG_DYNAMIC_FTRACE 142 lgr %r2,%r3 !! 169 PTR_L a0, PT_R12(sp) 143 brasl %r14,ftrace_return_to_handler !! 170 #else 144 aghi %r15,STACK_FRAME_OVERHEAD+__FG !! 171 move a0, MCOUNT_RA_ADDRESS_REG 145 lgr %r14,%r2 !! 172 #endif 146 lmg %r2,%r5,32(%r15) !! 173 bnez a0, 1f /* non-leaf func: stored in MCOUNT_RA_ADDRESS_REG */ 147 BR_EX %r14 !! 174 nop 148 SYM_FUNC_END(return_to_handler) !! 175 #endif 149 !! 176 PTR_LA a0, PT_R1(sp) /* leaf func: the location in current stack */ 150 #endif !! 177 1: 151 #endif /* CONFIG_FUNCTION_TRACER */ !! 178 152 !! 179 /* arg2: Get self return address */ 153 SYM_CODE_START(ftrace_shared_hotpatch_trampoli !! 180 #ifdef CONFIG_DYNAMIC_FTRACE 154 lmg %r0,%r1,2(%r1) !! 181 PTR_L a1, PT_R31(sp) 155 br %r1 !! 182 #else 156 SYM_INNER_LABEL(ftrace_shared_hotpatch_trampol !! 183 move a1, ra 157 SYM_CODE_END(ftrace_shared_hotpatch_trampoline !! 184 #endif 158 !! 185 159 #ifdef CONFIG_EXPOLINE !! 186 /* arg3: Get frame pointer of current stack */ 160 SYM_CODE_START(ftrace_shared_hotpatch_trampoli !! 187 #ifdef CONFIG_64BIT 161 lmg %r0,%r1,2(%r1) !! 188 PTR_LA a2, PT_SIZE(sp) 162 exrl %r0,0f !! 189 #else 163 j . !! 190 PTR_LA a2, (PT_SIZE+8)(sp) 164 0: br %r1 !! 191 #endif 165 SYM_INNER_LABEL(ftrace_shared_hotpatch_trampol !! 192 166 SYM_CODE_END(ftrace_shared_hotpatch_trampoline !! 193 jal prepare_ftrace_return 167 #endif /* CONFIG_EXPOLINE */ !! 194 nop 168 !! 195 MCOUNT_RESTORE_REGS 169 #ifdef CONFIG_RETHOOK !! 196 #ifndef CONFIG_DYNAMIC_FTRACE 170 !! 197 #ifdef CONFIG_32BIT 171 SYM_CODE_START(arch_rethook_trampoline) !! 198 addiu sp, sp, 8 172 stg %r14,(__SF_GPRS+8*8)(%r15) !! 199 #endif 173 lay %r15,-STACK_FRAME_SIZE_PTREGS( !! 200 #endif 174 stmg %r0,%r14,STACK_PTREGS_GPRS(%r1 !! 201 RETURN_BACK 175 !! 202 END(ftrace_graph_caller) 176 # store original stack pointer in back !! 203 177 lay %r7,STACK_FRAME_SIZE_PTREGS(%r !! 204 .align 2 178 stg %r7,__SF_BACKCHAIN(%r15) !! 205 .globl return_to_handler 179 stg %r7,STACK_PTREGS_GPRS+(15*8)(% !! 206 return_to_handler: 180 !! 207 PTR_SUBU sp, PT_SIZE 181 # store full psw !! 208 PTR_S v0, PT_R2(sp) 182 epsw %r2,%r3 !! 209 183 risbg %r3,%r2,0,31,32 !! 210 jal ftrace_return_to_handler 184 stg %r3,STACK_PTREGS_PSW(%r15) !! 211 PTR_S v1, PT_R3(sp) 185 larl %r1,arch_rethook_trampoline !! 212 186 stg %r1,STACK_PTREGS_PSW+8(%r15) !! 213 /* restore the real parent address: v0 -> ra */ 187 !! 214 move ra, v0 188 lay %r2,STACK_PTREGS(%r15) !! 215 189 brasl %r14,arch_rethook_trampoline_c !! 216 PTR_L v0, PT_R2(sp) 190 !! 217 PTR_L v1, PT_R3(sp) 191 mvc __SF_EMPTY(16,%r7),STACK_PTREG !! 218 jr ra 192 lmg %r0,%r15,STACK_PTREGS_GPRS(%r1 !! 219 PTR_ADDIU sp, PT_SIZE 193 lpswe __SF_EMPTY(%r15) !! 220 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 194 SYM_CODE_END(arch_rethook_trampoline) << 195 221 196 #endif /* CONFIG_RETHOOK */ !! 222 .set at >> 223 .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.