1 /* 1 /* 2 * Low-level ftrace handling !! 2 * MIPS specific _mcount support 3 * 3 * 4 * Copyright (C) 2009 Michal Simek <monstr@mons !! 4 * This file is subject to the terms and conditions of the GNU General Public 5 * Copyright (C) 2009 PetaLogix !! 5 * License. See the file "COPYING" in the main directory of this archive for >> 6 * more details. 6 * 7 * 7 * This file is subject to the terms and condi !! 8 * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China 8 * Public License. See the file COPYING in the !! 9 * Copyright (C) 2010 DSLab, Lanzhou University, China 9 * archive for more details. !! 10 * Author: Wu Zhangjin <wuzhangjin@gmail.com> 10 */ 11 */ 11 12 12 #include <linux/linkage.h> !! 13 #include <linux/export.h> >> 14 #include <asm/regdef.h> >> 15 #include <asm/stackframe.h> >> 16 #include <asm/ftrace.h> >> 17 >> 18 .text >> 19 .set noreorder >> 20 .set noat >> 21 >> 22 .macro MCOUNT_SAVE_REGS >> 23 PTR_SUBU sp, PT_SIZE >> 24 PTR_S ra, PT_R31(sp) >> 25 PTR_S AT, PT_R1(sp) >> 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 >> 36 .endm >> 37 >> 38 .macro MCOUNT_RESTORE_REGS >> 39 PTR_L ra, PT_R31(sp) >> 40 PTR_L AT, PT_R1(sp) >> 41 PTR_L a0, PT_R4(sp) >> 42 PTR_L a1, PT_R5(sp) >> 43 PTR_L a2, PT_R6(sp) >> 44 PTR_L a3, PT_R7(sp) >> 45 #ifdef CONFIG_64BIT >> 46 PTR_L a4, PT_R8(sp) >> 47 PTR_L a5, PT_R9(sp) >> 48 PTR_L a6, PT_R10(sp) >> 49 PTR_L a7, PT_R11(sp) >> 50 #endif >> 51 PTR_ADDIU sp, PT_SIZE >> 52 .endm >> 53 >> 54 .macro RETURN_BACK >> 55 jr ra >> 56 move ra, AT >> 57 .endm >> 58 >> 59 /* >> 60 * The -mmcount-ra-address option of gcc 4.5 uses register $12 to pass >> 61 * the location of the parent's return address. >> 62 */ >> 63 #define MCOUNT_RA_ADDRESS_REG $12 13 64 14 #define NOALIGN_ENTRY(name) .globl name; n !! 65 #ifdef CONFIG_DYNAMIC_FTRACE 15 66 16 /* FIXME MS: I think that I don't need to save !! 67 NESTED(ftrace_caller, PT_SIZE, ra) 17 #define SAVE_REGS \ !! 68 .globl _mcount 18 addik r1, r1, -120; \ !! 69 _mcount: 19 swi r2, r1, 4; \ !! 70 EXPORT_SYMBOL(_mcount) 20 swi r3, r1, 8; \ !! 71 b ftrace_stub 21 swi r4, r1, 12; \ !! 72 #ifdef CONFIG_32BIT 22 swi r5, r1, 116; \ !! 73 addiu sp,sp,8 23 swi r6, r1, 16; \ !! 74 #else 24 swi r7, r1, 20; \ !! 75 nop 25 swi r8, r1, 24; \ !! 76 #endif 26 swi r9, r1, 28; \ !! 77 27 swi r10, r1, 32; \ !! 78 /* When tracing is activated, it calls ftrace_caller+8 (aka here) */ 28 swi r11, r1, 36; \ !! 79 MCOUNT_SAVE_REGS 29 swi r12, r1, 40; \ !! 80 #ifdef KBUILD_MCOUNT_RA_ADDRESS 30 swi r13, r1, 44; \ !! 81 PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp) 31 swi r14, r1, 48; \ !! 82 #endif 32 swi r16, r1, 52; \ !! 83 33 swi r17, r1, 56; \ !! 84 PTR_SUBU a0, ra, 8 /* arg1: self address */ 34 swi r18, r1, 60; \ !! 85 PTR_LA t1, _stext 35 swi r19, r1, 64; \ !! 86 sltu t2, a0, t1 /* t2 = (a0 < _stext) */ 36 swi r20, r1, 68; \ !! 87 PTR_LA t1, _etext 37 swi r21, r1, 72; \ !! 88 sltu t3, t1, a0 /* t3 = (a0 > _etext) */ 38 swi r22, r1, 76; \ !! 89 or t1, t2, t3 39 swi r23, r1, 80; \ !! 90 beqz t1, ftrace_call 40 swi r24, r1, 84; \ !! 91 nop 41 swi r25, r1, 88; \ !! 92 #if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) 42 swi r26, r1, 92; \ !! 93 PTR_SUBU a0, a0, 16 /* arg1: adjust to module's recorded callsite */ 43 swi r27, r1, 96; \ !! 94 #else 44 swi r28, r1, 100; \ !! 95 PTR_SUBU a0, a0, 12 45 swi r29, r1, 104; \ !! 96 #endif 46 swi r30, r1, 108; \ !! 97 47 swi r31, r1, 112; !! 98 .globl ftrace_call 48 !! 99 ftrace_call: 49 #define RESTORE_REGS \ !! 100 nop /* a placeholder for the call to a real tracing function */ 50 lwi r2, r1, 4; \ !! 101 move a1, AT /* arg2: parent's return address */ 51 lwi r3, r1, 8; \ << 52 lwi r4, r1, 12; \ << 53 lwi r5, r1, 116; \ << 54 lwi r6, r1, 16; \ << 55 lwi r7, r1, 20; \ << 56 lwi r8, r1, 24; \ << 57 lwi r9, r1, 28; \ << 58 lwi r10, r1, 32; \ << 59 lwi r11, r1, 36; \ << 60 lwi r12, r1, 40; \ << 61 lwi r13, r1, 44; \ << 62 lwi r14, r1, 48; \ << 63 lwi r16, r1, 52; \ << 64 lwi r17, r1, 56; \ << 65 lwi r18, r1, 60; \ << 66 lwi r19, r1, 64; \ << 67 lwi r20, r1, 68; \ << 68 lwi r21, r1, 72; \ << 69 lwi r22, r1, 76; \ << 70 lwi r23, r1, 80; \ << 71 lwi r24, r1, 84; \ << 72 lwi r25, r1, 88; \ << 73 lwi r26, r1, 92; \ << 74 lwi r27, r1, 96; \ << 75 lwi r28, r1, 100; \ << 76 lwi r29, r1, 104; \ << 77 lwi r30, r1, 108; \ << 78 lwi r31, r1, 112; \ << 79 addik r1, r1, 120; << 80 << 81 ENTRY(ftrace_stub) << 82 rtsd r15, 8; << 83 nop; << 84 102 85 ENTRY(_mcount) << 86 #ifdef CONFIG_DYNAMIC_FTRACE << 87 ENTRY(ftrace_caller) << 88 /* MS: It is just barrier which is rem << 89 rtsd r15, 8 << 90 nop << 91 #endif /* CONFIG_DYNAMIC_FTRACE */ << 92 SAVE_REGS << 93 swi r15, r1, 0; << 94 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 103 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 95 #ifndef CONFIG_DYNAMIC_FTRACE !! 104 .globl ftrace_graph_call 96 lwi r5, r0, ftrace_graph_return; !! 105 ftrace_graph_call: 97 addik r6, r0, ftrace_stub; /* asm im << 98 cmpu r5, r5, r6; /* ftrace_graph_re << 99 beqid r5, end_graph_tracer; << 100 nop; << 101 << 102 lwi r6, r0, ftrace_graph_entry; << 103 addik r5, r0, ftrace_graph_entry_stu << 104 cmpu r5, r5, r6; /* ftrace_graph_en << 105 beqid r5, end_graph_tracer; << 106 nop; << 107 #else /* CONFIG_DYNAMIC_FTRACE */ << 108 NOALIGN_ENTRY(ftrace_call_graph) << 109 /* MS: jump over graph function - repl << 110 bri end_graph_tracer << 111 #endif /* CONFIG_DYNAMIC_FTRACE */ << 112 addik r5, r1, 120; /* MS: load paren << 113 addik r6, r15, 0; /* MS: load curren << 114 bralid r15, prepare_ftrace_return; << 115 nop; << 116 /* MS: graph was taken that's why - ca << 117 brid end; << 118 nop; << 119 end_graph_tracer: << 120 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ << 121 #ifndef CONFIG_DYNAMIC_FTRACE << 122 /* MS: test function trace if is taken << 123 lwi r20, r0, ftrace_trace_function << 124 addik r6, r0, ftrace_stub; << 125 cmpu r5, r20, r6; /* ftrace_trace_f << 126 beqid r5, end; /* MS: not taken -> j << 127 nop; << 128 #else /* CONFIG_DYNAMIC_FTRACE */ << 129 NOALIGN_ENTRY(ftrace_call) << 130 /* instruction for setup imm FUNC_part1, addik << 131 nop 106 nop 132 nop !! 107 nop 133 #endif /* CONFIG_DYNAMIC_FTRACE */ !! 108 #endif 134 /* static normal trace */ !! 109 135 lwi r6, r1, 120; /* MS: load paren !! 110 MCOUNT_RESTORE_REGS 136 addik r5, r15, -4; /* MS: load curre !! 111 .globl ftrace_stub 137 /* MS: here is dependency on previous !! 112 ftrace_stub: 138 brald r15, r20; /* MS: jump to ftrac !! 113 RETURN_BACK 139 nop; !! 114 END(ftrace_caller) 140 end: !! 115 141 lwi r15, r1, 0; !! 116 #else /* ! CONFIG_DYNAMIC_FTRACE */ 142 RESTORE_REGS !! 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) 143 153 144 rtsd r15, 8; /* MS: jump back */ !! 154 #endif /* ! CONFIG_DYNAMIC_FTRACE */ 145 nop; << 146 155 147 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 156 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 148 ENTRY(return_to_handler) !! 157 149 nop; /* MS: just barrier for rtsd r15, !! 158 NESTED(ftrace_graph_caller, PT_SIZE, ra) 150 nop; !! 159 #ifndef CONFIG_DYNAMIC_FTRACE 151 SAVE_REGS !! 160 MCOUNT_SAVE_REGS 152 swi r15, r1, 0; !! 161 #endif 153 !! 162 154 /* MS: find out returning address */ !! 163 /* arg1: Get the location of the parent's return address */ 155 bralid r15, ftrace_return_to_handler; !! 164 #ifdef KBUILD_MCOUNT_RA_ADDRESS 156 nop; !! 165 #ifdef CONFIG_DYNAMIC_FTRACE 157 !! 166 PTR_L a0, PT_R12(sp) 158 /* MS: return value from ftrace_return !! 167 #else 159 * must be before restore regs because !! 168 move a0, MCOUNT_RA_ADDRESS_REG 160 addik r15, r3, 0; !! 169 #endif 161 RESTORE_REGS !! 170 bnez a0, 1f /* non-leaf func: stored in MCOUNT_RA_ADDRESS_REG */ 162 !! 171 nop 163 rtsd r15, 8; /* MS: jump back */ !! 172 #endif 164 nop; !! 173 PTR_LA a0, PT_R1(sp) /* leaf func: the location in current stack */ 165 #endif /* CONFIG_FUNCTION_TRACER */ !! 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.