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 >> 68 _mcount: >> 69 b ftrace_stub >> 70 #ifdef CONFIG_32BIT >> 71 addiu sp,sp,8 96 #else 72 #else 97 lgr %r2,%r0 !! 73 nop 98 aghi %r2,-MCOUNT_INSN_SIZE !! 74 #endif 99 larl %r4,function_trace_op !! 75 100 lg %r4,0(%r4) !! 76 /* When tracing is activated, it calls ftrace_caller+8 (aka here) */ 101 larl %r1,ftrace_func !! 77 MCOUNT_SAVE_REGS 102 lg %r1,0(%r1) !! 78 #ifdef KBUILD_MCOUNT_RA_ADDRESS 103 #endif !! 79 PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp) 104 lgr %r3,%r14 !! 80 #endif 105 la %r5,STACK_FREGS(%r15) !! 81 106 BASR_EX %r14,%r1 !! 82 PTR_SUBU a0, ra, 8 /* arg1: self address */ 107 #ifdef CONFIG_FUNCTION_GRAPH_TRACER !! 83 PTR_LA t1, _stext 108 # The j instruction gets runtime patched to a !! 84 sltu t2, a0, t1 /* t2 = (a0 < _stext) */ 109 # See ftrace_enable_ftrace_graph_caller. !! 85 PTR_LA t1, _etext 110 SYM_INNER_LABEL(ftrace_graph_caller, SYM_L_GLO !! 86 sltu t3, t1, a0 /* t3 = (a0 > _etext) */ 111 j .Lftrace_graph_caller_end !! 87 or t1, t2, t3 112 lmg %r2,%r3,(STACK_FREGS_PTREGS_GP !! 88 beqz t1, ftrace_call 113 lg %r4,(STACK_FREGS_PTREGS_PSW+8) !! 89 nop 114 brasl %r14,prepare_ftrace_return !! 90 #if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) 115 stg %r2,(STACK_FREGS_PTREGS_GPRS+1 !! 91 PTR_SUBU a0, a0, 16 /* arg1: adjust to module's recorded callsite */ 116 .Lftrace_graph_caller_end: << 117 #endif << 118 lg %r0,(STACK_FREGS_PTREGS_PSW+8) << 119 #ifdef MARCH_HAS_Z196_FEATURES << 120 ltg %r1,STACK_FREGS_PTREGS_ORIG_GP << 121 locgrz %r1,%r0 << 122 #else 92 #else 123 lg %r1,STACK_FREGS_PTREGS_ORIG_GP !! 93 PTR_SUBU a0, a0, 12 124 ltgr %r1,%r1 !! 94 #endif 125 jnz 0f !! 95 126 lgr %r1,%r0 !! 96 .globl ftrace_call 127 #endif !! 97 ftrace_call: 128 0: lmg %r2,%r15,(STACK_FREGS_PTREGS_G !! 98 nop /* a placeholder for the call to a real tracing function */ 129 BR_EX %r1 !! 99 move a1, AT /* arg2: parent's return address */ 130 SYM_CODE_END(ftrace_common) << 131 100 132 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 101 #ifdef CONFIG_FUNCTION_GRAPH_TRACER >> 102 .globl ftrace_graph_call >> 103 ftrace_graph_call: >> 104 nop >> 105 nop >> 106 #endif >> 107 >> 108 MCOUNT_RESTORE_REGS >> 109 .globl ftrace_stub >> 110 ftrace_stub: >> 111 RETURN_BACK >> 112 END(ftrace_caller) >> 113 >> 114 #else /* ! CONFIG_DYNAMIC_FTRACE */ >> 115 >> 116 NESTED(_mcount, PT_SIZE, ra) >> 117 PTR_LA t1, ftrace_stub >> 118 PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */ >> 119 beq t1, t2, fgraph_trace >> 120 nop >> 121 >> 122 MCOUNT_SAVE_REGS >> 123 >> 124 move a0, ra /* arg1: self return address */ >> 125 jalr t2 /* (1) call *ftrace_trace_function */ >> 126 move a1, AT /* arg2: parent's return address */ >> 127 >> 128 MCOUNT_RESTORE_REGS >> 129 >> 130 fgraph_trace: >> 131 #ifdef CONFIG_FUNCTION_GRAPH_TRACER >> 132 PTR_LA t1, ftrace_stub >> 133 PTR_L t3, ftrace_graph_return >> 134 bne t1, t3, ftrace_graph_caller >> 135 nop >> 136 PTR_LA t1, ftrace_graph_entry_stub >> 137 PTR_L t3, ftrace_graph_entry >> 138 bne t1, t3, ftrace_graph_caller >> 139 nop >> 140 #endif >> 141 >> 142 #ifdef CONFIG_32BIT >> 143 addiu sp, sp, 8 >> 144 #endif >> 145 >> 146 .globl ftrace_stub >> 147 ftrace_stub: >> 148 RETURN_BACK >> 149 END(_mcount) >> 150 >> 151 #endif /* ! CONFIG_DYNAMIC_FTRACE */ >> 152 >> 153 #ifdef CONFIG_FUNCTION_GRAPH_TRACER >> 154 >> 155 NESTED(ftrace_graph_caller, PT_SIZE, ra) >> 156 #ifndef CONFIG_DYNAMIC_FTRACE >> 157 MCOUNT_SAVE_REGS >> 158 #endif >> 159 >> 160 /* arg1: Get the location of the parent's return address */ >> 161 #ifdef KBUILD_MCOUNT_RA_ADDRESS >> 162 #ifdef CONFIG_DYNAMIC_FTRACE >> 163 PTR_L a0, PT_R12(sp) >> 164 #else >> 165 move a0, MCOUNT_RA_ADDRESS_REG >> 166 #endif >> 167 bnez a0, 1f /* non-leaf func: stored in MCOUNT_RA_ADDRESS_REG */ >> 168 nop >> 169 #endif >> 170 PTR_LA a0, PT_R1(sp) /* leaf func: the location in current stack */ >> 171 1: >> 172 >> 173 /* arg2: Get self return address */ >> 174 #ifdef CONFIG_DYNAMIC_FTRACE >> 175 PTR_L a1, PT_R31(sp) >> 176 #else >> 177 move a1, ra >> 178 #endif >> 179 >> 180 /* arg3: Get frame pointer of current stack */ >> 181 #ifdef CONFIG_64BIT >> 182 PTR_LA a2, PT_SIZE(sp) >> 183 #else >> 184 PTR_LA a2, (PT_SIZE+8)(sp) >> 185 #endif >> 186 >> 187 jal prepare_ftrace_return >> 188 nop >> 189 MCOUNT_RESTORE_REGS >> 190 #ifndef CONFIG_DYNAMIC_FTRACE >> 191 #ifdef CONFIG_32BIT >> 192 addiu sp, sp, 8 >> 193 #endif >> 194 #endif >> 195 RETURN_BACK >> 196 END(ftrace_graph_caller) 133 197 134 SYM_FUNC_START(return_to_handler) !! 198 .align 2 135 stmg %r2,%r5,32(%r15) !! 199 .globl return_to_handler 136 lgr %r1,%r15 !! 200 return_to_handler: 137 aghi %r15,-(STACK_FRAME_OVERHEAD+__ !! 201 PTR_SUBU sp, PT_SIZE 138 stg %r1,__SF_BACKCHAIN(%r15) !! 202 PTR_S v0, PT_R2(sp) 139 la %r3,STACK_FRAME_OVERHEAD(%r15) !! 203 140 stg %r1,__FGRAPH_RET_FP(%r3) !! 204 jal ftrace_return_to_handler 141 stg %r2,__FGRAPH_RET_GPR2(%r3) !! 205 PTR_S v1, PT_R3(sp) 142 lgr %r2,%r3 !! 206 143 brasl %r14,ftrace_return_to_handler !! 207 /* restore the real parent address: v0 -> ra */ 144 aghi %r15,STACK_FRAME_OVERHEAD+__FG !! 208 move ra, v0 145 lgr %r14,%r2 !! 209 146 lmg %r2,%r5,32(%r15) !! 210 PTR_L v0, PT_R2(sp) 147 BR_EX %r14 !! 211 PTR_L v1, PT_R3(sp) 148 SYM_FUNC_END(return_to_handler) !! 212 jr ra 149 !! 213 PTR_ADDIU sp, PT_SIZE 150 #endif !! 214 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 151 #endif /* CONFIG_FUNCTION_TRACER */ << 152 << 153 SYM_CODE_START(ftrace_shared_hotpatch_trampoli << 154 lmg %r0,%r1,2(%r1) << 155 br %r1 << 156 SYM_INNER_LABEL(ftrace_shared_hotpatch_trampol << 157 SYM_CODE_END(ftrace_shared_hotpatch_trampoline << 158 << 159 #ifdef CONFIG_EXPOLINE << 160 SYM_CODE_START(ftrace_shared_hotpatch_trampoli << 161 lmg %r0,%r1,2(%r1) << 162 exrl %r0,0f << 163 j . << 164 0: br %r1 << 165 SYM_INNER_LABEL(ftrace_shared_hotpatch_trampol << 166 SYM_CODE_END(ftrace_shared_hotpatch_trampoline << 167 #endif /* CONFIG_EXPOLINE */ << 168 << 169 #ifdef CONFIG_RETHOOK << 170 << 171 SYM_CODE_START(arch_rethook_trampoline) << 172 stg %r14,(__SF_GPRS+8*8)(%r15) << 173 lay %r15,-STACK_FRAME_SIZE_PTREGS( << 174 stmg %r0,%r14,STACK_PTREGS_GPRS(%r1 << 175 << 176 # store original stack pointer in back << 177 lay %r7,STACK_FRAME_SIZE_PTREGS(%r << 178 stg %r7,__SF_BACKCHAIN(%r15) << 179 stg %r7,STACK_PTREGS_GPRS+(15*8)(% << 180 << 181 # store full psw << 182 epsw %r2,%r3 << 183 risbg %r3,%r2,0,31,32 << 184 stg %r3,STACK_PTREGS_PSW(%r15) << 185 larl %r1,arch_rethook_trampoline << 186 stg %r1,STACK_PTREGS_PSW+8(%r15) << 187 << 188 lay %r2,STACK_PTREGS(%r15) << 189 brasl %r14,arch_rethook_trampoline_c << 190 << 191 mvc __SF_EMPTY(16,%r7),STACK_PTREG << 192 lmg %r0,%r15,STACK_PTREGS_GPRS(%r1 << 193 lpswe __SF_EMPTY(%r15) << 194 SYM_CODE_END(arch_rethook_trampoline) << 195 215 196 #endif /* CONFIG_RETHOOK */ !! 216 .set at >> 217 .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.