1/* 2 * Copyright 2012 Tilera Corporation. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, version 2. 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 11 * NON INFRINGEMENT. See the GNU General Public License for 12 * more details. 13 * 14 * TILE-Gx specific __mcount support 15 */ 16 17#include <linux/linkage.h> 18#include <asm/ftrace.h> 19 20#define REGSIZE 8 21 22 .text 23 .global __mcount 24 25 .macro MCOUNT_SAVE_REGS 26 addli sp, sp, -REGSIZE 27 { 28 st sp, lr 29 addli r29, sp, - (12 * REGSIZE) 30 } 31 { 32 addli sp, sp, - (13 * REGSIZE) 33 st r29, sp 34 } 35 addli r29, r29, REGSIZE 36 { st r29, r0; addli r29, r29, REGSIZE } 37 { st r29, r1; addli r29, r29, REGSIZE } 38 { st r29, r2; addli r29, r29, REGSIZE } 39 { st r29, r3; addli r29, r29, REGSIZE } 40 { st r29, r4; addli r29, r29, REGSIZE } 41 { st r29, r5; addli r29, r29, REGSIZE } 42 { st r29, r6; addli r29, r29, REGSIZE } 43 { st r29, r7; addli r29, r29, REGSIZE } 44 { st r29, r8; addli r29, r29, REGSIZE } 45 { st r29, r9; addli r29, r29, REGSIZE } 46 { st r29, r10; addli r29, r29, REGSIZE } 47 .endm 48 49 .macro MCOUNT_RESTORE_REGS 50 addli r29, sp, (2 * REGSIZE) 51 { ld r0, r29; addli r29, r29, REGSIZE } 52 { ld r1, r29; addli r29, r29, REGSIZE } 53 { ld r2, r29; addli r29, r29, REGSIZE } 54 { ld r3, r29; addli r29, r29, REGSIZE } 55 { ld r4, r29; addli r29, r29, REGSIZE } 56 { ld r5, r29; addli r29, r29, REGSIZE } 57 { ld r6, r29; addli r29, r29, REGSIZE } 58 { ld r7, r29; addli r29, r29, REGSIZE } 59 { ld r8, r29; addli r29, r29, REGSIZE } 60 { ld r9, r29; addli r29, r29, REGSIZE } 61 { ld r10, r29; addli lr, sp, (13 * REGSIZE) } 62 { ld lr, lr; addli sp, sp, (14 * REGSIZE) } 63 .endm 64 65 .macro RETURN_BACK 66 { move r12, lr; move lr, r10 } 67 jrp r12 68 .endm 69 70#ifdef CONFIG_DYNAMIC_FTRACE 71 72 .align 64 73STD_ENTRY(__mcount) 74__mcount: 75 j ftrace_stub 76STD_ENDPROC(__mcount) 77 78 .align 64 79STD_ENTRY(ftrace_caller) 80 MCOUNT_SAVE_REGS 81 82 /* arg1: self return address */ 83 /* arg2: parent's return address */ 84 /* arg3: ftrace_ops */ 85 /* arg4: regs (but make it NULL) */ 86 { move r0, lr; moveli r2, hw2_last(function_trace_op) } 87 { move r1, r10; shl16insli r2, r2, hw1(function_trace_op) } 88 { movei r3, 0; shl16insli r2, r2, hw0(function_trace_op) } 89 ld r2,r2 90 91 .global ftrace_call 92ftrace_call: 93 /* 94 * a placeholder for the call to a real tracing function, i.e. 95 * ftrace_trace_function() 96 */ 97 nop 98 99#ifdef CONFIG_FUNCTION_GRAPH_TRACER 100 .global ftrace_graph_call 101ftrace_graph_call: 102 /* 103 * a placeholder for the call to a real tracing function, i.e. 104 * ftrace_graph_caller() 105 */ 106 nop 107#endif 108 MCOUNT_RESTORE_REGS 109 .global ftrace_stub 110ftrace_stub: 111 RETURN_BACK 112STD_ENDPROC(ftrace_caller) 113 114#else /* ! CONFIG_DYNAMIC_FTRACE */ 115 116 .align 64 117STD_ENTRY(__mcount) 118 { 119 moveli r11, hw2_last(ftrace_trace_function) 120 moveli r13, hw2_last(ftrace_stub) 121 } 122 { 123 shl16insli r11, r11, hw1(ftrace_trace_function) 124 shl16insli r13, r13, hw1(ftrace_stub) 125 } 126 { 127 shl16insli r11, r11, hw0(ftrace_trace_function) 128 shl16insli r13, r13, hw0(ftrace_stub) 129 } 130 131 ld r11, r11 132 sub r14, r13, r11 133 bnez r14, static_trace 134 135#ifdef CONFIG_FUNCTION_GRAPH_TRACER 136 moveli r15, hw2_last(ftrace_graph_return) 137 shl16insli r15, r15, hw1(ftrace_graph_return) 138 shl16insli r15, r15, hw0(ftrace_graph_return) 139 ld r15, r15 140 sub r15, r15, r13 141 bnez r15, ftrace_graph_caller 142 143 { 144 moveli r16, hw2_last(ftrace_graph_entry) 145 moveli r17, hw2_last(ftrace_graph_entry_stub) 146 } 147 { 148 shl16insli r16, r16, hw1(ftrace_graph_entry) 149 shl16insli r17, r17, hw1(ftrace_graph_entry_stub) 150 } 151 { 152 shl16insli r16, r16, hw0(ftrace_graph_entry) 153 shl16insli r17, r17, hw0(ftrace_graph_entry_stub) 154 } 155 ld r16, r16 156 sub r17, r16, r17 157 bnez r17, ftrace_graph_caller 158 159#endif 160 RETURN_BACK 161 162static_trace: 163 MCOUNT_SAVE_REGS 164 165 /* arg1: self return address */ 166 /* arg2: parent's return address */ 167 { move r0, lr; move r1, r10 } 168 169 /* call ftrace_trace_function() */ 170 jalr r11 171 172 MCOUNT_RESTORE_REGS 173 174 .global ftrace_stub 175ftrace_stub: 176 RETURN_BACK 177STD_ENDPROC(__mcount) 178 179#endif /* ! CONFIG_DYNAMIC_FTRACE */ 180 181#ifdef CONFIG_FUNCTION_GRAPH_TRACER 182 183STD_ENTRY(ftrace_graph_caller) 184ftrace_graph_caller: 185#ifndef CONFIG_DYNAMIC_FTRACE 186 MCOUNT_SAVE_REGS 187#endif 188 189 /* arg1: Get the location of the parent's return address */ 190 addi r0, sp, 12 * REGSIZE 191 /* arg2: Get self return address */ 192 move r1, lr 193 194 jal prepare_ftrace_return 195 196 MCOUNT_RESTORE_REGS 197 RETURN_BACK 198STD_ENDPROC(ftrace_graph_caller) 199 200 .global return_to_handler 201return_to_handler: 202 MCOUNT_SAVE_REGS 203 204 jal ftrace_return_to_handler 205 /* restore the real parent address */ 206 move r11, r0 207 208 MCOUNT_RESTORE_REGS 209 jr r11 210 211#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 212