diff options
Diffstat (limited to 'driver')
37 files changed, 1402 insertions, 1847 deletions
diff --git a/driver/Makefile b/driver/Makefile index a2cce89..28d2070 100644 --- a/driver/Makefile +++ b/driver/Makefile @@ -14,7 +14,6 @@ gator-y := gator_main.o \ gator_events_net.o \ gator_events_perf_pmu.o \ gator_events_sched.o \ - gator_events_threads.o \ # Convert the old GATOR_WITH_MALI_SUPPORT to the new kernel flags ifneq ($(GATOR_WITH_MALI_SUPPORT),) @@ -59,11 +58,10 @@ EXTRA_CFLAGS += -DOLD_BLOCK_RQ_COMPLETE=$(OLD_BLOCK_RQ_COMPLETE) gator-$(CONFIG_ARM) += gator_events_armv6.o \ gator_events_armv7.o \ - gator_events_ccn-504.o \ gator_events_l2c-310.o \ gator_events_scorpion.o -gator-$(CONFIG_ARM64) += gator_events_ccn-504.o +gator-$(CONFIG_ARM64) += else diff --git a/driver/gator.h b/driver/gator.h index df76afa..5cc73a3 100644 --- a/driver/gator.h +++ b/driver/gator.h @@ -14,13 +14,13 @@ #include <linux/mm.h> #include <linux/list.h> -#define GATOR_PERF_SUPPORT LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) -#define GATOR_PERF_PMU_SUPPORT GATOR_PERF_SUPPORT && defined(CONFIG_PERF_EVENTS) && (!(defined(__arm__) || defined(__aarch64__)) || defined(CONFIG_HW_PERF_EVENTS)) +#define GATOR_PERF_SUPPORT (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) +#define GATOR_PERF_PMU_SUPPORT (GATOR_PERF_SUPPORT && defined(CONFIG_PERF_EVENTS) && (!(defined(__arm__) || defined(__aarch64__)) || defined(CONFIG_HW_PERF_EVENTS))) #define GATOR_NO_PERF_SUPPORT (!(GATOR_PERF_SUPPORT)) -#define GATOR_CPU_FREQ_SUPPORT (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) && defined(CONFIG_CPU_FREQ) +#define GATOR_CPU_FREQ_SUPPORT ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) && defined(CONFIG_CPU_FREQ)) #define GATOR_IKS_SUPPORT defined(CONFIG_BL_SWITCHER) -// cpu ids +/* cpu ids */ #define ARM1136 0xb36 #define ARM1156 0xb56 #define ARM1176 0xb76 @@ -29,7 +29,6 @@ #define CORTEX_A7 0xc07 #define CORTEX_A8 0xc08 #define CORTEX_A9 0xc09 -#define CORTEX_A12 0xc0d #define CORTEX_A15 0xc0f #define CORTEX_A17 0xc0e #define SCORPION 0x00f @@ -42,7 +41,7 @@ #define AARCH64 0xd0f #define OTHER 0xfff -// gpu enums +/* gpu enums */ #define MALI_4xx 1 #define MALI_MIDGARD 2 @@ -50,12 +49,12 @@ struct gator_cpu { const int cpuid; - // Human readable name + /* Human readable name */ const char core_name[MAXSIZE_CORE_NAME]; - // gatorfs event and Perf PMU name - const char * const pmnc_name; - // compatible from Documentation/devicetree/bindings/arm/cpus.txt - const char * const dt_name; + /* gatorfs event and Perf PMU name */ + const char *const pmnc_name; + /* compatible from Documentation/devicetree/bindings/arm/cpus.txt */ + const char *const dt_name; const int pmnc_counters; }; @@ -107,15 +106,19 @@ int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root, * Events ******************************************************************************/ struct gator_interface { - void (*shutdown)(void); // Complementary function to init + /* Complementary function to init */ + void (*shutdown)(void); int (*create_files)(struct super_block *sb, struct dentry *root); int (*start)(void); - void (*stop)(void); // Complementary function to start + /* Complementary function to start */ + void (*stop)(void); int (*online)(int **buffer, bool migrate); int (*offline)(int **buffer, bool migrate); - void (*online_dispatch)(int cpu, bool migrate); // called in process context but may not be running on core 'cpu' - void (*offline_dispatch)(int cpu, bool migrate); // called in process context but may not be running on core 'cpu' - int (*read)(int **buffer); + /* called in process context but may not be running on core 'cpu' */ + void (*online_dispatch)(int cpu, bool migrate); + /* called in process context but may not be running on core 'cpu' */ + void (*offline_dispatch)(int cpu, bool migrate); + int (*read)(int **buffer, bool sched_switch); int (*read64)(long long **buffer); int (*read_proc)(long long **buffer, struct task_struct *); struct list_head list; @@ -146,4 +149,4 @@ int pcpu_to_lcpu(const int pcpu); #define get_logical_cpu() smp_processor_id() #define on_primary_core() (get_logical_cpu() == 0) -#endif // GATOR_H_ +#endif /* GATOR_H_ */ diff --git a/driver/gator_annotate.c b/driver/gator_annotate.c index 7e2c6e5..ff9a3ce 100644 --- a/driver/gator_annotate.c +++ b/driver/gator_annotate.c @@ -11,12 +11,12 @@ #include <linux/fs.h> #include <linux/mm.h> #include <linux/sched.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/current.h> #include <linux/spinlock.h> static DEFINE_SPINLOCK(annotate_lock); -static bool collect_annotations = false; +static bool collect_annotations; static int annotate_copy(struct file *file, char const __user *buf, size_t count) { @@ -24,10 +24,10 @@ static int annotate_copy(struct file *file, char const __user *buf, size_t count int write = per_cpu(gator_buffer_write, cpu)[ANNOTATE_BUF]; if (file == NULL) { - // copy from kernel + /* copy from kernel */ memcpy(&per_cpu(gator_buffer, cpu)[ANNOTATE_BUF][write], buf, count); } else { - // copy from user space + /* copy from user space */ if (copy_from_user(&per_cpu(gator_buffer, cpu)[ANNOTATE_BUF][write], buf, count) != 0) return -1; } @@ -41,70 +41,70 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t int pid, cpu, header_size, available, contiguous, length1, length2, size, count = count_orig & 0x7fffffff; bool interrupt_context; - if (*offset) { + if (*offset) return -EINVAL; - } interrupt_context = in_interrupt(); - // Annotations are not supported in interrupt context, but may work if you comment out the the next four lines of code. - // By doing so, annotations in interrupt context can result in deadlocks and lost data. + /* Annotations are not supported in interrupt context, but may work + * if you comment out the the next four lines of code. By doing so, + * annotations in interrupt context can result in deadlocks and lost + * data. + */ if (interrupt_context) { - printk(KERN_WARNING "gator: Annotations are not supported in interrupt context. Edit gator_annotate.c in the gator driver to enable annotations in interrupt context.\n"); + pr_warning("gator: Annotations are not supported in interrupt context. Edit gator_annotate.c in the gator driver to enable annotations in interrupt context.\n"); return -EINVAL; } retry: - // synchronize between cores and with collect_annotations + /* synchronize between cores and with collect_annotations */ spin_lock(&annotate_lock); if (!collect_annotations) { - // Not collecting annotations, tell the caller everything was written + /* Not collecting annotations, tell the caller everything was written */ size = count_orig; goto annotate_write_out; } - // Annotation only uses a single per-cpu buffer as the data must be in order to the engine + /* Annotation only uses a single per-cpu buffer as the data must be in order to the engine */ cpu = 0; - if (current == NULL) { + if (current == NULL) pid = 0; - } else { + else pid = current->pid; - } - // determine total size of the payload + /* determine total size of the payload */ header_size = MAXSIZE_PACK32 * 3 + MAXSIZE_PACK64; available = buffer_bytes_available(cpu, ANNOTATE_BUF) - header_size; size = count < available ? count : available; if (size <= 0) { - // Buffer is full, wait until space is available + /* Buffer is full, wait until space is available */ spin_unlock(&annotate_lock); - // Drop the annotation as blocking is not allowed in interrupt context - if (interrupt_context) { + /* Drop the annotation as blocking is not allowed in interrupt context */ + if (interrupt_context) return -EINVAL; - } wait_event_interruptible(gator_annotate_wait, buffer_bytes_available(cpu, ANNOTATE_BUF) > header_size || !collect_annotations); - // Check to see if a signal is pending - if (signal_pending(current)) { + /* Check to see if a signal is pending */ + if (signal_pending(current)) return -EINTR; - } goto retry; } - // synchronize shared variables annotateBuf and annotatePos + /* synchronize shared variables annotateBuf and annotatePos */ if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF]) { u64 time = gator_get_time(); + gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, get_physical_cpu()); gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid); gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, time); gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, size); - // determine the sizes to capture, length1 + length2 will equal size + /* determine the sizes to capture, length1 + length2 will equal size */ contiguous = contiguous_space_available(cpu, ANNOTATE_BUF); if (size < contiguous) { length1 = size; @@ -124,14 +124,14 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t goto annotate_write_out; } - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, ANNOTATE_BUF, time); } annotate_write_out: spin_unlock(&annotate_lock); - // return the number of bytes written + /* return the number of bytes written */ return size; } @@ -141,18 +141,21 @@ static int annotate_release(struct inode *inode, struct file *file) { int cpu = 0; - // synchronize between cores + /* synchronize between cores */ spin_lock(&annotate_lock); if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF] && buffer_check_space(cpu, ANNOTATE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) { uint32_t pid = current->pid; + gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, get_physical_cpu()); gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid); - gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); // time - gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); // size + /* time */ + gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); + /* size */ + gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); } - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, ANNOTATE_BUF, gator_get_time()); spin_unlock(&annotate_lock); @@ -178,7 +181,7 @@ static int gator_annotate_start(void) static void gator_annotate_stop(void) { - // the spinlock here will ensure that when this function exits, we are not in the middle of an annotation + /* the spinlock here will ensure that when this function exits, we are not in the middle of an annotation */ spin_lock(&annotate_lock); collect_annotations = false; wake_up(&gator_annotate_wait); diff --git a/driver/gator_annotate_kernel.c b/driver/gator_annotate_kernel.c index 0108068..69471f9 100644 --- a/driver/gator_annotate_kernel.c +++ b/driver/gator_annotate_kernel.c @@ -19,10 +19,11 @@ static void kannotate_write(const char *ptr, unsigned int size) int retval; int pos = 0; loff_t offset = 0; + while (pos < size) { retval = annotate_write(NULL, &ptr[pos], size - pos, &offset); if (retval < 0) { - printk(KERN_WARNING "gator: kannotate_write failed with return value %d\n", retval); + pr_warning("gator: kannotate_write failed with return value %d\n", retval); return; } pos += retval; @@ -47,6 +48,7 @@ void gator_annotate_channel(int channel, const char *str) { const u16 str_size = strlen(str) & 0xffff; char header[8]; + header[0] = ESCAPE_CODE; header[1] = STRING_ANNOTATION; marshal_u32(header + 2, channel); @@ -54,20 +56,19 @@ void gator_annotate_channel(int channel, const char *str) kannotate_write(header, sizeof(header)); kannotate_write(str, str_size); } - EXPORT_SYMBOL(gator_annotate_channel); void gator_annotate(const char *str) { gator_annotate_channel(0, str); } - EXPORT_SYMBOL(gator_annotate); void gator_annotate_channel_color(int channel, int color, const char *str) { const u16 str_size = (strlen(str) + 4) & 0xffff; char header[12]; + header[0] = ESCAPE_CODE; header[1] = STRING_ANNOTATION; marshal_u32(header + 2, channel); @@ -76,39 +77,37 @@ void gator_annotate_channel_color(int channel, int color, const char *str) kannotate_write(header, sizeof(header)); kannotate_write(str, str_size - 4); } - EXPORT_SYMBOL(gator_annotate_channel_color); void gator_annotate_color(int color, const char *str) { gator_annotate_channel_color(0, color, str); } - EXPORT_SYMBOL(gator_annotate_color); void gator_annotate_channel_end(int channel) { char header[8]; + header[0] = ESCAPE_CODE; header[1] = STRING_ANNOTATION; marshal_u32(header + 2, channel); marshal_u16(header + 6, 0); kannotate_write(header, sizeof(header)); } - EXPORT_SYMBOL(gator_annotate_channel_end); void gator_annotate_end(void) { gator_annotate_channel_end(0); } - EXPORT_SYMBOL(gator_annotate_end); -void gator_annotate_name_channel(int channel, int group, const char* str) +void gator_annotate_name_channel(int channel, int group, const char *str) { const u16 str_size = strlen(str) & 0xffff; char header[12]; + header[0] = ESCAPE_CODE; header[1] = NAME_CHANNEL_ANNOTATION; marshal_u32(header + 2, channel); @@ -117,13 +116,13 @@ void gator_annotate_name_channel(int channel, int group, const char* str) kannotate_write(header, sizeof(header)); kannotate_write(str, str_size); } - EXPORT_SYMBOL(gator_annotate_name_channel); -void gator_annotate_name_group(int group, const char* str) +void gator_annotate_name_group(int group, const char *str) { const u16 str_size = strlen(str) & 0xffff; char header[8]; + header[0] = ESCAPE_CODE; header[1] = NAME_GROUP_ANNOTATION; marshal_u32(header + 2, group); @@ -131,7 +130,6 @@ void gator_annotate_name_group(int group, const char* str) kannotate_write(header, sizeof(header)); kannotate_write(str, str_size); } - EXPORT_SYMBOL(gator_annotate_name_group); void gator_annotate_visual(const char *data, unsigned int length, const char *str) @@ -139,6 +137,7 @@ void gator_annotate_visual(const char *data, unsigned int length, const char *st const u16 str_size = strlen(str) & 0xffff; char header[4]; char header_length[4]; + header[0] = ESCAPE_CODE; header[1] = VISUAL_ANNOTATION; marshal_u16(header + 2, str_size); @@ -148,49 +147,49 @@ void gator_annotate_visual(const char *data, unsigned int length, const char *st kannotate_write(header_length, sizeof(header_length)); kannotate_write(data, length); } - EXPORT_SYMBOL(gator_annotate_visual); void gator_annotate_marker(void) { char header[4]; + header[0] = ESCAPE_CODE; header[1] = MARKER_ANNOTATION; marshal_u16(header + 2, 0); kannotate_write(header, sizeof(header)); } - EXPORT_SYMBOL(gator_annotate_marker); void gator_annotate_marker_str(const char *str) { const u16 str_size = strlen(str) & 0xffff; char header[4]; + header[0] = ESCAPE_CODE; header[1] = MARKER_ANNOTATION; marshal_u16(header + 2, str_size); kannotate_write(header, sizeof(header)); kannotate_write(str, str_size); } - EXPORT_SYMBOL(gator_annotate_marker_str); void gator_annotate_marker_color(int color) { char header[8]; + header[0] = ESCAPE_CODE; header[1] = MARKER_ANNOTATION; marshal_u16(header + 2, 4); marshal_u32(header + 4, color); kannotate_write(header, sizeof(header)); } - EXPORT_SYMBOL(gator_annotate_marker_color); void gator_annotate_marker_color_str(int color, const char *str) { const u16 str_size = (strlen(str) + 4) & 0xffff; char header[8]; + header[0] = ESCAPE_CODE; header[1] = MARKER_ANNOTATION; marshal_u16(header + 2, str_size); @@ -198,5 +197,4 @@ void gator_annotate_marker_color_str(int color, const char *str) kannotate_write(header, sizeof(header)); kannotate_write(str, str_size - 4); } - EXPORT_SYMBOL(gator_annotate_marker_color_str); diff --git a/driver/gator_backtrace.c b/driver/gator_backtrace.c index e03c165..76c941d 100644 --- a/driver/gator_backtrace.c +++ b/driver/gator_backtrace.c @@ -14,17 +14,17 @@ struct stack_frame_eabi { union { struct { unsigned long fp; - // May be the fp in the case of a leaf function or clang + /* May be the fp in the case of a leaf function or clang */ unsigned long lr; - // If lr is really the fp, lr2 is the corresponding lr + /* If lr is really the fp, lr2 is the corresponding lr */ unsigned long lr2; }; - // Used to read 32 bit fp/lr from a 64 bit kernel + /* Used to read 32 bit fp/lr from a 64 bit kernel */ struct { u32 fp_32; - // same as lr above + /* same as lr above */ u32 lr_32; - // same as lr2 above + /* same as lr2 above */ u32 lr2_32; }; }; @@ -35,9 +35,8 @@ static void gator_add_trace(int cpu, unsigned long address) off_t offset = 0; unsigned long cookie = get_address_cookie(cpu, current, address & ~1, &offset); - if (cookie == NO_COOKIE || cookie == UNRESOLVED_COOKIE) { + if (cookie == NO_COOKIE || cookie == UNRESOLVED_COOKIE) offset = address; - } marshal_backtrace(offset & ~1, cookie, 0); } @@ -54,36 +53,34 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs *const regs, unsigned int unsigned long lr = regs->ARM_lr; const int gcc_frame_offset = sizeof(unsigned long); #else - // Is userspace aarch32 (32 bit) + /* Is userspace aarch32 (32 bit) */ const bool is_compat = compat_user_mode(regs); unsigned long fp = (is_compat ? regs->regs[11] : regs->regs[29]); unsigned long sp = (is_compat ? regs->compat_sp : regs->sp); unsigned long lr = (is_compat ? regs->compat_lr : regs->regs[30]); const int gcc_frame_offset = (is_compat ? sizeof(u32) : 0); #endif - // clang frame offset is always zero + /* clang frame offset is always zero */ int is_user_mode = user_mode(regs); - // pc (current function) has already been added + /* pc (current function) has already been added */ - if (!is_user_mode) { + if (!is_user_mode) return; - } - // Add the lr (parent function) - // entry preamble may not have executed + /* Add the lr (parent function), entry preamble may not have + * executed + */ gator_add_trace(cpu, lr); - // check fp is valid - if (fp == 0 || fp < sp) { + /* check fp is valid */ + if (fp == 0 || fp < sp) return; - } - // Get the current stack frame + /* Get the current stack frame */ curr = (struct stack_frame_eabi *)(fp - gcc_frame_offset); - if ((unsigned long)curr & 3) { + if ((unsigned long)curr & 3) return; - } while (depth-- && curr) { if (!access_ok(VERIFY_READ, curr, sizeof(struct stack_frame_eabi)) || @@ -95,13 +92,15 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs *const regs, unsigned int lr = (is_compat ? bufcurr.lr_32 : bufcurr.lr); #define calc_next(reg) ((reg) - gcc_frame_offset) - // Returns true if reg is a valid fp + /* Returns true if reg is a valid fp */ #define validate_next(reg, curr) \ ((reg) != 0 && (calc_next(reg) & 3) == 0 && (unsigned long)(curr) < calc_next(reg)) - // Try lr from the stack as the fp because gcc leaf functions do not push lr - // If gcc_frame_offset is non-zero, the lr will also be the clang fp - // This assumes code is at a lower address than the stack + /* Try lr from the stack as the fp because gcc leaf functions do + * not push lr. If gcc_frame_offset is non-zero, the lr will also + * be the clang fp. This assumes code is at a lower address than + * the stack + */ if (validate_next(lr, curr)) { fp = lr; lr = (is_compat ? bufcurr.lr2_32 : bufcurr.lr2); @@ -109,11 +108,10 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs *const regs, unsigned int gator_add_trace(cpu, lr); - if (!validate_next(fp, curr)) { + if (!validate_next(fp, curr)) return; - } - // Move to the next stack frame + /* Move to the next stack frame */ curr = (struct stack_frame_eabi *)calc_next(fp); } #endif @@ -129,6 +127,7 @@ static int report_trace(struct stackframe *frame, void *d) #if defined(MODULE) unsigned int cpu = get_physical_cpu(); struct module *mod = __module_address(addr); + if (mod) { cookie = get_cookie(cpu, current, mod->name, false); addr = addr - (unsigned long)mod->module_core; @@ -142,13 +141,13 @@ static int report_trace(struct stackframe *frame, void *d) } #endif -// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile -// #define GATOR_KERNEL_STACK_UNWINDING +/* Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile */ +/* #define GATOR_KERNEL_STACK_UNWINDING */ #if (defined(__arm__) || defined(__aarch64__)) && !defined(GATOR_KERNEL_STACK_UNWINDING) -// Disabled by default +/* Disabled by default */ MODULE_PARM_DESC(kernel_stack_unwinding, "Allow kernel stack unwinding."); -static bool kernel_stack_unwinding = 0; +static bool kernel_stack_unwinding; module_param(kernel_stack_unwinding, bool, 0644); #endif @@ -161,6 +160,7 @@ static void kernel_backtrace(int cpu, struct pt_regs *const regs) int depth = (kernel_stack_unwinding ? gator_backtrace_depth : 1); #endif struct stackframe frame; + if (depth == 0) depth = 1; #if defined(__arm__) @@ -196,10 +196,10 @@ static void gator_add_sample(int cpu, struct pt_regs *const regs, u64 time) if (in_kernel) { kernel_backtrace(cpu, regs); } else { - // Cookie+PC + /* Cookie+PC */ gator_add_trace(cpu, PC_REG); - // Backtrace + /* Backtrace */ if (gator_backtrace_depth) arm_backtrace_eabi(cpu, regs, gator_backtrace_depth); } diff --git a/driver/gator_buffer.c b/driver/gator_buffer.c index dfbc97d..910d5aa 100644 --- a/driver/gator_buffer.c +++ b/driver/gator_buffer.c @@ -10,55 +10,65 @@ static void marshal_frame(int cpu, int buftype) { int frame; + bool write_cpu; - if (!per_cpu(gator_buffer, cpu)[buftype]) { + if (!per_cpu(gator_buffer, cpu)[buftype]) return; - } switch (buftype) { case SUMMARY_BUF: + write_cpu = false; frame = FRAME_SUMMARY; break; case BACKTRACE_BUF: + write_cpu = true; frame = FRAME_BACKTRACE; break; case NAME_BUF: + write_cpu = true; frame = FRAME_NAME; break; case COUNTER_BUF: + write_cpu = false; frame = FRAME_COUNTER; break; case BLOCK_COUNTER_BUF: + write_cpu = true; frame = FRAME_BLOCK_COUNTER; break; case ANNOTATE_BUF: + write_cpu = false; frame = FRAME_ANNOTATE; break; case SCHED_TRACE_BUF: + write_cpu = true; frame = FRAME_SCHED_TRACE; break; case IDLE_BUF: + write_cpu = false; frame = FRAME_IDLE; break; case ACTIVITY_BUF: + write_cpu = false; frame = FRAME_ACTIVITY; break; default: + write_cpu = false; frame = -1; break; } - // add response type - if (gator_response_type > 0) { + /* add response type */ + if (gator_response_type > 0) gator_buffer_write_packed_int(cpu, buftype, gator_response_type); - } - // leave space for 4-byte unpacked length + /* leave space for 4-byte unpacked length */ per_cpu(gator_buffer_write, cpu)[buftype] = (per_cpu(gator_buffer_write, cpu)[buftype] + sizeof(s32)) & gator_buffer_mask[buftype]; - // add frame type and core number + /* add frame type and core number */ gator_buffer_write_packed_int(cpu, buftype, frame); - gator_buffer_write_packed_int(cpu, buftype, cpu); + if (write_cpu) + gator_buffer_write_packed_int(cpu, buftype, cpu); } static int buffer_bytes_available(int cpu, int buftype) @@ -66,19 +76,17 @@ static int buffer_bytes_available(int cpu, int buftype) int remaining, filled; filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_read, cpu)[buftype]; - if (filled < 0) { + if (filled < 0) filled += gator_buffer_size[buftype]; - } remaining = gator_buffer_size[buftype] - filled; - if (per_cpu(buffer_space_available, cpu)[buftype]) { - // Give some extra room; also allows space to insert the overflow error packet + if (per_cpu(buffer_space_available, cpu)[buftype]) + /* Give some extra room; also allows space to insert the overflow error packet */ remaining -= 200; - } else { - // Hysteresis, prevents multiple overflow messages + else + /* Hysteresis, prevents multiple overflow messages */ remaining -= 2000; - } return remaining; } @@ -87,11 +95,10 @@ static bool buffer_check_space(int cpu, int buftype, int bytes) { int remaining = buffer_bytes_available(cpu, buftype); - if (remaining < bytes) { + if (remaining < bytes) per_cpu(buffer_space_available, cpu)[buftype] = false; - } else { + else per_cpu(buffer_space_available, cpu)[buftype] = true; - } return per_cpu(buffer_space_available, cpu)[buftype]; } @@ -100,10 +107,10 @@ static int contiguous_space_available(int cpu, int buftype) { int remaining = buffer_bytes_available(cpu, buftype); int contiguous = gator_buffer_size[buftype] - per_cpu(gator_buffer_write, cpu)[buftype]; + if (remaining < contiguous) return remaining; - else - return contiguous; + return contiguous; } static void gator_commit_buffer(int cpu, int buftype, u64 time) @@ -114,41 +121,38 @@ static void gator_commit_buffer(int cpu, int buftype, u64 time) if (!per_cpu(gator_buffer, cpu)[buftype]) return; - // post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload + /* post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload */ local_irq_save(flags); type_length = gator_response_type ? 1 : 0; commit = per_cpu(gator_buffer_commit, cpu)[buftype]; length = per_cpu(gator_buffer_write, cpu)[buftype] - commit; - if (length < 0) { + if (length < 0) length += gator_buffer_size[buftype]; - } length = length - type_length - sizeof(s32); if (length <= FRAME_HEADER_SIZE) { - // Nothing to write, only the frame header is present + /* Nothing to write, only the frame header is present */ local_irq_restore(flags); return; } - for (byte = 0; byte < sizeof(s32); byte++) { + for (byte = 0; byte < sizeof(s32); byte++) per_cpu(gator_buffer, cpu)[buftype][(commit + type_length + byte) & gator_buffer_mask[buftype]] = (length >> byte * 8) & 0xFF; - } per_cpu(gator_buffer_commit, cpu)[buftype] = per_cpu(gator_buffer_write, cpu)[buftype]; if (gator_live_rate > 0) { - while (time > per_cpu(gator_buffer_commit_time, cpu)) { + while (time > per_cpu(gator_buffer_commit_time, cpu)) per_cpu(gator_buffer_commit_time, cpu) += gator_live_rate; - } } marshal_frame(cpu, buftype); local_irq_restore(flags); - // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater + /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */ if (per_cpu(in_scheduler_context, cpu)) { #ifndef CONFIG_PREEMPT_RT_FULL - // mod_timer can not be used in interrupt context in RT-Preempt full + /* mod_timer can not be used in interrupt context in RT-Preempt full */ mod_timer(&gator_buffer_wake_up_timer, jiffies + 1); #endif } else { @@ -159,10 +163,9 @@ static void gator_commit_buffer(int cpu, int buftype, u64 time) static void buffer_check(int cpu, int buftype, u64 time) { int filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_commit, cpu)[buftype]; - if (filled < 0) { + + if (filled < 0) filled += gator_buffer_size[buftype]; - } - if (filled >= ((gator_buffer_size[buftype] * 3) / 4)) { + if (filled >= ((gator_buffer_size[buftype] * 3) / 4)) gator_commit_buffer(cpu, buftype, time); - } } diff --git a/driver/gator_buffer_write.c b/driver/gator_buffer_write.c index b621ba9..654ec60 100644 --- a/driver/gator_buffer_write.c +++ b/driver/gator_buffer_write.c @@ -14,16 +14,17 @@ static void gator_buffer_write_packed_int(int cpu, int buftype, int x) char *buffer = per_cpu(gator_buffer, cpu)[buftype]; int packedBytes = 0; int more = true; + while (more) { - // low order 7 bits of x + /* low order 7 bits of x */ char b = x & 0x7f; + x >>= 7; - if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) { + if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) more = false; - } else { + else b |= 0x80; - } buffer[(write + packedBytes) & mask] = b; packedBytes++; @@ -39,16 +40,17 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, long long x) char *buffer = per_cpu(gator_buffer, cpu)[buftype]; int packedBytes = 0; int more = true; + while (more) { - // low order 7 bits of x + /* low order 7 bits of x */ char b = x & 0x7f; + x >>= 7; - if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) { + if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) more = false; - } else { + else b |= 0x80; - } buffer[(write + packedBytes) & mask] = b; packedBytes++; @@ -75,6 +77,7 @@ static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int le static void gator_buffer_write_string(int cpu, int buftype, const char *x) { int len = strlen(x); + gator_buffer_write_packed_int(cpu, buftype, len); gator_buffer_write_bytes(cpu, buftype, x, len); } diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c index 5c7d842..c43cce8 100644 --- a/driver/gator_cookies.c +++ b/driver/gator_cookies.c @@ -7,8 +7,10 @@ * */ -#define COOKIEMAP_ENTRIES 1024 /* must be power of 2 */ -#define TRANSLATE_BUFFER_SIZE 512 // must be a power of 2 - 512/4 = 128 entries +/* must be power of 2 */ +#define COOKIEMAP_ENTRIES 1024 +/* must be a power of 2 - 512/4 = 128 entries */ +#define TRANSLATE_BUFFER_SIZE 512 #define TRANSLATE_TEXT_SIZE 256 #define MAX_COLLISIONS 2 @@ -38,6 +40,7 @@ static uint32_t cookiemap_code(uint64_t value64) { uint32_t value = (uint32_t)((value64 >> 32) + value64); uint32_t cookiecode = (value >> 24) & 0xff; + cookiecode = cookiecode * 31 + ((value >> 16) & 0xff); cookiecode = cookiecode * 31 + ((value >> 8) & 0xff); cookiecode = cookiecode * 31 + ((value >> 0) & 0xff); @@ -52,9 +55,8 @@ static uint32_t gator_chksum_crc32(const char *data) int i, length = strlen(data); crc = 0xFFFFFFFF; - for (i = 0; i < length; i++) { + for (i = 0; i < length; i++) crc = ((crc >> 8) & 0x00FFFFFF) ^ gator_crc32_table[(crc ^ *block++) & 0xFF]; - } return (crc ^ 0xFFFFFFFF); } @@ -72,11 +74,12 @@ static uint32_t cookiemap_exists(uint64_t key) uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]); uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]); - // Can be called from interrupt handler or from work queue + /* Can be called from interrupt handler or from work queue */ local_irq_save(flags); for (x = 0; x < MAX_COLLISIONS; x++) { if (keys[x] == key) { uint32_t value = values[x]; + for (; x > 0; x--) { keys[x] = keys[x - 1]; values[x] = values[x - 1]; @@ -126,7 +129,7 @@ static void translate_buffer_write_args(int cpu, struct task_struct *task, const write = per_cpu(translate_buffer_write, cpu); next_write = (write + 1) & translate_buffer_mask; - // At least one entry must always remain available as when read == write, the queue is empty not full + /* At least one entry must always remain available as when read == write, the queue is empty not full */ if (next_write != per_cpu(translate_buffer_read, cpu)) { args = &per_cpu(translate_buffer, cpu)[write]; args->task = task; @@ -178,11 +181,11 @@ static void wq_cookie_handler(struct work_struct *unused) static void app_process_wake_up_handler(unsigned long unused_data) { - // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater + /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */ schedule_work(&cookie_work); } -// Retrieve full name from proc/pid/cmdline for java processes on Android +/* Retrieve full name from proc/pid/cmdline for java processes on Android */ static int translate_app_process(const char **text, int cpu, struct task_struct *task, bool from_wq) { void *maddr; @@ -195,12 +198,16 @@ static int translate_app_process(const char **text, int cpu, struct task_struct char *buf = per_cpu(translate_text, cpu); #ifndef CONFIG_PREEMPT_RT_FULL - // Push work into a work queue if in atomic context as the kernel functions below might sleep - // Rely on the in_interrupt variable rather than in_irq() or in_interrupt() kernel functions, as the value of these functions seems - // inconsistent during a context switch between android/linux versions + /* Push work into a work queue if in atomic context as the kernel + * functions below might sleep. Rely on the in_interrupt variable + * rather than in_irq() or in_interrupt() kernel functions, as the + * value of these functions seems inconsistent during a context + * switch between android/linux versions + */ if (!from_wq) { - // Check if already in buffer + /* Check if already in buffer */ int pos = per_cpu(translate_buffer_read, cpu); + while (pos != per_cpu(translate_buffer_write, cpu)) { if (per_cpu(translate_buffer, cpu)[pos].task == task) goto out; @@ -209,7 +216,7 @@ static int translate_app_process(const char **text, int cpu, struct task_struct translate_buffer_write_args(cpu, task, *text); - // Not safe to call in RT-Preempt full in schedule switch context + /* Not safe to call in RT-Preempt full in schedule switch context */ mod_timer(&app_process_wake_up_timer, jiffies + 1); goto out; } @@ -239,7 +246,8 @@ static int translate_app_process(const char **text, int cpu, struct task_struct copy_from_user_page(page_vma, page, addr, buf, maddr + offset, bytes); - kunmap(page); // release page allocated by get_user_pages() + /* release page allocated by get_user_pages() */ + kunmap(page); page_cache_release(page); len -= bytes; @@ -250,7 +258,7 @@ static int translate_app_process(const char **text, int cpu, struct task_struct retval = 1; } - // On app_process startup, /proc/pid/cmdline is initially "zygote" then "<pre-initialized>" but changes after an initial startup period + /* On app_process startup, /proc/pid/cmdline is initially "zygote" then "<pre-initialized>" but changes after an initial startup period */ if (strcmp(*text, "zygote") == 0 || strcmp(*text, "<pre-initialized>") == 0) retval = 0; @@ -262,6 +270,8 @@ out: return retval; } +static const char APP_PROCESS[] = "app_process"; + static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq) { unsigned long flags, cookie; @@ -271,16 +281,16 @@ static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, key = (key << 32) | (uint32_t)task->tgid; cookie = cookiemap_exists(key); - if (cookie) { + if (cookie) return cookie; - } - if (strcmp(text, "app_process") == 0) { + /* On 64-bit android app_process can be app_process32 or app_process64 */ + if (strncmp(text, APP_PROCESS, sizeof(APP_PROCESS) - 1) == 0) { if (!translate_app_process(&text, cpu, task, from_wq)) return UNRESOLVED_COOKIE; } - // Can be called from interrupt handler or from work queue or from scheduler trace + /* Can be called from interrupt handler or from work queue or from scheduler trace */ local_irq_save(flags); cookie = UNRESOLVED_COOKIE; @@ -300,7 +310,7 @@ static int get_exec_cookie(int cpu, struct task_struct *task) struct mm_struct *mm = task->mm; const char *text; - // kernel threads have no address space + /* kernel threads have no address space */ if (!mm) return NO_COOKIE; @@ -355,7 +365,7 @@ static int cookies_initialize(void) per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu; size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint64_t); - per_cpu(cookie_keys, cpu) = (uint64_t *)kmalloc(size, GFP_KERNEL); + per_cpu(cookie_keys, cpu) = kmalloc(size, GFP_KERNEL); if (!per_cpu(cookie_keys, cpu)) { err = -ENOMEM; goto cookie_setup_error; @@ -363,14 +373,14 @@ static int cookies_initialize(void) memset(per_cpu(cookie_keys, cpu), 0, size); size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint32_t); - per_cpu(cookie_values, cpu) = (uint32_t *)kmalloc(size, GFP_KERNEL); + per_cpu(cookie_values, cpu) = kmalloc(size, GFP_KERNEL); if (!per_cpu(cookie_values, cpu)) { err = -ENOMEM; goto cookie_setup_error; } memset(per_cpu(cookie_values, cpu), 0, size); - per_cpu(translate_buffer, cpu) = (struct cookie_args *)kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL); + per_cpu(translate_buffer, cpu) = kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL); if (!per_cpu(translate_buffer, cpu)) { err = -ENOMEM; goto cookie_setup_error; @@ -379,16 +389,16 @@ static int cookies_initialize(void) per_cpu(translate_buffer_write, cpu) = 0; per_cpu(translate_buffer_read, cpu) = 0; - per_cpu(translate_text, cpu) = (char *)kmalloc(TRANSLATE_TEXT_SIZE, GFP_KERNEL); + per_cpu(translate_text, cpu) = kmalloc(TRANSLATE_TEXT_SIZE, GFP_KERNEL); if (!per_cpu(translate_text, cpu)) { err = -ENOMEM; goto cookie_setup_error; } } - // build CRC32 table + /* build CRC32 table */ poly = 0x04c11db7; - gator_crc32_table = (uint32_t *)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL); + gator_crc32_table = kmalloc(256 * sizeof(*gator_crc32_table), GFP_KERNEL); if (!gator_crc32_table) { err = -ENOMEM; goto cookie_setup_error; @@ -396,11 +406,10 @@ static int cookies_initialize(void) for (i = 0; i < 256; i++) { crc = i; for (j = 8; j > 0; j--) { - if (crc & 1) { + if (crc & 1) crc = (crc >> 1) ^ poly; - } else { + else crc >>= 1; - } } gator_crc32_table[i] = crc; } diff --git a/driver/gator_events_armv6.c b/driver/gator_events_armv6.c index 3536456..a157a00 100644 --- a/driver/gator_events_armv6.c +++ b/driver/gator_events_armv6.c @@ -8,7 +8,7 @@ #include "gator.h" -// gator_events_perf_pmu.c is used if perf is supported +/* gator_events_perf_pmu.c is used if perf is supported */ #if GATOR_NO_PERF_SUPPORT static const char *pmnc_name; @@ -28,7 +28,7 @@ static const char *pmnc_name; #define CCNT 2 #define CNTMAX (CCNT+1) -static int pmnc_counters = 0; +static int pmnc_counters; static unsigned long pmnc_enabled[CNTMAX]; static unsigned long pmnc_event[CNTMAX]; static unsigned long pmnc_key[CNTMAX]; @@ -45,6 +45,7 @@ static inline void armv6_pmnc_write(u32 val) static inline u32 armv6_pmnc_read(void) { u32 val; + asm volatile("mrc p15, 0, %0, c15, c12, 0" : "=r" (val)); return val; } @@ -52,6 +53,7 @@ static inline u32 armv6_pmnc_read(void) static void armv6_pmnc_reset_counter(unsigned int cnt) { u32 val = 0; + switch (cnt) { case CCNT: asm volatile("mcr p15, 0, %0, c15, c12, 1" : : "r" (val)); @@ -74,20 +76,18 @@ int gator_events_armv6_create_files(struct super_block *sb, struct dentry *root) for (i = PMN0; i <= CCNT; i++) { char buf[40]; - if (i == CCNT) { - snprintf(buf, sizeof buf, "ARM_%s_ccnt", pmnc_name); - } else { - snprintf(buf, sizeof buf, "ARM_%s_cnt%d", pmnc_name, i); - } + + if (i == CCNT) + snprintf(buf, sizeof(buf), "ARM_%s_ccnt", pmnc_name); + else + snprintf(buf, sizeof(buf), "ARM_%s_cnt%d", pmnc_name, i); dir = gatorfs_mkdir(sb, root, buf); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]); gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]); - if (i != CCNT) { + if (i != CCNT) gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]); - } } return 0; @@ -98,9 +98,8 @@ static int gator_events_armv6_online(int **buffer, bool migrate) unsigned int cnt, len = 0, cpu = smp_processor_id(); u32 pmnc; - if (armv6_pmnc_read() & PMCR_E) { + if (armv6_pmnc_read() & PMCR_E) armv6_pmnc_write(armv6_pmnc_read() & ~PMCR_E); - } /* initialize PMNC, reset overflow, D bit, C bit and P bit. */ armv6_pmnc_write(PMCR_OFL_PMN0 | PMCR_OFL_PMN1 | PMCR_OFL_CCNT | @@ -115,19 +114,18 @@ static int gator_events_armv6_online(int **buffer, bool migrate) event = pmnc_event[cnt] & 255; - // Set event (if destined for PMNx counters) - if (cnt == PMN0) { + /* Set event (if destined for PMNx counters) */ + if (cnt == PMN0) pmnc |= event << 20; - } else if (cnt == PMN1) { + else if (cnt == PMN1) pmnc |= event << 12; - } - // Reset counter + /* Reset counter */ armv6_pmnc_reset_counter(cnt); } armv6_pmnc_write(pmnc | PMCR_E); - // return zero values, no need to read as the counters were just reset + /* return zero values, no need to read as the counters were just reset */ for (cnt = PMN0; cnt <= CCNT; cnt++) { if (pmnc_enabled[cnt]) { per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt]; @@ -146,9 +144,8 @@ static int gator_events_armv6_offline(int **buffer, bool migrate) unsigned int cnt; armv6_pmnc_write(armv6_pmnc_read() & ~PMCR_E); - for (cnt = PMN0; cnt <= CCNT; cnt++) { + for (cnt = PMN0; cnt <= CCNT; cnt++) armv6_pmnc_reset_counter(cnt); - } return 0; } @@ -163,19 +160,19 @@ static void gator_events_armv6_stop(void) } } -static int gator_events_armv6_read(int **buffer) +static int gator_events_armv6_read(int **buffer, bool sched_switch) { int cnt, len = 0; int cpu = smp_processor_id(); - // a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled - if (!(armv6_pmnc_read() & PMCR_E)) { + /* a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled */ + if (!(armv6_pmnc_read() & PMCR_E)) return 0; - } for (cnt = PMN0; cnt <= CCNT; cnt++) { if (pmnc_enabled[cnt]) { u32 value = 0; + switch (cnt) { case CCNT: asm volatile("mrc p15, 0, %0, c15, c12, 1" : "=r" (value)); diff --git a/driver/gator_events_armv7.c b/driver/gator_events_armv7.c index bd8a9ba..09c9422 100644 --- a/driver/gator_events_armv7.c +++ b/driver/gator_events_armv7.c @@ -15,16 +15,16 @@ #include "gator.h" -// gator_events_perf_pmu.c is used if perf is supported +/* gator_events_perf_pmu.c is used if perf is supported */ #if GATOR_NO_PERF_SUPPORT -// Per-CPU PMNC: config reg +/* Per-CPU PMNC: config reg */ #define PMNC_E (1 << 0) /* Enable all counters */ #define PMNC_P (1 << 1) /* Reset all counters */ #define PMNC_C (1 << 2) /* Cycle counter reset */ #define PMNC_MASK 0x3f /* Mask for writable bits */ -// ccnt reg +/* ccnt reg */ #define CCNT_REG (1 << 31) #define CCNT 0 @@ -49,6 +49,7 @@ inline void armv7_pmnc_write(u32 val) inline u32 armv7_pmnc_read(void) { u32 val; + asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val)); return val; } @@ -61,10 +62,10 @@ inline u32 armv7_ccnt_read(u32 reset_value) u32 val; local_irq_save(flags); - asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); // disable - asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); // read - asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (newval)); // new value - asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable + asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); /* disable */ + asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); /* read */ + asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (newval)); /* new value */ + asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); /* enable */ local_irq_restore(flags); return val; @@ -79,11 +80,11 @@ inline u32 armv7_cntn_read(unsigned int cnt, u32 reset_value) u32 oldval; local_irq_save(flags); - asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); // disable - asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (sel)); // select - asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (oldval)); // read - asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (newval)); // new value - asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable + asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); /* disable */ + asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (sel)); /* select */ + asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (oldval)); /* read */ + asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (newval)); /* new value */ + asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); /* enable */ local_irq_restore(flags); return oldval; @@ -92,13 +93,15 @@ inline u32 armv7_cntn_read(unsigned int cnt, u32 reset_value) static inline void armv7_pmnc_disable_interrupt(unsigned int cnt) { u32 val = cnt ? (1 << (cnt - CNT0)) : (1 << 31); + asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val)); } inline u32 armv7_pmnc_reset_interrupt(void) { - // Get and reset overflow status flags + /* Get and reset overflow status flags */ u32 flags; + asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (flags)); flags &= 0x8000003f; asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (flags)); @@ -108,6 +111,7 @@ inline u32 armv7_pmnc_reset_interrupt(void) static inline u32 armv7_pmnc_enable_counter(unsigned int cnt) { u32 val = cnt ? (1 << (cnt - CNT0)) : CCNT_REG; + asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val)); return cnt; } @@ -115,6 +119,7 @@ static inline u32 armv7_pmnc_enable_counter(unsigned int cnt) static inline u32 armv7_pmnc_disable_counter(unsigned int cnt) { u32 val = cnt ? (1 << (cnt - CNT0)) : CCNT_REG; + asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val)); return cnt; } @@ -122,15 +127,15 @@ static inline u32 armv7_pmnc_disable_counter(unsigned int cnt) static inline int armv7_pmnc_select_counter(unsigned int cnt) { u32 val = (cnt - CNT0); + asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val)); return cnt; } static inline void armv7_pmnc_write_evtsel(unsigned int cnt, u32 val) { - if (armv7_pmnc_select_counter(cnt) == cnt) { + if (armv7_pmnc_select_counter(cnt) == cnt) asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val)); - } } static int gator_events_armv7_create_files(struct super_block *sb, struct dentry *root) @@ -140,20 +145,18 @@ static int gator_events_armv7_create_files(struct super_block *sb, struct dentry for (i = 0; i < pmnc_counters; i++) { char buf[40]; - if (i == 0) { - snprintf(buf, sizeof buf, "%s_ccnt", pmnc_name); - } else { - snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i - 1); - } + + if (i == 0) + snprintf(buf, sizeof(buf), "%s_ccnt", pmnc_name); + else + snprintf(buf, sizeof(buf), "%s_cnt%d", pmnc_name, i - 1); dir = gatorfs_mkdir(sb, root, buf); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]); gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]); - if (i > 0) { + if (i > 0) gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]); - } } return 0; @@ -163,14 +166,13 @@ static int gator_events_armv7_online(int **buffer, bool migrate) { unsigned int cnt, len = 0, cpu = smp_processor_id(); - if (armv7_pmnc_read() & PMNC_E) { + if (armv7_pmnc_read() & PMNC_E) armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E); - } - // Initialize & Reset PMNC: C bit and P bit + /* Initialize & Reset PMNC: C bit and P bit */ armv7_pmnc_write(PMNC_P | PMNC_C); - // Reset overflow flags + /* Reset overflow flags */ armv7_pmnc_reset_interrupt(); for (cnt = CCNT; cnt < CNTMAX; cnt++) { @@ -179,28 +181,28 @@ static int gator_events_armv7_online(int **buffer, bool migrate) if (!pmnc_enabled[cnt]) continue; - // Disable counter + /* Disable counter */ armv7_pmnc_disable_counter(cnt); event = pmnc_event[cnt] & 255; - // Set event (if destined for PMNx counters), we don't need to set the event if it's a cycle count + /* Set event (if destined for PMNx counters), we don't need to set the event if it's a cycle count */ if (cnt != CCNT) armv7_pmnc_write_evtsel(cnt, event); armv7_pmnc_disable_interrupt(cnt); - // Reset counter + /* Reset counter */ cnt ? armv7_cntn_read(cnt, 0) : armv7_ccnt_read(0); - // Enable counter + /* Enable counter */ armv7_pmnc_enable_counter(cnt); } - // enable + /* enable */ armv7_pmnc_write(armv7_pmnc_read() | PMNC_E); - // return zero values, no need to read as the counters were just reset + /* return zero values, no need to read as the counters were just reset */ for (cnt = 0; cnt < pmnc_counters; cnt++) { if (pmnc_enabled[cnt]) { per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt]; @@ -216,7 +218,7 @@ static int gator_events_armv7_online(int **buffer, bool migrate) static int gator_events_armv7_offline(int **buffer, bool migrate) { - // disable all counters, including PMCCNTR; overflow IRQs will not be signaled + /* disable all counters, including PMCCNTR; overflow IRQs will not be signaled */ armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E); return 0; @@ -232,24 +234,23 @@ static void gator_events_armv7_stop(void) } } -static int gator_events_armv7_read(int **buffer) +static int gator_events_armv7_read(int **buffer, bool sched_switch) { int cnt, len = 0; int cpu = smp_processor_id(); - // a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled - if (!(armv7_pmnc_read() & PMNC_E)) { + /* a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled */ + if (!(armv7_pmnc_read() & PMNC_E)) return 0; - } for (cnt = 0; cnt < pmnc_counters; cnt++) { if (pmnc_enabled[cnt]) { int value; - if (cnt == CCNT) { + + if (cnt == CCNT) value = armv7_ccnt_read(0); - } else { + else value = armv7_cntn_read(cnt, 0); - } per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt]; per_cpu(perfCnt, cpu)[len++] = value; } @@ -290,17 +291,16 @@ int gator_events_armv7_init(void) pmnc_name = "ARMv7_Cortex_A9"; pmnc_counters = 6; break; - // ARM Cortex A12 is not supported by version of Linux before 3.0 case CORTEX_A15: pmnc_name = "ARMv7_Cortex_A15"; pmnc_counters = 6; break; - // ARM Cortex A17 is not supported by version of Linux before 3.0 + /* ARM Cortex A17 is not supported by version of Linux before 3.0 */ default: return -1; } - pmnc_counters++; // CNT[n] + CCNT + pmnc_counters++; /* CNT[n] + CCNT */ for (cnt = CCNT; cnt < CNTMAX; cnt++) { pmnc_enabled[cnt] = 0; diff --git a/driver/gator_events_block.c b/driver/gator_events_block.c index 03eed4f..a352a54 100644 --- a/driver/gator_events_block.c +++ b/driver/gator_events_block.c @@ -28,7 +28,7 @@ static ulong block_rq_rd_key; static atomic_t blockCnt[BLOCK_TOTAL]; static int blockGet[BLOCK_TOTAL * 4]; -// Tracepoint changed in 3.15 backported to older kernels. The Makefile tries to autodetect the correct value, but if it fails change the #if below +/* Tracepoint changed in 3.15 backported to older kernels. The Makefile tries to autodetect the correct value, but if it fails change the #if below */ #if OLD_BLOCK_RQ_COMPLETE GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct request *rq)) #else @@ -52,13 +52,11 @@ GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct r return; if (write) { - if (block_rq_wr_enabled) { + if (block_rq_wr_enabled) atomic_add(size, &blockCnt[BLOCK_RQ_WR]); - } } else { - if (block_rq_rd_enabled) { + if (block_rq_rd_enabled) atomic_add(size, &blockCnt[BLOCK_RQ_RD]); - } } } @@ -68,17 +66,15 @@ static int gator_events_block_create_files(struct super_block *sb, struct dentry /* block_complete_wr */ dir = gatorfs_mkdir(sb, root, "Linux_block_rq_wr"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &block_rq_wr_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &block_rq_wr_key); /* block_complete_rd */ dir = gatorfs_mkdir(sb, root, "Linux_block_rq_rd"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &block_rq_rd_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &block_rq_rd_key); @@ -87,7 +83,7 @@ static int gator_events_block_create_files(struct super_block *sb, struct dentry static int gator_events_block_start(void) { - // register tracepoints + /* register tracepoints */ if (block_rq_wr_enabled || block_rq_rd_enabled) if (GATOR_REGISTER_TRACE(block_rq_complete)) goto fail_block_rq_exit; @@ -95,7 +91,7 @@ static int gator_events_block_start(void) return 0; - // unregister tracepoints on error + /* unregister tracepoints on error */ fail_block_rq_exit: pr_err("gator: block event tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n"); @@ -112,19 +108,19 @@ static void gator_events_block_stop(void) block_rq_rd_enabled = 0; } -static int gator_events_block_read(int **buffer) +static int gator_events_block_read(int **buffer, bool sched_switch) { int len, value, data = 0; - if (!on_primary_core()) { + if (!on_primary_core()) return 0; - } len = 0; if (block_rq_wr_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_WR])) > 0) { atomic_sub(value, &blockCnt[BLOCK_RQ_WR]); blockGet[len++] = block_rq_wr_key; - blockGet[len++] = 0; // indicates to Streamline that value bytes were written now, not since the last message + /* Indicates to Streamline that value bytes were written now, not since the last message */ + blockGet[len++] = 0; blockGet[len++] = block_rq_wr_key; blockGet[len++] = value; data += value; @@ -132,7 +128,8 @@ static int gator_events_block_read(int **buffer) if (block_rq_rd_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_RD])) > 0) { atomic_sub(value, &blockCnt[BLOCK_RQ_RD]); blockGet[len++] = block_rq_rd_key; - blockGet[len++] = 0; // indicates to Streamline that value bytes were read now, not since the last message + /* Indicates to Streamline that value bytes were read now, not since the last message */ + blockGet[len++] = 0; blockGet[len++] = block_rq_rd_key; blockGet[len++] = value; data += value; diff --git a/driver/gator_events_ccn-504.c b/driver/gator_events_ccn-504.c deleted file mode 100644 index 62d994c..0000000 --- a/driver/gator_events_ccn-504.c +++ /dev/null @@ -1,346 +0,0 @@ -/** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/io.h> -#include <linux/module.h> - -#include "gator.h" - -#define NUM_REGIONS 256 -#define REGION_SIZE (64*1024) -#define REGION_DEBUG 1 -#define REGION_XP 64 -#define NUM_XPS 11 - -// DT (Debug) region -#define PMEVCNTSR0 0x0150 -#define PMCCNTRSR 0x0190 -#define PMCR 0x01A8 -#define PMSR 0x01B0 -#define PMSR_REQ 0x01B8 -#define PMSR_CLR 0x01C0 - -// XP region -#define DT_CONFIG 0x0300 -#define DT_CONTROL 0x0370 - -// Multiple -#define PMU_EVENT_SEL 0x0600 -#define OLY_ID 0xFF00 - -#define CCNT 4 -#define CNTMAX (CCNT + 1) - -#define get_pmu_event_id(event) (((event) >> 0) & 0xFF) -#define get_node_type(event) (((event) >> 8) & 0xFF) -#define get_region(event) (((event) >> 16) & 0xFF) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) - -// From kernel/params.c -#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \ - int param_set_##name(const char *val, struct kernel_param *kp) \ - { \ - tmptype l; \ - int ret; \ - \ - if (!val) return -EINVAL; \ - ret = strtolfn(val, 0, &l); \ - if (ret == -EINVAL || ((type)l != l)) \ - return -EINVAL; \ - *((type *)kp->arg) = l; \ - return 0; \ - } \ - int param_get_##name(char *buffer, struct kernel_param *kp) \ - { \ - return sprintf(buffer, format, *((type *)kp->arg)); \ - } - -#else - -// From kernel/params.c -#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \ - int param_set_##name(const char *val, const struct kernel_param *kp) \ - { \ - tmptype l; \ - int ret; \ - \ - ret = strtolfn(val, 0, &l); \ - if (ret < 0 || ((type)l != l)) \ - return ret < 0 ? ret : -EINVAL; \ - *((type *)kp->arg) = l; \ - return 0; \ - } \ - int param_get_##name(char *buffer, const struct kernel_param *kp) \ - { \ - return scnprintf(buffer, PAGE_SIZE, format, \ - *((type *)kp->arg)); \ - } \ - struct kernel_param_ops param_ops_##name = { \ - .set = param_set_##name, \ - .get = param_get_##name, \ - }; \ - EXPORT_SYMBOL(param_set_##name); \ - EXPORT_SYMBOL(param_get_##name); \ - EXPORT_SYMBOL(param_ops_##name) - -#endif - -STANDARD_PARAM_DEF(u64, u64, "%llu", u64, kstrtoull); - -// From include/linux/moduleparam.h -#define param_check_u64(name, p) __param_check(name, p, u64) - -MODULE_PARM_DESC(ccn504_addr, "CCN-504 physical base address"); -static u64 ccn504_addr = 0; -module_param(ccn504_addr, u64, 0444); - -static void __iomem *gator_events_ccn504_base; -static bool gator_events_ccn504_global_enabled; -static unsigned long gator_events_ccn504_enabled[CNTMAX]; -static unsigned long gator_events_ccn504_event[CNTMAX]; -static unsigned long gator_events_ccn504_key[CNTMAX]; -static int gator_events_ccn504_buffer[2*CNTMAX]; -static int gator_events_ccn504_prev[CNTMAX]; - -static void gator_events_ccn504_create_shutdown(void) -{ - if (gator_events_ccn504_base != NULL) { - iounmap(gator_events_ccn504_base); - } -} - -static int gator_events_ccn504_create_files(struct super_block *sb, struct dentry *root) -{ - struct dentry *dir; - int i; - char buf[32]; - - for (i = 0; i < CNTMAX; ++i) { - if (i == CCNT) { - snprintf(buf, sizeof(buf), "CCN-504_ccnt"); - } else { - snprintf(buf, sizeof(buf), "CCN-504_cnt%i", i); - } - dir = gatorfs_mkdir(sb, root, buf); - if (!dir) { - return -1; - } - - gatorfs_create_ulong(sb, dir, "enabled", &gator_events_ccn504_enabled[i]); - if (i != CCNT) { - gatorfs_create_ulong(sb, dir, "event", &gator_events_ccn504_event[i]); - } - gatorfs_create_ro_ulong(sb, dir, "key", &gator_events_ccn504_key[i]); - } - - return 0; -} - -static void gator_events_ccn504_set_dt_config(int xp_node_id, int event_num, int value) -{ - u32 dt_config; - - dt_config = readl(gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG); - dt_config |= (value + event_num) << (4*event_num); - writel(dt_config, gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG); -} - -static int gator_events_ccn504_start(void) -{ - int i; - - gator_events_ccn504_global_enabled = 0; - for (i = 0; i < CNTMAX; ++i) { - if (gator_events_ccn504_enabled[i]) { - gator_events_ccn504_global_enabled = 1; - break; - } - } - - if (!gator_events_ccn504_global_enabled) { - return 0; - } - - memset(&gator_events_ccn504_prev, 0x80, sizeof(gator_events_ccn504_prev)); - - // Disable INTREQ on overflow - // [6] ovfl_intr_en = 0 - // perhaps set to 1? - // [5] cntr_rst = 0 - // No register paring - // [4:1] cntcfg = 0 - // Enable PMU features - // [0] pmu_en = 1 - writel(0x1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMCR); - - // Configure the XPs - for (i = 0; i < NUM_XPS; ++i) { - int dt_control; - - // Pass on all events - writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG); - - // Enable PMU capability - // [0] dt_enable = 1 - dt_control = readl(gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL); - dt_control |= 0x1; - writel(dt_control, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL); - } - - // Assume no other pmu_event_sel registers are set - - // cycle counter does not need to be enabled - for (i = 0; i < CCNT; ++i) { - int pmu_event_id; - int node_type; - int region; - u32 pmu_event_sel; - u32 oly_id_whole; - u32 oly_id; - u32 node_id; - - if (!gator_events_ccn504_enabled[i]) { - continue; - } - - pmu_event_id = get_pmu_event_id(gator_events_ccn504_event[i]); - node_type = get_node_type(gator_events_ccn504_event[i]); - region = get_region(gator_events_ccn504_event[i]); - - // Verify the node_type - oly_id_whole = readl(gator_events_ccn504_base + region*REGION_SIZE + OLY_ID); - oly_id = oly_id_whole & 0x1F; - node_id = (oly_id_whole >> 8) & 0x7F; - if ((oly_id != node_type) || - ((node_type == 0x16) && ((oly_id != 0x14) && (oly_id != 0x15) && (oly_id != 0x16) && (oly_id != 0x18) && (oly_id != 0x19) && (oly_id != 0x1A)))) { - printk(KERN_ERR "gator: oly_id is 0x%x expected 0x%x\n", oly_id, node_type); - return -1; - } - - // Set the control register - pmu_event_sel = readl(gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL); - switch (node_type) { - case 0x08: // XP - pmu_event_sel |= pmu_event_id << (7*i); - gator_events_ccn504_set_dt_config(node_id, i, 0x4); - break; - case 0x04: // HN-F - case 0x16: // RN-I - case 0x10: // SBAS - pmu_event_sel |= pmu_event_id << (4*i); - gator_events_ccn504_set_dt_config(node_id/2, i, (node_id & 1) == 0 ? 0x8 : 0xC); - break; - } - writel(pmu_event_sel, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL); - } - - return 0; -} - -static void gator_events_ccn504_stop(void) -{ - int i; - - if (!gator_events_ccn504_global_enabled) { - return; - } - - // cycle counter does not need to be disabled - for (i = 0; i < CCNT; ++i) { - int region; - - if (!gator_events_ccn504_enabled[i]) { - continue; - } - - region = get_region(gator_events_ccn504_event[i]); - - writel(0, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL); - } - - // Clear dt_config - for (i = 0; i < NUM_XPS; ++i) { - writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG); - } -} - -static int gator_events_ccn504_read(int **buffer) -{ - int i; - int len = 0; - int value; - - if (!on_primary_core() || !gator_events_ccn504_global_enabled) { - return 0; - } - - // Verify the pmsr register is zero - while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) != 0); - - // Request a PMU snapshot - writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_REQ); - - // Wait for the snapshot - while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) == 0); - - // Read the shadow registers - for (i = 0; i < CNTMAX; ++i) { - if (!gator_events_ccn504_enabled[i]) { - continue; - } - - value = readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + (i == CCNT ? PMCCNTRSR : PMEVCNTSR0 + 8*i)); - if (gator_events_ccn504_prev[i] != 0x80808080) { - gator_events_ccn504_buffer[len++] = gator_events_ccn504_key[i]; - gator_events_ccn504_buffer[len++] = value - gator_events_ccn504_prev[i]; - } - gator_events_ccn504_prev[i] = value; - - // Are the counters registers cleared when read? Is that what the cntr_rst bit on the pmcr register does? - } - - // Clear the PMU snapshot status - writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_CLR); - - if (buffer) - *buffer = gator_events_ccn504_buffer; - - return len; -} - -static struct gator_interface gator_events_ccn504_interface = { - .shutdown = gator_events_ccn504_create_shutdown, - .create_files = gator_events_ccn504_create_files, - .start = gator_events_ccn504_start, - .stop = gator_events_ccn504_stop, - .read = gator_events_ccn504_read, -}; - -int gator_events_ccn504_init(void) -{ - int i; - - if (ccn504_addr == 0) { - return -1; - } - - gator_events_ccn504_base = ioremap(ccn504_addr, NUM_REGIONS*REGION_SIZE); - if (gator_events_ccn504_base == NULL) { - printk(KERN_ERR "gator: ioremap returned NULL\n"); - return -1; - } - - for (i = 0; i < CNTMAX; ++i) { - gator_events_ccn504_enabled[i] = 0; - gator_events_ccn504_event[i] = 0; - gator_events_ccn504_key[i] = gator_events_get_key(); - } - - return gator_events_install(&gator_events_ccn504_interface); -} diff --git a/driver/gator_events_irq.c b/driver/gator_events_irq.c index facbdd6..5221aac 100644 --- a/driver/gator_events_irq.c +++ b/driver/gator_events_irq.c @@ -42,17 +42,15 @@ static int gator_events_irq_create_files(struct super_block *sb, struct dentry * /* irq */ dir = gatorfs_mkdir(sb, root, "Linux_irq_irq"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &hardirq_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &hardirq_key); /* soft irq */ dir = gatorfs_mkdir(sb, root, "Linux_irq_softirq"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &softirq_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &softirq_key); @@ -63,7 +61,7 @@ static int gator_events_irq_online(int **buffer, bool migrate) { int len = 0, cpu = get_physical_cpu(); - // synchronization with the irq_exit functions is not necessary as the values are being reset + /* synchronization with the irq_exit functions is not necessary as the values are being reset */ if (hardirq_enabled) { atomic_set(&per_cpu(irqCnt, cpu)[HARDIRQ], 0); per_cpu(irqGet, cpu)[len++] = hardirq_key; @@ -84,7 +82,7 @@ static int gator_events_irq_online(int **buffer, bool migrate) static int gator_events_irq_start(void) { - // register tracepoints + /* register tracepoints */ if (hardirq_enabled) if (GATOR_REGISTER_TRACE(irq_handler_exit)) goto fail_hardirq_exit; @@ -95,7 +93,7 @@ static int gator_events_irq_start(void) return 0; - // unregister tracepoints on error + /* unregister tracepoints on error */ fail_softirq_exit: if (hardirq_enabled) GATOR_UNREGISTER_TRACE(irq_handler_exit); @@ -117,7 +115,7 @@ static void gator_events_irq_stop(void) softirq_enabled = 0; } -static int gator_events_irq_read(int **buffer) +static int gator_events_irq_read(int **buffer, bool sched_switch) { int len, value; int cpu = get_physical_cpu(); diff --git a/driver/gator_events_l2c-310.c b/driver/gator_events_l2c-310.c index 553f970..73aaac3 100644 --- a/driver/gator_events_l2c-310.c +++ b/driver/gator_events_l2c-310.c @@ -91,7 +91,7 @@ static void gator_events_l2c310_stop(void) writel(0, l2c310_base + L2X0_EVENT_CNT_CTRL); } -static int gator_events_l2c310_read(int **buffer) +static int gator_events_l2c310_read(int **buffer, bool sched_switch) { static const unsigned long l2x0_event_cntx_val[L2C310_COUNTERS_NUM] = { L2X0_EVENT_CNT0_VAL, @@ -149,8 +149,8 @@ static void __iomem *gator_events_l2c310_probe(void) 0xa0412000, #endif #if defined(CONFIG_ARCH_VEXPRESS) - 0x1e00a000, // A9x4 core tile (HBI-0191) - 0x2c0f0000, // New memory map tiles + 0x1e00a000, /* A9x4 core tile (HBI-0191) */ + 0x2c0f0000, /* New memory map tiles */ #endif }; int i; diff --git a/driver/gator_events_mali_4xx.c b/driver/gator_events_mali_4xx.c index 77712ea..9cf43fe 100644 --- a/driver/gator_events_mali_4xx.c +++ b/driver/gator_events_mali_4xx.c @@ -36,7 +36,7 @@ #elif GATOR_MALI_INTERFACE_STYLE == 2 #error GATOR_MALI_INTERFACE_STYLE 2 is obsolete #elif GATOR_MALI_INTERFACE_STYLE >= 3 -// Valid GATOR_MALI_INTERFACE_STYLE +/* Valid GATOR_MALI_INTERFACE_STYLE */ #else #error Unknown GATOR_MALI_INTERFACE_STYLE option. #endif @@ -73,8 +73,8 @@ static u32 *counter_address[NUMBER_OF_EVENTS]; /* An array used to return the data we recorded * as key,value pairs hence the *2 */ -static unsigned long counter_dump[NUMBER_OF_EVENTS * 2]; -static unsigned long counter_prev[NUMBER_OF_EVENTS]; +static int counter_dump[NUMBER_OF_EVENTS * 2]; +static int counter_prev[NUMBER_OF_EVENTS]; static bool prev_set[NUMBER_OF_EVENTS]; /* Note whether tracepoints have been registered */ @@ -89,8 +89,8 @@ static unsigned int n_vp_cores = MAX_NUM_VP_CORES; static unsigned int n_l2_cores = MAX_NUM_L2_CACHE_CORES; static unsigned int n_fp_cores = MAX_NUM_FP_CORES; -extern mali_counter mali_activity[2]; -static const char* const mali_activity_names[] = { +extern struct mali_counter mali_activity[2]; +static const char *const mali_activity_names[] = { "fragment", "vertex", }; @@ -112,36 +112,11 @@ static inline int is_hw_counter(unsigned int event_id) return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER); } -/* - * These are provided for utgard compatibility. - */ -typedef void _mali_profiling_get_mali_version_type(struct _mali_profiling_mali_version *values); -typedef u32 _mali_profiling_get_l2_counters_type(_mali_profiling_l2_counter_values *values); - -/* Probe for continuously sampled counter */ -#if 0 //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING -GATOR_DEFINE_PROBE(mali_sample_address, TP_PROTO(unsigned int event_id, u32 *addr)) -{ - /* Turning on too many pr_debug statements in frequently called functions - * can cause stability and/or performance problems - */ - //pr_debug("gator: mali_sample_address %d %d\n", event_id, addr); - if (event_id >= ACTIVITY_VP && event_id <= COUNTER_FP3_C1) { - counter_address[event_id] = addr; - } -} -#endif - /* Probe for hardware counter events */ GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int value)) { - /* Turning on too many pr_debug statements in frequently called functions - * can cause stability and/or performance problems - */ - //pr_debug("gator: mali_hw_counter %d %d\n", event_id, value); - if (is_hw_counter(event_id)) { + if (is_hw_counter(event_id)) counter_data[event_id] = value; - } } GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surface_id, unsigned int *counters)) @@ -150,9 +125,8 @@ GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surfac /* Copy over the values for those counters which are enabled. */ for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) { - if (counter_enabled[i]) { + if (counter_enabled[i]) counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]); - } } } @@ -172,13 +146,11 @@ static int create_fs_entry(struct super_block *sb, struct dentry *root, const ch dir = gatorfs_mkdir(sb, root, name); - if (!dir) { + if (!dir) return -1; - } - if (create_event_item) { + if (create_event_item) gatorfs_create_ulong(sb, dir, "event", &counter_event[event]); - } gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]); gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]); @@ -192,7 +164,7 @@ static int create_fs_entry(struct super_block *sb, struct dentry *root, const ch */ static void initialise_version_info(void) { - _mali_profiling_get_mali_version_type *mali_profiling_get_mali_version_symbol; + void (*mali_profiling_get_mali_version_symbol)(struct _mali_profiling_mali_version *values); mali_profiling_get_mali_version_symbol = symbol_get(_mali_profiling_get_mali_version); @@ -214,8 +186,8 @@ static void initialise_version_info(void) /* Release the function - we're done with it. */ symbol_put(_mali_profiling_get_mali_version); } else { - printk("gator: mali online _mali_profiling_get_mali_version symbol not found\n"); - printk("gator: check your Mali DDK version versus the GATOR_MALI_INTERFACE_STYLE setting\n"); + pr_err("gator: mali online _mali_profiling_get_mali_version symbol not found\n"); + pr_err("gator: check your Mali DDK version versus the GATOR_MALI_INTERFACE_STYLE setting\n"); } } #endif @@ -242,26 +214,24 @@ static int create_files(struct super_block *sb, struct dentry *root) mali_activity[0].cores = n_fp_cores; mali_activity[1].cores = n_vp_cores; for (event = 0; event < ARRAY_SIZE(mali_activity); event++) { - if (gator_mali_create_file_system(mali_name, mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) { + if (gator_mali_create_file_system(mali_name, mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) return -1; - } } /* Vertex processor counters */ for (core_id = 0; core_id < n_vp_cores; core_id++) { int activity_counter_id = ACTIVITY_VP_0; - snprintf(buf, sizeof buf, "ARM_Mali-%s_VP_%d_active", mali_name, core_id); - if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0) { + + snprintf(buf, sizeof(buf), "ARM_Mali-%s_VP_%d_active", mali_name, core_id); + if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0) return -1; - } for (counter_number = 0; counter_number < 2; counter_number++) { int counter_id = COUNTER_VP_0_C0 + (2 * core_id) + counter_number; - snprintf(buf, sizeof buf, "ARM_Mali-%s_VP_%d_cnt%d", mali_name, core_id, counter_number); - if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) { + snprintf(buf, sizeof(buf), "ARM_Mali-%s_VP_%d_cnt%d", mali_name, core_id, counter_number); + if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) return -1; - } } } @@ -269,18 +239,16 @@ static int create_files(struct super_block *sb, struct dentry *root) for (core_id = 0; core_id < n_fp_cores; core_id++) { int activity_counter_id = ACTIVITY_FP_0 + core_id; - snprintf(buf, sizeof buf, "ARM_Mali-%s_FP_%d_active", mali_name, core_id); - if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0) { + snprintf(buf, sizeof(buf), "ARM_Mali-%s_FP_%d_active", mali_name, core_id); + if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0) return -1; - } for (counter_number = 0; counter_number < 2; counter_number++) { int counter_id = COUNTER_FP_0_C0 + (2 * core_id) + counter_number; - snprintf(buf, sizeof buf, "ARM_Mali-%s_FP_%d_cnt%d", mali_name, core_id, counter_number); - if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) { + snprintf(buf, sizeof(buf), "ARM_Mali-%s_FP_%d_cnt%d", mali_name, core_id, counter_number); + if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) return -1; - } } } @@ -289,10 +257,9 @@ static int create_files(struct super_block *sb, struct dentry *root) for (counter_number = 0; counter_number < 2; counter_number++) { int counter_id = COUNTER_L2_0_C0 + (2 * core_id) + counter_number; - snprintf(buf, sizeof buf, "ARM_Mali-%s_L2_%d_cnt%d", mali_name, core_id, counter_number); - if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) { + snprintf(buf, sizeof(buf), "ARM_Mali-%s_L2_%d_cnt%d", mali_name, core_id, counter_number); + if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) return -1; - } } } @@ -300,27 +267,23 @@ static int create_files(struct super_block *sb, struct dentry *root) for (event = FIRST_SW_COUNTER; event <= LAST_SW_COUNTER; event++) { snprintf(buf, sizeof(buf), "ARM_Mali-%s_SW_%d", mali_name, event - FIRST_SW_COUNTER); - if (create_fs_entry(sb, root, buf, event, 0) != 0) { + if (create_fs_entry(sb, root, buf, event, 0) != 0) return -1; - } } /* Now set up the special counter entries */ snprintf(buf, sizeof(buf), "ARM_Mali-%s_Filmstrip_cnt0", mali_name); - if (create_fs_entry(sb, root, buf, COUNTER_FILMSTRIP, 1) != 0) { + if (create_fs_entry(sb, root, buf, COUNTER_FILMSTRIP, 1) != 0) return -1; - } #ifdef DVFS_REPORTED_BY_DDK snprintf(buf, sizeof(buf), "ARM_Mali-%s_Frequency", mali_name); - if (create_fs_entry(sb, root, buf, COUNTER_FREQUENCY, 1) != 0) { + if (create_fs_entry(sb, root, buf, COUNTER_FREQUENCY, 1) != 0) return -1; - } snprintf(buf, sizeof(buf), "ARM_Mali-%s_Voltage", mali_name); - if (create_fs_entry(sb, root, buf, COUNTER_VOLTAGE, 1) != 0) { + if (create_fs_entry(sb, root, buf, COUNTER_VOLTAGE, 1) != 0) return -1; - } #endif return 0; @@ -330,8 +293,8 @@ static int create_files(struct super_block *sb, struct dentry *root) * Local store for the get_counters entry point into the DDK. * This is stored here since it is used very regularly. */ -static mali_profiling_get_counters_type *mali_get_counters = NULL; -static _mali_profiling_get_l2_counters_type *mali_get_l2_counters = NULL; +static void (*mali_get_counters)(unsigned int *, unsigned int *, unsigned int *, unsigned int *); +static u32 (*mali_get_l2_counters)(struct _mali_profiling_l2_counter_values *values); /* * Examine list of counters between two index limits and determine if any one is enabled. @@ -342,9 +305,8 @@ static int is_any_counter_enabled(unsigned int first_counter, unsigned int last_ unsigned int i; for (i = first_counter; i <= last_counter; i++) { - if (counter_enabled[i]) { + if (counter_enabled[i]) return 1; /* At least one counter is enabled */ - } } return 0; /* No s/w counters enabled */ @@ -366,16 +328,15 @@ static void init_counters(unsigned int from_counter, unsigned int to_counter) pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n", mali_set_hw_event); for (counter_id = from_counter; counter_id <= to_counter; counter_id++) { - if (counter_enabled[counter_id]) { + if (counter_enabled[counter_id]) mali_set_hw_event(counter_id, counter_event[counter_id]); - } else { + else mali_set_hw_event(counter_id, 0xFFFFFFFF); - } } symbol_put(_mali_profiling_set_event); } else { - printk("gator: mali online _mali_profiling_set_event symbol not found\n"); + pr_err("gator: mali online _mali_profiling_set_event symbol not found\n"); } } @@ -407,27 +368,23 @@ static void mali_counter_initialize(void) symbol_put(_mali_profiling_control); } else { - printk("gator: mali online _mali_profiling_control symbol not found\n"); + pr_err("gator: mali online _mali_profiling_control symbol not found\n"); } mali_get_counters = symbol_get(_mali_profiling_get_counters); - if (mali_get_counters) { + if (mali_get_counters) pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", mali_get_counters); - - } else { - pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined"); - } + else + pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined\n"); mali_get_l2_counters = symbol_get(_mali_profiling_get_l2_counters); - if (mali_get_l2_counters) { + if (mali_get_l2_counters) pr_debug("gator: mali online _mali_profiling_get_l2_counters symbol @ %p\n", mali_get_l2_counters); - - } else { - pr_debug("gator WARNING: mali _mali_profiling_get_l2_counters symbol not defined"); - } + else + pr_debug("gator WARNING: mali _mali_profiling_get_l2_counters symbol not defined\n"); if (!mali_get_counters && !mali_get_l2_counters) { - pr_debug("gator: WARNING: no L2 counters available"); + pr_debug("gator: WARNING: no L2 counters available\n"); n_l2_cores = 0; } @@ -449,13 +406,12 @@ static void mali_counter_deinitialize(void) int i; pr_debug("gator: mali offline _mali_profiling_set_event symbol @ %p\n", mali_set_hw_event); - for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) { + for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) mali_set_hw_event(i, 0xFFFFFFFF); - } symbol_put(_mali_profiling_set_event); } else { - printk("gator: mali offline _mali_profiling_set_event symbol not found\n"); + pr_err("gator: mali offline _mali_profiling_set_event symbol not found\n"); } /* Generic control interface for Mali DDK. */ @@ -471,29 +427,27 @@ static void mali_counter_deinitialize(void) symbol_put(_mali_profiling_control); } else { - printk("gator: mali offline _mali_profiling_control symbol not found\n"); + pr_err("gator: mali offline _mali_profiling_control symbol not found\n"); } - if (mali_get_counters) { + if (mali_get_counters) symbol_put(_mali_profiling_get_counters); - } - if (mali_get_l2_counters) { + if (mali_get_l2_counters) symbol_put(_mali_profiling_get_l2_counters); - } } static int start(void) { - // register tracepoints + /* register tracepoints */ if (GATOR_REGISTER_TRACE(mali_hw_counter)) { - printk("gator: mali_hw_counter tracepoint failed to activate\n"); + pr_err("gator: mali_hw_counter tracepoint failed to activate\n"); return -1; } /* For Mali drivers with built-in support. */ if (GATOR_REGISTER_TRACE(mali_sw_counters)) { - printk("gator: mali_sw_counters tracepoint failed to activate\n"); + pr_err("gator: mali_sw_counters tracepoint failed to activate\n"); return -1; } @@ -543,17 +497,17 @@ static void dump_counters(unsigned int from_counter, unsigned int to_counter, un } } -static int read(int **buffer) +static int read(int **buffer, bool sched_switch) { int len = 0; if (!on_primary_core()) return 0; - // Read the L2 C0 and C1 here. + /* Read the L2 C0 and C1 here. */ if (n_l2_cores > 0 && is_any_counter_enabled(COUNTER_L2_0_C0, COUNTER_L2_0_C0 + (2 * n_l2_cores))) { unsigned int unavailable_l2_caches = 0; - _mali_profiling_l2_counter_values cache_values; + struct _mali_profiling_l2_counter_values cache_values; unsigned int cache_id; struct _mali_profiling_core_counters *per_core; @@ -572,25 +526,24 @@ static int read(int **buffer) unsigned int counter_id_0 = COUNTER_L2_0_C0 + (2 * cache_id); unsigned int counter_id_1 = counter_id_0 + 1; - if ((1 << cache_id) & unavailable_l2_caches) { + if ((1 << cache_id) & unavailable_l2_caches) continue; /* This cache is unavailable (powered-off, possibly). */ - } per_core = &cache_values.cores[cache_id]; if (counter_enabled[counter_id_0] && prev_set[counter_id_0]) { - // Calculate and save src0's counter val0 + /* Calculate and save src0's counter val0 */ counter_dump[len++] = counter_key[counter_id_0]; counter_dump[len++] = per_core->value0 - counter_prev[counter_id_0]; } if (counter_enabled[counter_id_1] && prev_set[counter_id_1]) { - // Calculate and save src1's counter val1 + /* Calculate and save src1's counter val1 */ counter_dump[len++] = counter_key[counter_id_1]; counter_dump[len++] = per_core->value1 - counter_prev[counter_id_1]; } - // Save the previous values for the counters. + /* Save the previous values for the counters. */ counter_prev[counter_id_0] = per_core->value0; prev_set[counter_id_0] = true; counter_prev[counter_id_1] = per_core->value1; @@ -608,8 +561,9 @@ static int read(int **buffer) { int cnt; /* - * Add in the voltage and frequency counters if enabled. Note that, since these are - * actually passed as events, the counter value should not be cleared. + * Add in the voltage and frequency counters if enabled. Note + * that, since these are actually passed as events, the counter + * value should not be cleared. */ cnt = COUNTER_FREQUENCY; if (counter_enabled[cnt]) { @@ -625,9 +579,8 @@ static int read(int **buffer) } #endif - if (buffer) { - *buffer = (int *)counter_dump; - } + if (buffer) + *buffer = counter_dump; return len; } diff --git a/driver/gator_events_mali_common.c b/driver/gator_events_mali_common.c index c3d0503..1af87d6 100644 --- a/driver/gator_events_mali_common.c +++ b/driver/gator_events_mali_common.c @@ -8,7 +8,7 @@ */ #include "gator_events_mali_common.h" -extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter, unsigned long *event) +extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, struct mali_counter *counter, unsigned long *event) { int err; char buf[255]; @@ -17,40 +17,39 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even /* If the counter name is empty ignore it */ if (strlen(event_name) != 0) { /* Set up the filesystem entry for this event. */ - if (mali_name == NULL) { + if (mali_name == NULL) snprintf(buf, sizeof(buf), "ARM_Mali-%s", event_name); - } else { + else snprintf(buf, sizeof(buf), "ARM_Mali-%s_%s", mali_name, event_name); - } dir = gatorfs_mkdir(sb, root, buf); if (dir == NULL) { - pr_debug("gator: %s: error creating file system for: %s (%s)", mali_name, event_name, buf); + pr_debug("gator: %s: error creating file system for: %s (%s)\n", mali_name, event_name, buf); return -1; } err = gatorfs_create_ulong(sb, dir, "enabled", &counter->enabled); if (err != 0) { - pr_debug("gator: %s: error calling gatorfs_create_ulong for: %s (%s)", mali_name, event_name, buf); + pr_debug("gator: %s: error calling gatorfs_create_ulong for: %s (%s)\n", mali_name, event_name, buf); return -1; } err = gatorfs_create_ro_ulong(sb, dir, "key", &counter->key); if (err != 0) { - pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf); + pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf); return -1; } if (counter->cores != -1) { err = gatorfs_create_ro_ulong(sb, dir, "cores", &counter->cores); if (err != 0) { - pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf); + pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf); return -1; } } if (event != NULL) { err = gatorfs_create_ulong(sb, dir, "event", event); if (err != 0) { - pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf); + pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf); return -1; } } @@ -59,12 +58,12 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even return 0; } -extern void gator_mali_initialise_counters(mali_counter counters[], unsigned int n_counters) +extern void gator_mali_initialise_counters(struct mali_counter counters[], unsigned int n_counters) { unsigned int cnt; for (cnt = 0; cnt < n_counters; cnt++) { - mali_counter *counter = &counters[cnt]; + struct mali_counter *counter = &counters[cnt]; counter->key = gator_events_get_key(); counter->enabled = 0; diff --git a/driver/gator_events_mali_common.h b/driver/gator_events_mali_common.h index 91d871b..e7082e6 100644 --- a/driver/gator_events_mali_common.h +++ b/driver/gator_events_mali_common.h @@ -16,7 +16,7 @@ #include <linux/time.h> #include <linux/math64.h> #include <linux/slab.h> -#include <asm/io.h> +#include <linux/io.h> /* Ensure that MALI_SUPPORT has been defined to something. */ #ifndef MALI_SUPPORT @@ -30,21 +30,20 @@ /* * Runtime state information for a counter. */ -typedef struct { - // 'key' (a unique id set by gatord and returned by gator.ko) +struct mali_counter { + /* 'key' (a unique id set by gatord and returned by gator.ko) */ unsigned long key; - // counter enable state + /* counter enable state */ unsigned long enabled; - // for activity counters, the number of cores, otherwise -1 + /* for activity counters, the number of cores, otherwise -1 */ unsigned long cores; -} mali_counter; +}; /* * Mali-4xx */ typedef int mali_profiling_set_event_type(unsigned int, int); typedef void mali_profiling_control_type(unsigned int, unsigned int); -typedef void mali_profiling_get_counters_type(unsigned int *, unsigned int *, unsigned int *, unsigned int *); /* * Driver entry points for functions called directly by gator. @@ -65,7 +64,7 @@ extern void _mali_profiling_get_counters(unsigned int *, unsigned int *, unsigne * * @return 0 if entry point was created, non-zero if not. */ -extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter, unsigned long *event); +extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, struct mali_counter *counter, unsigned long *event); /** * Initializes the counter array. @@ -73,6 +72,6 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even * @param keys The array of counters * @param n_counters The number of entries in each of the arrays. */ -extern void gator_mali_initialise_counters(mali_counter counters[], unsigned int n_counters); +extern void gator_mali_initialise_counters(struct mali_counter counters[], unsigned int n_counters); #endif /* GATOR_EVENTS_MALI_COMMON_H */ diff --git a/driver/gator_events_mali_midgard.c b/driver/gator_events_mali_midgard.c index ab0584c..0aec906 100644 --- a/driver/gator_events_mali_midgard.c +++ b/driver/gator_events_mali_midgard.c @@ -13,7 +13,7 @@ #include <linux/time.h> #include <linux/math64.h> #include <linux/slab.h> -#include <asm/io.h> +#include <linux/io.h> #ifdef MALI_DIR_MIDGARD /* New DDK Directory structure with kernel/drivers/gpu/arm/midgard*/ @@ -49,7 +49,7 @@ static const char mali_name[] = "Midgard"; */ /* Timeline (start/stop) activity */ -static const char *timeline_event_names[] = { +static const char *const timeline_event_names[] = { "PM_SHADER_0", "PM_SHADER_1", "PM_SHADER_2", @@ -88,7 +88,7 @@ enum { #define NUM_PM_SHADER (8) /* Software Counters */ -static const char *software_counter_names[] = { +static const char *const software_counter_names[] = { "MMU_PAGE_FAULT_0", "MMU_PAGE_FAULT_1", "MMU_PAGE_FAULT_2", @@ -103,7 +103,7 @@ enum { }; /* Software Counters */ -static const char *accumulators_names[] = { +static const char *const accumulators_names[] = { "TOTAL_ALLOC_PAGES" }; @@ -123,17 +123,18 @@ enum { /* * gatorfs variables for counter enable state */ -static mali_counter counters[NUMBER_OF_EVENTS]; +static struct mali_counter counters[NUMBER_OF_EVENTS]; static unsigned long filmstrip_event; /* An array used to return the data we recorded * as key,value pairs hence the *2 */ -static unsigned long counter_dump[NUMBER_OF_EVENTS * 2]; +static int counter_dump[NUMBER_OF_EVENTS * 2]; /* - * Array holding counter start times (in ns) for each counter. A zero here - * indicates that the activity monitored by this counter is not running. + * Array holding counter start times (in ns) for each counter. A zero + * here indicates that the activity monitored by this counter is not + * running. */ static struct timespec timeline_event_starttime[NUMBER_OF_TIMELINE_EVENTS]; @@ -156,6 +157,7 @@ static struct timespec prev_timestamp; static inline long get_duration_us(const struct timespec *start, const struct timespec *end) { long event_duration_us = (end->tv_nsec - start->tv_nsec) / 1000; + event_duration_us += (end->tv_sec - start->tv_sec) * 1000000; return event_duration_us; @@ -172,9 +174,8 @@ static void record_timeline_event(unsigned int timeline_index, unsigned int type getnstimeofday(&event_timestamp); /* Remember the start time if the activity is not already started */ - if (event_start->tv_sec == 0) { + if (event_start->tv_sec == 0) *event_start = event_timestamp; /* Structure copy */ - } break; case ACTIVITY_STOP: @@ -208,9 +209,9 @@ GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long #define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */ #define BIT_AT(value, pos) ((value >> pos) & 1) - static unsigned long long previous_shader_bitmask = 0; - static unsigned long long previous_tiler_bitmask = 0; - static unsigned long long previous_l2_bitmask = 0; + static unsigned long long previous_shader_bitmask; + static unsigned long long previous_tiler_bitmask; + static unsigned long long previous_l2_bitmask; switch (event_id) { case SHADER_PRESENT_LO: @@ -219,9 +220,8 @@ GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long int pos; for (pos = 0; pos < NUM_PM_SHADER; ++pos) { - if (BIT_AT(changed_bitmask, pos)) { + if (BIT_AT(changed_bitmask, pos)) record_timeline_event(PM_SHADER_0 + pos, BIT_AT(value, pos) ? ACTIVITY_START : ACTIVITY_STOP); - } } previous_shader_bitmask = value; @@ -232,9 +232,8 @@ GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long { unsigned long long changed = previous_tiler_bitmask ^ value; - if (BIT_AT(changed, 0)) { + if (BIT_AT(changed, 0)) record_timeline_event(PM_TILER_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP); - } previous_tiler_bitmask = value; break; @@ -244,12 +243,10 @@ GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long { unsigned long long changed = previous_l2_bitmask ^ value; - if (BIT_AT(changed, 0)) { + if (BIT_AT(changed, 0)) record_timeline_event(PM_L2_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP); - } - if (BIT_AT(changed, 4)) { + if (BIT_AT(changed, 4)) record_timeline_event(PM_L2_1, BIT_AT(value, 4) ? ACTIVITY_START : ACTIVITY_STOP); - } previous_l2_bitmask = value; break; @@ -297,31 +294,27 @@ static int create_files(struct super_block *sb, struct dentry *root) mali_profiling_control_type *mali_control; for (event = FIRST_TIMELINE_EVENT; event < FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS; event++) { - if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event], NULL) != 0) { + if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event], NULL) != 0) return -1; - } counter_index++; } counter_index = 0; for (event = FIRST_SOFTWARE_COUNTER; event < FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS; event++) { - if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event], NULL) != 0) { + if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event], NULL) != 0) return -1; - } counter_index++; } counter_index = 0; for (event = FIRST_ACCUMULATOR; event < FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS; event++) { - if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event], NULL) != 0) { + if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event], NULL) != 0) return -1; - } counter_index++; } mali_control = symbol_get(_mali_profiling_control); if (mali_control) { - if (gator_mali_create_file_system(mali_name, "Filmstrip_cnt0", sb, root, &counters[FILMSTRIP], &filmstrip_event) != 0) { + if (gator_mali_create_file_system(mali_name, "Filmstrip_cnt0", sb, root, &counters[FILMSTRIP], &filmstrip_event) != 0) return -1; - } symbol_put(_mali_profiling_control); } @@ -376,18 +369,15 @@ static int start(void) timeline_data[cnt] = 0; } - for (cnt = 0; cnt < NUMBER_OF_SOFTWARE_COUNTERS; cnt++) { + for (cnt = 0; cnt < NUMBER_OF_SOFTWARE_COUNTERS; cnt++) sw_counter_data[cnt] = 0; - } - for (cnt = 0; cnt < NUMBER_OF_ACCUMULATORS; cnt++) { + for (cnt = 0; cnt < NUMBER_OF_ACCUMULATORS; cnt++) accumulators_data[cnt] = 0; - } /* Register tracepoints */ - if (register_tracepoints() == 0) { + if (register_tracepoints() == 0) return -1; - } /* Generic control interface for Mali DDK. */ mali_control = symbol_get(_mali_profiling_control); @@ -410,7 +400,7 @@ static int start(void) symbol_put(_mali_profiling_control); } else { - printk("gator: mali online _mali_profiling_control symbol not found\n"); + pr_err("gator: mali online _mali_profiling_control symbol not found\n"); } /* @@ -457,20 +447,19 @@ static void stop(void) symbol_put(_mali_profiling_control); } else { - printk("gator: mali offline _mali_profiling_control symbol not found\n"); + pr_err("gator: mali offline _mali_profiling_control symbol not found\n"); } } -static int read(int **buffer) +static int read(int **buffer, bool sched_switch) { int cnt; int len = 0; long sample_interval_us = 0; struct timespec read_timestamp; - if (!on_primary_core()) { + if (!on_primary_core()) return 0; - } /* Get the start of this sample period. */ getnstimeofday(&read_timestamp); @@ -479,9 +468,8 @@ static int read(int **buffer) * Calculate the sample interval if the previous sample time is valid. * We use tv_sec since it will not be 0. */ - if (prev_timestamp.tv_sec != 0) { + if (prev_timestamp.tv_sec != 0) sample_interval_us = get_duration_us(&prev_timestamp, &read_timestamp); - } /* Structure copy. Update the previous timestamp. */ prev_timestamp = read_timestamp; @@ -490,15 +478,19 @@ static int read(int **buffer) * Report the timeline counters (ACTIVITY_START/STOP) */ for (cnt = FIRST_TIMELINE_EVENT; cnt < (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS); cnt++) { - mali_counter *counter = &counters[cnt]; + struct mali_counter *counter = &counters[cnt]; + if (counter->enabled) { const int index = cnt - FIRST_TIMELINE_EVENT; unsigned int value; - /* If the activity is still running, reset its start time to the start of this sample period - * to correct the count. Add the time up to the end of the sample onto the count. */ + /* If the activity is still running, reset its start time to the + * start of this sample period to correct the count. Add the + * time up to the end of the sample onto the count. + */ if (timeline_event_starttime[index].tv_sec != 0) { const long event_duration = get_duration_us(&timeline_event_starttime[index], &read_timestamp); + timeline_data[index] += event_duration; timeline_event_starttime[index] = read_timestamp; /* Activity is still running. */ } @@ -521,9 +513,11 @@ static int read(int **buffer) /* Report the software counters */ for (cnt = FIRST_SOFTWARE_COUNTER; cnt < (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS); cnt++) { - const mali_counter *counter = &counters[cnt]; + const struct mali_counter *counter = &counters[cnt]; + if (counter->enabled) { const int index = cnt - FIRST_SOFTWARE_COUNTER; + counter_dump[len++] = counter->key; counter_dump[len++] = sw_counter_data[index]; /* Set the value to zero for the next time */ @@ -533,9 +527,11 @@ static int read(int **buffer) /* Report the accumulators */ for (cnt = FIRST_ACCUMULATOR; cnt < (FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS); cnt++) { - const mali_counter *counter = &counters[cnt]; + const struct mali_counter *counter = &counters[cnt]; + if (counter->enabled) { const int index = cnt - FIRST_ACCUMULATOR; + counter_dump[len++] = counter->key; counter_dump[len++] = accumulators_data[index]; /* Do not zero the accumulator */ @@ -543,9 +539,8 @@ static int read(int **buffer) } /* Update the buffer */ - if (buffer) { - *buffer = (int *)counter_dump; - } + if (buffer) + *buffer = counter_dump; return len; } diff --git a/driver/gator_events_mali_midgard_hw.c b/driver/gator_events_mali_midgard_hw.c index fe6d889..c8065da 100644 --- a/driver/gator_events_mali_midgard_hw.c +++ b/driver/gator_events_mali_midgard_hw.c @@ -13,7 +13,7 @@ #include <linux/time.h> #include <linux/math64.h> #include <linux/slab.h> -#include <asm/io.h> +#include <linux/io.h> /* Mali Midgard DDK includes */ #if defined(MALI_SIMPLE_API) @@ -46,62 +46,46 @@ * Mali-Midgard */ #if MALI_DDK_GATOR_API_VERSION == 3 -typedef uint32_t kbase_gator_instr_hwcnt_dump_irq_type(struct kbase_gator_hwcnt_handles *); -typedef uint32_t kbase_gator_instr_hwcnt_dump_complete_type(struct kbase_gator_hwcnt_handles *, uint32_t *const); -typedef struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init_type(struct kbase_gator_hwcnt_info *); -typedef void kbase_gator_hwcnt_term_type(struct kbase_gator_hwcnt_info *, struct kbase_gator_hwcnt_handles *); -typedef const char *const *kbase_gator_hwcnt_init_names_type(uint32_t *); -typedef void kbase_gator_hwcnt_term_names_type(void); - -static kbase_gator_instr_hwcnt_dump_irq_type *kbase_gator_instr_hwcnt_dump_irq_symbol; -static kbase_gator_instr_hwcnt_dump_complete_type *kbase_gator_instr_hwcnt_dump_complete_symbol; -static kbase_gator_hwcnt_init_type *kbase_gator_hwcnt_init_symbol; -static kbase_gator_hwcnt_term_type *kbase_gator_hwcnt_term_symbol; +static uint32_t (*kbase_gator_instr_hwcnt_dump_irq_symbol)(struct kbase_gator_hwcnt_handles *); +static uint32_t (*kbase_gator_instr_hwcnt_dump_complete_symbol)(struct kbase_gator_hwcnt_handles *, uint32_t *const); +static struct kbase_gator_hwcnt_handles *(*kbase_gator_hwcnt_init_symbol)(struct kbase_gator_hwcnt_info *); +static void (*kbase_gator_hwcnt_term_symbol)(struct kbase_gator_hwcnt_info *, struct kbase_gator_hwcnt_handles *); #else -typedef struct kbase_device *kbase_find_device_type(int); -typedef struct kbase_context *kbase_create_context_type(struct kbase_device *); -typedef void kbase_destroy_context_type(struct kbase_context *); +static struct kbase_device *(*kbase_find_device_symbol)(int); +static struct kbase_context *(*kbase_create_context_symbol)(struct kbase_device *); +static void (*kbase_destroy_context_symbol)(struct kbase_context *); #if MALI_DDK_GATOR_API_VERSION == 1 -typedef void *kbase_va_alloc_type(struct kbase_context *, u32); -typedef void kbase_va_free_type(struct kbase_context *, void *); +static void *(*kbase_va_alloc_symbol)(struct kbase_context *, u32); +static void (*kbase_va_free_symbol)(struct kbase_context *, void *); #elif MALI_DDK_GATOR_API_VERSION == 2 -typedef void *kbase_va_alloc_type(struct kbase_context *, u32, struct kbase_hwc_dma_mapping *); -typedef void kbase_va_free_type(struct kbase_context *, struct kbase_hwc_dma_mapping *); +static void *(*kbase_va_alloc_symbol)(struct kbase_context *, u32, struct kbase_hwc_dma_mapping *); +static void (*kbase_va_free_symbol)(struct kbase_context *, struct kbase_hwc_dma_mapping *); #endif -typedef mali_error kbase_instr_hwcnt_enable_type(struct kbase_context *, struct kbase_uk_hwcnt_setup *); -typedef mali_error kbase_instr_hwcnt_disable_type(struct kbase_context *); -typedef mali_error kbase_instr_hwcnt_clear_type(struct kbase_context *); -typedef mali_error kbase_instr_hwcnt_dump_irq_type(struct kbase_context *); -typedef mali_bool kbase_instr_hwcnt_dump_complete_type(struct kbase_context *, mali_bool *); - -static kbase_find_device_type *kbase_find_device_symbol; -static kbase_create_context_type *kbase_create_context_symbol; -static kbase_va_alloc_type *kbase_va_alloc_symbol; -static kbase_instr_hwcnt_enable_type *kbase_instr_hwcnt_enable_symbol; -static kbase_instr_hwcnt_clear_type *kbase_instr_hwcnt_clear_symbol; -static kbase_instr_hwcnt_dump_irq_type *kbase_instr_hwcnt_dump_irq_symbol; -static kbase_instr_hwcnt_dump_complete_type *kbase_instr_hwcnt_dump_complete_symbol; -static kbase_instr_hwcnt_disable_type *kbase_instr_hwcnt_disable_symbol; -static kbase_va_free_type *kbase_va_free_symbol; -static kbase_destroy_context_type *kbase_destroy_context_symbol; - -static long shader_present_low = 0; +static mali_error (*kbase_instr_hwcnt_enable_symbol)(struct kbase_context *, struct kbase_uk_hwcnt_setup *); +static mali_error (*kbase_instr_hwcnt_disable_symbol)(struct kbase_context *); +static mali_error (*kbase_instr_hwcnt_clear_symbol)(struct kbase_context *); +static mali_error (*kbase_instr_hwcnt_dump_irq_symbol)(struct kbase_context *); +static mali_bool (*kbase_instr_hwcnt_dump_complete_symbol)(struct kbase_context *, mali_bool *); + +static long shader_present_low; #endif /** The interval between reads, in ns. * - * Earlier we introduced - * a 'hold off for 1ms after last read' to resolve MIDBASE-2178 and MALINE-724. - * However, the 1ms hold off is too long if no context switches occur as there is a race - * between this value and the tick of the read clock in gator which is also 1ms. If we 'miss' the - * current read, the counter values are effectively 'spread' over 2ms and the values seen are half - * what they should be (since Streamline averages over sample time). In the presence of context switches - * this spread can vary and markedly affect the counters. Currently there is no 'proper' solution to - * this, but empirically we have found that reducing the minimum read interval to 950us causes the - * counts to be much more stable. + * Earlier we introduced a 'hold off for 1ms after last read' to + * resolve MIDBASE-2178 and MALINE-724. However, the 1ms hold off is + * too long if no context switches occur as there is a race between + * this value and the tick of the read clock in gator which is also + * 1ms. If we 'miss' the current read, the counter values are + * effectively 'spread' over 2ms and the values seen are half what + * they should be (since Streamline averages over sample time). In the + * presence of context switches this spread can vary and markedly + * affect the counters. Currently there is no 'proper' solution to + * this, but empirically we have found that reducing the minimum read + * interval to 950us causes the counts to be much more stable. */ static const int READ_INTERVAL_NSEC = 950000; @@ -428,26 +412,26 @@ struct kbase_hwc_dma_mapping kernel_dump_buffer_handle; #endif /* kbase context and device */ -static struct kbase_context *kbcontext = NULL; -static struct kbase_device *kbdevice = NULL; +static struct kbase_context *kbcontext; +static struct kbase_device *kbdevice; /* - * The following function has no external prototype in older DDK revisions. When the DDK - * is updated then this should be removed. + * The following function has no external prototype in older DDK + * revisions. When the DDK is updated then this should be removed. */ struct kbase_device *kbase_find_device(int minor); #endif -static volatile bool kbase_device_busy = false; +static volatile bool kbase_device_busy; static unsigned int num_hardware_counters_enabled; /* gatorfs variables for counter enable state */ -static mali_counter *counters; +static struct mali_counter *counters; /* An array used to return the data we recorded as key,value pairs */ -static unsigned long *counter_dump; +static int *counter_dump; -extern mali_counter mali_activity[3]; +extern struct mali_counter mali_activity[3]; static const char *const mali_activity_names[] = { "fragment", @@ -456,27 +440,26 @@ static const char *const mali_activity_names[] = { }; #define SYMBOL_GET(FUNCTION, ERROR_COUNT) \ - if(FUNCTION ## _symbol) \ - { \ - printk("gator: mali " #FUNCTION " symbol was already registered\n"); \ - (ERROR_COUNT)++; \ - } \ - else \ - { \ - FUNCTION ## _symbol = symbol_get(FUNCTION); \ - if(! FUNCTION ## _symbol) \ - { \ - printk("gator: mali online " #FUNCTION " symbol not found\n"); \ + do { \ + if (FUNCTION ## _symbol) { \ + pr_err("gator: mali " #FUNCTION " symbol was already registered\n"); \ (ERROR_COUNT)++; \ + } else { \ + FUNCTION ## _symbol = symbol_get(FUNCTION); \ + if (!FUNCTION ## _symbol) { \ + pr_err("gator: mali online " #FUNCTION " symbol not found\n"); \ + (ERROR_COUNT)++; \ + } \ } \ - } + } while (0) #define SYMBOL_CLEANUP(FUNCTION) \ - if(FUNCTION ## _symbol) \ - { \ - symbol_put(FUNCTION); \ - FUNCTION ## _symbol = NULL; \ - } + do { \ + if (FUNCTION ## _symbol) { \ + symbol_put(FUNCTION); \ + FUNCTION ## _symbol = NULL; \ + } \ + } while (0) /** * Execute symbol_get for all the Mali symbols and check for success. @@ -541,14 +524,12 @@ static void clean_symbols(void) static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns) { /* If the current ns count rolls over a second, roll the next read time too. */ - if (current_time->tv_sec != *prev_time_s) { + if (current_time->tv_sec != *prev_time_s) *next_read_time_ns = *next_read_time_ns - NSEC_PER_SEC; - } /* Abort the read if the next read time has not arrived. */ - if (current_time->tv_nsec < *next_read_time_ns) { + if (current_time->tv_nsec < *next_read_time_ns) return 0; - } /* Set the next read some fixed time after this one, and update the read timestamp. */ *next_read_time_ns = current_time->tv_nsec + READ_INTERVAL_NSEC; @@ -572,16 +553,16 @@ static int start(void) num_hardware_counters_enabled = 0; /* Declare and initialise kbase_gator_hwcnt_info structure */ - in_out_info = kmalloc(sizeof(struct kbase_gator_hwcnt_info), GFP_KERNEL); - for (cnt = 0; cnt < ARRAY_SIZE(in_out_info->bitmask); cnt++) { + in_out_info = kmalloc(sizeof(*in_out_info), GFP_KERNEL); + for (cnt = 0; cnt < ARRAY_SIZE(in_out_info->bitmask); cnt++) in_out_info->bitmask[cnt] = 0; - } /* Calculate enable bitmasks based on counters_enabled array */ for (cnt = 0; cnt < number_of_hardware_counters; cnt++) { if (counters[cnt].enabled) { int block = GET_HW_BLOCK(cnt); int enable_bit = GET_COUNTER_OFFSET(cnt) / 4; + in_out_info->bitmask[block] |= (1 << enable_bit); pr_debug("gator: Mali-Midgard: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt); num_hardware_counters_enabled++; @@ -598,9 +579,8 @@ static int start(void) handles = kbase_gator_hwcnt_init_symbol(in_out_info); - if (handles == NULL) { + if (handles == NULL) goto out; - } kbase_device_busy = false; } @@ -612,10 +592,12 @@ static int start(void) /* Calculate enable bitmasks based on counters_enabled array */ for (cnt = 0; cnt < number_of_hardware_counters; cnt++) { - const mali_counter *counter = &counters[cnt]; + const struct mali_counter *counter = &counters[cnt]; + if (counter->enabled) { int block = GET_HW_BLOCK(cnt); int enable_bit = GET_COUNTER_OFFSET(cnt) / 4; + bitmask[block] |= (1 << enable_bit); pr_debug("gator: Mali-Midgard: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt); num_hardware_counters_enabled++; @@ -684,7 +666,7 @@ static int start(void) } pr_debug("gator: Mali-Midgard: hardware counters enabled\n"); kbase_instr_hwcnt_clear_symbol(kbcontext); - pr_debug("gator: Mali-Midgard: hardware counters cleared \n"); + pr_debug("gator: Mali-Midgard: hardware counters cleared\n"); kbase_device_busy = false; } @@ -719,9 +701,8 @@ static void stop(void) pr_debug("gator: Mali-Midgard: stop\n"); /* Set all counters as disabled */ - for (cnt = 0; cnt < number_of_hardware_counters; cnt++) { + for (cnt = 0; cnt < number_of_hardware_counters; cnt++) counters[cnt].enabled = 0; - } /* Destroy the context for HW counters */ #if MALI_DDK_GATOR_API_VERSION == 3 @@ -763,30 +744,87 @@ static void stop(void) } } -static int read(int **buffer) +static int read_counter(const int cnt, const int len, const struct mali_counter *counter) +{ + const int block = GET_HW_BLOCK(cnt); + const int counter_offset = GET_COUNTER_OFFSET(cnt); + +#if MALI_DDK_GATOR_API_VERSION == 3 + const char *block_base_address = (char *)in_out_info->kernel_dump_buffer; + int i; + int shader_core_count = 0; + u32 value = 0; + + for (i = 0; i < in_out_info->nr_hwc_blocks; i++) { + if (block == in_out_info->hwc_layout[i]) { + value += *((u32 *)(block_base_address + (0x100 * i)) + counter_offset); + if (block == SHADER_BLOCK) + ++shader_core_count; + } + } + + if (shader_core_count > 1) + value /= shader_core_count; +#else + const char *block_base_address = (char *)kernel_dump_buffer + vithar_blocks[block]; + + /* If counter belongs to shader block need to take into account all cores */ + if (block == SHADER_BLOCK) { + int i = 0; + int shader_core_count = 0; + + value = 0; + + for (i = 0; i < 4; i++) { + if ((shader_present_low >> i) & 1) { + value += *((u32 *)(block_base_address + (0x100 * i)) + counter_offset); + shader_core_count++; + } + } + + for (i = 0; i < 4; i++) { + if ((shader_present_low >> (i+4)) & 1) { + value += *((u32 *)(block_base_address + (0x100 * i) + 0x800) + counter_offset); + shader_core_count++; + } + } + + /* Need to total by number of cores to produce an average */ + if (shader_core_count != 0) + value /= shader_core_count; + } else { + value = *((u32 *)block_base_address + counter_offset); + } +#endif + + counter_dump[len + 0] = counter->key; + counter_dump[len + 1] = value; + + return 2; +} + +static int read(int **buffer, bool sched_switch) { int cnt; int len = 0; - u32 value = 0; uint32_t success; struct timespec current_time; - static u32 prev_time_s = 0; - static s32 next_read_time_ns = 0; + static u32 prev_time_s; + static s32 next_read_time_ns; - if (!on_primary_core()) { + if (!on_primary_core() || sched_switch) return 0; - } getnstimeofday(¤t_time); /* - * Discard reads unless a respectable time has passed. This reduces the load on the GPU without sacrificing - * accuracy on the Streamline display. + * Discard reads unless a respectable time has passed. This + * reduces the load on the GPU without sacrificing accuracy on + * the Streamline display. */ - if (!is_read_scheduled(¤t_time, &prev_time_s, &next_read_time_ns)) { + if (!is_read_scheduled(¤t_time, &prev_time_s, &next_read_time_ns)) return 0; - } /* * Report the HW counters @@ -803,16 +841,14 @@ static int read(int **buffer) #endif #if MALI_DDK_GATOR_API_VERSION == 3 - if (!handles) { + if (!handles) return -1; - } /* Mali symbols can be called safely since a kbcontext is valid */ if (kbase_gator_instr_hwcnt_dump_complete_symbol(handles, &success) == MALI_TRUE) { #else - if (!kbcontext) { + if (!kbcontext) return -1; - } /* Mali symbols can be called safely since a kbcontext is valid */ if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE) { @@ -822,64 +858,10 @@ static int read(int **buffer) if (success == MALI_TRUE) { /* Cycle through hardware counters and accumulate totals */ for (cnt = 0; cnt < number_of_hardware_counters; cnt++) { - const mali_counter *counter = &counters[cnt]; - if (counter->enabled) { - const int block = GET_HW_BLOCK(cnt); - const int counter_offset = GET_COUNTER_OFFSET(cnt); - -#if MALI_DDK_GATOR_API_VERSION == 3 - const char *block_base_address = (char *)in_out_info->kernel_dump_buffer; - int i; - int shader_core_count = 0; - value = 0; - - for (i = 0; i < in_out_info->nr_hwc_blocks; i++) { - if (block == in_out_info->hwc_layout[i]) { - value += *((u32 *)(block_base_address + (0x100 * i)) + counter_offset); - if (block == SHADER_BLOCK) { - ++shader_core_count; - } - } - } - - if (shader_core_count > 1) { - value /= shader_core_count; - } -#else - const char *block_base_address = (char *)kernel_dump_buffer + vithar_blocks[block]; - - /* If counter belongs to shader block need to take into account all cores */ - if (block == SHADER_BLOCK) { - int i = 0; - int shader_core_count = 0; - value = 0; - - for (i = 0; i < 4; i++) { - if ((shader_present_low >> i) & 1) { - value += *((u32 *)(block_base_address + (0x100 * i)) + counter_offset); - shader_core_count++; - } - } - - for (i = 0; i < 4; i++) { - if((shader_present_low >> (i+4)) & 1) { - value += *((u32 *)(block_base_address + (0x100 * i) + 0x800) + counter_offset); - shader_core_count++; - } - } - - /* Need to total by number of cores to produce an average */ - if (shader_core_count != 0) { - value /= shader_core_count; - } - } else { - value = *((u32 *)block_base_address + counter_offset); - } -#endif + const struct mali_counter *counter = &counters[cnt]; - counter_dump[len++] = counter->key; - counter_dump[len++] = value; - } + if (counter->enabled) + len += read_counter(cnt, len, counter); } } } @@ -895,9 +877,8 @@ static int read(int **buffer) } /* Update the buffer */ - if (buffer) { - *buffer = (int *)counter_dump; - } + if (buffer) + *buffer = counter_dump; return len; } @@ -909,15 +890,13 @@ static int create_files(struct super_block *sb, struct dentry *root) * Create the filesystem for all events */ for (event = 0; event < ARRAY_SIZE(mali_activity); event++) { - if (gator_mali_create_file_system("Midgard", mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) { + if (gator_mali_create_file_system("Midgard", mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) return -1; - } } for (event = 0; event < number_of_hardware_counters; event++) { - if (gator_mali_create_file_system(mali_name, hardware_counter_names[event], sb, root, &counters[event], NULL) != 0) { + if (gator_mali_create_file_system(mali_name, hardware_counter_names[event], sb, root, &counters[event], NULL) != 0) return -1; - } } return 0; @@ -926,7 +905,7 @@ static int create_files(struct super_block *sb, struct dentry *root) static void shutdown(void) { #if MALI_DDK_GATOR_API_VERSION == 3 - kbase_gator_hwcnt_term_names_type *kbase_gator_hwcnt_term_names_symbol = NULL; + void (*kbase_gator_hwcnt_term_names_symbol)(void) = NULL; int error_count = 0; #endif @@ -940,7 +919,7 @@ static void shutdown(void) hardware_counter_names = NULL; if (kbase_gator_hwcnt_term_names_symbol != NULL) { kbase_gator_hwcnt_term_names_symbol(); - printk(KERN_ERR "Released symbols\n"); + pr_err("Released symbols\n"); } SYMBOL_CLEANUP(kbase_gator_hwcnt_term_names); @@ -958,7 +937,7 @@ static struct gator_interface gator_events_mali_midgard_interface = { int gator_events_mali_midgard_hw_init(void) { #if MALI_DDK_GATOR_API_VERSION == 3 - kbase_gator_hwcnt_init_names_type *kbase_gator_hwcnt_init_names_symbol = NULL; + const char *const *(*kbase_gator_hwcnt_init_names_symbol)(uint32_t *) = NULL; int error_count = 0; #endif @@ -981,7 +960,7 @@ int gator_events_mali_midgard_hw_init(void) SYMBOL_CLEANUP(kbase_gator_hwcnt_init_names); if ((hardware_counter_names == NULL) || (number_of_hardware_counters <= 0)) { - printk(KERN_ERR "gator: Error reading hardware counters names: got %d names\n", number_of_hardware_counters); + pr_err("gator: Error reading hardware counters names: got %d names\n", number_of_hardware_counters); return -1; } #else diff --git a/driver/gator_events_mali_midgard_hw_test.c b/driver/gator_events_mali_midgard_hw_test.c index ba6553f..31a91e1 100644 --- a/driver/gator_events_mali_midgard_hw_test.c +++ b/driver/gator_events_mali_midgard_hw_test.c @@ -23,12 +23,12 @@ static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int ex current_time.tv_nsec = ns; if (is_read_scheduled(¤t_time, &prev_time_s, &next_read_time_ns) != expected_result) { - printk("Failed do_read(%u, %u, %u, %d): expected %d\n", s, ns, prev_s, next_ns, expected_result); + pr_err("Failed do_read(%u, %u, %u, %d): expected %d\n", s, ns, prev_s, next_ns, expected_result); return 0; } if (next_read_time_ns != expected_next_ns) { - printk("Failed: next_read_ns expected=%d, actual=%d\n", expected_next_ns, next_read_time_ns); + pr_err("Failed: next_read_ns expected=%d, actual=%d\n", expected_next_ns, next_read_time_ns); return 0; } @@ -40,7 +40,7 @@ static void test_all_is_read_scheduled(void) const int HIGHEST_NS = 999999999; int n_tests_passed = 0; - printk("gator: running tests on %s\n", __FILE__); + pr_err("gator: running tests on %s\n", __FILE__); n_tests_passed += test_is_read_scheduled(0, 0, 0, 0, 1, READ_INTERVAL_NSEC); /* Null time */ n_tests_passed += test_is_read_scheduled(100, 1000, 0, 0, 1, READ_INTERVAL_NSEC + 1000); /* Initial values */ @@ -51,5 +51,5 @@ static void test_all_is_read_scheduled(void) n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500, 1, 600 + READ_INTERVAL_NSEC); - printk("gator: %d tests passed\n", n_tests_passed); + pr_err("gator: %d tests passed\n", n_tests_passed); } diff --git a/driver/gator_events_meminfo.c b/driver/gator_events_meminfo.c index c633dfd..c625ac5 100644 --- a/driver/gator_events_meminfo.c +++ b/driver/gator_events_meminfo.c @@ -16,6 +16,8 @@ #include <linux/workqueue.h> #include <trace/events/kmem.h> +#define USE_THREAD defined(CONFIG_PREEMPT_RT_FULL) + enum { MEMINFO_MEMFREE, MEMINFO_MEMUSED, @@ -48,7 +50,7 @@ static bool meminfo_global_enabled; static ulong meminfo_enabled[MEMINFO_TOTAL]; static ulong meminfo_keys[MEMINFO_TOTAL]; static long long meminfo_buffer[2 * (MEMINFO_TOTAL + 2)]; -static int meminfo_length = 0; +static int meminfo_length; static bool new_data_avail; static bool proc_global_enabled; @@ -56,22 +58,44 @@ static ulong proc_enabled[PROC_COUNT]; static ulong proc_keys[PROC_COUNT]; static DEFINE_PER_CPU(long long, proc_buffer[2 * (PROC_COUNT + 3)]); +#if USE_THREAD + static int gator_meminfo_func(void *data); static bool gator_meminfo_run; -// Initialize semaphore unlocked to initialize memory values +/* Initialize semaphore unlocked to initialize memory values */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) static DECLARE_MUTEX(gator_meminfo_sem); #else static DEFINE_SEMAPHORE(gator_meminfo_sem); #endif +static void notify(void) +{ + up(&gator_meminfo_sem); +} + +#else + +static unsigned int mem_event; +static void wq_sched_handler(struct work_struct *wsptr); +DECLARE_WORK(work, wq_sched_handler); +static struct timer_list meminfo_wake_up_timer; +static void meminfo_wake_up_handler(unsigned long unused_data); + +static void notify(void) +{ + mem_event++; +} + +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order)) #else GATOR_DEFINE_PROBE(mm_page_free, TP_PROTO(struct page *page, unsigned int order)) #endif { - up(&gator_meminfo_sem); + notify(); } #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) @@ -80,12 +104,12 @@ GATOR_DEFINE_PROBE(mm_pagevec_free, TP_PROTO(struct page *page, int cold)) GATOR_DEFINE_PROBE(mm_page_free_batched, TP_PROTO(struct page *page, int cold)) #endif { - up(&gator_meminfo_sem); + notify(); } GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype)) { - up(&gator_meminfo_sem); + notify(); } static int gator_events_meminfo_create_files(struct super_block *sb, struct dentry *root) @@ -95,18 +119,16 @@ static int gator_events_meminfo_create_files(struct super_block *sb, struct dent for (i = 0; i < MEMINFO_TOTAL; i++) { dir = gatorfs_mkdir(sb, root, meminfo_names[i]); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &meminfo_enabled[i]); gatorfs_create_ro_ulong(sb, dir, "key", &meminfo_keys[i]); } for (i = 0; i < PROC_COUNT; ++i) { dir = gatorfs_mkdir(sb, root, proc_names[i]); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &proc_enabled[i]); gatorfs_create_ro_ulong(sb, dir, "key", &proc_keys[i]); } @@ -134,9 +156,8 @@ static int gator_events_meminfo_start(void) break; } } - if (meminfo_enabled[MEMINFO_MEMUSED]) { + if (meminfo_enabled[MEMINFO_MEMUSED]) proc_global_enabled = 1; - } if (meminfo_global_enabled == 0) return 0; @@ -156,16 +177,22 @@ static int gator_events_meminfo_start(void) if (GATOR_REGISTER_TRACE(mm_page_alloc)) goto mm_page_alloc_exit; - // Start worker thread +#if USE_THREAD + /* Start worker thread */ gator_meminfo_run = true; - // Since the mutex starts unlocked, memory values will be initialized + /* Since the mutex starts unlocked, memory values will be initialized */ if (IS_ERR(kthread_run(gator_meminfo_func, NULL, "gator_meminfo"))) goto kthread_run_exit; +#else + setup_timer(&meminfo_wake_up_timer, meminfo_wake_up_handler, 0); +#endif return 0; +#if USE_THREAD kthread_run_exit: GATOR_UNREGISTER_TRACE(mm_page_alloc); +#endif mm_page_alloc_exit: #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) GATOR_UNREGISTER_TRACE(mm_pagevec_free); @@ -194,75 +221,111 @@ static void gator_events_meminfo_stop(void) #endif GATOR_UNREGISTER_TRACE(mm_page_alloc); - // Stop worker thread +#if USE_THREAD + /* Stop worker thread */ gator_meminfo_run = false; up(&gator_meminfo_sem); +#else + del_timer_sync(&meminfo_wake_up_timer); +#endif } } -// Must be run in process context as the kernel function si_meminfo() can sleep -static int gator_meminfo_func(void *data) +static void do_read(void) { struct sysinfo info; int i, len; unsigned long long value; - for (;;) { - if (down_killable(&gator_meminfo_sem)) { - break; + meminfo_length = len = 0; + + si_meminfo(&info); + for (i = 0; i < MEMINFO_TOTAL; i++) { + if (meminfo_enabled[i]) { + switch (i) { + case MEMINFO_MEMFREE: + value = info.freeram * PAGE_SIZE; + break; + case MEMINFO_MEMUSED: + /* pid -1 means system wide */ + meminfo_buffer[len++] = 1; + meminfo_buffer[len++] = -1; + /* Emit value */ + meminfo_buffer[len++] = meminfo_keys[MEMINFO_MEMUSED]; + meminfo_buffer[len++] = (info.totalram - info.freeram) * PAGE_SIZE; + /* Clear pid */ + meminfo_buffer[len++] = 1; + meminfo_buffer[len++] = 0; + continue; + case MEMINFO_BUFFERRAM: + value = info.bufferram * PAGE_SIZE; + break; + default: + value = 0; + break; + } + meminfo_buffer[len++] = meminfo_keys[i]; + meminfo_buffer[len++] = value; } + } - // Eat up any pending events - while (!down_trylock(&gator_meminfo_sem)); + meminfo_length = len; + new_data_avail = true; +} - if (!gator_meminfo_run) { +#if USE_THREAD + +static int gator_meminfo_func(void *data) +{ + for (;;) { + if (down_killable(&gator_meminfo_sem)) break; - } - meminfo_length = len = 0; - - si_meminfo(&info); - for (i = 0; i < MEMINFO_TOTAL; i++) { - if (meminfo_enabled[i]) { - switch (i) { - case MEMINFO_MEMFREE: - value = info.freeram * PAGE_SIZE; - break; - case MEMINFO_MEMUSED: - // pid -1 means system wide - meminfo_buffer[len++] = 1; - meminfo_buffer[len++] = -1; - // Emit value - meminfo_buffer[len++] = meminfo_keys[MEMINFO_MEMUSED]; - meminfo_buffer[len++] = (info.totalram - info.freeram) * PAGE_SIZE; - // Clear pid - meminfo_buffer[len++] = 1; - meminfo_buffer[len++] = 0; - continue; - case MEMINFO_BUFFERRAM: - value = info.bufferram * PAGE_SIZE; - break; - default: - value = 0; - break; - } - meminfo_buffer[len++] = meminfo_keys[i]; - meminfo_buffer[len++] = value; - } - } + /* Eat up any pending events */ + while (!down_trylock(&gator_meminfo_sem)) + ; + + if (!gator_meminfo_run) + break; - meminfo_length = len; - new_data_avail = true; + do_read(); } return 0; } +#else + +/* Must be run in process context as the kernel function si_meminfo() can sleep */ +static void wq_sched_handler(struct work_struct *wsptr) +{ + do_read(); +} + +static void meminfo_wake_up_handler(unsigned long unused_data) +{ + /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */ + schedule_work(&work); +} + +#endif + static int gator_events_meminfo_read(long long **buffer) { +#if !USE_THREAD + static unsigned int last_mem_event; +#endif + if (!on_primary_core() || !meminfo_global_enabled) return 0; +#if !USE_THREAD + if (last_mem_event != mem_event) { + last_mem_event = mem_event; + mod_timer(&meminfo_wake_up_timer, jiffies + 1); + } +#endif + if (!new_data_avail) return 0; @@ -280,6 +343,7 @@ static inline unsigned long gator_get_mm_counter(struct mm_struct *mm, int membe { #ifdef SPLIT_RSS_COUNTING long val = atomic_long_read(&mm->rss_stat.count[member]); + if (val < 0) val = 0; return (unsigned long)val; @@ -306,22 +370,19 @@ static int gator_events_meminfo_read_proc(long long **buffer, struct task_struct int cpu = get_physical_cpu(); long long *buf = per_cpu(proc_buffer, cpu); - if (!proc_global_enabled) { + if (!proc_global_enabled) return 0; - } - // Collect the memory stats of the process instead of the thread - if (task->group_leader != NULL) { + /* Collect the memory stats of the process instead of the thread */ + if (task->group_leader != NULL) task = task->group_leader; - } - // get_task_mm/mmput is not needed in this context because the task and it's mm are required as part of the sched_switch + /* get_task_mm/mmput is not needed in this context because the task and it's mm are required as part of the sched_switch */ mm = task->mm; - if (mm == NULL) { + if (mm == NULL) return 0; - } - // Derived from task_statm in fs/proc/task_mmu.c + /* Derived from task_statm in fs/proc/task_mmu.c */ if (meminfo_enabled[MEMINFO_MEMUSED] || proc_enabled[PROC_SHARE]) { share = get_mm_counter(mm, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) @@ -332,7 +393,7 @@ static int gator_events_meminfo_read_proc(long long **buffer, struct task_struct ); } - // key of 1 indicates a pid + /* key of 1 indicates a pid */ buf[len++] = 1; buf[len++] = task->pid; @@ -366,12 +427,12 @@ static int gator_events_meminfo_read_proc(long long **buffer, struct task_struct MM_ANONPAGES #endif ); - // Send resident for this pid + /* Send resident for this pid */ buf[len++] = meminfo_keys[MEMINFO_MEMUSED]; buf[len++] = value * PAGE_SIZE; } - // Clear pid + /* Clear pid */ buf[len++] = 1; buf[len++] = 0; diff --git a/driver/gator_events_mmapped.c b/driver/gator_events_mmapped.c index 5bc01c4..6b2af99 100644 --- a/driver/gator_events_mmapped.c +++ b/driver/gator_events_mmapped.c @@ -103,7 +103,7 @@ static int mmapped_simulate(int counter, int delta_in_us) switch (counter) { case 0: /* sort-of-sine */ { - static int t = 0; + static int t; int x; t += delta_in_us; @@ -140,7 +140,7 @@ static int mmapped_simulate(int counter, int delta_in_us) break; case 2: /* PWM signal */ { - static int dc, x, t = 0; + static int dc, x, t; t += delta_in_us; if (t > 1000000) @@ -157,7 +157,7 @@ static int mmapped_simulate(int counter, int delta_in_us) return result; } -static int gator_events_mmapped_read(int **buffer) +static int gator_events_mmapped_read(int **buffer, bool sched_switch) { int i; int len = 0; diff --git a/driver/gator_events_net.c b/driver/gator_events_net.c index 11c10e3..d21b4db 100644 --- a/driver/gator_events_net.c +++ b/driver/gator_events_net.c @@ -25,7 +25,7 @@ static int netGet[TOTALNET * 4]; static struct timer_list net_wake_up_timer; -// Must be run in process context as the kernel function dev_get_stats() can sleep +/* Must be run in process context as the kernel function dev_get_stats() can sleep */ static void get_network_stats(struct work_struct *wsptr) { int rx = 0, tx = 0; @@ -49,7 +49,7 @@ DECLARE_WORK(wq_get_stats, get_network_stats); static void net_wake_up_handler(unsigned long unused_data) { - // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater + /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */ schedule_work(&wq_get_stats); } @@ -73,21 +73,19 @@ static void calculate_delta(int *rx, int *tx) static int gator_events_net_create_files(struct super_block *sb, struct dentry *root) { - // Network counters are not currently supported in RT-Preempt full because mod_timer is used + /* Network counters are not currently supported in RT-Preempt full because mod_timer is used */ #ifndef CONFIG_PREEMPT_RT_FULL struct dentry *dir; dir = gatorfs_mkdir(sb, root, "Linux_net_rx"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &netrx_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &netrx_key); dir = gatorfs_mkdir(sb, root, "Linux_net_tx"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &nettx_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &nettx_key); #endif @@ -115,10 +113,10 @@ static void gator_events_net_stop(void) nettx_enabled = 0; } -static int gator_events_net_read(int **buffer) +static int gator_events_net_read(int **buffer, bool sched_switch) { int len, rx_delta, tx_delta; - static int last_rx_delta = 0, last_tx_delta = 0; + static int last_rx_delta, last_tx_delta; if (!on_primary_core()) return 0; @@ -134,7 +132,8 @@ static int gator_events_net_read(int **buffer) if (netrx_enabled && last_rx_delta != rx_delta) { last_rx_delta = rx_delta; netGet[len++] = netrx_key; - netGet[len++] = 0; // indicates to Streamline that rx_delta bytes were transmitted now, not since the last message + /* indicates to Streamline that rx_delta bytes were transmitted now, not since the last message */ + netGet[len++] = 0; netGet[len++] = netrx_key; netGet[len++] = rx_delta; } @@ -142,7 +141,8 @@ static int gator_events_net_read(int **buffer) if (nettx_enabled && last_tx_delta != tx_delta) { last_tx_delta = tx_delta; netGet[len++] = nettx_key; - netGet[len++] = 0; // indicates to Streamline that tx_delta bytes were transmitted now, not since the last message + /* indicates to Streamline that tx_delta bytes were transmitted now, not since the last message */ + netGet[len++] = 0; netGet[len++] = nettx_key; netGet[len++] = tx_delta; } diff --git a/driver/gator_events_perf_pmu.c b/driver/gator_events_perf_pmu.c index 06bbad5..47cf278 100644 --- a/driver/gator_events_perf_pmu.c +++ b/driver/gator_events_perf_pmu.c @@ -8,7 +8,7 @@ #include "gator.h" -// gator_events_armvX.c is used for Linux 2.6.x +/* gator_events_armvX.c is used for Linux 2.6.x */ #if GATOR_PERF_PMU_SUPPORT #include <linux/io.h> @@ -20,39 +20,41 @@ extern bool event_based_sampling; -// Maximum number of per-core counters - currently reserves enough space for two full hardware PMUs for big.LITTLE +/* Maximum number of per-core counters - currently reserves enough space for two full hardware PMUs for big.LITTLE */ #define CNTMAX 16 #define CCI_400 4 -// Maximum number of uncore counters -// + 1 for the cci-400 cycles counter -#define UCCNT (CCI_400 + 1) +#define CCN_5XX 8 +/* Maximum number of uncore counters */ +/* + 1 for the cci-400 cycles counter */ +/* + 1 for the CCN-5xx cycles counter */ +#define UCCNT (CCI_400 + 1 + CCN_5XX + 1) -// Default to 0 if unable to probe the revision which was the previous behavior +/* Default to 0 if unable to probe the revision which was the previous behavior */ #define DEFAULT_CCI_REVISION 0 -// A gator_attr is needed for every counter +/* A gator_attr is needed for every counter */ struct gator_attr { - // Set once in gator_events_perf_pmu_*_init - the name of the event in the gatorfs + /* Set once in gator_events_perf_pmu_*_init - the name of the event in the gatorfs */ char name[40]; - // Exposed in gatorfs - set by gatord to enable this counter + /* Exposed in gatorfs - set by gatord to enable this counter */ unsigned long enabled; - // Set once in gator_events_perf_pmu_*_init - the perf type to use, see perf_type_id in the perf_event.h header file. + /* Set once in gator_events_perf_pmu_*_init - the perf type to use, see perf_type_id in the perf_event.h header file. */ unsigned long type; - // Exposed in gatorfs - set by gatord to select the event to collect + /* Exposed in gatorfs - set by gatord to select the event to collect */ unsigned long event; - // Exposed in gatorfs - set by gatord with the sample period to use and enable EBS for this counter + /* Exposed in gatorfs - set by gatord with the sample period to use and enable EBS for this counter */ unsigned long count; - // Exposed as read only in gatorfs - set once in __attr_init as the key to use in the APC data + /* Exposed as read only in gatorfs - set once in __attr_init as the key to use in the APC data */ unsigned long key; }; -// Per-core counter attributes +/* Per-core counter attributes */ static struct gator_attr attrs[CNTMAX]; -// Number of initialized per-core counters +/* Number of initialized per-core counters */ static int attr_count; -// Uncore counter attributes +/* Uncore counter attributes */ static struct gator_attr uc_attrs[UCCNT]; -// Number of initialized uncore counters +/* Number of initialized uncore counters */ static int uc_attr_count; struct gator_event { @@ -74,13 +76,11 @@ static int __create_files(struct super_block *sb, struct dentry *root, struct ga { struct dentry *dir; - if (attr->name[0] == '\0') { + if (attr->name[0] == '\0') return 0; - } dir = gatorfs_mkdir(sb, root, attr->name); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &attr->enabled); gatorfs_create_ulong(sb, dir, "count", &attr->count); gatorfs_create_ro_ulong(sb, dir, "key", &attr->key); @@ -94,15 +94,13 @@ static int gator_events_perf_pmu_create_files(struct super_block *sb, struct den int cnt; for (cnt = 0; cnt < attr_count; cnt++) { - if (__create_files(sb, root, &attrs[cnt]) != 0) { + if (__create_files(sb, root, &attrs[cnt]) != 0) return -1; - } } for (cnt = 0; cnt < uc_attr_count; cnt++) { - if (__create_files(sb, root, &uc_attrs[cnt]) != 0) { + if (__create_files(sb, root, &uc_attrs[cnt]) != 0) return -1; - } } return 0; @@ -123,14 +121,14 @@ static void dummy_handler(struct perf_event *event, int unused, struct perf_samp static void dummy_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs) #endif { -// Required as perf_event_create_kernel_counter() requires an overflow handler, even though all we do is poll + /* Required as perf_event_create_kernel_counter() requires an overflow handler, even though all we do is poll */ } -static int gator_events_perf_pmu_read(int **buffer); +static int gator_events_perf_pmu_read(int **buffer, bool sched_switch); static int gator_events_perf_pmu_online(int **buffer, bool migrate) { - return gator_events_perf_pmu_read(buffer); + return gator_events_perf_pmu_read(buffer, false); } static void __online_dispatch(int cpu, bool migrate, struct gator_attr *const attr, struct gator_event *const event) @@ -139,15 +137,13 @@ static void __online_dispatch(int cpu, bool migrate, struct gator_attr *const at event->zero = true; - if (event->pevent != NULL || event->pevent_attr == 0 || migrate) { + if (event->pevent != NULL || event->pevent_attr == 0 || migrate) return; - } - if (attr->count > 0) { + if (attr->count > 0) handler = ebs_overflow_handler; - } else { + else handler = dummy_handler; - } #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) event->pevent = perf_event_create_kernel_counter(event->pevent_attr, cpu, 0, handler); @@ -174,14 +170,12 @@ static void gator_events_perf_pmu_online_dispatch(int cpu, bool migrate) cpu = pcpu_to_lcpu(cpu); - for (cnt = 0; cnt < attr_count; cnt++) { + for (cnt = 0; cnt < attr_count; cnt++) __online_dispatch(cpu, migrate, &attrs[cnt], &per_cpu(events, cpu)[cnt]); - } if (cpu == 0) { - for (cnt = 0; cnt < uc_attr_count; cnt++) { + for (cnt = 0; cnt < uc_attr_count; cnt++) __online_dispatch(cpu, migrate, &uc_attrs[cnt], &uc_events[cnt]); - } } } @@ -194,28 +188,24 @@ static void __offline_dispatch(int cpu, struct gator_event *const event) event->pevent = NULL; } - if (pe) { + if (pe) perf_event_release_kernel(pe); - } } static void gator_events_perf_pmu_offline_dispatch(int cpu, bool migrate) { int cnt; - if (migrate) { + if (migrate) return; - } cpu = pcpu_to_lcpu(cpu); - for (cnt = 0; cnt < attr_count; cnt++) { + for (cnt = 0; cnt < attr_count; cnt++) __offline_dispatch(cpu, &per_cpu(events, cpu)[cnt]); - } if (cpu == 0) { - for (cnt = 0; cnt < uc_attr_count; cnt++) { + for (cnt = 0; cnt < uc_attr_count; cnt++) __offline_dispatch(cpu, &uc_events[cnt]); - } } } @@ -225,7 +215,7 @@ static int __check_ebs(struct gator_attr *const attr) if (!event_based_sampling) { event_based_sampling = true; } else { - printk(KERN_WARNING "gator: Only one ebs counter is allowed\n"); + pr_warning("gator: Only one ebs counter is allowed\n"); return -1; } } @@ -238,9 +228,9 @@ static int __start(struct gator_attr *const attr, struct gator_event *const even u32 size = sizeof(struct perf_event_attr); event->pevent = NULL; - if (!attr->enabled) { // Skip disabled counters + /* Skip disabled counters */ + if (!attr->enabled) return 0; - } event->prev = 0; event->curr = 0; @@ -267,29 +257,25 @@ static int gator_events_perf_pmu_start(void) event_based_sampling = false; for (cnt = 0; cnt < attr_count; cnt++) { - if (__check_ebs(&attrs[cnt]) != 0) { + if (__check_ebs(&attrs[cnt]) != 0) return -1; - } } for (cnt = 0; cnt < uc_attr_count; cnt++) { - if (__check_ebs(&uc_attrs[cnt]) != 0) { + if (__check_ebs(&uc_attrs[cnt]) != 0) return -1; - } } for_each_present_cpu(cpu) { for (cnt = 0; cnt < attr_count; cnt++) { - if (__start(&attrs[cnt], &per_cpu(events, cpu)[cnt]) != 0) { + if (__start(&attrs[cnt], &per_cpu(events, cpu)[cnt]) != 0) return -1; - } } } for (cnt = 0; cnt < uc_attr_count; cnt++) { - if (__start(&uc_attrs[cnt], &uc_events[cnt]) != 0) { + if (__start(&uc_attrs[cnt], &uc_events[cnt]) != 0) return -1; - } } return 0; @@ -297,10 +283,8 @@ static int gator_events_perf_pmu_start(void) static void __event_stop(struct gator_event *const event) { - if (event->pevent_attr) { - kfree(event->pevent_attr); - event->pevent_attr = NULL; - } + kfree(event->pevent_attr); + event->pevent_attr = NULL; } static void __attr_stop(struct gator_attr *const attr) @@ -315,29 +299,25 @@ static void gator_events_perf_pmu_stop(void) unsigned int cnt, cpu; for_each_present_cpu(cpu) { - for (cnt = 0; cnt < attr_count; cnt++) { + for (cnt = 0; cnt < attr_count; cnt++) __event_stop(&per_cpu(events, cpu)[cnt]); - } } - for (cnt = 0; cnt < uc_attr_count; cnt++) { + for (cnt = 0; cnt < uc_attr_count; cnt++) __event_stop(&uc_events[cnt]); - } - for (cnt = 0; cnt < attr_count; cnt++) { + for (cnt = 0; cnt < attr_count; cnt++) __attr_stop(&attrs[cnt]); - } - for (cnt = 0; cnt < uc_attr_count; cnt++) { + for (cnt = 0; cnt < uc_attr_count; cnt++) __attr_stop(&uc_attrs[cnt]); - } } static void __read(int *const len, int cpu, struct gator_attr *const attr, struct gator_event *const event) { int delta; - struct perf_event *const ev = event->pevent; + if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) { /* After creating the perf counter in __online_dispatch, there * is a race condition between gator_events_perf_pmu_online and @@ -361,33 +341,29 @@ static void __read(int *const len, int cpu, struct gator_attr *const attr, struc event->prev_delta = delta; event->prev = event->curr; per_cpu(perf_cnt, cpu)[(*len)++] = attr->key; - if (delta < 0) { + if (delta < 0) delta *= -1; - } per_cpu(perf_cnt, cpu)[(*len)++] = delta; } } } } -static int gator_events_perf_pmu_read(int **buffer) +static int gator_events_perf_pmu_read(int **buffer, bool sched_switch) { int cnt, len = 0; const int cpu = get_logical_cpu(); - for (cnt = 0; cnt < attr_count; cnt++) { + for (cnt = 0; cnt < attr_count; cnt++) __read(&len, cpu, &attrs[cnt], &per_cpu(events, cpu)[cnt]); - } if (cpu == 0) { - for (cnt = 0; cnt < uc_attr_count; cnt++) { + for (cnt = 0; cnt < uc_attr_count; cnt++) __read(&len, cpu, &uc_attrs[cnt], &uc_events[cnt]); - } } - if (buffer) { + if (buffer) *buffer = per_cpu(perf_cnt, cpu); - } return len; } @@ -428,23 +404,20 @@ static int probe_cci_revision(void) int ret = DEFAULT_CCI_REVISION; np = of_find_matching_node(NULL, arm_cci_matches); - if (!np) { + if (!np) return ret; - } - if (of_address_to_resource(np, 0, &res)) { + if (of_address_to_resource(np, 0, &res)) goto node_put; - } cci_ctrl_base = ioremap(res.start, resource_size(&res)); rev = (readl_relaxed(cci_ctrl_base + 0xfe8) >> 4) & 0xf; - if (rev <= 4) { + if (rev <= 4) ret = 0; - } else if (rev <= 6) { + else if (rev <= 6) ret = 1; - } iounmap(cci_ctrl_base); @@ -463,9 +436,24 @@ static int probe_cci_revision(void) #endif -static void gator_events_perf_pmu_cci_init(const int type) +static void gator_events_perf_pmu_uncore_init(const char *const name, const int type, const int count) { int cnt; + + snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", name); + uc_attrs[uc_attr_count].type = type; + ++uc_attr_count; + + for (cnt = 0; cnt < count; ++cnt, ++uc_attr_count) { + struct gator_attr *const attr = &uc_attrs[uc_attr_count]; + + snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", name, cnt); + attr->type = type; + } +} + +static void gator_events_perf_pmu_cci_init(const int type) +{ const char *cci_name; switch (probe_cci_revision()) { @@ -480,15 +468,7 @@ static void gator_events_perf_pmu_cci_init(const int type) return; } - snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", cci_name); - uc_attrs[uc_attr_count].type = type; - ++uc_attr_count; - - for (cnt = 0; cnt < CCI_400; ++cnt, ++uc_attr_count) { - struct gator_attr *const attr = &uc_attrs[uc_attr_count]; - snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", cci_name, cnt); - attr->type = type; - } + gator_events_perf_pmu_uncore_init(cci_name, type, CCI_400); } static void gator_events_perf_pmu_cpu_init(const struct gator_cpu *const gator_cpu, const int type) @@ -501,6 +481,7 @@ static void gator_events_perf_pmu_cpu_init(const struct gator_cpu *const gator_c for (cnt = 0; cnt < gator_cpu->pmnc_counters; ++cnt, ++attr_count) { struct gator_attr *const attr = &attrs[attr_count]; + snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", gator_cpu->pmnc_name, cnt); attr->type = type; } @@ -516,12 +497,10 @@ int gator_events_perf_pmu_init(void) int cnt; bool found_cpu = false; - for (cnt = 0; cnt < CNTMAX; cnt++) { + for (cnt = 0; cnt < CNTMAX; cnt++) __attr_init(&attrs[cnt]); - } - for (cnt = 0; cnt < UCCNT; cnt++) { + for (cnt = 0; cnt < UCCNT; cnt++) __attr_init(&uc_attrs[cnt]); - } memset(&pea, 0, sizeof(pea)); pea.size = sizeof(pea); @@ -531,7 +510,7 @@ int gator_events_perf_pmu_init(void) for (type = PERF_TYPE_MAX; type < 0x20; ++type) { pea.type = type; - // A particular PMU may work on some but not all cores, so try on each core + /* A particular PMU may work on some but not all cores, so try on each core */ pe = NULL; for_each_present_cpu(cpu) { #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) @@ -539,23 +518,31 @@ int gator_events_perf_pmu_init(void) #else pe = perf_event_create_kernel_counter(&pea, cpu, 0, dummy_handler, 0); #endif - if (!IS_ERR(pe)) { + if (!IS_ERR(pe)) break; - } } - // Assume that valid PMUs are contiguous + /* Assume that valid PMUs are contiguous */ if (IS_ERR(pe)) { - break; + pea.config = 0xff00; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) + pe = perf_event_create_kernel_counter(&pea, 0, 0, dummy_handler); +#else + pe = perf_event_create_kernel_counter(&pea, 0, 0, dummy_handler, 0); +#endif + if (IS_ERR(pe)) + break; } if (pe->pmu != NULL && type == pe->pmu->type) { if (strcmp("CCI", pe->pmu->name) == 0 || strcmp("CCI_400", pe->pmu->name) == 0 || strcmp("CCI_400-r1", pe->pmu->name) == 0) { gator_events_perf_pmu_cci_init(type); + } else if (strcmp("ccn", pe->pmu->name) == 0) { + gator_events_perf_pmu_uncore_init("ARM_CCN_5XX", type, CCN_5XX); } else if ((gator_cpu = gator_find_cpu_by_pmu_name(pe->pmu->name)) != NULL) { found_cpu = true; gator_events_perf_pmu_cpu_init(gator_cpu, type); } - // Initialize gator_attrs for dynamic PMUs here + /* Initialize gator_attrs for dynamic PMUs here */ } perf_event_release_kernel(pe); @@ -563,21 +550,21 @@ int gator_events_perf_pmu_init(void) if (!found_cpu) { const struct gator_cpu *const gator_cpu = gator_find_cpu_by_cpuid(gator_cpuid()); - if (gator_cpu == NULL) { + + if (gator_cpu == NULL) return -1; - } gator_events_perf_pmu_cpu_init(gator_cpu, PERF_TYPE_RAW); } - // Initialize gator_attrs for non-dynamic PMUs here + /* Initialize gator_attrs for non-dynamic PMUs here */ if (attr_count > CNTMAX) { - printk(KERN_ERR "gator: Too many perf counters\n"); + pr_err("gator: Too many perf counters\n"); return -1; } if (uc_attr_count > UCCNT) { - printk(KERN_ERR "gator: Too many perf uncore counters\n"); + pr_err("gator: Too many perf uncore counters\n"); return -1; } diff --git a/driver/gator_events_sched.c b/driver/gator_events_sched.c index 9e39158..637107d 100644 --- a/driver/gator_events_sched.c +++ b/driver/gator_events_sched.c @@ -26,8 +26,9 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_ { unsigned long flags; - // disable interrupts to synchronize with gator_events_sched_read() - // spinlocks not needed since percpu buffers are used + /* disable interrupts to synchronize with gator_events_sched_read() + * spinlocks not needed since percpu buffers are used + */ local_irq_save(flags); per_cpu(schedCnt, get_physical_cpu())[SCHED_SWITCH]++; local_irq_restore(flags); @@ -39,9 +40,8 @@ static int gator_events_sched_create_files(struct super_block *sb, struct dentry /* switch */ dir = gatorfs_mkdir(sb, root, "Linux_sched_switch"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &sched_switch_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &sched_switch_key); @@ -50,7 +50,7 @@ static int gator_events_sched_create_files(struct super_block *sb, struct dentry static int gator_events_sched_start(void) { - // register tracepoints + /* register tracepoints */ if (sched_switch_enabled) if (GATOR_REGISTER_TRACE(sched_switch)) goto sched_switch_exit; @@ -58,7 +58,7 @@ static int gator_events_sched_start(void) return 0; - // unregister tracepoints on error + /* unregister tracepoints on error */ sched_switch_exit: pr_err("gator: scheduler event tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n"); @@ -74,7 +74,7 @@ static void gator_events_sched_stop(void) sched_switch_enabled = 0; } -static int gator_events_sched_read(int **buffer) +static int gator_events_sched_read(int **buffer, bool sched_switch) { unsigned long flags; int len, value; diff --git a/driver/gator_events_scorpion.c b/driver/gator_events_scorpion.c index 2e5be8d..4921936 100644 --- a/driver/gator_events_scorpion.c +++ b/driver/gator_events_scorpion.c @@ -8,13 +8,13 @@ #include "gator.h" -// gator_events_perf_pmu.c is used if perf is supported +/* gator_events_perf_pmu.c is used if perf is supported */ #if GATOR_NO_PERF_SUPPORT static const char *pmnc_name; static int pmnc_counters; -// Per-CPU PMNC: config reg +/* Per-CPU PMNC: config reg */ #define PMNC_E (1 << 0) /* Enable all counters */ #define PMNC_P (1 << 1) /* Reset all counters */ #define PMNC_C (1 << 2) /* Cycle counter reset */ @@ -23,7 +23,7 @@ static int pmnc_counters; #define PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug */ #define PMNC_MASK 0x3f /* Mask for writable bits */ -// ccnt reg +/* ccnt reg */ #define CCNT_REG (1 << 31) #define CCNT 0 @@ -243,6 +243,7 @@ static inline void scorpion_pmnc_write(u32 val) static inline u32 scorpion_pmnc_read(void) { u32 val; + asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val)); return val; } @@ -250,6 +251,7 @@ static inline u32 scorpion_pmnc_read(void) static inline u32 scorpion_ccnt_read(void) { u32 val; + asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); return val; } @@ -257,6 +259,7 @@ static inline u32 scorpion_ccnt_read(void) static inline u32 scorpion_cntn_read(void) { u32 val; + asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val)); return val; } @@ -317,6 +320,7 @@ static inline int scorpion_pmnc_select_counter(unsigned int cnt) static u32 scorpion_read_lpm0(void) { u32 val; + asm volatile("mrc p15, 0, %0, c15, c0, 0" : "=r" (val)); return val; } @@ -329,6 +333,7 @@ static void scorpion_write_lpm0(u32 val) static u32 scorpion_read_lpm1(void) { u32 val; + asm volatile("mrc p15, 1, %0, c15, c0, 0" : "=r" (val)); return val; } @@ -341,6 +346,7 @@ static void scorpion_write_lpm1(u32 val) static u32 scorpion_read_lpm2(void) { u32 val; + asm volatile("mrc p15, 2, %0, c15, c0, 0" : "=r" (val)); return val; } @@ -353,6 +359,7 @@ static void scorpion_write_lpm2(u32 val) static u32 scorpion_read_l2lpm(void) { u32 val; + asm volatile("mrc p15, 3, %0, c15, c2, 0" : "=r" (val)); return val; } @@ -365,6 +372,7 @@ static void scorpion_write_l2lpm(u32 val) static u32 scorpion_read_vlpm(void) { u32 val; + asm volatile("mrc p10, 7, %0, c11, c0, 0" : "=r" (val)); return val; } @@ -375,7 +383,7 @@ static void scorpion_write_vlpm(u32 val) } struct scorpion_access_funcs { - u32(*read)(void); + u32 (*read)(void); void (*write)(u32); }; @@ -420,17 +428,17 @@ static u32 scorpion_get_columnmask(u32 setval) { if (setval & COLMN0MASK) return 0xffffff00; - else if (setval & COLMN1MASK) + if (setval & COLMN1MASK) return 0xffff00ff; - else if (setval & COLMN2MASK) + if (setval & COLMN2MASK) return 0xff00ffff; - else - return 0x80ffffff; + return 0x80ffffff; } static void scorpion_evt_setup(u32 gr, u32 setval) { u32 val; + if (gr == 4) scorpion_pre_vlpm(); val = scorpion_get_columnmask(setval) & scor_func[gr].read(); @@ -443,6 +451,7 @@ static void scorpion_evt_setup(u32 gr, u32 setval) static int get_scorpion_evtinfo(unsigned int evt_type, struct scorp_evt *evtinfo) { u32 idx; + if ((evt_type < 0x4c) || (evt_type >= MSM_MAX_EVT)) return 0; idx = evt_type - 0x4c; @@ -463,7 +472,7 @@ static inline void scorpion_pmnc_write_evtsel(unsigned int cnt, u32 val) } else { u32 zero = 0; struct scorp_evt evtinfo; - // extract evtinfo.grp and evtinfo.tevt_type_act from val + /* extract evtinfo.grp and evtinfo.tevt_type_act from val */ if (get_scorpion_evtinfo(val, &evtinfo) == 0) return; asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (evtinfo.evt_type_act)); @@ -505,20 +514,18 @@ static int gator_events_scorpion_create_files(struct super_block *sb, struct den for (i = 0; i < pmnc_counters; i++) { char buf[40]; - if (i == 0) { - snprintf(buf, sizeof buf, "%s_ccnt", pmnc_name); - } else { - snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i - 1); - } + + if (i == 0) + snprintf(buf, sizeof(buf), "%s_ccnt", pmnc_name); + else + snprintf(buf, sizeof(buf), "%s_cnt%d", pmnc_name, i - 1); dir = gatorfs_mkdir(sb, root, buf); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]); gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]); - if (i > 0) { + if (i > 0) gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]); - } } return 0; @@ -528,9 +535,8 @@ static int gator_events_scorpion_online(int **buffer, bool migrate) { unsigned int cnt, len = 0, cpu = smp_processor_id(); - if (scorpion_pmnc_read() & PMNC_E) { + if (scorpion_pmnc_read() & PMNC_E) scorpion_pmnc_write(scorpion_pmnc_read() & ~PMNC_E); - } /* Initialize & Reset PMNC: C bit and P bit */ scorpion_pmnc_write(PMNC_P | PMNC_C); @@ -541,33 +547,32 @@ static int gator_events_scorpion_online(int **buffer, bool migrate) if (!pmnc_enabled[cnt]) continue; - // disable counter + /* disable counter */ scorpion_pmnc_disable_counter(cnt); event = pmnc_event[cnt] & 255; - // Set event (if destined for PMNx counters), We don't need to set the event if it's a cycle count + /* Set event (if destined for PMNx counters), We don't need to set the event if it's a cycle count */ if (cnt != CCNT) scorpion_pmnc_write_evtsel(cnt, event); - // reset counter + /* reset counter */ scorpion_pmnc_reset_counter(cnt); - // Enable counter, do not enable interrupt for this counter + /* Enable counter, do not enable interrupt for this counter */ scorpion_pmnc_enable_counter(cnt); } - // enable + /* enable */ scorpion_pmnc_write(scorpion_pmnc_read() | PMNC_E); - // read the counters and toss the invalid data, return zero instead + /* read the counters and toss the invalid data, return zero instead */ for (cnt = 0; cnt < pmnc_counters; cnt++) { if (pmnc_enabled[cnt]) { - if (cnt == CCNT) { + if (cnt == CCNT) scorpion_ccnt_read(); - } else if (scorpion_pmnc_select_counter(cnt) == cnt) { + else if (scorpion_pmnc_select_counter(cnt) == cnt) scorpion_cntn_read(); - } scorpion_pmnc_reset_counter(cnt); per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt]; @@ -597,26 +602,25 @@ static void gator_events_scorpion_stop(void) } } -static int gator_events_scorpion_read(int **buffer) +static int gator_events_scorpion_read(int **buffer, bool sched_switch) { int cnt, len = 0; int cpu = smp_processor_id(); - // a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled - if (!(scorpion_pmnc_read() & PMNC_E)) { + /* a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled */ + if (!(scorpion_pmnc_read() & PMNC_E)) return 0; - } for (cnt = 0; cnt < pmnc_counters; cnt++) { if (pmnc_enabled[cnt]) { int value; - if (cnt == CCNT) { + + if (cnt == CCNT) value = scorpion_ccnt_read(); - } else if (scorpion_pmnc_select_counter(cnt) == cnt) { + else if (scorpion_pmnc_select_counter(cnt) == cnt) value = scorpion_cntn_read(); - } else { + else value = 0; - } scorpion_pmnc_reset_counter(cnt); per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt]; @@ -655,7 +659,8 @@ int gator_events_scorpion_init(void) return -1; } - pmnc_counters++; // CNT[n] + CCNT + /* CNT[n] + CCNT */ + pmnc_counters++; for (cnt = CCNT; cnt < CNTMAX; cnt++) { pmnc_enabled[cnt] = 0; diff --git a/driver/gator_events_threads.c b/driver/gator_events_threads.c deleted file mode 100644 index 9de8586..0000000 --- a/driver/gator_events_threads.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Sample activity provider - * - * Copyright (C) ARM Limited 2014. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * See gator_events_mmapped.c for additional directions and - * troubleshooting. - * - * For this sample to work these entries must be present in the - * events.xml file. So create an events-threads.xml in the gator - * daemon source directory with the following contents and rebuild - * gatord: - * - * <category name="threads"> - * <event counter="Linux_threads" title="Linux" name="Threads" class="activity" activity1="odd" activity_color1="0x000000ff" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" description="Linux syscall activity"/> - * </category> - */ - -#include <trace/events/sched.h> - -#include "gator.h" - -static ulong threads_enabled; -static ulong threads_key; -static ulong threads_cores; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) -GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next)) -#else -GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_struct *next)) -#endif -{ - int cpu = get_physical_cpu(); - int pid = next->pid; - if (pid == 0) { - // idle - gator_marshal_activity_switch(cpu, threads_key, 0, 0); - } else if (pid & 1) { - // odd - gator_marshal_activity_switch(cpu, threads_key, 1, pid); - } else { - // even - //gator_marshal_activity_switch(cpu, threads_key, 2, current->pid); - // Multiple activities are not yet supported so emit idle - gator_marshal_activity_switch(cpu, threads_key, 0, 0); - } -} - -// Adds Linux_threads directory and enabled, key, and cores files to /dev/gator/events -static int gator_events_threads_create_files(struct super_block *sb, struct dentry *root) -{ - struct dentry *dir; - - dir = gatorfs_mkdir(sb, root, "Linux_threads"); - if (!dir) { - return -1; - } - gatorfs_create_ulong(sb, dir, "enabled", &threads_enabled); - gatorfs_create_ro_ulong(sb, dir, "key", &threads_key); - // Number of cores associated with this activity - gatorfs_create_ro_ulong(sb, dir, "cores", &threads_cores); - - return 0; -} - -static int gator_events_threads_start(void) -{ - int cpu; - - if (threads_enabled) { - preempt_disable(); - for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { - gator_marshal_activity_switch(cpu, threads_key, 0, 0); - } - preempt_enable(); - - if (GATOR_REGISTER_TRACE(sched_switch)) { - goto fail_sched_switch; - } - } - - return 0; - -fail_sched_switch: - return -1; -} - -static void gator_events_threads_stop(void) -{ - if (threads_enabled) { - GATOR_UNREGISTER_TRACE(sched_switch); - } - - threads_enabled = 0; -} - -static struct gator_interface gator_events_threads_interface = { - .create_files = gator_events_threads_create_files, - .start = gator_events_threads_start, - .stop = gator_events_threads_stop, -}; - -// Must not be static. Ensure that this init function is added to GATOR_EVENTS_LIST in gator_main.c -int __init gator_events_threads_init(void) -{ - threads_enabled = 0; - threads_key = gator_events_get_key(); - threads_cores = nr_cpu_ids; - - return gator_events_install(&gator_events_threads_interface); -} diff --git a/driver/gator_fs.c b/driver/gator_fs.c index 166cfe7..d8fb357 100644 --- a/driver/gator_fs.c +++ b/driver/gator_fs.c @@ -14,7 +14,7 @@ #include <linux/module.h> #include <linux/fs.h> #include <linux/pagemap.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #define gatorfs_MAGIC 0x24051020 #define TMPBUFSIZE 50 @@ -43,6 +43,7 @@ static ssize_t gatorfs_ulong_to_user(unsigned long val, char __user *buf, size_t { char tmpbuf[TMPBUFSIZE]; size_t maxlen = snprintf(tmpbuf, TMPBUFSIZE, "%lu\n", val); + if (maxlen > TMPBUFSIZE) maxlen = TMPBUFSIZE; return simple_read_from_buffer(buf, count, offset, tmpbuf, maxlen); @@ -52,6 +53,7 @@ static ssize_t gatorfs_u64_to_user(u64 val, char __user *buf, size_t count, loff { char tmpbuf[TMPBUFSIZE]; size_t maxlen = snprintf(tmpbuf, TMPBUFSIZE, "%llu\n", val); + if (maxlen > TMPBUFSIZE) maxlen = TMPBUFSIZE; return simple_read_from_buffer(buf, count, offset, tmpbuf, maxlen); @@ -104,12 +106,14 @@ static int gatorfs_u64_from_user(u64 *val, char const __user *buf, size_t count) static ssize_t ulong_read_file(struct file *file, char __user *buf, size_t count, loff_t *offset) { unsigned long *val = file->private_data; + return gatorfs_ulong_to_user(*val, buf, count, offset); } static ssize_t u64_read_file(struct file *file, char __user *buf, size_t count, loff_t *offset) { u64 *val = file->private_data; + return gatorfs_u64_to_user(*val, buf, count, offset); } @@ -231,7 +235,7 @@ int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root, } static int gatorfs_create_ro_u64(struct super_block *sb, struct dentry *root, - char const *name, u64 * val) + char const *name, u64 *val) { struct dentry *d = __gatorfs_create_file(sb, root, name, &u64_ro_fops, 0444); @@ -245,6 +249,7 @@ static int gatorfs_create_ro_u64(struct super_block *sb, struct dentry *root, static ssize_t atomic_read_file(struct file *file, char __user *buf, size_t count, loff_t *offset) { atomic_t *val = file->private_data; + return gatorfs_ulong_to_user(atomic_read(val), buf, count, offset); } diff --git a/driver/gator_hrtimer_gator.c b/driver/gator_hrtimer_gator.c index 7658455..c1525e1 100644 --- a/driver/gator_hrtimer_gator.c +++ b/driver/gator_hrtimer_gator.c @@ -18,6 +18,7 @@ static void gator_hrtimer_offline(void); static enum hrtimer_restart gator_hrtimer_notify(struct hrtimer *hrtimer) { int cpu = get_logical_cpu(); + hrtimer_forward(hrtimer, per_cpu(hrtimer_expire, cpu), profiling_interval); per_cpu(hrtimer_expire, cpu) = ktime_add(per_cpu(hrtimer_expire, cpu), profiling_interval); (*callback)(); @@ -64,12 +65,11 @@ static int gator_hrtimer_init(int interval, void (*func)(void)) per_cpu(hrtimer_is_active, cpu) = 0; } - // calculate profiling interval - if (interval > 0) { + /* calculate profiling interval */ + if (interval > 0) profiling_interval = ns_to_ktime(1000000000UL / interval); - } else { + else profiling_interval.tv64 = 0; - } return 0; } diff --git a/driver/gator_iks.c b/driver/gator_iks.c index 9180b87..fb78c10 100644 --- a/driver/gator_iks.c +++ b/driver/gator_iks.c @@ -16,7 +16,7 @@ static bool map_cpuids; static int mpidr_cpuids[NR_CPUS]; -static const struct gator_cpu * mpidr_cpus[NR_CPUS]; +static const struct gator_cpu *mpidr_cpus[NR_CPUS]; static int __lcpu_to_pcpu[NR_CPUS]; static const struct gator_cpu *gator_find_cpu_by_dt_name(const char *const name) @@ -25,9 +25,9 @@ static const struct gator_cpu *gator_find_cpu_by_dt_name(const char *const name) for (i = 0; gator_cpus[i].cpuid != 0; ++i) { const struct gator_cpu *const gator_cpu = &gator_cpus[i]; - if (gator_cpu->dt_name != NULL && strcmp(gator_cpu->dt_name, name) == 0) { + + if (gator_cpu->dt_name != NULL && strcmp(gator_cpu->dt_name, name) == 0) return gator_cpu; - } } return NULL; @@ -41,7 +41,7 @@ static void calc_first_cluster_size(void) struct device_node *cn = NULL; int mpidr_cpuids_count = 0; - // Zero is a valid cpuid, so initialize the array to 0xff's + /* Zero is a valid cpuid, so initialize the array to 0xff's */ memset(&mpidr_cpuids, 0xff, sizeof(mpidr_cpuids)); memset(&mpidr_cpus, 0, sizeof(mpidr_cpus)); @@ -70,10 +70,10 @@ static void calc_first_cluster_size(void) static int linearize_mpidr(int mpidr) { int i; + for (i = 0; i < nr_cpu_ids; ++i) { - if (mpidr_cpuids[i] == mpidr) { + if (mpidr_cpuids[i] == mpidr) return i; - } } BUG(); @@ -113,6 +113,7 @@ static void gator_update_cpu_mapping(u32 cpu_hwid) { int lcpu = smp_processor_id(); int pcpu = linearize_mpidr(cpu_hwid & MPIDR_HWID_BITMASK); + BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0); BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0); __lcpu_to_pcpu[lcpu] = pcpu; @@ -132,7 +133,7 @@ GATOR_DEFINE_PROBE(cpu_migrate_finish, TP_PROTO(u64 timestamp, u32 cpu_hwid)) gator_update_cpu_mapping(cpu_hwid); - // get_physical_cpu must be called after gator_update_cpu_mapping + /* get_physical_cpu must be called after gator_update_cpu_mapping */ cpu = get_physical_cpu(); gator_timer_online_dispatch(cpu, true); gator_timer_online((void *)1); @@ -146,12 +147,11 @@ GATOR_DEFINE_PROBE(cpu_migrate_current, TP_PROTO(u64 timestamp, u32 cpu_hwid)) static void gator_send_iks_core_names(void) { int cpu; - // Send the cpu names + /* Send the cpu names */ preempt_disable(); for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { - if (mpidr_cpus[cpu] != NULL) { + if (mpidr_cpus[cpu] != NULL) gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid); - } } preempt_enable(); } @@ -170,7 +170,7 @@ static int gator_migrate_start(void) if (retval == 0) retval = GATOR_REGISTER_TRACE(cpu_migrate_current); if (retval == 0) { - // Initialize the logical to physical cpu mapping + /* Initialize the logical to physical cpu mapping */ memset(&__lcpu_to_pcpu, 0xff, sizeof(__lcpu_to_pcpu)); bL_switcher_trace_trigger(); } diff --git a/driver/gator_main.c b/driver/gator_main.c index 03ca87e..30bf60d 100644 --- a/driver/gator_main.c +++ b/driver/gator_main.c @@ -7,8 +7,8 @@ * */ -// This version must match the gator daemon version -#define PROTOCOL_VERSION 19 +/* This version must match the gator daemon version */ +#define PROTOCOL_VERSION 20 static unsigned long gator_protocol_version = PROTOCOL_VERSION; #include <linux/slab.h> @@ -25,7 +25,7 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION; #include <linux/utsname.h> #include <linux/kthread.h> #include <asm/stacktrace.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include "gator.h" @@ -67,11 +67,11 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION; #define SUMMARY_BUFFER_SIZE (1*1024) #define BACKTRACE_BUFFER_SIZE (128*1024) #define NAME_BUFFER_SIZE (64*1024) -#define COUNTER_BUFFER_SIZE (64*1024) // counters have the core as part of the data and the core value in the frame header may be discarded +#define COUNTER_BUFFER_SIZE (64*1024) /* counters have the core as part of the data and the core value in the frame header may be discarded */ #define BLOCK_COUNTER_BUFFER_SIZE (128*1024) -#define ANNOTATE_BUFFER_SIZE (128*1024) // annotate counters have the core as part of the data and the core value in the frame header may be discarded +#define ANNOTATE_BUFFER_SIZE (128*1024) /* annotate counters have the core as part of the data and the core value in the frame header may be discarded */ #define SCHED_TRACE_BUFFER_SIZE (128*1024) -#define IDLE_BUFFER_SIZE (32*1024) // idle counters have the core as part of the data and the core value in the frame header may be discarded +#define IDLE_BUFFER_SIZE (32*1024) /* idle counters have the core as part of the data and the core value in the frame header may be discarded */ #define ACTIVITY_BUFFER_SIZE (128*1024) #define NO_COOKIE 0U @@ -89,24 +89,24 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION; #define MESSAGE_END_BACKTRACE 1 -// Name Frame Messages +/* Name Frame Messages */ #define MESSAGE_COOKIE 1 #define MESSAGE_THREAD_NAME 2 #define MESSAGE_LINK 4 -// Scheduler Trace Frame Messages +/* Scheduler Trace Frame Messages */ #define MESSAGE_SCHED_SWITCH 1 #define MESSAGE_SCHED_EXIT 2 -// Idle Frame Messages +/* Idle Frame Messages */ #define MESSAGE_IDLE_ENTER 1 #define MESSAGE_IDLE_EXIT 2 -// Summary Frame Messages +/* Summary Frame Messages */ #define MESSAGE_SUMMARY 1 #define MESSAGE_CORE_NAME 3 -// Activity Frame Messages +/* Activity Frame Messages */ #define MESSAGE_SWITCH 2 #define MESSAGE_EXIT 3 @@ -140,14 +140,15 @@ enum { * Globals ******************************************************************************/ static unsigned long gator_cpu_cores; -// Size of the largest buffer. Effectively constant, set in gator_op_create_files +/* Size of the largest buffer. Effectively constant, set in gator_op_create_files */ static unsigned long userspace_buffer_size; static unsigned long gator_backtrace_depth; -// How often to commit the buffers for live in nanoseconds +/* How often to commit the buffers for live in nanoseconds */ static u64 gator_live_rate; static unsigned long gator_started; static u64 gator_monotonic_started; +static u64 gator_sync_time; static u64 gator_hibernate_time; static unsigned long gator_buffer_opened; static unsigned long gator_timer_count; @@ -161,7 +162,7 @@ static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait); static DECLARE_WAIT_QUEUE_HEAD(gator_annotate_wait); static struct timer_list gator_buffer_wake_up_timer; static bool gator_buffer_wake_run; -// Initialize semaphore unlocked to initialize memory values +/* Initialize semaphore unlocked to initialize memory values */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) static DECLARE_MUTEX(gator_buffer_wake_sem); #else @@ -183,33 +184,43 @@ static DEFINE_PER_CPU(bool, in_scheduler_context); * Prototypes ******************************************************************************/ static u64 gator_get_time(void); +static void gator_emit_perf_time(u64 time); static void gator_op_create_files(struct super_block *sb, struct dentry *root); -// gator_buffer is protected by being per_cpu and by having IRQs disabled when writing to it. -// Most marshal_* calls take care of this except for marshal_cookie*, marshal_backtrace* and marshal_frame where the caller is responsible for doing so. -// No synchronization is needed with the backtrace buffer as it is per cpu and is only used from the hrtimer. -// The annotate_lock must be held when using the annotation buffer as it is not per cpu. -// collect_counters which is the sole writer to the block counter frame is additionally protected by the per cpu collecting flag +/* gator_buffer is protected by being per_cpu and by having IRQs + * disabled when writing to it. Most marshal_* calls take care of this + * except for marshal_cookie*, marshal_backtrace* and marshal_frame + * where the caller is responsible for doing so. No synchronization is + * needed with the backtrace buffer as it is per cpu and is only used + * from the hrtimer. The annotate_lock must be held when using the + * annotation buffer as it is not per cpu. collect_counters which is + * the sole writer to the block counter frame is additionally + * protected by the per cpu collecting flag. + */ -// Size of the buffer, must be a power of 2. Effectively constant, set in gator_op_setup. +/* Size of the buffer, must be a power of 2. Effectively constant, set in gator_op_setup. */ static uint32_t gator_buffer_size[NUM_GATOR_BUFS]; -// gator_buffer_size - 1, bitwise and with pos to get offset into the array. Effectively constant, set in gator_op_setup. +/* gator_buffer_size - 1, bitwise and with pos to get offset into the array. Effectively constant, set in gator_op_setup. */ static uint32_t gator_buffer_mask[NUM_GATOR_BUFS]; -// Read position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are read by userspace in userspace_buffer_read +/* Read position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are read by userspace in userspace_buffer_read */ static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_read); -// Write position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are written to the buffer +/* Write position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are written to the buffer */ static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_write); -// Commit position in the buffer. Initialized to zero in gator_op_setup and incremented after a frame is ready to be read by userspace +/* Commit position in the buffer. Initialized to zero in gator_op_setup and incremented after a frame is ready to be read by userspace */ static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_commit); -// If set to false, decreases the number of bytes returned by buffer_bytes_available. Set in buffer_check_space if no space is remaining. Initialized to true in gator_op_setup -// This means that if we run out of space, continue to report that no space is available until bytes are read by userspace +/* If set to false, decreases the number of bytes returned by + * buffer_bytes_available. Set in buffer_check_space if no space is + * remaining. Initialized to true in gator_op_setup. This means that + * if we run out of space, continue to report that no space is + * available until bytes are read by userspace + */ static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], buffer_space_available); -// The buffer. Allocated in gator_op_setup +/* The buffer. Allocated in gator_op_setup */ static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer); -// The time after which the buffer should be committed for live display +/* The time after which the buffer should be committed for live display */ static DEFINE_PER_CPU(u64, gator_buffer_commit_time); -// List of all gator events - new events must be added to this list +/* List of all gator events - new events must be added to this list */ #define GATOR_EVENTS_LIST \ GATOR_EVENT(gator_events_armv6_init) \ GATOR_EVENT(gator_events_armv7_init) \ @@ -226,7 +237,6 @@ static DEFINE_PER_CPU(u64, gator_buffer_commit_time); GATOR_EVENT(gator_events_perf_pmu_init) \ GATOR_EVENT(gator_events_sched_init) \ GATOR_EVENT(gator_events_scorpion_init) \ - GATOR_EVENT(gator_events_threads_init) \ #define GATOR_EVENT(EVENT_INIT) __weak int EVENT_INIT(void); GATOR_EVENTS_LIST @@ -315,13 +325,6 @@ static const struct gator_cpu gator_cpus[] = { .pmnc_counters = 6, }, { - .cpuid = CORTEX_A12, - .core_name = "Cortex-A12", - .pmnc_name = "ARMv7_Cortex_A12", - .dt_name = "arm,cortex-a12", - .pmnc_counters = 6, - }, - { .cpuid = CORTEX_A15, .core_name = "Cortex-A15", .pmnc_name = "ARMv7_Cortex_A15", @@ -400,23 +403,32 @@ const struct gator_cpu *gator_find_cpu_by_cpuid(const u32 cpuid) for (i = 0; gator_cpus[i].cpuid != 0; ++i) { const struct gator_cpu *const gator_cpu = &gator_cpus[i]; - if (gator_cpu->cpuid == cpuid) { + + if (gator_cpu->cpuid == cpuid) return gator_cpu; - } } return NULL; } +static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-"; +static const char NEW_PMU_PREFIX[] = "ARMv7_Cortex_"; + const struct gator_cpu *gator_find_cpu_by_pmu_name(const char *const name) { int i; for (i = 0; gator_cpus[i].cpuid != 0; ++i) { const struct gator_cpu *const gator_cpu = &gator_cpus[i]; - if (gator_cpu->pmnc_name != NULL && strcmp(gator_cpu->pmnc_name, name) == 0) { + + if (gator_cpu->pmnc_name != NULL && + /* Do the names match exactly? */ + (strcasecmp(gator_cpu->pmnc_name, name) == 0 || + /* Do these names match but have the old vs new prefix? */ + ((strncasecmp(name, OLD_PMU_PREFIX, sizeof(OLD_PMU_PREFIX) - 1) == 0 && + strncasecmp(gator_cpu->pmnc_name, NEW_PMU_PREFIX, sizeof(NEW_PMU_PREFIX) - 1) == 0 && + strcasecmp(name + sizeof(OLD_PMU_PREFIX) - 1, gator_cpu->pmnc_name + sizeof(NEW_PMU_PREFIX) - 1) == 0)))) return gator_cpu; - } } return NULL; @@ -445,16 +457,15 @@ static void gator_buffer_wake_up(unsigned long data) static int gator_buffer_wake_func(void *data) { for (;;) { - if (down_killable(&gator_buffer_wake_sem)) { + if (down_killable(&gator_buffer_wake_sem)) break; - } - // Eat up any pending events - while (!down_trylock(&gator_buffer_wake_sem)); + /* Eat up any pending events */ + while (!down_trylock(&gator_buffer_wake_sem)) + ; - if (!gator_buffer_wake_run) { + if (!gator_buffer_wake_run) break; - } gator_buffer_wake_up(0); } @@ -468,6 +479,7 @@ static int gator_buffer_wake_func(void *data) static bool buffer_commit_ready(int *cpu, int *buftype) { int cpu_x, x; + for_each_present_cpu(cpu_x) { for (x = 0; x < NUM_GATOR_BUFS; x++) if (per_cpu(gator_buffer_commit, cpu_x)[x] != per_cpu(gator_buffer_read, cpu_x)[x]) { @@ -487,6 +499,7 @@ static bool buffer_commit_ready(int *cpu, int *buftype) static void gator_timer_interrupt(void) { struct pt_regs *const regs = get_irq_regs(); + gator_backtrace_handler(regs); } @@ -495,15 +508,14 @@ void gator_backtrace_handler(struct pt_regs *const regs) u64 time = gator_get_time(); int cpu = get_physical_cpu(); - // Output backtrace + /* Output backtrace */ gator_add_sample(cpu, regs, time); - // Collect counters - if (!per_cpu(collecting, cpu)) { - collect_counters(time, NULL); - } + /* Collect counters */ + if (!per_cpu(collecting, cpu)) + collect_counters(time, current, false); - // No buffer flushing occurs during sched switch for RT-Preempt full. The block counter frame will be flushed by collect_counters, but the sched buffer needs to be explicitly flushed + /* No buffer flushing occurs during sched switch for RT-Preempt full. The block counter frame will be flushed by collect_counters, but the sched buffer needs to be explicitly flushed */ #ifdef CONFIG_PREEMPT_RT_FULL buffer_check(cpu, SCHED_TRACE_BUF, time); #endif @@ -511,7 +523,7 @@ void gator_backtrace_handler(struct pt_regs *const regs) static int gator_running; -// This function runs in interrupt context and on the appropriate core +/* This function runs in interrupt context and on the appropriate core */ static void gator_timer_offline(void *migrate) { struct gator_interface *gi; @@ -522,11 +534,10 @@ static void gator_timer_offline(void *migrate) gator_trace_sched_offline(); gator_trace_power_offline(); - if (!migrate) { + if (!migrate) gator_hrtimer_offline(); - } - // Offline any events and output counters + /* Offline any events and output counters */ time = gator_get_time(); if (marshal_event_header(time)) { list_for_each_entry(gi, &gator_events, list) { @@ -535,24 +546,23 @@ static void gator_timer_offline(void *migrate) marshal_event(len, buffer); } } - // Only check after writing all counters so that time and corresponding counters appear in the same frame + /* Only check after writing all counters so that time and corresponding counters appear in the same frame */ buffer_check(cpu, BLOCK_COUNTER_BUF, time); } - // Flush all buffers on this core + /* Flush all buffers on this core */ for (i = 0; i < NUM_GATOR_BUFS; i++) gator_commit_buffer(cpu, i, time); } -// This function runs in interrupt context and may be running on a core other than core 'cpu' +/* This function runs in interrupt context and may be running on a core other than core 'cpu' */ static void gator_timer_offline_dispatch(int cpu, bool migrate) { struct gator_interface *gi; list_for_each_entry(gi, &gator_events, list) { - if (gi->offline_dispatch) { + if (gi->offline_dispatch) gi->offline_dispatch(cpu, migrate); - } } } @@ -579,16 +589,15 @@ static void gator_send_core_name(const int cpu, const u32 cpuid) const char *core_name = NULL; char core_name_buf[32]; - // Save off this cpuid + /* Save off this cpuid */ gator_cpuids[cpu] = cpuid; if (gator_cpu != NULL) { core_name = gator_cpu->core_name; } else { - if (cpuid == -1) { + if (cpuid == -1) snprintf(core_name_buf, sizeof(core_name_buf), "Unknown"); - } else { + else snprintf(core_name_buf, sizeof(core_name_buf), "Unknown (0x%.3x)", cpuid); - } core_name = core_name_buf; } @@ -598,12 +607,12 @@ static void gator_send_core_name(const int cpu, const u32 cpuid) #endif } -static void gator_read_cpuid(void * arg) +static void gator_read_cpuid(void *arg) { gator_cpuids[get_physical_cpu()] = gator_cpuid(); } -// This function runs in interrupt context and on the appropriate core +/* This function runs in interrupt context and on the appropriate core */ static void gator_timer_online(void *migrate) { struct gator_interface *gi; @@ -611,12 +620,12 @@ static void gator_timer_online(void *migrate) int *buffer; u64 time; - // Send what is currently running on this core + /* Send what is currently running on this core */ marshal_sched_trace_switch(current->pid, 0); gator_trace_power_online(); - // online any events and output counters + /* online any events and output counters */ time = gator_get_time(); if (marshal_event_header(time)) { list_for_each_entry(gi, &gator_events, list) { @@ -625,26 +634,24 @@ static void gator_timer_online(void *migrate) marshal_event(len, buffer); } } - // Only check after writing all counters so that time and corresponding counters appear in the same frame + /* Only check after writing all counters so that time and corresponding counters appear in the same frame */ buffer_check(cpu, BLOCK_COUNTER_BUF, time); } - if (!migrate) { + if (!migrate) gator_hrtimer_online(); - } gator_send_core_name(cpu, gator_cpuid()); } -// This function runs in interrupt context and may be running on a core other than core 'cpu' +/* This function runs in interrupt context and may be running on a core other than core 'cpu' */ static void gator_timer_online_dispatch(int cpu, bool migrate) { struct gator_interface *gi; list_for_each_entry(gi, &gator_events, list) { - if (gi->online_dispatch) { + if (gi->online_dispatch) gi->online_dispatch(cpu, migrate); - } } } @@ -661,15 +668,14 @@ static int gator_timer_start(unsigned long sample_rate) gator_running = 1; - // event based sampling trumps hr timer based sampling - if (event_based_sampling) { + /* event based sampling trumps hr timer based sampling */ + if (event_based_sampling) sample_rate = 0; - } if (gator_hrtimer_init(sample_rate, gator_timer_interrupt) == -1) return -1; - // Send off the previously saved cpuids + /* Send off the previously saved cpuids */ for_each_present_cpu(cpu) { preempt_disable(); gator_send_core_name(cpu, gator_cpuids[cpu]); @@ -693,21 +699,24 @@ static u64 gator_get_time(void) u64 delta; int cpu = smp_processor_id(); - // Match clock_gettime(CLOCK_MONOTONIC_RAW, &ts) from userspace + /* Match clock_gettime(CLOCK_MONOTONIC_RAW, &ts) from userspace */ getrawmonotonic(&ts); timestamp = timespec_to_ns(&ts); - // getrawmonotonic is not monotonic on all systems. Detect and attempt to correct these cases. - // up to 0.5ms delta has been seen on some systems, which can skew Streamline data when viewing at high resolution. - // This doesn't work well with interrupts, but that it's OK - the real concern is to catch big jumps in time + /* getrawmonotonic is not monotonic on all systems. Detect and + * attempt to correct these cases. up to 0.5ms delta has been seen + * on some systems, which can skew Streamline data when viewing at + * high resolution. This doesn't work well with interrupts, but that + * it's OK - the real concern is to catch big jumps in time + */ prev_timestamp = per_cpu(last_timestamp, cpu); if (prev_timestamp <= timestamp) { per_cpu(last_timestamp, cpu) = timestamp; } else { delta = prev_timestamp - timestamp; - // Log the error once + /* Log the error once */ if (!printed_monotonic_warning && delta > 500000) { - printk(KERN_ERR "%s: getrawmonotonic is not monotonic cpu: %i delta: %lli\nSkew in Streamline data may be present at the fine zoom levels\n", __FUNCTION__, cpu, delta); + pr_err("%s: getrawmonotonic is not monotonic cpu: %i delta: %lli\nSkew in Streamline data may be present at the fine zoom levels\n", __func__, cpu, delta); printed_monotonic_warning = true; } timestamp = prev_timestamp; @@ -716,6 +725,19 @@ static u64 gator_get_time(void) return timestamp - gator_monotonic_started; } +static void gator_emit_perf_time(u64 time) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) + if (time >= gator_sync_time) { + int cpu = get_physical_cpu(); + + marshal_event_single64(0, -1, local_clock()); + gator_sync_time += NSEC_PER_SEC; + gator_commit_buffer(cpu, COUNTER_BUF, time); + } +#endif +} + /****************************************************************************** * cpu hotplug and pm notifiers ******************************************************************************/ @@ -743,8 +765,10 @@ static struct notifier_block __refdata gator_hotcpu_notifier = { .notifier_call = gator_hotcpu_notify, }; -// n.b. calling "on_each_cpu" only runs on those that are online -// Registered linux events are not disabled, so their counters will continue to collect +/* n.b. calling "on_each_cpu" only runs on those that are online. + * Registered linux events are not disabled, so their counters will + * continue to collect + */ static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy) { int cpu; @@ -760,13 +784,13 @@ static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void gator_timer_offline_dispatch(lcpu_to_pcpu(cpu), false); } - // Record the wallclock hibernate time + /* Record the wallclock hibernate time */ getnstimeofday(&ts); gator_hibernate_time = timespec_to_ns(&ts) - gator_get_time(); break; case PM_POST_HIBERNATION: case PM_POST_SUSPEND: - // Adjust gator_monotonic_started for the time spent sleeping, as gator_get_time does not account for it + /* Adjust gator_monotonic_started for the time spent sleeping, as gator_get_time does not account for it */ if (gator_hibernate_time > 0) { getnstimeofday(&ts); gator_monotonic_started += gator_hibernate_time + gator_get_time() - timespec_to_ns(&ts); @@ -792,6 +816,7 @@ static struct notifier_block gator_pm_notifier = { static int gator_notifier_start(void) { int retval; + retval = register_hotcpu_notifier(&gator_hotcpu_notifier); if (retval == 0) retval = register_pm_notifier(&gator_pm_notifier); @@ -818,29 +843,31 @@ static void gator_summary(void) getnstimeofday(&ts); timestamp = timespec_to_ns(&ts); - // Similar to reading /proc/uptime from fs/proc/uptime.c, calculate uptime + /* Similar to reading /proc/uptime from fs/proc/uptime.c, calculate uptime */ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) { void (*m2b)(struct timespec *ts); + do_posix_clock_monotonic_gettime(&ts); - // monotonic_to_bootbased is not defined for some versions of Android + /* monotonic_to_bootbased is not defined for some versions of Android */ m2b = symbol_get(monotonic_to_bootbased); - if (m2b) { + if (m2b) m2b(&ts); - } } #else get_monotonic_boottime(&ts); #endif uptime = timespec_to_ns(&ts); - // Disable preemption as gator_get_time calls smp_processor_id to verify time is monotonic + /* Disable preemption as gator_get_time calls smp_processor_id to verify time is monotonic */ preempt_disable(); - // Set monotonic_started to zero as gator_get_time is uptime minus monotonic_started + /* Set monotonic_started to zero as gator_get_time is uptime minus monotonic_started */ gator_monotonic_started = 0; gator_monotonic_started = gator_get_time(); marshal_summary(timestamp, uptime, gator_monotonic_started, uname_buf); + gator_sync_time = 0; + gator_emit_perf_time(gator_monotonic_started); preempt_enable(); } @@ -853,12 +880,14 @@ int gator_events_install(struct gator_interface *interface) int gator_events_get_key(void) { - // key 0 is reserved as a timestamp - // key 1 is reserved as the marker for thread specific counters - // Odd keys are assigned by the driver, even keys by the daemon + /* key 0 is reserved as a timestamp. key 1 is reserved as the marker + * for thread specific counters. key 2 is reserved as the marker for + * core. Odd keys are assigned by the driver, even keys by the + * daemon. + */ static int key = 3; - const int ret = key; + key += 2; return ret; } @@ -869,7 +898,7 @@ static int gator_init(void) calc_first_cluster_size(); - // events sources + /* events sources */ for (i = 0; i < ARRAY_SIZE(gator_events_list); i++) if (gator_events_list[i]) gator_events_list[i](); @@ -895,26 +924,25 @@ static int gator_start(void) struct gator_interface *gi; gator_buffer_wake_run = true; - if (IS_ERR(gator_buffer_wake_thread = kthread_run(gator_buffer_wake_func, NULL, "gator_bwake"))) { + gator_buffer_wake_thread = kthread_run(gator_buffer_wake_func, NULL, "gator_bwake"); + if (IS_ERR(gator_buffer_wake_thread)) goto bwake_failure; - } if (gator_migrate_start()) goto migrate_failure; - // Initialize the buffer with the frame type and core + /* Initialize the buffer with the frame type and core */ for_each_present_cpu(cpu) { - for (i = 0; i < NUM_GATOR_BUFS; i++) { + for (i = 0; i < NUM_GATOR_BUFS; i++) marshal_frame(cpu, i); - } per_cpu(last_timestamp, cpu) = 0; } printed_monotonic_warning = false; - // Capture the start time + /* Capture the start time */ gator_summary(); - // start all events + /* start all events */ list_for_each_entry(gi, &gator_events, list) { if (gi->start && gi->start() != 0) { struct list_head *ptr = gi->list.prev; @@ -931,7 +959,7 @@ static int gator_start(void) } } - // cookies shall be initialized before trace_sched_start() and gator_timer_start() + /* cookies shall be initialized before trace_sched_start() and gator_timer_start() */ if (cookies_initialize()) goto cookies_failure; if (gator_annotate_start()) @@ -962,7 +990,7 @@ sched_failure: annotate_failure: cookies_release(); cookies_failure: - // stop all events + /* stop all events */ list_for_each_entry(gi, &gator_events, list) if (gi->stop) gi->stop(); @@ -986,11 +1014,11 @@ static void gator_stop(void) gator_trace_power_stop(); gator_trace_gpu_stop(); - // stop all interrupt callback reads before tearing down other interfaces - gator_notifier_stop(); // should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined + /* stop all interrupt callback reads before tearing down other interfaces */ + gator_notifier_stop(); /* should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined */ gator_timer_stop(); - // stop all events + /* stop all events */ list_for_each_entry(gi, &gator_events, list) if (gi->stop) gi->stop(); @@ -1040,9 +1068,9 @@ static int gator_op_setup(void) gator_buffer_size[ACTIVITY_BUF] = ACTIVITY_BUFFER_SIZE; gator_buffer_mask[ACTIVITY_BUF] = ACTIVITY_BUFFER_SIZE - 1; - // Initialize percpu per buffer variables + /* Initialize percpu per buffer variables */ for (i = 0; i < NUM_GATOR_BUFS; i++) { - // Verify buffers are a power of 2 + /* Verify buffers are a power of 2 */ if (gator_buffer_size[i] & (gator_buffer_size[i] - 1)) { err = -ENOEXEC; goto setup_error; @@ -1055,7 +1083,7 @@ static int gator_op_setup(void) per_cpu(buffer_space_available, cpu)[i] = true; per_cpu(gator_buffer_commit_time, cpu) = gator_live_rate; - // Annotation is a special case that only uses a single buffer + /* Annotation is a special case that only uses a single buffer */ if (cpu > 0 && i == ANNOTATE_BUF) { per_cpu(gator_buffer, cpu)[i] = NULL; continue; @@ -1195,7 +1223,8 @@ static int userspace_buffer_open(struct inode *inode, struct file *file) if (test_and_set_bit_lock(0, &gator_buffer_opened)) return -EBUSY; - if ((err = gator_op_setup())) + err = gator_op_setup(); + if (err) goto fail; /* NB: the actual start happens from userspace @@ -1225,22 +1254,20 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf, size_t int cpu, buftype; int written = 0; - // ensure there is enough space for a whole frame - if (count < userspace_buffer_size || *offset) { + /* ensure there is enough space for a whole frame */ + if (count < userspace_buffer_size || *offset) return -EINVAL; - } - // sleep until the condition is true or a signal is received - // the condition is checked each time gator_buffer_wait is woken up + /* sleep until the condition is true or a signal is received the + * condition is checked each time gator_buffer_wait is woken up + */ wait_event_interruptible(gator_buffer_wait, buffer_commit_ready(&cpu, &buftype) || !gator_started); - if (signal_pending(current)) { + if (signal_pending(current)) return -EINTR; - } - if (buftype == -1 || cpu == -1) { + if (buftype == -1 || cpu == -1) return 0; - } mutex_lock(&gator_buffer_mutex); @@ -1248,12 +1275,11 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf, size_t read = per_cpu(gator_buffer_read, cpu)[buftype]; commit = per_cpu(gator_buffer_commit, cpu)[buftype]; - // May happen if the buffer is freed during pending reads. - if (!per_cpu(gator_buffer, cpu)[buftype]) { + /* May happen if the buffer is freed during pending reads. */ + if (!per_cpu(gator_buffer, cpu)[buftype]) break; - } - // determine the size of two halves + /* determine the size of two halves */ length1 = commit - read; length2 = 0; buffer1 = &(per_cpu(gator_buffer, cpu)[buftype][read]); @@ -1263,32 +1289,28 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf, size_t length2 = commit; } - if (length1 + length2 > count - written) { + if (length1 + length2 > count - written) break; - } - // start, middle or end - if (length1 > 0 && copy_to_user(&buf[written], buffer1, length1)) { + /* start, middle or end */ + if (length1 > 0 && copy_to_user(&buf[written], buffer1, length1)) break; - } - // possible wrap around - if (length2 > 0 && copy_to_user(&buf[written + length1], buffer2, length2)) { + /* possible wrap around */ + if (length2 > 0 && copy_to_user(&buf[written + length1], buffer2, length2)) break; - } per_cpu(gator_buffer_read, cpu)[buftype] = commit; written += length1 + length2; - // Wake up annotate_write if more space is available - if (buftype == ANNOTATE_BUF) { + /* Wake up annotate_write if more space is available */ + if (buftype == ANNOTATE_BUF) wake_up(&gator_annotate_wait); - } } while (buffer_commit_ready(&cpu, &buftype)); mutex_unlock(&gator_buffer_mutex); - // kick just in case we've lost an SMP event + /* kick just in case we've lost an SMP event */ wake_up(&gator_buffer_wait); return written > 0 ? written : -EFAULT; @@ -1355,19 +1377,19 @@ static void gator_op_create_files(struct super_block *sb, struct dentry *root) gatorfs_create_ro_u64(sb, root, "started", &gator_monotonic_started); gatorfs_create_u64(sb, root, "live_rate", &gator_live_rate); - // Annotate interface + /* Annotate interface */ gator_annotate_create_files(sb, root); - // Linux Events + /* Linux Events */ dir = gatorfs_mkdir(sb, root, "events"); list_for_each_entry(gi, &gator_events, list) if (gi->create_files) gi->create_files(sb, dir); - // Sched Events + /* Sched Events */ sched_trace_create_files(sb, dir); - // Power interface + /* Power interface */ gator_trace_power_create_files(sb, dir); } @@ -1403,19 +1425,22 @@ static void gator_op_create_files(struct super_block *sb, struct dentry *root) GATOR_HANDLE_TRACEPOINT(sched_process_free); \ GATOR_HANDLE_TRACEPOINT(sched_switch); \ GATOR_HANDLE_TRACEPOINT(softirq_exit); \ + GATOR_HANDLE_TRACEPOINT(task_rename); \ #define GATOR_HANDLE_TRACEPOINT(probe_name) \ struct tracepoint *gator_tracepoint_##probe_name GATOR_TRACEPOINTS; #undef GATOR_HANDLE_TRACEPOINT -static void gator_fct(struct tracepoint *tp, void *priv) +static void gator_save_tracepoint(struct tracepoint *tp, void *priv) { #define GATOR_HANDLE_TRACEPOINT(probe_name) \ - if (strcmp(tp->name, #probe_name) == 0) { \ - gator_tracepoint_##probe_name = tp; \ - return; \ - } + do { \ + if (strcmp(tp->name, #probe_name) == 0) { \ + gator_tracepoint_##probe_name = tp; \ + return; \ + } \ + } while (0) GATOR_TRACEPOINTS; #undef GATOR_HANDLE_TRACEPOINT } @@ -1428,11 +1453,10 @@ GATOR_TRACEPOINTS; static int __init gator_module_init(void) { - for_each_kernel_tracepoint(gator_fct, NULL); + for_each_kernel_tracepoint(gator_save_tracepoint, NULL); - if (gatorfs_register()) { + if (gatorfs_register()) return -1; - } if (gator_init()) { gatorfs_unregister(); @@ -1441,7 +1465,7 @@ static int __init gator_module_init(void) setup_timer(&gator_buffer_wake_up_timer, gator_buffer_wake_up, 0); - // Initialize the list of cpuids + /* Initialize the list of cpuids */ memset(gator_cpuids, -1, sizeof(gator_cpuids)); on_each_cpu(gator_read_cpuid, NULL, 1); diff --git a/driver/gator_marshaling.c b/driver/gator_marshaling.c index 31af325..0d11676 100644 --- a/driver/gator_marshaling.c +++ b/driver/gator_marshaling.c @@ -23,7 +23,7 @@ #include "gator_events_mali_common.h" #endif -static void marshal_summary(long long timestamp, long long uptime, long long monotonic_delta, const char * uname) +static void marshal_summary(long long timestamp, long long uptime, long long monotonic_delta, const char *uname) { unsigned long flags; int cpu = 0; @@ -40,7 +40,15 @@ static void marshal_summary(long long timestamp, long long uptime, long long mon gator_buffer_write_string(cpu, SUMMARY_BUF, "iks"); gator_buffer_write_string(cpu, SUMMARY_BUF, ""); #endif - // Let Streamline know which GPU is used so that it can label the GPU Activity appropriately. This is a temporary fix, to be improved in a future release. +#ifdef CONFIG_PREEMPT_RTB + gator_buffer_write_string(cpu, SUMMARY_BUF, "preempt_rtb"); + gator_buffer_write_string(cpu, SUMMARY_BUF, ""); +#endif +#ifdef CONFIG_PREEMPT_RT_FULL + gator_buffer_write_string(cpu, SUMMARY_BUF, "preempt_rt_full"); + gator_buffer_write_string(cpu, SUMMARY_BUF, ""); +#endif + /* Let Streamline know which GPU is used so that it can label the GPU Activity appropriately. This is a temporary fix, to be improved in a future release. */ #ifdef MALI_SUPPORT gator_buffer_write_string(cpu, SUMMARY_BUF, "mali_type"); #if (MALI_SUPPORT == MALI_4xx) @@ -52,7 +60,7 @@ static void marshal_summary(long long timestamp, long long uptime, long long mon #endif #endif gator_buffer_write_string(cpu, SUMMARY_BUF, ""); - // Commit the buffer now so it can be one of the first frames read by Streamline + /* Commit the buffer now so it can be one of the first frames read by Streamline */ local_irq_restore(flags); gator_commit_buffer(cpu, SUMMARY_BUF, gator_get_time()); } @@ -60,13 +68,14 @@ static void marshal_summary(long long timestamp, long long uptime, long long mon static bool marshal_cookie_header(const char *text) { int cpu = get_physical_cpu(); + return buffer_check_space(cpu, NAME_BUF, strlen(text) + 3 * MAXSIZE_PACK32); } static void marshal_cookie(int cookie, const char *text) { int cpu = get_physical_cpu(); - // buffer_check_space already called by marshal_cookie_header + /* buffer_check_space already called by marshal_cookie_header */ gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_COOKIE); gator_buffer_write_packed_int(cpu, NAME_BUF, cookie); gator_buffer_write_string(cpu, NAME_BUF, text); @@ -77,6 +86,7 @@ static void marshal_thread_name(int pid, char *name) { unsigned long flags, cpu; u64 time; + local_irq_save(flags); cpu = get_physical_cpu(); time = gator_get_time(); @@ -105,15 +115,16 @@ static void marshal_link(int cookie, int tgid, int pid) gator_buffer_write_packed_int(cpu, NAME_BUF, pid); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, NAME_BUF, time); } static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, u64 time) { int cpu = get_physical_cpu(); + if (!buffer_check_space(cpu, BACKTRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32 + gator_backtrace_depth * 2 * MAXSIZE_PACK32)) { - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, BACKTRACE_BUF, time); return false; @@ -130,9 +141,9 @@ static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, u64 tim static void marshal_backtrace(unsigned long address, int cookie, int in_kernel) { int cpu = get_physical_cpu(); - if (cookie == 0 && !in_kernel) { + + if (cookie == 0 && !in_kernel) cookie = UNRESOLVED_COOKIE; - } gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie); gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, address); } @@ -140,9 +151,10 @@ static void marshal_backtrace(unsigned long address, int cookie, int in_kernel) static void marshal_backtrace_footer(u64 time) { int cpu = get_physical_cpu(); + gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_END_BACKTRACE); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, BACKTRACE_BUF, time); } @@ -153,7 +165,7 @@ static bool marshal_event_header(u64 time) local_irq_save(flags); if (buffer_check_space(cpu, BLOCK_COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) { - gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0); // key of zero indicates a timestamp + gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0); /* key of zero indicates a timestamp */ gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, time); retval = true; } @@ -169,18 +181,17 @@ static void marshal_event(int len, int *buffer) if (len <= 0) return; - // length must be even since all data is a (key, value) pair + /* length must be even since all data is a (key, value) pair */ if (len & 0x1) { - pr_err("gator: invalid counter data detected and discarded"); + pr_err("gator: invalid counter data detected and discarded\n"); return; } - // events must be written in key,value pairs + /* events must be written in key,value pairs */ local_irq_save(flags); for (i = 0; i < len; i += 2) { - if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK32)) { + if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK32)) break; - } gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i]); gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i + 1]); } @@ -194,26 +205,24 @@ static void marshal_event64(int len, long long *buffer64) if (len <= 0) return; - // length must be even since all data is a (key, value) pair + /* length must be even since all data is a (key, value) pair */ if (len & 0x1) { - pr_err("gator: invalid counter data detected and discarded"); + pr_err("gator: invalid counter data detected and discarded\n"); return; } - // events must be written in key,value pairs + /* events must be written in key,value pairs */ local_irq_save(flags); for (i = 0; i < len; i += 2) { - if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK64)) { + if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK64)) break; - } gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i]); gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i + 1]); } local_irq_restore(flags); } -#if GATOR_CPU_FREQ_SUPPORT -static void marshal_event_single(int core, int key, int value) +static void __maybe_unused marshal_event_single(int core, int key, int value) { unsigned long flags, cpu; u64 time; @@ -228,11 +237,11 @@ static void marshal_event_single(int core, int key, int value) gator_buffer_write_packed_int(cpu, COUNTER_BUF, value); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, COUNTER_BUF, time); } -static void marshal_event_single64(int core, int key, long long value) +static void __maybe_unused marshal_event_single64(int core, int key, long long value) { unsigned long flags, cpu; u64 time; @@ -247,10 +256,9 @@ static void marshal_event_single64(int core, int key, long long value) gator_buffer_write_packed_int64(cpu, COUNTER_BUF, value); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, COUNTER_BUF, time); } -#endif static void marshal_sched_trace_switch(int pid, int state) { @@ -269,7 +277,7 @@ static void marshal_sched_trace_switch(int pid, int state) gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, SCHED_TRACE_BUF, time); } @@ -289,7 +297,7 @@ static void marshal_sched_trace_exit(int tgid, int pid) gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, SCHED_TRACE_BUF, time); } @@ -308,7 +316,7 @@ static void marshal_idle(int core, int state) gator_buffer_write_packed_int(cpu, IDLE_BUF, core); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, IDLE_BUF, time); } #endif @@ -318,6 +326,7 @@ static void marshal_core_name(const int core, const int cpuid, const char *name) { int cpu = get_physical_cpu(); unsigned long flags; + local_irq_save(flags); if (buffer_check_space(cpu, SUMMARY_BUF, MAXSIZE_PACK32 + MAXSIZE_CORE_NAME)) { gator_buffer_write_packed_int(cpu, SUMMARY_BUF, MESSAGE_CORE_NAME); @@ -325,7 +334,7 @@ static void marshal_core_name(const int core, const int cpuid, const char *name) gator_buffer_write_packed_int(cpu, SUMMARY_BUF, cpuid); gator_buffer_write_string(cpu, SUMMARY_BUF, name); } - // Commit core names now so that they can show up in live + /* Commit core names now so that they can show up in live */ local_irq_restore(flags); gator_commit_buffer(cpu, SUMMARY_BUF, gator_get_time()); } @@ -351,12 +360,12 @@ static void marshal_activity_switch(int core, int key, int activity, int pid, in gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, state); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, ACTIVITY_BUF, time); } void gator_marshal_activity_switch(int core, int key, int activity, int pid) { - // state is reserved for cpu use only + /* state is reserved for cpu use only */ marshal_activity_switch(core, key, activity, pid, 0); } diff --git a/driver/gator_trace_gpu.c b/driver/gator_trace_gpu.c index fbfb275..5de9152 100644 --- a/driver/gator_trace_gpu.c +++ b/driver/gator_trace_gpu.c @@ -58,11 +58,12 @@ struct mali_activity { static struct mali_activity mali_activities[NUMBER_OF_GPU_UNITS*NUMBER_OF_GPU_CORES]; static DEFINE_SPINLOCK(mali_activities_lock); -/* Only one event should be running on a unit and core at a time (ie, a start - * event can only be followed by a stop and vice versa), but because the kernel - * only knows when a job is enqueued and not started, it is possible for a - * start1, start2, stop1, stop2. Change it back into start1, stop1, start2, - * stop2 by queueing up start2 and releasing it when stop1 is received. +/* Only one event should be running on a unit and core at a time (ie, + * a start event can only be followed by a stop and vice versa), but + * because the kernel only knows when a job is enqueued and not + * started, it is possible for a start1, start2, stop1, stop2. Change + * it back into start1, stop1, start2, stop2 by queueing up start2 and + * releasing it when stop1 is received. */ static int mali_activity_index(int core, int key) @@ -70,9 +71,8 @@ static int mali_activity_index(int core, int key) int i; for (i = 0; i < ARRAY_SIZE(mali_activities); ++i) { - if ((mali_activities[i].core == core) && (mali_activities[i].key == key)) { + if ((mali_activities[i].core == core) && (mali_activities[i].key == key)) break; - } if ((mali_activities[i].core == 0) && (mali_activities[i].key == 0)) { mali_activities[i].core = core; mali_activities[i].key = key; @@ -101,9 +101,8 @@ static void mali_activity_enqueue(int core, int key, int activity, int pid) } spin_unlock(&mali_activities_lock); - if (!count) { + if (!count) gator_marshal_activity_switch(core, key, activity, pid); - } } static void mali_activity_stop(int core, int key) @@ -129,12 +128,11 @@ static void mali_activity_stop(int core, int key) spin_unlock(&mali_activities_lock); gator_marshal_activity_switch(core, key, 0, 0); - if (count) { + if (count) gator_marshal_activity_switch(core, key, last_activity, last_pid); - } } -void mali_activity_clear(mali_counter mali_activity[], size_t mali_activity_size) +void mali_activity_clear(struct mali_counter mali_activity[], size_t mali_activity_size) { int activity; int cores; @@ -142,9 +140,8 @@ void mali_activity_clear(mali_counter mali_activity[], size_t mali_activity_size for (activity = 0; activity < mali_activity_size; ++activity) { cores = mali_activity[activity].cores; - if (cores < 0) { + if (cores < 0) cores = 1; - } for (core = 0; core < cores; ++core) { if (mali_activity[activity].enabled) { preempt_disable(); @@ -185,40 +182,36 @@ enum { EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1, }; -mali_counter mali_activity[2]; +struct mali_counter mali_activity[2]; GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned int d2, unsigned int d3, unsigned int d4)) { unsigned int component, state; - // do as much work as possible before disabling interrupts - component = (event_id >> 16) & 0xFF; // component is an 8-bit field - state = (event_id >> 24) & 0xF; // state is a 4-bit field + /* do as much work as possible before disabling interrupts */ + component = (event_id >> 16) & 0xFF; /* component is an 8-bit field */ + state = (event_id >> 24) & 0xF; /* state is a 4-bit field */ switch (state) { case EVENT_TYPE_START: if (component == EVENT_CHANNEL_VP0) { /* tgid = d0; pid = d1; */ - if (mali_activity[1].enabled) { + if (mali_activity[1].enabled) mali_activity_enqueue(0, mali_activity[1].key, 1, d1); - } } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) { /* tgid = d0; pid = d1; */ - if (mali_activity[0].enabled) { + if (mali_activity[0].enabled) mali_activity_enqueue(component - EVENT_CHANNEL_FP0, mali_activity[0].key, 1, d1); - } } break; case EVENT_TYPE_STOP: if (component == EVENT_CHANNEL_VP0) { - if (mali_activity[1].enabled) { + if (mali_activity[1].enabled) mali_activity_stop(0, mali_activity[1].key); - } } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) { - if (mali_activity[0].enabled) { + if (mali_activity[0].enabled) mali_activity_stop(component - EVENT_CHANNEL_FP0, mali_activity[0].key); - } } break; @@ -226,9 +219,8 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned if (component == EVENT_CHANNEL_GPU) { unsigned int reason = (event_id & 0xffff); - if (reason == EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE) { + if (reason == EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE) gator_events_mali_log_dvfs_event(d0, d1); - } } break; @@ -240,7 +232,7 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned #if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD) -mali_counter mali_activity[3]; +struct mali_counter mali_activity[3]; #if defined(MALI_JOB_SLOTS_EVENT_CHANGED) GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid, unsigned char job_id)) @@ -253,8 +245,8 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne unsigned char job_id = 0; #endif - component = (event_id >> 16) & 0xFF; // component is an 8-bit field - state = (event_id >> 24) & 0xF; // state is a 4-bit field + component = (event_id >> 16) & 0xFF; /* component is an 8-bit field */ + state = (event_id >> 24) & 0xF; /* state is a 4-bit field */ switch (component) { case 0: @@ -273,15 +265,13 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne if (unit != GPU_UNIT_NONE) { switch (state) { case EVENT_TYPE_START: - if (mali_activity[component].enabled) { + if (mali_activity[component].enabled) mali_activity_enqueue(0, mali_activity[component].key, 1, (pid != 0 ? pid : tgid)); - } break; case EVENT_TYPE_STOP: - default: // Some jobs can be soft-stopped, so ensure that this terminates the activity trace. - if (mali_activity[component].enabled) { + default: /* Some jobs can be soft-stopped, so ensure that this terminates the activity trace. */ + if (mali_activity[component].enabled) mali_activity_stop(0, mali_activity[component].key); - } break; } } @@ -302,16 +292,14 @@ static int gator_trace_gpu_start(void) #if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD) mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity)); - if (!GATOR_REGISTER_TRACE(mali_timeline_event)) { + if (!GATOR_REGISTER_TRACE(mali_timeline_event)) mali_timeline_trace_registered = 1; - } #endif #if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD) mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity)); - if (!GATOR_REGISTER_TRACE(mali_job_slots_event)) { + if (!GATOR_REGISTER_TRACE(mali_job_slots_event)) mali_job_slots_trace_registered = 1; - } #endif return 0; @@ -320,15 +308,13 @@ static int gator_trace_gpu_start(void) static void gator_trace_gpu_stop(void) { #if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD) - if (mali_timeline_trace_registered) { + if (mali_timeline_trace_registered) GATOR_UNREGISTER_TRACE(mali_timeline_event); - } #endif #if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD) - if (mali_job_slots_trace_registered) { + if (mali_job_slots_trace_registered) GATOR_UNREGISTER_TRACE(mali_job_slots_event); - } #endif mali_timeline_trace_registered = mali_job_slots_trace_registered = 0; diff --git a/driver/gator_trace_power.c b/driver/gator_trace_power.c index f2754b1..46e04b2 100644 --- a/driver/gator_trace_power.c +++ b/driver/gator_trace_power.c @@ -22,18 +22,20 @@ #endif -// cpu_frequency and cpu_idle trace points were introduced in Linux kernel v2.6.38 -// the now deprecated power_frequency trace point was available prior to 2.6.38, but only for x86 +/* cpu_frequency and cpu_idle trace points were introduced in Linux + * kernel v2.6.38 the now deprecated power_frequency trace point was + * available prior to 2.6.38, but only for x86 + */ #if GATOR_CPU_FREQ_SUPPORT enum { POWER_CPU_FREQ, - POWER_CPU_IDLE, POWER_TOTAL }; static DEFINE_PER_CPU(ulong, idle_prev_state); static ulong power_cpu_enabled[POWER_TOTAL]; static ulong power_cpu_key[POWER_TOTAL]; +static ulong power_cpu_cores; static int gator_trace_power_create_files(struct super_block *sb, struct dentry *root) { @@ -41,8 +43,9 @@ static int gator_trace_power_create_files(struct super_block *sb, struct dentry int cpu; bool found_nonzero_freq = false; - // Even if CONFIG_CPU_FREQ is defined, it still may not be used. Check - // for non-zero values from cpufreq_quick_get + /* Even if CONFIG_CPU_FREQ is defined, it still may not be + * used. Check for non-zero values from cpufreq_quick_get + */ for_each_online_cpu(cpu) { if (cpufreq_quick_get(cpu) > 0) { found_nonzero_freq = true; @@ -51,27 +54,18 @@ static int gator_trace_power_create_files(struct super_block *sb, struct dentry } if (found_nonzero_freq) { - // cpu_frequency + /* cpu_frequency */ dir = gatorfs_mkdir(sb, root, "Linux_power_cpu_freq"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &power_cpu_enabled[POWER_CPU_FREQ]); gatorfs_create_ro_ulong(sb, dir, "key", &power_cpu_key[POWER_CPU_FREQ]); } - // cpu_idle - dir = gatorfs_mkdir(sb, root, "Linux_power_cpu_idle"); - if (!dir) { - return -1; - } - gatorfs_create_ulong(sb, dir, "enabled", &power_cpu_enabled[POWER_CPU_IDLE]); - gatorfs_create_ro_ulong(sb, dir, "key", &power_cpu_key[POWER_CPU_IDLE]); - return 0; } -// 'cpu' may not equal smp_processor_id(), i.e. may not be running on the core that is having the freq/idle state change +/* 'cpu' may not equal smp_processor_id(), i.e. may not be running on the core that is having the freq/idle state change */ GATOR_DEFINE_PROBE(cpu_frequency, TP_PROTO(unsigned int frequency, unsigned int cpu)) { cpu = lcpu_to_pcpu(cpu); @@ -82,56 +76,50 @@ GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu)) { cpu = lcpu_to_pcpu(cpu); - if (state == per_cpu(idle_prev_state, cpu)) { + if (state == per_cpu(idle_prev_state, cpu)) return; - } if (implements_wfi()) { if (state == PWR_EVENT_EXIT) { - // transition from wfi to non-wfi + /* transition from wfi to non-wfi */ marshal_idle(cpu, MESSAGE_IDLE_EXIT); } else { - // transition from non-wfi to wfi + /* transition from non-wfi to wfi */ marshal_idle(cpu, MESSAGE_IDLE_ENTER); } } per_cpu(idle_prev_state, cpu) = state; - - if (power_cpu_enabled[POWER_CPU_IDLE]) { - // Increment state so that no negative numbers are sent - marshal_event_single(cpu, power_cpu_key[POWER_CPU_IDLE], state + 1); - } } static void gator_trace_power_online(void) { int pcpu = get_physical_cpu(); int lcpu = get_logical_cpu(); - if (power_cpu_enabled[POWER_CPU_FREQ]) { + + if (power_cpu_enabled[POWER_CPU_FREQ]) marshal_event_single64(pcpu, power_cpu_key[POWER_CPU_FREQ], cpufreq_quick_get(lcpu) * 1000L); - } } static void gator_trace_power_offline(void) { - // Set frequency to zero on an offline + /* Set frequency to zero on an offline */ int cpu = get_physical_cpu(); - if (power_cpu_enabled[POWER_CPU_FREQ]) { + + if (power_cpu_enabled[POWER_CPU_FREQ]) marshal_event_single(cpu, power_cpu_key[POWER_CPU_FREQ], 0); - } } static int gator_trace_power_start(void) { int cpu; - // register tracepoints + /* register tracepoints */ if (power_cpu_enabled[POWER_CPU_FREQ]) if (GATOR_REGISTER_TRACE(cpu_frequency)) goto fail_cpu_frequency_exit; - // Always register for cpu:idle for detecting WFI, independent of power_cpu_enabled[POWER_CPU_IDLE] + /* Always register for cpu_idle for detecting WFI */ if (GATOR_REGISTER_TRACE(cpu_idle)) goto fail_cpu_idle_exit; pr_debug("gator: registered power event tracepoints\n"); @@ -142,7 +130,7 @@ static int gator_trace_power_start(void) return 0; - // unregister tracepoints on error + /* unregister tracepoints on error */ fail_cpu_idle_exit: if (power_cpu_enabled[POWER_CPU_FREQ]) GATOR_UNREGISTER_TRACE(cpu_frequency); @@ -161,14 +149,15 @@ static void gator_trace_power_stop(void) GATOR_UNREGISTER_TRACE(cpu_idle); pr_debug("gator: unregistered power event tracepoints\n"); - for (i = 0; i < POWER_TOTAL; i++) { + for (i = 0; i < POWER_TOTAL; i++) power_cpu_enabled[i] = 0; - } } static void gator_trace_power_init(void) { int i; + + power_cpu_cores = nr_cpu_ids; for (i = 0; i < POWER_TOTAL; i++) { power_cpu_enabled[i] = 0; power_cpu_key[i] = gator_events_get_key(); diff --git a/driver/gator_trace_sched.c b/driver/gator_trace_sched.c index 6550086..6d7cbd7 100644 --- a/driver/gator_trace_sched.c +++ b/driver/gator_trace_sched.c @@ -8,6 +8,10 @@ */ #include <trace/events/sched.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +#include <trace/events/task.h> +#endif + #include "gator.h" #define TASK_MAP_ENTRIES 1024 /* must be power of 2 */ @@ -23,8 +27,10 @@ enum { static DEFINE_PER_CPU(uint64_t *, taskname_keys); static DEFINE_PER_CPU(int, collecting); -// this array is never read as the cpu wait charts are derived counters -// the files are needed, nonetheless, to show that these counters are available +/* this array is never read as the cpu wait charts are derived + * counters the files are needed, nonetheless, to show that these + * counters are available + */ static ulong cpu_wait_enabled[CPU_WAIT_TOTAL]; static ulong sched_cpu_key[CPU_WAIT_TOTAL]; @@ -32,26 +38,24 @@ static int sched_trace_create_files(struct super_block *sb, struct dentry *root) { struct dentry *dir; - // CPU Wait - Contention + /* CPU Wait - Contention */ dir = gatorfs_mkdir(sb, root, "Linux_cpu_wait_contention"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &cpu_wait_enabled[STATE_CONTENTION]); gatorfs_create_ro_ulong(sb, dir, "key", &sched_cpu_key[STATE_CONTENTION]); - // CPU Wait - I/O + /* CPU Wait - I/O */ dir = gatorfs_mkdir(sb, root, "Linux_cpu_wait_io"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &cpu_wait_enabled[STATE_WAIT_ON_IO]); gatorfs_create_ro_ulong(sb, dir, "key", &sched_cpu_key[STATE_WAIT_ON_IO]); return 0; } -static void emit_pid_name(struct task_struct *task) +static void emit_pid_name(const char *comm, struct task_struct *task) { bool found = false; char taskcomm[TASK_COMM_LEN + 3]; @@ -59,10 +63,10 @@ static void emit_pid_name(struct task_struct *task) uint64_t *keys = &(per_cpu(taskname_keys, cpu)[(task->pid & 0xFF) * TASK_MAX_COLLISIONS]); uint64_t value; - value = gator_chksum_crc32(task->comm); + value = gator_chksum_crc32(comm); value = (value << 32) | (uint32_t)task->pid; - // determine if the thread name was emitted already + /* determine if the thread name was emitted already */ for (x = 0; x < TASK_MAX_COLLISIONS; x++) { if (keys[x] == value) { found = true; @@ -71,17 +75,18 @@ static void emit_pid_name(struct task_struct *task) } if (!found) { - // shift values, new value always in front + /* shift values, new value always in front */ uint64_t oldv, newv = value; + for (x = 0; x < TASK_MAX_COLLISIONS; x++) { oldv = keys[x]; keys[x] = newv; newv = oldv; } - // emit pid names, cannot use get_task_comm, as it's not exported on all kernel versions - if (strlcpy(taskcomm, task->comm, TASK_COMM_LEN) == TASK_COMM_LEN - 1) { - // append ellipses if task->comm has length of TASK_COMM_LEN - 1 + /* emit pid names, cannot use get_task_comm, as it's not exported on all kernel versions */ + if (strlcpy(taskcomm, comm, TASK_COMM_LEN) == TASK_COMM_LEN - 1) { + /* append ellipses if comm has length of TASK_COMM_LEN - 1 */ strcat(taskcomm, "..."); } @@ -89,7 +94,7 @@ static void emit_pid_name(struct task_struct *task) } } -static void collect_counters(u64 time, struct task_struct *task) +static void collect_counters(u64 time, struct task_struct *task, bool sched_switch) { int *buffer, len, cpu = get_physical_cpu(); long long *buffer64; @@ -98,7 +103,7 @@ static void collect_counters(u64 time, struct task_struct *task) if (marshal_event_header(time)) { list_for_each_entry(gi, &gator_events, list) { if (gi->read) { - len = gi->read(&buffer); + len = gi->read(&buffer, sched_switch); marshal_event(len, buffer); } else if (gi->read64) { len = gi->read64(&buffer64); @@ -109,22 +114,26 @@ static void collect_counters(u64 time, struct task_struct *task) marshal_event64(len, buffer64); } } - // Only check after writing all counters so that time and corresponding counters appear in the same frame + if (cpu == 0) + gator_emit_perf_time(time); + /* Only check after writing all counters so that time and corresponding counters appear in the same frame */ buffer_check(cpu, BLOCK_COUNTER_BUF, time); - // Commit buffers on timeout + /* Commit buffers on timeout */ if (gator_live_rate > 0 && time >= per_cpu(gator_buffer_commit_time, cpu)) { static const int buftypes[] = { NAME_BUF, COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF, ACTIVITY_BUF }; int i; - for (i = 0; i < ARRAY_SIZE(buftypes); ++i) { + for (i = 0; i < ARRAY_SIZE(buftypes); ++i) gator_commit_buffer(cpu, buftypes[i], time); - } - // spinlocks are noops on uniprocessor machines and mutexes do not work in sched_switch context in - // RT-Preempt full, so disable proactive flushing of the annotate frame on uniprocessor machines. + /* spinlocks are noops on uniprocessor machines and mutexes do + * not work in sched_switch context in RT-Preempt full, so + * disable proactive flushing of the annotate frame on + * uniprocessor machines. + */ #ifdef CONFIG_SMP - // Try to preemptively flush the annotate buffer to reduce the chance of the buffer being full + /* Try to preemptively flush the annotate buffer to reduce the chance of the buffer being full */ if (on_primary_core() && spin_trylock(&annotate_lock)) { gator_commit_buffer(0, ANNOTATE_BUF, time); spin_unlock(&annotate_lock); @@ -134,7 +143,7 @@ static void collect_counters(u64 time, struct task_struct *task) } } -// special case used during a suspend of the system +/* special case used during a suspend of the system */ static void trace_sched_insert_idle(void) { marshal_sched_trace_switch(0, 0); @@ -146,7 +155,7 @@ static void gator_trace_emit_link(struct task_struct *p) int cpu = get_physical_cpu(); cookie = get_exec_cookie(cpu, p); - emit_pid_name(p); + emit_pid_name(p->comm, p); marshal_link(cookie, p->tgid, p->pid); } @@ -161,6 +170,15 @@ GATOR_DEFINE_PROBE(sched_process_exec, TP_PROTO(struct task_struct *p, pid_t old { gator_trace_emit_link(p); } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) +GATOR_DEFINE_PROBE(task_rename, TP_PROTO(struct task_struct *task, char *comm)) +#else +GATOR_DEFINE_PROBE(task_rename, TP_PROTO(struct task_struct *task, const char *comm)) +#endif +{ + emit_pid_name(comm, task); +} #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) @@ -174,17 +192,16 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_ per_cpu(in_scheduler_context, cpu) = true; - // do as much work as possible before disabling interrupts - if (prev->state == TASK_RUNNING) { + /* do as much work as possible before disabling interrupts */ + if (prev->state == TASK_RUNNING) state = STATE_CONTENTION; - } else if (prev->in_iowait) { + else if (prev->in_iowait) state = STATE_WAIT_ON_IO; - } else { + else state = STATE_WAIT_ON_OTHER; - } per_cpu(collecting, cpu) = 1; - collect_counters(gator_get_time(), prev); + collect_counters(gator_get_time(), prev, true); per_cpu(collecting, cpu) = 0; #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) @@ -202,18 +219,20 @@ GATOR_DEFINE_PROBE(sched_process_free, TP_PROTO(struct task_struct *p)) static void do_nothing(void *info) { - // Intentionally do nothing + /* Intentionally do nothing */ (void)info; } static int register_scheduler_tracepoints(void) { - // register tracepoints + /* register tracepoints */ if (GATOR_REGISTER_TRACE(sched_process_fork)) goto fail_sched_process_fork; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) if (GATOR_REGISTER_TRACE(sched_process_exec)) goto fail_sched_process_exec; + if (GATOR_REGISTER_TRACE(task_rename)) + goto fail_task_rename; #endif if (GATOR_REGISTER_TRACE(sched_switch)) goto fail_sched_switch; @@ -221,21 +240,24 @@ static int register_scheduler_tracepoints(void) goto fail_sched_process_free; pr_debug("gator: registered tracepoints\n"); - // Now that the scheduler tracepoint is registered, force a context switch - // on all cpus to capture what is currently running. + /* Now that the scheduler tracepoint is registered, force a context + * switch on all cpus to capture what is currently running. + */ on_each_cpu(do_nothing, NULL, 0); return 0; - // unregister tracepoints on error + /* unregister tracepoints on error */ fail_sched_process_free: GATOR_UNREGISTER_TRACE(sched_switch); fail_sched_switch: - GATOR_UNREGISTER_TRACE(sched_process_fork); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) -fail_sched_process_exec: + GATOR_UNREGISTER_TRACE(task_rename); +fail_task_rename: GATOR_UNREGISTER_TRACE(sched_process_exec); +fail_sched_process_exec: #endif + GATOR_UNREGISTER_TRACE(sched_process_fork); fail_sched_process_fork: pr_err("gator: tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n"); @@ -247,6 +269,7 @@ static void unregister_scheduler_tracepoints(void) GATOR_UNREGISTER_TRACE(sched_process_fork); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) GATOR_UNREGISTER_TRACE(sched_process_exec); + GATOR_UNREGISTER_TRACE(task_rename); #endif GATOR_UNREGISTER_TRACE(sched_switch); GATOR_UNREGISTER_TRACE(sched_process_free); @@ -271,7 +294,7 @@ static int gator_trace_sched_start(void) for_each_present_cpu(cpu) { size = TASK_MAP_ENTRIES * TASK_MAX_COLLISIONS * sizeof(uint64_t); - per_cpu(taskname_keys, cpu) = (uint64_t *)kmalloc(size, GFP_KERNEL); + per_cpu(taskname_keys, cpu) = kmalloc(size, GFP_KERNEL); if (!per_cpu(taskname_keys, cpu)) return -1; memset(per_cpu(taskname_keys, cpu), 0, size); @@ -290,6 +313,7 @@ static void gator_trace_sched_offline(void) static void gator_trace_sched_init(void) { int i; + for (i = 0; i < CPU_WAIT_TOTAL; i++) { cpu_wait_enabled[i] = 0; sched_cpu_key[i] = gator_events_get_key(); diff --git a/driver/mali/mali_mjollnir_profiling_gator_api.h b/driver/mali/mali_mjollnir_profiling_gator_api.h index ff00d90..2bc0b03 100644 --- a/driver/mali/mali_mjollnir_profiling_gator_api.h +++ b/driver/mali/mali_mjollnir_profiling_gator_api.h @@ -23,83 +23,82 @@ extern "C" #define MAX_NUM_VP_CORES (1) #define MAX_NUM_L2_CACHE_CORES (1) -enum counters -{ - /* Timeline activity */ - ACTIVITY_VP_0 = 0, - ACTIVITY_FP_0, - ACTIVITY_FP_1, - ACTIVITY_FP_2, - ACTIVITY_FP_3, - - /* L2 cache counters */ - COUNTER_L2_0_C0, - COUNTER_L2_0_C1, - - /* Vertex processor counters */ - COUNTER_VP_0_C0, - COUNTER_VP_0_C1, - - /* Fragment processor counters */ - COUNTER_FP_0_C0, - COUNTER_FP_0_C1, - COUNTER_FP_1_C0, - COUNTER_FP_1_C1, - COUNTER_FP_2_C0, - COUNTER_FP_2_C1, - COUNTER_FP_3_C0, - COUNTER_FP_3_C1, - - /* EGL Software Counters */ - COUNTER_EGL_BLIT_TIME, - - /* GLES Software Counters */ - COUNTER_GLES_DRAW_ELEMENTS_CALLS, - COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, - COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, - COUNTER_GLES_DRAW_ARRAYS_CALLS, - COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, - COUNTER_GLES_DRAW_POINTS, - COUNTER_GLES_DRAW_LINES, - COUNTER_GLES_DRAW_LINE_LOOP, - COUNTER_GLES_DRAW_LINE_STRIP, - COUNTER_GLES_DRAW_TRIANGLES, - COUNTER_GLES_DRAW_TRIANGLE_STRIP, - COUNTER_GLES_DRAW_TRIANGLE_FAN, - COUNTER_GLES_NON_VBO_DATA_COPY_TIME, - COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, - COUNTER_GLES_UPLOAD_TEXTURE_TIME, - COUNTER_GLES_UPLOAD_VBO_TIME, - COUNTER_GLES_NUM_FLUSHES, - COUNTER_GLES_NUM_VSHADERS_GENERATED, - COUNTER_GLES_NUM_FSHADERS_GENERATED, - COUNTER_GLES_VSHADER_GEN_TIME, - COUNTER_GLES_FSHADER_GEN_TIME, - COUNTER_GLES_INPUT_TRIANGLES, - COUNTER_GLES_VXCACHE_HIT, - COUNTER_GLES_VXCACHE_MISS, - COUNTER_GLES_VXCACHE_COLLISION, - COUNTER_GLES_CULLED_TRIANGLES, - COUNTER_GLES_CULLED_LINES, - COUNTER_GLES_BACKFACE_TRIANGLES, - COUNTER_GLES_GBCLIP_TRIANGLES, - COUNTER_GLES_GBCLIP_LINES, - COUNTER_GLES_TRIANGLES_DRAWN, - COUNTER_GLES_DRAWCALL_TIME, - COUNTER_GLES_TRIANGLES_COUNT, - COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, - COUNTER_GLES_STRIP_TRIANGLES_COUNT, - COUNTER_GLES_FAN_TRIANGLES_COUNT, - COUNTER_GLES_LINES_COUNT, - COUNTER_GLES_INDEPENDENT_LINES_COUNT, - COUNTER_GLES_STRIP_LINES_COUNT, - COUNTER_GLES_LOOP_LINES_COUNT, - - COUNTER_FILMSTRIP, - COUNTER_FREQUENCY, - COUNTER_VOLTAGE, - - NUMBER_OF_EVENTS +enum counters { + /* Timeline activity */ + ACTIVITY_VP_0 = 0, + ACTIVITY_FP_0, + ACTIVITY_FP_1, + ACTIVITY_FP_2, + ACTIVITY_FP_3, + + /* L2 cache counters */ + COUNTER_L2_0_C0, + COUNTER_L2_0_C1, + + /* Vertex processor counters */ + COUNTER_VP_0_C0, + COUNTER_VP_0_C1, + + /* Fragment processor counters */ + COUNTER_FP_0_C0, + COUNTER_FP_0_C1, + COUNTER_FP_1_C0, + COUNTER_FP_1_C1, + COUNTER_FP_2_C0, + COUNTER_FP_2_C1, + COUNTER_FP_3_C0, + COUNTER_FP_3_C1, + + /* EGL Software Counters */ + COUNTER_EGL_BLIT_TIME, + + /* GLES Software Counters */ + COUNTER_GLES_DRAW_ELEMENTS_CALLS, + COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, + COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_ARRAYS_CALLS, + COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_POINTS, + COUNTER_GLES_DRAW_LINES, + COUNTER_GLES_DRAW_LINE_LOOP, + COUNTER_GLES_DRAW_LINE_STRIP, + COUNTER_GLES_DRAW_TRIANGLES, + COUNTER_GLES_DRAW_TRIANGLE_STRIP, + COUNTER_GLES_DRAW_TRIANGLE_FAN, + COUNTER_GLES_NON_VBO_DATA_COPY_TIME, + COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, + COUNTER_GLES_UPLOAD_TEXTURE_TIME, + COUNTER_GLES_UPLOAD_VBO_TIME, + COUNTER_GLES_NUM_FLUSHES, + COUNTER_GLES_NUM_VSHADERS_GENERATED, + COUNTER_GLES_NUM_FSHADERS_GENERATED, + COUNTER_GLES_VSHADER_GEN_TIME, + COUNTER_GLES_FSHADER_GEN_TIME, + COUNTER_GLES_INPUT_TRIANGLES, + COUNTER_GLES_VXCACHE_HIT, + COUNTER_GLES_VXCACHE_MISS, + COUNTER_GLES_VXCACHE_COLLISION, + COUNTER_GLES_CULLED_TRIANGLES, + COUNTER_GLES_CULLED_LINES, + COUNTER_GLES_BACKFACE_TRIANGLES, + COUNTER_GLES_GBCLIP_TRIANGLES, + COUNTER_GLES_GBCLIP_LINES, + COUNTER_GLES_TRIANGLES_DRAWN, + COUNTER_GLES_DRAWCALL_TIME, + COUNTER_GLES_TRIANGLES_COUNT, + COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, + COUNTER_GLES_STRIP_TRIANGLES_COUNT, + COUNTER_GLES_FAN_TRIANGLES_COUNT, + COUNTER_GLES_LINES_COUNT, + COUNTER_GLES_INDEPENDENT_LINES_COUNT, + COUNTER_GLES_STRIP_LINES_COUNT, + COUNTER_GLES_LOOP_LINES_COUNT, + + COUNTER_FILMSTRIP, + COUNTER_FREQUENCY, + COUNTER_VOLTAGE, + + NUMBER_OF_EVENTS }; #define FIRST_ACTIVITY_EVENT ACTIVITY_VP_0 @@ -117,34 +116,31 @@ enum counters /** * Structure to pass performance counter data of a Mali core */ -typedef struct _mali_profiling_core_counters -{ - u32 source0; - u32 value0; - u32 source1; - u32 value1; -} _mali_profiling_core_counters; +struct _mali_profiling_core_counters { + u32 source0; + u32 value0; + u32 source1; + u32 value1; +}; /* * For compatibility with utgard. */ -typedef struct _mali_profiling_l2_counter_values -{ - struct _mali_profiling_core_counters cores[MAX_NUM_L2_CACHE_CORES]; -} _mali_profiling_l2_counter_values; +struct _mali_profiling_l2_counter_values { + struct _mali_profiling_core_counters cores[MAX_NUM_L2_CACHE_CORES]; +}; -typedef struct _mali_profiling_mali_version -{ - u32 mali_product_id; - u32 mali_version_major; - u32 mali_version_minor; - u32 num_of_l2_cores; - u32 num_of_fp_cores; - u32 num_of_vp_cores; -} _mali_profiling_mali_version; +struct _mali_profiling_mali_version { + u32 mali_product_id; + u32 mali_version_major; + u32 mali_version_minor; + u32 num_of_l2_cores; + u32 num_of_fp_cores; + u32 num_of_vp_cores; +}; extern void _mali_profiling_get_mali_version(struct _mali_profiling_mali_version *values); -extern u32 _mali_profiling_get_l2_counters(_mali_profiling_l2_counter_values *values); +extern u32 _mali_profiling_get_l2_counters(struct _mali_profiling_l2_counter_values *values); /* * List of possible actions allowing DDK to be controlled by Streamline. diff --git a/driver/mali/mali_utgard_profiling_gator_api.h b/driver/mali/mali_utgard_profiling_gator_api.h index 43c5760..d646531 100644 --- a/driver/mali/mali_utgard_profiling_gator_api.h +++ b/driver/mali/mali_utgard_profiling_gator_api.h @@ -22,105 +22,104 @@ extern "C" #define MAX_NUM_VP_CORES 1 /** The list of events supported by the Mali DDK. */ -typedef enum -{ - /* Vertex processor activity */ - ACTIVITY_VP_0 = 0, - - /* Fragment processor activity */ - ACTIVITY_FP_0, /* 1 */ - ACTIVITY_FP_1, - ACTIVITY_FP_2, - ACTIVITY_FP_3, - ACTIVITY_FP_4, - ACTIVITY_FP_5, - ACTIVITY_FP_6, - ACTIVITY_FP_7, - - /* L2 cache counters */ - COUNTER_L2_0_C0, - COUNTER_L2_0_C1, - COUNTER_L2_1_C0, - COUNTER_L2_1_C1, - COUNTER_L2_2_C0, - COUNTER_L2_2_C1, - - /* Vertex processor counters */ - COUNTER_VP_0_C0, /*15*/ - COUNTER_VP_0_C1, - - /* Fragment processor counters */ - COUNTER_FP_0_C0, - COUNTER_FP_0_C1, - COUNTER_FP_1_C0, - COUNTER_FP_1_C1, - COUNTER_FP_2_C0, - COUNTER_FP_2_C1, - COUNTER_FP_3_C0, - COUNTER_FP_3_C1, - COUNTER_FP_4_C0, - COUNTER_FP_4_C1, - COUNTER_FP_5_C0, - COUNTER_FP_5_C1, - COUNTER_FP_6_C0, - COUNTER_FP_6_C1, - COUNTER_FP_7_C0, - COUNTER_FP_7_C1, /* 32 */ - - /* - * If more hardware counters are added, the _mali_osk_hw_counter_table - * below should also be updated. - */ - - /* EGL software counters */ - COUNTER_EGL_BLIT_TIME, - - /* GLES software counters */ - COUNTER_GLES_DRAW_ELEMENTS_CALLS, - COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, - COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, - COUNTER_GLES_DRAW_ARRAYS_CALLS, - COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, - COUNTER_GLES_DRAW_POINTS, - COUNTER_GLES_DRAW_LINES, - COUNTER_GLES_DRAW_LINE_LOOP, - COUNTER_GLES_DRAW_LINE_STRIP, - COUNTER_GLES_DRAW_TRIANGLES, - COUNTER_GLES_DRAW_TRIANGLE_STRIP, - COUNTER_GLES_DRAW_TRIANGLE_FAN, - COUNTER_GLES_NON_VBO_DATA_COPY_TIME, - COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, - COUNTER_GLES_UPLOAD_TEXTURE_TIME, - COUNTER_GLES_UPLOAD_VBO_TIME, - COUNTER_GLES_NUM_FLUSHES, - COUNTER_GLES_NUM_VSHADERS_GENERATED, - COUNTER_GLES_NUM_FSHADERS_GENERATED, - COUNTER_GLES_VSHADER_GEN_TIME, - COUNTER_GLES_FSHADER_GEN_TIME, - COUNTER_GLES_INPUT_TRIANGLES, - COUNTER_GLES_VXCACHE_HIT, - COUNTER_GLES_VXCACHE_MISS, - COUNTER_GLES_VXCACHE_COLLISION, - COUNTER_GLES_CULLED_TRIANGLES, - COUNTER_GLES_CULLED_LINES, - COUNTER_GLES_BACKFACE_TRIANGLES, - COUNTER_GLES_GBCLIP_TRIANGLES, - COUNTER_GLES_GBCLIP_LINES, - COUNTER_GLES_TRIANGLES_DRAWN, - COUNTER_GLES_DRAWCALL_TIME, - COUNTER_GLES_TRIANGLES_COUNT, - COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, - COUNTER_GLES_STRIP_TRIANGLES_COUNT, - COUNTER_GLES_FAN_TRIANGLES_COUNT, - COUNTER_GLES_LINES_COUNT, - COUNTER_GLES_INDEPENDENT_LINES_COUNT, - COUNTER_GLES_STRIP_LINES_COUNT, - COUNTER_GLES_LOOP_LINES_COUNT, - - /* Framebuffer capture pseudo-counter */ - COUNTER_FILMSTRIP, - - NUMBER_OF_EVENTS +enum { + /* Vertex processor activity */ + ACTIVITY_VP_0 = 0, + + /* Fragment processor activity */ + ACTIVITY_FP_0, /* 1 */ + ACTIVITY_FP_1, + ACTIVITY_FP_2, + ACTIVITY_FP_3, + ACTIVITY_FP_4, + ACTIVITY_FP_5, + ACTIVITY_FP_6, + ACTIVITY_FP_7, + + /* L2 cache counters */ + COUNTER_L2_0_C0, + COUNTER_L2_0_C1, + COUNTER_L2_1_C0, + COUNTER_L2_1_C1, + COUNTER_L2_2_C0, + COUNTER_L2_2_C1, + + /* Vertex processor counters */ + COUNTER_VP_0_C0, /*15*/ + COUNTER_VP_0_C1, + + /* Fragment processor counters */ + COUNTER_FP_0_C0, + COUNTER_FP_0_C1, + COUNTER_FP_1_C0, + COUNTER_FP_1_C1, + COUNTER_FP_2_C0, + COUNTER_FP_2_C1, + COUNTER_FP_3_C0, + COUNTER_FP_3_C1, + COUNTER_FP_4_C0, + COUNTER_FP_4_C1, + COUNTER_FP_5_C0, + COUNTER_FP_5_C1, + COUNTER_FP_6_C0, + COUNTER_FP_6_C1, + COUNTER_FP_7_C0, + COUNTER_FP_7_C1, /* 32 */ + + /* + * If more hardware counters are added, the _mali_osk_hw_counter_table + * below should also be updated. + */ + + /* EGL software counters */ + COUNTER_EGL_BLIT_TIME, + + /* GLES software counters */ + COUNTER_GLES_DRAW_ELEMENTS_CALLS, + COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, + COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_ARRAYS_CALLS, + COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_POINTS, + COUNTER_GLES_DRAW_LINES, + COUNTER_GLES_DRAW_LINE_LOOP, + COUNTER_GLES_DRAW_LINE_STRIP, + COUNTER_GLES_DRAW_TRIANGLES, + COUNTER_GLES_DRAW_TRIANGLE_STRIP, + COUNTER_GLES_DRAW_TRIANGLE_FAN, + COUNTER_GLES_NON_VBO_DATA_COPY_TIME, + COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, + COUNTER_GLES_UPLOAD_TEXTURE_TIME, + COUNTER_GLES_UPLOAD_VBO_TIME, + COUNTER_GLES_NUM_FLUSHES, + COUNTER_GLES_NUM_VSHADERS_GENERATED, + COUNTER_GLES_NUM_FSHADERS_GENERATED, + COUNTER_GLES_VSHADER_GEN_TIME, + COUNTER_GLES_FSHADER_GEN_TIME, + COUNTER_GLES_INPUT_TRIANGLES, + COUNTER_GLES_VXCACHE_HIT, + COUNTER_GLES_VXCACHE_MISS, + COUNTER_GLES_VXCACHE_COLLISION, + COUNTER_GLES_CULLED_TRIANGLES, + COUNTER_GLES_CULLED_LINES, + COUNTER_GLES_BACKFACE_TRIANGLES, + COUNTER_GLES_GBCLIP_TRIANGLES, + COUNTER_GLES_GBCLIP_LINES, + COUNTER_GLES_TRIANGLES_DRAWN, + COUNTER_GLES_DRAWCALL_TIME, + COUNTER_GLES_TRIANGLES_COUNT, + COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, + COUNTER_GLES_STRIP_TRIANGLES_COUNT, + COUNTER_GLES_FAN_TRIANGLES_COUNT, + COUNTER_GLES_LINES_COUNT, + COUNTER_GLES_INDEPENDENT_LINES_COUNT, + COUNTER_GLES_STRIP_LINES_COUNT, + COUNTER_GLES_LOOP_LINES_COUNT, + + /* Framebuffer capture pseudo-counter */ + COUNTER_FILMSTRIP, + + NUMBER_OF_EVENTS } _mali_osk_counter_id; #define FIRST_ACTIVITY_EVENT ACTIVITY_VP_0 @@ -138,21 +137,19 @@ typedef enum /** * Structure to pass performance counter data of a Mali core */ -typedef struct _mali_profiling_core_counters -{ +struct _mali_profiling_core_counters { u32 source0; u32 value0; u32 source1; u32 value1; -} _mali_profiling_core_counters; +}; /** * Structure to pass performance counter data of Mali L2 cache cores */ -typedef struct _mali_profiling_l2_counter_values -{ +struct _mali_profiling_l2_counter_values { struct _mali_profiling_core_counters cores[MAX_NUM_L2_CACHE_CORES]; -} _mali_profiling_l2_counter_values; +}; /** * Structure to pass data defining Mali instance in use: @@ -164,15 +161,14 @@ typedef struct _mali_profiling_l2_counter_values * num_of_fp_cores - number of fragment processor cores * num_of_vp_cores - number of vertex processor cores */ -typedef struct _mali_profiling_mali_version -{ +struct _mali_profiling_mali_version { u32 mali_product_id; u32 mali_version_major; u32 mali_version_minor; u32 num_of_l2_cores; u32 num_of_fp_cores; u32 num_of_vp_cores; -} _mali_profiling_mali_version; +}; /* * List of possible actions to be controlled by Streamline. @@ -186,7 +182,7 @@ typedef struct _mali_profiling_mali_version void _mali_profiling_control(u32 action, u32 value); -u32 _mali_profiling_get_l2_counters(_mali_profiling_l2_counter_values *values); +u32 _mali_profiling_get_l2_counters(struct _mali_profiling_l2_counter_values *values); int _mali_profiling_set_event(u32 counter_id, s32 event_id); |