gator: ARM DS-5.3 Streamline gator driver
[android-sdk/arm-ds5-gator.git] / gator_main.c
1 /**
2  * Copyright (C) ARM Limited 2010. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  */
10 static unsigned long gator_protocol_version = 2;
12 #include <linux/version.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/types.h>
16 #include <linux/fs.h>
17 #include <linux/sched.h>
18 #include <linux/interrupt.h>
19 #include <linux/irq.h>
20 #include <linux/smp.h>
21 #include <linux/slab.h>
22 #include <linux/mm.h>
23 #include <linux/dcookies.h>
24 #include <linux/vmalloc.h>
25 #include <asm/uaccess.h>
27 #ifndef CONFIG_GENERIC_TRACER
28 #ifndef CONFIG_TRACING
29 #warning gator requires the kernel to have CONFIG_GENERIC_TRACER or CONFIG_TRACING defined
30 #endif
31 #endif
33 #ifndef CONFIG_PROFILING
34 #warning gator requires the kernel to have CONFIG_PROFILING defined
35 #endif
37 #ifndef CONFIG_HIGH_RES_TIMERS
38 #warning gator requires the kernel to have CONFIG_HIGH_RES_TIMERS defined
39 #endif
41 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
42 #error kernels prior to 2.6.32 are not supported
43 #endif
45 #include "gator.h"
47 /******************************************************************************
48  * DEFINES
49  ******************************************************************************/
50 #define BUFFER_SIZE_DEFAULT             131072
52 #define NO_COOKIE                               0UL
53 #define INVALID_COOKIE                  ~0UL
55 #define PROTOCOL_FRAME                          ~0
56 #define PROTOCOL_START_TICK                     1
57 #define PROTOCOL_END_TICK                       3
58 #define PROTOCOL_START_BACKTRACE        5
59 #define PROTOCOL_END_BACKTRACE          7
60 #define PROTOCOL_COOKIE                         9
61 #define PROTOCOL_SCHEDULER_TRACE        11
62 #define PROTOCOL_COUNTERS                       13
63 #define PROTOCOL_ANNOTATE                       15
65 #if defined(__arm__)
66 #define PC_REG regs->ARM_pc
67 #else
68 #define PC_REG regs->ip
69 #endif
71 /******************************************************************************
72  * PER CPU
73  ******************************************************************************/
74 static unsigned long gator_buffer_size;
75 static unsigned long gator_backtrace_depth;
77 static unsigned long gator_started;
78 static unsigned long gator_buffer_opened;
79 static unsigned long gator_timer_count;
80 static unsigned long gator_dump;
81 static DEFINE_MUTEX(start_mutex);
82 static DEFINE_MUTEX(gator_buffer_mutex);
83 static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
84 /* atomic_t because wait_event checks it outside of gator_buffer_mutex */
85 static DEFINE_PER_CPU(atomic_t, gator_buffer_ready);
86 static DEFINE_PER_CPU(int, gator_tick);
87 static DEFINE_PER_CPU(int, gator_first_time);
89 /******************************************************************************
90  * Prototypes
91  ******************************************************************************/
92 static void gator_buffer_write_packed_int(int cpu, unsigned int x);
93 static void gator_buffer_write_string(int cpu, char *x);
94 static void gator_add_trace(int cpu, unsigned int address);
95 static uint64_t gator_get_time(void);
97 /******************************************************************************
98  * Application Includes
99  ******************************************************************************/
100 #include "gator_cookies.c"
101 #include "gator_trace_sched.c"
102 #include "gator_backtrace.c"
103 #include "gator_annotate.c"
104 #include "gator_events.c"
105 #include "gator_fs.c"
107 /******************************************************************************
108  * Misc
109  ******************************************************************************/
110 #if defined(__arm__)
111 u32 gator_cpuid(void)
113         u32 val;
114         asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (val));
115         return (val >> 4) & 0xfff;
117 #endif
118 /******************************************************************************
119  * Buffer management
120  ******************************************************************************/
121 static uint32_t use_buffer_size;
122 static uint32_t use_buffer_mask;
123 static DEFINE_PER_CPU(int, use_buffer_seq);
124 static DEFINE_PER_CPU(int, use_buffer_read);
125 static DEFINE_PER_CPU(int, use_buffer_write);
126 static DEFINE_PER_CPU(int, use_buffer_commit);
127 static DEFINE_PER_CPU(char *, use_buffer);
129 static void gator_buffer_write_packed_int(int cpu, unsigned int x)
131         uint32_t write = per_cpu(use_buffer_write, cpu);
132         uint32_t mask = use_buffer_mask;
133         char *buffer = per_cpu(use_buffer, cpu);
134         int write0 = (write + 0) & mask;
135         int write1 = (write + 1) & mask;
136         int write2 = (write + 2) & mask;
137         int write3 = (write + 3) & mask;
138         int write4 = (write + 4) & mask;
139         int write5 = (write + 5) & mask;
141         if ((x & 0xffffff80) == 0) {
142                 buffer[write0] = x & 0x7f;
143                 per_cpu(use_buffer_write, cpu) = write1;
144         } else if ((x & 0xffffc000) == 0) {
145                 buffer[write0] = x | 0x80;
146                 buffer[write1] = (x>>7) & 0x7f;
147                 per_cpu(use_buffer_write, cpu) = write2;
148         } else if ((x & 0xffe00000) == 0) {
149                 buffer[write0] = x | 0x80;
150                 buffer[write1] = (x>>7) | 0x80;
151                 buffer[write2] = (x>>14) & 0x7f;
152                 per_cpu(use_buffer_write, cpu) = write3;
153         } else if ((x & 0xf0000000) == 0) {
154                 buffer[write0] = x | 0x80;
155                 buffer[write1] = (x>>7) | 0x80;
156                 buffer[write2] = (x>>14) | 0x80;
157                 buffer[write3] = (x>>21) & 0x7f;
158                 per_cpu(use_buffer_write, cpu) = write4;
159         } else {
160                 buffer[write0] = x | 0x80;
161                 buffer[write1] = (x>>7) | 0x80;
162                 buffer[write2] = (x>>14) | 0x80;
163                 buffer[write3] = (x>>21) | 0x80;
164                 buffer[write4] = (x>>28) & 0x0f;
165                 per_cpu(use_buffer_write, cpu) = write5;
166         }
169 static void gator_buffer_write_bytes(int cpu, char *x, int len)
171         uint32_t write = per_cpu(use_buffer_write, cpu);
172         uint32_t mask = use_buffer_mask;
173         char *buffer = per_cpu(use_buffer, cpu);
174         int i;
176         for (i = 0; i < len; i++) {
177                 buffer[write] = x[i];
178                 write = (write + 1) & mask;
179         }
181         per_cpu(use_buffer_write, cpu) = write;
184 static void gator_buffer_write_string(int cpu, char *x)
186         int len = strlen(x);
187         gator_buffer_write_packed_int(cpu, len);
188         gator_buffer_write_bytes(cpu, x, len);
191 static void gator_buffer_header(int cpu)
193         gator_buffer_write_packed_int(cpu, PROTOCOL_FRAME);
194         gator_buffer_write_packed_int(cpu, cpu);
195         gator_buffer_write_packed_int(cpu, per_cpu(use_buffer_seq, cpu));
198 static void gator_buffer_commit(int cpu)
200         per_cpu(use_buffer_commit, cpu) = per_cpu(use_buffer_write, cpu);
202         per_cpu(use_buffer_seq, cpu)++;
203         gator_buffer_header(cpu);
205         atomic_set(&per_cpu(gator_buffer_ready, cpu), 1);
206         wake_up(&gator_buffer_wait);
209 static void gator_buffer_check(int cpu)
211         int commit = 0;
212         int available = per_cpu(use_buffer_write, cpu) - per_cpu(use_buffer_read, cpu);
213         if (available < 0) {
214                 available += use_buffer_size;
215         }
217         if (!cpu && gator_dump) {
218                 gator_dump = 0;
219                 commit = 1;
220         } else if (available >= ((use_buffer_size * 3) / 4)) {
221                 commit = 1;
222         } else if (cpu && (per_cpu(use_buffer_seq, cpu) < per_cpu(use_buffer_seq, 0))) {
223                 commit = 1;
224         }
226         if (commit) {
227                 gator_buffer_commit(cpu);
228         }
231 static void gator_add_trace(int cpu, unsigned int address)
233         off_t offset = 0;
234         unsigned long cookie = get_address_cookie(cpu, current, address & ~1, &offset);
236         if (cookie == NO_COOKIE || cookie == INVALID_COOKIE) {
237                 offset = address;
238         }
240         gator_buffer_write_packed_int(cpu, offset & ~1);
241         gator_buffer_write_packed_int(cpu, cookie);
244 static void gator_add_sample(int cpu, struct pt_regs * const regs)
246         int inKernel = regs ? !user_mode(regs) : 1;
247         unsigned long cookie = !inKernel ? get_exec_cookie(cpu, current) : NO_COOKIE;
249         gator_buffer_write_packed_int(cpu, PROTOCOL_START_BACKTRACE);
251         // TGID::PID::inKernel
252         gator_buffer_write_packed_int(cpu, cookie);
253         gator_buffer_write_packed_int(cpu, (unsigned int)current->tgid);
254         gator_buffer_write_packed_int(cpu, (unsigned int)current->pid);
255         gator_buffer_write_packed_int(cpu, inKernel);
257         // get_irq_regs() will return NULL outside of IRQ context (e.g. nested IRQ)
258         if (regs) {
259                 if (inKernel) {
260                         gator_buffer_write_packed_int(cpu, PC_REG & ~1);
261                         gator_buffer_write_packed_int(cpu, 0); // cookie
262                 } else {
263                         // Cookie+PC
264                         gator_add_trace(cpu, PC_REG);
266                         // Backtrace
267                         if (gator_backtrace_depth)
268                                 arm_backtrace_eabi(cpu, regs, gator_backtrace_depth);
269                 }
270         }
272         gator_buffer_write_packed_int(cpu, PROTOCOL_END_BACKTRACE);
275 static void gator_write_packet(int cpu, int type, int len, int *buffer)
277         int i;
278         gator_buffer_write_packed_int(cpu, type);
279         gator_buffer_write_packed_int(cpu, len);
280         for (i = 0; i < len; i++) {
281                 gator_buffer_write_packed_int(cpu, buffer[i]);
282         }
285 static void gator_write_annotate(int cpu, int len, int *buffer)
287         int pos = 0;
289         while (pos < len) {
290                 unsigned int tid = buffer[pos++];
291                 unsigned int bytes = buffer[pos++];
292                 unsigned int words = (bytes + 3) / 4;
293                 char *ptr = (char *)&buffer[pos];
294                 pos += words;
296                 gator_buffer_write_packed_int(cpu, PROTOCOL_ANNOTATE);
297                 gator_buffer_write_packed_int(cpu, tid);
298                 gator_buffer_write_packed_int(cpu, bytes);
299                 gator_buffer_write_bytes(cpu, ptr, bytes);
300         }
303 /******************************************************************************
304  * Interrupt Processing
305  ******************************************************************************/
306 static gator_interface *gi = NULL;
308 static void gator_timer_interrupt(unsigned int ticks)
310         struct pt_regs * const regs = get_irq_regs();
311         int cpu = raw_smp_processor_id();
312         int *buffer, len;
313         gator_interface *i;
315         // check full backtrace has enough space, otherwise may
316         // have breaks between samples in the same callstack
317         if (per_cpu(gator_first_time, cpu)) {
318                 per_cpu(gator_first_time, cpu) = 0;
320                 for (i = gi; i != NULL; i = i->next) {
321                         if (i->read) {
322                                 i->read(NULL);
323                         }
324                 }
325                 per_cpu(gator_tick, cpu) += ticks;
326                 return;
327         }
329         // Header
330         gator_buffer_write_packed_int(cpu, PROTOCOL_START_TICK);                        // Escape
332         // Output scheduler
333         len = gator_trace_sched_read(&buffer);
334         if (len > 0) {
335                 gator_write_packet(cpu, PROTOCOL_SCHEDULER_TRACE, len, buffer);
336         }
338         // Output annotate
339         len = gator_annotate_read(&buffer);
340         if (len > 0)
341                 gator_write_annotate(cpu, len, buffer);
343         // Output counters
344         for (i = gi; i != NULL; i = i->next) {
345                 if (i->read) {
346                         len = i->read(&buffer);
347                         if (len > 0) {
348                                 gator_write_packet(cpu, PROTOCOL_COUNTERS, len, buffer);
349                         }
350                 }
351         }
353         // Output backtrace
354         gator_add_sample(cpu, regs);
356         // Timer Tick
357         gator_write_packet(cpu, PROTOCOL_END_TICK, 1, &per_cpu(gator_tick, cpu));
358         per_cpu(gator_tick, cpu) += ticks;
360         // Check and commit
361         gator_buffer_check(cpu);
364 /******************************************************************************
365  * hrtimer
366  ******************************************************************************/
367 DEFINE_PER_CPU(struct hrtimer, percpu_hrtimer);
368 extern void gator_timer_stop(void);
369 static int hrtimer_running;
370 static ktime_t profiling_interval;
371 static atomic_t num_active_timers;
373 static enum hrtimer_restart gator_hrtimer_notify(struct hrtimer *hrtimer)
375         unsigned int ticks = (unsigned int)hrtimer_forward_now(hrtimer, profiling_interval);
376         gator_timer_interrupt(ticks);
377         return HRTIMER_RESTART;
380 int gator_timer_init(void)
382         return 0;
385 static void __gator_timer_start(void *unused)
387         int cpu = smp_processor_id();
389         struct hrtimer *hrtimer = &per_cpu(percpu_hrtimer, cpu);
390         hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
391         hrtimer->function = gator_hrtimer_notify;
392         hrtimer_start(hrtimer, profiling_interval, HRTIMER_MODE_REL_PINNED);
393         atomic_inc(&num_active_timers);
395         per_cpu(gator_first_time, cpu) = 1;
396         per_cpu(gator_tick, cpu) = 0;
399 int gator_timer_start(unsigned long setup)
401         atomic_set(&num_active_timers, 0);
403         if (!setup) {
404                 pr_err("gator: cannot start due to a system tick value of zero");
405                 return -1;
406         } else if (hrtimer_running) {
407                 pr_notice("gator: high res timer already running");
408                 return 0;
409         }
411         hrtimer_running = 1;
413         // calculate profiling interval
414         profiling_interval = ns_to_ktime(1000000000UL / setup);
416         // timer interrupt
417         on_each_cpu(__gator_timer_start, NULL, 1);
419         if (atomic_read(&num_active_timers) != num_present_cpus()) {
420                 pr_err("gator: %d timer(s) started yet %d cpu(s) detected, please bring all cpus online manually and restart\n", atomic_read(&num_active_timers), nr_cpu_ids);
421                 gator_timer_stop();
422                 return -1;
423         }
425         return 0;
428 void __gator_timer_stop(void *unused)
430         struct hrtimer *hrtimer = &per_cpu(percpu_hrtimer, smp_processor_id());
431         hrtimer_cancel(hrtimer);
432         atomic_dec(&num_active_timers);
435 void gator_timer_stop(void)
437         if (hrtimer_running) {
438                 int previously_running = atomic_read(&num_active_timers);
439                 hrtimer_running = 0;
440                 on_each_cpu(__gator_timer_stop, NULL, 1);
441                 if (atomic_read(&num_active_timers) != 0) {
442                         pr_err("gator: %d timers stopped yet %d were running, it is advised to quit and restart gatord", previously_running - atomic_read(&num_active_timers), previously_running);
443                         atomic_set(&num_active_timers, 0);
444                 }
445         }
448 static uint64_t gator_get_time(void)
450         struct timespec ts;
451         uint64_t timestamp;
453         ktime_get_ts(&ts);
454         timestamp = timespec_to_ns(&ts);
456         return timestamp;
459 /******************************************************************************
460  * Main
461  ******************************************************************************/
462 int gator_event_install(int (*event_install)(gator_interface *))
464         gator_interface *ni = (gator_interface*)kmalloc(sizeof(gator_interface), GFP_KERNEL);
465         if (ni == NULL) {
466                 return -1;
467         }
469         ni->create_files = NULL;
470         ni->init = NULL;
471         ni->start = NULL;
472         ni->stop = NULL;
473         ni->read = NULL;
474         ni->next = NULL;
476         // Initialize ni gator interface
477         if (!event_install(ni)) {
478                 if (gi == NULL) {
479                         // Set gi to point to the first gator interface
480                         gi = ni;
481                 } else {
482                         // Link the gator interfaces
483                         gator_interface *i = gi;
484                         while (i->next) {
485                                 i = i->next;
486                         }
487                         i->next = ni;
488                 }
489         } else {
490                 kfree(ni);
491         }
493         return 0;
496 static int gator_init(void)
498         gator_interface *i;
499         int key = 0;
501         if (gator_timer_init())
502                 return -1;
503         if (gator_trace_sched_init())
504                 return -1;
505         if (gator_annotate_init())
506                 return -1;
508         // set up gator interface linked list structure
509         if (gator_events_install())
510                 return -1;
512         // initialize all events
513         for (i = gi; i != NULL; i = i->next) {
514                 if (i->init) {
515                         if (i->init(&key)) {
516                                 return -1;
517                         }
518                 }
519         }
521         return 0;
524 static int gator_start(void)
526         gator_interface *i, *f;
528         // start all events
529         for (i = gi; i != NULL; i = i->next) {
530                 if (i->start) {
531                         if (i->start()) {
532                                 goto events_failure;
533                         }
534                 }
535         }
537         if (gator_annotate_start())
538                 goto annotate_failure;
539         if (gator_trace_sched_start())
540                 goto sched_failure;
541         if (gator_timer_start(gator_timer_count))
542                 goto timer_failure;
544         return 0;
546 timer_failure:
547         gator_trace_sched_stop();
548 sched_failure:
549         gator_annotate_stop();
550 annotate_failure:
551 events_failure:
552         for (f = gi; f != i; f = f->next) {
553                 f->stop();
554         }
556         return -1;
559 static void gator_stop(void)
561         gator_interface *i;
563         // stop all interrupt callback reads before tearing down other interfaces
564         gator_timer_stop();
565         gator_annotate_stop();
566         gator_trace_sched_stop();
568         // stop all events
569         for (i = gi; i != NULL; i = i->next) {
570                 if (i->stop) {
571                         i->stop();
572                 }
573         }
576 static void gator_exit(void)
578         gator_interface *i = gi;
580         while (i) {
581                 gator_interface *p = i;
582                 i = i->next;
583                 kfree(p);
584         }
587 /******************************************************************************
588  * Filesystem
589  ******************************************************************************/
590 /* fopen("buffer") */
591 static int gator_op_setup(void)
593         int err = 0;
594         int cpu;
596         mutex_lock(&start_mutex);
598         use_buffer_size = gator_buffer_size;
599         use_buffer_mask = use_buffer_size - 1;
601         // must be a power of 2
602         if (use_buffer_size & (use_buffer_size - 1)) {
603                 err = -ENOEXEC;
604                 goto setup_error;
605         }
607         for_each_possible_cpu(cpu) {
608                 per_cpu(use_buffer, cpu) = vmalloc(use_buffer_size);
609                 if (!per_cpu(use_buffer, cpu)) {
610                         err = -ENOMEM;
611                         goto setup_error;
612                 }
614                 atomic_set(&per_cpu(gator_buffer_ready, cpu), 0);
615                 per_cpu(use_buffer_seq, cpu) = 0;
616                 per_cpu(use_buffer_read, cpu) = 0;
617                 per_cpu(use_buffer_write, cpu) = 0;
618                 per_cpu(use_buffer_commit, cpu) = 0;
619                 gator_buffer_header(cpu);
620         }
622 setup_error:
623         mutex_unlock(&start_mutex);
624         return err;
627 /* Actually start profiling (echo 1>/dev/gator/enable) */
628 static int gator_op_start(void)
630         int err = 0;
632         mutex_lock(&start_mutex);
634         if (gator_started || gator_start())
635                 err = -EINVAL;
636         else
637                 gator_started = 1;
639         cookies_initialize();
641         mutex_unlock(&start_mutex);
643         return err;
646 /* echo 0>/dev/gator/enable */
647 static void gator_op_stop(void)
649         int cpu;
651         mutex_lock(&start_mutex);
653         if (gator_started) {
654                 gator_stop();
656                 mutex_lock(&gator_buffer_mutex);
658                 /* wake up the daemon to read what remains */
659                 for_each_possible_cpu(cpu) {
660                         gator_buffer_commit(cpu);
661                         atomic_set(&per_cpu(gator_buffer_ready, cpu), 1);
662                 }
663                 gator_started = 0;
664                 cookies_release();
665                 wake_up(&gator_buffer_wait);
667                 mutex_unlock(&gator_buffer_mutex);
668         }
670         mutex_unlock(&start_mutex);
673 static void gator_shutdown(void)
675         int cpu;
677         mutex_lock(&start_mutex);
679         for_each_possible_cpu(cpu) {
680                 mutex_lock(&gator_buffer_mutex);
681                 vfree(per_cpu(use_buffer, cpu));
682                 per_cpu(use_buffer, cpu) = NULL;
683                 per_cpu(use_buffer_seq, cpu) = 0;
684                 per_cpu(use_buffer_read, cpu) = 0;
685                 per_cpu(use_buffer_write, cpu) = 0;
686                 per_cpu(use_buffer_commit, cpu) = 0;
687                 mutex_unlock(&gator_buffer_mutex);
688         }
690         mutex_unlock(&start_mutex);
693 static int gator_set_backtrace(unsigned long val)
695         int err = 0;
697         mutex_lock(&start_mutex);
699         if (gator_started)
700                 err = -EBUSY;
701         else
702                 gator_backtrace_depth = val;
704         mutex_unlock(&start_mutex);
706         return err;
709 static ssize_t enable_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
711         return gatorfs_ulong_to_user(gator_started, buf, count, offset);
714 static ssize_t enable_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
716         unsigned long val;
717         int retval;
719         if (*offset)
720                 return -EINVAL;
722         retval = gatorfs_ulong_from_user(&val, buf, count);
723         if (retval)
724                 return retval;
726         if (val)
727                 retval = gator_op_start();
728         else
729                 gator_op_stop();
731         if (retval)
732                 return retval;
733         return count;
736 static const struct file_operations enable_fops = {
737         .read           = enable_read,
738         .write          = enable_write,
739 };
741 static int event_buffer_open(struct inode *inode, struct file *file)
743         int err = -EPERM;
745         if (!capable(CAP_SYS_ADMIN))
746                 return -EPERM;
748         if (test_and_set_bit_lock(0, &gator_buffer_opened))
749                 return -EBUSY;
751         /* Register as a user of dcookies
752          * to ensure they persist for the lifetime of
753          * the open event file
754          */
755         err = -EINVAL;
756         file->private_data = dcookie_register();
757         if (!file->private_data)
758                 goto out;
760         if ((err = gator_op_setup()))
761                 goto fail;
763         /* NB: the actual start happens from userspace
764          * echo 1 >/dev/gator/enable
765          */
767         return 0;
769 fail:
770         dcookie_unregister(file->private_data);
771 out:
772         __clear_bit_unlock(0, &gator_buffer_opened);
773         return err;
776 static int event_buffer_release(struct inode *inode, struct file *file)
778         int cpu;
779         gator_op_stop();
780         gator_shutdown();
781         dcookie_unregister(file->private_data);
782         for_each_possible_cpu(cpu) {
783                 atomic_set(&per_cpu(gator_buffer_ready, cpu), 0);
784         }
785         __clear_bit_unlock(0, &gator_buffer_opened);
786         return 0;
789 static int event_buffer_ready(void)
791         int cpu;
792         for_each_possible_cpu(cpu) {
793                 if (atomic_read(&per_cpu(gator_buffer_ready, cpu)))
794                         return cpu;
795         }
796         return -1;
799 static ssize_t event_buffer_read(struct file *file, char __user *buf,
800                                  size_t count, loff_t *offset)
802         int retval = -EINVAL;
803         int commit, length1, length2, read;
804         char *buffer1, *buffer2;
805         int cpu;
807         /* do not handle partial reads */
808         if (count != use_buffer_size || *offset)
809                 return -EINVAL;
811         wait_event_interruptible(gator_buffer_wait, event_buffer_ready() >= 0 || !gator_started);
812         cpu = event_buffer_ready();
814         if (signal_pending(current))
815                 return -EINTR;
817         if (cpu < 0)
818                 return 0;
820         /* should not happen */
821         if (!atomic_read(&per_cpu(gator_buffer_ready, cpu)))
822                 return -EAGAIN;
824         mutex_lock(&gator_buffer_mutex);
826         retval = -EFAULT;
828         /* May happen if the buffer is freed during pending reads. */
829         if (!per_cpu(use_buffer, cpu)) {
830                 retval = -EFAULT;
831                 goto out;
832         }
834         /* determine the size of two halves */
835         commit = per_cpu(use_buffer_commit, cpu);
836         read = per_cpu(use_buffer_read, cpu);
837         length1 = commit - read;
838         length2 = 0;
839         buffer1 = &(per_cpu(use_buffer, cpu)[read]);
840         buffer2 = &(per_cpu(use_buffer, cpu)[0]);
841         if (length1 < 0) {
842                 length1 = use_buffer_size - read;
843                 length2 = commit;
844         }
846         /* start, middle or end */
847         if (length1 > 0) {
848                 if (copy_to_user(&buf[0], buffer1, length1)) {
849                         goto out;
850                 }
851         }
853         /* possible wrap around */
854         if (length2 > 0) {
855                 if (copy_to_user(&buf[length1], buffer2, length2)) {
856                         goto out;
857                 }
858         }
860         /* update position */
861         retval = length1 + length2;
862         per_cpu(use_buffer_read, cpu) = (read + retval) & use_buffer_mask;
864         atomic_set(&per_cpu(gator_buffer_ready, cpu), 0);
866         /* kick just in case we've lost an SMP event */
867         wake_up(&gator_buffer_wait);
869 out:
870         mutex_unlock(&gator_buffer_mutex);
871         return retval;
874 const struct file_operations gator_event_buffer_fops = {
875         .open           = event_buffer_open,
876         .release        = event_buffer_release,
877         .read           = event_buffer_read,
878 };
880 static ssize_t depth_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
882         return gatorfs_ulong_to_user(gator_backtrace_depth, buf, count,
883                                         offset);
886 static ssize_t depth_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
888         unsigned long val;
889         int retval;
891         if (*offset)
892                 return -EINVAL;
894         retval = gatorfs_ulong_from_user(&val, buf, count);
895         if (retval)
896                 return retval;
898         retval = gator_set_backtrace(val);
900         if (retval)
901                 return retval;
902         return count;
905 static const struct file_operations depth_fops = {
906         .read           = depth_read,
907         .write          = depth_write
908 };
910 static const char gator_cpu_type[] = "gator";
912 static ssize_t cpu_type_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
914         return gatorfs_str_to_user(gator_cpu_type, buf, count, offset);
917 static const struct file_operations cpu_type_fops = {
918         .read           = cpu_type_read,
919 };
921 void gator_op_create_files(struct super_block *sb, struct dentry *root)
923         struct dentry *dir;
924         gator_interface *i;
926         /* reinitialize default values */
927         gator_buffer_size =     BUFFER_SIZE_DEFAULT;
929         gatorfs_create_file(sb, root, "enable", &enable_fops);
930         gatorfs_create_file(sb, root, "buffer", &gator_event_buffer_fops);
931         gatorfs_create_file(sb, root, "backtrace_depth", &depth_fops);
932         gatorfs_create_file(sb, root, "cpu_type", &cpu_type_fops);
933         gatorfs_create_ulong(sb, root, "buffer_size", &gator_buffer_size);
934         gatorfs_create_ulong(sb, root, "tick", &gator_timer_count);
935         gatorfs_create_ulong(sb, root, "dump", &gator_dump);
936         gatorfs_create_ro_ulong(sb, root, "version", &gator_protocol_version);
938         // Annotate interface
939         gator_annotate_create_files(sb, root);
941         // Linux Events
942         dir = gatorfs_mkdir(sb, root, "events");
943         for (i = gi; i != NULL; i = i->next) {
944                 if (i->create_files) {
945                         i->create_files(sb, dir);
946                 }
947         }
950 /******************************************************************************
951  * Module
952  ******************************************************************************/
953 static int gator_initialized;
955 static int __init gator_module_init(void)
957         if (gatorfs_register()) {
958                 return -1;
959         }
961         if (gator_init()) {
962                 gatorfs_unregister();
963                 return -1;
964         }
966         gator_initialized = 1;
967 #ifdef GATOR_DEBUG
968         pr_err("gator_module_init");
969 #endif
970         return 0;
973 static void __exit gator_module_exit(void)
975 #ifdef GATOR_DEBUG
976         pr_err("gator_module_exit");
977 #endif
978         gatorfs_unregister();
979         if (gator_initialized) {
980                 gator_initialized = 0;
981                 gator_exit();
982         }
985 module_init(gator_module_init);
986 module_exit(gator_module_exit);
988 MODULE_LICENSE("GPL");
989 MODULE_AUTHOR("ARM Ltd");
990 MODULE_DESCRIPTION("Gator system profiler");