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