1/* 2 * MIPS specific _mcount support 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> 11 */ 12 13#include <asm/regdef.h> 14#include <asm/stackframe.h> 15#include <asm/ftrace.h> 16 17 .text 18 .set noreorder 19 .set noat 20 21 .macro MCOUNT_SAVE_REGS 22 PTR_SUBU sp, PT_SIZE 23 PTR_S ra, PT_R31(sp) 24 PTR_S AT, PT_R1(sp) 25 PTR_S a0, PT_R4(sp) 26 PTR_S a1, PT_R5(sp) 27 PTR_S a2, PT_R6(sp) 28 PTR_S a3, PT_R7(sp) 29#ifdef CONFIG_64BIT 30 PTR_S a4, PT_R8(sp) 31 PTR_S a5, PT_R9(sp) 32 PTR_S a6, PT_R10(sp) 33 PTR_S a7, PT_R11(sp) 34#endif 35 .endm 36 37 .macro MCOUNT_RESTORE_REGS 38 PTR_L ra, PT_R31(sp) 39 PTR_L AT, PT_R1(sp) 40 PTR_L a0, PT_R4(sp) 41 PTR_L a1, PT_R5(sp) 42 PTR_L a2, PT_R6(sp) 43 PTR_L a3, PT_R7(sp) 44#ifdef CONFIG_64BIT 45 PTR_L a4, PT_R8(sp) 46 PTR_L a5, PT_R9(sp) 47 PTR_L a6, PT_R10(sp) 48 PTR_L a7, PT_R11(sp) 49#endif 50 PTR_ADDIU sp, PT_SIZE 51 .endm 52 53 .macro RETURN_BACK 54 jr ra 55 move ra, AT 56 .endm 57 58/* 59 * The -mmcount-ra-address option of gcc 4.5 uses register $12 to pass 60 * the location of the parent's return address. 61 */ 62#define MCOUNT_RA_ADDRESS_REG $12 63 64#ifdef CONFIG_DYNAMIC_FTRACE 65 66NESTED(ftrace_caller, PT_SIZE, ra) 67 .globl _mcount 68_mcount: 69 b ftrace_stub 70#ifdef CONFIG_32BIT 71 addiu sp,sp,8 72#else 73 nop 74#endif 75 76 /* When tracing is activated, it calls ftrace_caller+8 (aka here) */ 77 MCOUNT_SAVE_REGS 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 97ftrace_call: 98 nop /* a placeholder for the call to a real tracing function */ 99 move a1, AT /* arg2: parent's return address */ 100 101#ifdef CONFIG_FUNCTION_GRAPH_TRACER 102 .globl ftrace_graph_call 103ftrace_graph_call: 104 nop 105 nop 106#endif 107 108 MCOUNT_RESTORE_REGS 109 .globl ftrace_stub 110ftrace_stub: 111 RETURN_BACK 112 END(ftrace_caller) 113 114#else /* ! CONFIG_DYNAMIC_FTRACE */ 115 116NESTED(_mcount, PT_SIZE, ra) 117 PTR_LA t1, ftrace_stub 118 PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */ 119 bne t1, t2, static_trace 120 nop 121 122#ifdef CONFIG_FUNCTION_GRAPH_TRACER 123 PTR_L t3, ftrace_graph_return 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 nop 133 134static_trace: 135 MCOUNT_SAVE_REGS 136 137 move a0, ra /* arg1: self return address */ 138 jalr t2 /* (1) call *ftrace_trace_function */ 139 move a1, AT /* arg2: parent's return address */ 140 141 MCOUNT_RESTORE_REGS 142 .globl ftrace_stub 143ftrace_stub: 144 RETURN_BACK 145 END(_mcount) 146 147#endif /* ! CONFIG_DYNAMIC_FTRACE */ 148 149#ifdef CONFIG_FUNCTION_GRAPH_TRACER 150 151NESTED(ftrace_graph_caller, PT_SIZE, ra) 152#ifndef CONFIG_DYNAMIC_FTRACE 153 MCOUNT_SAVE_REGS 154#endif 155 156 /* arg1: Get the location of the parent's return address */ 157#ifdef KBUILD_MCOUNT_RA_ADDRESS 158#ifdef CONFIG_DYNAMIC_FTRACE 159 PTR_L a0, PT_R12(sp) 160#else 161 move a0, MCOUNT_RA_ADDRESS_REG 162#endif 163 bnez a0, 1f /* non-leaf func: stored in MCOUNT_RA_ADDRESS_REG */ 164 nop 165#endif 166 PTR_LA a0, PT_R1(sp) /* leaf func: the location in current stack */ 1671: 168 169 /* arg2: Get self return address */ 170#ifdef CONFIG_DYNAMIC_FTRACE 171 PTR_L a1, PT_R31(sp) 172#else 173 move a1, ra 174#endif 175 176 /* arg3: Get frame pointer of current stack */ 177#ifdef CONFIG_64BIT 178 PTR_LA a2, PT_SIZE(sp) 179#else 180 PTR_LA a2, (PT_SIZE+8)(sp) 181#endif 182 183 jal prepare_ftrace_return 184 nop 185 MCOUNT_RESTORE_REGS 186 RETURN_BACK 187 END(ftrace_graph_caller) 188 189 .align 2 190 .globl return_to_handler 191return_to_handler: 192 PTR_SUBU sp, PT_SIZE 193 PTR_S v0, PT_R2(sp) 194 195 jal ftrace_return_to_handler 196 PTR_S v1, PT_R3(sp) 197 198 /* restore the real parent address: v0 -> ra */ 199 move ra, v0 200 201 PTR_L v0, PT_R2(sp) 202 PTR_L v1, PT_R3(sp) 203 jr ra 204 PTR_ADDIU sp, PT_SIZE 205#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 206 207 .set at 208 .set reorder 209