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 <linux/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 >> 69 _mcount: >> 70 EXPORT_SYMBOL(_mcount) >> 71 b ftrace_stub >> 72 #ifdef CONFIG_32BIT >> 73 addiu sp,sp,8 96 #else 74 #else 97 lgr %r2,%r0 !! 75 nop 98 aghi %r2,-MCOUNT_INSN_SIZE !! 76 #endif 99 larl %r4,function_trace_op !! 77 100 lg %r4,0(%r4) !! 78 /* When tracing is activated, it calls ftrace_caller+8 (aka here) */ 101 larl %r1,ftrace_func !! 79 MCOUNT_SAVE_REGS 102 lg %r1,0(%r1) !! 80 #ifdef KBUILD_MCOUNT_RA_ADDRESS 103 #endif !! 81 PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp) 104 lgr %r3,%r14 !! 82 #endif 105 la %r5,STACK_FREGS(%r15) !! 83 106 BASR_EX %r14,%r1 !! 84 PTR_SUBU a0, ra, 8 /* arg1: self address */ 107 #ifdef CONFIG_FUNCTION_GRAPH_TRACER !! 85 PTR_LA t1, _stext 108 # The j instruction gets runtime patched to a !! 86 sltu t2, a0, t1 /* t2 = (a0 < _stext) */ 109 # See ftrace_enable_ftrace_graph_caller. !! 87 PTR_LA t1, _etext 110 SYM_INNER_LABEL(ftrace_graph_caller, SYM_L_GLO !! 88 sltu t3, t1, a0 /* t3 = (a0 > _etext) */ 111 j .Lftrace_graph_caller_end !! 89 or t1, t2, t3 112 lmg %r2,%r3,(STACK_FREGS_PTREGS_GP !! 90 beqz t1, ftrace_call 113 lg %r4,(STACK_FREGS_PTREGS_PSW+8) !! 91 nop 114 brasl %r14,prepare_ftrace_return !! 92 #if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) 115 stg %r2,(STACK_FREGS_PTREGS_GPRS+1 !! 93 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 94 #else 123 lg %r1,STACK_FREGS_PTREGS_ORIG_GP !! 95 PTR_SUBU a0, a0, 12 124 ltgr %r1,%r1 !! 96 #endif 125 jnz 0f !! 97 126 lgr %r1,%r0 !! 98 .globl ftrace_call 127 #endif !! 99 ftrace_call: 128 0: lmg %r2,%r15,(STACK_FREGS_PTREGS_G !! 100 nop /* a placeholder for the call to a real tracing function */ 129 BR_EX %r1 !! 101 move a1, AT /* arg2: parent's return address */ 130 SYM_CODE_END(ftrace_common) << 131 102 132 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 103 #ifdef CONFIG_FUNCTION_GRAPH_TRACER >> 104 .globl ftrace_graph_call >> 105 ftrace_graph_call: >> 106 nop >> 107 nop >> 108 #endif >> 109 >> 110 MCOUNT_RESTORE_REGS >> 111 .globl ftrace_stub >> 112 ftrace_stub: >> 113 RETURN_BACK >> 114 END(ftrace_caller) >> 115 >> 116 #else /* ! CONFIG_DYNAMIC_FTRACE */ >> 117 >> 118 NESTED(_mcount, PT_SIZE, ra) >> 119 EXPORT_SYMBOL(_mcount) >> 120 PTR_LA t1, ftrace_stub >> 121 PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */ >> 122 beq t1, t2, fgraph_trace >> 123 nop >> 124 >> 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 >> 143 #endif >> 144 >> 145 #ifdef CONFIG_32BIT >> 146 addiu sp, sp, 8 >> 147 #endif >> 148 >> 149 .globl ftrace_stub >> 150 ftrace_stub: >> 151 RETURN_BACK >> 152 END(_mcount) >> 153 >> 154 #endif /* ! CONFIG_DYNAMIC_FTRACE */ >> 155 >> 156 #ifdef CONFIG_FUNCTION_GRAPH_TRACER >> 157 >> 158 NESTED(ftrace_graph_caller, PT_SIZE, ra) >> 159 #ifndef CONFIG_DYNAMIC_FTRACE >> 160 MCOUNT_SAVE_REGS >> 161 #endif >> 162 >> 163 /* arg1: Get the location of the parent's return address */ >> 164 #ifdef KBUILD_MCOUNT_RA_ADDRESS >> 165 #ifdef CONFIG_DYNAMIC_FTRACE >> 166 PTR_L a0, PT_R12(sp) >> 167 #else >> 168 move a0, MCOUNT_RA_ADDRESS_REG >> 169 #endif >> 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) 133 200 134 SYM_FUNC_START(return_to_handler) !! 201 .align 2 135 stmg %r2,%r5,32(%r15) !! 202 .globl return_to_handler 136 lgr %r1,%r15 !! 203 return_to_handler: 137 aghi %r15,-(STACK_FRAME_OVERHEAD+__ !! 204 PTR_SUBU sp, PT_SIZE 138 stg %r1,__SF_BACKCHAIN(%r15) !! 205 PTR_S v0, PT_R2(sp) 139 la %r3,STACK_FRAME_OVERHEAD(%r15) !! 206 140 stg %r1,__FGRAPH_RET_FP(%r3) !! 207 jal ftrace_return_to_handler 141 stg %r2,__FGRAPH_RET_GPR2(%r3) !! 208 PTR_S v1, PT_R3(sp) 142 lgr %r2,%r3 !! 209 143 brasl %r14,ftrace_return_to_handler !! 210 /* restore the real parent address: v0 -> ra */ 144 aghi %r15,STACK_FRAME_OVERHEAD+__FG !! 211 move ra, v0 145 lgr %r14,%r2 !! 212 146 lmg %r2,%r5,32(%r15) !! 213 PTR_L v0, PT_R2(sp) 147 BR_EX %r14 !! 214 PTR_L v1, PT_R3(sp) 148 SYM_FUNC_END(return_to_handler) !! 215 jr ra 149 !! 216 PTR_ADDIU sp, PT_SIZE 150 #endif !! 217 #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 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.