aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
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
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')
-rw-r--r--arch/s390/Kconfig1
-rw-r--r--arch/s390/include/asm/ftrace.h10
-rw-r--r--arch/s390/kernel/Makefile6
-rw-r--r--arch/s390/kernel/ftrace.c72
-rw-r--r--arch/s390/kernel/mcount.S79
-rw-r--r--arch/s390/kernel/s390_ext.c3
-rw-r--r--arch/s390/kernel/time.c2
-rw-r--r--arch/s390/kernel/vmlinux.lds.S1
8 files changed, 164 insertions, 10 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 480590f21570..9023cc900bda 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -85,6 +85,7 @@ config S390
85 select HAVE_FUNCTION_TRACE_MCOUNT_TEST 85 select HAVE_FUNCTION_TRACE_MCOUNT_TEST
86 select HAVE_FTRACE_MCOUNT_RECORD 86 select HAVE_FTRACE_MCOUNT_RECORD
87 select HAVE_DYNAMIC_FTRACE 87 select HAVE_DYNAMIC_FTRACE
88 select HAVE_FUNCTION_GRAPH_TRACER
88 select HAVE_DEFAULT_NO_SPIN_MUTEXES 89 select HAVE_DEFAULT_NO_SPIN_MUTEXES
89 select HAVE_OPROFILE 90 select HAVE_OPROFILE
90 select HAVE_KPROBES 91 select HAVE_KPROBES
diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h
index ba23d8f97d07..96c14a9102b8 100644
--- a/arch/s390/include/asm/ftrace.h
+++ b/arch/s390/include/asm/ftrace.h
@@ -11,11 +11,13 @@ struct dyn_arch_ftrace { };
11#define MCOUNT_ADDR ((long)_mcount) 11#define MCOUNT_ADDR ((long)_mcount)
12 12
13#ifdef CONFIG_64BIT 13#ifdef CONFIG_64BIT
14#define MCOUNT_INSN_SIZE 24 14#define MCOUNT_OFFSET_RET 18
15#define MCOUNT_OFFSET 14 15#define MCOUNT_INSN_SIZE 24
16#define MCOUNT_OFFSET 14
16#else 17#else
17#define MCOUNT_INSN_SIZE 30 18#define MCOUNT_OFFSET_RET 26
18#define MCOUNT_OFFSET 8 19#define MCOUNT_INSN_SIZE 30
20#define MCOUNT_OFFSET 8
19#endif 21#endif
20 22
21static inline unsigned long ftrace_call_adjust(unsigned long addr) 23static inline unsigned long ftrace_call_adjust(unsigned long addr)
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index ce172bfaab8a..c75ed43b1a18 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -3,11 +3,8 @@
3# 3#
4 4
5ifdef CONFIG_FUNCTION_TRACER 5ifdef CONFIG_FUNCTION_TRACER
6# Do not trace early boot code 6# Don't trace early setup code and tracing code
7CFLAGS_REMOVE_early.o = -pg 7CFLAGS_REMOVE_early.o = -pg
8endif
9
10ifdef CONFIG_DYNAMIC_FTRACE
11CFLAGS_REMOVE_ftrace.o = -pg 8CFLAGS_REMOVE_ftrace.o = -pg
12endif 9endif
13 10
@@ -46,6 +43,7 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o
46obj-$(CONFIG_KPROBES) += kprobes.o 43obj-$(CONFIG_KPROBES) += kprobes.o
47obj-$(CONFIG_FUNCTION_TRACER) += mcount.o 44obj-$(CONFIG_FUNCTION_TRACER) += mcount.o
48obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o 45obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
46obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
49 47
50# Kexec part 48# Kexec part
51S390_KEXEC_OBJS := machine_kexec.o crash.o 49S390_KEXEC_OBJS := machine_kexec.o crash.o
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 */
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 0aa85ec94d08..2a0a5e97ba8c 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -34,6 +34,18 @@ ftrace_caller:
34 larl %r14,ftrace_dyn_func 34 larl %r14,ftrace_dyn_func
35 lg %r14,0(%r14) 35 lg %r14,0(%r14)
36 basr %r14,%r14 36 basr %r14,%r14
37#ifdef CONFIG_FUNCTION_GRAPH_TRACER
38 .globl ftrace_graph_caller
39ftrace_graph_caller:
40 # This unconditional branch gets runtime patched. Change only if
41 # you know what you are doing. See ftrace_enable_graph_caller().
42 j 0f
43 lg %r2,272(%r15)
44 lg %r3,168(%r15)
45 brasl %r14,prepare_ftrace_return
46 stg %r2,168(%r15)
470:
48#endif
37 aghi %r15,160 49 aghi %r15,160
38 lmg %r2,%r5,32(%r15) 50 lmg %r2,%r5,32(%r15)
39 lg %r14,112(%r15) 51 lg %r14,112(%r15)
@@ -62,6 +74,12 @@ _mcount:
62 larl %r14,ftrace_trace_function 74 larl %r14,ftrace_trace_function
63 lg %r14,0(%r14) 75 lg %r14,0(%r14)
64 basr %r14,%r14 76 basr %r14,%r14
77#ifdef CONFIG_FUNCTION_GRAPH_TRACER
78 lg %r2,272(%r15)
79 lg %r3,168(%r15)
80 brasl %r14,prepare_ftrace_return
81 stg %r2,168(%r15)
82#endif
65 aghi %r15,160 83 aghi %r15,160
66 lmg %r2,%r5,32(%r15) 84 lmg %r2,%r5,32(%r15)
67 lg %r14,112(%r15) 85 lg %r14,112(%r15)
@@ -69,6 +87,22 @@ _mcount:
69 87
70#endif /* CONFIG_DYNAMIC_FTRACE */ 88#endif /* CONFIG_DYNAMIC_FTRACE */
71 89
90#ifdef CONFIG_FUNCTION_GRAPH_TRACER
91
92 .globl return_to_handler
93return_to_handler:
94 stmg %r2,%r5,32(%r15)
95 lgr %r1,%r15
96 aghi %r15,-160
97 stg %r1,__SF_BACKCHAIN(%r15)
98 brasl %r14,ftrace_return_to_handler
99 aghi %r15,160
100 lgr %r14,%r2
101 lmg %r2,%r5,32(%r15)
102 br %r14
103
104#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
105
72#else /* CONFIG_64BIT */ 106#else /* CONFIG_64BIT */
73 107
74#ifdef CONFIG_DYNAMIC_FTRACE 108#ifdef CONFIG_DYNAMIC_FTRACE
@@ -96,6 +130,21 @@ ftrace_caller:
96 l %r14,0b-0b(%r1) 130 l %r14,0b-0b(%r1)
97 l %r14,0(%r14) 131 l %r14,0(%r14)
98 basr %r14,%r14 132 basr %r14,%r14
133#ifdef CONFIG_FUNCTION_GRAPH_TRACER
134 .globl ftrace_graph_caller
135ftrace_graph_caller:
136 # This unconditional branch gets runtime patched. Change only if
137 # you know what you are doing. See ftrace_enable_graph_caller().
138 j 1f
139 bras %r1,0f
140 .long prepare_ftrace_return
1410: l %r2,152(%r15)
142 l %r4,0(%r1)
143 l %r3,100(%r15)
144 basr %r14,%r4
145 st %r2,100(%r15)
1461:
147#endif
99 ahi %r15,96 148 ahi %r15,96
100 l %r14,56(%r15) 149 l %r14,56(%r15)
1013: lm %r2,%r5,16(%r15) 1503: lm %r2,%r5,16(%r15)
@@ -128,10 +177,40 @@ _mcount:
128 l %r14,0b-0b(%r1) 177 l %r14,0b-0b(%r1)
129 l %r14,0(%r14) 178 l %r14,0(%r14)
130 basr %r14,%r14 179 basr %r14,%r14
180#ifdef CONFIG_FUNCTION_GRAPH_TRACER
181 bras %r1,0f
182 .long prepare_ftrace_return
1830: l %r2,152(%r15)
184 l %r4,0(%r1)
185 l %r3,100(%r15)
186 basr %r14,%r4
187 st %r2,100(%r15)
188#endif
131 ahi %r15,96 189 ahi %r15,96
132 l %r14,56(%r15) 190 l %r14,56(%r15)
1333: lm %r2,%r5,16(%r15) 1913: lm %r2,%r5,16(%r15)
134 br %r14 192 br %r14
135 193
136#endif /* CONFIG_DYNAMIC_FTRACE */ 194#endif /* CONFIG_DYNAMIC_FTRACE */
195
196#ifdef CONFIG_FUNCTION_GRAPH_TRACER
197
198 .globl return_to_handler
199return_to_handler:
200 stm %r2,%r5,16(%r15)
201 st %r14,56(%r15)
202 lr %r0,%r15
203 ahi %r15,-96
204 st %r0,__SF_BACKCHAIN(%r15)
205 bras %r1,0f
206 .long ftrace_return_to_handler
2070: l %r2,0b-0b(%r1)
208 basr %r14,%r2
209 lr %r14,%r2
210 ahi %r15,96
211 lm %r2,%r5,16(%r15)
212 br %r14
213
214#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
215
137#endif /* CONFIG_64BIT */ 216#endif /* CONFIG_64BIT */
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index 6b0686d78fc7..0de305b598ce 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -10,6 +10,7 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/ftrace.h>
13#include <linux/errno.h> 14#include <linux/errno.h>
14#include <linux/kernel_stat.h> 15#include <linux/kernel_stat.h>
15#include <linux/interrupt.h> 16#include <linux/interrupt.h>
@@ -112,7 +113,7 @@ int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler,
112 return 0; 113 return 0;
113} 114}
114 115
115void do_extint(struct pt_regs *regs, unsigned short code) 116void __irq_entry do_extint(struct pt_regs *regs, unsigned short code)
116{ 117{
117 ext_int_info_t *p; 118 ext_int_info_t *p;
118 int index; 119 int index;
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index ad9a999aaa92..215330a2c128 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -70,7 +70,7 @@ static DEFINE_PER_CPU(struct clock_event_device, comparators);
70/* 70/*
71 * Scheduler clock - returns current time in nanosec units. 71 * Scheduler clock - returns current time in nanosec units.
72 */ 72 */
73unsigned long long sched_clock(void) 73unsigned long long notrace sched_clock(void)
74{ 74{
75 return ((get_clock_xt() - sched_clock_base_cc) * 125) >> 9; 75 return ((get_clock_xt() - sched_clock_base_cc) * 125) >> 9;
76} 76}
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 89399b8756c2..a53db23ee092 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -34,6 +34,7 @@ SECTIONS
34 SCHED_TEXT 34 SCHED_TEXT
35 LOCK_TEXT 35 LOCK_TEXT
36 KPROBES_TEXT 36 KPROBES_TEXT
37 IRQENTRY_TEXT
37 *(.fixup) 38 *(.fixup)
38 *(.gnu.warning) 39 *(.gnu.warning)
39 } :text = 0x0700 40 } :text = 0x0700