| 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 | |
| 13 |
|
| 14 | |
| 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 |
|
| 81 | ENTRY(ftrace_stub)
|
| 82 | rtsd r15, 8;
|
| 83 | nop;
|
| 84 |
|
| 85 | ENTRY(_mcount)
|
| 86 | #ifdef CONFIG_DYNAMIC_FTRACE
|
| 87 | ENTRY(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 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
| 95 | #ifndef CONFIG_DYNAMIC_FTRACE
|
| 96 | lwi r5, r0, ftrace_graph_return;
|
| 97 | addik r6, r0, ftrace_stub; /* asm implementation */
|
| 98 | cmpu r5, r5, r6; /* ftrace_graph_return != ftrace_stub */
|
| 99 | beqid r5, end_graph_tracer;
|
| 100 | nop;
|
| 101 |
|
| 102 | lwi r6, r0, ftrace_graph_entry;
|
| 103 | addik r5, r0, ftrace_graph_entry_stub; /* implemented in C */
|
| 104 | cmpu r5, r5, r6; /* ftrace_graph_entry != ftrace_graph_entry_stub */
|
| 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 - replaced from C code */
|
| 110 | bri end_graph_tracer
|
| 111 | #endif /* CONFIG_DYNAMIC_FTRACE */
|
| 112 | addik r5, r1, 120; /* MS: load parent addr */
|
| 113 | addik r6, r15, 0; /* MS: load current function addr */
|
| 114 | bralid r15, prepare_ftrace_return;
|
| 115 | nop;
|
| 116 | /* MS: graph was taken that's why - can jump over function trace */
|
| 117 | brid end;
|
| 118 | nop;
|
| 119 | end_graph_tracer:
|
| 120 | |
| 121 | |
| 122 | /* MS: test function trace if is taken or not */
|
| 123 | lwi r20, r0, ftrace_trace_function;
|
| 124 | addik r6, r0, ftrace_stub;
|
| 125 | cmpu r5, r20, r6; /* ftrace_trace_function != ftrace_stub */
|
| 126 | beqid r5, end; /* MS: not taken -> jump over */
|
| 127 | nop;
|
| 128 | |
| 129 | NOALIGN_ENTRY(ftrace_call)
|
| 130 | /* instruction for setup imm FUNC_part1, addik r20, r0, FUNC_part2 */
|
| 131 | nop
|
| 132 | nop
|
| 133 | |
| 134 | /* static normal trace */
|
| 135 | lwi r6, r1, 120; /* MS: load parent addr */
|
| 136 | addik r5, r15, -4; /* MS: load current function addr */
|
| 137 | /* MS: here is dependency on previous code */
|
| 138 | brald r15, r20; /* MS: jump to ftrace handler */
|
| 139 | nop;
|
| 140 | end:
|
| 141 | lwi r15, r1, 0;
|
| 142 | RESTORE_REGS
|
| 143 |
|
| 144 | rtsd r15, 8; /* MS: jump back */
|
| 145 | nop;
|
| 146 |
|
| 147 | |
| 148 | ENTRY(return_to_handler)
|
| 149 | nop; /* MS: just barrier for rtsd r15, 8 */
|
| 150 | nop;
|
| 151 | SAVE_REGS
|
| 152 | swi r15, r1, 0;
|
| 153 |
|
| 154 | /* MS: find out returning address */
|
| 155 | bralid r15, ftrace_return_to_handler;
|
| 156 | nop;
|
| 157 |
|
| 158 | /* MS: return value from ftrace_return_to_handler is my returning addr
|
| 159 | * must be before restore regs because I have to restore r3 content */
|
| 160 | addik r15, r3, 0;
|
| 161 | RESTORE_REGS
|
| 162 |
|
| 163 | rtsd r15, 8; /* MS: jump back */
|
| 164 | nop;
|
| 165 | |