This source file includes following definitions.
- ftrace_generate_orig_insn
- is_kprobe_on_ftrace
- ftrace_generate_kprobe_nop_insn
- ftrace_generate_kprobe_call_insn
- ftrace_modify_call
- ftrace_make_nop
- ftrace_make_call
- ftrace_update_ftrace_func
- ftrace_dyn_arch_init
- ftrace_plt_init
- prepare_ftrace_return
- ftrace_enable_ftrace_graph_caller
- ftrace_disable_ftrace_graph_caller
1
2
3
4
5
6
7
8
9
10
11 #include <linux/moduleloader.h>
12 #include <linux/hardirq.h>
13 #include <linux/uaccess.h>
14 #include <linux/ftrace.h>
15 #include <linux/kernel.h>
16 #include <linux/types.h>
17 #include <linux/kprobes.h>
18 #include <trace/syscall.h>
19 #include <asm/asm-offsets.h>
20 #include <asm/cacheflush.h>
21 #include <asm/set_memory.h>
22 #include "entry.h"
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 unsigned long ftrace_plt;
61
62 static inline void ftrace_generate_orig_insn(struct ftrace_insn *insn)
63 {
64 #if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
65
66 insn->opc = 0xc004;
67 insn->disp = 0;
68 #else
69
70 insn->opc = 0xe3e0;
71 insn->disp = 0xf0080024;
72 #endif
73 }
74
75 static inline int is_kprobe_on_ftrace(struct ftrace_insn *insn)
76 {
77 #ifdef CONFIG_KPROBES
78 if (insn->opc == BREAKPOINT_INSTRUCTION)
79 return 1;
80 #endif
81 return 0;
82 }
83
84 static inline void ftrace_generate_kprobe_nop_insn(struct ftrace_insn *insn)
85 {
86 #ifdef CONFIG_KPROBES
87 insn->opc = BREAKPOINT_INSTRUCTION;
88 insn->disp = KPROBE_ON_FTRACE_NOP;
89 #endif
90 }
91
92 static inline void ftrace_generate_kprobe_call_insn(struct ftrace_insn *insn)
93 {
94 #ifdef CONFIG_KPROBES
95 insn->opc = BREAKPOINT_INSTRUCTION;
96 insn->disp = KPROBE_ON_FTRACE_CALL;
97 #endif
98 }
99
100 int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
101 unsigned long addr)
102 {
103 return 0;
104 }
105
106 int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
107 unsigned long addr)
108 {
109 struct ftrace_insn orig, new, old;
110
111 if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old)))
112 return -EFAULT;
113 if (addr == MCOUNT_ADDR) {
114
115 ftrace_generate_orig_insn(&orig);
116 ftrace_generate_nop_insn(&new);
117 } else if (is_kprobe_on_ftrace(&old)) {
118
119
120
121
122
123
124
125 ftrace_generate_kprobe_call_insn(&orig);
126 ftrace_generate_kprobe_nop_insn(&new);
127 } else {
128
129 ftrace_generate_call_insn(&orig, rec->ip);
130 ftrace_generate_nop_insn(&new);
131 }
132
133 if (memcmp(&orig, &old, sizeof(old)))
134 return -EINVAL;
135 s390_kernel_write((void *) rec->ip, &new, sizeof(new));
136 return 0;
137 }
138
139 int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
140 {
141 struct ftrace_insn orig, new, old;
142
143 if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old)))
144 return -EFAULT;
145 if (is_kprobe_on_ftrace(&old)) {
146
147
148
149
150
151
152
153 ftrace_generate_kprobe_nop_insn(&orig);
154 ftrace_generate_kprobe_call_insn(&new);
155 } else {
156
157 ftrace_generate_nop_insn(&orig);
158 ftrace_generate_call_insn(&new, rec->ip);
159 }
160
161 if (memcmp(&orig, &old, sizeof(old)))
162 return -EINVAL;
163 s390_kernel_write((void *) rec->ip, &new, sizeof(new));
164 return 0;
165 }
166
167 int ftrace_update_ftrace_func(ftrace_func_t func)
168 {
169 return 0;
170 }
171
172 int __init ftrace_dyn_arch_init(void)
173 {
174 return 0;
175 }
176
177 #ifdef CONFIG_MODULES
178
179 static int __init ftrace_plt_init(void)
180 {
181 unsigned int *ip;
182
183 ftrace_plt = (unsigned long) module_alloc(PAGE_SIZE);
184 if (!ftrace_plt)
185 panic("cannot allocate ftrace plt\n");
186 ip = (unsigned int *) ftrace_plt;
187 ip[0] = 0x0d10e310;
188 ip[1] = 0x100a0004;
189 ip[2] = 0x07f10000;
190 ip[3] = FTRACE_ADDR >> 32;
191 ip[4] = FTRACE_ADDR & 0xffffffff;
192 set_memory_ro(ftrace_plt, 1);
193 return 0;
194 }
195 device_initcall(ftrace_plt_init);
196
197 #endif
198
199 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
200
201
202
203
204 unsigned long prepare_ftrace_return(unsigned long ra, unsigned long sp,
205 unsigned long ip)
206 {
207 if (unlikely(ftrace_graph_is_dead()))
208 goto out;
209 if (unlikely(atomic_read(¤t->tracing_graph_pause)))
210 goto out;
211 ip -= MCOUNT_INSN_SIZE;
212 if (!function_graph_enter(ra, ip, 0, (void *) sp))
213 ra = (unsigned long) return_to_handler;
214 out:
215 return ra;
216 }
217 NOKPROBE_SYMBOL(prepare_ftrace_return);
218
219
220
221
222
223
224
225
226
227 int ftrace_enable_ftrace_graph_caller(void)
228 {
229 u8 op = 0x04;
230
231 s390_kernel_write(__va(ftrace_graph_caller)+1, &op, sizeof(op));
232 return 0;
233 }
234
235 int ftrace_disable_ftrace_graph_caller(void)
236 {
237 u8 op = 0xf4;
238
239 s390_kernel_write(__va(ftrace_graph_caller)+1, &op, sizeof(op));
240 return 0;
241 }
242
243 #endif