2 * mcount and friends -- ftrace stuff
4 * Copyright (C) 2009 Analog Devices Inc.
5 * Licensed under the GPL-2 or later.
8 #include <linux/linkage.h>
9 #include <asm/ftrace.h>
13 /* GCC will have called us before setting up the function prologue, so we
14 * can clobber the normal scratch registers, but we need to make sure to
15 * save/restore the registers used for argument passing (R0-R2) in case
16 * the profiled function is using them. With data registers, R3 is the
17 * only one we can blow away. With pointer registers, we have P0-P2.
19 * Upon entry, the RETS will point to the top of the current profiled
20 * function. And since GCC setup the frame for us, the previous function
21 * will be waiting there. mmmm pie.
24 /* save third function arg early so we can do testing below */
27 /* load the function pointer to the tracer */
28 p0.l = _ftrace_trace_function;
29 p0.h = _ftrace_trace_function;
32 /* optional micro optimization: don't call the stub tracer */
36 if ! cc jump .Ldo_trace;
38 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
39 /* if the ftrace_graph_return function pointer is not set to
40 * the ftrace_stub entry, call prepare_ftrace_return().
42 p0.l = _ftrace_graph_return;
43 p0.h = _ftrace_graph_return;
46 if ! cc jump _ftrace_graph_caller;
48 /* similarly, if the ftrace_graph_entry function pointer is not
49 * set to the ftrace_graph_entry_stub entry, ...
51 p0.l = _ftrace_graph_entry;
52 p0.h = _ftrace_graph_entry;
53 r2.l = _ftrace_graph_entry_stub;
54 r2.h = _ftrace_graph_entry_stub;
57 if ! cc jump _ftrace_graph_caller;
65 /* save first/second function arg and the return register */
70 /* setup the tracer function */
73 /* tracer(ulong frompc, ulong selfpc):
74 * frompc: the pc that did the call to ...
75 * selfpc: ... this location
76 * the selfpc itself will need adjusting for the mcount call
80 r1 += -MCOUNT_INSN_SIZE;
85 /* restore state and get out of dodge */
97 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
98 /* The prepare_ftrace_return() function is similar to the trace function
99 * except it takes a pointer to the location of the frompc. This is so
100 * the prepare_ftrace_return() can hijack it temporarily for probing
103 ENTRY(_ftrace_graph_caller)
104 /* save first/second function arg and the return register */
112 r1 += -MCOUNT_INSN_SIZE;
113 call _prepare_ftrace_return;
116 ENDPROC(_ftrace_graph_caller)
118 /* Undo the rewrite caused by ftrace_graph_caller(). The common function
119 * ftrace_return_to_handler() will return the original rets so we can
120 * restore it and be on our way.
122 ENTRY(_return_to_handler)
123 /* make sure original return values are saved */
128 /* get original return address */
129 call _ftrace_return_to_handler;
132 /* anomaly 05000371 - make sure we have at least three instructions
133 * between rets setting and the return
139 ENDPROC(_return_to_handler)