3c748c05819d48b9b8e3cdd4b7c2eef65d83cfdd
[kernel/swap-modules.git] / driver / probes_manager.c
1 ////////////////////////////////////////////////////////////////////////////////////
2 //
3 //      FILE:           probes_manager.c
4 //
5 //      DESCRIPTION:
6 //      This file is C source for SWAP driver.
7 //
8 //      SEE ALSO:       probes_manager.h
9 //      AUTHOR:         L.Komkov, A.Gerenkov
10 //      COMPANY NAME:   Samsung Research Center in Moscow
11 //      DEPT NAME:      Advanced Software Group
12 //      CREATED:        2008.02.15
13 //      VERSION:        1.0
14 //      REVISION DATE:  2008.12.03
15 //
16 ////////////////////////////////////////////////////////////////////////////////////
17
18 #include <linux/percpu.h>
19 #include "module.h"
20 #include "probes_manager.h"
21
22 #ifdef EC_ARCH_arm
23 /* ARCH == arm */
24 #include "../kprobe/dbi_kprobes.h"
25 #endif /* def EC_ARCH_arm */
26
27 #ifdef EC_ARCH_x86
28 /* ARCH == x86 */
29 //#include <linux/kprobes.h>
30 #include "../kprobe/dbi_kprobes.h"
31 #endif /* def EC_ARCH_x86 */
32
33 #ifdef EC_ARCH_mips
34 /* ARCH == mips */
35 #include "../kprobe/dbi_kprobes.h"
36 #endif /* def EC_ARCH_mips */
37
38 unsigned long pf_addr;
39 unsigned long cp_addr;
40 unsigned long mr_addr;
41 unsigned long exit_addr;
42 unsigned long unmap_addr;
43 kernel_probe_t *pf_probe = NULL;
44 kernel_probe_t *cp_probe = NULL;
45 kernel_probe_t *mr_probe = NULL;
46 kernel_probe_t *exit_probe = NULL;
47 kernel_probe_t *unmap_probe = NULL;
48 unsigned int probes_flags = 0;
49
50 int
51 probes_manager_init (void)
52 {
53 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
54         spin_lock_init(&ec_spinlock);
55         spin_lock_init(&ec_probe_spinlock);
56 #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
57 #ifdef CONFIG_X86
58         //pf_addr = lookup_name("handle_mm_fault");
59         pf_addr = lookup_name("do_page_fault");
60 #else
61         pf_addr = lookup_name("do_page_fault");
62 #endif
63         if (pf_addr == 0) {
64                 EPRINTF("Cannot find address for page fault function!");
65                 return -EINVAL;
66         }
67
68         cp_addr = lookup_name("copy_process");
69         if (cp_addr == 0) {
70                 EPRINTF("Cannot find address for copy_process function!");
71                 return -EINVAL;
72         }
73
74         mr_addr = lookup_name("mm_release");
75         if (mr_addr == 0) {
76                 EPRINTF("Cannot find address for mm_release function!");
77                 return -EINVAL;
78         }
79
80         exit_addr = lookup_name("do_exit");
81         if (exit_addr == 0) {
82                 EPRINTF("Cannot find address for do_exit function!");
83                 return -EINVAL;
84         }
85
86         unmap_addr = lookup_name("do_munmap");
87         if (unmap_addr == 0) {
88                 EPRINTF("Cannot find address for do_munmap function!");
89                 return -EINVAL;
90         }
91
92         return storage_init ();
93 }
94
95 void
96 probes_manager_down (void)
97 {
98         detach_selected_probes ();
99         storage_down ();
100 }
101
102 static int
103 register_kernel_jprobe (kernel_probe_t * probe)
104 {
105         int result;
106         if( ((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
107             ((probe == cp_probe) && (us_proc_probes & US_PROC_CP_INSTLD)) ||
108             ((probe == mr_probe) && (us_proc_probes & US_PROC_MR_INSTLD)) ||
109             ((probe == unmap_probe) && (us_proc_probes & US_PROC_UNMAP_INSTLD)) ||
110             ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD)))
111         {
112                 return 0;       // probe is already registered
113         }
114         result = dbi_register_jprobe (&probe->jprobe);
115         if (result)
116         {
117                 EPRINTF ("register_kernel_jprobe(0x%lx) failure %d", probe->addr, result);
118                 return result;
119         }
120         return 0;
121 }
122
123 static int
124 unregister_kernel_jprobe (kernel_probe_t * probe)
125 {
126         if( ((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
127             ((probe == cp_probe) && (us_proc_probes & US_PROC_CP_INSTLD)) ||
128             ((probe == mr_probe) && (us_proc_probes & US_PROC_MR_INSTLD)) ||
129             ((probe == unmap_probe) && (us_proc_probes & US_PROC_UNMAP_INSTLD)) ||
130             ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD)) ) {
131                 return 0;       // probe is necessary for user space instrumentation
132         }
133         dbi_unregister_jprobe (&probe->jprobe);
134         return 0;
135 }
136
137 static int
138 register_kernel_retprobe (kernel_probe_t * probe)
139 {
140         int result;
141         if( ((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
142             ((probe == cp_probe) && (us_proc_probes & US_PROC_CP_INSTLD)) ||
143             ((probe == mr_probe) && (us_proc_probes & US_PROC_MR_INSTLD)) ||
144             ((probe == unmap_probe) && (us_proc_probes & US_PROC_UNMAP_INSTLD)) ||
145             ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD)) ) {
146
147                 return 0;       // probe is already registered
148         }
149
150         result = dbi_register_kretprobe (&probe->retprobe);
151         if (result)
152         {
153                 EPRINTF ("register_kernel_retprobe(0x%lx) failure %d", probe->addr, result);
154                 return result;
155         }
156         return 0;
157 }
158
159 static int
160 unregister_kernel_retprobe (kernel_probe_t * probe)
161 {
162         if( ((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
163             ((probe == cp_probe) && (us_proc_probes & US_PROC_CP_INSTLD)) ||
164             ((probe == mr_probe) && (us_proc_probes & US_PROC_MR_INSTLD)) ||
165             ((probe == unmap_probe) && (us_proc_probes & US_PROC_UNMAP_INSTLD)) ||
166             ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD)) ) {
167                 return 0;       // probe is necessary for user space instrumentation
168         }
169         dbi_unregister_kretprobe (&probe->retprobe);
170         return 0;
171 }
172
173 int
174 register_kernel_probe (kernel_probe_t * probe)
175 {
176         register_kernel_jprobe (probe);
177         register_kernel_retprobe (probe);
178         return 0;
179 }
180
181 int
182 unregister_kernel_probe (kernel_probe_t * probe)
183 {
184         unregister_kernel_jprobe (probe);
185         unregister_kernel_retprobe (probe);
186         return 0;
187 }
188
189 int
190 attach_selected_probes (void)
191 {
192         int result = 0;
193         int partial_result = 0;
194         kernel_probe_t *p;
195         struct hlist_node *node;
196
197         hlist_for_each_entry_rcu (p, node, &kernel_probes, hlist)
198         {
199                 partial_result = register_kernel_probe (p);
200                 if (partial_result)
201                 {
202                         result = partial_result;
203                         detach_selected_probes ();      // return into safe state
204                         break;
205                 }
206         }
207
208         return result;
209 }
210
211 int
212 detach_selected_probes (void)
213 {
214         kernel_probe_t *p;
215         struct hlist_node *node;
216
217         hlist_for_each_entry_rcu (p, node, &kernel_probes, hlist)
218                 unregister_kernel_probe (p);
219         hlist_for_each_entry_rcu (p, node, &otg_kernel_probes, hlist) {
220                 unregister_kernel_probe(p);
221         }
222
223         return 0;
224 }
225
226 int
227 add_probe (unsigned long addr)
228 {
229         int result = 0;
230         kernel_probe_t **pprobe = NULL;
231
232         DPRINTF("add probe at 0x%0x\n", addr);
233         if (EC_STATE_IDLE != ec_info.ec_state)
234         {
235                 EPRINTF("Probes addition is allowed in IDLE state only.");
236                 return -EINVAL;
237         }
238
239         if (addr == pf_addr) {
240                 probes_flags |= PROBE_FLAG_PF_INSTLD;
241                 if (us_proc_probes & US_PROC_PF_INSTLD)
242                 {
243                         return 0;
244                 }
245                 pprobe = &pf_probe;
246         }
247         else if (addr == cp_addr) {
248                 probes_flags |= PROBE_FLAG_CP_INSTLD;
249                 if (us_proc_probes & US_PROC_CP_INSTLD)
250                 {
251                         return 0;
252                 }
253                 pprobe = &cp_probe;
254         }
255         else if (addr == exit_addr) {
256                 probes_flags |= PROBE_FLAG_EXIT_INSTLD;
257                 if (us_proc_probes & US_PROC_EXIT_INSTLD)
258                 {
259                         return 0;
260                 }
261                 pprobe = &exit_probe;
262         }
263         else if (addr == mr_addr) {
264                 probes_flags |= PROBE_FLAG_MR_INSTLD;
265                 if (us_proc_probes & US_PROC_MR_INSTLD) {
266                         return 0;
267                 }
268                 pprobe = &mr_probe;
269         }
270         else if (addr == unmap_addr) {
271                 probes_flags |= PROBE_FLAG_UNMAP_INSTLD;
272                 if (us_proc_probes & US_PROC_UNMAP_INSTLD)
273                 {
274                         return 0;
275                 }
276                 pprobe = &unmap_probe;
277         }
278
279         result = add_probe_to_list (addr, pprobe);
280         if (result) {
281                 if (addr == pf_addr)
282                         probes_flags &= ~PROBE_FLAG_PF_INSTLD;
283                 else if (addr == cp_addr)
284                         probes_flags &= ~PROBE_FLAG_CP_INSTLD;
285                 else if (addr == exit_addr)
286                         probes_flags &= ~PROBE_FLAG_EXIT_INSTLD;
287                 else if (addr == mr_addr)
288                         probes_flags &= ~PROBE_FLAG_MR_INSTLD;
289                 else if (addr == unmap_addr)
290                         probes_flags &= ~PROBE_FLAG_UNMAP_INSTLD;
291         }
292         return result;
293 }
294
295 int reset_probes()
296 {
297         struct hlist_node *node, *tnode;
298         kernel_probe_t *p;
299
300         hlist_for_each_entry_safe (p, node, tnode, &kernel_probes, hlist) {
301                 if (p->addr == pf_addr) {
302                         probes_flags &= ~PROBE_FLAG_PF_INSTLD;
303                         pf_probe = NULL;
304                 } else if (p->addr == cp_addr) {
305                         probes_flags &= ~PROBE_FLAG_CP_INSTLD;
306                         cp_probe = NULL;
307                 } else if (p->addr == exit_addr) {
308                         probes_flags &= ~PROBE_FLAG_EXIT_INSTLD;
309                         exit_probe = NULL;
310                 } else if (p->addr == mr_addr) {
311                         probes_flags &= ~PROBE_FLAG_MR_INSTLD;
312                         mr_probe = NULL;
313                 } else if (p->addr == unmap_addr) {
314                         probes_flags &= ~PROBE_FLAG_UNMAP_INSTLD;
315                         unmap_probe = NULL;
316                 }
317                 hlist_del(node);
318                 kfree(p);
319         }
320
321         hlist_for_each_entry_safe (p, node, tnode, &otg_kernel_probes, hlist) {
322                 if (p->addr == pf_addr) {
323                         probes_flags &= ~PROBE_FLAG_PF_INSTLD;
324                         pf_probe = NULL;
325                 } else if (p->addr == cp_addr) {
326                         probes_flags &= ~PROBE_FLAG_CP_INSTLD;
327                         cp_probe = NULL;
328                 } else if (p->addr == exit_addr) {
329                         probes_flags &= ~PROBE_FLAG_EXIT_INSTLD;
330                         exit_probe = NULL;
331                 } else if (p->addr == mr_addr) {
332                         probes_flags &= ~PROBE_FLAG_MR_INSTLD;
333                         mr_probe = NULL;
334                 } else if (p->addr == unmap_addr) {
335                         probes_flags &= ~PROBE_FLAG_UNMAP_INSTLD;
336                         unmap_probe = NULL;
337                 }
338                 hlist_del(node);
339                 kfree(p);
340         }
341
342         return 0;
343 }
344
345 int
346 remove_probe (unsigned long addr)
347 {
348         int result = 0;
349
350         if (EC_STATE_IDLE != ec_info.ec_state)
351         {
352                 EPRINTF("Probes addition is allowed in IDLE state only.");
353                 return -EINVAL;
354         }
355
356         if (addr == pf_addr) {
357                 probes_flags &= ~PROBE_FLAG_PF_INSTLD;
358                 if (us_proc_probes & US_PROC_PF_INSTLD)
359                 {
360                         return 0;
361                 }
362                 pf_probe = NULL;
363         }
364         else if (addr == cp_addr) {
365                 probes_flags &= ~PROBE_FLAG_CP_INSTLD;
366                 if (us_proc_probes & US_PROC_CP_INSTLD)
367                 {
368                         return 0;
369                 }
370                 cp_probe = NULL;
371         }
372         else if (addr == mr_addr) {
373                 probes_flags &= ~PROBE_FLAG_MR_INSTLD;
374                 if (us_proc_probes & US_PROC_MR_INSTLD) {
375                         return 0;
376                 }
377                 mr_probe = NULL;
378         }
379         else if (addr == exit_addr) {
380                 probes_flags &= ~PROBE_FLAG_EXIT_INSTLD;
381                 if (us_proc_probes & US_PROC_EXIT_INSTLD)
382                 {
383                         return 0;
384                 }
385                 exit_probe = NULL;
386         }
387         else if (addr == unmap_addr) {
388                 probes_flags &= ~PROBE_FLAG_UNMAP_INSTLD;
389                 if (us_proc_probes & US_PROC_UNMAP_INSTLD)
390                 {
391                         return 0;
392                 }
393                 unmap_probe = NULL;
394         }
395
396         result = remove_probe_from_list (addr);
397
398         return result;
399 }
400
401 DEFINE_PER_CPU (kernel_probe_t *, gpKernProbe) = NULL;
402 EXPORT_PER_CPU_SYMBOL_GPL(gpKernProbe);
403
404 unsigned long
405 def_jprobe_event_pre_handler (kernel_probe_t * probe, struct pt_regs *regs)
406 {
407         __get_cpu_var (gpKernProbe) = probe;
408
409         return 0;
410 }
411
412 void
413 def_jprobe_event_handler (unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6)
414 {
415         //static int nCount;
416         kernel_probe_t *probe = __get_cpu_var(gpKernProbe);
417         int skip = 0;
418
419         if (pf_probe == probe)
420         {
421 #ifdef CONFIG_X86
422                 /* FIXME on x86 targets do_page_fault instrumentation may lead to
423                  * abnormal termination of some applications (in most cases GUI apps).
424                  * It looks like when do_page_fault probe is hit and the
425                  * def_jprobe_event_handler is executed it tries to write event info
426                  * into the SWAP buffer which seems not to be mapped into the
427                  * process memory yet. Such behaviour causes segmentation faults.
428                  * For now as a workaround we just avoid to write the ENTRY event into
429                  * the buffer in all cases. */
430                 skip = 1;
431 #else /* CONFIG_X86 */
432                 if (!(probes_flags & PROBE_FLAG_PF_INSTLD))
433                         skip = 1;
434 #endif /* CONFIG_X86 */
435         }
436         else if (cp_probe == probe)
437         {
438                 if (!(probes_flags & PROBE_FLAG_CP_INSTLD))
439                         skip = 1;
440         }
441         else if (mr_probe == probe)
442         {
443                 if (us_proc_probes & US_PROC_MR_INSTLD)
444                         mm_release_probe_pre_code();
445                 if (!(probes_flags & PROBE_FLAG_MR_INSTLD))
446                         skip = 1;
447         }
448         else if (exit_probe == probe)
449         {
450                 if (us_proc_probes & US_PROC_EXIT_INSTLD)
451                         do_exit_probe_pre_code();
452                 if (!(probes_flags & PROBE_FLAG_EXIT_INSTLD))
453                         skip = 1;
454         }
455         else if (unmap_probe == probe)
456         {
457                 if (us_proc_probes & US_PROC_UNMAP_INSTLD)
458                         do_munmap_probe_pre_code((struct mm_struct *)arg1, arg2, (size_t)arg3);
459                 if (!(probes_flags & PROBE_FLAG_UNMAP_INSTLD))
460                         skip = 1;
461         }
462
463         if (!skip)
464                 pack_event_info (KS_PROBE_ID, RECORD_ENTRY, "pxxxxxx", probe->addr, arg1, arg2, arg3, arg4, arg5, arg6);
465         dbi_jprobe_return ();
466 }
467
468 int
469 def_retprobe_event_handler (struct kretprobe_instance *pi, struct pt_regs *regs, kernel_probe_t * probe)
470 {
471         int skip = 0;
472         int ret_val;
473
474         if (pf_probe == probe)
475         {
476                 if (us_proc_probes & US_PROC_PF_INSTLD)
477                         do_page_fault_ret_pre_code ();
478                 if (!(probes_flags & PROBE_FLAG_PF_INSTLD))
479                         skip = 1;
480         }
481         if (cp_probe == probe)
482         {
483                 if (us_proc_probes & US_PROC_CP_INSTLD)
484                         copy_process_ret_pre_code((struct task_struct*)(regs_return_value(regs)));
485
486                 if (!(probes_flags & PROBE_FLAG_CP_INSTLD))
487                         skip = 1;
488         }
489         else if (mr_probe == probe)
490         {
491                 if (!(probes_flags & PROBE_FLAG_MR_INSTLD))
492                         skip = 1;
493         }
494         else if (exit_probe == probe)
495         {
496                 if (!(probes_flags & PROBE_FLAG_EXIT_INSTLD))
497                         skip = 1;
498         }
499         else if (unmap_probe == probe)
500         {
501                 if (!(probes_flags & PROBE_FLAG_UNMAP_INSTLD))
502                         skip = 1;
503         }
504
505         if (!skip) {
506                 ret_val = regs_return_value(regs);
507                 pack_event_info (KS_PROBE_ID, RECORD_RET, "pd",
508                                  probe->addr, ret_val);
509         }
510         return 0;
511 }
512
513 /* This is a callback that is called by module 'swap_handlers'
514  * in order to register user defined handlers */
515 void dbi_install_user_handlers(void)
516 {
517         kernel_probe_t *probe;
518         struct hlist_node *node;
519         unsigned long pre_handler_addr, jp_handler_addr, rp_handler_addr;
520
521         /* We must perform this lookup whenever this function is called
522          * because the addresses of find_*_handler functions may differ. */
523         // swap_handlers removed
524         unsigned long (*find_jp_handler)(unsigned long) =
525         // swap_handlers removed
526                 (unsigned long (*)(unsigned long))lookup_name("find_jp_handler");
527         unsigned long (*find_rp_handler)(unsigned long) =
528                         (unsigned long (*)(unsigned long))lookup_name("find_rp_handler");
529         unsigned long (*find_pre_handler)(unsigned long) =
530                         (unsigned long (*)(unsigned long))lookup_name("find_pre_handler");
531         hlist_for_each_entry_rcu (probe, node, &kernel_probes, hlist) {
532                 if(find_pre_handler)
533                 {
534                         pre_handler_addr = find_pre_handler(probe->addr);
535                         if (find_pre_handler != 0) {
536                                 DPRINTF("Added user pre handler for 0x%lx: 0x%lx",
537                                                 probe->addr, find_pre_handler);
538                                 probe->jprobe.pre_entry = (kprobe_pre_entry_handler_t)pre_handler_addr;
539                         }
540                 }
541                 jp_handler_addr = find_jp_handler(probe->addr);
542                 if (jp_handler_addr != 0) {
543                         DPRINTF("Added user jp handler for 0x%lx: 0x%lx",
544                                         probe->addr, jp_handler_addr);
545                         probe->jprobe.entry = (kprobe_opcode_t *)jp_handler_addr;
546                 }
547                 rp_handler_addr = find_rp_handler(probe->addr);
548                 if (rp_handler_addr != 0)
549                         probe->retprobe.handler = (kretprobe_handler_t)rp_handler_addr;
550         }
551 }
552 EXPORT_SYMBOL_GPL(dbi_install_user_handlers);
553
554 void dbi_uninstall_user_handlers(void)
555 {
556         kernel_probe_t *probe;
557         struct hlist_node *node;
558
559         hlist_for_each_entry_rcu (probe, node, &kernel_probes, hlist) {
560                 DPRINTF("Removed user jp handler for 0x%lx", probe->addr);
561                 probe->jprobe.pre_entry = (kprobe_pre_entry_handler_t)def_jprobe_event_pre_handler;
562                 probe->jprobe.entry = (kprobe_opcode_t *)def_jprobe_event_handler;
563                 probe->retprobe.handler = (kretprobe_handler_t)def_retprobe_event_handler;
564         }
565 }
566 EXPORT_SYMBOL_GPL(dbi_uninstall_user_handlers);
567
568 int is_pf_installed_by_user(void)
569 {
570         return (probes_flags & PROBE_FLAG_PF_INSTLD) ? 1: 0;
571 }
572 EXPORT_SYMBOL_GPL(is_pf_installed_by_user);
573
574 int install_kern_otg_probe(unsigned long addr,
575                            unsigned long pre_handler,
576                            unsigned long jp_handler,
577                            unsigned long rp_handler)
578 {
579         kernel_probe_t *new_probe = NULL;
580         kernel_probe_t *probe;
581         int ret = 0;
582
583         probe = find_probe(addr);
584         if (probe) {
585                 /* It is not a problem if we have already registered
586                    this probe before */
587                 return 0;
588         }
589
590         new_probe = kmalloc(sizeof (kernel_probe_t), GFP_ATOMIC);
591         if (!new_probe) {
592                 EPRINTF("No memory for new probe");
593                 return -1;
594         }
595         memset(new_probe, 0, sizeof(kernel_probe_t));
596
597         new_probe->addr = addr;
598         new_probe->jprobe.kp.addr = new_probe->retprobe.kp.addr = (kprobe_opcode_t *)addr;
599         new_probe->jprobe.priv_arg = new_probe->retprobe.priv_arg = new_probe;
600
601         if (pre_handler) {
602                 new_probe->jprobe.pre_entry =
603                         (kprobe_pre_entry_handler_t)
604                         pre_handler;
605         } else {
606                 new_probe->jprobe.pre_entry =
607                         (kprobe_pre_entry_handler_t)
608                         def_jprobe_event_pre_handler;
609         }
610
611         if (jp_handler) {
612                 new_probe->jprobe.entry = (kprobe_opcode_t *)jp_handler;
613         } else {
614                 new_probe->jprobe.entry =
615                         (kprobe_opcode_t *)
616                         def_jprobe_event_handler;
617         }
618
619         if (rp_handler) {
620                 new_probe->retprobe.handler = (kretprobe_handler_t)rp_handler;
621         } else {
622                 new_probe->retprobe.handler =
623                         (kretprobe_handler_t)
624                         def_retprobe_event_handler;
625         }
626
627         INIT_HLIST_NODE (&new_probe->hlist);
628         hlist_add_head_rcu (&new_probe->hlist, &kernel_probes);
629
630         ret = register_kernel_probe(new_probe);
631         if (ret) {
632                 EPRINTF("Cannot set kernel probe at addr %lx", addr);
633                 return -1;
634         }
635
636         return 0;
637 }
638 EXPORT_SYMBOL_GPL(install_kern_otg_probe);