]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blob - drivers/misc/tegra-profiler/comm.c
a50ddeed30b0c87127f5685c3350407a9aace2de
[sojka/nv-tegra/linux-3.10.git] / drivers / misc / tegra-profiler / comm.c
1 /*
2  * drivers/misc/tegra-profiler/comm.c
3  *
4  * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  */
16
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19 #include <linux/fs.h>
20 #include <linux/slab.h>
21 #include <linux/vmalloc.h>
22 #include <linux/miscdevice.h>
23 #include <linux/sched.h>
24 #include <linux/poll.h>
25 #include <linux/bitops.h>
26 #include <linux/err.h>
27
28 #include <asm/uaccess.h>
29
30 #include <linux/tegra_profiler.h>
31
32 #include "comm.h"
33 #include "version.h"
34
35 struct quadd_comm_ctx comm_ctx;
36
37 static inline void *rb_alloc(unsigned long size)
38 {
39         return vmalloc(size);
40 }
41
42 static inline void rb_free(void *addr)
43 {
44         vfree(addr);
45 }
46
47 static void rb_reset(struct quadd_ring_buffer *rb)
48 {
49         rb->pos_read = 0;
50         rb->pos_write = 0;
51         rb->fill_count = 0;
52         rb->max_fill_count = 0;
53 }
54
55 static int rb_init(struct quadd_ring_buffer *rb, size_t size)
56 {
57         spin_lock_init(&rb->lock);
58
59         rb->size = size;
60         rb->buf = NULL;
61
62         rb->buf = (char *) rb_alloc(rb->size);
63         if (!rb->buf) {
64                 pr_err("Ring buffer alloc error\n");
65                 return -ENOMEM;
66         }
67         pr_info("rb: data buffer size: %u\n", (unsigned int)rb->size);
68
69         rb_reset(rb);
70
71         return 0;
72 }
73
74 static void rb_deinit(struct quadd_ring_buffer *rb)
75 {
76         unsigned long flags;
77
78         spin_lock_irqsave(&rb->lock, flags);
79         if (rb->buf) {
80                 rb_reset(rb);
81
82                 rb_free(rb->buf);
83                 rb->buf = NULL;
84         }
85         spin_unlock_irqrestore(&rb->lock, flags);
86 }
87
88 static __attribute__((unused)) int rb_is_full(struct quadd_ring_buffer *rb)
89 {
90         return rb->fill_count == rb->size;
91 }
92
93 static int rb_is_empty(struct quadd_ring_buffer *rb)
94 {
95         return rb->fill_count == 0;
96 }
97
98 static int rb_is_empty_lock(struct quadd_ring_buffer *rb)
99 {
100         int res;
101         unsigned long flags;
102
103         spin_lock_irqsave(&rb->lock, flags);
104         res = rb->fill_count == 0;
105         spin_unlock_irqrestore(&rb->lock, flags);
106
107         return res;
108 }
109
110 static size_t
111 rb_get_free_space(struct quadd_ring_buffer *rb)
112 {
113         return rb->size - rb->fill_count;
114 }
115
116 static size_t
117 rb_write(struct quadd_ring_buffer *rb, char *data, size_t length)
118 {
119         size_t new_pos_write, chunk1;
120
121         if (length > rb_get_free_space(rb))
122                 return 0;
123
124         new_pos_write = (rb->pos_write + length) % rb->size;
125
126         if (new_pos_write < rb->pos_write) {
127                 chunk1 = rb->size - rb->pos_write;
128                 memcpy(rb->buf + rb->pos_write, data, chunk1);
129                 if (new_pos_write > 0)
130                         memcpy(rb->buf, data + chunk1, new_pos_write);
131         } else {
132                 memcpy(rb->buf + rb->pos_write, data, length);
133         }
134
135         rb->pos_write = new_pos_write;
136         rb->fill_count += length;
137
138         return length;
139 }
140
141 static ssize_t rb_read_undo(struct quadd_ring_buffer *rb, size_t length)
142 {
143         if (rb_get_free_space(rb) < length)
144                 return -EIO;
145
146         if (rb->pos_read > length)
147                 rb->pos_read -= length;
148         else
149                 rb->pos_read += rb->size - length;
150
151         rb->fill_count += length;
152         return length;
153 }
154
155 static size_t rb_read(struct quadd_ring_buffer *rb, char *data, size_t length)
156 {
157         unsigned int new_pos_read, chunk1;
158
159         if (length > rb->fill_count)
160                 return 0;
161
162         new_pos_read = (rb->pos_read + length) % rb->size;
163
164         if (new_pos_read < rb->pos_read) {
165                 chunk1 = rb->size - rb->pos_read;
166                 memcpy(data, rb->buf + rb->pos_read, chunk1);
167                 if (new_pos_read > 0)
168                         memcpy(data + chunk1, rb->buf, new_pos_read);
169         } else {
170                 memcpy(data, rb->buf + rb->pos_read, length);
171         }
172
173         rb->pos_read = new_pos_read;
174         rb->fill_count -= length;
175
176         return length;
177 }
178
179 static ssize_t
180 rb_read_user(struct quadd_ring_buffer *rb, char __user *data, size_t length)
181 {
182         size_t new_pos_read, chunk1;
183
184         if (length > rb->fill_count)
185                 return 0;
186
187         new_pos_read = (rb->pos_read + length) % rb->size;
188
189         if (new_pos_read < rb->pos_read) {
190                 chunk1 = rb->size - rb->pos_read;
191                 if (copy_to_user(data, rb->buf + rb->pos_read, chunk1))
192                         return -EFAULT;
193
194                 if (new_pos_read > 0) {
195                         if (copy_to_user(data + chunk1, rb->buf,
196                                          new_pos_read))
197                                 return -EFAULT;
198                 }
199         } else {
200                 if (copy_to_user(data, rb->buf + rb->pos_read, length))
201                         return -EFAULT;
202         }
203
204         rb->pos_read = new_pos_read;
205         rb->fill_count -= length;
206
207         return length;
208 }
209
210 static void
211 write_sample(struct quadd_record_data *sample,
212              struct quadd_iovec *vec, int vec_count)
213 {
214         int i;
215         unsigned long flags;
216         struct quadd_ring_buffer *rb = &comm_ctx.rb;
217         size_t length_sample;
218
219         length_sample = sizeof(struct quadd_record_data);
220         for (i = 0; i < vec_count; i++)
221                 length_sample += vec[i].len;
222
223         spin_lock_irqsave(&rb->lock, flags);
224
225         if (length_sample > rb_get_free_space(rb)) {
226                 pr_err_once("Error: Buffer has been overflowed\n");
227                 spin_unlock_irqrestore(&rb->lock, flags);
228                 return;
229         }
230
231         if (!rb_write(rb, (char *)sample, sizeof(struct quadd_record_data))) {
232                 spin_unlock_irqrestore(&rb->lock, flags);
233                 return;
234         }
235
236         for (i = 0; i < vec_count; i++) {
237                 if (!rb_write(rb, vec[i].base, vec[i].len)) {
238                         spin_unlock_irqrestore(&rb->lock, flags);
239                         pr_err_once("%s: error: ring buffer\n", __func__);
240                         return;
241                 }
242         }
243
244         if (rb->fill_count > rb->max_fill_count)
245                 rb->max_fill_count = rb->fill_count;
246
247         spin_unlock_irqrestore(&rb->lock, flags);
248
249         wake_up_interruptible(&comm_ctx.read_wait);
250 }
251
252 static ssize_t read_sample(char __user *buffer, size_t max_length)
253 {
254         u32 sed;
255         unsigned int type;
256         int retval = -EIO, ip_size;
257         int was_read = 0, write_offset = 0;
258         unsigned long flags;
259         struct quadd_ring_buffer *rb = &comm_ctx.rb;
260         struct quadd_record_data record;
261         size_t length_extra = 0, nr_events;
262         struct quadd_sample_data *sample;
263
264         spin_lock_irqsave(&rb->lock, flags);
265
266         if (rb_is_empty(rb)) {
267                 retval = 0;
268                 goto out;
269         }
270
271         if (rb->fill_count < sizeof(record))
272                 goto out;
273
274         if (!rb_read(rb, (char *)&record, sizeof(record)))
275                 goto out;
276
277         was_read += sizeof(record);
278
279         type = record.record_type;
280
281         switch (type) {
282         case QUADD_RECORD_TYPE_SAMPLE:
283                 sample = &record.sample;
284
285                 if (rb->fill_count < sizeof(sed))
286                         goto out;
287
288                 if (!rb_read(rb, (char *)&sed, sizeof(sed)))
289                         goto out;
290
291                 was_read += sizeof(sed);
292
293                 ip_size = (sed & QUADD_SED_IP64) ?
294                         sizeof(u64) : sizeof(u32);
295
296                 length_extra = sample->callchain_nr * ip_size;
297
298                 nr_events = __sw_hweight32(sample->events_flags);
299                 length_extra += nr_events * sizeof(u32);
300
301                 length_extra += sample->state ? sizeof(u32) : 0;
302                 break;
303
304         case QUADD_RECORD_TYPE_MMAP:
305                 length_extra = sizeof(u64) * 2;
306
307                 if (record.mmap.filename_length > 0) {
308                         length_extra += record.mmap.filename_length;
309                 } else {
310                         pr_err("Error: filename is empty\n");
311                         goto out;
312                 }
313                 break;
314
315         case QUADD_RECORD_TYPE_HEADER:
316                 length_extra = record.hdr.nr_events * sizeof(u32);
317                 break;
318
319         case QUADD_RECORD_TYPE_DEBUG:
320                 length_extra = record.debug.extra_length;
321                 break;
322
323         case QUADD_RECORD_TYPE_MA:
324                 length_extra = 0;
325                 break;
326
327         case QUADD_RECORD_TYPE_POWER_RATE:
328                 length_extra = record.power_rate.nr_cpus * sizeof(u32);
329                 break;
330
331         case QUADD_RECORD_TYPE_ADDITIONAL_SAMPLE:
332                 length_extra = record.additional_sample.extra_length;
333                 break;
334
335         default:
336                 goto out;
337         }
338
339         if (was_read + length_extra > max_length) {
340                 retval = rb_read_undo(rb, was_read);
341                 if (retval < 0)
342                         goto out;
343
344                 retval = 0;
345                 goto out;
346         }
347
348         if (length_extra > rb->fill_count)
349                 goto out;
350
351         if (copy_to_user(buffer, &record, sizeof(record)))
352                 goto out_fault_error;
353
354         write_offset += sizeof(record);
355
356         if (type == QUADD_RECORD_TYPE_SAMPLE) {
357                 if (copy_to_user(buffer + write_offset, &sed, sizeof(sed)))
358                         goto out_fault_error;
359
360                 write_offset += sizeof(sed);
361         }
362
363         if (length_extra > 0) {
364                 retval = rb_read_user(rb, buffer + write_offset,
365                                       length_extra);
366                 if (retval <= 0)
367                         goto out;
368
369                 write_offset += length_extra;
370         }
371
372         spin_unlock_irqrestore(&rb->lock, flags);
373         return write_offset;
374
375 out_fault_error:
376         retval = -EFAULT;
377
378 out:
379         spin_unlock_irqrestore(&rb->lock, flags);
380         return retval;
381 }
382
383 static void put_sample(struct quadd_record_data *data,
384                        struct quadd_iovec *vec, int vec_count)
385 {
386         if (!atomic_read(&comm_ctx.active))
387                 return;
388
389         write_sample(data, vec, vec_count);
390 }
391
392 static void comm_reset(void)
393 {
394         unsigned long flags;
395
396         pr_debug("Comm reset\n");
397         spin_lock_irqsave(&comm_ctx.rb.lock, flags);
398         rb_reset(&comm_ctx.rb);
399         spin_unlock_irqrestore(&comm_ctx.rb.lock, flags);
400 }
401
402 static int is_active(void)
403 {
404         return atomic_read(&comm_ctx.active) != 0;
405 }
406
407 static struct quadd_comm_data_interface comm_data = {
408         .put_sample = put_sample,
409         .reset = comm_reset,
410         .is_active = is_active,
411 };
412
413 static int check_access_permission(void)
414 {
415         struct task_struct *task;
416
417         if (capable(CAP_SYS_ADMIN))
418                 return 0;
419
420         if (!comm_ctx.params_ok || comm_ctx.process_pid == 0)
421                 return -EACCES;
422
423         rcu_read_lock();
424         task = pid_task(find_vpid(comm_ctx.process_pid), PIDTYPE_PID);
425         rcu_read_unlock();
426         if (!task)
427                 return -EACCES;
428
429         if (current_fsuid() != task_uid(task) &&
430             task_uid(task) != comm_ctx.debug_app_uid) {
431                 pr_err("Permission denied, owner/task uids: %u/%u\n",
432                            current_fsuid(), task_uid(task));
433                 return -EACCES;
434         }
435         return 0;
436 }
437
438 static int device_open(struct inode *inode, struct file *file)
439 {
440         mutex_lock(&comm_ctx.io_mutex);
441         comm_ctx.nr_users++;
442         mutex_unlock(&comm_ctx.io_mutex);
443         return 0;
444 }
445
446 static int device_release(struct inode *inode, struct file *file)
447 {
448         mutex_lock(&comm_ctx.io_mutex);
449         comm_ctx.nr_users--;
450
451         if (comm_ctx.nr_users == 0) {
452                 if (atomic_cmpxchg(&comm_ctx.active, 1, 0)) {
453                         comm_ctx.control->stop();
454                         pr_info("Stop profiling: daemon is closed\n");
455                 }
456         }
457         mutex_unlock(&comm_ctx.io_mutex);
458
459         return 0;
460 }
461
462 static unsigned int
463 device_poll(struct file *file, poll_table *wait)
464 {
465         unsigned int mask = 0;
466         struct quadd_ring_buffer *rb = &comm_ctx.rb;
467
468         poll_wait(file, &comm_ctx.read_wait, wait);
469
470         if (!rb_is_empty_lock(rb))
471                 mask |= POLLIN | POLLRDNORM;
472
473         if (!atomic_read(&comm_ctx.active))
474                 mask |= POLLHUP;
475
476         return mask;
477 }
478
479 static ssize_t
480 device_read(struct file *filp,
481             char __user *buffer,
482             size_t length,
483             loff_t *offset)
484 {
485         int err;
486         ssize_t res;
487         size_t samples_counter = 0;
488         size_t was_read = 0, min_size;
489
490         err = check_access_permission();
491         if (err)
492                 return err;
493
494         mutex_lock(&comm_ctx.io_mutex);
495
496         if (!atomic_read(&comm_ctx.active)) {
497                 mutex_unlock(&comm_ctx.io_mutex);
498                 return -EPIPE;
499         }
500
501         min_size = sizeof(struct quadd_record_data) + sizeof(u32);
502
503         while (was_read + min_size < length) {
504                 res = read_sample(buffer + was_read, length - was_read);
505                 if (res < 0) {
506                         mutex_unlock(&comm_ctx.io_mutex);
507                         pr_err("Error: data is corrupted\n");
508                         return res;
509                 }
510
511                 if (res == 0)
512                         break;
513
514                 was_read += res;
515                 samples_counter++;
516
517                 if (!atomic_read(&comm_ctx.active))
518                         break;
519         }
520
521         mutex_unlock(&comm_ctx.io_mutex);
522         return was_read;
523 }
524
525 static long
526 device_ioctl(struct file *file,
527              unsigned int ioctl_num,
528              unsigned long ioctl_param)
529 {
530         int err = 0;
531         struct quadd_parameters *user_params;
532         struct quadd_comm_cap cap;
533         struct quadd_module_state state;
534         struct quadd_module_version versions;
535         struct quadd_extables extabs;
536         unsigned long flags;
537         struct quadd_ring_buffer *rb = &comm_ctx.rb;
538
539         if (ioctl_num != IOCTL_SETUP &&
540             ioctl_num != IOCTL_GET_CAP &&
541             ioctl_num != IOCTL_GET_STATE &&
542             ioctl_num != IOCTL_GET_VERSION) {
543                 err = check_access_permission();
544                 if (err)
545                         return err;
546         }
547
548         mutex_lock(&comm_ctx.io_mutex);
549
550         switch (ioctl_num) {
551         case IOCTL_SETUP:
552                 if (atomic_read(&comm_ctx.active)) {
553                         pr_err("error: tegra profiler is active\n");
554                         err = -EBUSY;
555                         goto error_out;
556                 }
557
558                 user_params = vmalloc(sizeof(*user_params));
559                 if (!user_params) {
560                         err = -ENOMEM;
561                         goto error_out;
562                 }
563
564                 if (copy_from_user(user_params, (void __user *)ioctl_param,
565                                    sizeof(struct quadd_parameters))) {
566                         pr_err("setup failed\n");
567                         vfree(user_params);
568                         err = -EFAULT;
569                         goto error_out;
570                 }
571
572                 err = comm_ctx.control->set_parameters(user_params,
573                                                        &comm_ctx.debug_app_uid);
574                 if (err) {
575                         pr_err("error: setup failed\n");
576                         vfree(user_params);
577                         goto error_out;
578                 }
579                 comm_ctx.params_ok = 1;
580                 comm_ctx.process_pid = user_params->pids[0];
581
582                 if (user_params->reserved[QUADD_PARAM_IDX_SIZE_OF_RB] == 0) {
583                         pr_err("error: too old version of daemon\n");
584                         vfree(user_params);
585                         err = -EINVAL;
586                         goto error_out;
587                 }
588                 comm_ctx.rb_size = user_params->reserved[0];
589
590                 pr_info("setup success: freq/mafreq: %u/%u, backtrace: %d, pid: %d\n",
591                         user_params->freq,
592                         user_params->ma_freq,
593                         user_params->backtrace,
594                         user_params->pids[0]);
595
596                 vfree(user_params);
597                 break;
598
599         case IOCTL_GET_CAP:
600                 comm_ctx.control->get_capabilities(&cap);
601                 if (copy_to_user((void __user *)ioctl_param, &cap,
602                                  sizeof(struct quadd_comm_cap))) {
603                         pr_err("error: get_capabilities failed\n");
604                         err = -EFAULT;
605                         goto error_out;
606                 }
607                 break;
608
609         case IOCTL_GET_VERSION:
610                 strcpy((char *)versions.branch, QUADD_MODULE_BRANCH);
611                 strcpy((char *)versions.version, QUADD_MODULE_VERSION);
612
613                 versions.samples_version = QUADD_SAMPLES_VERSION;
614                 versions.io_version = QUADD_IO_VERSION;
615
616                 if (copy_to_user((void __user *)ioctl_param, &versions,
617                                  sizeof(struct quadd_module_version))) {
618                         pr_err("error: get version failed\n");
619                         err = -EFAULT;
620                         goto error_out;
621                 }
622                 break;
623
624         case IOCTL_GET_STATE:
625                 comm_ctx.control->get_state(&state);
626
627                 state.buffer_size = comm_ctx.rb_size;
628
629                 spin_lock_irqsave(&rb->lock, flags);
630                 state.buffer_fill_size =
631                         comm_ctx.rb_size - rb_get_free_space(rb);
632                 state.reserved[QUADD_MOD_STATE_IDX_RB_MAX_FILL_COUNT] =
633                         rb->max_fill_count;
634                 spin_unlock_irqrestore(&rb->lock, flags);
635
636                 if (copy_to_user((void __user *)ioctl_param, &state,
637                                  sizeof(struct quadd_module_state))) {
638                         pr_err("error: get_state failed\n");
639                         err = -EFAULT;
640                         goto error_out;
641                 }
642                 break;
643
644         case IOCTL_START:
645                 if (!atomic_cmpxchg(&comm_ctx.active, 0, 1)) {
646                         if (!comm_ctx.params_ok) {
647                                 pr_err("error: params failed\n");
648                                 atomic_set(&comm_ctx.active, 0);
649                                 err = -EFAULT;
650                                 goto error_out;
651                         }
652
653                         err = rb_init(rb, comm_ctx.rb_size);
654                         if (err) {
655                                 pr_err("error: rb_init failed\n");
656                                 atomic_set(&comm_ctx.active, 0);
657                                 goto error_out;
658                         }
659
660                         err = comm_ctx.control->start();
661                         if (err) {
662                                 pr_err("error: start failed\n");
663                                 atomic_set(&comm_ctx.active, 0);
664                                 goto error_out;
665                         }
666                         pr_info("Start profiling success\n");
667                 }
668                 break;
669
670         case IOCTL_STOP:
671                 if (atomic_cmpxchg(&comm_ctx.active, 1, 0)) {
672                         comm_ctx.control->stop();
673                         wake_up_interruptible(&comm_ctx.read_wait);
674                         rb_deinit(&comm_ctx.rb);
675                         pr_info("Stop profiling success\n");
676                 }
677                 break;
678
679         case IOCTL_SET_EXTAB:
680                 if (copy_from_user(&extabs, (void __user *)ioctl_param,
681                                    sizeof(extabs))) {
682                         pr_err("error: set_extab failed\n");
683                         err = -EFAULT;
684                         goto error_out;
685                 }
686
687                 err = comm_ctx.control->set_extab(&extabs);
688                 if (err) {
689                         pr_err("error: set_extab\n");
690                         goto error_out;
691                 }
692                 break;
693
694         default:
695                 pr_err("error: ioctl %u is unsupported in this version of module\n",
696                        ioctl_num);
697                 err = -EFAULT;
698         }
699
700 error_out:
701         mutex_unlock(&comm_ctx.io_mutex);
702         return err;
703 }
704
705 static void unregister(void)
706 {
707         misc_deregister(comm_ctx.misc_dev);
708         kfree(comm_ctx.misc_dev);
709 }
710
711 static void free_ctx(void)
712 {
713         rb_deinit(&comm_ctx.rb);
714 }
715
716 static const struct file_operations qm_fops = {
717         .read           = device_read,
718         .poll           = device_poll,
719         .open           = device_open,
720         .release        = device_release,
721         .unlocked_ioctl = device_ioctl,
722         .compat_ioctl   = device_ioctl,
723 };
724
725 static int comm_init(void)
726 {
727         int res;
728         struct miscdevice *misc_dev;
729
730         misc_dev = kzalloc(sizeof(*misc_dev), GFP_KERNEL);
731         if (!misc_dev) {
732                 pr_err("Error: alloc error\n");
733                 return -ENOMEM;
734         }
735
736         misc_dev->minor = MISC_DYNAMIC_MINOR;
737         misc_dev->name = QUADD_DEVICE_NAME;
738         misc_dev->fops = &qm_fops;
739
740         res = misc_register(misc_dev);
741         if (res < 0) {
742                 pr_err("Error: misc_register: %d\n", res);
743                 return res;
744         }
745         comm_ctx.misc_dev = misc_dev;
746
747         mutex_init(&comm_ctx.io_mutex);
748         atomic_set(&comm_ctx.active, 0);
749
750         comm_ctx.params_ok = 0;
751         comm_ctx.process_pid = 0;
752         comm_ctx.nr_users = 0;
753
754         init_waitqueue_head(&comm_ctx.read_wait);
755
756         return 0;
757 }
758
759 struct quadd_comm_data_interface *
760 quadd_comm_events_init(struct quadd_comm_control_interface *control)
761 {
762         int err;
763
764         err = comm_init();
765         if (err < 0)
766                 return ERR_PTR(err);
767
768         comm_ctx.control = control;
769         return &comm_data;
770 }
771
772 void quadd_comm_events_exit(void)
773 {
774         mutex_lock(&comm_ctx.io_mutex);
775         unregister();
776         free_ctx();
777         mutex_unlock(&comm_ctx.io_mutex);
778 }