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/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 64 65#ifdef CONFIG_DYNAMIC_FTRACE 66 67NESTED(ftrace_caller, PT_SIZE, ra) 68 .globl _mcount 69_mcount: 70EXPORT_SYMBOL(_mcount) 71 b ftrace_stub 72#ifdef CONFIG_32BIT 73 addiu sp,sp,8 74#else 75 nop 76#endif 77 78 /* When tracing is activated, it calls ftrace_caller+8 (aka here) */ 79 MCOUNT_SAVE_REGS 80#ifdef KBUILD_MCOUNT_RA_ADDRESS 81 PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp) 82#endif 83 84 PTR_SUBU a0, ra, 8 /* arg1: self address */ 85 PTR_LA t1, _stext 86 sltu t2, a0, t1 /* t2 = (a0 < _stext) */ 87 PTR_LA t1, _etext 88 sltu t3, t1, a0 /* t3 = (a0 > _etext) */ 89 or t1, t2, t3 90 beqz t1, ftrace_call 91 nop 92#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) 93 PTR_SUBU a0, a0, 16 /* arg1: adjust to module's recorded callsite */ 94#else 95 PTR_SUBU a0, a0, 12 96#endif 97 98 .globl ftrace_call 99ftrace_call: 100 nop /* a placeholder for the call to a real tracing function */ 101 move a1, AT /* arg2: parent's return address */ 102 103#ifdef CONFIG_FUNCTION_GRAPH_TRACER 104 .globl ftrace_graph_call 105ftrace_graph_call: 106 nop 107 nop 108#endif 109 110 MCOUNT_RESTORE_REGS 111 .globl ftrace_stub 112ftrace_stub: 113 RETURN_BACK 114 END(ftrace_caller) 115 116#else /* ! CONFIG_DYNAMIC_FTRACE */ 117 118NESTED(_mcount, PT_SIZE, ra) 119EXPORT_SYMBOL(_mcount) 120 PTR_LA t1, ftrace_stub 121 PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */ 122 bne t1, t2, static_trace 123 nop 124 125#ifdef CONFIG_FUNCTION_GRAPH_TRACER 126 PTR_L t3, ftrace_graph_return 127 bne t1, t3, ftrace_graph_caller 128 nop 129 PTR_LA t1, ftrace_graph_entry_stub 130 PTR_L t3, ftrace_graph_entry 131 bne t1, t3, ftrace_graph_caller 132 nop 133#endif 134 b ftrace_stub 135#ifdef CONFIG_32BIT 136 addiu sp, sp, 8 137#else 138 nop 139#endif 140 141static_trace: 142 MCOUNT_SAVE_REGS 143 144 move a0, ra /* arg1: self return address */ 145 jalr t2 /* (1) call *ftrace_trace_function */ 146 move a1, AT /* arg2: parent's return address */ 147 148 MCOUNT_RESTORE_REGS 149#ifdef CONFIG_32BIT 150 addiu sp, sp, 8 151#endif 152 .globl ftrace_stub 153ftrace_stub: 154 RETURN_BACK 155 END(_mcount) 156 157#endif /* ! CONFIG_DYNAMIC_FTRACE */ 158 159#ifdef CONFIG_FUNCTION_GRAPH_TRACER 160 161NESTED(ftrace_graph_caller, PT_SIZE, ra) 162#ifndef CONFIG_DYNAMIC_FTRACE 163 MCOUNT_SAVE_REGS 164#endif 165 166 /* arg1: Get the location of the parent's return address */ 167#ifdef KBUILD_MCOUNT_RA_ADDRESS 168#ifdef CONFIG_DYNAMIC_FTRACE 169 PTR_L a0, PT_R12(sp) 170#else 171 move a0, MCOUNT_RA_ADDRESS_REG 172#endif 173 bnez a0, 1f /* non-leaf func: stored in MCOUNT_RA_ADDRESS_REG */ 174 nop 175#endif 176 PTR_LA a0, PT_R1(sp) /* leaf func: the location in current stack */ 1771: 178 179 /* arg2: Get self return address */ 180#ifdef CONFIG_DYNAMIC_FTRACE 181 PTR_L a1, PT_R31(sp) 182#else 183 move a1, ra 184#endif 185 186 /* arg3: Get frame pointer of current stack */ 187#ifdef CONFIG_64BIT 188 PTR_LA a2, PT_SIZE(sp) 189#else 190 PTR_LA a2, (PT_SIZE+8)(sp) 191#endif 192 193 jal prepare_ftrace_return 194 nop 195 MCOUNT_RESTORE_REGS 196#ifndef CONFIG_DYNAMIC_FTRACE 197#ifdef CONFIG_32BIT 198 addiu sp, sp, 8 199#endif 200#endif 201 RETURN_BACK 202 END(ftrace_graph_caller) 203 204 .align 2 205 .globl return_to_handler 206return_to_handler: 207 PTR_SUBU sp, PT_SIZE 208 PTR_S v0, PT_R2(sp) 209 210 jal ftrace_return_to_handler 211 PTR_S v1, PT_R3(sp) 212 213 /* restore the real parent address: v0 -> ra */ 214 move ra, v0 215 216 PTR_L v0, PT_R2(sp) 217 PTR_L v1, PT_R3(sp) 218 jr ra 219 PTR_ADDIU sp, PT_SIZE 220#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 221 222 .set at 223 .set reorder 224