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