1 ////////////////////////////////////////////////////////////////////////////////////
3 // FILE: device_driver.c
6 // This file is C source for SWAP driver.
8 // SEE ALSO: device_driver.h
9 // AUTHOR: L.Komkov, S.Dianov, S.Grekhov, 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 ////////////////////////////////////////////////////////////////////////////////////
19 #include "device_driver.h" // device driver
20 #include "handlers_core.h"
21 #include <linux/notifier.h>
22 #include "sspt/sspt_procs.h"
25 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
26 static BLOCKING_NOTIFIER_HEAD(swap_notifier_list);
29 EXPORT_SYMBOL_GPL(gl_nNotifyTgid);
31 static DECLARE_WAIT_QUEUE_HEAD (notification_waiters_queue);
32 static volatile unsigned notification_count;
34 static int device_mmap (struct file *filp, struct vm_area_struct *vma);
35 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
36 static int device_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
38 static long device_ioctl (struct file *file, unsigned int cmd, unsigned long arg);
40 static int device_open(struct inode *, struct file *);
41 static int device_release(struct inode *, struct file *);
42 static ssize_t device_read(struct file *, char __user *, size_t, loff_t *);
43 static ssize_t device_write(struct file *, const char __user *, size_t, loff_t *);
45 static int gl_nDeviceOpened = 0;
46 static struct file_operations device_fops = {
49 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
50 .ioctl = device_ioctl,
52 .unlocked_ioctl = device_ioctl,
55 .write = device_write,
57 .release = device_release
60 typedef void (* dbi_module_callback)(void);
62 int device_init (void)
65 nReserved = register_chrdev(0, device_name, &device_fops);
68 unregister_chrdev(nReserved, device_name);
69 EPRINTF("Cannot register character device!");
72 EPRINTF("New device node with major number [%d], was created\n", nReserved);
73 device_major = nReserved;
77 void device_down (void)
79 unregister_chrdev(device_major, device_name);
82 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
83 void swap_register_notify (struct notifier_block *nb)
85 blocking_notifier_chain_register(&swap_notifier_list, nb);
87 EXPORT_SYMBOL_GPL(swap_register_notify);
89 void swap_unregister_notify (struct notifier_block *nb)
91 blocking_notifier_chain_unregister(&swap_notifier_list, nb);
93 EXPORT_SYMBOL_GPL(swap_unregister_notify);
96 void notify_user (event_id_t event_id)
98 ec_info.events_counters[event_id] += 1;
100 if (EVENT_EC_PROBE_RECORD == event_id)
102 // EC_PROBE_RECORD events happen to often. To reduce overhead user
103 // space will be notified only once per each EVENTS_AGGREGATION_USEC
104 static uint64_t timestamp_usec = 0;
106 uint64_t current_usec;
111 do_gettimeofday (&tv);
112 current_usec = 1000000ULL * (unsigned) tv.tv_sec + (unsigned) tv.tv_usec;
114 if (current_usec < timestamp_usec)
116 // Note: time from do_gettimeofday() may go backward
117 EPRINTF ("current_usec=%llu timestamp_usec=%llu", current_usec, timestamp_usec);
121 delta_usec = current_usec - timestamp_usec;
122 if (EVENTS_AGGREGATION_USEC > delta_usec)
124 // wait the time left
126 unsigned UNUSED left_usec = EVENTS_AGGREGATION_USEC - delta_usec;
127 #endif /* defined(__DEBUG) */
128 return; // supress notification
131 timestamp_usec = current_usec; // remember new time for the future use
132 } else if (EVENT_EC_START_CONDITION_SEEN == event_id) {
133 return; // supress notification
134 } else if (EVENT_EC_STOP_CONDITION_SEEN == event_id) {
135 return; // supress notification
138 ++notification_count;
139 wake_up_interruptible (¬ification_waiters_queue);
142 static int device_mmap (struct file *filp UNUSED, struct vm_area_struct *vma)
145 EPRINTF("Null pointer to buffer!");
148 return remap_vmalloc_range (vma, p_buffer, 0);
151 static int device_open(struct inode *inode, struct file *file)
153 /*if (gl_nDeviceOpened)
157 try_module_get(THIS_MODULE);
161 static int device_release(struct inode *inode, struct file *file)
164 module_put(THIS_MODULE);
169 static ssize_t device_read(struct file *filp, char __user *buffer, size_t length, loff_t * offset)
171 EPRINTF("Operation <<read>> not supported!");
175 static ssize_t device_write(struct file *filp, const char __user *buff, size_t len, loff_t * off)
177 EPRINTF("Operation <<write>> not supported!");
181 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
182 static int device_ioctl (struct inode *inode UNUSED, struct file *file UNUSED, unsigned int cmd, unsigned long arg)
184 static long device_ioctl (struct file *file UNUSED, unsigned int cmd, unsigned long arg)
187 unsigned long spinlock_flags = 0L;
189 void __user * arg_pointer = (void __user *) arg;
190 // DPRINTF("Command=%d", cmd);
193 case EC_IOCTL_SET_EC_MODE:
195 ioctl_general_t param;
196 unsigned long nIgnoredBytes = 0;
197 memset(¶m, '0', sizeof(ioctl_general_t));
198 nIgnoredBytes = copy_from_user (¶m, arg_pointer, sizeof(ioctl_general_t));
199 if (nIgnoredBytes > 0) {
203 if(SetECMode(param.m_unsignedLong) == -1) {
208 DPRINTF("Set EC Mode = %lu", param.m_unsignedLong);
211 case EC_IOCTL_GET_EC_MODE:
213 ioctl_general_t param;
214 unsigned long nIgnoredBytes = 0;
215 memset(¶m, '0', sizeof(ioctl_general_t));
216 param.m_unsignedLong = GetECMode();
217 nIgnoredBytes = copy_to_user (arg_pointer, ¶m, sizeof (ioctl_general_t));
218 if (nIgnoredBytes > 0) {
223 // DPRINTF("Get EC Mode = %lu", param.m_unsignedLong); // Frequent call
226 case EC_IOCTL_SET_BUFFER_SIZE:
228 ioctl_general_t param;
229 unsigned long nIgnoredBytes = 0;
230 memset(¶m, '0', sizeof(ioctl_general_t));
231 nIgnoredBytes = copy_from_user (¶m, arg_pointer, sizeof(ioctl_general_t));
232 if (nIgnoredBytes > 0) {
236 if (SetBufferSize(param.m_unsignedLong) == -1) {
241 DPRINTF("Set Buffer Size = %lu", param.m_unsignedLong);
244 case EC_IOCTL_GET_BUFFER_SIZE:
246 ioctl_general_t param;
247 unsigned long nIgnoredBytes = 0;
248 memset(¶m, '0', sizeof(ioctl_general_t));
249 param.m_unsignedLong = GetBufferSize();
250 nIgnoredBytes = copy_to_user (arg_pointer, ¶m, sizeof (ioctl_general_t));
251 if (nIgnoredBytes > 0) {
256 DPRINTF("Get Buffer Size = %lu", param.m_unsignedLong);
259 case EC_IOCTL_RESET_BUFFER:
261 if (ResetBuffer() == -1) {
266 DPRINTF("Reset Buffer");
269 case EC_IOCTL_GET_EC_INFO:
271 if (copy_ec_info_to_user_space ((ec_info_t *) arg) != 0) {
276 // DPRINTF("Get Buffer Status"); // Frequent call
279 case EC_IOCTL_CONSUME_BUFFER:
281 static ec_info_t ec_info_copy;
282 int nIgnoredBytes = 0;
284 nIgnoredBytes = copy_from_user (&ec_info_copy, (const void __user *) arg, sizeof (ec_info_t));
285 if(nIgnoredBytes > 0)
287 EPRINTF ("copy_from_user(%08X,%08X)=%d", (unsigned) arg, (unsigned) &ec_info_copy, nIgnoredBytes);
292 spin_lock_irqsave (&ec_spinlock, spinlock_flags);
295 if(ec_info.after_last > ec_info.first) {
296 ec_info.buffer_effect = ec_info.buffer_size;
298 if (ec_info.after_last == ec_info.buffer_effect) {
301 ec_info.first = ec_info_copy.after_last;
303 ec_info.trace_size = ec_info.trace_size - ec_info_copy.trace_size;
305 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
307 // DPRINTF("Consume Buffer"); // Frequent call
310 case EC_IOCTL_ADD_PROBE:
312 unsigned long addr = arg;
313 unsigned long pre_handler = 0, jp_handler = 0, rp_handler = 0;
315 dbi_find_and_set_handler_for_probe(addr, &pre_handler, &jp_handler, &rp_handler);
316 result = add_probe(addr, pre_handler, jp_handler, rp_handler);
320 //@AGv: remove_probe expects probe address instead of name
321 /*case EC_IOCTL_REMOVE_PROBE:
323 char *probe_name = (char *) arg;
324 result = remove_probe (probe_name);
328 case EC_IOCTL_SET_APPDEPS:
331 result = copy_from_user(&size, arg_pointer, sizeof(size_t));
333 EPRINTF("Cannot copy deps size!");
337 DPRINTF("Deps size has been copied (%d)", size);
340 DPRINTF("Deps are size of 0");
344 deps = vmalloc(size);
346 EPRINTF("Cannot alloc mem for deps!");
350 DPRINTF("Mem for deps has been allocated");
352 result = copy_from_user(deps, arg_pointer, size);
354 EPRINTF("Cannot copy deps!");
358 DPRINTF("Deps has been copied successfully");
362 case EC_IOCTL_SET_PID:
366 result = copy_from_user(&_pid, arg_pointer, sizeof(unsigned int));
368 EPRINTF("Cannot copy pid!");
375 DPRINTF("EC_IOCTL_SET_PID pid:%d", inst_pid);
379 case EC_IOCTL_SET_PROFILEBUNDLE:
383 result = copy_from_user(&size, arg_pointer, sizeof(size_t));
385 EPRINTF("Cannot copy bundle size!");
389 DPRINTF("Bundle size has been copied");
391 bundle = vmalloc(size);
392 if (bundle == NULL) {
393 EPRINTF("Cannot alloc mem for bundle!");
397 DPRINTF("Mem for bundle has been alloced");
399 result = copy_from_user(bundle, arg_pointer, size);
401 EPRINTF("Cannot copy bundle!");
405 DPRINTF("Bundle has been copied successfully");
407 if (link_bundle() == -1 || has_last_error() == -1) {
408 EPRINTF("Cannot link profile bundle!");
415 case EC_IOCTL_RESET_PROBES:
417 result = reset_probes();
421 case EC_IOCTL_UPDATE_CONDS:
424 struct cond *c, *c_tmp, *p_cond;
425 unsigned char *p_data;
428 err = copy_from_user(&args_cnt, arg_pointer, sizeof(int));
433 /* first, delete all the conds */
434 list_for_each_entry_safe(c, c_tmp, &cond_list.list, list) {
438 /* second, add new conds */
439 p_data = (unsigned char *)(arg + sizeof(int));
440 for (i = 0; i < args_cnt; i++) {
441 p_cond = kmalloc(sizeof(struct cond), GFP_KERNEL);
443 DPRINTF("Cannot alloc cond!");
447 err = copy_from_user(&p_cond->tmpl, (const void __user *)p_data,
448 sizeof(struct event_tmpl));
450 DPRINTF("Cannot copy cond from user!");
455 list_add(&(p_cond->list), &(cond_list.list));
456 p_data += sizeof(struct event_tmpl);
460 case EC_IOCTL_ATTACH:
462 unsigned long dbi_flags;
463 struct dbi_modules_handlers *local_mh;
464 struct dbi_modules_handlers_info *local_mhi;
466 dbi_module_callback dmc_start;
468 // call "start"-callback for all modules according module priority
469 local_mh = get_dbi_modules_handlers();
470 spin_lock_irqsave(&local_mh->lock, dbi_flags);
471 for (j = 0; j <= MAX_PRIORITY; j++) {
472 list_for_each_entry_rcu(local_mhi, &local_mh->modules_handlers, dbi_list_head) {
473 if (local_mhi->dbi_module_priority_start == j) {
474 if (local_mhi->dbi_module_callback_start != NULL) {
475 printk("Started module callback (start) %s\n", local_mhi->dbi_module->name);
476 dmc_start = (dbi_module_callback )local_mhi->dbi_module_callback_start;
482 spin_unlock_irqrestore(&local_mh->lock, dbi_flags);
484 result = ec_user_attach ();
485 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
486 DPRINTF("EC_IOCTL_ATTACH calling notification chain");
487 blocking_notifier_call_chain(&swap_notifier_list, EC_IOCTL_ATTACH, (void*)NULL);
489 DPRINTF("Attach Probes");
492 case EC_IOCTL_ACTIVATE:
493 result = ec_user_activate ();
494 DPRINTF("Activate Probes");
496 case EC_IOCTL_STOP_AND_DETACH:
498 unsigned long nIgnoredBytes = 0;
499 unsigned long dbi_flags;
500 struct dbi_modules_handlers *local_mh;
501 struct dbi_modules_handlers_info *local_mhi;
502 unsigned int local_module_refcount = 0;
504 dbi_module_callback dmc_stop;
506 local_mh = get_dbi_modules_handlers();
507 if(ec_user_stop() != 0) {
511 nIgnoredBytes = copy_ec_info_to_user_space ((ec_info_t*)arg);
512 if(nIgnoredBytes > 0) {
517 sspt_procs_free_all();
521 DPRINTF("Stop and Detach Probes");
522 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
523 DPRINTF("EC_IOCTL_STOP_AND_DETACH calling notification chain");
524 blocking_notifier_call_chain(&swap_notifier_list, EC_IOCTL_STOP_AND_DETACH, (void*)&gl_nNotifyTgid);
526 // call "stop"-callback for all modules according module priority
527 spin_lock_irqsave(&local_mh->lock, dbi_flags);
528 for (j = 0; j <= MAX_PRIORITY; j++) {
529 list_for_each_entry_rcu(local_mhi, &local_mh->modules_handlers, dbi_list_head) {
530 if (local_mhi->dbi_module_priority_stop == j) {
531 if (local_mhi->dbi_module_callback_stop != NULL) {
532 printk("Started module callback (stop) %s\n", local_mhi->dbi_module->name);
533 dmc_stop = (dbi_module_callback )local_mhi->dbi_module_callback_stop;
539 spin_unlock_irqrestore(&local_mh->lock, dbi_flags);
541 spin_lock_irqsave(&local_mh->lock, dbi_flags);
542 list_for_each_entry_rcu(local_mhi, &local_mh->modules_handlers, dbi_list_head) {
543 local_module_refcount = module_refcount(local_mhi->dbi_module);
544 if (local_module_refcount == 1) {
545 module_put(local_mhi->dbi_module);
547 else if (local_module_refcount > 1) {
548 printk("local_module_refcount too much - force set refcount to zero\n");
549 while (local_module_refcount--)
550 module_put(local_mhi->dbi_module);
553 spin_unlock_irqrestore(&local_mh->lock, dbi_flags);
556 case EC_IOCTL_US_EVENT:
558 ioctl_us_event_t ioctl_args;
559 result = copy_from_user (&ioctl_args, (const void __user *) arg, sizeof (ioctl_args));
563 EPRINTF ("copy_from_user() failure");
567 if(ioctl_args.len == 0){
569 EPRINTF ("invalid event length!");
572 char *buf = kmalloc(ioctl_args.len, GFP_KERNEL);
575 EPRINTF ("failed to alloc mem for event!");
578 result = copy_from_user (buf, (const void __user *) ioctl_args.data, ioctl_args.len);
581 EPRINTF ("failed to copy event from user space!");
584 result = put_us_event(buf, ioctl_args.len);
589 // DPRINTF("User Space Event"); // Frequent call
593 case EC_IOCTL_SET_EVENT_MASK:
596 result = copy_from_user (&mask, arg_pointer, sizeof (mask));
603 result = set_event_mask (mask);
608 DPRINTF("Set Event Mask = %d", mask);
612 case EC_IOCTL_GET_EVENT_MASK:
615 result = get_event_mask(&mask);
620 result = copy_to_user (arg_pointer, &mask, sizeof (mask));
625 DPRINTF("Get Event Mask = %d", mask);
629 case EC_IOCTL_GET_PREDEF_UPROBES:
631 result = get_predef_uprobes((ioctl_predef_uprobes_info_t *)arg);
636 DPRINTF("Get Predefined User Space Probes");
640 case EC_IOCTL_GET_PREDEF_UPROBES_SIZE:
643 result = get_predef_uprobes_size(&size);
648 result = copy_to_user (arg_pointer, &size, sizeof (size));
653 DPRINTF("Get Size of Predefined User Space Probes");
656 case EC_IOCTL_GET_LAST_ERROR:
658 result = get_last_error((void*)arg);
659 DPRINTF("Get last error buffer");
663 EPRINTF ("Unknown driver command = %u", cmd);