aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/ftrace.c
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2009-06-12 04:26:46 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-12 04:27:39 -0400
commit88dbd2037229bd2ed7543ffd0d8f2d9dec9d31d2 (patch)
tree60dd9e5ec02fb95872809c7076a4e717fc82dea5 /arch/s390/kernel/ftrace.c
parent8b4488f85d619253c9e631ec723368f400106771 (diff)
[S390] ftrace: add function graph tracer support
Function graph tracer support for s390. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/ftrace.c')
-rw-r--r--arch/s390/kernel/ftrace.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
index 0b81a784e039..c92a10953279 100644
--- a/arch/s390/kernel/ftrace.c
+++ b/arch/s390/kernel/ftrace.c
@@ -7,13 +7,17 @@
7 * 7 *
8 */ 8 */
9 9
10#include <linux/hardirq.h>
10#include <linux/uaccess.h> 11#include <linux/uaccess.h>
11#include <linux/ftrace.h> 12#include <linux/ftrace.h>
12#include <linux/kernel.h> 13#include <linux/kernel.h>
13#include <linux/types.h> 14#include <linux/types.h>
14#include <asm/lowcore.h> 15#include <asm/lowcore.h>
15 16
17#ifdef CONFIG_DYNAMIC_FTRACE
18
16void ftrace_disable_code(void); 19void ftrace_disable_code(void);
20void ftrace_disable_return(void);
17void ftrace_call_code(void); 21void ftrace_call_code(void);
18void ftrace_nop_code(void); 22void ftrace_nop_code(void);
19 23
@@ -28,6 +32,7 @@ asm(
28 " .word 0x0024\n" 32 " .word 0x0024\n"
29 " lg %r1,"__stringify(__LC_FTRACE_FUNC)"\n" 33 " lg %r1,"__stringify(__LC_FTRACE_FUNC)"\n"
30 " basr %r14,%r1\n" 34 " basr %r14,%r1\n"
35 "ftrace_disable_return:\n"
31 " lg %r14,8(15)\n" 36 " lg %r14,8(15)\n"
32 " lgr %r0,%r0\n" 37 " lgr %r0,%r0\n"
33 "0:\n"); 38 "0:\n");
@@ -50,6 +55,7 @@ asm(
50 " j 0f\n" 55 " j 0f\n"
51 " l %r1,"__stringify(__LC_FTRACE_FUNC)"\n" 56 " l %r1,"__stringify(__LC_FTRACE_FUNC)"\n"
52 " basr %r14,%r1\n" 57 " basr %r14,%r1\n"
58 "ftrace_disable_return:\n"
53 " l %r14,4(%r15)\n" 59 " l %r14,4(%r15)\n"
54 " j 0f\n" 60 " j 0f\n"
55 " bcr 0,%r7\n" 61 " bcr 0,%r7\n"
@@ -130,3 +136,69 @@ int __init ftrace_dyn_arch_init(void *data)
130 *(unsigned long *)data = 0; 136 *(unsigned long *)data = 0;
131 return 0; 137 return 0;
132} 138}
139
140#endif /* CONFIG_DYNAMIC_FTRACE */
141
142#ifdef CONFIG_FUNCTION_GRAPH_TRACER
143#ifdef CONFIG_DYNAMIC_FTRACE
144/*
145 * Patch the kernel code at ftrace_graph_caller location:
146 * The instruction there is branch relative on condition. The condition mask
147 * is either all ones (always branch aka disable ftrace_graph_caller) or all
148 * zeroes (nop aka enable ftrace_graph_caller).
149 * Instruction format for brc is a7m4xxxx where m is the condition mask.
150 */
151int ftrace_enable_ftrace_graph_caller(void)
152{
153 unsigned short opcode = 0xa704;
154
155 return probe_kernel_write(ftrace_graph_caller, &opcode, sizeof(opcode));
156}
157
158int ftrace_disable_ftrace_graph_caller(void)
159{
160 unsigned short opcode = 0xa7f4;
161
162 return probe_kernel_write(ftrace_graph_caller, &opcode, sizeof(opcode));
163}
164
165static inline unsigned long ftrace_mcount_call_adjust(unsigned long addr)
166{
167 return addr - (ftrace_disable_return - ftrace_disable_code);
168}
169
170#else /* CONFIG_DYNAMIC_FTRACE */
171
172static inline unsigned long ftrace_mcount_call_adjust(unsigned long addr)
173{
174 return addr - MCOUNT_OFFSET_RET;
175}
176
177#endif /* CONFIG_DYNAMIC_FTRACE */
178
179/*
180 * Hook the return address and push it in the stack of return addresses
181 * in current thread info.
182 */
183unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent)
184{
185 struct ftrace_graph_ent trace;
186
187 /* Nmi's are currently unsupported. */
188 if (unlikely(in_nmi()))
189 goto out;
190 if (unlikely(atomic_read(&current->tracing_graph_pause)))
191 goto out;
192 if (ftrace_push_return_trace(parent, ip, &trace.depth) == -EBUSY)
193 goto out;
194 trace.func = ftrace_mcount_call_adjust(ip) & PSW_ADDR_INSN;
195 /* Only trace if the calling function expects to. */
196 if (!ftrace_graph_entry(&trace)) {
197 current->curr_ret_stack--;
198 goto out;
199 }
200 parent = (unsigned long)return_to_handler;
201out:
202 return parent;
203}
204#endif /* CONFIG_FUNCTION_GRAPH_TRACER */