diff options
Diffstat (limited to 'driver')
31 files changed, 2335 insertions, 2201 deletions
diff --git a/driver/Makefile b/driver/Makefile index 6cafecf..d22d29d 100644 --- a/driver/Makefile +++ b/driver/Makefile @@ -27,7 +27,7 @@ gator-y += gator_events_mali_common.o EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT) endif -# GATOR_TEST controls whether to include (=1) or exclude (=0) test code. +# GATOR_TEST controls whether to include (=1) or exclude (=0) test code. GATOR_TEST ?= 0 EXTRA_CFLAGS += -DGATOR_TEST=$(GATOR_TEST) diff --git a/driver/gator.h b/driver/gator.h index 5a40e17..9a4617b 100644 --- a/driver/gator.h +++ b/driver/gator.h @@ -15,7 +15,7 @@ #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(CONFIG_HW_PERF_EVENTS) +#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) @@ -33,22 +33,39 @@ #define SCORPIONMP 0x02d #define KRAITSIM 0x049 #define KRAIT 0x04d +#define KRAIT_S4_PRO 0x06f +#define CORTEX_A53 0xd03 +#define CORTEX_A57 0xd07 #define AARCH64 0xd0f +#define OTHER 0xfff + +#define MAXSIZE_CORE_NAME 32 + +struct gator_cpu { + const int cpuid; + const char core_name[MAXSIZE_CORE_NAME]; + const char * const pmnc_name; + const int pmnc_counters; + const int ccnt; +}; + +extern struct gator_cpu gator_cpus[]; /****************************************************************************** * Filesystem ******************************************************************************/ int gatorfs_create_file_perm(struct super_block *sb, struct dentry *root, - char const *name, const struct file_operations *fops, int perm); + char const *name, + const struct file_operations *fops, int perm); -struct dentry *gatorfs_mkdir(struct super_block *sb, - struct dentry *root, char const *name); +struct dentry *gatorfs_mkdir(struct super_block *sb, struct dentry *root, + char const *name); int gatorfs_create_ulong(struct super_block *sb, struct dentry *root, - char const *name, unsigned long *val); + char const *name, unsigned long *val); int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root, - char const *name, unsigned long *val); + char const *name, unsigned long *val); void gator_op_create_files(struct super_block *sb, struct dentry *root); @@ -77,15 +94,16 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root); * Events ******************************************************************************/ struct gator_interface { - int (*create_files)(struct super_block *sb, struct dentry *root); - int (*start)(void); - void (*stop)(void); - int (*online)(int** buffer); - int (*offline)(int** buffer); - void (*online_dispatch)(int cpu); // called in process context but may not be running on core 'cpu' - void (*offline_dispatch)(int cpu); // called in process context but may not be running on core 'cpu' - int (*read)(int **buffer); - int (*read64)(long long **buffer); + void (*shutdown)(void); // Complementary function to init + int (*create_files)(struct super_block *sb, struct dentry *root); + int (*start)(void); + void (*stop)(void); // Complementary function to start + int (*online)(int **buffer); + int (*offline)(int **buffer); + void (*online_dispatch)(int cpu); // called in process context but may not be running on core 'cpu' + void (*offline_dispatch)(int cpu); // called in process context but may not be running on core 'cpu' + int (*read)(int **buffer); + int (*read64)(long long **buffer); struct list_head list; }; @@ -96,8 +114,8 @@ struct gator_interface { int gator_events_install(struct gator_interface *interface); int gator_events_get_key(void); -extern u32 gator_cpuid(void); +u32 gator_cpuid(void); -void gator_backtrace_handler(struct pt_regs * const regs); +void gator_backtrace_handler(struct pt_regs *const regs); #endif // GATOR_H_ diff --git a/driver/gator_annotate.c b/driver/gator_annotate.c index 928e252..42f9951 100644 --- a/driver/gator_annotate.c +++ b/driver/gator_annotate.c @@ -44,8 +44,9 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t return -EINVAL; } - // Annotation is not supported in interrupt context + // Annotations are not supported in interrupt context if (in_interrupt()) { + printk(KERN_WARNING "gator: Annotations are not supported in interrupt context\n"); return -EINVAL; } @@ -58,7 +59,8 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t goto annotate_write_out; } - cpu = 0; // 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) { pid = 0; @@ -129,18 +131,21 @@ static int annotate_release(struct inode *inode, struct file *file) uint32_t pid = current->pid; gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id()); 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 + gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); // time + gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); // size } + // Check and commit; commit is set to occur once buffer is 3/4 full + buffer_check(cpu, ANNOTATE_BUF); + spin_unlock(&annotate_lock); return 0; } static const struct file_operations annotate_fops = { - .write = annotate_write, - .release = annotate_release + .write = annotate_write, + .release = annotate_release }; static int gator_annotate_create_files(struct super_block *sb, struct dentry *root) diff --git a/driver/gator_annotate_kernel.c b/driver/gator_annotate_kernel.c index bc68fa8..67d2d6c 100644 --- a/driver/gator_annotate_kernel.c +++ b/driver/gator_annotate_kernel.c @@ -8,11 +8,13 @@ */ #define ESCAPE_CODE 0x1c -#define STRING_ANNOTATION 0x03 +#define STRING_ANNOTATION 0x06 +#define NAME_CHANNEL_ANNOTATION 0x07 +#define NAME_GROUP_ANNOTATION 0x08 #define VISUAL_ANNOTATION 0x04 #define MARKER_ANNOTATION 0x05 -static void kannotate_write(const char* ptr, unsigned int size) +static void kannotate_write(const char *ptr, unsigned int size) { int retval; int pos = 0; @@ -27,91 +29,129 @@ static void kannotate_write(const char* ptr, unsigned int size) } } -static void gator_annotate_code(char code) +void gator_annotate_channel(int channel, const char *str) { - int header = ESCAPE_CODE | (code << 8); - kannotate_write((char*)&header, sizeof(header)); + int str_size = strlen(str) & 0xffff; + long long header = ESCAPE_CODE | (STRING_ANNOTATION << 8) | (channel << 16) | ((long long)str_size << 48); + kannotate_write((char *)&header, sizeof(header)); + kannotate_write(str, str_size); } -static void gator_annotate_code_str(char code, const char* string) -{ - int str_size = strlen(string) & 0xffff; - int header = ESCAPE_CODE | (code << 8) | (str_size << 16); - kannotate_write((char*)&header, sizeof(header)); - kannotate_write(string, str_size); -} +EXPORT_SYMBOL(gator_annotate_channel); -static void gator_annotate_code_color(char code, int color) +void gator_annotate(const char *str) { - long long header = (ESCAPE_CODE | (code << 8) | 0x00040000 | ((long long)color << 32)); - kannotate_write((char*)&header, sizeof(header)); + gator_annotate_channel(0, str); } -static void gator_annotate_code_color_str(char code, int color, const char* string) +EXPORT_SYMBOL(gator_annotate); + +void gator_annotate_channel_color(int channel, int color, const char *str) { - int str_size = (strlen(string) + 4) & 0xffff; - long long header = ESCAPE_CODE | (code << 8) | (str_size << 16) | ((long long)color << 32); - kannotate_write((char*)&header, sizeof(header)); - kannotate_write(string, str_size - 4); + int str_size = (strlen(str) + 4) & 0xffff; + char header[12]; + header[0] = ESCAPE_CODE; + header[1] = STRING_ANNOTATION; + *(u32 *)(&header[2]) = channel; + *(u16 *)(&header[6]) = str_size; + *(u32 *)(&header[8]) = color; + kannotate_write((char *)&header, sizeof(header)); + kannotate_write(str, str_size - 4); } -// String annotation -void gator_annotate(const char* string) +EXPORT_SYMBOL(gator_annotate_channel_color); + +void gator_annotate_color(int color, const char *str) { - gator_annotate_code_str(STRING_ANNOTATION, string); + gator_annotate_channel_color(0, color, str); } -EXPORT_SYMBOL(gator_annotate); -// String annotation with color -void gator_annotate_color(int color, const char* string) +EXPORT_SYMBOL(gator_annotate_color); + +void gator_annotate_channel_end(int channel) { - gator_annotate_code_color_str(STRING_ANNOTATION, color, string); + long long header = ESCAPE_CODE | (STRING_ANNOTATION << 8) | (channel << 16); + kannotate_write((char *)&header, sizeof(header)); } -EXPORT_SYMBOL(gator_annotate_color); -// Terminate an annotation +EXPORT_SYMBOL(gator_annotate_channel_end); + void gator_annotate_end(void) { - gator_annotate_code(STRING_ANNOTATION); + gator_annotate_channel_end(0); } + EXPORT_SYMBOL(gator_annotate_end); -// Image annotation with optional string -void gator_annotate_visual(const char* data, unsigned int length, const char* string) +void gator_annotate_name_channel(int channel, int group, const char* str) +{ + int str_size = strlen(str) & 0xffff; + char header[12]; + header[0] = ESCAPE_CODE; + header[1] = NAME_CHANNEL_ANNOTATION; + *(u32 *)(&header[2]) = channel; + *(u32 *)(&header[6]) = group; + *(u16 *)(&header[10]) = str_size; + kannotate_write((char *)&header, sizeof(header)); + kannotate_write(str, str_size); +} + +EXPORT_SYMBOL(gator_annotate_name_channel); + +void gator_annotate_name_group(int group, const char* str) +{ + int str_size = strlen(str) & 0xffff; + long long header = ESCAPE_CODE | (NAME_GROUP_ANNOTATION << 8) | (group << 16) | ((long long)str_size << 48); + kannotate_write((char *)&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) { - int str_size = strlen(string) & 0xffff; + int str_size = strlen(str) & 0xffff; int visual_annotation = ESCAPE_CODE | (VISUAL_ANNOTATION << 8) | (str_size << 16); - kannotate_write((char*)&visual_annotation, sizeof(visual_annotation)); - kannotate_write(string, str_size); - kannotate_write((char*)&length, sizeof(length)); + kannotate_write((char *)&visual_annotation, sizeof(visual_annotation)); + kannotate_write(str, str_size); + kannotate_write((char *)&length, sizeof(length)); kannotate_write(data, length); } + EXPORT_SYMBOL(gator_annotate_visual); -// Marker annotation void gator_annotate_marker(void) { - gator_annotate_code(MARKER_ANNOTATION); + int header = ESCAPE_CODE | (MARKER_ANNOTATION << 8); + kannotate_write((char *)&header, sizeof(header)); } + EXPORT_SYMBOL(gator_annotate_marker); -// Marker annotation with a string -void gator_annotate_marker_str(const char* string) +void gator_annotate_marker_str(const char *str) { - gator_annotate_code_str(MARKER_ANNOTATION, string); + int str_size = strlen(str) & 0xffff; + int header = ESCAPE_CODE | (MARKER_ANNOTATION << 8) | (str_size << 16); + kannotate_write((char *)&header, sizeof(header)); + kannotate_write(str, str_size); } + EXPORT_SYMBOL(gator_annotate_marker_str); -// Marker annotation with a color void gator_annotate_marker_color(int color) { - gator_annotate_code_color(MARKER_ANNOTATION, color); + long long header = (ESCAPE_CODE | (MARKER_ANNOTATION << 8) | 0x00040000 | ((long long)color << 32)); + kannotate_write((char *)&header, sizeof(header)); } + EXPORT_SYMBOL(gator_annotate_marker_color); -// Marker annotation with a string and color -void gator_annotate_marker_color_str(int color, const char* string) +void gator_annotate_marker_color_str(int color, const char *str) { - gator_annotate_code_color_str(MARKER_ANNOTATION, color, string); + int str_size = (strlen(str) + 4) & 0xffff; + long long header = ESCAPE_CODE | (MARKER_ANNOTATION << 8) | (str_size << 16) | ((long long)color << 32); + kannotate_write((char *)&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 2173d8a..e6125b3 100644 --- a/driver/gator_backtrace.c +++ b/driver/gator_backtrace.c @@ -11,20 +11,28 @@ * EABI backtrace stores {fp,lr} on the stack. */ struct frame_tail_eabi { - unsigned long fp; // points to prev_lr + unsigned long fp; // points to prev_lr unsigned long lr; }; -static void arm_backtrace_eabi(int cpu, struct pt_regs * const regs, unsigned int depth) +static void arm_backtrace_eabi(int cpu, struct pt_regs *const regs, unsigned int depth) { -#if defined(__arm__) +#if defined(__arm__) || defined(__aarch64__) struct frame_tail_eabi *tail; struct frame_tail_eabi *next; struct frame_tail_eabi *ptrtail; struct frame_tail_eabi buftail; +#if defined(__arm__) unsigned long fp = regs->ARM_fp; unsigned long sp = regs->ARM_sp; unsigned long lr = regs->ARM_lr; + const int frame_offset = 4; +#else + unsigned long fp = regs->regs[29]; + unsigned long sp = regs->sp; + unsigned long lr = regs->regs[30]; + const int frame_offset = 0; +#endif int is_user_mode = user_mode(regs); if (!is_user_mode) { @@ -39,9 +47,9 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs * const regs, unsigned in return; } - tail = (struct frame_tail_eabi *)(fp - 4); + tail = (struct frame_tail_eabi *)(fp - frame_offset); - while (depth-- && tail && !((unsigned long) tail & 3)) { + while (depth-- && tail && !((unsigned long)tail & 3)) { /* Also check accessibility of one struct frame_tail beyond */ if (!access_ok(VERIFY_READ, tail, sizeof(struct frame_tail_eabi))) return; @@ -53,10 +61,10 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs * const regs, unsigned in gator_add_trace(cpu, lr); /* frame pointers should progress back up the stack, towards higher addresses */ - next = (struct frame_tail_eabi *)(lr - 4); + next = (struct frame_tail_eabi *)(lr - frame_offset); if (tail >= next || lr == 0) { fp = ptrtail[0].fp; - next = (struct frame_tail_eabi *)(fp - 4); + next = (struct frame_tail_eabi *)(fp - frame_offset); /* check tail is valid */ if (tail >= next || fp == 0) { return; @@ -68,7 +76,7 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs * const regs, unsigned in #endif } -#if defined(__arm__) +#if defined(__arm__) || defined(__aarch64__) static int report_trace(struct stackframe *frame, void *d) { struct module *mod; @@ -78,7 +86,7 @@ static int report_trace(struct stackframe *frame, void *d) if (*depth) { mod = __module_address(addr); if (mod) { - cookie = get_cookie(cpu, current, NULL, mod, true); + cookie = get_cookie(cpu, current, mod->name, false); addr = addr - (unsigned long)mod->module_core; } marshal_backtrace(addr & ~1, cookie); @@ -91,9 +99,9 @@ static int report_trace(struct stackframe *frame, void *d) // 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 -static void kernel_backtrace(int cpu, struct pt_regs * const regs) +static void kernel_backtrace(int cpu, struct pt_regs *const regs) { -#if defined(__arm__) +#if defined(__arm__) || defined(__aarch64__) #ifdef GATOR_KERNEL_STACK_UNWINDING int depth = gator_backtrace_depth; #else @@ -102,10 +110,16 @@ static void kernel_backtrace(int cpu, struct pt_regs * const regs) struct stackframe frame; if (depth == 0) depth = 1; +#if defined(__arm__) frame.fp = regs->ARM_fp; frame.sp = regs->ARM_sp; frame.lr = regs->ARM_lr; frame.pc = regs->ARM_pc; +#else + frame.fp = regs->regs[29]; + frame.sp = regs->sp; + frame.pc = regs->pc; +#endif walk_stackframe(&frame, report_trace, &depth); #else marshal_backtrace(PC_REG & ~1, NO_COOKIE); diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c index 21dc4eb..bb401bb 100644 --- a/driver/gator_cookies.c +++ b/driver/gator_cookies.c @@ -7,7 +7,7 @@ * */ -#define COOKIEMAP_ENTRIES 1024 /* must be power of 2 */ +#define COOKIEMAP_ENTRIES 1024 /* must be power of 2 */ #define TRANSLATE_SIZE 256 #define MAX_COLLISIONS 2 @@ -20,28 +20,29 @@ static DEFINE_PER_CPU(uint64_t *, cookie_keys); static DEFINE_PER_CPU(uint32_t *, cookie_values); static DEFINE_PER_CPU(int, translate_buffer_read); static DEFINE_PER_CPU(int, translate_buffer_write); -static DEFINE_PER_CPU(void * *, translate_buffer); +static DEFINE_PER_CPU(void **, translate_buffer); -static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt); +static inline uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq); static void wq_cookie_handler(struct work_struct *unused); DECLARE_WORK(cookie_work, wq_cookie_handler); static struct timer_list app_process_wake_up_timer; static void app_process_wake_up_handler(unsigned long unused_data); -static uint32_t cookiemap_code(uint64_t value64) { +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); - cookiecode &= (COOKIEMAP_ENTRIES-1); + cookiecode &= (COOKIEMAP_ENTRIES - 1); return cookiecode * MAX_COLLISIONS; } -static uint32_t gator_chksum_crc32(char *data) +static uint32_t gator_chksum_crc32(const char *data) { register unsigned long crc; - unsigned char *block = data; + const unsigned char *block = data; int i, length = strlen(data); crc = 0xFFFFFFFF; @@ -57,7 +58,8 @@ static uint32_t gator_chksum_crc32(char *data) * Pre: [0][1][v][3]..[n-1] * Post: [v][0][1][3]..[n-1] */ -static uint32_t cookiemap_exists(uint64_t key) { +static uint32_t cookiemap_exists(uint64_t key) +{ unsigned long x, flags, retval = 0; int cpu = smp_processor_id(); uint32_t cookiecode = cookiemap_code(key); @@ -70,8 +72,8 @@ static uint32_t cookiemap_exists(uint64_t key) { if (keys[x] == key) { uint32_t value = values[x]; for (; x > 0; x--) { - keys[x] = keys[x-1]; - values[x] = values[x-1]; + keys[x] = keys[x - 1]; + values[x] = values[x - 1]; } keys[0] = key; values[0] = value; @@ -89,30 +91,31 @@ static uint32_t cookiemap_exists(uint64_t key) { * Pre: [0][1][2][3]..[n-1] * Post: [v][0][1][2]..[n-2] */ -static void cookiemap_add(uint64_t key, uint32_t value) { +static void cookiemap_add(uint64_t key, uint32_t value) +{ int cpu = smp_processor_id(); int cookiecode = cookiemap_code(key); uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]); uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]); int x; - for (x = MAX_COLLISIONS-1; x > 0; x--) { - keys[x] = keys[x-1]; - values[x] = values[x-1]; + for (x = MAX_COLLISIONS - 1; x > 0; x--) { + keys[x] = keys[x - 1]; + values[x] = values[x - 1]; } keys[0] = key; values[0] = value; } -static void translate_buffer_write_ptr(int cpu, void * x) +static void translate_buffer_write_ptr(int cpu, void *x) { per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x; per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask; } -static void * translate_buffer_read_ptr(int cpu) +static void *translate_buffer_read_ptr(int cpu) { - void * value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++]; + void *value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++]; per_cpu(translate_buffer_read, cpu) &= translate_buffer_mask; return value; } @@ -120,9 +123,9 @@ static void * translate_buffer_read_ptr(int cpu) static void wq_cookie_handler(struct work_struct *unused) { struct task_struct *task; - struct vm_area_struct *vma; + char *text; int cpu = smp_processor_id(); - unsigned int cookie, commit; + unsigned int commit; mutex_lock(&start_mutex); @@ -130,8 +133,8 @@ static void wq_cookie_handler(struct work_struct *unused) commit = per_cpu(translate_buffer_write, cpu); while (per_cpu(translate_buffer_read, cpu) != commit) { task = (struct task_struct *)translate_buffer_read_ptr(cpu); - vma = (struct vm_area_struct *)translate_buffer_read_ptr(cpu); - cookie = get_cookie(cpu, task, vma, NULL, false); + text = (char *)translate_buffer_read_ptr(cpu); + get_cookie(cpu, task, text, true); } } @@ -145,7 +148,7 @@ static void app_process_wake_up_handler(unsigned long unused_data) } // Retrieve full name from proc/pid/cmdline for java processes on Android -static int translate_app_process(char** text, int cpu, struct task_struct * task, struct vm_area_struct *vma, bool in_interrupt) +static int translate_app_process(const char **text, int cpu, struct task_struct *task, bool from_wq) { void *maddr; unsigned int len; @@ -154,12 +157,12 @@ static int translate_app_process(char** text, int cpu, struct task_struct * task struct page *page = NULL; struct vm_area_struct *page_vma; int bytes, offset, retval = 0, ptr; - char * buf = per_cpu(translate_text, cpu); + char *buf = per_cpu(translate_text, cpu); // 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 (in_interrupt) { + if (!from_wq) { // Check if already in buffer ptr = per_cpu(translate_buffer_read, cpu); while (ptr != per_cpu(translate_buffer_write, cpu)) { @@ -169,7 +172,7 @@ static int translate_app_process(char** text, int cpu, struct task_struct * task } translate_buffer_write_ptr(cpu, (void *)task); - translate_buffer_write_ptr(cpu, (void *)vma); + translate_buffer_write_ptr(cpu, (void *)*text); mod_timer(&app_process_wake_up_timer, jiffies + 1); goto out; @@ -192,7 +195,7 @@ static int translate_app_process(char** text, int cpu, struct task_struct * task goto outsem; maddr = kmap(page); - offset = addr & (PAGE_SIZE-1); + offset = addr & (PAGE_SIZE - 1); bytes = len; if (bytes > PAGE_SIZE - offset) bytes = PAGE_SIZE - offset; @@ -222,29 +225,10 @@ out: return retval; } -static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt) +static inline uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq) { unsigned long flags, cookie; - struct path *path; uint64_t key; - char *text; - - if (mod) { - text = mod->name; - } else { - if (vma && vma->vm_file) { - path = &vma->vm_file->f_path; - } else if (task && task->mm && task->mm->exe_file) { - path = &task->mm->exe_file->f_path; - } else { - return INVALID_COOKIE; - } - if (!path || !path->dentry) { - return INVALID_COOKIE; - } - - text = (char*)path->dentry->d_name.name; - } key = gator_chksum_crc32(text); key = (key << 32) | (uint32_t)task->tgid; @@ -254,8 +238,8 @@ static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_a return cookie; } - if (strcmp(text, "app_process") == 0 && !mod) { - if (!translate_app_process(&text, cpu, task, vma, in_interrupt)) + if (strcmp(text, "app_process") == 0) { + if (!translate_app_process(&text, cpu, task, from_wq)) return INVALID_COOKIE; } @@ -276,16 +260,19 @@ static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_a static int get_exec_cookie(int cpu, struct task_struct *task) { - unsigned long cookie = NO_COOKIE; struct mm_struct *mm = task->mm; + const char *text; // kernel threads have no address space if (!mm) - return cookie; + return NO_COOKIE; - cookie = get_cookie(cpu, task, NULL, NULL, true); + if (task && task->mm && task->mm->exe_file) { + text = task->mm->exe_file->f_path.dentry->d_name.name; + return get_cookie(cpu, task, text, false); + } - return cookie; + return INVALID_COOKIE; } static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsigned long addr, off_t *offset) @@ -293,6 +280,7 @@ static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsig unsigned long cookie = NO_COOKIE; struct mm_struct *mm = task->mm; struct vm_area_struct *vma; + const char *text; if (!mm) return cookie; @@ -302,7 +290,8 @@ static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsig continue; if (vma->vm_file) { - cookie = get_cookie(cpu, task, vma, NULL, true); + text = vma->vm_file->f_path.dentry->d_name.name; + cookie = get_cookie(cpu, task, text, false); *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; } else { /* must be an anonymous map */ @@ -323,14 +312,14 @@ static int cookies_initialize(void) uint32_t crc, poly; int i, j, cpu, size, err = 0; - int translate_buffer_size = 512; // must be a power of 2 + int translate_buffer_size = 512; // must be a power of 2 translate_buffer_mask = translate_buffer_size / sizeof(per_cpu(translate_buffer, 0)[0]) - 1; for_each_present_cpu(cpu) { 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) = (uint64_t *)kmalloc(size, GFP_KERNEL); if (!per_cpu(cookie_keys, cpu)) { err = -ENOMEM; goto cookie_setup_error; @@ -338,14 +327,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) = (uint32_t *)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) = (void * *)kmalloc(translate_buffer_size, GFP_KERNEL); + per_cpu(translate_buffer, cpu) = (void **)kmalloc(translate_buffer_size, GFP_KERNEL); if (!per_cpu(translate_buffer, cpu)) { err = -ENOMEM; goto cookie_setup_error; @@ -363,7 +352,7 @@ static int cookies_initialize(void) // build CRC32 table poly = 0x04c11db7; - gator_crc32_table = (uint32_t*)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL); + gator_crc32_table = (uint32_t *)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL); for (i = 0; i < 256; i++) { crc = i; for (j = 8; j > 0; j--) { diff --git a/driver/gator_events_armv6.c b/driver/gator_events_armv6.c index 5f989ba..ee36dd0 100644 --- a/driver/gator_events_armv6.c +++ b/driver/gator_events_armv6.c @@ -93,7 +93,7 @@ int gator_events_armv6_create_files(struct super_block *sb, struct dentry *root) return 0; } -static int gator_events_armv6_online(int** buffer) +static int gator_events_armv6_online(int **buffer) { unsigned int cnt, len = 0, cpu = smp_processor_id(); u32 pmnc; @@ -104,7 +104,7 @@ static int gator_events_armv6_online(int** buffer) /* initialize PMNC, reset overflow, D bit, C bit and P bit. */ armv6_pmnc_write(PMCR_OFL_PMN0 | PMCR_OFL_PMN1 | PMCR_OFL_CCNT | - PMCR_C | PMCR_P); + PMCR_C | PMCR_P); /* configure control register */ for (pmnc = 0, cnt = PMN0; cnt <= CCNT; cnt++) { @@ -141,7 +141,7 @@ static int gator_events_armv6_online(int** buffer) return len; } -static int gator_events_armv6_offline(int** buffer) +static int gator_events_armv6_offline(int **buffer) { unsigned int cnt; diff --git a/driver/gator_events_armv7.c b/driver/gator_events_armv7.c index 590421d..212b17b 100644 --- a/driver/gator_events_armv7.c +++ b/driver/gator_events_armv7.c @@ -22,7 +22,7 @@ #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 */ +#define PMNC_MASK 0x3f /* Mask for writable bits */ // ccnt reg #define CCNT_REG (1 << 31) @@ -63,7 +63,7 @@ inline u32 armv7_ccnt_read(u32 reset_value) 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, c13, 0" : : "r" (newval)); // new value asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable local_irq_restore(flags); @@ -82,7 +82,7 @@ inline u32 armv7_cntn_read(unsigned int cnt, u32 reset_value) 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, c13, 2" : : "r" (newval)); // new value asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable local_irq_restore(flags); @@ -143,7 +143,7 @@ static int gator_events_armv7_create_files(struct super_block *sb, struct dentry if (i == 0) { snprintf(buf, sizeof buf, "ARM_%s_ccnt", pmnc_name); } else { - snprintf(buf, sizeof buf, "ARM_%s_cnt%d", pmnc_name, i-1); + snprintf(buf, sizeof buf, "ARM_%s_cnt%d", pmnc_name, i - 1); } dir = gatorfs_mkdir(sb, root, buf); if (!dir) { @@ -159,7 +159,7 @@ static int gator_events_armv7_create_files(struct super_block *sb, struct dentry return 0; } -static int gator_events_armv7_online(int** buffer) +static int gator_events_armv7_online(int **buffer) { unsigned int cnt, len = 0, cpu = smp_processor_id(); @@ -214,11 +214,11 @@ static int gator_events_armv7_online(int** buffer) return len; } -static int gator_events_armv7_offline(int** buffer) +static int gator_events_armv7_offline(int **buffer) { - // disbale 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; } @@ -298,7 +298,7 @@ int gator_events_armv7_init(void) 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 b18c3ca..f512b13 100644 --- a/driver/gator_events_block.c +++ b/driver/gator_events_block.c @@ -119,7 +119,7 @@ static int gator_events_block_read(int **buffer) 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 + blockGet[len++] = 0; // indicates to Streamline that value bytes were written now, not since the last message blockGet[len++] = block_rq_wr_key; blockGet[len++] = value; data += value; @@ -127,7 +127,7 @@ 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 + blockGet[len++] = 0; // indicates to Streamline that value bytes were read now, not since the last message blockGet[len++] = block_rq_rd_key; blockGet[len++] = value; data += value; @@ -156,4 +156,5 @@ int gator_events_block_init(void) return gator_events_install(&gator_events_block_interface); } + gator_events_init(gator_events_block_init); diff --git a/driver/gator_events_irq.c b/driver/gator_events_irq.c index 435bc86..1221372 100644 --- a/driver/gator_events_irq.c +++ b/driver/gator_events_irq.c @@ -21,8 +21,8 @@ static ulong softirq_key; static DEFINE_PER_CPU(int[TOTALIRQ], irqCnt); static DEFINE_PER_CPU(int[TOTALIRQ * 2], irqGet); -GATOR_DEFINE_PROBE(irq_handler_exit, TP_PROTO(int irq, - struct irqaction *action, int ret)) +GATOR_DEFINE_PROBE(irq_handler_exit, + TP_PROTO(int irq, struct irqaction *action, int ret)) { unsigned long flags; @@ -71,10 +71,10 @@ static int gator_events_irq_create_files(struct super_block *sb, struct dentry * return 0; } -static int gator_events_irq_online(int** buffer) +static int gator_events_irq_online(int **buffer) { int len = 0, cpu = smp_processor_id(); - unsigned long flags; // not necessary as we are in interrupt context anyway, but doesn't hurt + unsigned long flags; // not necessary as we are in interrupt context anyway, but doesn't hurt // synchronization with the irq_exit functions is not necessary as the values are being reset if (hardirq_enabled) { @@ -136,7 +136,7 @@ static void gator_events_irq_stop(void) static int gator_events_irq_read(int **buffer) { - unsigned long flags; // not necessary as we are in interrupt context anyway, but doesn't hurt + unsigned long flags; // not necessary as we are in interrupt context anyway, but doesn't hurt int len, value; int cpu = smp_processor_id(); @@ -185,4 +185,5 @@ int gator_events_irq_init(void) return gator_events_install(&gator_events_irq_interface); } + gator_events_init(gator_events_irq_init); diff --git a/driver/gator_events_l2c-310.c b/driver/gator_events_l2c-310.c index bd1c48a..197af04 100644 --- a/driver/gator_events_l2c-310.c +++ b/driver/gator_events_l2c-310.c @@ -26,8 +26,6 @@ static int l2c310_buffer[L2C310_COUNTERS_NUM * 2]; static void __iomem *l2c310_base; - - static void gator_events_l2c310_reset_counters(void) { u32 val = readl(l2c310_base + L2X0_EVENT_CNT_CTRL); @@ -37,9 +35,8 @@ static void gator_events_l2c310_reset_counters(void) writel(val, l2c310_base + L2X0_EVENT_CNT_CTRL); } - static int gator_events_l2c310_create_files(struct super_block *sb, - struct dentry *root) + struct dentry *root) { int i; @@ -52,11 +49,11 @@ static int gator_events_l2c310_create_files(struct super_block *sb, if (WARN_ON(!dir)) return -1; gatorfs_create_ulong(sb, dir, "enabled", - &l2c310_counters[i].enabled); + &l2c310_counters[i].enabled); gatorfs_create_ulong(sb, dir, "event", - &l2c310_counters[i].event); + &l2c310_counters[i].event); gatorfs_create_ro_ulong(sb, dir, "key", - &l2c310_counters[i].key); + &l2c310_counters[i].key); } return 0; @@ -73,7 +70,7 @@ static int gator_events_l2c310_start(void) /* Counter event sources */ for (i = 0; i < L2C310_COUNTERS_NUM; i++) writel((l2c310_counters[i].event & 0xf) << 2, - l2c310_base + l2x0_event_cntx_cfg[i]); + l2c310_base + l2x0_event_cntx_cfg[i]); gator_events_l2c310_reset_counters(); @@ -105,10 +102,10 @@ static int gator_events_l2c310_read(int **buffer) if (l2c310_counters[i].enabled) { l2c310_buffer[len++] = l2c310_counters[i].key; l2c310_buffer[len++] = readl(l2c310_base + - l2x0_event_cntx_val[i]); + l2x0_event_cntx_val[i]); } } - + /* l2c310 counters are saturating, not wrapping in case of overflow */ gator_events_l2c310_reset_counters(); @@ -176,4 +173,5 @@ int gator_events_l2c310_init(void) return gator_events_install(&gator_events_l2c310_interface); } + gator_events_init(gator_events_l2c310_init); diff --git a/driver/gator_events_mali_400.c b/driver/gator_events_mali_400.c index a44cd8e..34a73c8 100644 --- a/driver/gator_events_mali_400.c +++ b/driver/gator_events_mali_400.c @@ -17,14 +17,6 @@ #include "gator_events_mali_common.h" #include "gator_events_mali_400.h" -#if !defined(GATOR_MALI_INTERFACE_STYLE) -/* - * At the moment, we only have users with the old style interface, so - * make our life easier by making it the default... - */ -#define GATOR_MALI_INTERFACE_STYLE (2) -#endif - /* * There are (currently) three different variants of the comms between gator and Mali: * 1 (deprecated): No software counter support @@ -60,81 +52,81 @@ #define NUM_FP_UNITS (4) enum counters { - /* Timeline activity */ - ACTIVITY_VP = 0, - ACTIVITY_FP0, - ACTIVITY_FP1, - ACTIVITY_FP2, - ACTIVITY_FP3, - - /* L2 cache counters */ - COUNTER_L2_C0, - COUNTER_L2_C1, - - /* Vertex processor counters */ - COUNTER_VP_C0, - COUNTER_VP_C1, - - /* Fragment processor counters */ - COUNTER_FP0_C0, - COUNTER_FP0_C1, - COUNTER_FP1_C0, - COUNTER_FP1_C1, - COUNTER_FP2_C0, - COUNTER_FP2_C1, - COUNTER_FP3_C0, - COUNTER_FP3_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 + /* Timeline activity */ + ACTIVITY_VP = 0, + ACTIVITY_FP0, + ACTIVITY_FP1, + ACTIVITY_FP2, + ACTIVITY_FP3, + + /* L2 cache counters */ + COUNTER_L2_C0, + COUNTER_L2_C1, + + /* Vertex processor counters */ + COUNTER_VP_C0, + COUNTER_VP_C1, + + /* Fragment processor counters */ + COUNTER_FP0_C0, + COUNTER_FP0_C1, + COUNTER_FP1_C0, + COUNTER_FP1_C1, + COUNTER_FP2_C0, + COUNTER_FP2_C1, + COUNTER_FP3_C0, + COUNTER_FP3_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 @@ -161,7 +153,7 @@ static unsigned long counter_key[NUMBER_OF_EVENTS]; /* The data we have recorded */ static u32 counter_data[NUMBER_OF_EVENTS]; /* The address to sample (or 0 if samples are sent to us) */ -static u32* counter_address[NUMBER_OF_EVENTS]; +static u32 *counter_address[NUMBER_OF_EVENTS]; /* An array used to return the data we recorded * as key,value pairs hence the *2 @@ -177,13 +169,12 @@ static int trace_registered; */ static u32 get_difference(u32 start, u32 end) { - if (start - end >= 0) - { - return start - end; - } + if (start - end >= 0) { + return start - end; + } - // Mali counters are unsigned 32 bit values that wrap. - return (4294967295u - end) + start; + // Mali counters are unsigned 32 bit values that wrap. + return (4294967295u - end) + start; } /** @@ -191,8 +182,8 @@ static u32 get_difference(u32 start, u32 end) */ static inline int is_activity_counter(unsigned int event_id) { - return (event_id >= FIRST_ACTIVITY_EVENT && - event_id <= LAST_ACTIVITY_EVENT); + return (event_id >= FIRST_ACTIVITY_EVENT && + event_id <= LAST_ACTIVITY_EVENT); } /** @@ -200,7 +191,7 @@ static inline int is_activity_counter(unsigned int event_id) */ static inline int is_hw_counter(unsigned int event_id) { - return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER); + return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER); } #if GATOR_MALI_INTERFACE_STYLE == 2 @@ -209,7 +200,7 @@ static inline int is_hw_counter(unsigned int event_id) */ static inline int is_sw_counter(unsigned int event_id) { - return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER); + return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER); } #endif @@ -217,209 +208,204 @@ static inline int is_sw_counter(unsigned int event_id) /* * The Mali DDK uses s64 types to contain software counter values, but gator * can only use a maximum of 32 bits. This function scales a software counter - * to an appopriate range. + * to an appropriate range. */ static u32 scale_sw_counter_value(unsigned int event_id, signed long long value) { - u32 scaled_value; - - switch (event_id) { - case COUNTER_GLES_UPLOAD_TEXTURE_TIME: - case COUNTER_GLES_UPLOAD_VBO_TIME: - scaled_value = (u32)div_s64(value, 1000000); - break; - default: - scaled_value = (u32)value; - break; - } - - return scaled_value; + u32 scaled_value; + + switch (event_id) { + case COUNTER_GLES_UPLOAD_TEXTURE_TIME: + case COUNTER_GLES_UPLOAD_VBO_TIME: + scaled_value = (u32)div_s64(value, 1000000); + break; + default: + scaled_value = (u32)value; + break; + } + + return scaled_value; } #endif /* 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)) +#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; - } + /* 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)) { - counter_data[event_id] = 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)) { + counter_data[event_id] = value; + } } #if GATOR_MALI_INTERFACE_STYLE == 2 GATOR_DEFINE_PROBE(mali_sw_counter, TP_PROTO(unsigned int event_id, signed long long value)) { - if (is_sw_counter(event_id)) { - counter_data[event_id] = scale_sw_counter_value(event_id, value); - } + if (is_sw_counter(event_id)) { + counter_data[event_id] = scale_sw_counter_value(event_id, value); + } } #endif /* GATOR_MALI_INTERFACE_STYLE == 2 */ - #if GATOR_MALI_INTERFACE_STYLE == 3 -GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void * surface_id, unsigned int * counters)) +GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surface_id, unsigned int *counters)) { - u32 i; - - /* Copy over the values for those counters which are enabled. */ - for(i=FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) - { - if(counter_enabled[i]) - { - counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]); - } - } + u32 i; + + /* Copy over the values for those counters which are enabled. */ + for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) { + if (counter_enabled[i]) { + counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]); + } + } } #endif /* GATOR_MALI_INTERFACE_STYLE == 3 */ -static int create_files(struct super_block *sb, struct dentry *root) { - struct dentry *dir; - int event; - int n_fp = NUM_FP_UNITS; - - const char* mali_name = gator_mali_get_mali_name(); - - /* - * Create the filesystem entries for vertex processor, fragement processor - * and L2 cache timeline and hardware counters. Software counters get - * special handling after this block. - */ - for (event = FIRST_ACTIVITY_EVENT; event <= LAST_HW_COUNTER; event++) - { - char buf[40]; - - /* - * We can skip this event if it's for a non-existent fragment - * processor. - */ - if (((event - ACTIVITY_FP0 >= n_fp) && (event < COUNTER_L2_C0)) || - (((event - COUNTER_FP0_C0)/2 >= n_fp))) - { - continue; - } - - /* Otherwise, set up the filesystem entry for this event. */ - switch (event) { - case ACTIVITY_VP: - snprintf(buf, sizeof buf, "ARM_%s_VP_active", mali_name); - break; - case ACTIVITY_FP0: - case ACTIVITY_FP1: - case ACTIVITY_FP2: - case ACTIVITY_FP3: - snprintf(buf, sizeof buf, "ARM_%s_FP%d_active", - mali_name, event - ACTIVITY_FP0); - break; - case COUNTER_L2_C0: - case COUNTER_L2_C1: - snprintf(buf, sizeof buf, "ARM_%s_L2_cnt%d", - mali_name, event - COUNTER_L2_C0); - break; - case COUNTER_VP_C0: - case COUNTER_VP_C1: - snprintf(buf, sizeof buf, "ARM_%s_VP_cnt%d", - mali_name, event - COUNTER_VP_C0); - break; - case COUNTER_FP0_C0: - case COUNTER_FP0_C1: - case COUNTER_FP1_C0: - case COUNTER_FP1_C1: - case COUNTER_FP2_C0: - case COUNTER_FP2_C1: - case COUNTER_FP3_C0: - case COUNTER_FP3_C1: - snprintf(buf, sizeof buf, "ARM_%s_FP%d_cnt%d", mali_name, - (event - COUNTER_FP0_C0) / 2, (event - COUNTER_FP0_C0) % 2); - break; - default: - printk("gator: trying to create file for non-existent counter (%d)\n", event); - continue; - } - - dir = gatorfs_mkdir(sb, root, buf); - - if (!dir) { - return -1; - } - - gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]); - - /* Only create an event node for counters that can change what they count */ - if (event >= COUNTER_L2_C0) { - gatorfs_create_ulong(sb, dir, "event", &counter_event[event]); - } - - gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]); - } - - /* Now set up the software counter entries */ - for (event = FIRST_SW_COUNTER; event <= LAST_SW_COUNTER; event++) - { - char buf[40]; - - snprintf(buf, sizeof(buf), "ARM_%s_SW_%d", mali_name, event); - - dir = gatorfs_mkdir(sb, root, buf); - - if (!dir) { - return -1; - } - - gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]); - gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]); - } - - /* Now set up the special counter entries */ - for (event = FIRST_SPECIAL_COUNTER; event <= LAST_SPECIAL_COUNTER; event++) - { - char buf[40]; - - switch(event) { - case COUNTER_FILMSTRIP: - snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip_cnt0", mali_name); - break; - - case COUNTER_FREQUENCY: - snprintf(buf, sizeof(buf), "ARM_%s_Frequency", mali_name); - break; - - case COUNTER_VOLTAGE: - snprintf(buf, sizeof(buf), "ARM_%s_Voltage", mali_name); - break; - - default: - break; - } - - dir = gatorfs_mkdir(sb, root, buf); - - if (!dir) { - return -1; - } - - 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]); - } - - return 0; +static int create_files(struct super_block *sb, struct dentry *root) +{ + struct dentry *dir; + int event; + int n_fp = NUM_FP_UNITS; + + const char *mali_name = gator_mali_get_mali_name(); + + /* + * Create the filesystem entries for vertex processor, fragment processor + * and L2 cache timeline and hardware counters. Software counters get + * special handling after this block. + */ + for (event = FIRST_ACTIVITY_EVENT; event <= LAST_HW_COUNTER; event++) { + char buf[40]; + + /* + * We can skip this event if it's for a non-existent fragment + * processor. + */ + if (((event - ACTIVITY_FP0 >= n_fp) && (event < COUNTER_L2_C0)) + || (((event - COUNTER_FP0_C0) / 2 >= n_fp))) { + continue; + } + + /* Otherwise, set up the filesystem entry for this event. */ + switch (event) { + case ACTIVITY_VP: + snprintf(buf, sizeof buf, "ARM_%s_VP_active", mali_name); + break; + case ACTIVITY_FP0: + case ACTIVITY_FP1: + case ACTIVITY_FP2: + case ACTIVITY_FP3: + snprintf(buf, sizeof buf, "ARM_%s_FP%d_active", + mali_name, event - ACTIVITY_FP0); + break; + case COUNTER_L2_C0: + case COUNTER_L2_C1: + snprintf(buf, sizeof buf, "ARM_%s_L2_cnt%d", + mali_name, event - COUNTER_L2_C0); + break; + case COUNTER_VP_C0: + case COUNTER_VP_C1: + snprintf(buf, sizeof buf, "ARM_%s_VP_cnt%d", + mali_name, event - COUNTER_VP_C0); + break; + case COUNTER_FP0_C0: + case COUNTER_FP0_C1: + case COUNTER_FP1_C0: + case COUNTER_FP1_C1: + case COUNTER_FP2_C0: + case COUNTER_FP2_C1: + case COUNTER_FP3_C0: + case COUNTER_FP3_C1: + snprintf(buf, sizeof buf, "ARM_%s_FP%d_cnt%d", + mali_name, (event - COUNTER_FP0_C0) / 2, + (event - COUNTER_FP0_C0) % 2); + break; + default: + printk("gator: trying to create file for non-existent counter (%d)\n", event); + continue; + } + + dir = gatorfs_mkdir(sb, root, buf); + + if (!dir) { + return -1; + } + + gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]); + + /* Only create an event node for counters that can change what they count */ + if (event >= COUNTER_L2_C0) { + gatorfs_create_ulong(sb, dir, "event", &counter_event[event]); + } + + gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]); + } + + /* Now set up the software counter entries */ + for (event = FIRST_SW_COUNTER; event <= LAST_SW_COUNTER; event++) { + char buf[40]; + + snprintf(buf, sizeof(buf), "ARM_%s_SW_%d", mali_name, event); + + dir = gatorfs_mkdir(sb, root, buf); + + if (!dir) { + return -1; + } + + gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]); + gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]); + } + + /* Now set up the special counter entries */ + for (event = FIRST_SPECIAL_COUNTER; event <= LAST_SPECIAL_COUNTER; event++) { + char buf[40]; + + switch (event) { + case COUNTER_FILMSTRIP: + snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip_cnt0", mali_name); + break; + + case COUNTER_FREQUENCY: + snprintf(buf, sizeof(buf), "ARM_%s_Frequency", mali_name); + break; + + case COUNTER_VOLTAGE: + snprintf(buf, sizeof(buf), "ARM_%s_Voltage", mali_name); + break; + + default: + break; + } + + dir = gatorfs_mkdir(sb, root, buf); + + if (!dir) { + return -1; + } + + 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]); + } + + return 0; } /* @@ -434,312 +420,311 @@ static mali_profiling_get_counters_type *mali_get_counters = NULL; */ static int is_any_sw_counter_enabled(void) { - unsigned int i; + unsigned int i; - for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) - { - if (counter_enabled[i]) - { - return 1; /* At least one counter is enabled */ - } - } + for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) { + if (counter_enabled[i]) { + return 1; /* At least one counter is enabled */ + } + } - return 0; /* No s/w counters enabled */ + return 0; /* No s/w counters enabled */ } -static void mali_counter_initialize(void) +static void mali_counter_initialize(void) { - /* If a Mali driver is present and exporting the appropriate symbol - * then we can request the HW counters (of which there are only 2) - * be configured to count the desired events - */ - mali_profiling_set_event_type *mali_set_hw_event; - mali_osk_fb_control_set_type *mali_set_fb_event; - mali_profiling_control_type *mali_control; - - mali_set_hw_event = symbol_get(_mali_profiling_set_event); - - if (mali_set_hw_event) { - int i; - - pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n",mali_set_hw_event); - - for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) { - if (counter_enabled[i]) { - mali_set_hw_event(i, counter_event[i]); - } else { - mali_set_hw_event(i, 0xFFFFFFFF); - } - } - - symbol_put(_mali_profiling_set_event); - } else { - printk("gator: mali online _mali_profiling_set_event symbol not found\n"); - } - - mali_set_fb_event = symbol_get(_mali_osk_fb_control_set); - - if (mali_set_fb_event) { - pr_debug("gator: mali online _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event); - - mali_set_fb_event(0,(counter_enabled[COUNTER_FILMSTRIP]?1:0)); - - symbol_put(_mali_osk_fb_control_set); - } else { - printk("gator: mali online _mali_osk_fb_control_set symbol not found\n"); - } - - /* Generic control interface for Mali DDK. */ - mali_control = symbol_get(_mali_profiling_control); - if (mali_control) { - /* The event attribute in the XML file keeps the actual frame rate. */ - unsigned int rate = counter_event[COUNTER_FILMSTRIP] & 0xff; - unsigned int resize_factor = (counter_event[COUNTER_FILMSTRIP] >> 8) & 0xff; - - pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control); - - mali_control(SW_EVENTS_ENABLE, (is_any_sw_counter_enabled()?1:0)); - mali_control(FBDUMP_CONTROL_ENABLE, (counter_enabled[COUNTER_FILMSTRIP]?1:0)); - mali_control(FBDUMP_CONTROL_RATE, rate); - mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor); - - pr_debug("gator: sent mali_control enabled=%d, rate=%d\n", (counter_enabled[COUNTER_FILMSTRIP]?1:0), rate); - - symbol_put(_mali_profiling_control); - } else { - printk("gator: mali online _mali_profiling_control symbol not found\n"); - } - - mali_get_counters = symbol_get(_mali_profiling_get_counters); - if (mali_get_counters){ - pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", mali_get_counters); - counter_prev[COUNTER_L2_C0] = 0; - counter_prev[COUNTER_L2_C1] = 0; - } - else{ - pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined"); - } + /* If a Mali driver is present and exporting the appropriate symbol + * then we can request the HW counters (of which there are only 2) + * be configured to count the desired events + */ + mali_profiling_set_event_type *mali_set_hw_event; + mali_osk_fb_control_set_type *mali_set_fb_event; + mali_profiling_control_type *mali_control; + + mali_set_hw_event = symbol_get(_mali_profiling_set_event); + + if (mali_set_hw_event) { + int i; + + pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n", mali_set_hw_event); + + for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) { + if (counter_enabled[i]) { + mali_set_hw_event(i, counter_event[i]); + } else { + mali_set_hw_event(i, 0xFFFFFFFF); + } + } + + symbol_put(_mali_profiling_set_event); + } else { + printk("gator: mali online _mali_profiling_set_event symbol not found\n"); + } + + mali_set_fb_event = symbol_get(_mali_osk_fb_control_set); + + if (mali_set_fb_event) { + pr_debug("gator: mali online _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event); + + mali_set_fb_event(0, (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0)); + + symbol_put(_mali_osk_fb_control_set); + } else { + printk("gator: mali online _mali_osk_fb_control_set symbol not found\n"); + } + + /* Generic control interface for Mali DDK. */ + mali_control = symbol_get(_mali_profiling_control); + if (mali_control) { + /* The event attribute in the XML file keeps the actual frame rate. */ + unsigned int rate = counter_event[COUNTER_FILMSTRIP] & 0xff; + unsigned int resize_factor = (counter_event[COUNTER_FILMSTRIP] >> 8) & 0xff; + + pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control); + + mali_control(SW_EVENTS_ENABLE, (is_any_sw_counter_enabled() ? 1 : 0)); + mali_control(FBDUMP_CONTROL_ENABLE, (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0)); + mali_control(FBDUMP_CONTROL_RATE, rate); + mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor); + + pr_debug("gator: sent mali_control enabled=%d, rate=%d\n", (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0), rate); + + symbol_put(_mali_profiling_control); + } else { + printk("gator: mali online _mali_profiling_control symbol not found\n"); + } + + mali_get_counters = symbol_get(_mali_profiling_get_counters); + if (mali_get_counters) { + pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", mali_get_counters); + counter_prev[COUNTER_L2_C0] = 0; + counter_prev[COUNTER_L2_C1] = 0; + } else { + pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined"); + } } -static void mali_counter_deinitialize(void) +static void mali_counter_deinitialize(void) { - mali_profiling_set_event_type *mali_set_hw_event; - mali_osk_fb_control_set_type *mali_set_fb_event; - mali_profiling_control_type *mali_control; + mali_profiling_set_event_type *mali_set_hw_event; + mali_osk_fb_control_set_type *mali_set_fb_event; + mali_profiling_control_type *mali_control; - mali_set_hw_event = symbol_get(_mali_profiling_set_event); + mali_set_hw_event = symbol_get(_mali_profiling_set_event); - if (mali_set_hw_event) { - 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++) { - 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"); - } + if (mali_set_hw_event) { + int i; - mali_set_fb_event = symbol_get(_mali_osk_fb_control_set); + 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++) { + mali_set_hw_event(i, 0xFFFFFFFF); + } - if (mali_set_fb_event) { - pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event); + symbol_put(_mali_profiling_set_event); + } else { + printk("gator: mali offline _mali_profiling_set_event symbol not found\n"); + } - mali_set_fb_event(0,0); + mali_set_fb_event = symbol_get(_mali_osk_fb_control_set); - symbol_put(_mali_osk_fb_control_set); - } else { - printk("gator: mali offline _mali_osk_fb_control_set symbol not found\n"); - } + if (mali_set_fb_event) { + pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event); - /* Generic control interface for Mali DDK. */ - mali_control = symbol_get(_mali_profiling_control); + mali_set_fb_event(0, 0); - if (mali_control) { - pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_set_fb_event); + symbol_put(_mali_osk_fb_control_set); + } else { + printk("gator: mali offline _mali_osk_fb_control_set symbol not found\n"); + } - /* Reset the DDK state - disable counter collection */ - mali_control(SW_EVENTS_ENABLE, 0); + /* Generic control interface for Mali DDK. */ + mali_control = symbol_get(_mali_profiling_control); - mali_control(FBDUMP_CONTROL_ENABLE, 0); + if (mali_control) { + pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_set_fb_event); - symbol_put(_mali_profiling_control); - } else { - printk("gator: mali offline _mali_profiling_control symbol not found\n"); - } + /* Reset the DDK state - disable counter collection */ + mali_control(SW_EVENTS_ENABLE, 0); - if (mali_get_counters){ - symbol_put(_mali_profiling_get_counters); - } + mali_control(FBDUMP_CONTROL_ENABLE, 0); + + symbol_put(_mali_profiling_control); + } else { + printk("gator: mali offline _mali_profiling_control symbol not found\n"); + } + + if (mali_get_counters) { + symbol_put(_mali_profiling_get_counters); + } } -static int start(void) { - // register tracepoints - if (GATOR_REGISTER_TRACE(mali_hw_counter)) { - printk("gator: mali_hw_counter tracepoint failed to activate\n"); - return -1; - } +static int start(void) +{ + // register tracepoints + if (GATOR_REGISTER_TRACE(mali_hw_counter)) { + printk("gator: mali_hw_counter tracepoint failed to activate\n"); + return -1; + } #if GATOR_MALI_INTERFACE_STYLE == 1 - /* None. */ + /* None. */ #elif GATOR_MALI_INTERFACE_STYLE == 2 - /* For patched Mali driver. */ - if (GATOR_REGISTER_TRACE(mali_sw_counter)) { - printk("gator: mali_sw_counter tracepoint failed to activate\n"); - return -1; - } + /* For patched Mali driver. */ + if (GATOR_REGISTER_TRACE(mali_sw_counter)) { + printk("gator: mali_sw_counter tracepoint failed to activate\n"); + return -1; + } #elif GATOR_MALI_INTERFACE_STYLE == 3 /* For Mali drivers with built-in support. */ - if (GATOR_REGISTER_TRACE(mali_sw_counters)) { - printk("gator: mali_sw_counters tracepoint failed to activate\n"); - return -1; - } + if (GATOR_REGISTER_TRACE(mali_sw_counters)) { + printk("gator: mali_sw_counters tracepoint failed to activate\n"); + return -1; + } #else #error Unknown GATOR_MALI_INTERFACE_STYLE option. #endif - trace_registered = 1; + trace_registered = 1; - mali_counter_initialize(); - return 0; + mali_counter_initialize(); + return 0; } -static void stop(void) { - unsigned int cnt; +static void stop(void) +{ + unsigned int cnt; - pr_debug("gator: mali stop\n"); + pr_debug("gator: mali stop\n"); - if (trace_registered) { - GATOR_UNREGISTER_TRACE(mali_hw_counter); + if (trace_registered) { + GATOR_UNREGISTER_TRACE(mali_hw_counter); #if GATOR_MALI_INTERFACE_STYLE == 1 - /* None. */ + /* None. */ #elif GATOR_MALI_INTERFACE_STYLE == 2 - /* For patched Mali driver. */ - GATOR_UNREGISTER_TRACE(mali_sw_counter); + /* For patched Mali driver. */ + GATOR_UNREGISTER_TRACE(mali_sw_counter); #elif GATOR_MALI_INTERFACE_STYLE == 3 - /* For Mali drivers with built-in support. */ - GATOR_UNREGISTER_TRACE(mali_sw_counters); + /* For Mali drivers with built-in support. */ + GATOR_UNREGISTER_TRACE(mali_sw_counters); #else #error Unknown GATOR_MALI_INTERFACE_STYLE option. #endif - pr_debug("gator: mali timeline tracepoint deactivated\n"); - - trace_registered = 0; - } + pr_debug("gator: mali timeline tracepoint deactivated\n"); - for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) { - counter_enabled[cnt] = 0; - counter_event[cnt] = 0; - counter_address[cnt] = NULL; - } + trace_registered = 0; + } - mali_counter_deinitialize(); + for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) { + counter_enabled[cnt] = 0; + counter_event[cnt] = 0; + counter_address[cnt] = NULL; + } + + mali_counter_deinitialize(); } -static int read(int **buffer) { - int cnt, len = 0; - - if (smp_processor_id()) return 0; - - // Read the L2 C0 and C1 here. - if (counter_enabled[COUNTER_L2_C0] || counter_enabled[COUNTER_L2_C1] ) { - u32 src0 = 0; - u32 val0 = 0; - u32 src1 = 0; - u32 val1 = 0; - - // Poke the driver to get the counter values - if (mali_get_counters){ - mali_get_counters(&src0, &val0, &src1, &val1); - } - - if (counter_enabled[COUNTER_L2_C0]) - { - // Calculate and save src0's counter val0 - counter_dump[len++] = counter_key[COUNTER_L2_C0]; - counter_dump[len++] = get_difference(val0, counter_prev[COUNTER_L2_C0]); - } - - if (counter_enabled[COUNTER_L2_C1]) - { - // Calculate and save src1's counter val1 - counter_dump[len++] = counter_key[COUNTER_L2_C1]; - counter_dump[len++] = get_difference(val1, counter_prev[COUNTER_L2_C1]); - } - - // Save the previous values for the counters. - counter_prev[COUNTER_L2_C0] = val0; - counter_prev[COUNTER_L2_C1] = val1; - } - - // Process other (non-timeline) counters. - for (cnt = COUNTER_VP_C0; cnt <= LAST_SW_COUNTER; cnt++) { - if (counter_enabled[cnt]) { - counter_dump[len++] = counter_key[cnt]; - counter_dump[len++] = counter_data[cnt]; - - counter_data[cnt] = 0; - } - } - - /* - * 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]) { - counter_dump[len++] = counter_key[cnt]; - counter_dump[len++] = counter_data[cnt]; - } - - cnt = COUNTER_VOLTAGE; - if (counter_enabled[cnt]) { - counter_dump[len++] = counter_key[cnt]; - counter_dump[len++] = counter_data[cnt]; - } - - - if (buffer) { - *buffer = (int*) counter_dump; - } - - return len; +static int read(int **buffer) +{ + int cnt, len = 0; + + if (smp_processor_id()) + return 0; + + // Read the L2 C0 and C1 here. + if (counter_enabled[COUNTER_L2_C0] || counter_enabled[COUNTER_L2_C1]) { + u32 src0 = 0; + u32 val0 = 0; + u32 src1 = 0; + u32 val1 = 0; + + // Poke the driver to get the counter values + if (mali_get_counters) { + mali_get_counters(&src0, &val0, &src1, &val1); + } + + if (counter_enabled[COUNTER_L2_C0]) { + // Calculate and save src0's counter val0 + counter_dump[len++] = counter_key[COUNTER_L2_C0]; + counter_dump[len++] = get_difference(val0, counter_prev[COUNTER_L2_C0]); + } + + if (counter_enabled[COUNTER_L2_C1]) { + // Calculate and save src1's counter val1 + counter_dump[len++] = counter_key[COUNTER_L2_C1]; + counter_dump[len++] = get_difference(val1, counter_prev[COUNTER_L2_C1]); + } + + // Save the previous values for the counters. + counter_prev[COUNTER_L2_C0] = val0; + counter_prev[COUNTER_L2_C1] = val1; + } + + // Process other (non-timeline) counters. + for (cnt = COUNTER_VP_C0; cnt <= LAST_SW_COUNTER; cnt++) { + if (counter_enabled[cnt]) { + counter_dump[len++] = counter_key[cnt]; + counter_dump[len++] = counter_data[cnt]; + + counter_data[cnt] = 0; + } + } + + /* + * 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]) { + counter_dump[len++] = counter_key[cnt]; + counter_dump[len++] = counter_data[cnt]; + } + + cnt = COUNTER_VOLTAGE; + if (counter_enabled[cnt]) { + counter_dump[len++] = counter_key[cnt]; + counter_dump[len++] = counter_data[cnt]; + } + + if (buffer) { + *buffer = (int *)counter_dump; + } + + return len; } static struct gator_interface gator_events_mali_interface = { - .create_files = create_files, - .start = start, - .stop = stop, - .read = read, + .create_files = create_files, + .start = start, + .stop = stop, + .read = read, }; -extern void gator_events_mali_log_dvfs_event(unsigned int frequency_mhz, unsigned int voltage_mv) { +extern void gator_events_mali_log_dvfs_event(unsigned int frequency_mhz, unsigned int voltage_mv) +{ counter_data[COUNTER_FREQUENCY] = frequency_mhz; counter_data[COUNTER_VOLTAGE] = voltage_mv; } int gator_events_mali_init(void) { - unsigned int cnt; + unsigned int cnt; - pr_debug("gator: mali init\n"); + pr_debug("gator: mali init\n"); - for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) { - counter_enabled[cnt] = 0; - counter_event[cnt] = 0; - counter_key[cnt] = gator_events_get_key(); - counter_address[cnt] = NULL; - counter_data[cnt] = 0; - } + for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) { + counter_enabled[cnt] = 0; + counter_event[cnt] = 0; + counter_key[cnt] = gator_events_get_key(); + counter_address[cnt] = NULL; + counter_data[cnt] = 0; + } - trace_registered = 0; + trace_registered = 0; - return gator_events_install(&gator_events_mali_interface); + return gator_events_install(&gator_events_mali_interface); } gator_events_init(gator_events_mali_init); diff --git a/driver/gator_events_mali_common.c b/driver/gator_events_mali_common.c index 62e441c..2186eee 100644 --- a/driver/gator_events_mali_common.c +++ b/driver/gator_events_mali_common.c @@ -10,69 +10,65 @@ static u32 gator_mali_get_id(void) { - return MALI_SUPPORT; + return MALI_SUPPORT; } -extern const char* gator_mali_get_mali_name(void) +extern const char *gator_mali_get_mali_name(void) { - u32 id = gator_mali_get_id(); + u32 id = gator_mali_get_id(); - switch (id) { - case MALI_T6xx: - return "Mali-T6xx"; - case MALI_400: - return "Mali-400"; - default: - pr_debug("gator: Mali-T6xx: unknown Mali ID (%d)\n", id); - return "Mali-Unknown"; - } + switch (id) { + case MALI_T6xx: + return "Mali-T6xx"; + case MALI_400: + return "Mali-400"; + default: + pr_debug("gator: Mali-T6xx: unknown Mali ID (%d)\n", id); + return "Mali-Unknown"; + } } -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) +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) { - int err; - char buf[255]; - struct dentry *dir; + int err; + char buf[255]; + struct dentry *dir; - /* If the counter name is empty ignore it*/ - if (strlen(event_name) != 0) - { - /* Set up the filesystem entry for this event. */ - snprintf(buf, sizeof(buf), "ARM_%s_%s", mali_name, event_name); + /* If the counter name is empty ignore it */ + if (strlen(event_name) != 0) { + /* Set up the filesystem entry for this event. */ + snprintf(buf, sizeof(buf), "ARM_%s_%s", mali_name, event_name); - dir = gatorfs_mkdir(sb, root, buf); + dir = gatorfs_mkdir(sb, root, buf); - if (dir == NULL) - { - pr_debug("gator: Mali-T6xx: error creating file system for: %s (%s)", event_name, buf); - return -1; - } + if (dir == NULL) { + pr_debug("gator: Mali-T6xx: error creating file system for: %s (%s)", event_name, buf); + return -1; + } - err = gatorfs_create_ulong(sb, dir, "enabled", &counter->enabled); - if (err != 0) - { - pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ulong for: %s (%s)", event_name, buf); - return -1; - } - err = gatorfs_create_ro_ulong(sb, dir, "key", &counter->key); - if (err != 0) - { - pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf); - return -1; - } - } + err = gatorfs_create_ulong(sb, dir, "enabled", &counter->enabled); + if (err != 0) { + pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ulong for: %s (%s)", event_name, buf); + return -1; + } + err = gatorfs_create_ro_ulong(sb, dir, "key", &counter->key); + if (err != 0) { + pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf); + return -1; + } + } - return 0; + return 0; } extern void gator_mali_initialise_counters(mali_counter counters[], unsigned int n_counters) { - unsigned int cnt; + unsigned int cnt; - for (cnt = 0; cnt < n_counters; cnt++) { - mali_counter *counter = &counters[cnt]; + for (cnt = 0; cnt < n_counters; cnt++) { + mali_counter *counter = &counters[cnt]; - counter->key = gator_events_get_key(); - counter->enabled = 0; - } + 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 2c9457f..8e33edf 100644 --- a/driver/gator_events_mali_common.h +++ b/driver/gator_events_mali_common.h @@ -35,8 +35,8 @@ * Runtime state information for a counter. */ typedef struct { - unsigned long key; /* 'key' (a unique id set by gatord and returned by gator.ko) */ - unsigned long enabled; /* counter enable state */ + unsigned long key; /* 'key' (a unique id set by gatord and returned by gator.ko) */ + unsigned long enabled; /* counter enable state */ } mali_counter; /* @@ -45,7 +45,7 @@ typedef struct { typedef void mali_profiling_set_event_type(unsigned int, unsigned int); typedef void mali_osk_fb_control_set_type(unsigned int, unsigned 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*); +typedef void mali_profiling_get_counters_type(unsigned int *, unsigned int *, unsigned int *, unsigned int *); /* * Driver entry points for functions called directly by gator. @@ -53,14 +53,14 @@ typedef void mali_profiling_get_counters_type(unsigned int*, unsigned int*, unsi extern void _mali_profiling_set_event(unsigned int, unsigned int); extern void _mali_osk_fb_control_set(unsigned int, unsigned int); extern void _mali_profiling_control(unsigned int, unsigned int); -extern void _mali_profiling_get_counters(unsigned int*, unsigned int*, unsigned int*, unsigned int*); +extern void _mali_profiling_get_counters(unsigned int *, unsigned int *, unsigned int *, unsigned int *); /** * Returns a name which identifies the GPU type (eg Mali-400, Mali-T6xx). * * @return The name as a constant string. */ -extern const char* gator_mali_get_mali_name(void); +extern const char *gator_mali_get_mali_name(void); /** * Creates a filesystem entry under /dev/gator relating to the specified event name and key, and @@ -75,10 +75,10 @@ extern const char* gator_mali_get_mali_name(void); * * @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); +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); /** - * Initialises the counter array. + * Initializes the counter array. * * @param keys The array of counters * @param n_counters The number of entries in each of the arrays. diff --git a/driver/gator_events_mali_t6xx.c b/driver/gator_events_mali_t6xx.c index f8f868e..1b3a53d 100644 --- a/driver/gator_events_mali_t6xx.c +++ b/driver/gator_events_mali_t6xx.c @@ -17,7 +17,6 @@ #include "linux/mali_linux_trace.h" - #include "gator_events_mali_common.h" /* @@ -27,7 +26,6 @@ #error MALI_SUPPORT set to an invalid device code: expecting MALI_T6xx #endif - /* Counters for Mali-T6xx: * * - Timeline events @@ -43,72 +41,66 @@ */ /* Timeline (start/stop) activity */ -static const char* timeline_event_names [] = -{ - "PM_SHADER_0", - "PM_SHADER_1", - "PM_SHADER_2", - "PM_SHADER_3", - "PM_SHADER_4", - "PM_SHADER_5", - "PM_SHADER_6", - "PM_SHADER_7", - "PM_TILER_0", - "PM_L2_0", - "PM_L2_1", - "MMU_AS_0", - "MMU_AS_1", - "MMU_AS_2", - "MMU_AS_3" +static const char *timeline_event_names[] = { + "PM_SHADER_0", + "PM_SHADER_1", + "PM_SHADER_2", + "PM_SHADER_3", + "PM_SHADER_4", + "PM_SHADER_5", + "PM_SHADER_6", + "PM_SHADER_7", + "PM_TILER_0", + "PM_L2_0", + "PM_L2_1", + "MMU_AS_0", + "MMU_AS_1", + "MMU_AS_2", + "MMU_AS_3" }; -enum -{ - PM_SHADER_0 = 0, - PM_SHADER_1, - PM_SHADER_2, - PM_SHADER_3, - PM_SHADER_4, - PM_SHADER_5, - PM_SHADER_6, - PM_SHADER_7, - PM_TILER_0, - PM_L2_0, - PM_L2_1, - MMU_AS_0, - MMU_AS_1, - MMU_AS_2, - MMU_AS_3 +enum { + PM_SHADER_0 = 0, + PM_SHADER_1, + PM_SHADER_2, + PM_SHADER_3, + PM_SHADER_4, + PM_SHADER_5, + PM_SHADER_6, + PM_SHADER_7, + PM_TILER_0, + PM_L2_0, + PM_L2_1, + MMU_AS_0, + MMU_AS_1, + MMU_AS_2, + MMU_AS_3 }; /* The number of shader blocks in the enum above */ #define NUM_PM_SHADER (8) /* Software Counters */ -static const char* software_counter_names [] = -{ - "MMU_PAGE_FAULT_0", - "MMU_PAGE_FAULT_1", - "MMU_PAGE_FAULT_2", - "MMU_PAGE_FAULT_3" +static const char *software_counter_names[] = { + "MMU_PAGE_FAULT_0", + "MMU_PAGE_FAULT_1", + "MMU_PAGE_FAULT_2", + "MMU_PAGE_FAULT_3" }; -enum -{ - MMU_PAGE_FAULT_0 = 0, - MMU_PAGE_FAULT_1, - MMU_PAGE_FAULT_2, - MMU_PAGE_FAULT_3 +enum { + MMU_PAGE_FAULT_0 = 0, + MMU_PAGE_FAULT_1, + MMU_PAGE_FAULT_2, + MMU_PAGE_FAULT_3 }; /* Software Counters */ -static const char* accumulators_names [] = -{ - "TOTAL_ALLOC_PAGES" +static const char *accumulators_names[] = { + "TOTAL_ALLOC_PAGES" }; -enum -{ - TOTAL_ALLOC_PAGES = 0 +enum { + TOTAL_ALLOC_PAGES = 0 }; #define FIRST_TIMELINE_EVENT (0) @@ -153,49 +145,46 @@ 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; + 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; + return event_duration_us; } static void record_timeline_event(unsigned int timeline_index, unsigned int type) { - struct timespec event_timestamp; - struct timespec *event_start = &timeline_event_starttime[timeline_index]; - - switch(type) - { - case ACTIVITY_START: - /* Get the event time... */ - getnstimeofday(&event_timestamp); - - /* Remember the start time if the activity is not already started */ - if(event_start->tv_sec == 0) - { - *event_start = event_timestamp; /* Structure copy */ - } - break; - - case ACTIVITY_STOP: - /* if the counter was started... */ - if(event_start->tv_sec != 0) - { - /* Get the event time... */ - getnstimeofday(&event_timestamp); - - /* Accumulate the duration in us */ - timeline_data[timeline_index] += get_duration_us(event_start, &event_timestamp); - - /* Reset the start time to indicate the activity is stopped. */ - event_start->tv_sec = 0; - } - break; - - default: - /* Other activity events are ignored. */ - break; - } + struct timespec event_timestamp; + struct timespec *event_start = &timeline_event_starttime[timeline_index]; + + switch (type) { + case ACTIVITY_START: + /* Get the event time... */ + getnstimeofday(&event_timestamp); + + /* Remember the start time if the activity is not already started */ + if (event_start->tv_sec == 0) { + *event_start = event_timestamp; /* Structure copy */ + } + break; + + case ACTIVITY_STOP: + /* if the counter was started... */ + if (event_start->tv_sec != 0) { + /* Get the event time... */ + getnstimeofday(&event_timestamp); + + /* Accumulate the duration in us */ + timeline_data[timeline_index] += get_duration_us(event_start, &event_timestamp); + + /* Reset the start time to indicate the activity is stopped. */ + event_start->tv_sec = 0; + } + break; + + default: + /* Other activity events are ignored. */ + break; + } } /* @@ -204,68 +193,62 @@ static void record_timeline_event(unsigned int timeline_index, unsigned int type GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long long value)) { -#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */ -#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */ -#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */ +#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */ +#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */ +#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; - - switch (event_id) - { - case SHADER_PRESENT_LO: - { - unsigned long long changed_bitmask = previous_shader_bitmask ^ value; - int pos; - - for (pos = 0; pos < NUM_PM_SHADER; ++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; - break; - } - - case TILER_PRESENT_LO: - { - unsigned long long changed = previous_tiler_bitmask ^ value; - - if (BIT_AT(changed, 0)) - { - record_timeline_event(PM_TILER_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP); - } - - previous_tiler_bitmask = value; - break; - } - - case L2_PRESENT_LO: - { - unsigned long long changed = previous_l2_bitmask ^ value; - - if (BIT_AT(changed, 0)) - { - record_timeline_event(PM_L2_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP); - } - if (BIT_AT(changed, 4)) - { - record_timeline_event(PM_L2_1, BIT_AT(value, 4) ? ACTIVITY_START : ACTIVITY_STOP); - } - - previous_l2_bitmask = value; - break; - } - - default: - /* No other blocks are supported at present */ - break; - } + static unsigned long long previous_shader_bitmask = 0; + static unsigned long long previous_tiler_bitmask = 0; + static unsigned long long previous_l2_bitmask = 0; + + switch (event_id) { + case SHADER_PRESENT_LO: + { + unsigned long long changed_bitmask = previous_shader_bitmask ^ value; + int pos; + + for (pos = 0; pos < NUM_PM_SHADER; ++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; + break; + } + + case TILER_PRESENT_LO: + { + unsigned long long changed = previous_tiler_bitmask ^ value; + + if (BIT_AT(changed, 0)) { + record_timeline_event(PM_TILER_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP); + } + + previous_tiler_bitmask = value; + break; + } + + case L2_PRESENT_LO: + { + unsigned long long changed = previous_l2_bitmask ^ value; + + if (BIT_AT(changed, 0)) { + record_timeline_event(PM_L2_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP); + } + if (BIT_AT(changed, 4)) { + record_timeline_event(PM_L2_1, BIT_AT(value, 4) ? ACTIVITY_START : ACTIVITY_STOP); + } + + previous_l2_bitmask = value; + break; + } + + default: + /* No other blocks are supported at present */ + break; + } #undef SHADER_PRESENT_LO #undef TILER_PRESENT_LO @@ -275,278 +258,255 @@ GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long GATOR_DEFINE_PROBE(mali_page_fault_insert_pages, TP_PROTO(int event_id, unsigned long value)) { - /* We add to the previous since we may receive many tracepoints in one sample period */ - sw_counter_data[MMU_PAGE_FAULT_0 + event_id] += value; + /* We add to the previous since we may receive many tracepoints in one sample period */ + sw_counter_data[MMU_PAGE_FAULT_0 + event_id] += value; } GATOR_DEFINE_PROBE(mali_mmu_as_in_use, TP_PROTO(int event_id)) { - record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_START); + record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_START); } GATOR_DEFINE_PROBE(mali_mmu_as_released, TP_PROTO(int event_id)) { - record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_STOP); + record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_STOP); } GATOR_DEFINE_PROBE(mali_total_alloc_pages_change, TP_PROTO(long long int event_id)) { - accumulators_data[TOTAL_ALLOC_PAGES] = event_id; + accumulators_data[TOTAL_ALLOC_PAGES] = event_id; } static int create_files(struct super_block *sb, struct dentry *root) { - int event; - /* - * Create the filesystem for all events - */ - int counter_index = 0; - const char* mali_name = gator_mali_get_mali_name(); - - 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]) != 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]) != 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]) != 0) - { - return -1; - } - counter_index++; - } - - return 0; + int event; + /* + * Create the filesystem for all events + */ + int counter_index = 0; + const char *mali_name = gator_mali_get_mali_name(); + + 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]) != 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]) != 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]) != 0) { + return -1; + } + counter_index++; + } + + return 0; } static int register_tracepoints(void) { - if (GATOR_REGISTER_TRACE(mali_pm_status)) - { - pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint failed to activate\n"); - return 0; - } - - if (GATOR_REGISTER_TRACE(mali_page_fault_insert_pages)) - { - pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint failed to activate\n"); - return 0; - } - - if (GATOR_REGISTER_TRACE(mali_mmu_as_in_use)) - { - pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint failed to activate\n"); - return 0; - } - - if (GATOR_REGISTER_TRACE(mali_mmu_as_released)) - { - pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint failed to activate\n"); - return 0; - } - - if (GATOR_REGISTER_TRACE(mali_total_alloc_pages_change)) - { - pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint failed to activate\n"); - return 0; - } - - pr_debug("gator: Mali-T6xx: start\n"); - pr_debug("gator: Mali-T6xx: mali_pm_status probe is at %p\n", &probe_mali_pm_status); - pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages probe is at %p\n", &probe_mali_page_fault_insert_pages); - pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use probe is at %p\n", &probe_mali_mmu_as_in_use); - pr_debug("gator: Mali-T6xx: mali_mmu_as_released probe is at %p\n", &probe_mali_mmu_as_released); - pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change probe is at %p\n", &probe_mali_total_alloc_pages_change); - - return 1; + if (GATOR_REGISTER_TRACE(mali_pm_status)) { + pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint failed to activate\n"); + return 0; + } + + if (GATOR_REGISTER_TRACE(mali_page_fault_insert_pages)) { + pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint failed to activate\n"); + return 0; + } + + if (GATOR_REGISTER_TRACE(mali_mmu_as_in_use)) { + pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint failed to activate\n"); + return 0; + } + + if (GATOR_REGISTER_TRACE(mali_mmu_as_released)) { + pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint failed to activate\n"); + return 0; + } + + if (GATOR_REGISTER_TRACE(mali_total_alloc_pages_change)) { + pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint failed to activate\n"); + return 0; + } + + pr_debug("gator: Mali-T6xx: start\n"); + pr_debug("gator: Mali-T6xx: mali_pm_status probe is at %p\n", &probe_mali_pm_status); + pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages probe is at %p\n", &probe_mali_page_fault_insert_pages); + pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use probe is at %p\n", &probe_mali_mmu_as_in_use); + pr_debug("gator: Mali-T6xx: mali_mmu_as_released probe is at %p\n", &probe_mali_mmu_as_released); + pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change probe is at %p\n", &probe_mali_total_alloc_pages_change); + + return 1; } static int start(void) { - unsigned int cnt; - - /* Clean all data for the next capture */ - for (cnt = 0; cnt < NUMBER_OF_TIMELINE_EVENTS; cnt++) - { - timeline_event_starttime[cnt].tv_sec = timeline_event_starttime[cnt].tv_nsec = 0; - timeline_data[cnt] = 0; - } - - for (cnt = 0; cnt < NUMBER_OF_SOFTWARE_COUNTERS; cnt++) - { - sw_counter_data[cnt] = 0; - } - - for (cnt = 0; cnt < NUMBER_OF_ACCUMULATORS; cnt++) - { - accumulators_data[cnt] = 0; - } - - /* Register tracepoints */ - if (register_tracepoints() == 0) - { - return -1; - } - - /* - * Set the first timestamp for calculating the sample interval. The first interval could be quite long, - * since it will be the time between 'start' and the first 'read'. - * This means that timeline values will be divided by a big number for the first sample. - */ - getnstimeofday(&prev_timestamp); - - return 0; + unsigned int cnt; + + /* Clean all data for the next capture */ + for (cnt = 0; cnt < NUMBER_OF_TIMELINE_EVENTS; cnt++) { + timeline_event_starttime[cnt].tv_sec = timeline_event_starttime[cnt].tv_nsec = 0; + timeline_data[cnt] = 0; + } + + for (cnt = 0; cnt < NUMBER_OF_SOFTWARE_COUNTERS; cnt++) { + sw_counter_data[cnt] = 0; + } + + for (cnt = 0; cnt < NUMBER_OF_ACCUMULATORS; cnt++) { + accumulators_data[cnt] = 0; + } + + /* Register tracepoints */ + if (register_tracepoints() == 0) { + return -1; + } + + /* + * Set the first timestamp for calculating the sample interval. The first interval could be quite long, + * since it will be the time between 'start' and the first 'read'. + * This means that timeline values will be divided by a big number for the first sample. + */ + getnstimeofday(&prev_timestamp); + + return 0; } static void stop(void) { - pr_debug("gator: Mali-T6xx: stop\n"); + pr_debug("gator: Mali-T6xx: stop\n"); - /* - * It is safe to unregister traces even if they were not successfully - * registered, so no need to check. - */ - GATOR_UNREGISTER_TRACE(mali_pm_status); - pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint deactivated\n"); + /* + * It is safe to unregister traces even if they were not successfully + * registered, so no need to check. + */ + GATOR_UNREGISTER_TRACE(mali_pm_status); + pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint deactivated\n"); - GATOR_UNREGISTER_TRACE(mali_page_fault_insert_pages); - pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint deactivated\n"); + GATOR_UNREGISTER_TRACE(mali_page_fault_insert_pages); + pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint deactivated\n"); - GATOR_UNREGISTER_TRACE(mali_mmu_as_in_use); - pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint deactivated\n"); + GATOR_UNREGISTER_TRACE(mali_mmu_as_in_use); + pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint deactivated\n"); - GATOR_UNREGISTER_TRACE(mali_mmu_as_released); - pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint deactivated\n"); + GATOR_UNREGISTER_TRACE(mali_mmu_as_released); + pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint deactivated\n"); - GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change); - pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint deactivated\n"); + GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change); + pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint deactivated\n"); } static int read(int **buffer) { - int cnt; - int len = 0; - long sample_interval_us = 0; - struct timespec read_timestamp; - - if (smp_processor_id()!=0) - { - return 0; - } - - /* Get the start of this sample period. */ - getnstimeofday(&read_timestamp); - - /* - * 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) { - sample_interval_us = get_duration_us(&prev_timestamp, &read_timestamp); - } - - /* Structure copy. Update the previous timestamp. */ - prev_timestamp = read_timestamp; - - /* - * 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]; - 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(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. */ - } - - if(sample_interval_us != 0) { - /* Convert the counter to a percent-of-sample value */ - value = (timeline_data[index] * 100) / sample_interval_us; - } else { - pr_debug("gator: Mali-T6xx: setting value to zero\n"); - value = 0; - } - - /* Clear the counter value ready for the next sample. */ - timeline_data[index] = 0; - - counter_dump[len++] = counter->key; - counter_dump[len++] = value; - } - } - - /* Report the software counters */ - for (cnt = FIRST_SOFTWARE_COUNTER; cnt < (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS); cnt++) - { - const 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 */ - sw_counter_data[index] = 0; - } - } - - /* Report the accumulators */ - for (cnt = FIRST_ACCUMULATOR; cnt < (FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS); cnt++) - { - const 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 */ - } - } - - /* Update the buffer */ - if (buffer) - { - *buffer = (int*) counter_dump; - } - - return len; + int cnt; + int len = 0; + long sample_interval_us = 0; + struct timespec read_timestamp; + + if (smp_processor_id() != 0) { + return 0; + } + + /* Get the start of this sample period. */ + getnstimeofday(&read_timestamp); + + /* + * 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) { + sample_interval_us = get_duration_us(&prev_timestamp, &read_timestamp); + } + + /* Structure copy. Update the previous timestamp. */ + prev_timestamp = read_timestamp; + + /* + * 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]; + 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 (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. */ + } + + if (sample_interval_us != 0) { + /* Convert the counter to a percent-of-sample value */ + value = (timeline_data[index] * 100) / sample_interval_us; + } else { + pr_debug("gator: Mali-T6xx: setting value to zero\n"); + value = 0; + } + + /* Clear the counter value ready for the next sample. */ + timeline_data[index] = 0; + + counter_dump[len++] = counter->key; + counter_dump[len++] = value; + } + } + + /* Report the software counters */ + for (cnt = FIRST_SOFTWARE_COUNTER; cnt < (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS); cnt++) { + const 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 */ + sw_counter_data[index] = 0; + } + } + + /* Report the accumulators */ + for (cnt = FIRST_ACCUMULATOR; cnt < (FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS); cnt++) { + const 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 */ + } + } + + /* Update the buffer */ + if (buffer) { + *buffer = (int *)counter_dump; + } + + return len; } static struct gator_interface gator_events_mali_t6xx_interface = { - .create_files = create_files, - .start = start, - .stop = stop, - .read = read + .create_files = create_files, + .start = start, + .stop = stop, + .read = read }; extern int gator_events_mali_t6xx_init(void) { - pr_debug("gator: Mali-T6xx: sw_counters init\n"); + pr_debug("gator: Mali-T6xx: sw_counters init\n"); - gator_mali_initialise_counters(counters, NUMBER_OF_EVENTS); + gator_mali_initialise_counters(counters, NUMBER_OF_EVENTS); - return gator_events_install(&gator_events_mali_t6xx_interface); + return gator_events_install(&gator_events_mali_t6xx_interface); } gator_events_init(gator_events_mali_t6xx_init); diff --git a/driver/gator_events_mali_t6xx_hw.c b/driver/gator_events_mali_t6xx_hw.c index 854d02d..72498c8 100644 --- a/driver/gator_events_mali_t6xx_hw.c +++ b/driver/gator_events_mali_t6xx_hw.c @@ -26,7 +26,7 @@ * Mali-T6xx */ typedef struct kbase_device *kbase_find_device_type(int); -typedef kbase_context *kbase_create_context_type(kbase_device*); +typedef kbase_context *kbase_create_context_type(kbase_device *); typedef void kbase_destroy_context_type(kbase_context *); typedef void *kbase_va_alloc_type(kbase_context *, u32); typedef void kbase_va_free_type(kbase_context *, void *); @@ -36,32 +36,41 @@ typedef mali_error kbase_instr_hwcnt_clear_type(kbase_context *); typedef mali_error kbase_instr_hwcnt_dump_irq_type(kbase_context *); typedef mali_bool kbase_instr_hwcnt_dump_complete_type(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; - -/** The interval between reads, in ns. */ -static const int READ_INTERVAL_NSEC = 1000000; - +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; + +/** 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. + */ +static const int READ_INTERVAL_NSEC = 950000; #if GATOR_TEST #include "gator_events_mali_t6xx_hw_test.c" #endif /* Blocks for HW counters */ -enum -{ - JM_BLOCK = 0, - TILER_BLOCK, - SHADER_BLOCK, - MMU_BLOCK +enum { + JM_BLOCK = 0, + TILER_BLOCK, + SHADER_BLOCK, + MMU_BLOCK }; /* Counters for Mali-T6xx: @@ -75,271 +84,270 @@ enum */ /* Hardware Counters */ -static const char* const hardware_counter_names [] = -{ - /* Job Manager */ - "", - "", - "", - "", - "MESSAGES_SENT", - "MESSAGES_RECEIVED", - "GPU_ACTIVE", /* 6 */ - "IRQ_ACTIVE", - "JS0_JOBS", - "JS0_TASKS", - "JS0_ACTIVE", - "", - "JS0_WAIT_READ", - "JS0_WAIT_ISSUE", - "JS0_WAIT_DEPEND", - "JS0_WAIT_FINISH", - "JS1_JOBS", - "JS1_TASKS", - "JS1_ACTIVE", - "", - "JS1_WAIT_READ", - "JS1_WAIT_ISSUE", - "JS1_WAIT_DEPEND", - "JS1_WAIT_FINISH", - "JS2_JOBS", - "JS2_TASKS", - "JS2_ACTIVE", - "", - "JS2_WAIT_READ", - "JS2_WAIT_ISSUE", - "JS2_WAIT_DEPEND", - "JS2_WAIT_FINISH", - "JS3_JOBS", - "JS3_TASKS", - "JS3_ACTIVE", - "", - "JS3_WAIT_READ", - "JS3_WAIT_ISSUE", - "JS3_WAIT_DEPEND", - "JS3_WAIT_FINISH", - "JS4_JOBS", - "JS4_TASKS", - "JS4_ACTIVE", - "", - "JS4_WAIT_READ", - "JS4_WAIT_ISSUE", - "JS4_WAIT_DEPEND", - "JS4_WAIT_FINISH", - "JS5_JOBS", - "JS5_TASKS", - "JS5_ACTIVE", - "", - "JS5_WAIT_READ", - "JS5_WAIT_ISSUE", - "JS5_WAIT_DEPEND", - "JS5_WAIT_FINISH", - "JS6_JOBS", - "JS6_TASKS", - "JS6_ACTIVE", - "", - "JS6_WAIT_READ", - "JS6_WAIT_ISSUE", - "JS6_WAIT_DEPEND", - "JS6_WAIT_FINISH", - - /*Tiler*/ - "", - "", - "", - "JOBS_PROCESSED", - "TRIANGLES", - "QUADS", - "POLYGONS", - "POINTS", - "LINES", - "VCACHE_HIT", - "VCACHE_MISS", - "FRONT_FACING", - "BACK_FACING", - "PRIM_VISIBLE", - "PRIM_CULLED", - "PRIM_CLIPPED", - "LEVEL0", - "LEVEL1", - "LEVEL2", - "LEVEL3", - "LEVEL4", - "LEVEL5", - "LEVEL6", - "LEVEL7", - "COMMAND_1", - "COMMAND_2", - "COMMAND_3", - "COMMAND_4", - "COMMAND_4_7", - "COMMAND_8_15", - "COMMAND_16_63", - "COMMAND_64", - "COMPRESS_IN", - "COMPRESS_OUT", - "COMPRESS_FLUSH", - "TIMESTAMPS", - "PCACHE_HIT", - "PCACHE_MISS", - "PCACHE_LINE", - "PCACHE_STALL", - "WRBUF_HIT", - "WRBUF_MISS", - "WRBUF_LINE", - "WRBUF_PARTIAL", - "WRBUF_STALL", - "ACTIVE", - "LOADING_DESC", - "INDEX_WAIT", - "INDEX_RANGE_WAIT", - "VERTEX_WAIT", - "PCACHE_WAIT", - "WRBUF_WAIT", - "BUS_READ", - "BUS_WRITE", - "", - "", - "", - "", - "", - "UTLB_STALL", - "UTLB_REPLAY_MISS", - "UTLB_REPLAY_FULL", - "UTLB_NEW_MISS", - "UTLB_HIT", - - /* Shader Core */ - "", - "", - "", - "SHADER_CORE_ACTIVE", - "FRAG_ACTIVE", - "FRAG_PRIMATIVES", - "FRAG_PRIMATIVES_DROPPED", - "FRAG_CYCLE_DESC", - "FRAG_CYCLES_PLR", - "FRAG_CYCLES_VERT", - "FRAG_CYCLES_TRISETUP", - "FRAG_CYCLES_RAST", - "FRAG_THREADS", - "FRAG_DUMMY_THREADS", - "FRAG_QUADS_RAST", - "FRAG_QUADS_EZS_TEST", - "FRAG_QUADS_EZS_KILLED", - "FRAG_QUADS_LZS_TEST", - "FRAG_QUADS_LZS_KILLED", - "FRAG_CYCLE_NO_TILE", - "FRAG_NUM_TILES", - "FRAG_TRANS_ELIM", - "COMPUTE_ACTIVE", - "COMPUTE_TASKS", - "COMPUTE_THREADS", - "COMPUTE_CYCLES_DESC", - "TRIPIPE_ACTIVE", - "ARITH_WORDS", - "ARITH_CYCLES_REG", - "ARITH_CYCLES_L0", - "ARITH_FRAG_DEPEND", - "LS_WORDS", - "LS_ISSUES", - "LS_RESTARTS", - "LS_REISSUES_MISS", - "LS_REISSUES_VD", - "LS_REISSUE_ATTRIB_MISS", - "LS_NO_WB", - "TEX_WORDS", - "TEX_BUBBLES", - "TEX_WORDS_L0", - "TEX_WORDS_DESC", - "TEX_THREADS", - "TEX_RECIRC_FMISS", - "TEX_RECIRC_DESC", - "TEX_RECIRC_MULTI", - "TEX_RECIRC_PMISS", - "TEX_RECIRC_CONF", - "LSC_READ_HITS", - "LSC_READ_MISSES", - "LSC_WRITE_HITS", - "LSC_WRITE_MISSES", - "LSC_ATOMIC_HITS", - "LSC_ATOMIC_MISSES", - "LSC_LINE_FETCHES", - "LSC_DIRTY_LINE", - "LSC_SNOOPS", - "AXI_TLB_STALL", - "AXI_TLB_MIESS", - "AXI_TLB_TRANSACTION", - "LS_TLB_MISS", - "LS_TLB_HIT", - "AXI_BEATS_READ", - "AXI_BEATS_WRITTEN", - - /*L2 and MMU */ - "", - "", - "", - "", - "MMU_TABLE_WALK", - "MMU_REPLAY_MISS", - "MMU_REPLAY_FULL", - "MMU_NEW_MISS", - "MMU_HIT", - "", - "", - "", - "", - "", - "", - "", - "UTLB_STALL", - "UTLB_REPLAY_MISS", - "UTLB_REPLAY_FULL", - "UTLB_NEW_MISS", - "UTLB_HIT", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "L2_WRITE_BEATS", - "L2_READ_BEATS", - "L2_ANY_LOOKUP", - "L2_READ_LOOKUP", - "L2_SREAD_LOOKUP", - "L2_READ_REPLAY", - "L2_READ_SNOOP", - "L2_READ_HIT", - "L2_CLEAN_MISS", - "L2_WRITE_LOOKUP", - "L2_SWRITE_LOOKUP", - "L2_WRITE_REPLAY", - "L2_WRITE_SNOOP", - "L2_WRITE_HIT", - "L2_EXT_READ_FULL", - "L2_EXT_READ_HALF", - "L2_EXT_WRITE_FULL", - "L2_EXT_WRITE_HALF", - "L2_EXT_READ", - "L2_EXT_READ_LINE", - "L2_EXT_WRITE", - "L2_EXT_WRITE_LINE", - "L2_EXT_WRITE_SMALL", - "L2_EXT_BARRIER", - "L2_EXT_AR_STALL", - "L2_EXT_R_BUF_FULL", - "L2_EXT_RD_BUF_FULL", - "L2_EXT_R_RAW", - "L2_EXT_W_STALL", - "L2_EXT_W_BUF_FULL", - "L2_EXT_R_W_HAZARD", - "L2_TAG_HAZARD", - "L2_SNOOP_FULL", - "L2_REPLAY_FULL" +static const char *const hardware_counter_names[] = { + /* Job Manager */ + "", + "", + "", + "", + "MESSAGES_SENT", + "MESSAGES_RECEIVED", + "GPU_ACTIVE", /* 6 */ + "IRQ_ACTIVE", + "JS0_JOBS", + "JS0_TASKS", + "JS0_ACTIVE", + "", + "JS0_WAIT_READ", + "JS0_WAIT_ISSUE", + "JS0_WAIT_DEPEND", + "JS0_WAIT_FINISH", + "JS1_JOBS", + "JS1_TASKS", + "JS1_ACTIVE", + "", + "JS1_WAIT_READ", + "JS1_WAIT_ISSUE", + "JS1_WAIT_DEPEND", + "JS1_WAIT_FINISH", + "JS2_JOBS", + "JS2_TASKS", + "JS2_ACTIVE", + "", + "JS2_WAIT_READ", + "JS2_WAIT_ISSUE", + "JS2_WAIT_DEPEND", + "JS2_WAIT_FINISH", + "JS3_JOBS", + "JS3_TASKS", + "JS3_ACTIVE", + "", + "JS3_WAIT_READ", + "JS3_WAIT_ISSUE", + "JS3_WAIT_DEPEND", + "JS3_WAIT_FINISH", + "JS4_JOBS", + "JS4_TASKS", + "JS4_ACTIVE", + "", + "JS4_WAIT_READ", + "JS4_WAIT_ISSUE", + "JS4_WAIT_DEPEND", + "JS4_WAIT_FINISH", + "JS5_JOBS", + "JS5_TASKS", + "JS5_ACTIVE", + "", + "JS5_WAIT_READ", + "JS5_WAIT_ISSUE", + "JS5_WAIT_DEPEND", + "JS5_WAIT_FINISH", + "JS6_JOBS", + "JS6_TASKS", + "JS6_ACTIVE", + "", + "JS6_WAIT_READ", + "JS6_WAIT_ISSUE", + "JS6_WAIT_DEPEND", + "JS6_WAIT_FINISH", + + /*Tiler */ + "", + "", + "", + "JOBS_PROCESSED", + "TRIANGLES", + "QUADS", + "POLYGONS", + "POINTS", + "LINES", + "VCACHE_HIT", + "VCACHE_MISS", + "FRONT_FACING", + "BACK_FACING", + "PRIM_VISIBLE", + "PRIM_CULLED", + "PRIM_CLIPPED", + "LEVEL0", + "LEVEL1", + "LEVEL2", + "LEVEL3", + "LEVEL4", + "LEVEL5", + "LEVEL6", + "LEVEL7", + "COMMAND_1", + "COMMAND_2", + "COMMAND_3", + "COMMAND_4", + "COMMAND_4_7", + "COMMAND_8_15", + "COMMAND_16_63", + "COMMAND_64", + "COMPRESS_IN", + "COMPRESS_OUT", + "COMPRESS_FLUSH", + "TIMESTAMPS", + "PCACHE_HIT", + "PCACHE_MISS", + "PCACHE_LINE", + "PCACHE_STALL", + "WRBUF_HIT", + "WRBUF_MISS", + "WRBUF_LINE", + "WRBUF_PARTIAL", + "WRBUF_STALL", + "ACTIVE", + "LOADING_DESC", + "INDEX_WAIT", + "INDEX_RANGE_WAIT", + "VERTEX_WAIT", + "PCACHE_WAIT", + "WRBUF_WAIT", + "BUS_READ", + "BUS_WRITE", + "", + "", + "", + "", + "", + "UTLB_STALL", + "UTLB_REPLAY_MISS", + "UTLB_REPLAY_FULL", + "UTLB_NEW_MISS", + "UTLB_HIT", + + /* Shader Core */ + "", + "", + "", + "SHADER_CORE_ACTIVE", + "FRAG_ACTIVE", + "FRAG_PRIMATIVES", + "FRAG_PRIMATIVES_DROPPED", + "FRAG_CYCLE_DESC", + "FRAG_CYCLES_PLR", + "FRAG_CYCLES_VERT", + "FRAG_CYCLES_TRISETUP", + "FRAG_CYCLES_RAST", + "FRAG_THREADS", + "FRAG_DUMMY_THREADS", + "FRAG_QUADS_RAST", + "FRAG_QUADS_EZS_TEST", + "FRAG_QUADS_EZS_KILLED", + "FRAG_QUADS_LZS_TEST", + "FRAG_QUADS_LZS_KILLED", + "FRAG_CYCLE_NO_TILE", + "FRAG_NUM_TILES", + "FRAG_TRANS_ELIM", + "COMPUTE_ACTIVE", + "COMPUTE_TASKS", + "COMPUTE_THREADS", + "COMPUTE_CYCLES_DESC", + "TRIPIPE_ACTIVE", + "ARITH_WORDS", + "ARITH_CYCLES_REG", + "ARITH_CYCLES_L0", + "ARITH_FRAG_DEPEND", + "LS_WORDS", + "LS_ISSUES", + "LS_RESTARTS", + "LS_REISSUES_MISS", + "LS_REISSUES_VD", + "LS_REISSUE_ATTRIB_MISS", + "LS_NO_WB", + "TEX_WORDS", + "TEX_BUBBLES", + "TEX_WORDS_L0", + "TEX_WORDS_DESC", + "TEX_THREADS", + "TEX_RECIRC_FMISS", + "TEX_RECIRC_DESC", + "TEX_RECIRC_MULTI", + "TEX_RECIRC_PMISS", + "TEX_RECIRC_CONF", + "LSC_READ_HITS", + "LSC_READ_MISSES", + "LSC_WRITE_HITS", + "LSC_WRITE_MISSES", + "LSC_ATOMIC_HITS", + "LSC_ATOMIC_MISSES", + "LSC_LINE_FETCHES", + "LSC_DIRTY_LINE", + "LSC_SNOOPS", + "AXI_TLB_STALL", + "AXI_TLB_MIESS", + "AXI_TLB_TRANSACTION", + "LS_TLB_MISS", + "LS_TLB_HIT", + "AXI_BEATS_READ", + "AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "MMU_TABLE_WALK", + "MMU_REPLAY_MISS", + "MMU_REPLAY_FULL", + "MMU_NEW_MISS", + "MMU_HIT", + "", + "", + "", + "", + "", + "", + "", + "UTLB_STALL", + "UTLB_REPLAY_MISS", + "UTLB_REPLAY_FULL", + "UTLB_NEW_MISS", + "UTLB_HIT", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "L2_WRITE_BEATS", + "L2_READ_BEATS", + "L2_ANY_LOOKUP", + "L2_READ_LOOKUP", + "L2_SREAD_LOOKUP", + "L2_READ_REPLAY", + "L2_READ_SNOOP", + "L2_READ_HIT", + "L2_CLEAN_MISS", + "L2_WRITE_LOOKUP", + "L2_SWRITE_LOOKUP", + "L2_WRITE_REPLAY", + "L2_WRITE_SNOOP", + "L2_WRITE_HIT", + "L2_EXT_READ_FULL", + "L2_EXT_READ_HALF", + "L2_EXT_WRITE_FULL", + "L2_EXT_WRITE_HALF", + "L2_EXT_READ", + "L2_EXT_READ_LINE", + "L2_EXT_WRITE", + "L2_EXT_WRITE_LINE", + "L2_EXT_WRITE_SMALL", + "L2_EXT_BARRIER", + "L2_EXT_AR_STALL", + "L2_EXT_R_BUF_FULL", + "L2_EXT_RD_BUF_FULL", + "L2_EXT_R_RAW", + "L2_EXT_W_STALL", + "L2_EXT_W_BUF_FULL", + "L2_EXT_R_W_HAZARD", + "L2_TAG_HAZARD", + "L2_SNOOP_FULL", + "L2_REPLAY_FULL" }; #define NUMBER_OF_HARDWARE_COUNTERS (sizeof(hardware_counter_names) / sizeof(hardware_counter_names[0])) @@ -392,8 +400,8 @@ static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2]; #define SYMBOL_CLEANUP(FUNCTION) \ if(FUNCTION ## _symbol) \ { \ - symbol_put(FUNCTION); \ - FUNCTION ## _symbol = NULL; \ + symbol_put(FUNCTION); \ + FUNCTION ## _symbol = NULL; \ } /** @@ -442,17 +450,15 @@ static void clean_symbols(void) * * Note that this function has been separated out here to allow it to be tested. */ -static int is_read_scheduled(const struct timespec *current_time, u32* prev_time_s, s32* next_read_time_ns) +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; } @@ -465,154 +471,146 @@ static int is_read_scheduled(const struct timespec *current_time, u32* prev_time static int start(void) { - kbase_uk_hwcnt_setup setup; - mali_error err; - int cnt; - u16 bitmask[] = {0, 0, 0, 0}; - - /* Setup HW counters */ - num_hardware_counters_enabled = 0; - - if(NUMBER_OF_HARDWARE_COUNTERS != 256) - { - pr_debug("Unexpected number of hardware counters defined: expecting 256, got %d\n", NUMBER_OF_HARDWARE_COUNTERS); - } - - /* Calculate enable bitmasks based on counters_enabled array */ - for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) - { - const 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-T6xx: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt); - num_hardware_counters_enabled++; - } - } - - /* Create a kbase context for HW counters */ - if (num_hardware_counters_enabled > 0) - { - if(init_symbols() > 0) - { - clean_symbols(); - /* No Mali driver code entrypoints found - not a fault. */ - return 0; - } - - kbdevice = kbase_find_device_symbol(-1); - - /* If we already got a context, fail */ - if (kbcontext) { - pr_debug("gator: Mali-T6xx: error context already present\n"); - goto out; - } - - /* kbcontext will only be valid after all the Mali symbols are loaded successfully */ - kbcontext = kbase_create_context_symbol(kbdevice); - if (!kbcontext) - { - pr_debug("gator: Mali-T6xx: error creating kbase context\n"); - goto out; - } - - /* - * The amount of memory needed to store the dump (bytes) - * DUMP_SIZE = number of core groups - * * number of blocks (always 8 for midgard) - * * number of counters per block (always 64 for midgard) - * * number of bytes per counter (always 4 in midgard) - * For a Mali-T6xx with a single core group = 1 * 8 * 64 * 4 - */ - kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 2048); - if (!kernel_dump_buffer) - { - pr_debug("gator: Mali-T6xx: error trying to allocate va\n"); - goto destroy_context; - } - - setup.dump_buffer = (uintptr_t)kernel_dump_buffer; - setup.jm_bm = bitmask[JM_BLOCK]; - setup.tiler_bm = bitmask[TILER_BLOCK]; - setup.shader_bm = bitmask[SHADER_BLOCK]; - setup.mmu_l2_bm = bitmask[MMU_BLOCK]; - /* These counters do not exist on Mali-T60x */ - setup.l3_cache_bm = 0; - - /* Use kbase API to enable hardware counters and provide dump buffer */ - err = kbase_instr_hwcnt_enable_symbol(kbcontext, &setup); - if (err != MALI_ERROR_NONE) - { - pr_debug("gator: Mali-T6xx: can't setup hardware counters\n"); - goto free_buffer; - } - pr_debug("gator: Mali-T6xx: hardware counters enabled\n"); - kbase_instr_hwcnt_clear_symbol(kbcontext); - pr_debug("gator: Mali-T6xx: hardware counters cleared \n"); - - kbase_device_busy = false; - } - - return 0; - - free_buffer: + kbase_uk_hwcnt_setup setup; + mali_error err; + int cnt; + u16 bitmask[] = { 0, 0, 0, 0 }; + + /* Setup HW counters */ + num_hardware_counters_enabled = 0; + + if (NUMBER_OF_HARDWARE_COUNTERS != 256) { + pr_debug("Unexpected number of hardware counters defined: expecting 256, got %d\n", NUMBER_OF_HARDWARE_COUNTERS); + } + + /* Calculate enable bitmasks based on counters_enabled array */ + for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) { + const 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-T6xx: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt); + num_hardware_counters_enabled++; + } + } + + /* Create a kbase context for HW counters */ + if (num_hardware_counters_enabled > 0) { + if (init_symbols() > 0) { + clean_symbols(); + /* No Mali driver code entrypoints found - not a fault. */ + return 0; + } + + kbdevice = kbase_find_device_symbol(-1); + + /* If we already got a context, fail */ + if (kbcontext) { + pr_debug("gator: Mali-T6xx: error context already present\n"); + goto out; + } + + /* kbcontext will only be valid after all the Mali symbols are loaded successfully */ + kbcontext = kbase_create_context_symbol(kbdevice); + if (!kbcontext) { + pr_debug("gator: Mali-T6xx: error creating kbase context\n"); + goto out; + } + + /* + * The amount of memory needed to store the dump (bytes) + * DUMP_SIZE = number of core groups + * * number of blocks (always 8 for midgard) + * * number of counters per block (always 64 for midgard) + * * number of bytes per counter (always 4 in midgard) + * For a Mali-T6xx with a single core group = 1 * 8 * 64 * 4 + */ + kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 2048); + if (!kernel_dump_buffer) { + pr_debug("gator: Mali-T6xx: error trying to allocate va\n"); + goto destroy_context; + } + + setup.dump_buffer = (uintptr_t)kernel_dump_buffer; + setup.jm_bm = bitmask[JM_BLOCK]; + setup.tiler_bm = bitmask[TILER_BLOCK]; + setup.shader_bm = bitmask[SHADER_BLOCK]; + setup.mmu_l2_bm = bitmask[MMU_BLOCK]; + /* These counters do not exist on Mali-T60x */ + setup.l3_cache_bm = 0; + + /* Use kbase API to enable hardware counters and provide dump buffer */ + err = kbase_instr_hwcnt_enable_symbol(kbcontext, &setup); + if (err != MALI_ERROR_NONE) { + pr_debug("gator: Mali-T6xx: can't setup hardware counters\n"); + goto free_buffer; + } + pr_debug("gator: Mali-T6xx: hardware counters enabled\n"); + kbase_instr_hwcnt_clear_symbol(kbcontext); + pr_debug("gator: Mali-T6xx: hardware counters cleared \n"); + + kbase_device_busy = false; + } + + return 0; + +free_buffer: kbase_va_free_symbol(kbcontext, kernel_dump_buffer); - destroy_context: +destroy_context: kbase_destroy_context_symbol(kbcontext); - out: +out: clean_symbols(); - return -1; + return -1; } -static void stop(void) { - unsigned int cnt; - kbase_context *temp_kbcontext; +static void stop(void) +{ + unsigned int cnt; + kbase_context *temp_kbcontext; - pr_debug("gator: Mali-T6xx: stop\n"); + pr_debug("gator: Mali-T6xx: stop\n"); - /* Set all counters as disabled */ - for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) { - counters[cnt].enabled = 0; - } + /* Set all counters as disabled */ + for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) { + counters[cnt].enabled = 0; + } - /* Destroy the context for HW counters */ - if (num_hardware_counters_enabled > 0 && kbcontext != NULL) - { - /* - * Set the global variable to NULL before destroying it, because - * other function will check this before using it. - */ - temp_kbcontext = kbcontext; - kbcontext = NULL; + /* Destroy the context for HW counters */ + if (num_hardware_counters_enabled > 0 && kbcontext != NULL) { + /* + * Set the global variable to NULL before destroying it, because + * other function will check this before using it. + */ + temp_kbcontext = kbcontext; + kbcontext = NULL; - kbase_instr_hwcnt_disable_symbol(temp_kbcontext); - kbase_va_free_symbol(temp_kbcontext, kernel_dump_buffer); - kbase_destroy_context_symbol(temp_kbcontext); + kbase_instr_hwcnt_disable_symbol(temp_kbcontext); + kbase_va_free_symbol(temp_kbcontext, kernel_dump_buffer); + kbase_destroy_context_symbol(temp_kbcontext); - pr_debug("gator: Mali-T6xx: hardware counters stopped\n"); + pr_debug("gator: Mali-T6xx: hardware counters stopped\n"); - clean_symbols(); - } + clean_symbols(); + } } -static int read(int **buffer) { - int cnt; - int len = 0; - u32 value = 0; - mali_bool success; +static int read(int **buffer) +{ + int cnt; + int len = 0; + u32 value = 0; + mali_bool success; struct timespec current_time; static u32 prev_time_s = 0; static s32 next_read_time_ns = 0; - if (smp_processor_id()!=0) - { - return 0; - } + if (smp_processor_id() != 0) { + return 0; + } getnstimeofday(¤t_time); @@ -620,114 +618,105 @@ static int read(int **buffer) { * 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 - * Only process hardware counters if at least one of the hardware counters is enabled. - */ - if (num_hardware_counters_enabled > 0) - { - const unsigned int vithar_blocks[] = { - 0x700, /* VITHAR_JOB_MANAGER, Block 0 */ - 0x400, /* VITHAR_TILER, Block 1 */ - 0x000, /* VITHAR_SHADER_CORE, Block 2 */ - 0x500 /* VITHAR_MEMORY_SYSTEM, Block 3 */ - }; - - 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) - { - kbase_device_busy = false; - - if (success == MALI_TRUE) - { - 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); - const u32 *counter_block = (u32 *)((uintptr_t)kernel_dump_buffer + vithar_blocks[block]); - const u32 *counter_address = counter_block + counter_offset; - - value = *counter_address; - - if(block == SHADER_BLOCK){ - /* (counter_address + 0x000) has already been accounted-for above. */ - value += *(counter_address + 0x100); - value += *(counter_address + 0x200); - value += *(counter_address + 0x300); - } - - counter_dump[len++] = counter->key; - counter_dump[len++] = value; - } - } - } - } - - if (! kbase_device_busy) - { - kbase_device_busy = true; - kbase_instr_hwcnt_dump_irq_symbol(kbcontext); - } - } - - /* Update the buffer */ - if (buffer) { - *buffer = (int*) counter_dump; - } - - return len; + /* + * Report the HW counters + * Only process hardware counters if at least one of the hardware counters is enabled. + */ + if (num_hardware_counters_enabled > 0) { + const unsigned int vithar_blocks[] = { + 0x700, /* VITHAR_JOB_MANAGER, Block 0 */ + 0x400, /* VITHAR_TILER, Block 1 */ + 0x000, /* VITHAR_SHADER_CORE, Block 2 */ + 0x500 /* VITHAR_MEMORY_SYSTEM, Block 3 */ + }; + + 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) { + kbase_device_busy = false; + + if (success == MALI_TRUE) { + 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); + const u32 *counter_block = (u32 *) ((uintptr_t)kernel_dump_buffer + vithar_blocks[block]); + const u32 *counter_address = counter_block + counter_offset; + + value = *counter_address; + + if (block == SHADER_BLOCK) { + /* (counter_address + 0x000) has already been accounted-for above. */ + value += *(counter_address + 0x100); + value += *(counter_address + 0x200); + value += *(counter_address + 0x300); + } + + counter_dump[len++] = counter->key; + counter_dump[len++] = value; + } + } + } + } + + if (!kbase_device_busy) { + kbase_device_busy = true; + kbase_instr_hwcnt_dump_irq_symbol(kbcontext); + } + } + + /* Update the buffer */ + if (buffer) { + *buffer = (int *)counter_dump; + } + + return len; } static int create_files(struct super_block *sb, struct dentry *root) { - unsigned int event; - /* - * Create the filesystem for all events - */ - int counter_index = 0; - const char* mali_name = gator_mali_get_mali_name(); - - for (event = 0; event < NUMBER_OF_HARDWARE_COUNTERS; event++) - { - if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event]) != 0) - return -1; - counter_index++; - } - - return 0; + unsigned int event; + /* + * Create the filesystem for all events + */ + int counter_index = 0; + const char *mali_name = gator_mali_get_mali_name(); + + for (event = 0; event < NUMBER_OF_HARDWARE_COUNTERS; event++) { + if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event]) != 0) + return -1; + counter_index++; + } + + return 0; } static struct gator_interface gator_events_mali_t6xx_interface = { - .create_files = create_files, - .start = start, - .stop = stop, - .read = read + .create_files = create_files, + .start = start, + .stop = stop, + .read = read }; int gator_events_mali_t6xx_hw_init(void) { - pr_debug("gator: Mali-T6xx: sw_counters init\n"); + pr_debug("gator: Mali-T6xx: sw_counters init\n"); #if GATOR_TEST test_all_is_read_scheduled(); #endif - gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS); + gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS); - return gator_events_install(&gator_events_mali_t6xx_interface); + return gator_events_install(&gator_events_mali_t6xx_interface); } gator_events_init(gator_events_mali_t6xx_hw_init); diff --git a/driver/gator_events_mali_t6xx_hw_test.c b/driver/gator_events_mali_t6xx_hw_test.c index 2a35e77..eb77110 100644 --- a/driver/gator_events_mali_t6xx_hw_test.c +++ b/driver/gator_events_mali_t6xx_hw_test.c @@ -11,7 +11,7 @@ * Test functions for mali_t600_hw code. */ -static int is_read_scheduled(const struct timespec *current_time, u32* prev_time_s, s32* next_read_time_ns); +static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns); static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int expected_result, s32 expected_next_ns) { @@ -22,14 +22,12 @@ static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int ex current_time.tv_sec = s; current_time.tv_nsec = ns; - if(is_read_scheduled(¤t_time, &prev_time_s, &next_read_time_ns) != expected_result) - { + 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); return 0; } - if(next_read_time_ns != expected_next_ns) - { + 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); return 0; } @@ -44,14 +42,14 @@ static void test_all_is_read_scheduled(void) printk("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 */ + 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 */ - n_tests_passed += test_is_read_scheduled(100, HIGHEST_NS, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500); - n_tests_passed += test_is_read_scheduled(101, 0001, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500 - NSEC_PER_SEC); - n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500 - NSEC_PER_SEC, 1, 600 + READ_INTERVAL_NSEC); + n_tests_passed += test_is_read_scheduled(100, HIGHEST_NS, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500); + n_tests_passed += test_is_read_scheduled(101, 0001, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500 - NSEC_PER_SEC); + n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500 - NSEC_PER_SEC, 1, 600 + READ_INTERVAL_NSEC); - n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500, 1, 600 + READ_INTERVAL_NSEC); + 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); } diff --git a/driver/gator_events_meminfo.c b/driver/gator_events_meminfo.c index b962641..fd063b2 100644 --- a/driver/gator_events_meminfo.c +++ b/driver/gator_events_meminfo.c @@ -31,22 +31,25 @@ static struct timer_list meminfo_wake_up_timer; static void meminfo_wake_up_handler(unsigned long unused_data); #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) -GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order)) { +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)) { +GATOR_DEFINE_PROBE(mm_page_free, TP_PROTO(struct page *page, unsigned int order)) #endif +{ mem_event++; } #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) -GATOR_DEFINE_PROBE(mm_pagevec_free, TP_PROTO(struct page *page, int cold)) { +GATOR_DEFINE_PROBE(mm_pagevec_free, TP_PROTO(struct page *page, int cold)) #else -GATOR_DEFINE_PROBE(mm_page_free_batched, TP_PROTO(struct page *page, int cold)) { +GATOR_DEFINE_PROBE(mm_page_free_batched, TP_PROTO(struct page *page, int cold)) #endif +{ mem_event++; } -GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype)) { +GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype)) +{ mem_event++; } @@ -233,4 +236,5 @@ int gator_events_meminfo_init(void) return gator_events_install(&gator_events_meminfo_interface); } + gator_events_init(gator_events_meminfo_init); diff --git a/driver/gator_events_mmaped.c b/driver/gator_events_mmaped.c index 1be6e66..c4cb44f 100644 --- a/driver/gator_events_mmaped.c +++ b/driver/gator_events_mmaped.c @@ -45,7 +45,7 @@ static s64 prev_time; /* Adds mmaped_cntX directories and enabled, event, and key files to /dev/gator/events */ static int gator_events_mmaped_create_files(struct super_block *sb, - struct dentry *root) + struct dentry *root) { int i; @@ -58,11 +58,11 @@ static int gator_events_mmaped_create_files(struct super_block *sb, if (WARN_ON(!dir)) return -1; gatorfs_create_ulong(sb, dir, "enabled", - &mmaped_counters[i].enabled); + &mmaped_counters[i].enabled); gatorfs_create_ulong(sb, dir, "event", - &mmaped_counters[i].event); + &mmaped_counters[i].event); gatorfs_create_ro_ulong(sb, dir, "key", - &mmaped_counters[i].key); + &mmaped_counters[i].key); } return 0; @@ -73,7 +73,7 @@ static int gator_events_mmaped_start(void) #ifdef TODO for (i = 0; i < MMAPED_COUNTERS_NUM; i++) writel(mmaped_counters[i].event, - mmaped_base + COUNTERS_CONFIG_OFFSET[i]); + mmaped_base + COUNTERS_CONFIG_OFFSET[i]); writel(ENABLED, COUNTERS_CONTROL_OFFSET); #endif @@ -102,7 +102,7 @@ static int mmaped_simulate(int counter, int delta_in_us) int result = 0; switch (counter) { - case 0: /* sort-of-sine */ + case 0: /* sort-of-sine */ { static int t = 0; int x; @@ -123,7 +123,7 @@ static int mmaped_simulate(int counter, int delta_in_us) result = 1922 - result; } break; - case 1: /* triangle */ + case 1: /* triangle */ { static int v, d = 1; @@ -139,7 +139,7 @@ static int mmaped_simulate(int counter, int delta_in_us) result = v; } break; - case 2: /* PWM signal */ + case 2: /* PWM signal */ { static int t, dc, x; @@ -149,7 +149,7 @@ static int mmaped_simulate(int counter, int delta_in_us) if (x / 1000000 != (x + delta_in_us) / 1000000) dc = (dc + 100000) % 1000000; x += delta_in_us; - + result = t < dc ? 0 : 10; } break; @@ -173,7 +173,7 @@ static int gator_events_mmaped_read(int **buffer) if (smp_processor_id()) return 0; -#ifndef TODO +#ifndef TODO getnstimeofday(&ts); time = timespec_to_ns(&ts); delta_in_us = (int)(time - prev_time) / 1000; @@ -184,15 +184,16 @@ static int gator_events_mmaped_read(int **buffer) if (mmaped_counters[i].enabled) { mmaped_buffer[len++] = mmaped_counters[i].key; #ifdef TODO - mmaped_buffer[len++] = readl(mmaped_base + - COUNTERS_VALUE_OFFSET[i]); + mmaped_buffer[len++] = + readl(mmaped_base + COUNTERS_VALUE_OFFSET[i]); #else - mmaped_buffer[len++] = mmaped_simulate( - mmaped_counters[i].event, delta_in_us); + mmaped_buffer[len++] = + mmaped_simulate(mmaped_counters[i].event, + delta_in_us); #endif } } - + if (buffer) *buffer = mmaped_buffer; @@ -214,7 +215,7 @@ int __init gator_events_mmaped_init(void) #ifdef TODO mmaped_base = ioremap(COUNTERS_PHYS_ADDR, SZ_4K); if (!mmaped_base) - return -ENOMEM; + return -ENOMEM; #endif for (i = 0; i < MMAPED_COUNTERS_NUM; i++) { @@ -224,4 +225,5 @@ int __init gator_events_mmaped_init(void) return gator_events_install(&gator_events_mmaped_interface); } + gator_events_init(gator_events_mmaped_init); diff --git a/driver/gator_events_net.c b/driver/gator_events_net.c index 31cc3ef..b6ce06a 100644 --- a/driver/gator_events_net.c +++ b/driver/gator_events_net.c @@ -26,7 +26,8 @@ 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 -static void get_network_stats(struct work_struct *wsptr) { +static void get_network_stats(struct work_struct *wsptr) +{ int rx = 0, tx = 0; struct net_device *dev; @@ -43,6 +44,7 @@ static void get_network_stats(struct work_struct *wsptr) { rx_total = rx; tx_total = tx; } + DECLARE_WORK(wq_get_stats, get_network_stats); static void net_wake_up_handler(unsigned long unused_data) @@ -129,7 +131,7 @@ 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 + netGet[len++] = 0; // indicates to Streamline that rx_delta bytes were transmitted now, not since the last message netGet[len++] = netrx_key; netGet[len++] = rx_delta; } @@ -137,7 +139,7 @@ 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 + netGet[len++] = 0; // indicates to Streamline that tx_delta bytes were transmitted now, not since the last message netGet[len++] = nettx_key; netGet[len++] = tx_delta; } @@ -165,4 +167,5 @@ int gator_events_net_init(void) return gator_events_install(&gator_events_net_interface); } + gator_events_init(gator_events_net_init); diff --git a/driver/gator_events_perf_pmu.c b/driver/gator_events_perf_pmu.c index e025155..ce3a40f 100644 --- a/driver/gator_events_perf_pmu.c +++ b/driver/gator_events_perf_pmu.c @@ -45,7 +45,7 @@ static int gator_events_perf_pmu_create_files(struct super_block *sb, struct den if (i == 0) { snprintf(buf, sizeof buf, "%s_ccnt", pmnc_name); } else { - snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i-1); + snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i - 1); } dir = gatorfs_mkdir(sb, root, buf); if (!dir) { @@ -80,13 +80,13 @@ static void dummy_handler(struct perf_event *event, struct perf_sample_data *dat // Required as perf_event_create_kernel_counter() requires an overflow handler, even though all we do is poll } -static int gator_events_perf_pmu_online(int** buffer) +static int gator_events_perf_pmu_online(int **buffer) { int cnt, len = 0, cpu = smp_processor_id(); // read the counters and toss the invalid data, return zero instead for (cnt = 0; cnt < pmnc_counters; cnt++) { - struct perf_event * ev = per_cpu(pevent, cpu)[cnt]; + struct perf_event *ev = per_cpu(pevent, cpu)[cnt]; if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) { ev->pmu->read(ev); per_cpu(perfPrev, cpu)[cnt] = per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count); @@ -140,7 +140,7 @@ static void gator_events_perf_pmu_online_dispatch(int cpu) static void gator_events_perf_pmu_offline_dispatch(int cpu) { int cnt; - struct perf_event * pe; + struct perf_event *pe; for (cnt = 0; cnt < pmnc_counters; cnt++) { pe = NULL; @@ -177,7 +177,7 @@ static int gator_events_perf_pmu_start(void) for_each_present_cpu(cpu) { for (cnt = 0; cnt < pmnc_counters; cnt++) { per_cpu(pevent, cpu)[cnt] = NULL; - if (!pmnc_enabled[cnt]) // Skip disabled counters + if (!pmnc_enabled[cnt]) // Skip disabled counters continue; per_cpu(perfPrev, cpu)[cnt] = 0; @@ -233,7 +233,7 @@ static int gator_events_perf_pmu_read(int **buffer) int cpu = smp_processor_id(); for (cnt = 0; cnt < pmnc_counters; cnt++) { - struct perf_event * ev = per_cpu(pevent, cpu)[cnt]; + struct perf_event *ev = per_cpu(pevent, cpu)[cnt]; if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) { ev->pmu->read(ev); per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count); @@ -268,62 +268,21 @@ static struct gator_interface gator_events_perf_pmu_interface = { int gator_events_perf_pmu_init(void) { unsigned int cnt; - - switch (gator_cpuid()) { - case ARM1136: - case ARM1156: - case ARM1176: - pmnc_name = "ARM_ARM11"; - pmnc_counters = 3; - ccnt = 2; - break; - case ARM11MPCORE: - pmnc_name = "ARM_ARM11MPCore"; - pmnc_counters = 3; - break; - case CORTEX_A5: - pmnc_name = "ARM_Cortex-A5"; - pmnc_counters = 2; - break; - case CORTEX_A7: - pmnc_name = "ARM_Cortex-A7"; - pmnc_counters = 4; - break; - case CORTEX_A8: - pmnc_name = "ARM_Cortex-A8"; - pmnc_counters = 4; - break; - case CORTEX_A9: - pmnc_name = "ARM_Cortex-A9"; - pmnc_counters = 6; - break; - case CORTEX_A15: - pmnc_name = "ARM_Cortex-A15"; - pmnc_counters = 6; - break; - case SCORPION: - pmnc_name = "Scorpion"; - pmnc_counters = 4; - break; - case SCORPIONMP: - pmnc_name = "ScorpionMP"; - pmnc_counters = 4; - break; - case KRAITSIM: - case KRAIT: - pmnc_name = "Krait"; - pmnc_counters = 4; - break; - case AARCH64: - pmnc_name = "ARM_AArch64"; - // Copied from A15, get the correct number - pmnc_counters = 6; - break; - default: + const u32 cpuid = gator_cpuid(); + + for (cnt = 0; gator_cpus[cnt].cpuid != 0; ++cnt) { + if (gator_cpus[cnt].cpuid == cpuid) { + pmnc_name = gator_cpus[cnt].pmnc_name; + pmnc_counters = gator_cpus[cnt].pmnc_counters; + ccnt = gator_cpus[cnt].ccnt; + break; + } + } + if (gator_cpus[cnt].cpuid == 0) { return -1; } - pmnc_counters++; // CNT[n] + CCNT + pmnc_counters++; // CNT[n] + CCNT for (cnt = 0; cnt < CNTMAX; cnt++) { pmnc_enabled[cnt] = 0; diff --git a/driver/gator_events_sched.c b/driver/gator_events_sched.c index 9bed364..ba6744d 100644 --- a/driver/gator_events_sched.c +++ b/driver/gator_events_sched.c @@ -111,4 +111,5 @@ int gator_events_sched_init(void) return gator_events_install(&gator_events_sched_interface); } + gator_events_init(gator_events_sched_init); diff --git a/driver/gator_events_scorpion.c b/driver/gator_events_scorpion.c index ed0d8de..5ffc63a 100644 --- a/driver/gator_events_scorpion.c +++ b/driver/gator_events_scorpion.c @@ -20,8 +20,8 @@ static int pmnc_counters; #define PMNC_C (1 << 2) /* Cycle counter reset */ #define PMNC_D (1 << 3) /* CCNT counts every 64th cpu cycle */ #define PMNC_X (1 << 4) /* Export to ETM */ -#define PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ -#define PMNC_MASK 0x3f /* Mask for writable bits */ +#define PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug */ +#define PMNC_MASK 0x3f /* Mask for writable bits */ // ccnt reg #define CCNT_REG (1 << 31) @@ -37,95 +37,95 @@ static unsigned long pmnc_key[CNTMAX]; static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt); enum scorpion_perf_types { - SCORPION_ICACHE_EXPL_INV = 0x4c, - SCORPION_ICACHE_MISS = 0x4d, - SCORPION_ICACHE_ACCESS = 0x4e, - SCORPION_ICACHE_CACHEREQ_L2 = 0x4f, - SCORPION_ICACHE_NOCACHE_L2 = 0x50, - SCORPION_HIQUP_NOPED = 0x51, - SCORPION_DATA_ABORT = 0x52, - SCORPION_IRQ = 0x53, - SCORPION_FIQ = 0x54, - SCORPION_ALL_EXCPT = 0x55, - SCORPION_UNDEF = 0x56, - SCORPION_SVC = 0x57, - SCORPION_SMC = 0x58, - SCORPION_PREFETCH_ABORT = 0x59, - SCORPION_INDEX_CHECK = 0x5a, - SCORPION_NULL_CHECK = 0x5b, - SCORPION_EXPL_ICIALLU = 0x5c, - SCORPION_IMPL_ICIALLU = 0x5d, - SCORPION_NONICIALLU_BTAC_INV = 0x5e, - SCORPION_ICIMVAU_IMPL_ICIALLU = 0x5f, - SCORPION_SPIPE_ONLY_CYCLES = 0x60, - SCORPION_XPIPE_ONLY_CYCLES = 0x61, - SCORPION_DUAL_CYCLES = 0x62, - SCORPION_DISPATCH_ANY_CYCLES = 0x63, - SCORPION_FIFO_FULLBLK_CMT = 0x64, - SCORPION_FAIL_COND_INST = 0x65, - SCORPION_PASS_COND_INST = 0x66, - SCORPION_ALLOW_VU_CLK = 0x67, - SCORPION_VU_IDLE = 0x68, - SCORPION_ALLOW_L2_CLK = 0x69, - SCORPION_L2_IDLE = 0x6a, - SCORPION_DTLB_IMPL_INV_SCTLR_DACR = 0x6b, - SCORPION_DTLB_EXPL_INV = 0x6c, - SCORPION_DTLB_MISS = 0x6d, - SCORPION_DTLB_ACCESS = 0x6e, - SCORPION_ITLB_MISS = 0x6f, - SCORPION_ITLB_IMPL_INV = 0x70, - SCORPION_ITLB_EXPL_INV = 0x71, - SCORPION_UTLB_D_MISS = 0x72, - SCORPION_UTLB_D_ACCESS = 0x73, - SCORPION_UTLB_I_MISS = 0x74, - SCORPION_UTLB_I_ACCESS = 0x75, - SCORPION_UTLB_INV_ASID = 0x76, - SCORPION_UTLB_INV_MVA = 0x77, - SCORPION_UTLB_INV_ALL = 0x78, - SCORPION_S2_HOLD_RDQ_UNAVAIL = 0x79, - SCORPION_S2_HOLD = 0x7a, - SCORPION_S2_HOLD_DEV_OP = 0x7b, - SCORPION_S2_HOLD_ORDER = 0x7c, - SCORPION_S2_HOLD_BARRIER = 0x7d, - SCORPION_VIU_DUAL_CYCLE = 0x7e, - SCORPION_VIU_SINGLE_CYCLE = 0x7f, - SCORPION_VX_PIPE_WAR_STALL_CYCLES = 0x80, - SCORPION_VX_PIPE_WAW_STALL_CYCLES = 0x81, - SCORPION_VX_PIPE_RAW_STALL_CYCLES = 0x82, - SCORPION_VX_PIPE_LOAD_USE_STALL = 0x83, - SCORPION_VS_PIPE_WAR_STALL_CYCLES = 0x84, - SCORPION_VS_PIPE_WAW_STALL_CYCLES = 0x85, - SCORPION_VS_PIPE_RAW_STALL_CYCLES = 0x86, - SCORPION_EXCEPTIONS_INV_OPERATION = 0x87, - SCORPION_EXCEPTIONS_DIV_BY_ZERO = 0x88, - SCORPION_COND_INST_FAIL_VX_PIPE = 0x89, - SCORPION_COND_INST_FAIL_VS_PIPE = 0x8a, - SCORPION_EXCEPTIONS_OVERFLOW = 0x8b, - SCORPION_EXCEPTIONS_UNDERFLOW = 0x8c, - SCORPION_EXCEPTIONS_DENORM = 0x8d, + SCORPION_ICACHE_EXPL_INV = 0x4c, + SCORPION_ICACHE_MISS = 0x4d, + SCORPION_ICACHE_ACCESS = 0x4e, + SCORPION_ICACHE_CACHEREQ_L2 = 0x4f, + SCORPION_ICACHE_NOCACHE_L2 = 0x50, + SCORPION_HIQUP_NOPED = 0x51, + SCORPION_DATA_ABORT = 0x52, + SCORPION_IRQ = 0x53, + SCORPION_FIQ = 0x54, + SCORPION_ALL_EXCPT = 0x55, + SCORPION_UNDEF = 0x56, + SCORPION_SVC = 0x57, + SCORPION_SMC = 0x58, + SCORPION_PREFETCH_ABORT = 0x59, + SCORPION_INDEX_CHECK = 0x5a, + SCORPION_NULL_CHECK = 0x5b, + SCORPION_EXPL_ICIALLU = 0x5c, + SCORPION_IMPL_ICIALLU = 0x5d, + SCORPION_NONICIALLU_BTAC_INV = 0x5e, + SCORPION_ICIMVAU_IMPL_ICIALLU = 0x5f, + SCORPION_SPIPE_ONLY_CYCLES = 0x60, + SCORPION_XPIPE_ONLY_CYCLES = 0x61, + SCORPION_DUAL_CYCLES = 0x62, + SCORPION_DISPATCH_ANY_CYCLES = 0x63, + SCORPION_FIFO_FULLBLK_CMT = 0x64, + SCORPION_FAIL_COND_INST = 0x65, + SCORPION_PASS_COND_INST = 0x66, + SCORPION_ALLOW_VU_CLK = 0x67, + SCORPION_VU_IDLE = 0x68, + SCORPION_ALLOW_L2_CLK = 0x69, + SCORPION_L2_IDLE = 0x6a, + SCORPION_DTLB_IMPL_INV_SCTLR_DACR = 0x6b, + SCORPION_DTLB_EXPL_INV = 0x6c, + SCORPION_DTLB_MISS = 0x6d, + SCORPION_DTLB_ACCESS = 0x6e, + SCORPION_ITLB_MISS = 0x6f, + SCORPION_ITLB_IMPL_INV = 0x70, + SCORPION_ITLB_EXPL_INV = 0x71, + SCORPION_UTLB_D_MISS = 0x72, + SCORPION_UTLB_D_ACCESS = 0x73, + SCORPION_UTLB_I_MISS = 0x74, + SCORPION_UTLB_I_ACCESS = 0x75, + SCORPION_UTLB_INV_ASID = 0x76, + SCORPION_UTLB_INV_MVA = 0x77, + SCORPION_UTLB_INV_ALL = 0x78, + SCORPION_S2_HOLD_RDQ_UNAVAIL = 0x79, + SCORPION_S2_HOLD = 0x7a, + SCORPION_S2_HOLD_DEV_OP = 0x7b, + SCORPION_S2_HOLD_ORDER = 0x7c, + SCORPION_S2_HOLD_BARRIER = 0x7d, + SCORPION_VIU_DUAL_CYCLE = 0x7e, + SCORPION_VIU_SINGLE_CYCLE = 0x7f, + SCORPION_VX_PIPE_WAR_STALL_CYCLES = 0x80, + SCORPION_VX_PIPE_WAW_STALL_CYCLES = 0x81, + SCORPION_VX_PIPE_RAW_STALL_CYCLES = 0x82, + SCORPION_VX_PIPE_LOAD_USE_STALL = 0x83, + SCORPION_VS_PIPE_WAR_STALL_CYCLES = 0x84, + SCORPION_VS_PIPE_WAW_STALL_CYCLES = 0x85, + SCORPION_VS_PIPE_RAW_STALL_CYCLES = 0x86, + SCORPION_EXCEPTIONS_INV_OPERATION = 0x87, + SCORPION_EXCEPTIONS_DIV_BY_ZERO = 0x88, + SCORPION_COND_INST_FAIL_VX_PIPE = 0x89, + SCORPION_COND_INST_FAIL_VS_PIPE = 0x8a, + SCORPION_EXCEPTIONS_OVERFLOW = 0x8b, + SCORPION_EXCEPTIONS_UNDERFLOW = 0x8c, + SCORPION_EXCEPTIONS_DENORM = 0x8d, #ifdef CONFIG_ARCH_MSM_SCORPIONMP - SCORPIONMP_NUM_BARRIERS = 0x8e, - SCORPIONMP_BARRIER_CYCLES = 0x8f, + SCORPIONMP_NUM_BARRIERS = 0x8e, + SCORPIONMP_BARRIER_CYCLES = 0x8f, #else - SCORPION_BANK_AB_HIT = 0x8e, - SCORPION_BANK_AB_ACCESS = 0x8f, - SCORPION_BANK_CD_HIT = 0x90, - SCORPION_BANK_CD_ACCESS = 0x91, - SCORPION_BANK_AB_DSIDE_HIT = 0x92, - SCORPION_BANK_AB_DSIDE_ACCESS = 0x93, - SCORPION_BANK_CD_DSIDE_HIT = 0x94, - SCORPION_BANK_CD_DSIDE_ACCESS = 0x95, - SCORPION_BANK_AB_ISIDE_HIT = 0x96, - SCORPION_BANK_AB_ISIDE_ACCESS = 0x97, - SCORPION_BANK_CD_ISIDE_HIT = 0x98, - SCORPION_BANK_CD_ISIDE_ACCESS = 0x99, - SCORPION_ISIDE_RD_WAIT = 0x9a, - SCORPION_DSIDE_RD_WAIT = 0x9b, - SCORPION_BANK_BYPASS_WRITE = 0x9c, - SCORPION_BANK_AB_NON_CASTOUT = 0x9d, - SCORPION_BANK_AB_L2_CASTOUT = 0x9e, - SCORPION_BANK_CD_NON_CASTOUT = 0x9f, - SCORPION_BANK_CD_L2_CASTOUT = 0xa0, + SCORPION_BANK_AB_HIT = 0x8e, + SCORPION_BANK_AB_ACCESS = 0x8f, + SCORPION_BANK_CD_HIT = 0x90, + SCORPION_BANK_CD_ACCESS = 0x91, + SCORPION_BANK_AB_DSIDE_HIT = 0x92, + SCORPION_BANK_AB_DSIDE_ACCESS = 0x93, + SCORPION_BANK_CD_DSIDE_HIT = 0x94, + SCORPION_BANK_CD_DSIDE_ACCESS = 0x95, + SCORPION_BANK_AB_ISIDE_HIT = 0x96, + SCORPION_BANK_AB_ISIDE_ACCESS = 0x97, + SCORPION_BANK_CD_ISIDE_HIT = 0x98, + SCORPION_BANK_CD_ISIDE_ACCESS = 0x99, + SCORPION_ISIDE_RD_WAIT = 0x9a, + SCORPION_DSIDE_RD_WAIT = 0x9b, + SCORPION_BANK_BYPASS_WRITE = 0x9c, + SCORPION_BANK_AB_NON_CASTOUT = 0x9d, + SCORPION_BANK_AB_L2_CASTOUT = 0x9e, + SCORPION_BANK_CD_NON_CASTOUT = 0x9f, + SCORPION_BANK_CD_L2_CASTOUT = 0xa0, #endif MSM_MAX_EVT }; @@ -209,8 +209,8 @@ static const struct scorp_evt sc_evt[] = { {SCORPION_EXCEPTIONS_DENORM, 0x8c000000, 4, 0x5f}, #ifdef CONFIG_ARCH_MSM_SCORPIONMP - {SCORPIONMP_NUM_BARRIERS, 0x80000e00, 3, 0x59}, - {SCORPIONMP_BARRIER_CYCLES, 0x800e0000, 3, 0x5a}, + {SCORPIONMP_NUM_BARRIERS, 0x80000e00, 3, 0x59}, + {SCORPIONMP_BARRIER_CYCLES, 0x800e0000, 3, 0x5a}, #else {SCORPION_BANK_AB_HIT, 0x80000001, 3, 0x58}, {SCORPION_BANK_AB_ACCESS, 0x80000100, 3, 0x59}, @@ -375,8 +375,8 @@ static void scorpion_write_vlpm(u32 val) } struct scorpion_access_funcs { - u32 (*read) (void); - void (*write) (u32); + u32(*read)(void); + void (*write)(u32); }; struct scorpion_access_funcs scor_func[] = { @@ -395,7 +395,7 @@ static void scorpion_pre_vlpm(void) u32 venum_new_val; u32 fp_new_val; - /* CPACR Enable CP10 access*/ + /* CPACR Enable CP10 access */ asm volatile("mrc p15, 0, %0, c1, c0, 2" : "=r" (venum_orig_val)); venum_new_val = venum_orig_val | 0x00300000; asm volatile("mcr p15, 0, %0, c1, c0, 2" : : "r" (venum_new_val)); @@ -407,9 +407,9 @@ static void scorpion_pre_vlpm(void) static void scorpion_post_vlpm(void) { - /* Restore FPEXC*/ + /* Restore FPEXC */ asm volatile("mcr p10, 7, %0, c8, c0, 0" : : "r" (fp_orig_val)); - /* Restore CPACR*/ + /* Restore CPACR */ asm volatile("mcr p15, 0, %0, c1, c0, 2" : : "r" (venum_orig_val)); } @@ -464,7 +464,8 @@ static inline void scorpion_pmnc_write_evtsel(unsigned int cnt, u32 val) u32 zero = 0; struct scorp_evt evtinfo; // extract evtinfo.grp and evtinfo.tevt_type_act from val - if (get_scorpion_evtinfo(val, &evtinfo) == 0) return; + if (get_scorpion_evtinfo(val, &evtinfo) == 0) + return; asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (evtinfo.evt_type_act)); asm volatile("mcr p15, 0, %0, c9, c15, 0" : : "r" (zero)); scorpion_evt_setup(evtinfo.grp, val); @@ -482,7 +483,7 @@ static void scorpion_pmnc_reset_counter(unsigned int cnt) asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (val)); if (pmnc_enabled[cnt] != 0) - scorpion_pmnc_enable_counter(cnt); + scorpion_pmnc_enable_counter(cnt); } else if (cnt >= CNTMAX) { pr_err("gator: CPU%u resetting wrong PMNC counter %d\n", smp_processor_id(), cnt); @@ -490,10 +491,10 @@ static void scorpion_pmnc_reset_counter(unsigned int cnt) scorpion_pmnc_disable_counter(cnt); if (scorpion_pmnc_select_counter(cnt) == cnt) - asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (val)); + asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (val)); if (pmnc_enabled[cnt] != 0) - scorpion_pmnc_enable_counter(cnt); + scorpion_pmnc_enable_counter(cnt); } } @@ -507,14 +508,14 @@ static int gator_events_scorpion_create_files(struct super_block *sb, struct den if (i == 0) { snprintf(buf, sizeof buf, "%s_ccnt", pmnc_name); } else { - snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i-1); + snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i - 1); } dir = gatorfs_mkdir(sb, root, buf); if (!dir) { return -1; } gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]); - gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]); + gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]); if (i > 0) { gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]); } @@ -523,7 +524,7 @@ static int gator_events_scorpion_create_files(struct super_block *sb, struct den return 0; } -static int gator_events_scorpion_online(int** buffer) +static int gator_events_scorpion_online(int **buffer) { unsigned int cnt, len = 0, cpu = smp_processor_id(); @@ -562,13 +563,10 @@ static int gator_events_scorpion_online(int** buffer) // read the counters and toss the invalid data, return zero instead for (cnt = 0; cnt < pmnc_counters; cnt++) { if (pmnc_enabled[cnt]) { - int value; if (cnt == CCNT) { - value = scorpion_ccnt_read(); + scorpion_ccnt_read(); } else if (scorpion_pmnc_select_counter(cnt) == cnt) { - value = scorpion_cntn_read(); - } else { - value = 0; + scorpion_cntn_read(); } scorpion_pmnc_reset_counter(cnt); @@ -583,7 +581,7 @@ static int gator_events_scorpion_online(int** buffer) return len; } -static int gator_events_scorpion_offline(int** buffer) +static int gator_events_scorpion_offline(int **buffer) { scorpion_pmnc_write(scorpion_pmnc_read() & ~PMNC_E); return 0; @@ -657,7 +655,7 @@ int gator_events_scorpion_init(void) 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_fs.c b/driver/gator_fs.c index 81b0d5b..9ff118b 100644 --- a/driver/gator_fs.c +++ b/driver/gator_fs.c @@ -35,8 +35,8 @@ static struct inode *gatorfs_get_inode(struct super_block *sb, int mode) } static const struct super_operations s_ops = { - .statfs = simple_statfs, - .drop_inode = generic_delete_inode, + .statfs = simple_statfs, + .drop_inode = generic_delete_inode, }; ssize_t gatorfs_str_to_user(char const *str, char __user *buf, size_t count, loff_t *offset) @@ -104,19 +104,21 @@ static int default_open(struct inode *inode, struct file *filp) } static const struct file_operations ulong_fops = { - .read = ulong_read_file, - .write = ulong_write_file, - .open = default_open, + .read = ulong_read_file, + .write = ulong_write_file, + .open = default_open, }; static const struct file_operations ulong_ro_fops = { - .read = ulong_read_file, - .open = default_open, + .read = ulong_read_file, + .open = default_open, }; static struct dentry *__gatorfs_create_file(struct super_block *sb, - struct dentry *root, char const *name, const struct file_operations *fops, - int perm) + struct dentry *root, + char const *name, + const struct file_operations *fops, + int perm) { struct dentry *dentry; struct inode *inode; @@ -135,10 +137,10 @@ static struct dentry *__gatorfs_create_file(struct super_block *sb, } int gatorfs_create_ulong(struct super_block *sb, struct dentry *root, - char const *name, unsigned long *val) + char const *name, unsigned long *val) { struct dentry *d = __gatorfs_create_file(sb, root, name, - &ulong_fops, 0644); + &ulong_fops, 0644); if (!d) return -EFAULT; @@ -147,10 +149,10 @@ int gatorfs_create_ulong(struct super_block *sb, struct dentry *root, } int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root, - char const *name, unsigned long *val) + char const *name, unsigned long *val) { struct dentry *d = __gatorfs_create_file(sb, root, name, - &ulong_ro_fops, 0444); + &ulong_ro_fops, 0444); if (!d) return -EFAULT; @@ -165,15 +167,15 @@ static ssize_t atomic_read_file(struct file *file, char __user *buf, size_t coun } static const struct file_operations atomic_ro_fops = { - .read = atomic_read_file, - .open = default_open, + .read = atomic_read_file, + .open = default_open, }; int gatorfs_create_ro_atomic(struct super_block *sb, struct dentry *root, - char const *name, atomic_t *val) + char const *name, atomic_t *val) { struct dentry *d = __gatorfs_create_file(sb, root, name, - &atomic_ro_fops, 0444); + &atomic_ro_fops, 0444); if (!d) return -EFAULT; @@ -182,7 +184,7 @@ int gatorfs_create_ro_atomic(struct super_block *sb, struct dentry *root, } int gatorfs_create_file(struct super_block *sb, struct dentry *root, - char const *name, const struct file_operations *fops) + char const *name, const struct file_operations *fops) { if (!__gatorfs_create_file(sb, root, name, fops, 0644)) return -EFAULT; @@ -190,7 +192,8 @@ int gatorfs_create_file(struct super_block *sb, struct dentry *root, } int gatorfs_create_file_perm(struct super_block *sb, struct dentry *root, - char const *name, const struct file_operations *fops, int perm) + char const *name, + const struct file_operations *fops, int perm) { if (!__gatorfs_create_file(sb, root, name, fops, perm)) return -EFAULT; @@ -198,7 +201,7 @@ int gatorfs_create_file_perm(struct super_block *sb, struct dentry *root, } struct dentry *gatorfs_mkdir(struct super_block *sb, - struct dentry *root, char const *name) + struct dentry *root, char const *name) { struct dentry *dentry; struct inode *inode; @@ -256,28 +259,29 @@ static int gatorfs_fill_super(struct super_block *sb, void *data, int silent) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) static int gatorfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data, struct vfsmount *mnt) + int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { return get_sb_single(fs_type, flags, data, gatorfs_fill_super, mnt); } #else static struct dentry *gatorfs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) + int flags, const char *dev_name, void *data) { return mount_nodev(fs_type, flags, data, gatorfs_fill_super); } #endif static struct file_system_type gatorfs_type = { - .owner = THIS_MODULE, - .name = "gatorfs", + .owner = THIS_MODULE, + .name = "gatorfs", #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) - .get_sb = gatorfs_get_sb, + .get_sb = gatorfs_get_sb, #else - .mount = gatorfs_mount, + .mount = gatorfs_mount, #endif - .kill_sb = kill_litter_super, + .kill_sb = kill_litter_super, }; int __init gatorfs_register(void) diff --git a/driver/gator_main.c b/driver/gator_main.c index a2d8ef0..9e031c1 100644 --- a/driver/gator_main.c +++ b/driver/gator_main.c @@ -7,7 +7,7 @@ * */ -static unsigned long gator_protocol_version = 11; +static unsigned long gator_protocol_version = 12; #include <linux/slab.h> #include <linux/cpu.h> @@ -48,9 +48,9 @@ static unsigned long gator_protocol_version = 11; #if (GATOR_PERF_SUPPORT) && (!(GATOR_PERF_PMU_SUPPORT)) #ifndef CONFIG_PERF_EVENTS -#warning gator requires the kernel to have CONFIG_PERF_EVENTS defined to support pmu hardware counters +#error gator requires the kernel to have CONFIG_PERF_EVENTS defined to support pmu hardware counters #elif !defined CONFIG_HW_PERF_EVENTS -#warning gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters +#error gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters #endif #endif @@ -60,12 +60,12 @@ static unsigned long gator_protocol_version = 11; #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 (64*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 (64*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 GPU_TRACE_BUFFER_SIZE (64*1024) // gpu trace 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 GPU_TRACE_BUFFER_SIZE (64*1024) // gpu trace 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 NO_COOKIE 0U #define INVALID_COOKIE ~0U @@ -94,7 +94,6 @@ static unsigned long gator_protocol_version = 11; #define MAXSIZE_PACK32 5 #define MAXSIZE_PACK64 10 -#define MAXSIZE_CORE_NAME 32 #if defined(__arm__) #define PC_REG regs->ARM_pc @@ -121,6 +120,7 @@ enum { * Globals ******************************************************************************/ static unsigned long gator_cpu_cores; +// 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; @@ -148,15 +148,23 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len); static void gator_buffer_write_string(int cpu, int buftype, const char *x); static void gator_add_trace(int cpu, unsigned long address); -static void gator_add_sample(int cpu, struct pt_regs * const regs); +static void gator_add_sample(int cpu, struct pt_regs *const regs); static uint64_t gator_get_time(void); +// 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. 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 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 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 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 static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], buffer_space_available); +// The buffer. Allocated in gator_op_setup static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer); /****************************************************************************** @@ -177,9 +185,125 @@ static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer); /****************************************************************************** * Misc ******************************************************************************/ -#if defined(__arm__) || defined(__aarch64__) + +struct gator_cpu gator_cpus[] = { + { + .cpuid = ARM1136, + .core_name = "ARM1136", + .pmnc_name = "ARM_ARM11", + .pmnc_counters = 3, + .ccnt = 2, + }, + { + .cpuid = ARM1156, + .core_name = "ARM1156", + .pmnc_name = "ARM_ARM11", + .pmnc_counters = 3, + .ccnt = 2, + }, + { + .cpuid = ARM1176, + .core_name = "ARM1176", + .pmnc_name = "ARM_ARM11", + .pmnc_counters = 3, + .ccnt = 2, + }, + { + .cpuid = ARM11MPCORE, + .core_name = "ARM11MPCore", + .pmnc_name = "ARM_ARM11MPCore", + .pmnc_counters = 3, + }, + { + .cpuid = CORTEX_A5, + .core_name = "Cortex-A5", + .pmnc_name = "ARM_Cortex-A5", + .pmnc_counters = 2, + }, + { + .cpuid = CORTEX_A7, + .core_name = "Cortex-A7", + .pmnc_name = "ARM_Cortex-A7", + .pmnc_counters = 4, + }, + { + .cpuid = CORTEX_A8, + .core_name = "Cortex-A8", + .pmnc_name = "ARM_Cortex-A8", + .pmnc_counters = 4, + }, + { + .cpuid = CORTEX_A9, + .core_name = "Cortex-A9", + .pmnc_name = "ARM_Cortex-A9", + .pmnc_counters = 6, + }, + { + .cpuid = CORTEX_A15, + .core_name = "Cortex-A15", + .pmnc_name = "ARM_Cortex-A15", + .pmnc_counters = 6, + }, + { + .cpuid = SCORPION, + .core_name = "Scorpion", + .pmnc_name = "Scorpion", + .pmnc_counters = 4, + }, + { + .cpuid = SCORPIONMP, + .core_name = "ScorpionMP", + .pmnc_name = "ScorpionMP", + .pmnc_counters = 4, + }, + { + .cpuid = KRAITSIM, + .core_name = "KraitSIM", + .pmnc_name = "Krait", + .pmnc_counters = 4, + }, + { + .cpuid = KRAIT, + .core_name = "Krait", + .pmnc_name = "Krait", + .pmnc_counters = 4, + }, + { + .cpuid = KRAIT_S4_PRO, + .core_name = "Krait S4 Pro", + .pmnc_name = "Krait", + .pmnc_counters = 4, + }, + { + .cpuid = CORTEX_A53, + .core_name = "Cortex-A53", + .pmnc_name = "ARM_Cortex-A53", + .pmnc_counters = 6, + }, + { + .cpuid = CORTEX_A57, + .core_name = "Cortex-A57", + .pmnc_name = "ARM_Cortex-A57", + .pmnc_counters = 6, + }, + { + .cpuid = AARCH64, + .core_name = "AArch64", + .pmnc_name = "ARM_AArch64", + .pmnc_counters = 6, + }, + { + .cpuid = OTHER, + .core_name = "Other", + .pmnc_name = "Other", + .pmnc_counters = 6, + }, + {} +}; + u32 gator_cpuid(void) { +#if defined(__arm__) || defined(__aarch64__) u32 val; #if !defined(__aarch64__) asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (val)); @@ -187,8 +311,10 @@ u32 gator_cpuid(void) asm volatile("mrs %0, midr_el1" : "=r" (val)); #endif return (val >> 4) & 0xfff; -} +#else + return OTHER; #endif +} static void gator_buffer_wake_up(unsigned long data) { @@ -198,7 +324,7 @@ static void gator_buffer_wake_up(unsigned long data) /****************************************************************************** * Commit interface ******************************************************************************/ -static bool buffer_commit_ready(int* cpu, int* buftype) +static bool buffer_commit_ready(int *cpu, int *buftype) { int cpu_x, x; for_each_present_cpu(cpu_x) { @@ -265,7 +391,7 @@ static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int le int i; u32 write = per_cpu(gator_buffer_write, cpu)[buftype]; u32 mask = gator_buffer_mask[buftype]; - char* buffer = per_cpu(gator_buffer, cpu)[buftype]; + char *buffer = per_cpu(gator_buffer, cpu)[buftype]; for (i = 0; i < len; i++) { buffer[write] = x[i]; @@ -282,55 +408,27 @@ static void gator_buffer_write_string(int cpu, int buftype, const char *x) gator_buffer_write_bytes(cpu, buftype, x, len); } -static void gator_buffer_header(int cpu, int buftype) -{ - int frame; - - switch (buftype) { - case SUMMARY_BUF: - frame = FRAME_SUMMARY; - break; - case BACKTRACE_BUF: - frame = FRAME_BACKTRACE; - break; - case NAME_BUF: - frame = FRAME_NAME; - break; - case COUNTER_BUF: - frame = FRAME_COUNTER; - break; - case BLOCK_COUNTER_BUF: - frame = FRAME_BLOCK_COUNTER; - break; - case ANNOTATE_BUF: - frame = FRAME_ANNOTATE; - break; - case SCHED_TRACE_BUF: - frame = FRAME_SCHED_TRACE; - break; - case GPU_TRACE_BUF: - frame = FRAME_GPU_TRACE; - break; - case IDLE_BUF: - frame = FRAME_IDLE; - break; - default: - frame = -1; - break; - } - - if (per_cpu(gator_buffer, cpu)[buftype]) { - marshal_frame(cpu, buftype, frame); - } -} - static void gator_commit_buffer(int cpu, int buftype) { + int type_length, commit, length, byte; + 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 + 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) { + length += gator_buffer_size[buftype]; + } + length = length - type_length - sizeof(int); + for (byte = 0; byte < sizeof(int); 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]; - gator_buffer_header(cpu, buftype); + marshal_frame(cpu, buftype); // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater mod_timer(&gator_buffer_wake_up_timer, jiffies + 1); @@ -359,7 +457,7 @@ static void gator_add_trace(int cpu, unsigned long address) marshal_backtrace(offset & ~1, cookie); } -static void gator_add_sample(int cpu, struct pt_regs * const regs) +static void gator_add_sample(int cpu, struct pt_regs *const regs) { bool inKernel; unsigned long exec_cookie; @@ -392,11 +490,11 @@ static void gator_add_sample(int cpu, struct pt_regs * const regs) ******************************************************************************/ static void gator_timer_interrupt(void) { - struct pt_regs * const regs = get_irq_regs(); + struct pt_regs *const regs = get_irq_regs(); gator_backtrace_handler(regs); } -void gator_backtrace_handler(struct pt_regs * const regs) +void gator_backtrace_handler(struct pt_regs *const regs) { int cpu = smp_processor_id(); @@ -412,11 +510,11 @@ void gator_backtrace_handler(struct pt_regs * const regs) static int gator_running; // This function runs in interrupt context and on the appropriate core -static void gator_timer_offline(void* unused) +static void gator_timer_offline(void *unused) { struct gator_interface *gi; int i, len, cpu = smp_processor_id(); - int* buffer; + int *buffer; gator_trace_sched_offline(); gator_trace_power_offline(); @@ -444,8 +542,8 @@ static void gator_timer_offline_dispatch(int cpu) struct gator_interface *gi; list_for_each_entry(gi, &gator_events, list) - if (gi->offline_dispatch) - gi->offline_dispatch(cpu); + if (gi->offline_dispatch) + gi->offline_dispatch(cpu); } static void gator_timer_stop(void) @@ -464,11 +562,11 @@ static void gator_timer_stop(void) } // This function runs in interrupt context and on the appropriate core -static void gator_timer_online(void* unused) +static void gator_timer_online(void *unused) { struct gator_interface *gi; int len, cpu = smp_processor_id(); - int* buffer; + int *buffer; gator_trace_power_online(); @@ -485,25 +583,15 @@ static void gator_timer_online(void* unused) gator_hrtimer_online(cpu); #if defined(__arm__) || defined(__aarch64__) { - const char * core_name = NULL; - - // String lengths must be less than MAXSIZE_CORE_NAME - switch (gator_cpuid()) { - case ARM1136: core_name = "ARM1136"; break; - case ARM1156: core_name = "ARM1156"; break; - case ARM1176: core_name = "ARM1176"; break; - case ARM11MPCORE: core_name = "ARM11MPCore"; break; - case CORTEX_A5: core_name = "Cortex-A5"; break; - case CORTEX_A7: core_name = "Cortex-A7"; break; - case CORTEX_A8: core_name = "Cortex-A8"; break; - case CORTEX_A9: core_name = "Cortex-A9"; break; - case CORTEX_A15: core_name = "Cortex-A15"; break; - case SCORPION: core_name = "Scorpion"; break; - case SCORPIONMP: core_name = "ScorpionMP"; break; - case KRAITSIM: core_name = "KraitSIM"; break; - case KRAIT: core_name = "Krait"; break; - case AARCH64: core_name = "AArch64"; break; - default: core_name = "Unknown"; break; + const char *core_name = "Unknown"; + const u32 cpuid = gator_cpuid(); + int i; + + for (i = 0; gator_cpus[i].cpuid != 0; ++i) { + if (gator_cpus[i].cpuid == cpuid) { + core_name = gator_cpus[i].core_name; + break; + } } marshal_core_name(core_name); @@ -517,8 +605,8 @@ static void gator_timer_online_dispatch(int cpu) struct gator_interface *gi; list_for_each_entry(gi, &gator_events, list) - if (gi->online_dispatch) - gi->online_dispatch(cpu); + if (gi->online_dispatch) + gi->online_dispatch(cpu); } int gator_timer_start(unsigned long sample_rate) @@ -563,16 +651,16 @@ static int __cpuinit gator_hotcpu_notify(struct notifier_block *self, unsigned l long cpu = (long)hcpu; switch (action) { - case CPU_DOWN_PREPARE: - case CPU_DOWN_PREPARE_FROZEN: - smp_call_function_single(cpu, gator_timer_offline, NULL, 1); - gator_timer_offline_dispatch(cpu); - break; - case CPU_ONLINE: - case CPU_ONLINE_FROZEN: - gator_timer_online_dispatch(cpu); - smp_call_function_single(cpu, gator_timer_online, NULL, 1); - break; + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: + smp_call_function_single(cpu, gator_timer_offline, NULL, 1); + gator_timer_offline_dispatch(cpu); + break; + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + gator_timer_online_dispatch(cpu); + smp_call_function_single(cpu, gator_timer_online, NULL, 1); + break; } return NOTIFY_OK; @@ -589,24 +677,24 @@ static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void int cpu; switch (event) { - case PM_HIBERNATION_PREPARE: - case PM_SUSPEND_PREPARE: - unregister_hotcpu_notifier(&gator_hotcpu_notifier); - unregister_scheduler_tracepoints(); - on_each_cpu(gator_timer_offline, NULL, 1); - for_each_online_cpu(cpu) { - gator_timer_offline_dispatch(cpu); - } - break; - case PM_POST_HIBERNATION: - case PM_POST_SUSPEND: - for_each_online_cpu(cpu) { - gator_timer_online_dispatch(cpu); - } - on_each_cpu(gator_timer_online, NULL, 1); - register_scheduler_tracepoints(); - register_hotcpu_notifier(&gator_hotcpu_notifier); - break; + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: + unregister_hotcpu_notifier(&gator_hotcpu_notifier); + unregister_scheduler_tracepoints(); + on_each_cpu(gator_timer_offline, NULL, 1); + for_each_online_cpu(cpu) { + gator_timer_offline_dispatch(cpu); + } + break; + case PM_POST_HIBERNATION: + case PM_POST_SUSPEND: + for_each_online_cpu(cpu) { + gator_timer_online_dispatch(cpu); + } + on_each_cpu(gator_timer_online, NULL, 1); + register_scheduler_tracepoints(); + register_hotcpu_notifier(&gator_hotcpu_notifier); + break; } return NOTIFY_OK; @@ -676,6 +764,15 @@ static int gator_init(void) return 0; } +static void gator_exit(void) +{ + struct gator_interface *gi; + + list_for_each_entry(gi, &gator_events, list) + if (gi->shutdown) + gi->shutdown(); +} + static int gator_start(void) { unsigned long cpu, i; @@ -684,7 +781,7 @@ static int gator_start(void) // Initialize the buffer with the frame type and core for_each_present_cpu(cpu) { for (i = 0; i < NUM_GATOR_BUFS; i++) { - gator_buffer_header(cpu, i); + marshal_frame(cpu, i); } } @@ -741,8 +838,8 @@ annotate_failure: cookies_failure: // stop all events list_for_each_entry(gi, &gator_events, list) - if (gi->stop) - gi->stop(); + if (gi->stop) + gi->stop(); events_failure: return -1; @@ -758,13 +855,13 @@ static void gator_stop(void) 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 + 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 list_for_each_entry(gi, &gator_events, list) - if (gi->stop) - gi->stop(); + if (gi->stop) + gi->stop(); } /****************************************************************************** @@ -941,8 +1038,8 @@ static ssize_t enable_write(struct file *file, char const __user *buf, size_t co } static const struct file_operations enable_fops = { - .read = enable_read, - .write = enable_write, + .read = enable_read, + .write = enable_write, }; static int userspace_buffer_open(struct inode *inode, struct file *file) @@ -978,10 +1075,10 @@ static int userspace_buffer_release(struct inode *inode, struct file *file) } static ssize_t userspace_buffer_read(struct file *file, char __user *buf, - size_t count, loff_t *offset) + size_t count, loff_t *offset) { int retval = -EINVAL; - int commit = 0, length, length1, length2, read, byte, type_length; + int commit = 0, length1, length2, read; char *buffer1; char *buffer2 = NULL; int cpu, buftype; @@ -1026,13 +1123,6 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf, length2 = commit; } - // post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload - type_length = gator_response_type ? 1 : 0; - length = length1 + length2 - type_length - sizeof(int); - for (byte = 0; byte < sizeof(int); byte++) { - per_cpu(gator_buffer, cpu)[buftype][(read + type_length + byte) & gator_buffer_mask[buftype]] = (length >> byte * 8) & 0xFF; - } - /* start, middle or end */ if (length1 > 0) { if (copy_to_user(&buf[0], buffer1, length1)) { @@ -1059,15 +1149,14 @@ out: } const struct file_operations gator_event_buffer_fops = { - .open = userspace_buffer_open, - .release = userspace_buffer_release, - .read = userspace_buffer_read, + .open = userspace_buffer_open, + .release = userspace_buffer_release, + .read = userspace_buffer_read, }; static ssize_t depth_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { - return gatorfs_ulong_to_user(gator_backtrace_depth, buf, count, - offset); + return gatorfs_ulong_to_user(gator_backtrace_depth, buf, count, offset); } static ssize_t depth_write(struct file *file, char const __user *buf, size_t count, loff_t *offset) @@ -1090,8 +1179,8 @@ static ssize_t depth_write(struct file *file, char const __user *buf, size_t cou } static const struct file_operations depth_fops = { - .read = depth_read, - .write = depth_write + .read = depth_read, + .write = depth_write }; void gator_op_create_files(struct super_block *sb, struct dentry *root) @@ -1105,7 +1194,7 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root) for_each_present_cpu(cpu) { gator_cpu_cores++; } - userspace_buffer_size = BACKTRACE_BUFFER_SIZE; + userspace_buffer_size = BACKTRACE_BUFFER_SIZE; gator_response_type = 1; gatorfs_create_file(sb, root, "enable", &enable_fops); @@ -1123,8 +1212,8 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root) // 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); + if (gi->create_files) + gi->create_files(sb, dir); // Power interface gator_trace_power_create_files(sb, dir); @@ -1153,6 +1242,7 @@ static void __exit gator_module_exit(void) { del_timer_sync(&gator_buffer_wake_up_timer); tracepoint_synchronize_unregister(); + gator_exit(); gatorfs_unregister(); } diff --git a/driver/gator_marshaling.c b/driver/gator_marshaling.c index a84b280..b2efdd2 100644 --- a/driver/gator_marshaling.c +++ b/driver/gator_marshaling.c @@ -7,49 +7,52 @@ * */ -static void marshal_summary(long long timestamp, long long uptime) { +static void marshal_summary(long long timestamp, long long uptime) +{ int cpu = 0; gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, timestamp); gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, uptime); buffer_check(cpu, SUMMARY_BUF); } -static bool marshal_cookie_header(char* text) { +static bool marshal_cookie_header(const char *text) +{ int cpu = smp_processor_id(); - return buffer_check_space(cpu, NAME_BUF, strlen(text) + 2*MAXSIZE_PACK32); + return buffer_check_space(cpu, NAME_BUF, strlen(text) + 3 * MAXSIZE_PACK32); } -static void marshal_cookie(int cookie, char* text) { +static void marshal_cookie(int cookie, const char *text) +{ int cpu = smp_processor_id(); - // TODO(dreric01) How long can the string be? - if (buffer_check_space(cpu, NAME_BUF, 2*MAXSIZE_PACK32)) { - 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); - } + // 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); buffer_check(cpu, NAME_BUF); } -static void marshal_thread_name(int pid, char* name) { +static void marshal_thread_name(int pid, char *name) +{ unsigned long flags, cpu; local_irq_save(flags); cpu = smp_processor_id(); - if (buffer_check_space(cpu, NAME_BUF, TASK_COMM_LEN + 2*MAXSIZE_PACK32 + MAXSIZE_PACK64)) { + if (buffer_check_space(cpu, NAME_BUF, TASK_COMM_LEN + 3 * MAXSIZE_PACK32 + MAXSIZE_PACK64)) { gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_THREAD_NAME); gator_buffer_write_packed_int64(cpu, NAME_BUF, gator_get_time()); gator_buffer_write_packed_int(cpu, NAME_BUF, pid); gator_buffer_write_string(cpu, NAME_BUF, name); } - local_irq_restore(flags); buffer_check(cpu, NAME_BUF); + local_irq_restore(flags); } -static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel) { +static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel) +{ int cpu = smp_processor_id(); - if (buffer_check_space(cpu, BACKTRACE_BUF, gator_backtrace_depth*2*MAXSIZE_PACK32)) { + if (buffer_check_space(cpu, BACKTRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32 + gator_backtrace_depth * 2 * MAXSIZE_PACK32)) { gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, gator_get_time()); gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, exec_cookie); - gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, tgid); + gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, tgid); gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, pid); gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, inKernel); return true; @@ -61,13 +64,15 @@ static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inK return false; } -static void marshal_backtrace(unsigned long address, int cookie) { +static void marshal_backtrace(unsigned long address, int cookie) +{ int cpu = smp_processor_id(); - gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, address); gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie); + gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, address); } -static void marshal_backtrace_footer(void) { +static void marshal_backtrace_footer(void) +{ int cpu = smp_processor_id(); gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_END_BACKTRACE); @@ -75,30 +80,31 @@ static void marshal_backtrace_footer(void) { buffer_check(cpu, BACKTRACE_BUF); } -static bool marshal_event_header(void) { +static bool marshal_event_header(void) +{ unsigned long flags, cpu = smp_processor_id(); bool retval = false; - + 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, gator_get_time()); retval = true; } - local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full buffer_check(cpu, BLOCK_COUNTER_BUF); + local_irq_restore(flags); return retval; } -static void marshal_event(int len, int* buffer) { +static void marshal_event(int len, int *buffer) +{ unsigned long i, flags, cpu = smp_processor_id(); if (len <= 0) return; - + // length must be even since all data is a (key, value) pair if (len & 0x1) { pr_err("gator: invalid counter data detected and discarded"); @@ -106,27 +112,26 @@ static void marshal_event(int len, int* buffer) { } // events must be written in key,value pairs + local_irq_save(flags); for (i = 0; i < len; i += 2) { - local_irq_save(flags); - if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2*MAXSIZE_PACK32)) { - local_irq_restore(flags); + 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]); - local_irq_restore(flags); } - // Check and commit; commit is set to occur once buffer is 3/4 full buffer_check(cpu, BLOCK_COUNTER_BUF); + local_irq_restore(flags); } -static void marshal_event64(int len, long long* buffer64) { +static void marshal_event64(int len, long long *buffer64) +{ unsigned long i, flags, cpu = smp_processor_id(); if (len <= 0) return; - + // length must be even since all data is a (key, value) pair if (len & 0x1) { pr_err("gator: invalid counter data detected and discarded"); @@ -134,48 +139,47 @@ static void marshal_event64(int len, long long* buffer64) { } // events must be written in key,value pairs + local_irq_save(flags); for (i = 0; i < len; i += 2) { - local_irq_save(flags); - if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2*MAXSIZE_PACK64)) { - local_irq_restore(flags); + 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); } - // Check and commit; commit is set to occur once buffer is 3/4 full buffer_check(cpu, BLOCK_COUNTER_BUF); + local_irq_restore(flags); } #if GATOR_CPU_FREQ_SUPPORT -static void marshal_event_single(int core, int key, int value) { +static void marshal_event_single(int core, int key, int value) +{ unsigned long flags, cpu; - + local_irq_save(flags); cpu = smp_processor_id(); - if (buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK64 + 3*MAXSIZE_PACK32)) { + if (buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) { gator_buffer_write_packed_int64(cpu, COUNTER_BUF, gator_get_time()); gator_buffer_write_packed_int(cpu, COUNTER_BUF, core); gator_buffer_write_packed_int(cpu, COUNTER_BUF, key); 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 buffer_check(cpu, COUNTER_BUF); + local_irq_restore(flags); } #endif -static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid) { +static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid) +{ unsigned long cpu = smp_processor_id(), flags; if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF]) return; local_irq_save(flags); - if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5*MAXSIZE_PACK32)) { + if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) { gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_START); gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, gator_get_time()); gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit); @@ -183,39 +187,39 @@ static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid) { gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, tgid); gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, pid); } - local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full buffer_check(cpu, GPU_TRACE_BUF); + local_irq_restore(flags); } -static void marshal_sched_gpu_stop(int unit, int core) { +static void marshal_sched_gpu_stop(int unit, int core) +{ unsigned long cpu = smp_processor_id(), flags; if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF]) return; local_irq_save(flags); - if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 3*MAXSIZE_PACK32)) { + if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) { gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_STOP); gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, gator_get_time()); gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit); gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core); } - local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full buffer_check(cpu, GPU_TRACE_BUF); + local_irq_restore(flags); } -static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state) { +static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state) +{ unsigned long cpu = smp_processor_id(), flags; if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF]) return; local_irq_save(flags); - if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5*MAXSIZE_PACK32)) { + if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) { gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_SWITCH); gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, gator_get_time()); gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid); @@ -223,49 +227,88 @@ static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state) gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie); 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 buffer_check(cpu, SCHED_TRACE_BUF); + local_irq_restore(flags); } -static void marshal_sched_trace_exit(int tgid, int pid) { +static void marshal_sched_trace_exit(int tgid, int pid) +{ unsigned long cpu = smp_processor_id(), flags; if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF]) return; local_irq_save(flags); - if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 2*MAXSIZE_PACK32)) { + if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) { gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_EXIT); gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, gator_get_time()); 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 buffer_check(cpu, SCHED_TRACE_BUF); + local_irq_restore(flags); } #if GATOR_CPU_FREQ_SUPPORT -static void marshal_idle(int core, int state) { +static void marshal_idle(int core, int state) +{ unsigned long flags, cpu; - + local_irq_save(flags); cpu = smp_processor_id(); - if (buffer_check_space(cpu, IDLE_BUF, MAXSIZE_PACK64 + 2*MAXSIZE_PACK32)) { + if (buffer_check_space(cpu, IDLE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) { gator_buffer_write_packed_int(cpu, IDLE_BUF, state); gator_buffer_write_packed_int64(cpu, IDLE_BUF, gator_get_time()); 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 buffer_check(cpu, IDLE_BUF); + local_irq_restore(flags); } #endif -static void marshal_frame(int cpu, int buftype, int frame) { +static void marshal_frame(int cpu, int buftype) +{ + int frame; + + if (!per_cpu(gator_buffer, cpu)[buftype]) { + return; + } + + switch (buftype) { + case SUMMARY_BUF: + frame = FRAME_SUMMARY; + break; + case BACKTRACE_BUF: + frame = FRAME_BACKTRACE; + break; + case NAME_BUF: + frame = FRAME_NAME; + break; + case COUNTER_BUF: + frame = FRAME_COUNTER; + break; + case BLOCK_COUNTER_BUF: + frame = FRAME_BLOCK_COUNTER; + break; + case ANNOTATE_BUF: + frame = FRAME_ANNOTATE; + break; + case SCHED_TRACE_BUF: + frame = FRAME_SCHED_TRACE; + break; + case GPU_TRACE_BUF: + frame = FRAME_GPU_TRACE; + break; + case IDLE_BUF: + frame = FRAME_IDLE; + break; + default: + frame = -1; + break; + } + // add response type if (gator_response_type > 0) { gator_buffer_write_packed_int(cpu, buftype, gator_response_type); @@ -280,7 +323,8 @@ static void marshal_frame(int cpu, int buftype, int frame) { } #if defined(__arm__) || defined(__aarch64__) -static void marshal_core_name(const char* name) { +static void marshal_core_name(const char *name) +{ int cpu = smp_processor_id(); unsigned long flags; local_irq_save(flags); @@ -288,8 +332,7 @@ static void marshal_core_name(const char* name) { gator_buffer_write_packed_int(cpu, NAME_BUF, HRTIMER_CORE_NAME); gator_buffer_write_string(cpu, NAME_BUF, name); } - local_irq_restore(flags); - buffer_check(cpu, NAME_BUF); + local_irq_restore(flags); } #endif diff --git a/driver/gator_pack.c b/driver/gator_pack.c index 5ad53db..119746b 100644 --- a/driver/gator_pack.c +++ b/driver/gator_pack.c @@ -21,23 +21,23 @@ static void gator_buffer_write_packed_int(int cpu, int buftype, unsigned int x) } else if ((x & 0xffffc000) == 0) { int write2 = (write + 2) & mask; buffer[write0] = x | 0x80; - buffer[write1] = (x>>7) & 0x7f; + buffer[write1] = (x >> 7) & 0x7f; per_cpu(gator_buffer_write, cpu)[buftype] = write2; } else if ((x & 0xffe00000) == 0) { int write2 = (write + 2) & mask; int write3 = (write + 3) & mask; buffer[write0] = x | 0x80; - buffer[write1] = (x>>7) | 0x80; - buffer[write2] = (x>>14) & 0x7f; + buffer[write1] = (x >> 7) | 0x80; + buffer[write2] = (x >> 14) & 0x7f; per_cpu(gator_buffer_write, cpu)[buftype] = write3; } else if ((x & 0xf0000000) == 0) { int write2 = (write + 2) & mask; int write3 = (write + 3) & mask; int write4 = (write + 4) & mask; buffer[write0] = x | 0x80; - buffer[write1] = (x>>7) | 0x80; - buffer[write2] = (x>>14) | 0x80; - buffer[write3] = (x>>21) & 0x7f; + buffer[write1] = (x >> 7) | 0x80; + buffer[write2] = (x >> 14) | 0x80; + buffer[write3] = (x >> 21) & 0x7f; per_cpu(gator_buffer_write, cpu)[buftype] = write4; } else { int write2 = (write + 2) & mask; @@ -45,10 +45,10 @@ static void gator_buffer_write_packed_int(int cpu, int buftype, unsigned int x) int write4 = (write + 4) & mask; int write5 = (write + 5) & mask; buffer[write0] = x | 0x80; - buffer[write1] = (x>>7) | 0x80; - buffer[write2] = (x>>14) | 0x80; - buffer[write3] = (x>>21) | 0x80; - buffer[write4] = (x>>28) & 0x0f; + buffer[write1] = (x >> 7) | 0x80; + buffer[write2] = (x >> 14) | 0x80; + buffer[write3] = (x >> 21) | 0x80; + buffer[write4] = (x >> 28) & 0x0f; per_cpu(gator_buffer_write, cpu)[buftype] = write5; } } @@ -67,23 +67,23 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long } else if ((x & 0xffffffffffffc000LL) == 0) { int write2 = (write + 2) & mask; buffer[write0] = x | 0x80; - buffer[write1] = (x>>7) & 0x7f; + buffer[write1] = (x >> 7) & 0x7f; per_cpu(gator_buffer_write, cpu)[buftype] = write2; } else if ((x & 0xffffffffffe00000LL) == 0) { int write2 = (write + 2) & mask; int write3 = (write + 3) & mask; buffer[write0] = x | 0x80; - buffer[write1] = (x>>7) | 0x80; - buffer[write2] = (x>>14) & 0x7f; + buffer[write1] = (x >> 7) | 0x80; + buffer[write2] = (x >> 14) & 0x7f; per_cpu(gator_buffer_write, cpu)[buftype] = write3; } else if ((x & 0xfffffffff0000000LL) == 0) { int write2 = (write + 2) & mask; int write3 = (write + 3) & mask; int write4 = (write + 4) & mask; buffer[write0] = x | 0x80; - buffer[write1] = (x>>7) | 0x80; - buffer[write2] = (x>>14) | 0x80; - buffer[write3] = (x>>21) & 0x7f; + buffer[write1] = (x >> 7) | 0x80; + buffer[write2] = (x >> 14) | 0x80; + buffer[write3] = (x >> 21) & 0x7f; per_cpu(gator_buffer_write, cpu)[buftype] = write4; } else if ((x & 0xfffffff800000000LL) == 0) { int write2 = (write + 2) & mask; @@ -91,10 +91,10 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long int write4 = (write + 4) & mask; int write5 = (write + 5) & mask; buffer[write0] = x | 0x80; - buffer[write1] = (x>>7) | 0x80; - buffer[write2] = (x>>14) | 0x80; - buffer[write3] = (x>>21) | 0x80; - buffer[write4] = (x>>28) & 0x7f; + buffer[write1] = (x >> 7) | 0x80; + buffer[write2] = (x >> 14) | 0x80; + buffer[write3] = (x >> 21) | 0x80; + buffer[write4] = (x >> 28) & 0x7f; per_cpu(gator_buffer_write, cpu)[buftype] = write5; } else if ((x & 0xfffffc0000000000LL) == 0) { int write2 = (write + 2) & mask; @@ -103,11 +103,11 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long int write5 = (write + 5) & mask; int write6 = (write + 6) & mask; buffer[write0] = x | 0x80; - buffer[write1] = (x>>7) | 0x80; - buffer[write2] = (x>>14) | 0x80; - buffer[write3] = (x>>21) | 0x80; - buffer[write4] = (x>>28) | 0x80; - buffer[write5] = (x>>35) & 0x7f; + buffer[write1] = (x >> 7) | 0x80; + buffer[write2] = (x >> 14) | 0x80; + buffer[write3] = (x >> 21) | 0x80; + buffer[write4] = (x >> 28) | 0x80; + buffer[write5] = (x >> 35) & 0x7f; per_cpu(gator_buffer_write, cpu)[buftype] = write6; } else if ((x & 0xfffe000000000000LL) == 0) { int write2 = (write + 2) & mask; @@ -117,12 +117,12 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long int write6 = (write + 6) & mask; int write7 = (write + 7) & mask; buffer[write0] = x | 0x80; - buffer[write1] = (x>>7) | 0x80; - buffer[write2] = (x>>14) | 0x80; - buffer[write3] = (x>>21) | 0x80; - buffer[write4] = (x>>28) | 0x80; - buffer[write5] = (x>>35) | 0x80; - buffer[write6] = (x>>42) & 0x7f; + buffer[write1] = (x >> 7) | 0x80; + buffer[write2] = (x >> 14) | 0x80; + buffer[write3] = (x >> 21) | 0x80; + buffer[write4] = (x >> 28) | 0x80; + buffer[write5] = (x >> 35) | 0x80; + buffer[write6] = (x >> 42) & 0x7f; per_cpu(gator_buffer_write, cpu)[buftype] = write7; } else if ((x & 0xff00000000000000LL) == 0) { int write2 = (write + 2) & mask; @@ -133,13 +133,13 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long int write7 = (write + 7) & mask; int write8 = (write + 8) & mask; buffer[write0] = x | 0x80; - buffer[write1] = (x>>7) | 0x80; - buffer[write2] = (x>>14) | 0x80; - buffer[write3] = (x>>21) | 0x80; - buffer[write4] = (x>>28) | 0x80; - buffer[write5] = (x>>35) | 0x80; - buffer[write6] = (x>>42) | 0x80; - buffer[write7] = (x>>49) & 0x7f; + buffer[write1] = (x >> 7) | 0x80; + buffer[write2] = (x >> 14) | 0x80; + buffer[write3] = (x >> 21) | 0x80; + buffer[write4] = (x >> 28) | 0x80; + buffer[write5] = (x >> 35) | 0x80; + buffer[write6] = (x >> 42) | 0x80; + buffer[write7] = (x >> 49) & 0x7f; per_cpu(gator_buffer_write, cpu)[buftype] = write8; } else if ((x & 0x8000000000000000LL) == 0) { int write2 = (write + 2) & mask; @@ -151,14 +151,14 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long int write8 = (write + 8) & mask; int write9 = (write + 9) & mask; buffer[write0] = x | 0x80; - buffer[write1] = (x>>7) | 0x80; - buffer[write2] = (x>>14) | 0x80; - buffer[write3] = (x>>21) | 0x80; - buffer[write4] = (x>>28) | 0x80; - buffer[write5] = (x>>35) | 0x80; - buffer[write6] = (x>>42) | 0x80; - buffer[write7] = (x>>49) | 0x80; - buffer[write8] = (x>>56) & 0x7f; + buffer[write1] = (x >> 7) | 0x80; + buffer[write2] = (x >> 14) | 0x80; + buffer[write3] = (x >> 21) | 0x80; + buffer[write4] = (x >> 28) | 0x80; + buffer[write5] = (x >> 35) | 0x80; + buffer[write6] = (x >> 42) | 0x80; + buffer[write7] = (x >> 49) | 0x80; + buffer[write8] = (x >> 56) & 0x7f; per_cpu(gator_buffer_write, cpu)[buftype] = write9; } else { int write2 = (write + 2) & mask; @@ -171,15 +171,15 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long int write9 = (write + 9) & mask; int write10 = (write + 10) & mask; buffer[write0] = x | 0x80; - buffer[write1] = (x>>7) | 0x80; - buffer[write2] = (x>>14) | 0x80; - buffer[write3] = (x>>21) | 0x80; - buffer[write4] = (x>>28) | 0x80; - buffer[write5] = (x>>35) | 0x80; - buffer[write6] = (x>>42) | 0x80; - buffer[write7] = (x>>49) | 0x80; - buffer[write8] = (x>>56) | 0x80; - buffer[write9] = (x>>63) & 0x7f; + buffer[write1] = (x >> 7) | 0x80; + buffer[write2] = (x >> 14) | 0x80; + buffer[write3] = (x >> 21) | 0x80; + buffer[write4] = (x >> 28) | 0x80; + buffer[write5] = (x >> 35) | 0x80; + buffer[write6] = (x >> 42) | 0x80; + buffer[write7] = (x >> 49) | 0x80; + buffer[write8] = (x >> 56) | 0x80; + buffer[write9] = (x >> 63) & 0x7f; per_cpu(gator_buffer_write, cpu)[buftype] = write10; } } diff --git a/driver/gator_trace_gpu.c b/driver/gator_trace_gpu.c index 0511d71..9fc488b 100644 --- a/driver/gator_trace_gpu.c +++ b/driver/gator_trace_gpu.c @@ -27,7 +27,6 @@ #define EVENT_TYPE_SUSPEND 3 #define EVENT_TYPE_RESUME 4 - /* Note whether tracepoints have been registered */ static int mali_timeline_trace_registered; static int mali_job_slots_trace_registered; @@ -49,34 +48,33 @@ static int gpu_trace_registered; */ enum { EVENT_CHANNEL_SOFTWARE = 0, - EVENT_CHANNEL_VP0 = 1, - EVENT_CHANNEL_FP0 = 5, - EVENT_CHANNEL_FP1, - EVENT_CHANNEL_FP2, - EVENT_CHANNEL_FP3, - EVENT_CHANNEL_FP4, - EVENT_CHANNEL_FP5, - EVENT_CHANNEL_FP6, - EVENT_CHANNEL_FP7, - EVENT_CHANNEL_GPU = 21 + EVENT_CHANNEL_VP0 = 1, + EVENT_CHANNEL_FP0 = 5, + EVENT_CHANNEL_FP1, + EVENT_CHANNEL_FP2, + EVENT_CHANNEL_FP3, + EVENT_CHANNEL_FP4, + EVENT_CHANNEL_FP5, + EVENT_CHANNEL_FP6, + EVENT_CHANNEL_FP7, + EVENT_CHANNEL_GPU = 21 }; /** * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from the GPU channel */ enum { - EVENT_REASON_SINGLE_GPU_NONE = 0, - EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1, + EVENT_REASON_SINGLE_GPU_NONE = 0, + EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1, }; - 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 + 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: @@ -101,7 +99,7 @@ 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); } } @@ -118,11 +116,10 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne { unsigned int component, state, unit; - 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) - { + switch (component) { case 0: unit = GPU_UNIT_FP; break; @@ -136,9 +133,8 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne unit = GPU_UNIT_NONE; } - if (unit != GPU_UNIT_NONE) - { - switch(state) { + if (unit != GPU_UNIT_NONE) { + switch (state) { case EVENT_TYPE_START: marshal_sched_gpu_start(unit, 0, tgid, (pid != 0 ? pid : tgid)); break; @@ -175,27 +171,27 @@ int gator_trace_gpu_start(void) gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0; #if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx) - if (!GATOR_REGISTER_TRACE(mali_timeline_event)) { - mali_timeline_trace_registered = 1; - } + if (!GATOR_REGISTER_TRACE(mali_timeline_event)) { + mali_timeline_trace_registered = 1; + } #endif #if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx) - if (!GATOR_REGISTER_TRACE(mali_job_slots_event)) { - mali_job_slots_trace_registered = 1; - } + if (!GATOR_REGISTER_TRACE(mali_job_slots_event)) { + mali_job_slots_trace_registered = 1; + } #endif - if (!mali_timeline_trace_registered) { - if (GATOR_REGISTER_TRACE(gpu_activity_start)) { - return 0; - } - if (GATOR_REGISTER_TRACE(gpu_activity_stop)) { - GATOR_UNREGISTER_TRACE(gpu_activity_start); - return 0; - } - gpu_trace_registered = 1; - } + if (!mali_timeline_trace_registered) { + if (GATOR_REGISTER_TRACE(gpu_activity_start)) { + return 0; + } + if (GATOR_REGISTER_TRACE(gpu_activity_stop)) { + GATOR_UNREGISTER_TRACE(gpu_activity_start); + return 0; + } + gpu_trace_registered = 1; + } return 0; } diff --git a/driver/gator_trace_gpu.h b/driver/gator_trace_gpu.h index 894289b..efb47c6 100644 --- a/driver/gator_trace_gpu.h +++ b/driver/gator_trace_gpu.h @@ -28,50 +28,50 @@ */ TRACE_EVENT(gpu_activity_start, - TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p), + TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p), - TP_ARGS(gpu_unit, gpu_core, p), + TP_ARGS(gpu_unit, gpu_core, p), - TP_STRUCT__entry( - __field( int, gpu_unit ) - __field( int, gpu_core ) - __array( char, comm, TASK_COMM_LEN ) - __field( pid_t, pid ) - ), + TP_STRUCT__entry( + __field(int, gpu_unit) + __field(int, gpu_core) + __array(char, comm, TASK_COMM_LEN) + __field(pid_t, pid) + ), - TP_fast_assign( - __entry->gpu_unit = gpu_unit; - __entry->gpu_core = gpu_core; - memcpy(__entry->comm, p->comm, TASK_COMM_LEN); - __entry->pid = p->pid; - ), + TP_fast_assign( + __entry->gpu_unit = gpu_unit; + __entry->gpu_core = gpu_core; + memcpy(__entry->comm, p->comm, TASK_COMM_LEN); + __entry->pid = p->pid; + ), - TP_printk("unit=%d core=%d comm=%s pid=%d", - __entry->gpu_unit, __entry->gpu_core, __entry->comm, __entry->pid) -); + TP_printk("unit=%d core=%d comm=%s pid=%d", + __entry->gpu_unit, __entry->gpu_core, __entry->comm, + __entry->pid) + ); /* * Tracepoint for calling GPU unit stop activity on core */ TRACE_EVENT(gpu_activity_stop, - TP_PROTO(int gpu_unit, int gpu_core), + TP_PROTO(int gpu_unit, int gpu_core), - TP_ARGS(gpu_unit, gpu_core), + TP_ARGS(gpu_unit, gpu_core), - TP_STRUCT__entry( - __field( int, gpu_unit ) - __field( int, gpu_core ) - ), + TP_STRUCT__entry( + __field(int, gpu_unit) + __field(int, gpu_core) + ), - TP_fast_assign( - __entry->gpu_unit = gpu_unit; - __entry->gpu_core = gpu_core; - ), + TP_fast_assign( + __entry->gpu_unit = gpu_unit; + __entry->gpu_core = gpu_core; + ), - TP_printk("unit=%d core=%d", - __entry->gpu_unit, __entry->gpu_core) -); + TP_printk("unit=%d core=%d", __entry->gpu_unit, __entry->gpu_core) + ); #endif /* _TRACE_GPU_H */ diff --git a/driver/gator_trace_power.c b/driver/gator_trace_power.c index b1687e1..79fa13c 100644 --- a/driver/gator_trace_power.c +++ b/driver/gator_trace_power.c @@ -9,8 +9,19 @@ #include <linux/cpufreq.h> #include <trace/events/power.h> + +#if defined(__arm__) + #include <asm/mach-types.h> +#define implements_wfi() (!machine_is_omap3_beagle()) + +#else + +#define implements_wfi() false + +#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 #if GATOR_CPU_FREQ_SUPPORT @@ -61,9 +72,9 @@ GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu)) return; } - if (!machine_is_omap3_beagle()) { + if (implements_wfi()) { if (state == PWR_EVENT_EXIT) { - // transition from wfi to non-wfi + // transition from wfi to non-wfi marshal_idle(cpu, WFI_EXIT); } else { // transition from non-wfi to wfi @@ -149,10 +160,29 @@ void gator_trace_power_init(void) } } #else -static int gator_trace_power_create_files(struct super_block *sb, struct dentry *root) {return 0;} -static void gator_trace_power_online(void) {} -static void gator_trace_power_offline(void) {} -static int gator_trace_power_start(void) {return 0;} -static void gator_trace_power_stop(void) {} -void gator_trace_power_init(void) {} +static int gator_trace_power_create_files(struct super_block *sb, struct dentry *root) +{ + return 0; +} + +static void gator_trace_power_online(void) +{ +} + +static void gator_trace_power_offline(void) +{ +} + +static int gator_trace_power_start(void) +{ + return 0; +} + +static void gator_trace_power_stop(void) +{ +} + +void gator_trace_power_init(void) +{ +} #endif diff --git a/driver/gator_trace_sched.c b/driver/gator_trace_sched.c index 9ddb822..d0336f9 100644 --- a/driver/gator_trace_sched.c +++ b/driver/gator_trace_sched.c @@ -13,7 +13,7 @@ #define SCHED_SWITCH 1 #define SCHED_PROCESS_EXIT 2 -#define TASK_MAP_ENTRIES 1024 /* must be power of 2 */ +#define TASK_MAP_ENTRIES 1024 /* must be power of 2 */ #define TASK_MAX_COLLISIONS 2 static DEFINE_PER_CPU(uint64_t *, taskname_keys); @@ -26,14 +26,14 @@ enum { STATE_WAIT_ON_MUTEX, }; -void emit_pid_name(struct task_struct* task) +void emit_pid_name(struct task_struct *task) { bool found = false; char taskcomm[TASK_COMM_LEN + 3]; unsigned long x, cpu = smp_processor_id(); uint64_t *keys = &(per_cpu(taskname_keys, cpu)[(task->pid & 0xFF) * TASK_MAX_COLLISIONS]); uint64_t value; - + value = gator_chksum_crc32(task->comm); value = (value << 32) | (uint32_t)task->pid; @@ -64,7 +64,6 @@ void emit_pid_name(struct task_struct* task) } } - static void collect_counters(void) { int *buffer, len; @@ -84,7 +83,7 @@ static void collect_counters(void) } } -static void probe_sched_write(int type, struct task_struct* task, struct task_struct* old_task) +static void probe_sched_write(int type, struct task_struct *task, struct task_struct *old_task) { int cookie = 0, state = 0; int cpu = smp_processor_id(); @@ -141,7 +140,14 @@ GATOR_DEFINE_PROBE(sched_process_exit, TP_PROTO(struct task_struct *p)) probe_sched_write(SCHED_PROCESS_EXIT, p, 0); } -static int register_scheduler_tracepoints(void) { +static void do_nothing(void *info) +{ + // Intentionally do nothing + (void)info; +} + +static int register_scheduler_tracepoints(void) +{ // register tracepoints if (GATOR_REGISTER_TRACE(sched_switch)) goto fail_sched_switch; @@ -149,6 +155,10 @@ static int register_scheduler_tracepoints(void) { goto fail_sched_process_exit; 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. + on_each_cpu(do_nothing, NULL, 0); + return 0; // unregister tracepoints on error @@ -166,7 +176,7 @@ 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) = (uint64_t *)kmalloc(size, GFP_KERNEL); if (!per_cpu(taskname_keys, cpu)) return -1; memset(per_cpu(taskname_keys, cpu), 0, size); |