Merge branch 'akpm' (fixes from Andrew)
[linux-drm-fsl-dcu.git] / kernel / test_kprobes.c
1 /*
2  * test_kprobes.c - simple sanity test for *probes
3  *
4  * Copyright IBM Corp. 2008
5  *
6  * This program is free software;  you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it would be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14  * the GNU General Public License for more details.
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/kprobes.h>
19 #include <linux/random.h>
20
21 #define div_factor 3
22
23 static u32 rand1, preh_val, posth_val, jph_val;
24 static int errors, handler_errors, num_tests;
25 static u32 (*target)(u32 value);
26 static u32 (*target2)(u32 value);
27
28 static noinline u32 kprobe_target(u32 value)
29 {
30         return (value / div_factor);
31 }
32
33 static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
34 {
35         preh_val = (rand1 / div_factor);
36         return 0;
37 }
38
39 static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
40                 unsigned long flags)
41 {
42         if (preh_val != (rand1 / div_factor)) {
43                 handler_errors++;
44                 printk(KERN_ERR "Kprobe smoke test failed: "
45                                 "incorrect value in post_handler\n");
46         }
47         posth_val = preh_val + div_factor;
48 }
49
50 static struct kprobe kp = {
51         .symbol_name = "kprobe_target",
52         .pre_handler = kp_pre_handler,
53         .post_handler = kp_post_handler
54 };
55
56 static int test_kprobe(void)
57 {
58         int ret;
59
60         ret = register_kprobe(&kp);
61         if (ret < 0) {
62                 printk(KERN_ERR "Kprobe smoke test failed: "
63                                 "register_kprobe returned %d\n", ret);
64                 return ret;
65         }
66
67         ret = target(rand1);
68         unregister_kprobe(&kp);
69
70         if (preh_val == 0) {
71                 printk(KERN_ERR "Kprobe smoke test failed: "
72                                 "kprobe pre_handler not called\n");
73                 handler_errors++;
74         }
75
76         if (posth_val == 0) {
77                 printk(KERN_ERR "Kprobe smoke test failed: "
78                                 "kprobe post_handler not called\n");
79                 handler_errors++;
80         }
81
82         return 0;
83 }
84
85 static noinline u32 kprobe_target2(u32 value)
86 {
87         return (value / div_factor) + 1;
88 }
89
90 static int kp_pre_handler2(struct kprobe *p, struct pt_regs *regs)
91 {
92         preh_val = (rand1 / div_factor) + 1;
93         return 0;
94 }
95
96 static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs,
97                 unsigned long flags)
98 {
99         if (preh_val != (rand1 / div_factor) + 1) {
100                 handler_errors++;
101                 printk(KERN_ERR "Kprobe smoke test failed: "
102                                 "incorrect value in post_handler2\n");
103         }
104         posth_val = preh_val + div_factor;
105 }
106
107 static struct kprobe kp2 = {
108         .symbol_name = "kprobe_target2",
109         .pre_handler = kp_pre_handler2,
110         .post_handler = kp_post_handler2
111 };
112
113 static int test_kprobes(void)
114 {
115         int ret;
116         struct kprobe *kps[2] = {&kp, &kp2};
117
118         /* addr and flags should be cleard for reusing kprobe. */
119         kp.addr = NULL;
120         kp.flags = 0;
121         ret = register_kprobes(kps, 2);
122         if (ret < 0) {
123                 printk(KERN_ERR "Kprobe smoke test failed: "
124                                 "register_kprobes returned %d\n", ret);
125                 return ret;
126         }
127
128         preh_val = 0;
129         posth_val = 0;
130         ret = target(rand1);
131
132         if (preh_val == 0) {
133                 printk(KERN_ERR "Kprobe smoke test failed: "
134                                 "kprobe pre_handler not called\n");
135                 handler_errors++;
136         }
137
138         if (posth_val == 0) {
139                 printk(KERN_ERR "Kprobe smoke test failed: "
140                                 "kprobe post_handler not called\n");
141                 handler_errors++;
142         }
143
144         preh_val = 0;
145         posth_val = 0;
146         ret = target2(rand1);
147
148         if (preh_val == 0) {
149                 printk(KERN_ERR "Kprobe smoke test failed: "
150                                 "kprobe pre_handler2 not called\n");
151                 handler_errors++;
152         }
153
154         if (posth_val == 0) {
155                 printk(KERN_ERR "Kprobe smoke test failed: "
156                                 "kprobe post_handler2 not called\n");
157                 handler_errors++;
158         }
159
160         unregister_kprobes(kps, 2);
161         return 0;
162
163 }
164
165 static u32 j_kprobe_target(u32 value)
166 {
167         if (value != rand1) {
168                 handler_errors++;
169                 printk(KERN_ERR "Kprobe smoke test failed: "
170                                 "incorrect value in jprobe handler\n");
171         }
172
173         jph_val = rand1;
174         jprobe_return();
175         return 0;
176 }
177
178 static struct jprobe jp = {
179         .entry          = j_kprobe_target,
180         .kp.symbol_name = "kprobe_target"
181 };
182
183 static int test_jprobe(void)
184 {
185         int ret;
186
187         ret = register_jprobe(&jp);
188         if (ret < 0) {
189                 printk(KERN_ERR "Kprobe smoke test failed: "
190                                 "register_jprobe returned %d\n", ret);
191                 return ret;
192         }
193
194         ret = target(rand1);
195         unregister_jprobe(&jp);
196         if (jph_val == 0) {
197                 printk(KERN_ERR "Kprobe smoke test failed: "
198                                 "jprobe handler not called\n");
199                 handler_errors++;
200         }
201
202         return 0;
203 }
204
205 static struct jprobe jp2 = {
206         .entry          = j_kprobe_target,
207         .kp.symbol_name = "kprobe_target2"
208 };
209
210 static int test_jprobes(void)
211 {
212         int ret;
213         struct jprobe *jps[2] = {&jp, &jp2};
214
215         /* addr and flags should be cleard for reusing kprobe. */
216         jp.kp.addr = NULL;
217         jp.kp.flags = 0;
218         ret = register_jprobes(jps, 2);
219         if (ret < 0) {
220                 printk(KERN_ERR "Kprobe smoke test failed: "
221                                 "register_jprobes returned %d\n", ret);
222                 return ret;
223         }
224
225         jph_val = 0;
226         ret = target(rand1);
227         if (jph_val == 0) {
228                 printk(KERN_ERR "Kprobe smoke test failed: "
229                                 "jprobe handler not called\n");
230                 handler_errors++;
231         }
232
233         jph_val = 0;
234         ret = target2(rand1);
235         if (jph_val == 0) {
236                 printk(KERN_ERR "Kprobe smoke test failed: "
237                                 "jprobe handler2 not called\n");
238                 handler_errors++;
239         }
240         unregister_jprobes(jps, 2);
241
242         return 0;
243 }
244 #ifdef CONFIG_KRETPROBES
245 static u32 krph_val;
246
247 static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
248 {
249         krph_val = (rand1 / div_factor);
250         return 0;
251 }
252
253 static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
254 {
255         unsigned long ret = regs_return_value(regs);
256
257         if (ret != (rand1 / div_factor)) {
258                 handler_errors++;
259                 printk(KERN_ERR "Kprobe smoke test failed: "
260                                 "incorrect value in kretprobe handler\n");
261         }
262         if (krph_val == 0) {
263                 handler_errors++;
264                 printk(KERN_ERR "Kprobe smoke test failed: "
265                                 "call to kretprobe entry handler failed\n");
266         }
267
268         krph_val = rand1;
269         return 0;
270 }
271
272 static struct kretprobe rp = {
273         .handler        = return_handler,
274         .entry_handler  = entry_handler,
275         .kp.symbol_name = "kprobe_target"
276 };
277
278 static int test_kretprobe(void)
279 {
280         int ret;
281
282         ret = register_kretprobe(&rp);
283         if (ret < 0) {
284                 printk(KERN_ERR "Kprobe smoke test failed: "
285                                 "register_kretprobe returned %d\n", ret);
286                 return ret;
287         }
288
289         ret = target(rand1);
290         unregister_kretprobe(&rp);
291         if (krph_val != rand1) {
292                 printk(KERN_ERR "Kprobe smoke test failed: "
293                                 "kretprobe handler not called\n");
294                 handler_errors++;
295         }
296
297         return 0;
298 }
299
300 static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs)
301 {
302         unsigned long ret = regs_return_value(regs);
303
304         if (ret != (rand1 / div_factor) + 1) {
305                 handler_errors++;
306                 printk(KERN_ERR "Kprobe smoke test failed: "
307                                 "incorrect value in kretprobe handler2\n");
308         }
309         if (krph_val == 0) {
310                 handler_errors++;
311                 printk(KERN_ERR "Kprobe smoke test failed: "
312                                 "call to kretprobe entry handler failed\n");
313         }
314
315         krph_val = rand1;
316         return 0;
317 }
318
319 static struct kretprobe rp2 = {
320         .handler        = return_handler2,
321         .entry_handler  = entry_handler,
322         .kp.symbol_name = "kprobe_target2"
323 };
324
325 static int test_kretprobes(void)
326 {
327         int ret;
328         struct kretprobe *rps[2] = {&rp, &rp2};
329
330         /* addr and flags should be cleard for reusing kprobe. */
331         rp.kp.addr = NULL;
332         rp.kp.flags = 0;
333         ret = register_kretprobes(rps, 2);
334         if (ret < 0) {
335                 printk(KERN_ERR "Kprobe smoke test failed: "
336                                 "register_kretprobe returned %d\n", ret);
337                 return ret;
338         }
339
340         krph_val = 0;
341         ret = target(rand1);
342         if (krph_val != rand1) {
343                 printk(KERN_ERR "Kprobe smoke test failed: "
344                                 "kretprobe handler not called\n");
345                 handler_errors++;
346         }
347
348         krph_val = 0;
349         ret = target2(rand1);
350         if (krph_val != rand1) {
351                 printk(KERN_ERR "Kprobe smoke test failed: "
352                                 "kretprobe handler2 not called\n");
353                 handler_errors++;
354         }
355         unregister_kretprobes(rps, 2);
356         return 0;
357 }
358 #endif /* CONFIG_KRETPROBES */
359
360 int init_test_probes(void)
361 {
362         int ret;
363
364         target = kprobe_target;
365         target2 = kprobe_target2;
366
367         do {
368                 rand1 = prandom_u32();
369         } while (rand1 <= div_factor);
370
371         printk(KERN_INFO "Kprobe smoke test started\n");
372         num_tests++;
373         ret = test_kprobe();
374         if (ret < 0)
375                 errors++;
376
377         num_tests++;
378         ret = test_kprobes();
379         if (ret < 0)
380                 errors++;
381
382         num_tests++;
383         ret = test_jprobe();
384         if (ret < 0)
385                 errors++;
386
387         num_tests++;
388         ret = test_jprobes();
389         if (ret < 0)
390                 errors++;
391
392 #ifdef CONFIG_KRETPROBES
393         num_tests++;
394         ret = test_kretprobe();
395         if (ret < 0)
396                 errors++;
397
398         num_tests++;
399         ret = test_kretprobes();
400         if (ret < 0)
401                 errors++;
402 #endif /* CONFIG_KRETPROBES */
403
404         if (errors)
405                 printk(KERN_ERR "BUG: Kprobe smoke test: %d out of "
406                                 "%d tests failed\n", errors, num_tests);
407         else if (handler_errors)
408                 printk(KERN_ERR "BUG: Kprobe smoke test: %d error(s) "
409                                 "running handlers\n", handler_errors);
410         else
411                 printk(KERN_INFO "Kprobe smoke test passed successfully\n");
412
413         return 0;
414 }