diff options
Diffstat (limited to 'driver')
26 files changed, 274 insertions, 179 deletions
diff --git a/driver/Makefile b/driver/Makefile index d14e2a0..4f97237 100644 --- a/driver/Makefile +++ b/driver/Makefile @@ -77,7 +77,7 @@ clean-files := gator_src_md5.h silent_chk_events.h = : $(obj)/gator_src_md5.h: FORCE @$($(quiet)chk_events.h) - $(Q)cd $(srctree) && cd $(src) ; $(CONFIG_SHELL) -c "echo 'static char *gator_src_md5 = \"'\`ls *.c *.h mali/*.h | grep -Ev '^(gator_src_md5\.c|gator\.mod\.c)$$' | LC_ALL=C sort | xargs cat | md5sum | cut -b 1-32\`'\";'" > $(abspath $@) + $(Q)cd $(srctree) && cd $(src) ; $(CONFIG_SHELL) -c "echo 'static char *gator_src_md5 = \"'\`ls *.c *.h mali/*.h | grep -Ev '^(gator_src_md5\.h|gator\.mod\.c)$$' | LC_ALL=C sort | xargs cat | md5sum | cut -b 1-32\`'\";'" > $(abspath $@) else diff --git a/driver/gator.h b/driver/gator.h index 202eb41..50b0180 100644 --- a/driver/gator.h +++ b/driver/gator.h @@ -77,8 +77,8 @@ int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root, /****************************************************************************** * Tracepoints ******************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) -# error Kernels prior to 2.6.32 not supported +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) +# error Kernels prior to 3.4.0 not supported. DS-5 v5.21 and earlier supported 2.6.32 and later. #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) # define GATOR_DEFINE_PROBE(probe_name, proto) \ static void probe_##probe_name(PARAMS(proto)) @@ -103,10 +103,15 @@ int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root, tracepoint_probe_unregister(gator_tracepoint_##probe_name, probe_##probe_name, NULL) #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) +#define setup_deferrable_timer_on_stack setup_timer +#endif + /****************************************************************************** * Events ******************************************************************************/ struct gator_interface { + const char *const name; /* Complementary function to init */ void (*shutdown)(void); int (*create_files)(struct super_block *sb, struct dentry *root); @@ -120,11 +125,12 @@ struct gator_interface { /* called in process context but may not be running on core 'cpu' */ void (*offline_dispatch)(int cpu, bool migrate); int (*read)(int **buffer, bool sched_switch); - int (*read64)(long long **buffer); + int (*read64)(long long **buffer, bool sched_switch); int (*read_proc)(long long **buffer, struct task_struct *); struct list_head list; }; +u64 gator_get_time(void); int gator_events_install(struct gator_interface *interface); int gator_events_get_key(void); u32 gator_cpuid(void); diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c index 9bd4c8b..7636726 100644 --- a/driver/gator_cookies.c +++ b/driver/gator_cookies.c @@ -7,6 +7,29 @@ * */ +#include <linux/mount.h> + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) + +struct mount { + struct mount *mnt_parent; + struct dentry *mnt_mountpoint; + struct vfsmount mnt; +}; + +static inline struct mount *real_mount(struct vfsmount *mnt) +{ + return container_of(mnt, struct mount, mnt); +} + +#define GET_MNT_ROOT(mount) (mount)->mnt.mnt_root + +#else + +#define GET_MNT_ROOT(mount) (mount)->mnt_root + +#endif + /* must be power of 2 */ #define COOKIEMAP_ENTRIES 1024 /* must be a power of 2 - 512/4 = 128 entries */ @@ -23,6 +46,7 @@ struct cookie_args { }; static DEFINE_PER_CPU(char *, translate_text); +static DEFINE_PER_CPU(char *, scratch); static DEFINE_PER_CPU(uint32_t, cookie_next_key); static DEFINE_PER_CPU(uint64_t *, cookie_keys); static DEFINE_PER_CPU(uint32_t *, cookie_values); @@ -285,7 +309,7 @@ static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, return cookie; /* On 64-bit android app_process can be app_process32 or app_process64 */ - if (strncmp(text, APP_PROCESS, sizeof(APP_PROCESS) - 1) == 0) { + if (strstr(text, APP_PROCESS) != NULL) { if (!translate_app_process(&text, cpu, task, from_wq)) return UNRESOLVED_COOKIE; } @@ -305,6 +329,75 @@ static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, return cookie; } +/* Can't call d_path in interrupt context so create something similar */ +static const char *gator_d_path(const struct path *path, char *buf, int buflen) +{ + struct dentry *dentry = path->dentry; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) + struct mount *mount = real_mount(path->mnt); +#else + struct vfsmount *mount = path->mnt; +#endif + int pos = buflen - 1; + int len; + + buf[pos] = '\0'; + + for (;;) { + if (dentry == NULL) { + pr_err("gator: dentry is null!\n"); + break; + } + if (dentry->d_name.name[0] == '\0') { + pr_err("gator: path is empty string\n"); + break; + } + if (dentry->d_name.name[0] == '/' && dentry->d_name.name[1] == '\0') { + /* Normal operation */ + /* pr_err("gator: path is /\n"); */ + break; + } + + len = strlen(dentry->d_name.name); + if (pos < len) { + pr_err("gator: path is too long\n"); + break; + } + pos -= len; + memcpy(buf + pos, dentry->d_name.name, len); + + if (pos == 0) { + pr_err("gator: no room for slash\n"); + /* Fall back to name only */ + return path->dentry->d_name.name; + } + --pos; + buf[pos] = '/'; + + if (dentry->d_parent == GET_MNT_ROOT(mount)) { + /* pr_err("gator: filesystem is complete, moving to next '%s'\n", buf + pos); */ + dentry = mount->mnt_mountpoint; + mount = mount->mnt_parent; + continue; + } + if (dentry == dentry->d_parent) { + pr_err("gator: parent is self\n"); + break; + } + dentry = dentry->d_parent; + } + + if (pos < 0) { + pr_err("gator: pos is somenow negative\n"); + /* Fall back to name only */ + return path->dentry->d_name.name; + } + + return buf + pos; +} + +#define d_path gator_d_path + static int get_exec_cookie(int cpu, struct task_struct *task) { struct mm_struct *mm = task->mm; @@ -315,7 +408,7 @@ static int get_exec_cookie(int cpu, struct task_struct *task) return NO_COOKIE; if (task && task->mm && task->mm->exe_file) { - text = task->mm->exe_file->f_path.dentry->d_name.name; + text = d_path(&task->mm->exe_file->f_path, per_cpu(scratch, get_physical_cpu()), PAGE_SIZE); return get_cookie(cpu, task, text, false); } @@ -337,7 +430,7 @@ static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsig continue; if (vma->vm_file) { - text = vma->vm_file->f_path.dentry->d_name.name; + text = d_path(&vma->vm_file->f_path, per_cpu(scratch, get_physical_cpu()), PAGE_SIZE); cookie = get_cookie(cpu, task, text, false); *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; } else { @@ -394,6 +487,12 @@ static int cookies_initialize(void) err = -ENOMEM; goto cookie_setup_error; } + + per_cpu(scratch, cpu) = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!per_cpu(scratch, cpu)) { + err = -ENOMEM; + goto cookie_setup_error; + } } /* build CRC32 table */ @@ -414,7 +513,7 @@ static int cookies_initialize(void) gator_crc32_table[i] = crc; } - setup_timer(&app_process_wake_up_timer, app_process_wake_up_handler, 0); + setup_deferrable_timer_on_stack(&app_process_wake_up_timer, app_process_wake_up_handler, 0); cookie_setup_error: return err; @@ -438,6 +537,9 @@ static void cookies_release(void) kfree(per_cpu(translate_text, cpu)); per_cpu(translate_text, cpu) = NULL; + + kfree(per_cpu(scratch, cpu)); + per_cpu(scratch, cpu) = NULL; } del_timer_sync(&app_process_wake_up_timer); diff --git a/driver/gator_events_armv6.c b/driver/gator_events_armv6.c index 1783970..62bd6eb 100644 --- a/driver/gator_events_armv6.c +++ b/driver/gator_events_armv6.c @@ -198,6 +198,7 @@ static int gator_events_armv6_read(int **buffer, bool sched_switch) } static struct gator_interface gator_events_armv6_interface = { + .name = "armv6", .create_files = gator_events_armv6_create_files, .stop = gator_events_armv6_stop, .online = gator_events_armv6_online, diff --git a/driver/gator_events_armv7.c b/driver/gator_events_armv7.c index e1f6a5f..0db857c 100644 --- a/driver/gator_events_armv7.c +++ b/driver/gator_events_armv7.c @@ -263,6 +263,7 @@ static int gator_events_armv7_read(int **buffer, bool sched_switch) } static struct gator_interface gator_events_armv7_interface = { + .name = "armv7", .create_files = gator_events_armv7_create_files, .stop = gator_events_armv7_stop, .online = gator_events_armv7_online, diff --git a/driver/gator_events_block.c b/driver/gator_events_block.c index b3467b1..0bb4085 100644 --- a/driver/gator_events_block.c +++ b/driver/gator_events_block.c @@ -142,6 +142,7 @@ static int gator_events_block_read(int **buffer, bool sched_switch) } static struct gator_interface gator_events_block_interface = { + .name = "block", .create_files = gator_events_block_create_files, .start = gator_events_block_start, .stop = gator_events_block_stop, diff --git a/driver/gator_events_irq.c b/driver/gator_events_irq.c index 81b976a..aa1ebbb 100644 --- a/driver/gator_events_irq.c +++ b/driver/gator_events_irq.c @@ -144,6 +144,7 @@ static int gator_events_irq_read(int **buffer, bool sched_switch) } static struct gator_interface gator_events_irq_interface = { + .name = "irq", .create_files = gator_events_irq_create_files, .online = gator_events_irq_online, .start = gator_events_irq_start, diff --git a/driver/gator_events_l2c-310.c b/driver/gator_events_l2c-310.c index 063a060..de3b383 100644 --- a/driver/gator_events_l2c-310.c +++ b/driver/gator_events_l2c-310.c @@ -121,6 +121,7 @@ static int gator_events_l2c310_read(int **buffer, bool sched_switch) } static struct gator_interface gator_events_l2c310_interface = { + .name = "l2c-310", .create_files = gator_events_l2c310_create_files, .start = gator_events_l2c310_start, .stop = gator_events_l2c310_stop, diff --git a/driver/gator_events_mali_4xx.c b/driver/gator_events_mali_4xx.c index 423b4e0..fb3909a 100644 --- a/driver/gator_events_mali_4xx.c +++ b/driver/gator_events_mali_4xx.c @@ -66,9 +66,7 @@ static unsigned long counter_event[NUMBER_OF_EVENTS]; 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 atomic_t counter_data[NUMBER_OF_EVENTS]; /* An array used to return the data we recorded * as key,value pairs hence the *2 @@ -116,7 +114,7 @@ static inline int is_hw_counter(unsigned int event_id) GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int value)) { if (is_hw_counter(event_id)) - counter_data[event_id] = value; + atomic_add(value, &counter_data[event_id]); } GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surface_id, unsigned int *counters)) @@ -126,7 +124,7 @@ GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surfac /* Copy over the values for those counters which are enabled. */ for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) { if (counter_enabled[i]) - counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]); + atomic_add(counters[i - FIRST_SW_COUNTER], &counter_data[i]); } } @@ -375,22 +373,22 @@ static void mali_counter_initialize(void) if (mali_get_counters) pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", mali_get_counters); else - pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined\n"); + pr_debug("gator: mali _mali_profiling_get_counters symbol not defined\n"); mali_get_l2_counters = symbol_get(_mali_profiling_get_l2_counters); if (mali_get_l2_counters) pr_debug("gator: mali online _mali_profiling_get_l2_counters symbol @ %p\n", mali_get_l2_counters); else - pr_debug("gator WARNING: mali _mali_profiling_get_l2_counters symbol not defined\n"); + pr_debug("gator: mali _mali_profiling_get_l2_counters symbol not defined\n"); if (!mali_get_counters && !mali_get_l2_counters) { - pr_debug("gator: WARNING: no L2 counters available\n"); + pr_err("gator: no L2 counters available\n"); n_l2_cores = 0; } /* Clear counters in the start */ for (i = 0; i < NUMBER_OF_EVENTS; i++) { - counter_data[i] = 0; + atomic_set(&counter_data[i], 0); prev_set[i] = false; } } @@ -477,7 +475,6 @@ static void stop(void) for (cnt = 0; cnt < NUMBER_OF_EVENTS; cnt++) { counter_enabled[cnt] = 0; counter_event[cnt] = 0; - counter_address[cnt] = NULL; } mali_counter_deinitialize(); @@ -489,10 +486,12 @@ static void dump_counters(unsigned int from_counter, unsigned int to_counter, un for (counter_id = from_counter; counter_id <= to_counter; counter_id++) { if (counter_enabled[counter_id]) { - counter_dump[(*len)++] = counter_key[counter_id]; - counter_dump[(*len)++] = counter_data[counter_id]; + unsigned int value; - counter_data[counter_id] = 0; + counter_dump[(*len)++] = counter_key[counter_id]; + value = atomic_read(&counter_data[counter_id]); + atomic_sub(value, &counter_data[counter_id]); + counter_dump[(*len)++] = value; } } } @@ -564,17 +563,19 @@ static int read(int **buffer, bool sched_switch) * 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. + * + * Intentionally use atomic_read as these are absolute counters */ cnt = COUNTER_FREQUENCY; if (counter_enabled[cnt]) { counter_dump[len++] = counter_key[cnt]; - counter_dump[len++] = counter_data[cnt]; + counter_dump[len++] = atomic_read(&counter_data[cnt]); } cnt = COUNTER_VOLTAGE; if (counter_enabled[cnt]) { counter_dump[len++] = counter_key[cnt]; - counter_dump[len++] = counter_data[cnt]; + counter_dump[len++] = atomic_read(&counter_data[cnt]); } } #endif @@ -586,6 +587,7 @@ static int read(int **buffer, bool sched_switch) } static struct gator_interface gator_events_mali_interface = { + .name = "mali_4xx", .create_files = create_files, .start = start, .stop = stop, @@ -595,8 +597,9 @@ static struct gator_interface gator_events_mali_interface = { extern void gator_events_mali_log_dvfs_event(unsigned int frequency_mhz, unsigned int voltage_mv) { #ifdef DVFS_REPORTED_BY_DDK - counter_data[COUNTER_FREQUENCY] = frequency_mhz; - counter_data[COUNTER_VOLTAGE] = voltage_mv; + /* Intentionally use atomic_set as these are absolute counters */ + atomic_set(&counter_data[COUNTER_FREQUENCY], frequency_mhz); + atomic_set(&counter_data[COUNTER_VOLTAGE], voltage_mv); #endif } @@ -612,8 +615,7 @@ int gator_events_mali_init(void) counter_enabled[cnt] = 0; counter_event[cnt] = 0; counter_key[cnt] = gator_events_get_key(); - counter_address[cnt] = NULL; - counter_data[cnt] = 0; + atomic_set(&counter_data[cnt], 0); } trace_registered = 0; diff --git a/driver/gator_events_mali_common.c b/driver/gator_events_mali_common.c index 7741f25..60fece8 100644 --- a/driver/gator_events_mali_common.c +++ b/driver/gator_events_mali_common.c @@ -25,31 +25,31 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even dir = gatorfs_mkdir(sb, root, buf); if (dir == NULL) { - pr_debug("gator: %s: error creating file system for: %s (%s)\n", mali_name, event_name, buf); + pr_err("gator: %s: error creating file system for: %s (%s)\n", mali_name, event_name, buf); return -1; } err = gatorfs_create_ulong(sb, dir, "enabled", &counter->enabled); if (err != 0) { - pr_debug("gator: %s: error calling gatorfs_create_ulong for: %s (%s)\n", mali_name, event_name, buf); + pr_err("gator: %s: error calling gatorfs_create_ulong for: %s (%s)\n", mali_name, event_name, buf); return -1; } err = gatorfs_create_ro_ulong(sb, dir, "key", &counter->key); if (err != 0) { - pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf); + pr_err("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf); return -1; } if (counter->cores != -1) { err = gatorfs_create_ro_ulong(sb, dir, "cores", &counter->cores); if (err != 0) { - pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf); + pr_err("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf); return -1; } } if (event != NULL) { err = gatorfs_create_ulong(sb, dir, "event", event); if (err != 0) { - pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf); + pr_err("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf); return -1; } } diff --git a/driver/gator_events_mali_midgard.c b/driver/gator_events_mali_midgard.c index 3b0963a..5b84975 100644 --- a/driver/gator_events_mali_midgard.c +++ b/driver/gator_events_mali_midgard.c @@ -146,6 +146,10 @@ static unsigned int accumulators_data[NUMBER_OF_ACCUMULATORS]; /* Hold the previous timestamp, used to calculate the sample interval. */ static struct timespec prev_timestamp; +static unsigned long long previous_shader_bitmask; +static unsigned long long previous_tiler_bitmask; +static unsigned long long previous_l2_bitmask; + /** * Returns the timespan (in microseconds) between the two specified timestamps. * @@ -209,10 +213,6 @@ GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long #define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */ #define BIT_AT(value, pos) ((value >> pos) & 1) - static unsigned long long previous_shader_bitmask; - static unsigned long long previous_tiler_bitmask; - static unsigned long long previous_l2_bitmask; - switch (event_id) { case SHADER_PRESENT_LO: { @@ -324,27 +324,27 @@ static int create_files(struct super_block *sb, struct dentry *root) static int register_tracepoints(void) { if (GATOR_REGISTER_TRACE(mali_pm_status)) { - pr_debug("gator: Mali-Midgard: mali_pm_status tracepoint failed to activate\n"); + pr_err("gator: Mali-Midgard: mali_pm_status tracepoint failed to activate\n"); return 0; } if (GATOR_REGISTER_TRACE(mali_page_fault_insert_pages)) { - pr_debug("gator: Mali-Midgard: mali_page_fault_insert_pages tracepoint failed to activate\n"); + pr_err("gator: Mali-Midgard: 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-Midgard: mali_mmu_as_in_use tracepoint failed to activate\n"); + pr_err("gator: Mali-Midgard: mali_mmu_as_in_use tracepoint failed to activate\n"); return 0; } if (GATOR_REGISTER_TRACE(mali_mmu_as_released)) { - pr_debug("gator: Mali-Midgard: mali_mmu_as_released tracepoint failed to activate\n"); + pr_err("gator: Mali-Midgard: mali_mmu_as_released tracepoint failed to activate\n"); return 0; } if (GATOR_REGISTER_TRACE(mali_total_alloc_pages_change)) { - pr_debug("gator: Mali-Midgard: mali_total_alloc_pages_change tracepoint failed to activate\n"); + pr_err("gator: Mali-Midgard: mali_total_alloc_pages_change tracepoint failed to activate\n"); return 0; } @@ -363,6 +363,10 @@ static int start(void) unsigned int cnt; mali_profiling_control_type *mali_control; + previous_shader_bitmask = 0; + previous_tiler_bitmask = 0; + previous_l2_bitmask = 0; + /* 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; @@ -546,6 +550,7 @@ static int read(int **buffer, bool sched_switch) } static struct gator_interface gator_events_mali_midgard_interface = { + .name = "mali_midgard", .create_files = create_files, .start = start, .stop = stop, diff --git a/driver/gator_events_mali_midgard_hw.c b/driver/gator_events_mali_midgard_hw.c index 7e1eee3..db91c42 100644 --- a/driver/gator_events_mali_midgard_hw.c +++ b/driver/gator_events_mali_midgard_hw.c @@ -433,7 +433,8 @@ static unsigned int num_hardware_counters_enabled; static struct mali_counter *counters; /* An array used to return the data we recorded as key,value pairs */ -static int *counter_dump; +static long long *counter_dump; +static uint64_t last_read_time; extern struct mali_counter mali_activity[3]; @@ -517,31 +518,6 @@ static void clean_symbols(void) #endif } -/** - * Determines whether a read should take place - * @param current_time The current time, obtained from getnstimeofday() - * @param prev_time_s The number of seconds at the previous read attempt. - * @param next_read_time_ns The time (in ns) when the next read should be allowed. - * - * 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) -{ - /* If the current ns count rolls over a second, roll the next read time too. */ - 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) - return 0; - - /* Set the next read some fixed time after this one, and update the read timestamp. */ - *next_read_time_ns = current_time->tv_nsec + READ_INTERVAL_NSEC; - - *prev_time_s = current_time->tv_sec; - return 1; -} - static int start(void) { #if MALI_DDK_GATOR_API_VERSION != 3 @@ -552,6 +528,8 @@ static int start(void) #endif int cnt; + last_read_time = 0; + #if MALI_DDK_GATOR_API_VERSION == 3 /* Setup HW counters */ num_hardware_counters_enabled = 0; @@ -620,14 +598,14 @@ static int start(void) /* If we already got a context, fail */ if (kbcontext) { - pr_debug("gator: Mali-Midgard: error context already present\n"); + pr_err("gator: Mali-Midgard: 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-Midgard: error creating kbase context\n"); + pr_err("gator: Mali-Midgard: error creating kbase context\n"); goto out; } @@ -650,7 +628,7 @@ static int start(void) kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 4096, &kernel_dump_buffer_handle); #endif if (!kernel_dump_buffer) { - pr_debug("gator: Mali-Midgard: error trying to allocate va\n"); + pr_err("gator: Mali-Midgard: error trying to allocate va\n"); goto destroy_context; } @@ -665,7 +643,7 @@ static int start(void) /* 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-Midgard: can't setup hardware counters\n"); + pr_err("gator: Mali-Midgard: can't setup hardware counters\n"); goto free_buffer; } pr_debug("gator: Mali-Midgard: hardware counters enabled\n"); @@ -813,68 +791,80 @@ static int read_counter(const int cnt, const int len, const struct mali_counter return 2; } -static int read(int **buffer, bool sched_switch) +static int read(long long **buffer, bool sched_switch) { int cnt; int len = 0; uint32_t success; - struct timespec current_time; - static u32 prev_time_s; - static s32 next_read_time_ns; + uint64_t curr_time; if (!on_primary_core() || sched_switch) return 0; - getnstimeofday(¤t_time); + /* + * Report the HW counters + * Only process hardware counters if at least one of the hardware counters is enabled. + */ + if (num_hardware_counters_enabled <= 0) + return 0; + + curr_time = gator_get_time(); /* * 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 (curr_time - last_read_time < READ_INTERVAL_NSEC) 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) { #if MALI_DDK_GATOR_API_VERSION == 3 - if (!handles) - return -1; + if (!handles) + return -1; - /* Mali symbols can be called safely since a kbcontext is valid */ - if (kbase_gator_instr_hwcnt_dump_complete_symbol(handles, &success)) { + /* Mali symbols can be called safely since a kbcontext is valid */ + if (kbase_gator_instr_hwcnt_dump_complete_symbol(handles, &success)) { #else - if (!kbcontext) - return -1; + 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 symbols can be called safely since a kbcontext is valid */ + if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success)) { #endif - kbase_device_busy = false; + kbase_device_busy = false; + + /* + * If last_read_time is zero, then this result is from a previous + * capture or in error. + */ + if (success && last_read_time > 0) { + /* Backdate these events to when they were requested */ + counter_dump[len++] = 0; + counter_dump[len++] = last_read_time; - if (success) { - /* Cycle through hardware counters and accumulate totals */ - for (cnt = 0; cnt < number_of_hardware_counters; cnt++) { - const struct mali_counter *counter = &counters[cnt]; + /* Cycle through hardware counters and accumulate totals */ + for (cnt = 0; cnt < number_of_hardware_counters; cnt++) { + const struct mali_counter *counter = &counters[cnt]; - if (counter->enabled) - len += read_counter(cnt, len, counter); - } + if (counter->enabled) + len += read_counter(cnt, len, counter); } + + /* Restore the timestamp */ + counter_dump[len++] = 0; + counter_dump[len++] = curr_time; } + } - if (!kbase_device_busy) { - kbase_device_busy = true; + if (!kbase_device_busy) { + kbase_device_busy = true; + last_read_time = curr_time; #if MALI_DDK_GATOR_API_VERSION == 3 - kbase_gator_instr_hwcnt_dump_irq_symbol(handles); + kbase_gator_instr_hwcnt_dump_irq_symbol(handles); #else - kbase_instr_hwcnt_dump_irq_symbol(kbcontext); + kbase_instr_hwcnt_dump_irq_symbol(kbcontext); #endif - } } /* Update the buffer */ @@ -920,7 +910,7 @@ static void shutdown(void) hardware_counter_names = NULL; if (kbase_gator_hwcnt_term_names_symbol != NULL) { kbase_gator_hwcnt_term_names_symbol(); - pr_err("Released symbols\n"); + pr_debug("gator: Released symbols\n"); } SYMBOL_CLEANUP(kbase_gator_hwcnt_term_names); @@ -928,11 +918,12 @@ static void shutdown(void) } static struct gator_interface gator_events_mali_midgard_interface = { + .name = "mali_midgard_hw", .shutdown = shutdown, .create_files = create_files, .start = start, .stop = stop, - .read = read + .read64 = read }; int gator_events_mali_midgard_hw_init(void) @@ -969,7 +960,7 @@ int gator_events_mali_midgard_hw_init(void) #endif counters = kmalloc(sizeof(*counters)*number_of_hardware_counters, GFP_KERNEL); - counter_dump = kmalloc(sizeof(*counter_dump)*number_of_hardware_counters*2, GFP_KERNEL); + counter_dump = kmalloc(sizeof(*counter_dump)*number_of_hardware_counters*2 + 4, GFP_KERNEL); gator_mali_initialise_counters(mali_activity, ARRAY_SIZE(mali_activity)); gator_mali_initialise_counters(counters, number_of_hardware_counters); diff --git a/driver/gator_events_mali_midgard_hw_test.c b/driver/gator_events_mali_midgard_hw_test.c index 87c569c..9fd44bc 100644 --- a/driver/gator_events_mali_midgard_hw_test.c +++ b/driver/gator_events_mali_midgard_hw_test.c @@ -10,46 +10,3 @@ /** * 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 test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int expected_result, s32 expected_next_ns) -{ - struct timespec current_time; - u32 prev_time_s = prev_s; - s32 next_read_time_ns = next_ns; - - 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) { - pr_err("Failed do_read(%u, %u, %u, %d): expected %d\n", s, ns, prev_s, next_ns, expected_result); - return 0; - } - - if (next_read_time_ns != expected_next_ns) { - pr_err("Failed: next_read_ns expected=%d, actual=%d\n", expected_next_ns, next_read_time_ns); - return 0; - } - - return 1; -} - -static void test_all_is_read_scheduled(void) -{ - const int HIGHEST_NS = 999999999; - int n_tests_passed = 0; - - pr_err("gator: running tests on %s\n", __FILE__); - - n_tests_passed += test_is_read_scheduled(0, 0, 0, 0, 1, READ_INTERVAL_NSEC); /* Null time */ - n_tests_passed += test_is_read_scheduled(100, 1000, 0, 0, 1, READ_INTERVAL_NSEC + 1000); /* Initial values */ - - 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); - - pr_err("gator: %d tests passed\n", n_tests_passed); -} diff --git a/driver/gator_events_meminfo.c b/driver/gator_events_meminfo.c index 985b312..42a6947 100644 --- a/driver/gator_events_meminfo.c +++ b/driver/gator_events_meminfo.c @@ -80,7 +80,7 @@ static void notify(void) static unsigned int mem_event; static void wq_sched_handler(struct work_struct *wsptr); -DECLARE_WORK(work, wq_sched_handler); +static DECLARE_WORK(work, wq_sched_handler); static struct timer_list meminfo_wake_up_timer; static void meminfo_wake_up_handler(unsigned long unused_data); @@ -187,7 +187,7 @@ static int gator_events_meminfo_start(void) if (IS_ERR(kthread_run(gator_meminfo_func, NULL, "gator_meminfo"))) goto kthread_run_exit; #else - setup_timer(&meminfo_wake_up_timer, meminfo_wake_up_handler, 0); + setup_deferrable_timer_on_stack(&meminfo_wake_up_timer, meminfo_wake_up_handler, 0); #endif return 0; @@ -313,7 +313,7 @@ static void meminfo_wake_up_handler(unsigned long unused_data) #endif -static int gator_events_meminfo_read(long long **buffer) +static int gator_events_meminfo_read(long long **buffer, bool sched_switch) { #if !USE_THREAD static unsigned int last_mem_event; @@ -446,6 +446,7 @@ static int gator_events_meminfo_read_proc(long long **buffer, struct task_struct } static struct gator_interface gator_events_meminfo_interface = { + .name = "meminfo", .create_files = gator_events_meminfo_create_files, .start = gator_events_meminfo_start, .stop = gator_events_meminfo_stop, diff --git a/driver/gator_events_mmapped.c b/driver/gator_events_mmapped.c index 7b51761..30ca980 100644 --- a/driver/gator_events_mmapped.c +++ b/driver/gator_events_mmapped.c @@ -189,6 +189,7 @@ static int gator_events_mmapped_read(int **buffer, bool sched_switch) } static struct gator_interface gator_events_mmapped_interface = { + .name = "mmapped", .create_files = gator_events_mmapped_create_files, .start = gator_events_mmapped_start, .stop = gator_events_mmapped_stop, diff --git a/driver/gator_events_net.c b/driver/gator_events_net.c index 1e36731..053f719 100644 --- a/driver/gator_events_net.c +++ b/driver/gator_events_net.c @@ -45,7 +45,7 @@ static void get_network_stats(struct work_struct *wsptr) tx_total = tx; } -DECLARE_WORK(wq_get_stats, get_network_stats); +static DECLARE_WORK(wq_get_stats, get_network_stats); static void net_wake_up_handler(unsigned long unused_data) { @@ -98,11 +98,7 @@ static int gator_events_net_start(void) get_network_stats(0); netPrev[NETRX] = rx_total; netPrev[NETTX] = tx_total; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) - setup_timer(&net_wake_up_timer, net_wake_up_handler, 0); -#else setup_deferrable_timer_on_stack(&net_wake_up_timer, net_wake_up_handler, 0); -#endif return 0; } @@ -154,6 +150,7 @@ static int gator_events_net_read(int **buffer, bool sched_switch) } static struct gator_interface gator_events_net_interface = { + .name = "net", .create_files = gator_events_net_create_files, .start = gator_events_net_start, .stop = gator_events_net_stop, diff --git a/driver/gator_events_perf_pmu.c b/driver/gator_events_perf_pmu.c index f6b4f18..d49277d 100644 --- a/driver/gator_events_perf_pmu.c +++ b/driver/gator_events_perf_pmu.c @@ -153,13 +153,13 @@ static void __online_dispatch(int cpu, bool migrate, struct gator_attr *const at event->pevent = perf_event_create_kernel_counter(event->pevent_attr, cpu, 0, handler, 0); #endif if (IS_ERR(event->pevent)) { - pr_debug("gator: unable to online a counter on cpu %d\n", cpu); + pr_err("gator: unable to online a counter on cpu %d\n", cpu); event->pevent = NULL; return; } if (event->pevent->state != PERF_EVENT_STATE_ACTIVE) { - pr_debug("gator: inactive counter on cpu %d\n", cpu); + pr_err("gator: inactive counter on cpu %d\n", cpu); perf_event_release_kernel(event->pevent); event->pevent = NULL; return; @@ -369,6 +369,7 @@ static int gator_events_perf_pmu_read(int **buffer, bool sched_switch) } static struct gator_interface gator_events_perf_pmu_interface = { + .name = "perf_pmu", .create_files = gator_events_perf_pmu_create_files, .start = gator_events_perf_pmu_start, .stop = gator_events_perf_pmu_stop, @@ -463,10 +464,10 @@ static void gator_events_perf_pmu_cci_400_init(const int type) cci_name = "CCI_400"; break; case 1: - cci_name = "CCI_400-r1"; + cci_name = "CCI_400_r1"; break; default: - pr_debug("gator: unrecognized cci-400 revision\n"); + pr_err("gator: unrecognized cci-400 revision\n"); return; } @@ -536,14 +537,19 @@ int gator_events_perf_pmu_init(void) } if (pe->pmu != NULL && type == pe->pmu->type) { - if (strcmp("CCI", pe->pmu->name) == 0 || strcmp("CCI_400", pe->pmu->name) == 0 || strcmp("CCI_400-r1", pe->pmu->name) == 0) { + pr_notice("gator: perf pmu: %s\n", pe->pmu->name); + if (strcmp("CCI", pe->pmu->name) == 0 || strcmp("CCI_400", pe->pmu->name) == 0 || strcmp("CCI_400_r1", pe->pmu->name) == 0) { + pr_notice("gator: Adding CCI-400 counters with type %i\n", type); gator_events_perf_pmu_cci_400_init(type); } else if (strcmp("CCI_500", pe->pmu->name) == 0) { + pr_notice("gator: Adding CCI-500 counters with type %i\n", type); gator_events_perf_pmu_uncore_init("CCI_500", type, CCI_500, false); } else if (strcmp("ccn", pe->pmu->name) == 0) { + pr_notice("gator: Adding CCN counters with type %i\n", type); gator_events_perf_pmu_uncore_init("ARM_CCN_5XX", type, CCN_5XX, true); } else if ((gator_cpu = gator_find_cpu_by_pmu_name(pe->pmu->name)) != NULL) { found_cpu = true; + pr_notice("gator: Adding cpu counters for %s with type %i\n", gator_cpu->pmnc_name, type); gator_events_perf_pmu_cpu_init(gator_cpu, type); } /* Initialize gator_attrs for dynamic PMUs here */ @@ -562,6 +568,7 @@ int gator_events_perf_pmu_init(void) return -1; } } + pr_notice("gator: Adding cpu counters (based on cpuid) for %s\n", gator_cpu->pmnc_name); gator_events_perf_pmu_cpu_init(gator_cpu, PERF_TYPE_RAW); } diff --git a/driver/gator_events_sched.c b/driver/gator_events_sched.c index 463d834..d352415 100644 --- a/driver/gator_events_sched.c +++ b/driver/gator_events_sched.c @@ -97,6 +97,7 @@ static int gator_events_sched_read(int **buffer, bool sched_switch) } static struct gator_interface gator_events_sched_interface = { + .name = "sched", .create_files = gator_events_sched_create_files, .start = gator_events_sched_start, .stop = gator_events_sched_stop, diff --git a/driver/gator_events_scorpion.c b/driver/gator_events_scorpion.c index b51dcd3..efb5e7a 100644 --- a/driver/gator_events_scorpion.c +++ b/driver/gator_events_scorpion.c @@ -635,6 +635,7 @@ static int gator_events_scorpion_read(int **buffer, bool sched_switch) } static struct gator_interface gator_events_scorpion_interface = { + .name = "scorpion", .create_files = gator_events_scorpion_create_files, .stop = gator_events_scorpion_stop, .online = gator_events_scorpion_online, diff --git a/driver/gator_fs.c b/driver/gator_fs.c index d8fb357..205da8b 100644 --- a/driver/gator_fs.c +++ b/driver/gator_fs.c @@ -18,7 +18,7 @@ #define gatorfs_MAGIC 0x24051020 #define TMPBUFSIZE 50 -DEFINE_SPINLOCK(gatorfs_lock); +static DEFINE_SPINLOCK(gatorfs_lock); static struct inode *gatorfs_get_inode(struct super_block *sb, int mode) { diff --git a/driver/gator_hrtimer_gator.c b/driver/gator_hrtimer_gator.c index 36961f8..8b86ede 100644 --- a/driver/gator_hrtimer_gator.c +++ b/driver/gator_hrtimer_gator.c @@ -7,10 +7,10 @@ * */ -void (*callback)(void); -DEFINE_PER_CPU(struct hrtimer, percpu_hrtimer); -DEFINE_PER_CPU(ktime_t, hrtimer_expire); -DEFINE_PER_CPU(int, hrtimer_is_active); +static void (*callback)(void); +static DEFINE_PER_CPU(struct hrtimer, percpu_hrtimer); +static DEFINE_PER_CPU(ktime_t, hrtimer_expire); +static DEFINE_PER_CPU(int, hrtimer_is_active); static ktime_t profiling_interval; static void gator_hrtimer_online(void); static void gator_hrtimer_offline(void); diff --git a/driver/gator_main.c b/driver/gator_main.c index affa1dc..2d55afe 100644 --- a/driver/gator_main.c +++ b/driver/gator_main.c @@ -8,7 +8,7 @@ */ /* This version must match the gator daemon version */ -#define PROTOCOL_VERSION 21 +#define PROTOCOL_VERSION 22 static unsigned long gator_protocol_version = PROTOCOL_VERSION; #include <linux/slab.h> @@ -180,7 +180,6 @@ static DEFINE_PER_CPU(bool, in_scheduler_context); /****************************************************************************** * Prototypes ******************************************************************************/ -static u64 gator_get_time(void); static void gator_emit_perf_time(u64 time); static void gator_op_create_files(struct super_block *sb, struct dentry *root); @@ -378,21 +377,21 @@ static const struct gator_cpu gator_cpus[] = { { .cpuid = CORTEX_A53, .core_name = "Cortex-A53", - .pmnc_name = "ARM_Cortex-A53", + .pmnc_name = "ARMv8_Cortex_A53", .dt_name = "arm,cortex-a53", .pmnc_counters = 6, }, { .cpuid = CORTEX_A57, .core_name = "Cortex-A57", - .pmnc_name = "ARM_Cortex-A57", + .pmnc_name = "ARMv8_Cortex_A57", .dt_name = "arm,cortex-a57", .pmnc_counters = 6, }, { .cpuid = CORTEX_A72, .core_name = "Cortex-A72", - .pmnc_name = "ARM_Cortex-A72", + .pmnc_name = "ARMv8_Cortex_A72", .dt_name = "arm,cortex-a72", .pmnc_counters = 6, }, @@ -551,6 +550,8 @@ static void gator_timer_offline(void *migrate) list_for_each_entry(gi, &gator_events, list) { if (gi->offline) { len = gi->offline(&buffer, migrate); + if (len < 0) + pr_err("gator: offline failed for %s\n", gi->name); marshal_event(len, buffer); } } @@ -639,6 +640,8 @@ static void gator_timer_online(void *migrate) list_for_each_entry(gi, &gator_events, list) { if (gi->online) { len = gi->online(&buffer, migrate); + if (len < 0) + pr_err("gator: online failed for %s\n", gi->name); marshal_event(len, buffer); } } @@ -699,7 +702,7 @@ static int gator_timer_start(unsigned long sample_rate) return 0; } -static u64 gator_get_time(void) +u64 gator_get_time(void) { struct timespec ts; u64 timestamp; @@ -1366,6 +1369,7 @@ static void gator_op_create_files(struct super_block *sb, struct dentry *root) struct dentry *dir; struct gator_interface *gi; int cpu; + int err; /* reinitialize default values */ gator_cpu_cores = 0; @@ -1393,8 +1397,12 @@ static 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) { + err = gi->create_files(sb, dir); + if (err != 0) { + pr_err("gator: create_files failed for %s\n", gi->name); + } + } /* Sched Events */ sched_trace_create_files(sb, dir); @@ -1473,7 +1481,7 @@ static int __init gator_module_init(void) return -1; } - setup_timer(&gator_buffer_wake_up_timer, gator_buffer_wake_up, 0); + setup_deferrable_timer_on_stack(&gator_buffer_wake_up_timer, gator_buffer_wake_up, 0); /* Initialize the list of cpuids */ memset(gator_cpuids, -1, sizeof(gator_cpuids)); diff --git a/driver/gator_marshaling.c b/driver/gator_marshaling.c index f5b8184..cb75a34 100644 --- a/driver/gator_marshaling.c +++ b/driver/gator_marshaling.c @@ -27,6 +27,7 @@ static void marshal_summary(long long timestamp, long long uptime, long long mon { unsigned long flags; int cpu = 0; + char buf[32]; local_irq_save(flags); gator_buffer_write_packed_int(cpu, SUMMARY_BUF, MESSAGE_SUMMARY); @@ -36,6 +37,9 @@ static void marshal_summary(long long timestamp, long long uptime, long long mon gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, monotonic_delta); gator_buffer_write_string(cpu, SUMMARY_BUF, "uname"); gator_buffer_write_string(cpu, SUMMARY_BUF, uname); + gator_buffer_write_string(cpu, SUMMARY_BUF, "PAGESIZE"); + snprintf(buf, sizeof(buf), "%lu", PAGE_SIZE); + gator_buffer_write_string(cpu, SUMMARY_BUF, buf); #if GATOR_IKS_SUPPORT gator_buffer_write_string(cpu, SUMMARY_BUF, "iks"); gator_buffer_write_string(cpu, SUMMARY_BUF, ""); diff --git a/driver/gator_trace_gpu.c b/driver/gator_trace_gpu.c index d9b82ee..b35ccd5 100644 --- a/driver/gator_trace_gpu.c +++ b/driver/gator_trace_gpu.c @@ -132,7 +132,7 @@ static void mali_activity_stop(int core, int key) gator_marshal_activity_switch(core, key, last_activity, last_pid); } -void mali_activity_clear(struct mali_counter mali_activity[], size_t mali_activity_size) +static void mali_activity_clear(struct mali_counter mali_activity[], size_t mali_activity_size) { int activity; int cores; diff --git a/driver/gator_trace_sched.c b/driver/gator_trace_sched.c index ad7c39e..700dd2e 100644 --- a/driver/gator_trace_sched.c +++ b/driver/gator_trace_sched.c @@ -104,13 +104,19 @@ static void collect_counters(u64 time, struct task_struct *task, bool sched_swit list_for_each_entry(gi, &gator_events, list) { if (gi->read) { len = gi->read(&buffer, sched_switch); + if (len < 0) + pr_err("gator: read failed for %s\n", gi->name); marshal_event(len, buffer); } else if (gi->read64) { - len = gi->read64(&buffer64); + len = gi->read64(&buffer64, sched_switch); + if (len < 0) + pr_err("gator: read64 failed for %s\n", gi->name); marshal_event64(len, buffer64); } if (gi->read_proc && task != NULL) { len = gi->read_proc(&buffer64, task); + if (len < 0) + pr_err("gator: read_proc failed for %s\n", gi->name); marshal_event64(len, buffer64); } } diff --git a/driver/mali_midgard.mk b/driver/mali_midgard.mk index b0076c2..bd0ac77 100644 --- a/driver/mali_midgard.mk +++ b/driver/mali_midgard.mk @@ -36,5 +36,6 @@ EXTRA_CFLAGS += -I$(KBASE_DIR)/ \ -I$(DDK_DIR)/include \ -I$(KBASE_DIR)/osk/src/linux/include \ -I$(KBASE_DIR)/platform_dummy \ - -I$(KBASE_DIR)/src + -I$(KBASE_DIR)/src \ + -Idrivers/staging/android \ |