1/* 2 * Low-level ftrace handling 3 * 4 * Copyright (C) 2009 Michal Simek <monstr@monstr.eu> 5 * Copyright (C) 2009 PetaLogix 6 * 7 * This file is subject to the terms and conditions of the GNU General 8 * Public License. See the file COPYING in the main directory of this 9 * archive for more details. 10 */ 11 12#include <linux/linkage.h> 13 14#define NOALIGN_ENTRY(name) .globl name; name: 15 16/* FIXME MS: I think that I don't need to save all regs */ 17#define SAVE_REGS \ 18 addik r1, r1, -120; \ 19 swi r2, r1, 4; \ 20 swi r3, r1, 8; \ 21 swi r4, r1, 12; \ 22 swi r5, r1, 116; \ 23 swi r6, r1, 16; \ 24 swi r7, r1, 20; \ 25 swi r8, r1, 24; \ 26 swi r9, r1, 28; \ 27 swi r10, r1, 32; \ 28 swi r11, r1, 36; \ 29 swi r12, r1, 40; \ 30 swi r13, r1, 44; \ 31 swi r14, r1, 48; \ 32 swi r16, r1, 52; \ 33 swi r17, r1, 56; \ 34 swi r18, r1, 60; \ 35 swi r19, r1, 64; \ 36 swi r20, r1, 68; \ 37 swi r21, r1, 72; \ 38 swi r22, r1, 76; \ 39 swi r23, r1, 80; \ 40 swi r24, r1, 84; \ 41 swi r25, r1, 88; \ 42 swi r26, r1, 92; \ 43 swi r27, r1, 96; \ 44 swi r28, r1, 100; \ 45 swi r29, r1, 104; \ 46 swi r30, r1, 108; \ 47 swi r31, r1, 112; 48 49#define RESTORE_REGS \ 50 lwi r2, r1, 4; \ 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 81ENTRY(ftrace_stub) 82 rtsd r15, 8; 83 nop; 84 85ENTRY(_mcount) 86#ifdef CONFIG_DYNAMIC_FTRACE 87ENTRY(ftrace_caller) 88 /* MS: It is just barrier which is removed from C code */ 89 rtsd r15, 8 90 nop 91#endif /* CONFIG_DYNAMIC_FTRACE */ 92 SAVE_REGS 93 swi r15, r1, 0; 94 /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST begin of checking */ 95 lwi r5, r0, function_trace_stop; 96 bneid r5, end; 97 nop; 98 /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */ 99#ifdef CONFIG_FUNCTION_GRAPH_TRACER 100#ifndef CONFIG_DYNAMIC_FTRACE 101 lwi r5, r0, ftrace_graph_return; 102 addik r6, r0, ftrace_stub; /* asm implementation */ 103 cmpu r5, r5, r6; /* ftrace_graph_return != ftrace_stub */ 104 beqid r5, end_graph_tracer; 105 nop; 106 107 lwi r6, r0, ftrace_graph_entry; 108 addik r5, r0, ftrace_graph_entry_stub; /* implemented in C */ 109 cmpu r5, r5, r6; /* ftrace_graph_entry != ftrace_graph_entry_stub */ 110 beqid r5, end_graph_tracer; 111 nop; 112#else /* CONFIG_DYNAMIC_FTRACE */ 113NOALIGN_ENTRY(ftrace_call_graph) 114 /* MS: jump over graph function - replaced from C code */ 115 bri end_graph_tracer 116#endif /* CONFIG_DYNAMIC_FTRACE */ 117 addik r5, r1, 120; /* MS: load parent addr */ 118 addik r6, r15, 0; /* MS: load current function addr */ 119 bralid r15, prepare_ftrace_return; 120 nop; 121 /* MS: graph was taken that's why - can jump over function trace */ 122 brid end; 123 nop; 124end_graph_tracer: 125#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 126#ifndef CONFIG_DYNAMIC_FTRACE 127 /* MS: test function trace if is taken or not */ 128 lwi r20, r0, ftrace_trace_function; 129 addik r6, r0, ftrace_stub; 130 cmpu r5, r20, r6; /* ftrace_trace_function != ftrace_stub */ 131 beqid r5, end; /* MS: not taken -> jump over */ 132 nop; 133#else /* CONFIG_DYNAMIC_FTRACE */ 134NOALIGN_ENTRY(ftrace_call) 135/* instruction for setup imm FUNC_part1, addik r20, r0, FUNC_part2 */ 136 nop 137 nop 138#endif /* CONFIG_DYNAMIC_FTRACE */ 139/* static normal trace */ 140 lwi r6, r1, 120; /* MS: load parent addr */ 141 addik r5, r15, 0; /* MS: load current function addr */ 142 /* MS: here is dependency on previous code */ 143 brald r15, r20; /* MS: jump to ftrace handler */ 144 nop; 145end: 146 lwi r15, r1, 0; 147 RESTORE_REGS 148 149 rtsd r15, 8; /* MS: jump back */ 150 nop; 151 152#ifdef CONFIG_FUNCTION_GRAPH_TRACER 153ENTRY(return_to_handler) 154 nop; /* MS: just barrier for rtsd r15, 8 */ 155 nop; 156 SAVE_REGS 157 swi r15, r1, 0; 158 159 /* MS: find out returning address */ 160 bralid r15, ftrace_return_to_handler; 161 nop; 162 163 /* MS: return value from ftrace_return_to_handler is my returning addr 164 * must be before restore regs because I have to restore r3 content */ 165 addik r15, r3, 0; 166 RESTORE_REGS 167 168 rtsd r15, 8; /* MS: jump back */ 169 nop; 170#endif /* CONFIG_FUNCTION_TRACER */ 171