Merge branch 'next' of git://git.monstr.eu/linux-2.6-microblaze
[pandora-kernel.git] / arch / microblaze / kernel / mcount.S
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
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         /* 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 */
113 NOALIGN_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;
124 end_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 */
134 NOALIGN_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;
145 end:
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
153 ENTRY(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 */