1 ////////////////////////////////////////////////////////////////////////////////////
3 // FILE: probes_manager.c
6 // This file is C source for SWAP driver.
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
14 // REVISION DATE: 2008.12.03
16 ////////////////////////////////////////////////////////////////////////////////////
18 #include <linux/percpu.h>
20 #include "probes_manager.h"
24 #include "../kprobe/dbi_kprobes.h"
25 #endif /* def EC_ARCH_arm */
29 //#include <linux/kprobes.h>
30 #include "../kprobe/kprobes.h"
31 #endif /* def EC_ARCH_i386 */
35 #include "../kprobe/kprobes.h"
36 #endif /* def EC_ARCH_mips */
38 unsigned long pf_addr;
39 unsigned long exit_addr;
40 kernel_probe_t *pf_probe = NULL;
41 kernel_probe_t *exit_probe = NULL;
42 unsigned int probes_flags = 0;
45 probes_manager_init (void)
48 pf_addr = lookup_name("handle_mm_fault");
50 pf_addr = lookup_name("do_page_fault");
53 EPRINTF("Cannot find address for page fault function!");
57 exit_addr = lookup_name("do_exit");
59 EPRINTF("Cannot find address for do_exit function!");
63 return storage_init ();
67 probes_manager_down (void)
69 detach_selected_probes ();
74 register_kernel_jprobe (kernel_probe_t * probe)
77 if (((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
78 ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD)))
80 return 0; // probe is already registered
82 result = register_jprobe (&probe->jprobe, 0);
85 EPRINTF ("register_kernel_jprobe(0x%lx) failure %d", probe->addr, result);
92 unregister_kernel_jprobe (kernel_probe_t * probe)
94 if (((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
95 ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD)))
97 return 0; // probe is necessary for user space instrumentation
99 unregister_jprobe (&probe->jprobe, 0);
104 register_kernel_retprobe (kernel_probe_t * probe)
107 if (((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
108 ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD))/* ||
109 ((probe == fork_probe) && (us_proc_probes & US_PROC_FORK_INSTLD)) ||
110 ((probe == ss_probe) && (us_proc_probes & US_PROC_SS_INSTLD))*/)
112 return 0; // probe is already registered
115 result = register_kretprobe (&probe->retprobe, 0);
118 EPRINTF ("register_kernel_retprobe(0x%lx) failure %d", probe->addr, result);
125 unregister_kernel_retprobe (kernel_probe_t * probe)
127 if (((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
128 ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD))/* ||
129 ((probe == fork_probe) && (us_proc_probes & US_PROC_FORK_INSTLD)) ||
130 ((probe == ss_probe) && (us_proc_probes & US_PROC_SS_INSTLD))*/)
132 return 0; // probe is necessary for user space instrumentation
134 unregister_kretprobe (&probe->retprobe, 0);
139 register_kernel_probe (kernel_probe_t * probe)
141 register_kernel_jprobe (probe);
142 register_kernel_retprobe (probe);
147 unregister_kernel_probe (kernel_probe_t * probe)
149 unregister_kernel_jprobe (probe);
150 unregister_kernel_retprobe (probe);
155 attach_selected_probes (void)
158 int partial_result = 0;
160 struct hlist_node *node;
162 hlist_for_each_entry_rcu (p, node, &kernel_probes, hlist)
164 partial_result = register_kernel_probe (p);
167 result = partial_result;
168 detach_selected_probes (); // return into safe state
177 detach_selected_probes (void)
180 struct hlist_node *node;
182 hlist_for_each_entry_rcu (p, node, &kernel_probes, hlist)
183 unregister_kernel_probe (p);
189 add_probe (unsigned long addr)
192 kernel_probe_t **pprobe = NULL;
194 DPRINTF("add probe at 0x%0x\n", addr);
195 if (EC_STATE_IDLE != ec_info.ec_state)
197 EPRINTF("Probes addition is allowed in IDLE state only.");
201 if (addr == pf_addr) {
202 probes_flags |= PROBE_FLAG_PF_INSTLD;
203 if (us_proc_probes & US_PROC_PF_INSTLD)
209 else if (addr == exit_addr) {
210 probes_flags |= PROBE_FLAG_EXIT_INSTLD;
211 if (us_proc_probes & US_PROC_EXIT_INSTLD)
215 pprobe = &exit_probe;
218 result = add_probe_to_list (addr, pprobe);
221 probes_flags &= ~PROBE_FLAG_PF_INSTLD;
222 else if (addr == exit_addr)
223 probes_flags &= ~PROBE_FLAG_EXIT_INSTLD;
230 struct hlist_node *node, *tnode;
233 hlist_for_each_entry_safe (p, node, tnode, &kernel_probes, hlist) {
234 if (p->addr == pf_addr) {
235 probes_flags &= ~PROBE_FLAG_PF_INSTLD;
237 } else if (p->addr == exit_addr) {
238 probes_flags &= ~PROBE_FLAG_EXIT_INSTLD;
249 remove_probe (unsigned long addr)
253 if (EC_STATE_IDLE != ec_info.ec_state)
255 EPRINTF("Probes addition is allowed in IDLE state only.");
259 if (addr == pf_addr) {
260 probes_flags &= ~PROBE_FLAG_PF_INSTLD;
261 if (us_proc_probes & US_PROC_PF_INSTLD)
267 else if (addr == exit_addr) {
268 probes_flags &= ~PROBE_FLAG_EXIT_INSTLD;
269 if (us_proc_probes & US_PROC_EXIT_INSTLD)
276 result = remove_probe_from_list (addr);
281 DEFINE_PER_CPU (kernel_probe_t *, gpKernProbe) = NULL;
282 EXPORT_PER_CPU_SYMBOL_GPL(gpKernProbe);
283 DEFINE_PER_CPU(struct pt_regs *, gpKernRegs) = NULL;
284 EXPORT_PER_CPU_SYMBOL_GPL(gpKernRegs);
287 def_jprobe_event_pre_handler (kernel_probe_t * probe, struct pt_regs *regs)
289 __get_cpu_var (gpKernProbe) = probe;
290 __get_cpu_var (gpKernRegs) = regs;
296 def_jprobe_event_handler (unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6)
299 kernel_probe_t *probe = __get_cpu_var(gpKernProbe);
302 if (pf_probe == probe)
304 if (!(probes_flags & PROBE_FLAG_PF_INSTLD))
307 else if (exit_probe == probe)
309 if (us_proc_probes & US_PROC_EXIT_INSTLD)
310 do_exit_probe_pre_code ();
311 if (!(probes_flags & PROBE_FLAG_EXIT_INSTLD))
316 pack_event_info (KS_PROBE_ID, RECORD_ENTRY, "pxxxxxx", probe->addr, arg1, arg2, arg3, arg4, arg5, arg6);
321 def_retprobe_event_handler (struct kretprobe_instance *pi, struct pt_regs *regs, kernel_probe_t * probe)
325 if (pf_probe == probe)
327 if (us_proc_probes & US_PROC_PF_INSTLD)
328 do_page_fault_ret_pre_code ();
329 if (!(probes_flags & PROBE_FLAG_PF_INSTLD))
332 else if (exit_probe == probe)
334 if (!(probes_flags & PROBE_FLAG_EXIT_INSTLD))
339 pack_event_info (KS_PROBE_ID, RECORD_RET, "p", probe->addr);
343 /* This is a callback that is called by module 'inperfa_handlers'
344 * in order to register user defined handlers */
345 void install_user_handlers(void)
347 kernel_probe_t *probe;
348 struct hlist_node *node;
349 unsigned long pre_handler_addr, jp_handler_addr, rp_handler_addr;
351 /* We must perform this lookup whenever this function is called
352 * because the addresses of find_*_handler functions may differ. */
353 // MCPP inperfa_handlers removed
354 unsigned long (*find_jp_handler)(unsigned long) =
355 // MCPP inperfa_handlers removed
356 (unsigned long (*)(unsigned long))lookup_name("find_jp_handler");
357 unsigned long (*find_rp_handler)(unsigned long) =
358 (unsigned long (*)(unsigned long))lookup_name("find_rp_handler");
359 unsigned long (*find_pre_handler)(unsigned long) =
360 (unsigned long (*)(unsigned long))lookup_name("find_pre_handler");
361 hlist_for_each_entry_rcu (probe, node, &kernel_probes, hlist) {
364 pre_handler_addr = find_pre_handler(probe->addr);
365 if (find_pre_handler != 0) {
366 DPRINTF("Added user pre handler for 0x%lx: 0x%lx",
367 probe->addr, find_pre_handler);
368 probe->jprobe.pre_entry = (kprobe_pre_entry_handler_t)pre_handler_addr;
371 jp_handler_addr = find_jp_handler(probe->addr);
372 if (jp_handler_addr != 0) {
373 DPRINTF("Added user jp handler for 0x%lx: 0x%lx",
374 probe->addr, jp_handler_addr);
375 probe->jprobe.entry = (kprobe_opcode_t *)jp_handler_addr;
377 rp_handler_addr = find_rp_handler(probe->addr);
378 if (rp_handler_addr != 0)
379 probe->retprobe.handler = (kretprobe_handler_t)rp_handler_addr;
382 EXPORT_SYMBOL_GPL(install_user_handlers);
384 void uninstall_user_handlers(void)
386 kernel_probe_t *probe;
387 struct hlist_node *node;
389 hlist_for_each_entry_rcu (probe, node, &kernel_probes, hlist) {
390 DPRINTF("Removed user jp handler for 0x%lx", probe->addr);
391 probe->jprobe.pre_entry = (kprobe_pre_entry_handler_t)def_jprobe_event_pre_handler;
392 probe->jprobe.entry = (kprobe_opcode_t *)def_jprobe_event_handler;
393 probe->retprobe.handler = (kretprobe_handler_t)def_retprobe_event_handler;
396 EXPORT_SYMBOL_GPL(uninstall_user_handlers);
398 int is_pf_installed_by_user(void)
400 return (probes_flags & PROBE_FLAG_PF_INSTLD) ? 1: 0;
402 EXPORT_SYMBOL_GPL(is_pf_installed_by_user);