From e31266f78058409d18d48e0afa8339e77322b17f Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Mon, 4 Aug 2014 15:47:44 +0100 Subject: [PATCH] gator: Version 5.19 Signed-off-by: Jon Medhurst --- drivers/gator/Makefile | 15 +- drivers/gator/gator.h | 16 +- drivers/gator/gator_backtrace.c | 2 +- drivers/gator/gator_buffer.c | 6 +- drivers/gator/gator_events_armv7.c | 4 +- drivers/gator/gator_events_block.c | 12 +- drivers/gator/gator_events_mali_4xx.c | 144 ++++-------- drivers/gator/gator_events_mali_common.c | 36 +-- drivers/gator/gator_events_mali_common.h | 20 +- drivers/gator/gator_events_mali_t6xx.c | 5 +- drivers/gator/gator_events_mali_t6xx_hw.c | 183 ++++++++++++--- drivers/gator/gator_events_mmapped.c | 26 +-- drivers/gator/gator_events_perf_pmu.c | 6 +- drivers/gator/gator_events_scorpion.c | 4 +- drivers/gator/gator_events_threads.c | 115 +++++++++ drivers/gator/gator_iks.c | 2 +- drivers/gator/gator_main.c | 126 ++++++++-- drivers/gator/gator_marshaling.c | 101 ++++---- drivers/gator/gator_trace_gpu.c | 178 ++++++++------ drivers/gator/gator_trace_gpu.h | 79 ------- drivers/gator/gator_trace_power.c | 4 +- drivers/gator/gator_trace_sched.c | 85 ++++--- drivers/gator/mali/mali_dd_gator_api.h | 40 ++++ drivers/gator/mali_t6xx.mk | 4 + tools/gator/daemon/Android.mk | 6 +- tools/gator/daemon/Application.mk | 1 + tools/gator/daemon/Buffer.cpp | 36 ++- tools/gator/daemon/Buffer.h | 11 +- tools/gator/daemon/CapturedXML.cpp | 11 +- tools/gator/daemon/CapturedXML.h | 2 +- tools/gator/daemon/Child.cpp | 45 ++-- tools/gator/daemon/Child.h | 2 +- tools/gator/daemon/ConfigurationXML.cpp | 10 +- tools/gator/daemon/Counter.h | 4 + tools/gator/daemon/DriverSource.cpp | 53 ++++- tools/gator/daemon/DriverSource.h | 5 + tools/gator/daemon/EventsXML.cpp | 16 +- tools/gator/daemon/EventsXML.h | 5 +- tools/gator/daemon/ExternalSource.cpp | 177 +++++++++++++- tools/gator/daemon/ExternalSource.h | 11 +- tools/gator/daemon/FSDriver.cpp | 212 +++++++++++++++++ tools/gator/daemon/FSDriver.h | 44 ++++ tools/gator/daemon/Fifo.h | 2 +- tools/gator/daemon/Hwmon.cpp | 16 +- tools/gator/daemon/KMod.cpp | 11 +- tools/gator/daemon/LocalCapture.h | 2 +- tools/gator/daemon/Logging.h | 2 +- tools/gator/daemon/Makefile | 8 +- tools/gator/daemon/Makefile_aarch64 | 9 +- tools/gator/daemon/MaliVideoDriver.cpp | 253 ++++++++++++++++++++ tools/gator/daemon/MaliVideoDriver.h | 50 ++++ tools/gator/daemon/Monitor.cpp | 11 +- tools/gator/daemon/Monitor.h | 1 + tools/gator/daemon/OlySocket.cpp | 77 ++---- tools/gator/daemon/OlySocket.h | 14 +- tools/gator/daemon/PerfDriver.cpp | 92 ++++++-- tools/gator/daemon/PerfDriver.h | 6 +- tools/gator/daemon/PerfGroup.cpp | 28 ++- tools/gator/daemon/PerfGroup.h | 2 + tools/gator/daemon/PerfSource.cpp | 14 +- tools/gator/daemon/Proc.cpp | 106 ++++++--- tools/gator/daemon/Proc.h | 2 +- tools/gator/daemon/Sender.h | 2 +- tools/gator/daemon/SessionData.cpp | 55 ++++- tools/gator/daemon/SessionData.h | 17 +- tools/gator/daemon/SessionXML.cpp | 8 +- tools/gator/daemon/StreamlineSetup.cpp | 2 +- tools/gator/daemon/StreamlineSetup.h | 4 +- tools/gator/daemon/UEvent.cpp | 3 +- tools/gator/daemon/UserSpaceSource.cpp | 14 +- tools/gator/daemon/UserSpaceSource.h | 2 +- tools/gator/daemon/c++.cpp | 40 ++++ tools/gator/daemon/common.mk | 16 +- tools/gator/daemon/defaults.xml | 5 + tools/gator/daemon/escape.c | 2 +- tools/gator/daemon/events-CCI-400.xml | 21 +- tools/gator/daemon/events-CCN-504.xml | 9 - tools/gator/daemon/events-Cortex-A53.xml | 84 ------- tools/gator/daemon/events-Cortex-A57.xml | 84 ------- tools/gator/daemon/events-Filesystem.xml | 11 + tools/gator/daemon/events-L2C-310.xml | 30 +-- tools/gator/daemon/events-Linux.xml | 5 +- tools/gator/daemon/events-Mali-4xx.xml | 126 +++++----- tools/gator/daemon/events-Mali-T6xx.xml | 26 +-- tools/gator/daemon/events-Mali-T6xx_hw.xml | 33 +-- tools/gator/daemon/events-Mali-V500.xml | 29 +++ tools/gator/daemon/main.cpp | 260 ++++++++++++--------- 87 files changed, 2305 insertions(+), 1153 deletions(-) create mode 100644 drivers/gator/gator_events_threads.c delete mode 100644 drivers/gator/gator_trace_gpu.h create mode 100644 drivers/gator/mali/mali_dd_gator_api.h create mode 100644 tools/gator/daemon/Application.mk create mode 100644 tools/gator/daemon/FSDriver.cpp create mode 100644 tools/gator/daemon/FSDriver.h create mode 100644 tools/gator/daemon/MaliVideoDriver.cpp create mode 100644 tools/gator/daemon/MaliVideoDriver.h create mode 100644 tools/gator/daemon/c++.cpp create mode 100644 tools/gator/daemon/events-Filesystem.xml create mode 100644 tools/gator/daemon/events-Mali-V500.xml diff --git a/drivers/gator/Makefile b/drivers/gator/Makefile index 3dc9d059a4b4..2f86823313c6 100644 --- a/drivers/gator/Makefile +++ b/drivers/gator/Makefile @@ -7,13 +7,14 @@ CONFIG_GATOR ?= m obj-$(CONFIG_GATOR) := gator.o gator-y := gator_main.o \ - gator_events_irq.o \ - gator_events_sched.o \ - gator_events_net.o \ gator_events_block.o \ + gator_events_irq.o \ gator_events_meminfo.o \ - gator_events_perf_pmu.o \ gator_events_mmapped.o \ + gator_events_net.o \ + gator_events_perf_pmu.o \ + gator_events_sched.o \ + gator_events_threads.o \ # Convert the old GATOR_WITH_MALI_SUPPORT to the new kernel flags ifneq ($(GATOR_WITH_MALI_SUPPORT),) @@ -48,10 +49,14 @@ ifeq ($(CONFIG_GATOR_WITH_MALI_SUPPORT),y) ccflags-$(CONFIG_GATOR_MALI_T6XX) += -DMALI_SUPPORT=MALI_T6xx 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) +# Should the original or new block_rq_complete API be used? +OLD_BLOCK_RQ_COMPLETE := $(shell grep -A3 block_rq_complete include/trace/events/block.h | grep nr_bytes > /dev/null; echo $$?) +EXTRA_CFLAGS += -DOLD_BLOCK_RQ_COMPLETE=$(OLD_BLOCK_RQ_COMPLETE) + gator-$(CONFIG_ARM) += gator_events_armv6.o \ gator_events_armv7.o \ gator_events_ccn-504.o \ diff --git a/drivers/gator/gator.h b/drivers/gator/gator.h index 586cd9e742fb..5ad0254d86a9 100644 --- a/drivers/gator/gator.h +++ b/drivers/gator/gator.h @@ -42,6 +42,10 @@ #define AARCH64 0xd0f #define OTHER 0xfff +// gpu enums +#define MALI_4xx 1 +#define MALI_T6xx 2 + #define MAXSIZE_CORE_NAME 32 struct gator_cpu { @@ -82,13 +86,21 @@ int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root, register_trace_##probe_name(probe_##probe_name) # define GATOR_UNREGISTER_TRACE(probe_name) \ unregister_trace_##probe_name(probe_##probe_name) -#else +#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) # define GATOR_DEFINE_PROBE(probe_name, proto) \ static void probe_##probe_name(void *data, PARAMS(proto)) # define GATOR_REGISTER_TRACE(probe_name) \ register_trace_##probe_name(probe_##probe_name, NULL) # define GATOR_UNREGISTER_TRACE(probe_name) \ unregister_trace_##probe_name(probe_##probe_name, NULL) +#else +# define GATOR_DEFINE_PROBE(probe_name, proto) \ + extern struct tracepoint *gator_tracepoint_##probe_name; \ + static void probe_##probe_name(void *data, PARAMS(proto)) +# define GATOR_REGISTER_TRACE(probe_name) \ + tracepoint_probe_register(gator_tracepoint_##probe_name, probe_##probe_name, NULL) +# define GATOR_UNREGISTER_TRACE(probe_name) \ + tracepoint_probe_unregister(gator_tracepoint_##probe_name, probe_##probe_name, NULL) #endif /****************************************************************************** @@ -115,6 +127,8 @@ u32 gator_cpuid(void); void gator_backtrace_handler(struct pt_regs *const regs); +void gator_marshal_activity_switch(int core, int key, int activity, int pid); + #if !GATOR_IKS_SUPPORT #define get_physical_cpu() smp_processor_id() diff --git a/drivers/gator/gator_backtrace.c b/drivers/gator/gator_backtrace.c index 9f305cf7242c..e03c1653c5b5 100644 --- a/drivers/gator/gator_backtrace.c +++ b/drivers/gator/gator_backtrace.c @@ -178,7 +178,7 @@ static void kernel_backtrace(int cpu, struct pt_regs *const regs) marshal_backtrace(PC_REG & ~1, NO_COOKIE, 1); #endif } - + static void gator_add_sample(int cpu, struct pt_regs *const regs, u64 time) { bool in_kernel; diff --git a/drivers/gator/gator_buffer.c b/drivers/gator/gator_buffer.c index eba22dfe3bf2..dfbc97d80221 100644 --- a/drivers/gator/gator_buffer.c +++ b/drivers/gator/gator_buffer.c @@ -37,12 +37,12 @@ static void marshal_frame(int cpu, int buftype) 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; + case ACTIVITY_BUF: + frame = FRAME_ACTIVITY; + break; default: frame = -1; break; diff --git a/drivers/gator/gator_events_armv7.c b/drivers/gator/gator_events_armv7.c index 153119b463e6..bd8a9ba24e99 100644 --- a/drivers/gator/gator_events_armv7.c +++ b/drivers/gator/gator_events_armv7.c @@ -27,9 +27,9 @@ // ccnt reg #define CCNT_REG (1 << 31) -#define CCNT 0 +#define CCNT 0 #define CNT0 1 -#define CNTMAX (6+1) +#define CNTMAX (6+1) static const char *pmnc_name; static int pmnc_counters; diff --git a/drivers/gator/gator_events_block.c b/drivers/gator/gator_events_block.c index b2bc414e462e..03eed4fb9ebb 100644 --- a/drivers/gator/gator_events_block.c +++ b/drivers/gator/gator_events_block.c @@ -28,15 +28,25 @@ static ulong block_rq_rd_key; static atomic_t blockCnt[BLOCK_TOTAL]; static int blockGet[BLOCK_TOTAL * 4]; +// Tracepoint changed in 3.15 backported to older kernels. The Makefile tries to autodetect the correct value, but if it fails change the #if below +#if OLD_BLOCK_RQ_COMPLETE GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct request *rq)) +#else +GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct request *rq, unsigned int nr_bytes)) +#endif { - int write, size; + int write; + unsigned int size; if (!rq) return; write = rq->cmd_flags & EVENTWRITE; +#if OLD_BLOCK_RQ_COMPLETE size = rq->resid_len; +#else + size = nr_bytes; +#endif if (!size) return; diff --git a/drivers/gator/gator_events_mali_4xx.c b/drivers/gator/gator_events_mali_4xx.c index 85d47645a9d9..9e1c7064bd73 100644 --- a/drivers/gator/gator_events_mali_4xx.c +++ b/drivers/gator/gator_events_mali_4xx.c @@ -18,17 +18,27 @@ #include "gator_events_mali_4xx.h" /* - * There are (currently) four different variants of the comms between gator and Mali: - * 1 (deprecated): No software counter support - * 2 (deprecated): Tracepoint called for each separate s/w counter value as it appears - * 3 (default): Single tracepoint for all s/w counters in a bundle. - * Interface style 3 is the default if no other is specified. 1 and 2 will be eliminated when - * existing Mali DDKs are upgraded. - * 4. As above, but for the Utgard (Mali-450) driver. - */ +* There have been four different variants of the comms between gator and Mali depending on driver version: +* # | DDK vsn range | Support | Notes +* +* 1 | (obsolete) | No software counter support | Obsolete patches +* 2 | (obsolete) | Tracepoint called for each separate s/w counter value as it appears | Obsolete patches +* 3 | r3p0-04rel0 - r3p2-01rel2 | Single tracepoint for all s/w counters in a bundle. | +* 4 | r3p2-01rel3 - date | As above but with extensions for MP devices (Mali-450) | At least r4p0-00rel1 +*/ #if !defined(GATOR_MALI_INTERFACE_STYLE) -#define GATOR_MALI_INTERFACE_STYLE (3) +#define GATOR_MALI_INTERFACE_STYLE (4) +#endif + +#if GATOR_MALI_INTERFACE_STYLE == 1 +#error GATOR_MALI_INTERFACE_STYLE 1 is obsolete +#elif GATOR_MALI_INTERFACE_STYLE == 2 +#error GATOR_MALI_INTERFACE_STYLE 2 is obsolete +#elif GATOR_MALI_INTERFACE_STYLE >= 3 +// Valid GATOR_MALI_INTERFACE_STYLE +#else +#error Unknown GATOR_MALI_INTERFACE_STYLE option. #endif #if GATOR_MALI_INTERFACE_STYLE < 4 @@ -44,6 +54,8 @@ #error MALI_SUPPORT set to an invalid device code: expecting MALI_4xx #endif +static const char mali_name[] = "Mali-4xx"; + /* gatorfs variables for counter enable state, * the event the counter should count and the * 'key' (a unique id set by gatord and returned @@ -63,6 +75,7 @@ static u32 *counter_address[NUMBER_OF_EVENTS]; */ static unsigned long counter_dump[NUMBER_OF_EVENTS * 2]; static unsigned long counter_prev[NUMBER_OF_EVENTS]; +static bool prev_set[NUMBER_OF_EVENTS]; /* Note whether tracepoints have been registered */ static int trace_registered; @@ -76,18 +89,11 @@ static unsigned int n_vp_cores = MAX_NUM_VP_CORES; static unsigned int n_l2_cores = MAX_NUM_L2_CACHE_CORES; static unsigned int n_fp_cores = MAX_NUM_FP_CORES; -/** - * Calculate the difference and handle the overflow. - */ -static u32 get_difference(u32 start, u32 end) -{ - if (start - end >= 0) { - return start - end; - } - - // Mali counters are unsigned 32 bit values that wrap. - return (4294967295u - end) + start; -} +extern mali_counter mali_activity[2]; +static const char* const mali_activity_names[] = { + "fragment", + "vertex", +}; /** * Returns non-zero if the given counter ID is an activity counter. @@ -112,40 +118,6 @@ static inline int is_hw_counter(unsigned int event_id) typedef void _mali_profiling_get_mali_version_type(struct _mali_profiling_mali_version *values); typedef u32 _mali_profiling_get_l2_counters_type(_mali_profiling_l2_counter_values *values); -#if GATOR_MALI_INTERFACE_STYLE == 2 -/** - * Returns non-zero if the given counter ID is a software counter. - */ -static inline int is_sw_counter(unsigned int event_id) -{ - return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER); -} -#endif - -#if GATOR_MALI_INTERFACE_STYLE == 2 -/* - * 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 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; -} -#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)) @@ -172,16 +144,6 @@ GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int } } -#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); - } -} -#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)) { u32 i; @@ -193,7 +155,6 @@ GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surfac } } } -#endif /* GATOR_MALI_INTERFACE_STYLE >= 3 */ /** * Create a single filesystem entry for a specified event. @@ -254,6 +215,7 @@ static void initialise_version_info(void) symbol_put(_mali_profiling_get_mali_version); } else { printk("gator: mali online _mali_profiling_get_mali_version symbol not found\n"); + printk("gator: check your Mali DDK version versus the GATOR_MALI_INTERFACE_STYLE setting\n"); } } #endif @@ -261,7 +223,6 @@ static void initialise_version_info(void) static int create_files(struct super_block *sb, struct dentry *root) { int event; - const char *mali_name = gator_mali_get_mali_name(); char buf[40]; int core_id; @@ -278,6 +239,14 @@ static int create_files(struct super_block *sb, struct dentry *root) initialise_version_info(); #endif + mali_activity[0].cores = n_fp_cores; + mali_activity[1].cores = n_vp_cores; + for (event = 0; event < ARRAY_SIZE(mali_activity); event++) { + if (gator_mali_create_file_system(mali_name, mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) { + return -1; + } + } + /* Vertex processor counters */ for (core_id = 0; core_id < n_vp_cores; core_id++) { int activity_counter_id = ACTIVITY_VP_0; @@ -413,7 +382,6 @@ static void init_counters(unsigned int from_counter, unsigned int to_counter) static void mali_counter_initialize(void) { int i; - int core_id; mali_profiling_control_type *mali_control; @@ -463,15 +431,10 @@ static void mali_counter_initialize(void) n_l2_cores = 0; } - for (core_id = 0; core_id < n_l2_cores; core_id++) { - int counter_id = COUNTER_L2_0_C0 + (2 * core_id); - counter_prev[counter_id] = 0; - counter_prev[counter_id + 1] = 0; - } - /* Clear counters in the start */ for (i = 0; i < NUMBER_OF_EVENTS; i++) { counter_data[i] = 0; + prev_set[i] = false; } } @@ -528,23 +491,11 @@ static int start(void) return -1; } -#if GATOR_MALI_INTERFACE_STYLE == 1 - /* 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; - } -#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; } -#else -#error Unknown GATOR_MALI_INTERFACE_STYLE option. -#endif trace_registered = 1; @@ -561,17 +512,8 @@ static void stop(void) if (trace_registered) { GATOR_UNREGISTER_TRACE(mali_hw_counter); -#if GATOR_MALI_INTERFACE_STYLE == 1 - /* None. */ -#elif GATOR_MALI_INTERFACE_STYLE == 2 - /* 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); -#else -#error Unknown GATOR_MALI_INTERFACE_STYLE option. -#endif pr_debug("gator: mali timeline tracepoint deactivated\n"); @@ -636,21 +578,23 @@ static int read(int **buffer) per_core = &cache_values.cores[cache_id]; - if (counter_enabled[counter_id_0]) { + if (counter_enabled[counter_id_0] && prev_set[counter_id_0]) { // Calculate and save src0's counter val0 counter_dump[len++] = counter_key[counter_id_0]; - counter_dump[len++] = get_difference(per_core->value0, counter_prev[counter_id_0]); + counter_dump[len++] = per_core->value0 - counter_prev[counter_id_0]; } - if (counter_enabled[counter_id_1]) { + if (counter_enabled[counter_id_1] && prev_set[counter_id_1]) { // Calculate and save src1's counter val1 counter_dump[len++] = counter_key[counter_id_1]; - counter_dump[len++] = get_difference(per_core->value1, counter_prev[counter_id_1]); + counter_dump[len++] = per_core->value1 - counter_prev[counter_id_1]; } // Save the previous values for the counters. counter_prev[counter_id_0] = per_core->value0; + prev_set[counter_id_0] = true; counter_prev[counter_id_1] = per_core->value1; + prev_set[counter_id_1] = true; } } @@ -709,6 +653,8 @@ int gator_events_mali_init(void) pr_debug("gator: mali init\n"); + gator_mali_initialise_counters(mali_activity, ARRAY_SIZE(mali_activity)); + for (cnt = 0; cnt < NUMBER_OF_EVENTS; cnt++) { counter_enabled[cnt] = 0; counter_event[cnt] = 0; diff --git a/drivers/gator/gator_events_mali_common.c b/drivers/gator/gator_events_mali_common.c index dc58dcf0c662..4f2cce4ce67b 100644 --- a/drivers/gator/gator_events_mali_common.c +++ b/drivers/gator/gator_events_mali_common.c @@ -8,26 +8,6 @@ */ #include "gator_events_mali_common.h" -static u32 gator_mali_get_id(void) -{ - return MALI_SUPPORT; -} - -extern const char *gator_mali_get_mali_name(void) -{ - u32 id = gator_mali_get_id(); - - switch (id) { - case MALI_T6xx: - return "Mali-T6xx"; - case MALI_4xx: - return "Mali-4xx"; - 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, unsigned long *event) { int err; @@ -42,24 +22,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: Mali-T6xx: error creating file system for: %s (%s)", event_name, buf); + pr_debug("gator: %s: error creating file system for: %s (%s)", mali_name, 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); + pr_debug("gator: %s: error calling gatorfs_create_ulong for: %s (%s)", mali_name, 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); + pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf); return -1; } + if (counter->cores != -1) { + err = gatorfs_create_ro_ulong(sb, dir, "cores", &counter->cores); + if (err != 0) { + pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf); + return -1; + } + } if (event != NULL) { err = gatorfs_create_ulong(sb, dir, "event", event); if (err != 0) { - pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf); + pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf); return -1; } } @@ -77,5 +64,6 @@ extern void gator_mali_initialise_counters(mali_counter counters[], unsigned int counter->key = gator_events_get_key(); counter->enabled = 0; + counter->cores = -1; } } diff --git a/drivers/gator/gator_events_mali_common.h b/drivers/gator/gator_events_mali_common.h index 41c2a3c13fae..91d871bc915a 100644 --- a/drivers/gator/gator_events_mali_common.h +++ b/drivers/gator/gator_events_mali_common.h @@ -18,10 +18,6 @@ #include #include -/* Device codes for each known GPU */ -#define MALI_4xx (0x0b07) -#define MALI_T6xx (0x0056) - /* Ensure that MALI_SUPPORT has been defined to something. */ #ifndef MALI_SUPPORT #error MALI_SUPPORT not defined! @@ -35,8 +31,12 @@ * 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 */ + // 'key' (a unique id set by gatord and returned by gator.ko) + unsigned long key; + // counter enable state + unsigned long enabled; + // for activity counters, the number of cores, otherwise -1 + unsigned long cores; } mali_counter; /* @@ -53,18 +53,10 @@ extern int _mali_profiling_set_event(unsigned int, int); extern void _mali_profiling_control(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-4xx, Mali-T6xx). - * - * @return The name as a constant string. - */ -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 * associate the key/enable values with this entry point. * - * @param mali_name A name related to the type of GPU, obtained from a call to gator_mali_get_mali_name() * @param event_name The name of the event. * @param sb Linux super block * @param root Directory under which the entry will be created. diff --git a/drivers/gator/gator_events_mali_t6xx.c b/drivers/gator/gator_events_mali_t6xx.c index 76f14eee7676..e56ba84aefb8 100644 --- a/drivers/gator/gator_events_mali_t6xx.c +++ b/drivers/gator/gator_events_mali_t6xx.c @@ -32,6 +32,8 @@ #error MALI_SUPPORT set to an invalid device code: expecting MALI_T6xx #endif +static const char mali_name[] = "Mali-T6xx"; + /* Counters for Mali-T6xx: * * - Timeline events @@ -292,7 +294,6 @@ static int create_files(struct super_block *sb, struct dentry *root) * Create the filesystem for all events */ int counter_index = 0; - const char *mali_name = gator_mali_get_mali_name(); mali_profiling_control_type *mali_control; for (event = FIRST_TIMELINE_EVENT; event < FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS; event++) { @@ -317,7 +318,7 @@ static int create_files(struct super_block *sb, struct dentry *root) } mali_control = symbol_get(_mali_profiling_control); - if (mali_control) { + if (mali_control) { if (gator_mali_create_file_system(mali_name, "Filmstrip_cnt0", sb, root, &counters[FILMSTRIP], &filmstrip_event) != 0) { return -1; } diff --git a/drivers/gator/gator_events_mali_t6xx_hw.c b/drivers/gator/gator_events_mali_t6xx_hw.c index dfbc91ffd765..3a072bb6ac06 100644 --- a/drivers/gator/gator_events_mali_t6xx_hw.c +++ b/drivers/gator/gator_events_mali_t6xx_hw.c @@ -16,7 +16,10 @@ #include /* Mali T6xx DDK includes */ -#ifdef MALI_DIR_MIDGARD +#if defined(MALI_SIMPLE_API) +/* Header with wrapper functions to kbase structures and functions */ +#include "mali/mali_dd_gator_api.h" +#elif defined(MALI_DIR_MIDGARD) /* New DDK Directory structure with kernel/drivers/gpu/arm/midgard*/ #include "mali_linux_trace.h" #include "mali_kbase.h" @@ -28,37 +31,49 @@ #include "kbase/src/linux/mali_kbase_mem_linux.h" #endif -#include "gator_events_mali_common.h" - /* If API version is not specified then assume API version 1. */ #ifndef MALI_DDK_GATOR_API_VERSION #define MALI_DDK_GATOR_API_VERSION 1 #endif -#if (MALI_DDK_GATOR_API_VERSION != 1) && (MALI_DDK_GATOR_API_VERSION != 2) -#error MALI_DDK_GATOR_API_VERSION is invalid (must be 1 for r1/r2 DDK, or 2 for r3 DDK). +#if (MALI_DDK_GATOR_API_VERSION != 1) && (MALI_DDK_GATOR_API_VERSION != 2) && (MALI_DDK_GATOR_API_VERSION != 3) +#error MALI_DDK_GATOR_API_VERSION is invalid (must be 1 for r1/r2 DDK, or 2 for r3 DDK, or 3 for r? DDK). #endif +#include "gator_events_mali_common.h" + /* * Mali-T6xx */ +#if MALI_DDK_GATOR_API_VERSION == 3 +typedef uint32_t kbase_dd_instr_hwcnt_dump_irq_type(struct mali_dd_hwcnt_handles *); +typedef uint32_t kbase_dd_instr_hwcnt_dump_complete_type(struct mali_dd_hwcnt_handles *, uint32_t *); +typedef struct mali_dd_hwcnt_handles* mali_dd_hwcnt_init_type(struct mali_dd_hwcnt_info *); +typedef void mali_dd_hwcnt_clear_type(struct mali_dd_hwcnt_info *, struct mali_dd_hwcnt_handles *); + +static kbase_dd_instr_hwcnt_dump_irq_type *kbase_dd_instr_hwcnt_dump_irq_symbol; +static kbase_dd_instr_hwcnt_dump_complete_type *kbase_dd_instr_hwcnt_dump_complete_symbol; +static mali_dd_hwcnt_init_type *mali_dd_hwcnt_init_symbol; +static mali_dd_hwcnt_clear_type *mali_dd_hwcnt_clear_symbol; + +#else typedef struct kbase_device *kbase_find_device_type(int); -typedef kbase_context *kbase_create_context_type(kbase_device *); -typedef void kbase_destroy_context_type(kbase_context *); +typedef struct kbase_context *kbase_create_context_type(struct kbase_device *); +typedef void kbase_destroy_context_type(struct kbase_context *); #if MALI_DDK_GATOR_API_VERSION == 1 -typedef void *kbase_va_alloc_type(kbase_context *, u32); -typedef void kbase_va_free_type(kbase_context *, void *); +typedef void *kbase_va_alloc_type(struct kbase_context *, u32); +typedef void kbase_va_free_type(struct kbase_context *, void *); #elif MALI_DDK_GATOR_API_VERSION == 2 -typedef void *kbase_va_alloc_type(kbase_context *, u32, kbase_hwc_dma_mapping * handle); -typedef void kbase_va_free_type(kbase_context *, kbase_hwc_dma_mapping * handle); +typedef void *kbase_va_alloc_type(struct kbase_context *, u32, kbase_hwc_dma_mapping * handle); +typedef void kbase_va_free_type(struct kbase_context *, kbase_hwc_dma_mapping * handle); #endif -typedef mali_error kbase_instr_hwcnt_enable_type(kbase_context *, kbase_uk_hwcnt_setup *); -typedef mali_error kbase_instr_hwcnt_disable_type(kbase_context *); -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 *); +typedef mali_error kbase_instr_hwcnt_enable_type(struct kbase_context *, struct kbase_uk_hwcnt_setup *); +typedef mali_error kbase_instr_hwcnt_disable_type(struct kbase_context *); +typedef mali_error kbase_instr_hwcnt_clear_type(struct kbase_context *); +typedef mali_error kbase_instr_hwcnt_dump_irq_type(struct kbase_context *); +typedef mali_bool kbase_instr_hwcnt_dump_complete_type(struct kbase_context *, mali_bool *); static kbase_find_device_type *kbase_find_device_symbol; static kbase_create_context_type *kbase_create_context_symbol; @@ -70,6 +85,7 @@ static kbase_instr_hwcnt_dump_complete_type *kbase_instr_hwcnt_dump_complete_sym 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; +#endif static long shader_present_low = 0; @@ -99,6 +115,8 @@ enum { MMU_BLOCK }; +static const char mali_name[] = "Mali-T6xx"; + /* Counters for Mali-T6xx: * * - HW counters, 4 blocks @@ -381,6 +399,14 @@ static const char *const hardware_counter_names[] = { #define GET_HW_BLOCK(c) (((c) >> 6) & 0x3) #define GET_COUNTER_OFFSET(c) ((c) & 0x3f) +#if MALI_DDK_GATOR_API_VERSION == 3 +/* Opaque handles for kbase_context and kbase_hwc_dma_mapping */ +static struct mali_dd_hwcnt_handles *handles; + +/* Information about hardware counters */ +static struct mali_dd_hwcnt_info *in_out_info; + +#else /* Memory to dump hardware counters into */ static void *kernel_dump_buffer; @@ -390,14 +416,9 @@ kbase_hwc_dma_mapping kernel_dump_buffer_handle; #endif /* kbase context and device */ -static kbase_context *kbcontext = NULL; +static struct kbase_context *kbcontext = NULL; static struct kbase_device *kbdevice = NULL; - -/* - * The following function has no external prototype in older DDK revisions. When the DDK - * is updated then this should be removed. - */ -struct kbase_device *kbase_find_device(int minor); +#endif static volatile bool kbase_device_busy = false; static unsigned int num_hardware_counters_enabled; @@ -412,6 +433,13 @@ static mali_counter counters[NUMBER_OF_HARDWARE_COUNTERS]; */ static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2]; +extern mali_counter mali_activity[3]; +static const char* const mali_activity_names[] = { + "fragment", + "vertex", + "opencl", +}; + #define SYMBOL_GET(FUNCTION, ERROR_COUNT) \ if(FUNCTION ## _symbol) \ { \ @@ -431,8 +459,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,6 +470,12 @@ static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2]; static int init_symbols(void) { int error_count = 0; +#if MALI_DDK_GATOR_API_VERSION == 3 + SYMBOL_GET(kbase_dd_instr_hwcnt_dump_irq, error_count); + SYMBOL_GET(kbase_dd_instr_hwcnt_dump_complete, error_count); + SYMBOL_GET(mali_dd_hwcnt_init, error_count); + SYMBOL_GET(mali_dd_hwcnt_clear, error_count); +#else SYMBOL_GET(kbase_find_device, error_count); SYMBOL_GET(kbase_create_context, error_count); SYMBOL_GET(kbase_va_alloc, error_count); @@ -452,6 +486,7 @@ static int init_symbols(void) SYMBOL_GET(kbase_instr_hwcnt_disable, error_count); SYMBOL_GET(kbase_va_free, error_count); SYMBOL_GET(kbase_destroy_context, error_count); +#endif return error_count; } @@ -461,6 +496,12 @@ static int init_symbols(void) */ static void clean_symbols(void) { +#if MALI_DDK_GATOR_API_VERSION == 3 + SYMBOL_CLEANUP(kbase_dd_instr_hwcnt_dump_irq); + SYMBOL_CLEANUP(kbase_dd_instr_hwcnt_dump_complete); + SYMBOL_CLEANUP(mali_dd_hwcnt_init); + SYMBOL_CLEANUP(mali_dd_hwcnt_clear); +#else SYMBOL_CLEANUP(kbase_find_device); SYMBOL_CLEANUP(kbase_create_context); SYMBOL_CLEANUP(kbase_va_alloc); @@ -471,6 +512,7 @@ static void clean_symbols(void) SYMBOL_CLEANUP(kbase_instr_hwcnt_disable); SYMBOL_CLEANUP(kbase_va_free); SYMBOL_CLEANUP(kbase_destroy_context); +#endif } /** @@ -502,11 +544,13 @@ static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time static int start(void) { - kbase_uk_hwcnt_setup setup; +#if MALI_DDK_GATOR_API_VERSION < 3 + struct kbase_uk_hwcnt_setup setup; + unsigned long long shadersPresent = 0; + u16 bitmask[] = { 0, 0, 0, 0 }; mali_error err; +#endif int cnt; - u16 bitmask[] = { 0, 0, 0, 0 }; - unsigned long long shadersPresent = 0; /* Setup HW counters */ num_hardware_counters_enabled = 0; @@ -515,18 +559,52 @@ static int start(void) pr_debug("Unexpected number of hardware counters defined: expecting 256, got %d\n", NUMBER_OF_HARDWARE_COUNTERS); } +#if MALI_DDK_GATOR_API_VERSION == 3 + /* Declare and initialise mali_dd_hwcnt_info structure */ + in_out_info = kmalloc(sizeof(struct mali_dd_hwcnt_info), GFP_KERNEL); + for (cnt = 0; cnt < 4; cnt++){ + in_out_info->bitmask[cnt] = 0; + } +#endif /* 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; +#if MALI_DDK_GATOR_API_VERSION == 3 + in_out_info->bitmask[block] |= (1 << enable_bit); +#else bitmask[block] |= (1 << enable_bit); +#endif pr_debug("gator: Mali-T6xx: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt); num_hardware_counters_enabled++; } } +#if MALI_DDK_GATOR_API_VERSION == 3 + /* 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; + } + + handles = mali_dd_hwcnt_init_symbol(in_out_info); + + if(handles == NULL) { + goto out; + } + + /* See if we can get the number of shader cores */ + shader_present_low = (unsigned long)in_out_info->shader_present_bitmap; + + kbase_device_busy = false; + } + + return 0; +#else /* Create a kbase context for HW counters */ if (num_hardware_counters_enabled > 0) { if (init_symbols() > 0) { @@ -606,6 +684,7 @@ free_buffer: destroy_context: kbase_destroy_context_symbol(kbcontext); +#endif out: clean_symbols(); @@ -615,7 +694,11 @@ out: static void stop(void) { unsigned int cnt; - kbase_context *temp_kbcontext; +#if MALI_DDK_GATOR_API_VERSION == 3 + struct mali_dd_hwcnt_handles *temp_hand; +#else + struct kbase_context *temp_kbcontext; +#endif pr_debug("gator: Mali-T6xx: stop\n"); @@ -625,6 +708,20 @@ static void stop(void) } /* Destroy the context for HW counters */ +#if MALI_DDK_GATOR_API_VERSION == 3 + if (num_hardware_counters_enabled > 0 && handles != NULL) { + /* + * Set the global variable to NULL before destroying it, because + * other function will check this before using it. + */ + temp_hand = handles; + handles = NULL; + + mali_dd_hwcnt_clear_symbol(in_out_info, temp_hand); + + kfree(in_out_info); + +#else if (num_hardware_counters_enabled > 0 && kbcontext != NULL) { /* * Set the global variable to NULL before destroying it, because @@ -642,6 +739,7 @@ static void stop(void) #endif kbase_destroy_context_symbol(temp_kbcontext); +#endif pr_debug("gator: Mali-T6xx: hardware counters stopped\n"); @@ -654,7 +752,7 @@ static int read(int **buffer) int cnt; int len = 0; u32 value = 0; - mali_bool success; + uint32_t success; struct timespec current_time; static u32 prev_time_s = 0; @@ -686,12 +784,21 @@ static int read(int **buffer) 0x500 /* VITHAR_MEMORY_SYSTEM, Block 3 */ }; +#if MALI_DDK_GATOR_API_VERSION == 3 + if (!handles) { + return -1; + } + + /* Mali symbols can be called safely since a kbcontext is valid */ + if (kbase_dd_instr_hwcnt_dump_complete_symbol(handles, &success) == MALI_TRUE) { +#else 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) { +#endif kbase_device_busy = false; if (success == MALI_TRUE) { @@ -702,7 +809,11 @@ static int read(int **buffer) const int block = GET_HW_BLOCK(cnt); const int counter_offset = GET_COUNTER_OFFSET(cnt); +#if MALI_DDK_GATOR_API_VERSION == 3 + const char* block_base_address = (char*)in_out_info->kernel_dump_buffer + vithar_blocks[block]; +#else const char* block_base_address = (char*)kernel_dump_buffer + vithar_blocks[block]; +#endif /* If counter belongs to shader block need to take into account all cores */ if (block == SHADER_BLOCK) { @@ -741,7 +852,11 @@ static int read(int **buffer) if (!kbase_device_busy) { kbase_device_busy = true; +#if MALI_DDK_GATOR_API_VERSION == 3 + kbase_dd_instr_hwcnt_dump_irq_symbol(handles); +#else kbase_instr_hwcnt_dump_irq_symbol(kbcontext); +#endif } } @@ -760,7 +875,12 @@ static int create_files(struct super_block *sb, struct dentry *root) * Create the filesystem for all events */ int counter_index = 0; - const char *mali_name = gator_mali_get_mali_name(); + + for (event = 0; event < ARRAY_SIZE(mali_activity); event++) { + if (gator_mali_create_file_system(mali_name, mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) { + return -1; + } + } 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], NULL) != 0) @@ -786,6 +906,7 @@ int gator_events_mali_t6xx_hw_init(void) test_all_is_read_scheduled(); #endif + gator_mali_initialise_counters(mali_activity, ARRAY_SIZE(mali_activity)); gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS); return gator_events_install(&gator_events_mali_t6xx_interface); diff --git a/drivers/gator/gator_events_mmapped.c b/drivers/gator/gator_events_mmapped.c index 3b248ec24e6e..5bc01c42c3a2 100644 --- a/drivers/gator/gator_events_mmapped.c +++ b/drivers/gator/gator_events_mmapped.c @@ -8,21 +8,25 @@ * published by the Free Software Foundation. * * Similar entries to those below must be present in the events.xml file. - * To add them to the events.xml, create an events-mmap.xml with the + * To add them to the events.xml, create an events-mmap.xml with the * following contents and rebuild gatord: * - * - * - * - * - * + * + * + * + * * * - * When adding custom events, be sure do the following + * When adding custom events, be sure to do the following: * - add any needed .c files to the gator driver Makefile * - call gator_events_install in the events init function * - add the init function to GATOR_EVENTS_LIST in gator_main.c * - add a new events-*.xml file to the gator daemon and rebuild + * + * Troubleshooting: + * - verify the new events are part of events.xml, which is created when building the daemon + * - verify the new events exist at /dev/gator/events/ once gatord is launched + * - verify the counter name in the XML matches the name at /dev/gator/events */ #include @@ -37,7 +41,6 @@ static int mmapped_global_enabled; static struct { unsigned long enabled; - unsigned long event; unsigned long key; } mmapped_counters[MMAPPED_COUNTERS_NUM]; @@ -47,7 +50,7 @@ static s64 prev_time; /* Adds mmapped_cntX directories and enabled, event, and key files to /dev/gator/events */ static int gator_events_mmapped_create_files(struct super_block *sb, - struct dentry *root) + struct dentry *root) { int i; @@ -61,8 +64,6 @@ static int gator_events_mmapped_create_files(struct super_block *sb, return -1; gatorfs_create_ulong(sb, dir, "enabled", &mmapped_counters[i].enabled); - gatorfs_create_ulong(sb, dir, "event", - &mmapped_counters[i].event); gatorfs_create_ro_ulong(sb, dir, "key", &mmapped_counters[i].key); } @@ -177,8 +178,7 @@ static int gator_events_mmapped_read(int **buffer) if (mmapped_counters[i].enabled) { mmapped_buffer[len++] = mmapped_counters[i].key; mmapped_buffer[len++] = - mmapped_simulate(mmapped_counters[i].event, - delta_in_us); + mmapped_simulate(i, delta_in_us); } } diff --git a/drivers/gator/gator_events_perf_pmu.c b/drivers/gator/gator_events_perf_pmu.c index 8b2d67a058b3..06bbad5b10c3 100644 --- a/drivers/gator/gator_events_perf_pmu.c +++ b/drivers/gator/gator_events_perf_pmu.c @@ -470,10 +470,10 @@ static void gator_events_perf_pmu_cci_init(const int type) switch (probe_cci_revision()) { case 0: - cci_name = "cci-400"; + 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"); @@ -549,7 +549,7 @@ 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) { + if (strcmp("CCI", pe->pmu->name) == 0 || strcmp("CCI_400", pe->pmu->name) == 0 || strcmp("CCI_400-r1", pe->pmu->name) == 0) { gator_events_perf_pmu_cci_init(type); } else if ((gator_cpu = gator_find_cpu_by_pmu_name(pe->pmu->name)) != NULL) { found_cpu = true; diff --git a/drivers/gator/gator_events_scorpion.c b/drivers/gator/gator_events_scorpion.c index 8ca251af0e26..2e5be8d50e9d 100644 --- a/drivers/gator/gator_events_scorpion.c +++ b/drivers/gator/gator_events_scorpion.c @@ -26,9 +26,9 @@ static int pmnc_counters; // ccnt reg #define CCNT_REG (1 << 31) -#define CCNT 0 +#define CCNT 0 #define CNT0 1 -#define CNTMAX (4+1) +#define CNTMAX (4+1) static unsigned long pmnc_enabled[CNTMAX]; static unsigned long pmnc_event[CNTMAX]; diff --git a/drivers/gator/gator_events_threads.c b/drivers/gator/gator_events_threads.c new file mode 100644 index 000000000000..9de85862fe6c --- /dev/null +++ b/drivers/gator/gator_events_threads.c @@ -0,0 +1,115 @@ +/* + * Sample activity provider + * + * Copyright (C) ARM Limited 2014. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * See gator_events_mmapped.c for additional directions and + * troubleshooting. + * + * For this sample to work these entries must be present in the + * events.xml file. So create an events-threads.xml in the gator + * daemon source directory with the following contents and rebuild + * gatord: + * + * + * + * + */ + +#include + +#include "gator.h" + +static ulong threads_enabled; +static ulong threads_key; +static ulong threads_cores; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) +GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next)) +#else +GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_struct *next)) +#endif +{ + int cpu = get_physical_cpu(); + int pid = next->pid; + if (pid == 0) { + // idle + gator_marshal_activity_switch(cpu, threads_key, 0, 0); + } else if (pid & 1) { + // odd + gator_marshal_activity_switch(cpu, threads_key, 1, pid); + } else { + // even + //gator_marshal_activity_switch(cpu, threads_key, 2, current->pid); + // Multiple activities are not yet supported so emit idle + gator_marshal_activity_switch(cpu, threads_key, 0, 0); + } +} + +// Adds Linux_threads directory and enabled, key, and cores files to /dev/gator/events +static int gator_events_threads_create_files(struct super_block *sb, struct dentry *root) +{ + struct dentry *dir; + + dir = gatorfs_mkdir(sb, root, "Linux_threads"); + if (!dir) { + return -1; + } + gatorfs_create_ulong(sb, dir, "enabled", &threads_enabled); + gatorfs_create_ro_ulong(sb, dir, "key", &threads_key); + // Number of cores associated with this activity + gatorfs_create_ro_ulong(sb, dir, "cores", &threads_cores); + + return 0; +} + +static int gator_events_threads_start(void) +{ + int cpu; + + if (threads_enabled) { + preempt_disable(); + for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { + gator_marshal_activity_switch(cpu, threads_key, 0, 0); + } + preempt_enable(); + + if (GATOR_REGISTER_TRACE(sched_switch)) { + goto fail_sched_switch; + } + } + + return 0; + +fail_sched_switch: + return -1; +} + +static void gator_events_threads_stop(void) +{ + if (threads_enabled) { + GATOR_UNREGISTER_TRACE(sched_switch); + } + + threads_enabled = 0; +} + +static struct gator_interface gator_events_threads_interface = { + .create_files = gator_events_threads_create_files, + .start = gator_events_threads_start, + .stop = gator_events_threads_stop, +}; + +// Must not be static. Ensure that this init function is added to GATOR_EVENTS_LIST in gator_main.c +int __init gator_events_threads_init(void) +{ + threads_enabled = 0; + threads_key = gator_events_get_key(); + threads_cores = nr_cpu_ids; + + return gator_events_install(&gator_events_threads_interface); +} diff --git a/drivers/gator/gator_iks.c b/drivers/gator/gator_iks.c index e90dfcce9381..9180b874457a 100644 --- a/drivers/gator/gator_iks.c +++ b/drivers/gator/gator_iks.c @@ -150,7 +150,7 @@ static void gator_send_iks_core_names(void) preempt_disable(); for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { if (mpidr_cpus[cpu] != NULL) { - gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid, mpidr_cpus[cpu]); + gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid); } } preempt_enable(); diff --git a/drivers/gator/gator_main.c b/drivers/gator/gator_main.c index e67f7c5cc61d..0d867f22364f 100644 --- a/drivers/gator/gator_main.c +++ b/drivers/gator/gator_main.c @@ -8,7 +8,7 @@ */ // This version must match the gator daemon version -#define PROTOCOL_VERSION 18 +#define PROTOCOL_VERSION 19 static unsigned long gator_protocol_version = PROTOCOL_VERSION; #include @@ -71,8 +71,8 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION; #define BLOCK_COUNTER_BUFFER_SIZE (128*1024) #define ANNOTATE_BUFFER_SIZE (128*1024) // annotate counters have the core as part of the data and the core value in the frame header may be discarded #define 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 ACTIVITY_BUFFER_SIZE (128*1024) #define NO_COOKIE 0U #define UNRESOLVED_COOKIE ~0U @@ -84,8 +84,8 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION; #define FRAME_BLOCK_COUNTER 5 #define FRAME_ANNOTATE 6 #define FRAME_SCHED_TRACE 7 -#define FRAME_GPU_TRACE 8 #define FRAME_IDLE 9 +#define FRAME_ACTIVITY 13 #define MESSAGE_END_BACKTRACE 1 @@ -94,14 +94,9 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION; #define MESSAGE_THREAD_NAME 2 #define MESSAGE_LINK 4 -// GPU Trace Frame Messages -#define MESSAGE_GPU_START 1 -#define MESSAGE_GPU_STOP 2 - // Scheduler Trace Frame Messages #define MESSAGE_SCHED_SWITCH 1 #define MESSAGE_SCHED_EXIT 2 -#define MESSAGE_SCHED_START 3 // Idle Frame Messages #define MESSAGE_IDLE_ENTER 1 @@ -111,6 +106,10 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION; #define MESSAGE_SUMMARY 1 #define MESSAGE_CORE_NAME 3 +// Activity Frame Messages +#define MESSAGE_SWITCH 2 +#define MESSAGE_EXIT 3 + #define MAXSIZE_PACK32 5 #define MAXSIZE_PACK64 10 @@ -132,8 +131,8 @@ enum { BLOCK_COUNTER_BUF, ANNOTATE_BUF, SCHED_TRACE_BUF, - GPU_TRACE_BUF, IDLE_BUF, + ACTIVITY_BUF, NUM_GATOR_BUFS }; @@ -175,6 +174,7 @@ static DEFINE_PER_CPU(u64, last_timestamp); static bool printed_monotonic_warning; +static u32 gator_cpuids[NR_CPUS]; static bool sent_core_name[NR_CPUS]; static DEFINE_PER_CPU(bool, in_scheduler_context); @@ -226,6 +226,7 @@ static DEFINE_PER_CPU(u64, gator_buffer_commit_time); GATOR_EVENT(gator_events_perf_pmu_init) \ GATOR_EVENT(gator_events_sched_init) \ GATOR_EVENT(gator_events_scorpion_init) \ + GATOR_EVENT(gator_events_threads_init) \ #define GATOR_EVENT(EVENT_INIT) __weak int EVENT_INIT(void); GATOR_EVENTS_LIST @@ -570,25 +571,37 @@ static void gator_timer_stop(void) } } -#if defined(__arm__) || defined(__aarch64__) -static void gator_send_core_name(int cpu, const u32 cpuid, const struct gator_cpu *const gator_cpu) +static void gator_send_core_name(const int cpu, const u32 cpuid) { - const char *core_name = NULL; - char core_name_buf[32]; +#if defined(__arm__) || defined(__aarch64__) + if (!sent_core_name[cpu] || (cpuid != gator_cpuids[cpu])) { + const struct gator_cpu *const gator_cpu = gator_find_cpu_by_cpuid(cpuid); + const char *core_name = NULL; + char core_name_buf[32]; - if (!sent_core_name[cpu]) { + // Save off this cpuid + gator_cpuids[cpu] = cpuid; if (gator_cpu != NULL) { core_name = gator_cpu->core_name; } else { - snprintf(core_name_buf, sizeof(core_name_buf), "Unknown (0x%.3x)", cpuid); + if (cpuid == -1) { + snprintf(core_name_buf, sizeof(core_name_buf), "Unknown"); + } else { + snprintf(core_name_buf, sizeof(core_name_buf), "Unknown (0x%.3x)", cpuid); + } core_name = core_name_buf; } marshal_core_name(cpu, cpuid, core_name); sent_core_name[cpu] = true; } -} #endif +} + +static void gator_read_cpuid(void * arg) +{ + gator_cpuids[get_physical_cpu()] = gator_cpuid(); +} // This function runs in interrupt context and on the appropriate core static void gator_timer_online(void *migrate) @@ -598,6 +611,9 @@ static void gator_timer_online(void *migrate) int *buffer; u64 time; + // Send what is currently running on this core + marshal_sched_trace_switch(current->pid, 0); + gator_trace_power_online(); // online any events and output counters @@ -617,12 +633,7 @@ static void gator_timer_online(void *migrate) gator_hrtimer_online(); } -#if defined(__arm__) || defined(__aarch64__) - if (!sent_core_name[cpu]) { - const u32 cpuid = gator_cpuid(); - gator_send_core_name(cpu, cpuid, gator_find_cpu_by_cpuid(cpuid)); - } -#endif + gator_send_core_name(cpu, gator_cpuid()); } // This function runs in interrupt context and may be running on a core other than core 'cpu' @@ -658,6 +669,13 @@ static int gator_timer_start(unsigned long sample_rate) if (gator_hrtimer_init(sample_rate, gator_timer_interrupt) == -1) return -1; + // Send off the previously saved cpuids + for_each_present_cpu(cpu) { + preempt_disable(); + gator_send_core_name(cpu, gator_cpuids[cpu]); + preempt_enable(); + } + gator_send_iks_core_names(); for_each_online_cpu(cpu) { gator_timer_online_dispatch(lcpu_to_pcpu(cpu), false); @@ -1009,12 +1027,12 @@ static int gator_op_setup(void) gator_buffer_size[SCHED_TRACE_BUF] = SCHED_TRACE_BUFFER_SIZE; gator_buffer_mask[SCHED_TRACE_BUF] = SCHED_TRACE_BUFFER_SIZE - 1; - gator_buffer_size[GPU_TRACE_BUF] = GPU_TRACE_BUFFER_SIZE; - gator_buffer_mask[GPU_TRACE_BUF] = GPU_TRACE_BUFFER_SIZE - 1; - gator_buffer_size[IDLE_BUF] = IDLE_BUFFER_SIZE; gator_buffer_mask[IDLE_BUF] = IDLE_BUFFER_SIZE - 1; + gator_buffer_size[ACTIVITY_BUF] = ACTIVITY_BUFFER_SIZE; + gator_buffer_mask[ACTIVITY_BUF] = ACTIVITY_BUFFER_SIZE - 1; + // Initialize percpu per buffer variables for (i = 0; i < NUM_GATOR_BUFS; i++) { // Verify buffers are a power of 2 @@ -1349,8 +1367,62 @@ static void gator_op_create_files(struct super_block *sb, struct dentry *root) /****************************************************************************** * Module ******************************************************************************/ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) + +#define GATOR_TRACEPOINTS \ + GATOR_HANDLE_TRACEPOINT(block_rq_complete); \ + GATOR_HANDLE_TRACEPOINT(cpu_frequency); \ + GATOR_HANDLE_TRACEPOINT(cpu_idle); \ + GATOR_HANDLE_TRACEPOINT(cpu_migrate_begin); \ + GATOR_HANDLE_TRACEPOINT(cpu_migrate_current); \ + GATOR_HANDLE_TRACEPOINT(cpu_migrate_finish); \ + GATOR_HANDLE_TRACEPOINT(irq_handler_exit); \ + GATOR_HANDLE_TRACEPOINT(mali_hw_counter); \ + GATOR_HANDLE_TRACEPOINT(mali_job_slots_event); \ + GATOR_HANDLE_TRACEPOINT(mali_mmu_as_in_use); \ + GATOR_HANDLE_TRACEPOINT(mali_mmu_as_released); \ + GATOR_HANDLE_TRACEPOINT(mali_page_fault_insert_pages); \ + GATOR_HANDLE_TRACEPOINT(mali_pm_status); \ + GATOR_HANDLE_TRACEPOINT(mali_sw_counter); \ + GATOR_HANDLE_TRACEPOINT(mali_sw_counters); \ + GATOR_HANDLE_TRACEPOINT(mali_timeline_event); \ + GATOR_HANDLE_TRACEPOINT(mali_total_alloc_pages_change); \ + GATOR_HANDLE_TRACEPOINT(mm_page_alloc); \ + GATOR_HANDLE_TRACEPOINT(mm_page_free); \ + GATOR_HANDLE_TRACEPOINT(mm_page_free_batched); \ + GATOR_HANDLE_TRACEPOINT(sched_process_exec); \ + GATOR_HANDLE_TRACEPOINT(sched_process_fork); \ + GATOR_HANDLE_TRACEPOINT(sched_process_free); \ + GATOR_HANDLE_TRACEPOINT(sched_switch); \ + GATOR_HANDLE_TRACEPOINT(softirq_exit); \ + +#define GATOR_HANDLE_TRACEPOINT(probe_name) \ + struct tracepoint *gator_tracepoint_##probe_name +GATOR_TRACEPOINTS; +#undef GATOR_HANDLE_TRACEPOINT + +static void gator_fct(struct tracepoint *tp, void *priv) +{ +#define GATOR_HANDLE_TRACEPOINT(probe_name) \ + if (strcmp(tp->name, #probe_name) == 0) { \ + gator_tracepoint_##probe_name = tp; \ + return; \ + } +GATOR_TRACEPOINTS; +#undef GATOR_HANDLE_TRACEPOINT +} + +#else + +#define for_each_kernel_tracepoint(fct, priv) + +#endif + static int __init gator_module_init(void) { + for_each_kernel_tracepoint(gator_fct, NULL); + if (gatorfs_register()) { return -1; } @@ -1362,6 +1434,10 @@ static int __init gator_module_init(void) setup_timer(&gator_buffer_wake_up_timer, gator_buffer_wake_up, 0); + // Initialize the list of cpuids + memset(gator_cpuids, -1, sizeof(gator_cpuids)); + on_each_cpu(gator_read_cpuid, NULL, 1); + return 0; } diff --git a/drivers/gator/gator_marshaling.c b/drivers/gator/gator_marshaling.c index fd413ad1331c..97b4ae6f9d4d 100644 --- a/drivers/gator/gator_marshaling.c +++ b/drivers/gator/gator_marshaling.c @@ -231,75 +231,28 @@ static void marshal_event_single(int core, int key, int value) // Check and commit; commit is set to occur once buffer is 3/4 full buffer_check(cpu, COUNTER_BUF, time); } -#endif -static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid) +static void marshal_event_single64(int core, int key, long long value) { - unsigned long cpu = get_physical_cpu(), flags; - u64 time; - - if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF]) - return; - - local_irq_save(flags); - time = gator_get_time(); - 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, time); - gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit); - gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core); - 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, time); -} - -static void marshal_sched_gpu_stop(int unit, int core) -{ - unsigned long cpu = get_physical_cpu(), flags; - u64 time; - - if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF]) - return; - - local_irq_save(flags); - time = gator_get_time(); - 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, 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, time); -} - -static void marshal_sched_trace_start(int tgid, int pid, int cookie) -{ - unsigned long cpu = get_physical_cpu(), flags; + unsigned long flags, cpu; u64 time; - if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF]) - return; - local_irq_save(flags); + cpu = get_physical_cpu(); time = gator_get_time(); - if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) { - gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_START); - gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, time); - gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid); - gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid); - gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie); + if (buffer_check_space(cpu, COUNTER_BUF, 2 * MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) { + gator_buffer_write_packed_int64(cpu, COUNTER_BUF, time); + gator_buffer_write_packed_int(cpu, COUNTER_BUF, core); + gator_buffer_write_packed_int(cpu, COUNTER_BUF, key); + gator_buffer_write_packed_int64(cpu, COUNTER_BUF, value); } local_irq_restore(flags); // Check and commit; commit is set to occur once buffer is 3/4 full - buffer_check(cpu, SCHED_TRACE_BUF, time); + buffer_check(cpu, COUNTER_BUF, time); } +#endif -static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state) +static void marshal_sched_trace_switch(int pid, int state) { unsigned long cpu = get_physical_cpu(), flags; u64 time; @@ -312,9 +265,7 @@ static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state) 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, time); - gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid); gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid); - gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie); gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state); } local_irq_restore(flags); @@ -379,3 +330,33 @@ static void marshal_core_name(const int core, const int cpuid, const char *name) gator_commit_buffer(cpu, SUMMARY_BUF, gator_get_time()); } #endif + +static void marshal_activity_switch(int core, int key, int activity, int pid, int state) +{ + unsigned long cpu = get_physical_cpu(), flags; + u64 time; + + if (!per_cpu(gator_buffer, cpu)[ACTIVITY_BUF]) + return; + + local_irq_save(flags); + time = gator_get_time(); + if (buffer_check_space(cpu, ACTIVITY_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) { + gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, MESSAGE_SWITCH); + gator_buffer_write_packed_int64(cpu, ACTIVITY_BUF, time); + gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, core); + gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, key); + gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, activity); + gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, pid); + gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, state); + } + local_irq_restore(flags); + // Check and commit; commit is set to occur once buffer is 3/4 full + buffer_check(cpu, ACTIVITY_BUF, time); +} + +void gator_marshal_activity_switch(int core, int key, int activity, int pid) +{ + // state is reserved for cpu use only + marshal_activity_switch(core, key, activity, pid, 0); +} diff --git a/drivers/gator/gator_trace_gpu.c b/drivers/gator/gator_trace_gpu.c index 6332098e5958..a8b9e7d61ece 100644 --- a/drivers/gator/gator_trace_gpu.c +++ b/drivers/gator/gator_trace_gpu.c @@ -23,8 +23,6 @@ #endif #endif -#include "gator_trace_gpu.h" - /* * Taken from MALI_PROFILING_EVENT_TYPE_* items in Mali DDK. */ @@ -37,7 +35,6 @@ /* Note whether tracepoints have been registered */ static int mali_timeline_trace_registered; static int mali_job_slots_trace_registered; -static int gpu_trace_registered; enum { GPU_UNIT_NONE = 0, @@ -47,19 +44,19 @@ enum { NUMBER_OF_GPU_UNITS }; -#define MALI_4xx (0x0b07) -#define MALI_T6xx (0x0056) +#if defined(MALI_SUPPORT) -struct mali_gpu_job { +struct mali_activity { + int core; + int key; int count; - int last_tgid; + int last_activity; int last_pid; - int last_job_id; }; #define NUMBER_OF_GPU_CORES 16 -static struct mali_gpu_job mali_gpu_jobs[NUMBER_OF_GPU_UNITS][NUMBER_OF_GPU_CORES]; -static DEFINE_SPINLOCK(mali_gpu_jobs_lock); +static struct mali_activity mali_activities[NUMBER_OF_GPU_UNITS*NUMBER_OF_GPU_CORES]; +static DEFINE_SPINLOCK(mali_activities_lock); /* Only one event should be running on a unit and core at a time (ie, a start * event can only be followed by a stop and vice versa), but because the kernel @@ -67,53 +64,97 @@ static DEFINE_SPINLOCK(mali_gpu_jobs_lock); * start1, start2, stop1, stop2. Change it back into start1, stop1, start2, * stop2 by queueing up start2 and releasing it when stop1 is received. */ -static void mali_gpu_enqueue(int unit, int core, int tgid, int pid, int job_id) + +static int mali_activity_index(int core, int key) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mali_activities); ++i) { + if ((mali_activities[i].core == core) && (mali_activities[i].key == key)) { + break; + } + if ((mali_activities[i].core == 0) && (mali_activities[i].key == 0)) { + mali_activities[i].core = core; + mali_activities[i].key = key; + break; + } + } + BUG_ON(i >= ARRAY_SIZE(mali_activities)); + + return i; +} + +static void mali_activity_enqueue(int core, int key, int activity, int pid) { + int i; int count; - spin_lock(&mali_gpu_jobs_lock); - count = mali_gpu_jobs[unit][core].count; + spin_lock(&mali_activities_lock); + i = mali_activity_index(core, key); + + count = mali_activities[i].count; BUG_ON(count < 0); - ++mali_gpu_jobs[unit][core].count; + ++mali_activities[i].count; if (count) { - mali_gpu_jobs[unit][core].last_tgid = tgid; - mali_gpu_jobs[unit][core].last_pid = pid; - mali_gpu_jobs[unit][core].last_job_id = job_id; + mali_activities[i].last_activity = activity; + mali_activities[i].last_pid = pid; } - spin_unlock(&mali_gpu_jobs_lock); + spin_unlock(&mali_activities_lock); if (!count) { - marshal_sched_gpu_start(unit, core, tgid, pid/*, job_id*/); + gator_marshal_activity_switch(core, key, activity, pid); } } -static void mali_gpu_stop(int unit, int core) +static void mali_activity_stop(int core, int key) { + int i; int count; - int last_tgid = 0; + int last_activity = 0; int last_pid = 0; - //int last_job_id = 0; - spin_lock(&mali_gpu_jobs_lock); - if (mali_gpu_jobs[unit][core].count == 0) { - spin_unlock(&mali_gpu_jobs_lock); + spin_lock(&mali_activities_lock); + i = mali_activity_index(core, key); + + if (mali_activities[i].count == 0) { + spin_unlock(&mali_activities_lock); return; } - --mali_gpu_jobs[unit][core].count; - count = mali_gpu_jobs[unit][core].count; + --mali_activities[i].count; + count = mali_activities[i].count; if (count) { - last_tgid = mali_gpu_jobs[unit][core].last_tgid; - last_pid = mali_gpu_jobs[unit][core].last_pid; - //last_job_id = mali_gpu_jobs[unit][core].last_job_id; + last_activity = mali_activities[i].last_activity; + last_pid = mali_activities[i].last_pid; } - spin_unlock(&mali_gpu_jobs_lock); + spin_unlock(&mali_activities_lock); - marshal_sched_gpu_stop(unit, core); + gator_marshal_activity_switch(core, key, 0, 0); if (count) { - marshal_sched_gpu_start(unit, core, last_tgid, last_pid/*, last_job_id*/); + gator_marshal_activity_switch(core, key, last_activity, last_pid); } } +void mali_activity_clear(mali_counter mali_activity[], size_t mali_activity_size) +{ + int activity; + int cores; + int core; + + for (activity = 0; activity < mali_activity_size; ++activity) { + cores = mali_activity[activity].cores; + if (cores < 0) { + cores = 1; + } + for (core = 0; core < cores; ++core) { + if (mali_activity[activity].enabled) { + gator_marshal_activity_switch(core, mali_activity[activity].key, 0, 0); + } + } + } +} + +#endif + #if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx) #include "gator_events_mali_4xx.h" @@ -142,6 +183,8 @@ enum { EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1, }; +mali_counter mali_activity[2]; + GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned int d2, unsigned int d3, unsigned int d4)) { unsigned int component, state; @@ -154,18 +197,26 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned case EVENT_TYPE_START: if (component == EVENT_CHANNEL_VP0) { /* tgid = d0; pid = d1; */ - mali_gpu_enqueue(GPU_UNIT_VP, 0, d0, d1, 0); + if (mali_activity[1].enabled) { + mali_activity_enqueue(0, mali_activity[1].key, 1, d1); + } } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) { /* tgid = d0; pid = d1; */ - mali_gpu_enqueue(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, d0, d1, 0); + if (mali_activity[0].enabled) { + mali_activity_enqueue(component - EVENT_CHANNEL_FP0, mali_activity[0].key, 1, d1); + } } break; case EVENT_TYPE_STOP: if (component == EVENT_CHANNEL_VP0) { - mali_gpu_stop(GPU_UNIT_VP, 0); + if (mali_activity[1].enabled) { + mali_activity_stop(0, mali_activity[1].key); + } } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) { - mali_gpu_stop(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0); + if (mali_activity[0].enabled) { + mali_activity_stop(component - EVENT_CHANNEL_FP0, mali_activity[0].key); + } } break; @@ -186,6 +237,9 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned #endif #if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx) + +mali_counter mali_activity[3]; + #if defined(MALI_JOB_SLOTS_EVENT_CHANGED) GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid, unsigned char job_id)) #else @@ -217,31 +271,21 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne if (unit != GPU_UNIT_NONE) { switch (state) { case EVENT_TYPE_START: - mali_gpu_enqueue(unit, 0, tgid, (pid != 0 ? pid : tgid), job_id); + if (mali_activity[component].enabled) { + mali_activity_enqueue(0, mali_activity[component].key, 1, (pid != 0 ? pid : tgid)); + } break; case EVENT_TYPE_STOP: - mali_gpu_stop(unit, 0); + default: // Some jobs can be soft-stopped, so ensure that this terminates the activity trace. + if (mali_activity[component].enabled) { + mali_activity_stop(0, mali_activity[component].key); + } break; - default: - /* - * Some jobs can be soft-stopped, so ensure that this terminates the activity trace. - */ - mali_gpu_stop(unit, 0); } } } #endif -GATOR_DEFINE_PROBE(gpu_activity_start, TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p)) -{ - mali_gpu_enqueue(gpu_unit, gpu_core, (int)p->tgid, (int)p->pid, 0); -} - -GATOR_DEFINE_PROBE(gpu_activity_stop, TP_PROTO(int gpu_unit, int gpu_core)) -{ - mali_gpu_stop(gpu_unit, gpu_core); -} - static int gator_trace_gpu_start(void) { /* @@ -249,32 +293,25 @@ static int gator_trace_gpu_start(void) * Absence of gpu trace points is not an error */ - memset(&mali_gpu_jobs, 0, sizeof(mali_gpu_jobs)); - gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0; +#if defined(MALI_SUPPORT) + memset(&mali_activities, 0, sizeof(mali_activities)); +#endif + mali_timeline_trace_registered = mali_job_slots_trace_registered = 0; #if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx) + mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity)); if (!GATOR_REGISTER_TRACE(mali_timeline_event)) { mali_timeline_trace_registered = 1; } #endif #if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx) + mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity)); 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; - } - return 0; } @@ -292,10 +329,5 @@ static void gator_trace_gpu_stop(void) } #endif - if (gpu_trace_registered) { - GATOR_UNREGISTER_TRACE(gpu_activity_stop); - GATOR_UNREGISTER_TRACE(gpu_activity_start); - } - - gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0; + mali_timeline_trace_registered = mali_job_slots_trace_registered = 0; } diff --git a/drivers/gator/gator_trace_gpu.h b/drivers/gator/gator_trace_gpu.h deleted file mode 100644 index 5113d459e24c..000000000000 --- a/drivers/gator/gator_trace_gpu.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#undef TRACE_GPU -#define TRACE_GPU gpu - -#if !defined(_TRACE_GPU_H) -#define _TRACE_GPU_H - -#include - -/* - * UNIT - the GPU processor type - * 1 = Vertex Processor - * 2 = Fragment Processor - * - * CORE - the GPU processor core number - * this is not the CPU core number - */ - -/* - * Tracepoint for calling GPU unit start activity on core - */ -TRACE_EVENT(gpu_activity_start, - - TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *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_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) - ); - -/* - * Tracepoint for calling GPU unit stop activity on core - */ -TRACE_EVENT(gpu_activity_stop, - - TP_PROTO(int gpu_unit, int gpu_core), - - TP_ARGS(gpu_unit, 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_printk("unit=%d core=%d", __entry->gpu_unit, __entry->gpu_core) - ); - -#endif /* _TRACE_GPU_H */ - -/* This part must be outside protection */ -#include diff --git a/drivers/gator/gator_trace_power.c b/drivers/gator/gator_trace_power.c index 1895bb988c9f..f2754b1c2b56 100644 --- a/drivers/gator/gator_trace_power.c +++ b/drivers/gator/gator_trace_power.c @@ -75,7 +75,7 @@ static int gator_trace_power_create_files(struct super_block *sb, struct dentry GATOR_DEFINE_PROBE(cpu_frequency, TP_PROTO(unsigned int frequency, unsigned int cpu)) { cpu = lcpu_to_pcpu(cpu); - marshal_event_single(cpu, power_cpu_key[POWER_CPU_FREQ], frequency * 1000); + marshal_event_single64(cpu, power_cpu_key[POWER_CPU_FREQ], frequency * 1000L); } GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu)) @@ -109,7 +109,7 @@ static void gator_trace_power_online(void) int pcpu = get_physical_cpu(); int lcpu = get_logical_cpu(); if (power_cpu_enabled[POWER_CPU_FREQ]) { - marshal_event_single(pcpu, power_cpu_key[POWER_CPU_FREQ], cpufreq_quick_get(lcpu) * 1000); + marshal_event_single64(pcpu, power_cpu_key[POWER_CPU_FREQ], cpufreq_quick_get(lcpu) * 1000L); } } diff --git a/drivers/gator/gator_trace_sched.c b/drivers/gator/gator_trace_sched.c index 52990e9d4811..655008628933 100644 --- a/drivers/gator/gator_trace_sched.c +++ b/drivers/gator/gator_trace_sched.c @@ -114,7 +114,7 @@ static void collect_counters(u64 time, struct task_struct *task) // Commit buffers on timeout if (gator_live_rate > 0 && time >= per_cpu(gator_buffer_commit_time, cpu)) { - static const int buftypes[] = { NAME_BUF, COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF }; + static const int buftypes[] = { NAME_BUF, COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF, ACTIVITY_BUF }; int i; for (i = 0; i < ARRAY_SIZE(buftypes); ++i) { @@ -137,35 +137,44 @@ static void collect_counters(u64 time, struct task_struct *task) // special case used during a suspend of the system static void trace_sched_insert_idle(void) { - marshal_sched_trace_switch(0, 0, 0, 0); + marshal_sched_trace_switch(0, 0); } -GATOR_DEFINE_PROBE(sched_process_fork, TP_PROTO(struct task_struct *parent, struct task_struct *child)) +static void gator_trace_emit_link(struct task_struct *p) { int cookie; int cpu = get_physical_cpu(); - cookie = get_exec_cookie(cpu, child); - emit_pid_name(child); + cookie = get_exec_cookie(cpu, p); + emit_pid_name(p); - marshal_sched_trace_start(child->tgid, child->pid, cookie); + marshal_link(cookie, p->tgid, p->pid); } +GATOR_DEFINE_PROBE(sched_process_fork, TP_PROTO(struct task_struct *parent, struct task_struct *child)) +{ + gator_trace_emit_link(child); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +GATOR_DEFINE_PROBE(sched_process_exec, TP_PROTO(struct task_struct *p, pid_t old_pid, struct linux_binprm *bprm)) +{ + gator_trace_emit_link(p); +} +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next)) #else GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_struct *next)) #endif { - int cookie; int state; int cpu = get_physical_cpu(); per_cpu(in_scheduler_context, cpu) = true; // do as much work as possible before disabling interrupts - cookie = get_exec_cookie(cpu, next); - emit_pid_name(next); if (prev->state == TASK_RUNNING) { state = STATE_CONTENTION; } else if (prev->in_iowait) { @@ -178,7 +187,10 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_ collect_counters(gator_get_time(), prev); per_cpu(collecting, cpu) = 0; - marshal_sched_trace_switch(next->tgid, next->pid, cookie, state); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) + gator_trace_emit_link(next); +#endif + marshal_sched_trace_switch(next->pid, state); per_cpu(in_scheduler_context, cpu) = false; } @@ -199,6 +211,10 @@ static int register_scheduler_tracepoints(void) // register tracepoints if (GATOR_REGISTER_TRACE(sched_process_fork)) goto fail_sched_process_fork; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) + if (GATOR_REGISTER_TRACE(sched_process_exec)) + goto fail_sched_process_exec; +#endif if (GATOR_REGISTER_TRACE(sched_switch)) goto fail_sched_switch; if (GATOR_REGISTER_TRACE(sched_process_free)) @@ -216,15 +232,42 @@ fail_sched_process_free: GATOR_UNREGISTER_TRACE(sched_switch); fail_sched_switch: GATOR_UNREGISTER_TRACE(sched_process_fork); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +fail_sched_process_exec: + GATOR_UNREGISTER_TRACE(sched_process_exec); +#endif fail_sched_process_fork: pr_err("gator: tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n"); return -1; } +static void unregister_scheduler_tracepoints(void) +{ + GATOR_UNREGISTER_TRACE(sched_process_fork); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) + GATOR_UNREGISTER_TRACE(sched_process_exec); +#endif + GATOR_UNREGISTER_TRACE(sched_switch); + GATOR_UNREGISTER_TRACE(sched_process_free); + pr_debug("gator: unregistered tracepoints\n"); +} + +static void gator_trace_sched_stop(void) +{ + int cpu; + + unregister_scheduler_tracepoints(); + + for_each_present_cpu(cpu) { + kfree(per_cpu(taskname_keys, cpu)); + } +} + static int gator_trace_sched_start(void) { int cpu, size; + int ret; for_each_present_cpu(cpu) { size = TASK_MAP_ENTRIES * TASK_MAX_COLLISIONS * sizeof(uint64_t); @@ -234,7 +277,9 @@ static int gator_trace_sched_start(void) memset(per_cpu(taskname_keys, cpu), 0, size); } - return register_scheduler_tracepoints(); + ret = register_scheduler_tracepoints(); + + return ret; } static void gator_trace_sched_offline(void) @@ -242,24 +287,6 @@ static void gator_trace_sched_offline(void) trace_sched_insert_idle(); } -static void unregister_scheduler_tracepoints(void) -{ - GATOR_UNREGISTER_TRACE(sched_process_fork); - GATOR_UNREGISTER_TRACE(sched_switch); - GATOR_UNREGISTER_TRACE(sched_process_free); - pr_debug("gator: unregistered tracepoints\n"); -} - -static void gator_trace_sched_stop(void) -{ - int cpu; - unregister_scheduler_tracepoints(); - - for_each_present_cpu(cpu) { - kfree(per_cpu(taskname_keys, cpu)); - } -} - static void gator_trace_sched_init(void) { int i; diff --git a/drivers/gator/mali/mali_dd_gator_api.h b/drivers/gator/mali/mali_dd_gator_api.h new file mode 100644 index 000000000000..104b34f2d72a --- /dev/null +++ b/drivers/gator/mali/mali_dd_gator_api.h @@ -0,0 +1,40 @@ +#if !defined(MALI_DDK_GATOR_API_VERSION) + #define MALI_DDK_GATOR_API_VERSION 3 +#endif +#if !defined(MALI_TRUE) + #define MALI_TRUE ((unsigned int)1) +#endif + +#if !defined(MALI_FALSE) + #define MALI_FALSE ((unsigned int)0) +#endif + +struct mali_dd_hwcnt_info { + + /* Passed from Gator to kbase */ + //u32 in_mali_dd_hwcnt_version; + unsigned short int bitmask[4]; + + /* Passed from kbase to Gator */ + + /* ptr to counter dump memory */ + void *kernel_dump_buffer; + + /* size of counter dump memory */ + unsigned int size; + + unsigned int gpu_id; + + unsigned int nr_cores; + + unsigned int nr_core_groups; + + /* The cached present bitmaps - these are the same as the corresponding hardware registers*/ + unsigned long int shader_present_bitmap; +}; + +struct mali_dd_hwcnt_handles; +extern struct mali_dd_hwcnt_handles* mali_dd_hwcnt_init(struct mali_dd_hwcnt_info *in_out_info); +extern void mali_dd_hwcnt_clear(struct mali_dd_hwcnt_info *in_out_info, struct mali_dd_hwcnt_handles *opaque_handles); +extern unsigned int kbase_dd_instr_hwcnt_dump_complete(struct mali_dd_hwcnt_handles *opaque_handles, unsigned int * const success); +extern unsigned int kbase_dd_instr_hwcnt_dump_irq(struct mali_dd_hwcnt_handles *opaque_handles); diff --git a/drivers/gator/mali_t6xx.mk b/drivers/gator/mali_t6xx.mk index 059d47aec910..fa7571ded17b 100644 --- a/drivers/gator/mali_t6xx.mk +++ b/drivers/gator/mali_t6xx.mk @@ -21,6 +21,10 @@ OSK_DIR = $(DDK_DIR)/drivers/gpu/arm/midgard/osk EXTRA_CFLAGS += -DMALI_DIR_MIDGARD=1 endif +ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/midgard/mali_dd_gator_api.h),) +EXTRA_CFLAGS += -DMALI_SIMPLE_API=1 +endif + UMP_DIR = $(DDK_DIR)/include/linux # Include directories in the DDK diff --git a/tools/gator/daemon/Android.mk b/tools/gator/daemon/Android.mk index 045d028fda5f..44c069cc7e24 100644 --- a/tools/gator/daemon/Android.mk +++ b/tools/gator/daemon/Android.mk @@ -3,7 +3,7 @@ include $(CLEAR_VARS) XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h) -LOCAL_CFLAGS += -Wall -O3 -mthumb-interwork -fno-exceptions -DETCDIR=\"/etc\" -Ilibsensors +LOCAL_CFLAGS += -Wall -O3 -mthumb-interwork -fno-exceptions -pthread -DETCDIR=\"/etc\" -Ilibsensors LOCAL_SRC_FILES := \ Buffer.cpp \ @@ -15,12 +15,14 @@ LOCAL_SRC_FILES := \ DynBuf.cpp \ EventsXML.cpp \ ExternalSource.cpp \ + FSDriver.cpp \ Fifo.cpp \ Hwmon.cpp \ KMod.cpp \ LocalCapture.cpp \ Logging.cpp \ main.cpp \ + MaliVideoDriver.cpp \ Monitor.cpp \ OlySocket.cpp \ OlyUtility.cpp \ @@ -55,7 +57,7 @@ LOCAL_SRC_FILES := \ mxml/mxml-set.c \ mxml/mxml-string.c -LOCAL_C_INCLUDES := $(LOCAL_PATH) +LOCAL_C_INCLUDES := $(LOCAL_PATH) LOCAL_MODULE := gatord LOCAL_MODULE_TAGS := optional diff --git a/tools/gator/daemon/Application.mk b/tools/gator/daemon/Application.mk new file mode 100644 index 000000000000..631ba54148d1 --- /dev/null +++ b/tools/gator/daemon/Application.mk @@ -0,0 +1 @@ +APP_PLATFORM := android-8 diff --git a/tools/gator/daemon/Buffer.cpp b/tools/gator/daemon/Buffer.cpp index 93557dabed9f..dd19f7f8be76 100644 --- a/tools/gator/daemon/Buffer.cpp +++ b/tools/gator/daemon/Buffer.cpp @@ -15,11 +15,12 @@ #define mask (mSize - 1) enum { - CODE_PEA = 1, - CODE_KEYS = 2, - CODE_FORMAT = 3, - CODE_MAPS = 4, - CODE_COMM = 5, + CODE_PEA = 1, + CODE_KEYS = 2, + CODE_FORMAT = 3, + CODE_MAPS = 4, + CODE_COMM = 5, + CODE_KEYS_OLD = 6, }; // Summary Frame Messages @@ -167,7 +168,7 @@ void Buffer::check(const uint64_t time) { } } -void Buffer::packInt(int32_t x) { +void Buffer::packInt(char *const buf, const int size, int &writePos, int32_t x) { int packedBytes = 0; int more = true; while (more) { @@ -181,11 +182,15 @@ void Buffer::packInt(int32_t x) { b |= 0x80; } - mBuf[(mWritePos + packedBytes) & mask] = b; + buf[(writePos + packedBytes) & /*mask*/(size - 1)] = b; packedBytes++; } - mWritePos = (mWritePos + packedBytes) & mask; + writePos = (writePos + packedBytes) & /*mask*/(size - 1); +} + +void Buffer::packInt(int32_t x) { + packInt(mBuf, mSize, mWritePos, x); } void Buffer::packInt64(int64_t x) { @@ -320,6 +325,21 @@ void Buffer::keys(const int count, const __u64 *const ids, const int *const keys check(1); } +void Buffer::keysOld(const int keyCount, const int *const keys, const int bytes, const char *const buf) { + if (checkSpace((2 + keyCount) * MAXSIZE_PACK32 + bytes)) { + packInt(CODE_KEYS_OLD); + packInt(keyCount); + for (int i = 0; i < keyCount; ++i) { + packInt(keys[i]); + } + writeBytes(buf, bytes); + } else { + logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs"); + handleException(); + } + check(1); +} + void Buffer::format(const int length, const char *const format) { if (checkSpace(MAXSIZE_PACK32 + length + 1)) { packInt(CODE_FORMAT); diff --git a/tools/gator/daemon/Buffer.h b/tools/gator/daemon/Buffer.h index 50237771860c..2de1b97ac091 100644 --- a/tools/gator/daemon/Buffer.h +++ b/tools/gator/daemon/Buffer.h @@ -54,6 +54,7 @@ public: // Perf Attrs messages void pea(const struct perf_event_attr *const pea, int key); void keys(const int count, const __u64 *const ids, const int *const keys); + void keysOld(const int keyCount, const int *const keys, const int bytes, const char *const buf); void format(const int length, const char *const format); void maps(const int pid, const int tid, const char *const maps); void comm(const int pid, const int tid, const char *const image, const char *const comm); @@ -64,6 +65,11 @@ public: // Prefer a new member to using these functions if possible char *getWritePos() { return mBuf + mWritePos; } void advanceWrite(int bytes) { mWritePos = (mWritePos + bytes) & /*mask*/(mSize - 1); } + static void packInt(char *const buf, const int size, int &writePos, int32_t x); + void packInt(int32_t x); + void packInt64(int64_t x); + void writeBytes(const void *const data, size_t count); + void writeString(const char *const str); static void writeLEInt(unsigned char *buf, int v) { buf[0] = (v >> 0) & 0xFF; @@ -76,11 +82,6 @@ private: bool commitReady() const; bool checkSpace(int bytes); - void packInt(int32_t x); - void packInt64(int64_t x); - void writeBytes(const void *const data, size_t count); - void writeString(const char *const str); - const int32_t mCore; const int32_t mBufType; const int mSize; diff --git a/tools/gator/daemon/CapturedXML.cpp b/tools/gator/daemon/CapturedXML.cpp index cf79b72a1166..4a11415a00c9 100644 --- a/tools/gator/daemon/CapturedXML.cpp +++ b/tools/gator/daemon/CapturedXML.cpp @@ -33,7 +33,7 @@ mxml_node_t* CapturedXML::getTree(bool includeTime) { captured = mxmlNewElement(xml, "captured"); mxmlElementSetAttr(captured, "version", "1"); if (gSessionData->perf.isSetup()) { - mxmlElementSetAttr(captured, "type", "Perf"); + mxmlElementSetAttr(captured, "type", "Perf"); } mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION); if (includeTime) { // Send the following only after the capture is complete @@ -66,10 +66,15 @@ mxml_node_t* CapturedXML::getTree(bool includeTime) { mxml_node_t *const node = mxmlNewElement(counters, "counter"); mxmlElementSetAttrf(node, "key", "0x%x", counter.getKey()); mxmlElementSetAttr(node, "type", counter.getType()); - mxmlElementSetAttrf(node, "event", "0x%x", counter.getEvent()); + if (counter.getEvent() != -1) { + mxmlElementSetAttrf(node, "event", "0x%x", counter.getEvent()); + } if (counter.getCount() > 0) { mxmlElementSetAttrf(node, "count", "%d", counter.getCount()); } + if (counter.getCores() > 0) { + mxmlElementSetAttrf(node, "cores", "%d", counter.getCores()); + } } } @@ -89,7 +94,7 @@ void CapturedXML::write(char* path) { // Set full path snprintf(file, PATH_MAX, "%s/captured.xml", path); - + char* xml = getXML(true); if (util->writeToDisk(file, xml) < 0) { logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); diff --git a/tools/gator/daemon/CapturedXML.h b/tools/gator/daemon/CapturedXML.h index efc1e52bdba3..ed08c44bc3ff 100644 --- a/tools/gator/daemon/CapturedXML.h +++ b/tools/gator/daemon/CapturedXML.h @@ -23,4 +23,4 @@ private: const char * mxmlWhitespaceCB(mxml_node_t *node, int where); -#endif //__CAPTURED_XML_H__ +#endif //__CAPTURED_XML_H__ diff --git a/tools/gator/daemon/Child.cpp b/tools/gator/daemon/Child.cpp index ca33561ffdca..1901ecc6a724 100644 --- a/tools/gator/daemon/Child.cpp +++ b/tools/gator/daemon/Child.cpp @@ -26,13 +26,13 @@ #include "Driver.h" #include "PerfSource.h" #include "DriverSource.h" -#include "UserSpaceSource.h" #include "ExternalSource.h" +#include "UserSpaceSource.h" static sem_t haltPipeline, senderThreadStarted, startProfile, senderSem; // Shared by Child and spawned threads static Source *primarySource = NULL; -static Source *userSpaceSource = NULL; static Source *externalSource = NULL; +static Source *userSpaceSource = NULL; static Sender* sender = NULL; // Shared by Child.cpp and spawned threads Child* child = NULL; // shared by Child.cpp and main.cpp @@ -147,16 +147,16 @@ static void *senderThread(void *) { prctl(PR_SET_NAME, (unsigned long)&"gatord-sender", 0, 0, 0); sem_wait(&haltPipeline); - while (!primarySource->isDone() || (userSpaceSource != NULL && !userSpaceSource->isDone()) || (externalSource != NULL && !externalSource->isDone())) { + while (!primarySource->isDone() || + !externalSource->isDone() || + (userSpaceSource != NULL && !userSpaceSource->isDone())) { sem_wait(&senderSem); primarySource->write(sender); + externalSource->write(sender); if (userSpaceSource != NULL) { userSpaceSource->write(sender); } - if (externalSource != NULL) { - externalSource->write(sender); - } } // write end-of-capture sequence @@ -202,6 +202,10 @@ void Child::initialization() { void Child::endSession() { gSessionData->mSessionIsActive = false; primarySource->interrupt(); + externalSource->interrupt(); + if (userSpaceSource != NULL) { + userSpaceSource->interrupt(); + } sem_post(&haltPipeline); } @@ -227,9 +231,9 @@ void Child::run() { // Set up the driver; must be done after gSessionData->mPerfCounterType[] is populated if (!gSessionData->perf.isSetup()) { - primarySource = new DriverSource(&senderSem, &startProfile); + primarySource = new DriverSource(&senderSem, &startProfile); } else { - primarySource = new PerfSource(&senderSem, &startProfile); + primarySource = new PerfSource(&senderSem, &startProfile); } // Initialize all drivers @@ -280,11 +284,18 @@ void Child::run() { thread_creation_success = false; } else if (socket && pthread_create(&stopThreadID, NULL, stopThread, NULL)) { thread_creation_success = false; - } else if (pthread_create(&senderThreadID, NULL, senderThread, NULL)){ + } else if (pthread_create(&senderThreadID, NULL, senderThread, NULL)) { thread_creation_success = false; } - if (gSessionData->hwmon.countersEnabled()) { + externalSource = new ExternalSource(&senderSem); + if (!externalSource->prepare()) { + logg->logError(__FILE__, __LINE__, "Unable to prepare for capture"); + handleException(); + } + externalSource->start(); + + if (gSessionData->hwmon.countersEnabled() || gSessionData->fsDriver.countersEnabled()) { userSpaceSource = new UserSpaceSource(&senderSem); if (!userSpaceSource->prepare()) { logg->logError(__FILE__, __LINE__, "Unable to prepare for capture"); @@ -292,14 +303,6 @@ void Child::run() { } userSpaceSource->start(); } - if (access("/tmp/gator", F_OK) == 0) { - externalSource = new ExternalSource(&senderSem); - if (!externalSource->prepare()) { - logg->logError(__FILE__, __LINE__, "Unable to prepare for capture"); - handleException(); - } - externalSource->start(); - } if (!thread_creation_success) { logg->logError(__FILE__, __LINE__, "Failed to create gator threads"); @@ -312,12 +315,10 @@ void Child::run() { // Start profiling primarySource->run(); - if (externalSource != NULL) { - externalSource->join(); - } if (userSpaceSource != NULL) { userSpaceSource->join(); } + externalSource->join(); // Wait for the other threads to exit pthread_join(senderThreadID, NULL); @@ -337,8 +338,8 @@ void Child::run() { logg->logMessage("Profiling ended."); - delete externalSource; delete userSpaceSource; + delete externalSource; delete primarySource; delete sender; delete localCapture; diff --git a/tools/gator/daemon/Child.h b/tools/gator/daemon/Child.h index 9e206d7113b8..a306a7760819 100644 --- a/tools/gator/daemon/Child.h +++ b/tools/gator/daemon/Child.h @@ -30,4 +30,4 @@ private: Child &operator=(const Child &); }; -#endif //__CHILD_H__ +#endif //__CHILD_H__ diff --git a/tools/gator/daemon/ConfigurationXML.cpp b/tools/gator/daemon/ConfigurationXML.cpp index fd479f2452cd..6590dd389196 100644 --- a/tools/gator/daemon/ConfigurationXML.cpp +++ b/tools/gator/daemon/ConfigurationXML.cpp @@ -21,12 +21,13 @@ static const char* ATTR_COUNTER = "counter"; static const char* ATTR_REVISION = "revision"; static const char* ATTR_EVENT = "event"; static const char* ATTR_COUNT = "count"; +static const char* ATTR_CORES = "cores"; ConfigurationXML::ConfigurationXML() { const char * configuration_xml; unsigned int configuration_xml_len; getDefaultConfigurationXml(configuration_xml, configuration_xml_len); - + char path[PATH_MAX]; getPath(path); @@ -53,7 +54,7 @@ ConfigurationXML::ConfigurationXML() { break; } - + validate(); } @@ -82,7 +83,7 @@ int ConfigurationXML::parse(const char* configurationXML) { node = mxmlGetFirstChild(tree); while (node && mxmlGetType(node) != MXML_ELEMENT) node = mxmlWalkNext(node, tree, MXML_NO_DESCEND); - + ret = configurationsTag(node); node = mxmlGetFirstChild(node); @@ -127,7 +128,7 @@ void ConfigurationXML::validate(void) { #define CONFIGURATION_REVISION 3 int ConfigurationXML::configurationsTag(mxml_node_t *node) { const char* revision_string; - + revision_string = mxmlElementGetAttr(node, ATTR_REVISION); if (!revision_string) { return 1; //revision issue; @@ -158,6 +159,7 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) { if (mxmlElementGetAttr(node, ATTR_COUNTER)) counter.setType(mxmlElementGetAttr(node, ATTR_COUNTER)); if (mxmlElementGetAttr(node, ATTR_EVENT)) counter.setEvent(strtol(mxmlElementGetAttr(node, ATTR_EVENT), NULL, 16)); if (mxmlElementGetAttr(node, ATTR_COUNT)) counter.setCount(strtol(mxmlElementGetAttr(node, ATTR_COUNT), NULL, 10)); + if (mxmlElementGetAttr(node, ATTR_CORES)) counter.setCores(strtol(mxmlElementGetAttr(node, ATTR_CORES), NULL, 10)); if (counter.getCount() > 0) { gSessionData->mIsEBS = true; } diff --git a/tools/gator/daemon/Counter.h b/tools/gator/daemon/Counter.h index 689174573e4e..5202aa046362 100644 --- a/tools/gator/daemon/Counter.h +++ b/tools/gator/daemon/Counter.h @@ -27,6 +27,7 @@ public: mEnabled = false; mEvent = -1; mCount = 0; + mCores = -1; mKey = 0; mDriver = NULL; } @@ -35,6 +36,7 @@ public: void setEnabled(const bool enabled) { mEnabled = enabled; } void setEvent(const int event) { mEvent = event; } void setCount(const int count) { mCount = count; } + void setCores(const int cores) { mCores = cores; } void setKey(const int key) { mKey = key; } void setDriver(Driver *const driver) { mDriver = driver; } @@ -42,6 +44,7 @@ public: bool isEnabled() const { return mEnabled; } int getEvent() const { return mEvent; } int getCount() const { return mCount; } + int getCores() const { return mCores; } int getKey() const { return mKey; } Driver *getDriver() const { return mDriver; } @@ -54,6 +57,7 @@ private: bool mEnabled; int mEvent; int mCount; + int mCores; int mKey; Driver *mDriver; }; diff --git a/tools/gator/daemon/DriverSource.cpp b/tools/gator/daemon/DriverSource.cpp index f78ec6b7ce41..11d3095ef6d2 100644 --- a/tools/gator/daemon/DriverSource.cpp +++ b/tools/gator/daemon/DriverSource.cpp @@ -12,19 +12,24 @@ #include #include +#include #include +#include "Buffer.h" #include "Child.h" +#include "DynBuf.h" #include "Fifo.h" #include "Logging.h" +#include "Proc.h" #include "Sender.h" #include "SessionData.h" extern Child *child; -DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mFifo(NULL), mSenderSem(senderSem), mStartProfile(startProfile), mBufferSize(0), mBufferFD(0), mLength(1) { +DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL), mFifo(NULL), mSenderSem(senderSem), mStartProfile(startProfile), mBufferSize(0), mBufferFD(0), mLength(1) { int driver_version = 0; + mBuffer = new Buffer(0, FRAME_PERF_ATTRS, 4*1024*1024, senderSem); if (readIntDriver("/dev/gator/version", &driver_version) == -1) { logg->logError(__FILE__, __LINE__, "Error reading gator driver version"); handleException(); @@ -43,7 +48,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mFifo(NULL), handleException(); } else { // Release version mismatch - logg->logError(__FILE__, __LINE__, + logg->logError(__FILE__, __LINE__, "gator driver version \"%d\" is different than gator daemon version \"%d\".\n" ">> Please upgrade the driver and daemon to the latest versions.", driver_version, PROTOCOL_VERSION); handleException(); @@ -87,6 +92,28 @@ bool DriverSource::prepare() { return true; } +void DriverSource::bootstrapThread() { + prctl(PR_SET_NAME, (unsigned long)&"gatord-bootstrap", 0, 0, 0); + + DynBuf printb; + DynBuf b1; + DynBuf b2; + DynBuf b3; + + if (!readProc(mBuffer, false, &printb, &b1, &b2, &b3)) { + logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__); + handleException(); + } + + mBuffer->commit(1); + mBuffer->setDone(); +} + +void *DriverSource::bootstrapThreadStatic(void *arg) { + static_cast(arg)->bootstrapThread(); + return NULL; +} + void DriverSource::run() { // Get the initial pointer to the collect buffer char *collectBuffer = mFifo->start(); @@ -138,6 +165,12 @@ void DriverSource::run() { sem_post(mStartProfile); + pthread_t bootstrapThreadID; + if (pthread_create(&bootstrapThreadID, NULL, bootstrapThreadStatic, this) != 0) { + logg->logError(__FILE__, __LINE__, "Unable to start the gator_bootstrap thread"); + handleException(); + } + // Collect Data do { // This command will stall until data is received from the driver @@ -164,6 +197,8 @@ void DriverSource::run() { } while (bytesCollected > 0); logg->logMessage("Exit collect data loop"); + + pthread_join(bootstrapThreadID, NULL); } void DriverSource::interrupt() { @@ -174,7 +209,7 @@ void DriverSource::interrupt() { } bool DriverSource::isDone() { - return mLength <= 0; + return mLength <= 0 && (mBuffer == NULL || mBuffer->isDone()); } void DriverSource::write(Sender *sender) { @@ -182,6 +217,16 @@ void DriverSource::write(Sender *sender) { if (data != NULL) { sender->writeData(data, mLength, RESPONSE_APC_DATA); mFifo->release(); + // Assume the summary packet is in the first block received from the driver + gSessionData->mSentSummary = true; + } + if (mBuffer != NULL && !mBuffer->isDone()) { + mBuffer->write(sender); + if (mBuffer->isDone()) { + Buffer *buf = mBuffer; + mBuffer = NULL; + delete buf; + } } } @@ -227,7 +272,7 @@ int DriverSource::readInt64Driver(const char *fullpath, int64_t *value) { char *endptr; errno = 0; *value = strtoll(data, &endptr, 10); - if (errno != 0 || *endptr != '\n') { + if (errno != 0 || (*endptr != '\n' && *endptr != '\0')) { logg->logMessage("Invalid value in file %s", fullpath); return -1; } diff --git a/tools/gator/daemon/DriverSource.h b/tools/gator/daemon/DriverSource.h index dcf1078a239c..ec27b0815bbf 100644 --- a/tools/gator/daemon/DriverSource.h +++ b/tools/gator/daemon/DriverSource.h @@ -14,6 +14,7 @@ #include "Source.h" +class Buffer; class Fifo; class DriverSource : public Source { @@ -37,6 +38,10 @@ public: static int writeReadDriver(const char *path, int64_t *value); private: + static void *bootstrapThreadStatic(void *arg); + void bootstrapThread(); + + Buffer *mBuffer; Fifo *mFifo; sem_t *const mSenderSem; sem_t *const mStartProfile; diff --git a/tools/gator/daemon/EventsXML.cpp b/tools/gator/daemon/EventsXML.cpp index a07a046f3353..cf0192ef671f 100644 --- a/tools/gator/daemon/EventsXML.cpp +++ b/tools/gator/daemon/EventsXML.cpp @@ -13,7 +13,7 @@ #include "OlyUtility.h" #include "SessionData.h" -char* EventsXML::getXML() { +mxml_node_t *EventsXML::getTree() { #include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len char path[PATH_MAX]; mxml_node_t *xml; @@ -38,6 +38,12 @@ char* EventsXML::getXML() { xml = mxmlLoadString(NULL, (const char *)events_xml, MXML_NO_CALLBACK); } + return xml; +} + +char *EventsXML::getXML() { + mxml_node_t *xml = getTree(); + // Add dynamic events from the drivers mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND); if (!events) { @@ -48,19 +54,19 @@ char* EventsXML::getXML() { driver->writeEvents(events); } - char* string = mxmlSaveAllocString(xml, mxmlWhitespaceCB); + char *string = mxmlSaveAllocString(xml, mxmlWhitespaceCB); mxmlDelete(xml); return string; } -void EventsXML::write(const char* path) { +void EventsXML::write(const char *path) { char file[PATH_MAX]; // Set full path snprintf(file, PATH_MAX, "%s/events.xml", path); - - char* buf = getXML(); + + char *buf = getXML(); if (util->writeToDisk(file, buf) < 0) { logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); handleException(); diff --git a/tools/gator/daemon/EventsXML.h b/tools/gator/daemon/EventsXML.h index 6cd1560f7d4e..ff7a02fd3c78 100644 --- a/tools/gator/daemon/EventsXML.h +++ b/tools/gator/daemon/EventsXML.h @@ -9,9 +9,12 @@ #ifndef EVENTS_XML #define EVENTS_XML +#include "mxml/mxml.h" + class EventsXML { public: - char* getXML(); + mxml_node_t *getTree(); + char *getXML(); void write(const char* path); }; diff --git a/tools/gator/daemon/ExternalSource.cpp b/tools/gator/daemon/ExternalSource.cpp index fe5824b04812..b6ec301d0c08 100644 --- a/tools/gator/daemon/ExternalSource.cpp +++ b/tools/gator/daemon/ExternalSource.cpp @@ -8,41 +8,195 @@ #include "ExternalSource.h" +#include #include +#include #include "Logging.h" #include "OlySocket.h" #include "SessionData.h" -ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 1024, senderSem), mSock("/tmp/gator") { +static const char MALI_VIDEO[] = "\0mali-video"; +static const char MALI_VIDEO_STARTUP[] = "\0mali-video-startup"; +static const char MALI_VIDEO_V1[] = "MALI_VIDEO 1\n"; + +static bool setNonblock(const int fd) { + int flags; + + flags = fcntl(fd, F_GETFL); + if (flags < 0) { + logg->logMessage("fcntl getfl failed"); + return false; + } + + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) { + logg->logMessage("fcntl setfl failed"); + return false; + } + + return true; +} + +ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 128*1024, senderSem), mMonitor(), mMveStartupUds(MALI_VIDEO_STARTUP, sizeof(MALI_VIDEO_STARTUP)), mInterruptFd(-1), mMveUds(-1) { + sem_init(&mBufferSem, 0, 0); } ExternalSource::~ExternalSource() { } +void ExternalSource::waitFor(const uint64_t currTime, const int bytes) { + while (mBuffer.bytesAvailable() <= bytes) { + mBuffer.check(currTime); + sem_wait(&mBufferSem); + } +} + +void ExternalSource::configureConnection(const int fd, const char *const handshake, size_t size) { + if (!setNonblock(fd)) { + logg->logError(__FILE__, __LINE__, "Unable to set nonblock on fh"); + handleException(); + } + + if (!mMonitor.add(fd)) { + logg->logError(__FILE__, __LINE__, "Unable to add fh to monitor"); + handleException(); + } + + // Write the handshake to the circular buffer + waitFor(1, Buffer::MAXSIZE_PACK32 + 4 + size - 1); + mBuffer.packInt(fd); + mBuffer.writeLEInt((unsigned char *)mBuffer.getWritePos(), size - 1); + mBuffer.advanceWrite(4); + mBuffer.writeBytes(handshake, size - 1); +} + +bool ExternalSource::connectMve() { + if (!gSessionData->maliVideo.countersEnabled()) { + return true; + } + + mMveUds = OlySocket::connect(MALI_VIDEO, sizeof(MALI_VIDEO)); + if (mMveUds < 0) { + return false; + } + + if (!gSessionData->maliVideo.start(mMveUds)) { + return false; + } + + configureConnection(mMveUds, MALI_VIDEO_V1, sizeof(MALI_VIDEO_V1)); + + return true; +} + bool ExternalSource::prepare() { + if (!mMonitor.init() || !setNonblock(mMveStartupUds.getFd()) || !mMonitor.add(mMveStartupUds.getFd())) { + return false; + } + + connectMve(); + return true; } void ExternalSource::run() { - prctl(PR_SET_NAME, (unsigned long)&"gatord-uds", 0, 0, 0); + int pipefd[2]; + + prctl(PR_SET_NAME, (unsigned long)&"gatord-external", 0, 0, 0); + + if (pipe(pipefd) != 0) { + logg->logError(__FILE__, __LINE__, "pipe failed"); + handleException(); + } + mInterruptFd = pipefd[1]; + + if (!mMonitor.add(pipefd[0])) { + logg->logError(__FILE__, __LINE__, "Monitor::add failed"); + handleException(); + } while (gSessionData->mSessionIsActive) { - // Will be aborted when the socket is closed at the end of the capture - int length = mSock.receive(mBuffer.getWritePos(), mBuffer.contiguousSpaceAvailable()); - if (length <= 0) { - break; + struct epoll_event events[16]; + // Clear any pending sem posts + while (sem_trywait(&mBufferSem) == 0); + int ready = mMonitor.wait(events, ARRAY_LENGTH(events), -1); + if (ready < 0) { + logg->logError(__FILE__, __LINE__, "Monitor::wait failed"); + handleException(); } - mBuffer.advanceWrite(length); - mBuffer.check(0); + const uint64_t currTime = getTime(); + + for (int i = 0; i < ready; ++i) { + const int fd = events[i].data.fd; + if (fd == mMveStartupUds.getFd()) { + // Mali Video Engine says it's alive + int client = mMveStartupUds.acceptConnection(); + // Don't read from this connection, establish a new connection to Mali-V500 + close(client); + if (!connectMve()) { + logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali video connection"); + handleException(); + } + } else if (fd == pipefd[0]) { + // Means interrupt has been called and mSessionIsActive should be reread + } else { + while (true) { + waitFor(currTime, Buffer::MAXSIZE_PACK32 + 4); + + mBuffer.packInt(fd); + char *const bytesPos = mBuffer.getWritePos(); + mBuffer.advanceWrite(4); + const int contiguous = mBuffer.contiguousSpaceAvailable(); + const int bytes = read(fd, mBuffer.getWritePos(), contiguous); + if (bytes < 0) { + if (errno == EAGAIN) { + // Nothing left to read, and Buffer convention dictates that writePos can't go backwards + mBuffer.writeLEInt((unsigned char *)bytesPos, 0); + break; + } + // Something else failed, close the socket + mBuffer.writeLEInt((unsigned char *)bytesPos, -1); + close(fd); + break; + } else if (bytes == 0) { + // The other side is closed + mBuffer.writeLEInt((unsigned char *)bytesPos, -1); + close(fd); + break; + } + + mBuffer.writeLEInt((unsigned char *)bytesPos, bytes); + mBuffer.advanceWrite(bytes); + + // Short reads also mean nothing is left to read + if (bytes < contiguous) { + break; + } + } + } + } + + // Only call mBufferCheck once per iteration + mBuffer.check(currTime); } mBuffer.setDone(); + + mInterruptFd = -1; + close(pipefd[0]); + close(pipefd[1]); } void ExternalSource::interrupt() { - // Do nothing + if (mInterruptFd >= 0) { + int8_t c = 0; + // Write to the pipe to wake the monitor which will cause mSessionIsActive to be reread + if (::write(mInterruptFd, &c, sizeof(c)) != sizeof(c)) { + logg->logError(__FILE__, __LINE__, "write failed"); + handleException(); + } + } } bool ExternalSource::isDone() { @@ -50,7 +204,12 @@ bool ExternalSource::isDone() { } void ExternalSource::write(Sender *sender) { + // Don't send external data until the summary packet is sent so that monotonic delta is available + if (!gSessionData->mSentSummary) { + return; + } if (!mBuffer.isDone()) { mBuffer.write(sender); + sem_post(&mBufferSem); } } diff --git a/tools/gator/daemon/ExternalSource.h b/tools/gator/daemon/ExternalSource.h index 2052bdf2823e..2e7ed27df255 100644 --- a/tools/gator/daemon/ExternalSource.h +++ b/tools/gator/daemon/ExternalSource.h @@ -12,6 +12,7 @@ #include #include "Buffer.h" +#include "Monitor.h" #include "OlySocket.h" #include "Source.h" @@ -29,8 +30,16 @@ public: void write(Sender *sender); private: + void waitFor(const uint64_t currTime, const int bytes); + void configureConnection(const int fd, const char *const handshake, size_t size); + bool connectMve(); + + sem_t mBufferSem; Buffer mBuffer; - OlySocket mSock; + Monitor mMonitor; + OlyServerSocket mMveStartupUds; + int mInterruptFd; + int mMveUds; // Intentionally unimplemented ExternalSource(const ExternalSource &); diff --git a/tools/gator/daemon/FSDriver.cpp b/tools/gator/daemon/FSDriver.cpp new file mode 100644 index 000000000000..40c8df1af222 --- /dev/null +++ b/tools/gator/daemon/FSDriver.cpp @@ -0,0 +1,212 @@ +/** + * Copyright (C) ARM Limited 2014. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "FSDriver.h" + +#include +#include +#include +#include +#include + +#include "Buffer.h" +#include "Counter.h" +#include "DriverSource.h" +#include "Logging.h" +#include "SessionData.h" + +class FSCounter { +public: + FSCounter(FSCounter *next, char *name, const char *regex); + ~FSCounter(); + + FSCounter *getNext() const { return next; } + int getKey() const { return key; } + bool isEnabled() const { return enabled; } + void setEnabled(const bool enabled) { this->enabled = enabled; } + const char *getName() const { return name; } + int64_t read(); + +private: + FSCounter *const next; + regex_t reg; + char *name; + const int key; + int enabled : 1, + useRegex : 1; + + // Intentionally unimplemented + FSCounter(const FSCounter &); + FSCounter &operator=(const FSCounter &); +}; + +FSCounter::FSCounter(FSCounter *next, char *name, const char *regex) : next(next), name(name), key(getEventKey()), enabled(false), useRegex(regex != NULL) { + if (useRegex) { + int result = regcomp(®, regex, REG_EXTENDED); + if (result != 0) { + char buf[128]; + regerror(result, ®, buf, sizeof(buf)); + logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf); + handleException(); + } + } +} + +FSCounter::~FSCounter() { + free(name); + if (useRegex) { + regfree(®); + } +} + +int64_t FSCounter::read() { + int64_t value; + if (useRegex) { + char buf[4096]; + size_t pos = 0; + const int fd = open(name, O_RDONLY); + if (fd < 0) { + goto fail; + } + while (pos < sizeof(buf) - 1) { + const ssize_t bytes = ::read(fd, buf + pos, sizeof(buf) - pos - 1); + if (bytes < 0) { + goto fail; + } else if (bytes == 0) { + break; + } + pos += bytes; + } + close(fd); + buf[pos] = '\0'; + + regmatch_t match[2]; + int result = regexec(®, buf, 2, match, 0); + if (result != 0) { + regerror(result, ®, buf, sizeof(buf)); + logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, buf); + handleException(); + } + + if (match[1].rm_so < 0) { + logg->logError(__FILE__, __LINE__, "Parsing %s failed", name); + handleException(); + } + char *endptr; + errno = 0; + value = strtoll(buf + match[1].rm_so, &endptr, 0); + if (errno != 0) { + logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, strerror(errno)); + handleException(); + } + } else { + if (DriverSource::readInt64Driver(name, &value) != 0) { + goto fail; + } + } + return value; + + fail: + logg->logError(__FILE__, __LINE__, "Unable to read %s", name); + handleException(); +} + +FSDriver::FSDriver() : counters(NULL) { +} + +FSDriver::~FSDriver() { + while (counters != NULL) { + FSCounter * counter = counters; + counters = counter->getNext(); + delete counter; + } +} + +void FSDriver::setup(mxml_node_t *const xml) { + // fs driver does not currently work with perf + if (gSessionData->perf.isSetup()) { + return; + } + + mxml_node_t *node = xml; + while (true) { + node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND); + if (node == NULL) { + break; + } + const char *counter = mxmlElementGetAttr(node, "counter"); + if ((counter != NULL) && (counter[0] == '/')) { + const char *regex = mxmlElementGetAttr(node, "regex"); + counters = new FSCounter(counters, strdup(counter), regex); + } + } +} + +FSCounter *FSDriver::findCounter(const Counter &counter) const { + for (FSCounter * fsCounter = counters; fsCounter != NULL; fsCounter = fsCounter->getNext()) { + if (strcmp(fsCounter->getName(), counter.getType()) == 0) { + return fsCounter; + } + } + + return NULL; +} + +bool FSDriver::claimCounter(const Counter &counter) const { + return findCounter(counter) != NULL; +} + +bool FSDriver::countersEnabled() const { + for (FSCounter *counter = counters; counter != NULL; counter = counter->getNext()) { + if (counter->isEnabled()) { + return true; + } + } + return false; +} + +void FSDriver::resetCounters() { + for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) { + counter->setEnabled(false); + } +} + +void FSDriver::setupCounter(Counter &counter) { + FSCounter *const fsCounter = findCounter(counter); + if (fsCounter == NULL) { + counter.setEnabled(false); + return; + } + fsCounter->setEnabled(true); + counter.setKey(fsCounter->getKey()); +} + +int FSDriver::writeCounters(mxml_node_t *root) const { + int count = 0; + for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) { + if (access(counter->getName(), R_OK) == 0) { + mxml_node_t *node = mxmlNewElement(root, "counter"); + mxmlElementSetAttr(node, "name", counter->getName()); + ++count; + } + } + + return count; +} + +void FSDriver::start() { +} + +void FSDriver::read(Buffer * const buffer) { + for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) { + if (!counter->isEnabled()) { + continue; + } + buffer->event(counter->getKey(), counter->read()); + } +} diff --git a/tools/gator/daemon/FSDriver.h b/tools/gator/daemon/FSDriver.h new file mode 100644 index 000000000000..ef3955362331 --- /dev/null +++ b/tools/gator/daemon/FSDriver.h @@ -0,0 +1,44 @@ +/** + * Copyright (C) ARM Limited 2014. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef FSDRIVER_H +#define FSDRIVER_H + +#include "Driver.h" + +class Buffer; +class FSCounter; + +class FSDriver : public Driver { +public: + FSDriver(); + ~FSDriver(); + + void setup(mxml_node_t *const xml); + + bool claimCounter(const Counter &counter) const; + bool countersEnabled() const; + void resetCounters(); + void setupCounter(Counter &counter); + + int writeCounters(mxml_node_t *root) const; + + void start(); + void read(Buffer * buffer); + +private: + FSCounter *findCounter(const Counter &counter) const; + + FSCounter *counters; + + // Intentionally unimplemented + FSDriver(const FSDriver &); + FSDriver &operator=(const FSDriver &); +}; + +#endif // FSDRIVER_H diff --git a/tools/gator/daemon/Fifo.h b/tools/gator/daemon/Fifo.h index 7dd7426132d8..bdda3f549b50 100644 --- a/tools/gator/daemon/Fifo.h +++ b/tools/gator/daemon/Fifo.h @@ -45,4 +45,4 @@ private: Fifo &operator=(const Fifo &); }; -#endif //__FIFO_H__ +#endif //__FIFO_H__ diff --git a/tools/gator/daemon/Hwmon.cpp b/tools/gator/daemon/Hwmon.cpp index 778f30755dfe..e44424743ef0 100644 --- a/tools/gator/daemon/Hwmon.cpp +++ b/tools/gator/daemon/Hwmon.cpp @@ -28,6 +28,7 @@ public: const char *getTitle() const { return title; } bool isDuplicate() const { return duplicate; } const char *getDisplay() const { return display; } + const char *getCounterClass() const { return counter_class; } const char *getUnit() const { return unit; } int getModifier() const { return modifier; } @@ -58,6 +59,7 @@ private: char *label; const char *title; const char *display; + const char *counter_class; const char *unit; int modifier; double previous_value; @@ -87,7 +89,8 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co case SENSORS_FEATURE_IN: title = "Voltage"; input = SENSORS_SUBFEATURE_IN_INPUT; - display = "average"; + display = "maximum"; + counter_class = "absolute"; unit = "V"; modifier = 1000; monotonic = false; @@ -96,6 +99,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co title = "Fan"; input = SENSORS_SUBFEATURE_FAN_INPUT; display = "average"; + counter_class = "absolute"; unit = "RPM"; modifier = 1; monotonic = false; @@ -104,6 +108,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co title = "Temperature"; input = SENSORS_SUBFEATURE_TEMP_INPUT; display = "maximum"; + counter_class = "absolute"; unit = "°C"; modifier = 1000; monotonic = false; @@ -111,7 +116,8 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co case SENSORS_FEATURE_POWER: title = "Power"; input = SENSORS_SUBFEATURE_POWER_INPUT; - display = "average"; + display = "maximum"; + counter_class = "absolute"; unit = "W"; modifier = 1000000; monotonic = false; @@ -120,6 +126,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co title = "Energy"; input = SENSORS_SUBFEATURE_ENERGY_INPUT; display = "accumulate"; + counter_class = "delta"; unit = "J"; modifier = 1000000; monotonic = true; @@ -127,7 +134,8 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co case SENSORS_FEATURE_CURR: title = "Current"; input = SENSORS_SUBFEATURE_CURR_INPUT; - display = "average"; + display = "maximum"; + counter_class = "absolute"; unit = "A"; modifier = 1000; monotonic = false; @@ -136,6 +144,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co title = "Humidity"; input = SENSORS_SUBFEATURE_HUMIDITY_INPUT; display = "average"; + counter_class = "absolute"; unit = "%"; modifier = 1000; monotonic = false; @@ -311,6 +320,7 @@ void Hwmon::writeEvents(mxml_node_t *root) const { mxmlElementSetAttr(node, "name", counter->getLabel()); } mxmlElementSetAttr(node, "display", counter->getDisplay()); + mxmlElementSetAttr(node, "class", counter->getCounterClass()); mxmlElementSetAttr(node, "units", counter->getUnit()); if (counter->getModifier() != 1) { mxmlElementSetAttrf(node, "modifier", "%d", counter->getModifier()); diff --git a/tools/gator/daemon/KMod.cpp b/tools/gator/daemon/KMod.cpp index 9300002f3fb2..73e123d2f14e 100644 --- a/tools/gator/daemon/KMod.cpp +++ b/tools/gator/daemon/KMod.cpp @@ -58,10 +58,15 @@ void KMod::setupCounter(Counter &counter) { return; } + int value = 0; snprintf(text, sizeof(text), "%s/key", base); - int key = 0; - DriverSource::readIntDriver(text, &key); - counter.setKey(key); + DriverSource::readIntDriver(text, &value); + counter.setKey(value); + + snprintf(text, sizeof(text), "%s/cores", base); + if (DriverSource::readIntDriver(text, &value) == 0) { + counter.setCores(value); + } snprintf(text, sizeof(text), "%s/event", base); DriverSource::writeDriver(text, counter.getEvent()); diff --git a/tools/gator/daemon/LocalCapture.h b/tools/gator/daemon/LocalCapture.h index aadeccecf0cc..b1e7219795cf 100644 --- a/tools/gator/daemon/LocalCapture.h +++ b/tools/gator/daemon/LocalCapture.h @@ -23,4 +23,4 @@ private: int removeDirAndAllContents(char* path); }; -#endif //__LOCAL_CAPTURE_H__ +#endif //__LOCAL_CAPTURE_H__ diff --git a/tools/gator/daemon/Logging.h b/tools/gator/daemon/Logging.h index 6ae328046989..4934bb079754 100644 --- a/tools/gator/daemon/Logging.h +++ b/tools/gator/daemon/Logging.h @@ -33,4 +33,4 @@ extern Logging* logg; extern void handleException() __attribute__ ((noreturn)); -#endif //__LOGGING_H__ +#endif //__LOGGING_H__ diff --git a/tools/gator/daemon/Makefile b/tools/gator/daemon/Makefile index 24ee94045470..2ed49fdb688b 100644 --- a/tools/gator/daemon/Makefile +++ b/tools/gator/daemon/Makefile @@ -8,14 +8,14 @@ # targets run 'make SOFTFLOAT=1 SYSROOT=/path/to/sysroot', see # README_Streamline.txt for more details -CPP = $(CROSS_COMPILE)g++ -GCC = $(CROSS_COMPILE)gcc +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ # -mthumb-interwork is required for interworking to ARM or Thumb stdlibc -CFLAGS += -mthumb-interwork +CPPFLAGS += -mthumb-interwork ifeq ($(SOFTFLOAT),1) - CFLAGS += -marm -march=armv4t -mfloat-abi=soft + CPPFLAGS += -marm -march=armv4t -mfloat-abi=soft LDFLAGS += -marm -march=armv4t -mfloat-abi=soft endif ifneq ($(SYSROOT),) diff --git a/tools/gator/daemon/Makefile_aarch64 b/tools/gator/daemon/Makefile_aarch64 index 10b4b4a71ab1..efd1fa002182 100644 --- a/tools/gator/daemon/Makefile_aarch64 +++ b/tools/gator/daemon/Makefile_aarch64 @@ -4,12 +4,9 @@ # # Uncomment and define CROSS_COMPILE if it is not already defined -# CROSS_COMPILE=/path/to/cross-compiler/arm-linux-gnueabihf- -# NOTE: This toolchain uses the hardfloat abi by default. For non-hardfloat -# targets it is necessary to add options -# '-marm -march=armv4t -mfloat-abi=soft'. +# CROSS_COMPILE=/path/to/cross-compiler/aarch64-linux-gnu- -CPP = $(CROSS_COMPILE)g++ -GCC = $(CROSS_COMPILE)gcc +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ include common.mk diff --git a/tools/gator/daemon/MaliVideoDriver.cpp b/tools/gator/daemon/MaliVideoDriver.cpp new file mode 100644 index 000000000000..18b413b01a37 --- /dev/null +++ b/tools/gator/daemon/MaliVideoDriver.cpp @@ -0,0 +1,253 @@ +/** + * Copyright (C) ARM Limited 2014. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "MaliVideoDriver.h" + +#include + +#include "Buffer.h" +#include "Counter.h" +#include "Logging.h" +#include "SessionData.h" + +// From instr/src/mve_instr_comm_protocol.h +typedef enum mve_instr_configuration_type { + MVE_INSTR_RAW = 1 << 0, + MVE_INSTR_COUNTERS = 1 << 1, + MVE_INSTR_EVENTS = 1 << 2, + MVE_INSTR_ACTIVITIES = 1 << 3, + + // Raw always pushed regardless + MVE_INSTR_PULL = 1 << 12, + // Raw always unpacked regardless + MVE_INSTR_PACKED_COMM = 1 << 13, + // Don’t send ACKt response + MVE_INSTR_NO_AUTO_ACK = 1 << 14, +} mve_instr_configuration_type_t; + +static const char COUNTER[] = "ARM_Mali-V500_cnt"; +static const char EVENT[] = "ARM_Mali-V500_evn"; +static const char ACTIVITY[] = "ARM_Mali-V500_act"; + +class MaliVideoCounter { +public: + MaliVideoCounter(MaliVideoCounter *next, const char *name, const MaliVideoCounterType type, const int id) : mNext(next), mName(name), mType(type), mId(id), mKey(getEventKey()), mEnabled(false) { + } + + ~MaliVideoCounter() { + delete mName; + } + + MaliVideoCounter *getNext() const { return mNext; } + const char *getName() const { return mName; } + MaliVideoCounterType getType() const { return mType; } + int getId() const { return mId; } + int getKey() const { return mKey; } + bool isEnabled() const { return mEnabled; } + void setEnabled(const bool enabled) { mEnabled = enabled; } + +private: + MaliVideoCounter *const mNext; + const char *const mName; + const MaliVideoCounterType mType; + // Mali Video id + const int mId; + // Streamline key + const int mKey; + bool mEnabled; +}; + +MaliVideoDriver::MaliVideoDriver() : mCounters(NULL), mActivityCount(0) { +} + +MaliVideoDriver::~MaliVideoDriver() { + while (mCounters != NULL) { + MaliVideoCounter *counter = mCounters; + mCounters = counter->getNext(); + delete counter; + } +} + +void MaliVideoDriver::setup(mxml_node_t *const xml) { + // hwmon does not currently work with perf + if (gSessionData->perf.isSetup()) { + return; + } + + mxml_node_t *node = xml; + while (true) { + node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND); + if (node == NULL) { + break; + } + const char *counter = mxmlElementGetAttr(node, "counter"); + if (counter == NULL) { + // Ignore + } else if (strncmp(counter, COUNTER, sizeof(COUNTER) - 1) == 0) { + const int i = strtol(counter + sizeof(COUNTER) - 1, NULL, 10); + mCounters = new MaliVideoCounter(mCounters, strdup(counter), MVCT_COUNTER, i); + } else if (strncmp(counter, EVENT, sizeof(EVENT) - 1) == 0) { + const int i = strtol(counter + sizeof(EVENT) - 1, NULL, 10); + mCounters = new MaliVideoCounter(mCounters, strdup(counter), MVCT_EVENT, i); + } else if (strcmp(counter, ACTIVITY) == 0) { + mCounters = new MaliVideoCounter(mCounters, strdup(ACTIVITY), MVCT_ACTIVITY, 0); + mActivityCount = 0; + while (true) { + char buf[32]; + snprintf(buf, sizeof(buf), "activity%i", mActivityCount + 1); + if (mxmlElementGetAttr(node, buf) == NULL) { + break; + } + ++mActivityCount; + } + } + } +} + +MaliVideoCounter *MaliVideoDriver::findCounter(const Counter &counter) const { + for (MaliVideoCounter *maliVideoCounter = mCounters; maliVideoCounter != NULL; maliVideoCounter = maliVideoCounter->getNext()) { + if (strcmp(maliVideoCounter->getName(), counter.getType()) == 0) { + return maliVideoCounter; + } + } + + return NULL; +} + +bool MaliVideoDriver::claimCounter(const Counter &counter) const { + return findCounter(counter) != NULL; +} + +bool MaliVideoDriver::countersEnabled() const { + for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { + if (counter->isEnabled()) { + return true; + } + } + return false; +} + +void MaliVideoDriver::resetCounters() { + for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { + counter->setEnabled(false); + } +} + +void MaliVideoDriver::setupCounter(Counter &counter) { + MaliVideoCounter *const maliVideoCounter = findCounter(counter); + if (maliVideoCounter == NULL) { + counter.setEnabled(false); + return; + } + maliVideoCounter->setEnabled(true); + counter.setKey(maliVideoCounter->getKey()); +} + +int MaliVideoDriver::writeCounters(mxml_node_t *root) const { + if (access("/dev/mv500", F_OK) != 0) { + return 0; + } + + int count = 0; + for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { + mxml_node_t *node = mxmlNewElement(root, "counter"); + mxmlElementSetAttr(node, "name", counter->getName()); + ++count; + } + + return count; +} + +void MaliVideoDriver::marshalEnable(const MaliVideoCounterType type, char *const buf, const size_t bufsize, int &pos) { + // size + int numEnabled = 0; + for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { + if (counter->isEnabled() && (counter->getType() == type)) { + ++numEnabled; + } + } + Buffer::packInt(buf, bufsize, pos, numEnabled*sizeof(uint32_t)); + for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { + if (counter->isEnabled() && (counter->getType() == type)) { + Buffer::packInt(buf, bufsize, pos, counter->getId()); + } + } +} + +bool MaliVideoDriver::start(const int mveUds) { + char buf[256]; + int pos = 0; + + // code - MVE_INSTR_STARTUP + buf[pos++] = 'C'; + buf[pos++] = 'L'; + buf[pos++] = 'N'; + buf[pos++] = 'T'; + // size + Buffer::packInt(buf, sizeof(buf), pos, sizeof(uint32_t)); + // client_version_number + Buffer::packInt(buf, sizeof(buf), pos, 1); + + // code - MVE_INSTR_CONFIGURE + buf[pos++] = 'C'; + buf[pos++] = 'N'; + buf[pos++] = 'F'; + buf[pos++] = 'G'; + // size + Buffer::packInt(buf, sizeof(buf), pos, 5*sizeof(uint32_t)); + // configuration + Buffer::packInt(buf, sizeof(buf), pos, MVE_INSTR_COUNTERS | MVE_INSTR_EVENTS | MVE_INSTR_ACTIVITIES | MVE_INSTR_PACKED_COMM); + // communication_protocol_version + Buffer::packInt(buf, sizeof(buf), pos, 1); + // data_protocol_version + Buffer::packInt(buf, sizeof(buf), pos, 1); + // sample_rate - convert samples/second to ms/sample + Buffer::packInt(buf, sizeof(buf), pos, 1000/gSessionData->mSampleRate); + // live_rate - convert ns/flush to ms/flush + Buffer::packInt(buf, sizeof(buf), pos, gSessionData->mLiveRate/1000000); + + // code - MVE_INSTR_ENABLE_COUNTERS + buf[pos++] = 'C'; + buf[pos++] = 'F'; + buf[pos++] = 'G'; + buf[pos++] = 'c'; + marshalEnable(MVCT_COUNTER, buf, sizeof(buf), pos); + + // code - MVE_INSTR_ENABLE_EVENTS + buf[pos++] = 'C'; + buf[pos++] = 'F'; + buf[pos++] = 'G'; + buf[pos++] = 'e'; + marshalEnable(MVCT_EVENT, buf, sizeof(buf), pos); + + /* + // code - MVE_INSTR_ENABLE_ACTIVITIES + buf[pos++] = 'C'; + buf[pos++] = 'F'; + buf[pos++] = 'G'; + buf[pos++] = 'a'; + // size + Buffer::packInt(buf, sizeof(buf), pos, mActivityCount*sizeof(uint32_t)); + for (int i = 0; i < mActivityCount; ++i) { + // activity_id + Buffer::packInt(buf, sizeof(buf), pos, i); + } + */ + + int written = 0; + while (written < pos) { + size_t bytes = ::write(mveUds, buf + written, pos - written); + if (bytes <= 0) { + logg->logMessage("%s(%s:%i): write failed", __FUNCTION__, __FILE__, __LINE__); + return false; + } + written += bytes; + } + + return true; +} diff --git a/tools/gator/daemon/MaliVideoDriver.h b/tools/gator/daemon/MaliVideoDriver.h new file mode 100644 index 000000000000..00cb80889a74 --- /dev/null +++ b/tools/gator/daemon/MaliVideoDriver.h @@ -0,0 +1,50 @@ +/** + * Copyright (C) ARM Limited 2014. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef MALIVIDEODRIVER_H +#define MALIVIDEODRIVER_H + +#include "Driver.h" + +class MaliVideoCounter; + +enum MaliVideoCounterType { + MVCT_COUNTER, + MVCT_EVENT, + MVCT_ACTIVITY, +}; + +class MaliVideoDriver : public Driver { +public: + MaliVideoDriver(); + ~MaliVideoDriver(); + + void setup(mxml_node_t *const xml); + + bool claimCounter(const Counter &counter) const; + bool countersEnabled() const; + void resetCounters(); + void setupCounter(Counter &counter); + + int writeCounters(mxml_node_t *root) const; + + bool start(const int mveUds); + +private: + MaliVideoCounter *findCounter(const Counter &counter) const; + void marshalEnable(const MaliVideoCounterType type, char *const buf, const size_t bufsize, int &pos); + + MaliVideoCounter *mCounters; + int mActivityCount; + + // Intentionally unimplemented + MaliVideoDriver(const MaliVideoDriver &); + MaliVideoDriver &operator=(const MaliVideoDriver &); +}; + +#endif // MALIVIDEODRIVER_H diff --git a/tools/gator/daemon/Monitor.cpp b/tools/gator/daemon/Monitor.cpp index 90d5c47706c7..b34a15f0eb0c 100644 --- a/tools/gator/daemon/Monitor.cpp +++ b/tools/gator/daemon/Monitor.cpp @@ -18,8 +18,15 @@ Monitor::Monitor() : mFd(-1) { } Monitor::~Monitor() { - if (mFd >= -1) { - close(mFd); + if (mFd >= 0) { + ::close(mFd); + } +} + +void Monitor::close() { + if (mFd >= 0) { + ::close(mFd); + mFd = -1; } } diff --git a/tools/gator/daemon/Monitor.h b/tools/gator/daemon/Monitor.h index 6e268b6e1bed..7194e0e4ca50 100644 --- a/tools/gator/daemon/Monitor.h +++ b/tools/gator/daemon/Monitor.h @@ -16,6 +16,7 @@ public: Monitor(); ~Monitor(); + void close(); bool init(); bool add(const int fd); int wait(struct epoll_event *const events, int maxevents, int timeout); diff --git a/tools/gator/daemon/OlySocket.cpp b/tools/gator/daemon/OlySocket.cpp index 26e4768f3934..28774e36e510 100644 --- a/tools/gator/daemon/OlySocket.cpp +++ b/tools/gator/daemon/OlySocket.cpp @@ -9,6 +9,7 @@ #include "OlySocket.h" #include +#include #ifdef WIN32 #include #include @@ -43,16 +44,18 @@ OlyServerSocket::OlyServerSocket(int port) { createServerSocket(port); } -OlySocket::OlySocket(int port, const char* host) { - createClientSocket(host, port); -} - OlySocket::OlySocket(int socketID) : mSocketID(socketID) { } #ifndef WIN32 -OlyServerSocket::OlyServerSocket(const char* path) { +#define MIN(A, B) ({ \ + const __typeof__(A) __a = A; \ + const __typeof__(B) __b = B; \ + __a > __b ? __b : __a; \ +}) + +OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize) { // Create socket mFDServer = socket(PF_UNIX, SOCK_STREAM, 0); if (mFDServer < 0) { @@ -60,13 +63,11 @@ OlyServerSocket::OlyServerSocket(const char* path) { handleException(); } - unlink(path); - // Create sockaddr_in structure, ensuring non-populated fields are zero struct sockaddr_un sockaddr; memset((void*)&sockaddr, 0, sizeof(sockaddr)); sockaddr.sun_family = AF_UNIX; - strncpy(sockaddr.sun_path, path, sizeof(sockaddr.sun_path) - 1); + memcpy(sockaddr.sun_path, path, MIN(pathSize, sizeof(sockaddr.sun_path))); sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0'; // Bind the socket to an address @@ -82,24 +83,25 @@ OlyServerSocket::OlyServerSocket(const char* path) { } } -OlySocket::OlySocket(const char* path) { - mSocketID = socket(PF_UNIX, SOCK_STREAM, 0); - if (mSocketID < 0) { - return; +int OlySocket::connect(const char* path, const size_t pathSize) { + int fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + return -1; } // Create sockaddr_in structure, ensuring non-populated fields are zero struct sockaddr_un sockaddr; memset((void*)&sockaddr, 0, sizeof(sockaddr)); sockaddr.sun_family = AF_UNIX; - strncpy(sockaddr.sun_path, path, sizeof(sockaddr.sun_path) - 1); + memcpy(sockaddr.sun_path, path, MIN(pathSize, sizeof(sockaddr.sun_path))); sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0'; - if (connect(mSocketID, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) { - close(mSocketID); - mSocketID = -1; - return; + if (::connect(fd, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) { + close(fd); + return -1; } + + return fd; } #endif @@ -137,47 +139,6 @@ void OlyServerSocket::closeServerSocket() { mFDServer = 0; } -void OlySocket::createClientSocket(const char* hostname, int portno) { -#ifdef WIN32 - // TODO: Implement for Windows -#else - char buf[32]; - struct addrinfo hints, *res, *res0; - - snprintf(buf, sizeof(buf), "%d", portno); - mSocketID = -1; - memset((void*)&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - if (getaddrinfo(hostname, buf, &hints, &res0)) { - logg->logError(__FILE__, __LINE__, "Client socket failed to get address info for %s", hostname); - handleException(); - } - for (res=res0; res!=NULL; res = res->ai_next) { - if ( res->ai_family != PF_INET || res->ai_socktype != SOCK_STREAM ) { - continue; - } - mSocketID = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (mSocketID < 0) { - continue; - } - if (connect(mSocketID, res->ai_addr, res->ai_addrlen) < 0) { - close(mSocketID); - mSocketID = -1; - } - if (mSocketID > 0) { - break; - } - } - freeaddrinfo(res0); - if (mSocketID <= 0) { - logg->logError(__FILE__, __LINE__, "Could not connect to client socket. Ensure ARM Streamline is running."); - handleException(); - } -#endif -} - void OlyServerSocket::createServerSocket(int port) { int family = AF_INET6; diff --git a/tools/gator/daemon/OlySocket.h b/tools/gator/daemon/OlySocket.h index eab786b304bf..20c67cc695e1 100644 --- a/tools/gator/daemon/OlySocket.h +++ b/tools/gator/daemon/OlySocket.h @@ -9,13 +9,15 @@ #ifndef __OLY_SOCKET_H__ #define __OLY_SOCKET_H__ +#include + class OlySocket { public: - OlySocket(int port, const char* hostname); - OlySocket(int socketID); #ifndef WIN32 - OlySocket(const char* path); + static int connect(const char* path, const size_t pathSize); #endif + + OlySocket(int socketID); ~OlySocket(); void closeSocket(); @@ -29,21 +31,21 @@ public: private: int mSocketID; - - void createClientSocket(const char* hostname, int port); }; class OlyServerSocket { public: OlyServerSocket(int port); #ifndef WIN32 - OlyServerSocket(const char* path); + OlyServerSocket(const char* path, const size_t pathSize); #endif ~OlyServerSocket(); int acceptConnection(); void closeServerSocket(); + int getFd() { return mFDServer; } + private: int mFDServer; diff --git a/tools/gator/daemon/PerfDriver.cpp b/tools/gator/daemon/PerfDriver.cpp index 8e25c22f6798..ac97a077d266 100644 --- a/tools/gator/daemon/PerfDriver.cpp +++ b/tools/gator/daemon/PerfDriver.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "Buffer.h" #include "Config.h" @@ -30,7 +31,7 @@ struct gator_cpu { const int cpuid; // Human readable name - const char core_name[32]; + const char *const core_name; // gatorfs event and Perf PMU name const char *const pmnc_name; const int pmnc_counters; @@ -62,9 +63,20 @@ static const struct gator_cpu gator_cpus[] = { static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-"; static const char NEW_PMU_PREFIX[] = "ARMv7_Cortex_"; +struct uncore_counter { + // gatorfs event and Perf PMU name + const char *const name; + const int count; +}; + +static const struct uncore_counter uncore_counters[] = { + { "CCI_400", 4 }, + { "CCI_400-r1", 4 }, +}; + class PerfCounter { public: - PerfCounter(PerfCounter *next, const char *name, uint32_t type, uint64_t config) : mNext(next), mName(name), mType(type), mCount(0), mKey(getEventKey()), mConfig(config), mEnabled(false) {} + PerfCounter(PerfCounter *next, const char *name, uint32_t type, uint64_t config, bool perCpu) : mNext(next), mName(name), mType(type), mCount(0), mKey(getEventKey()), mConfig(config), mEnabled(false), mPerCpu(perCpu) {} ~PerfCounter() { delete [] mName; } @@ -79,6 +91,7 @@ public: void setConfig(const uint64_t config) { mConfig = config; } bool isEnabled() const { return mEnabled; } void setEnabled(const bool enabled) { mEnabled = enabled; } + bool isPerCpu() const { return mPerCpu; } private: PerfCounter *const mNext; @@ -87,10 +100,11 @@ private: int mCount; const int mKey; uint64_t mConfig; - bool mEnabled; + int mEnabled : 1, + mPerCpu : 1; }; -PerfDriver::PerfDriver() : mCounters(NULL), mIsSetup(false) { +PerfDriver::PerfDriver() : mCounters(NULL), mIsSetup(false), mLegacySupport(false) { } PerfDriver::~PerfDriver() { @@ -105,13 +119,27 @@ void PerfDriver::addCpuCounters(const char *const counterName, const int type, c int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1; char *name = new char[len]; snprintf(name, len, "%s_ccnt", counterName); - mCounters = new PerfCounter(mCounters, name, type, -1); + mCounters = new PerfCounter(mCounters, name, type, -1, true); for (int j = 0; j < numCounters; ++j) { len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1; name = new char[len]; snprintf(name, len, "%s_cnt%d", counterName, j); - mCounters = new PerfCounter(mCounters, name, type, -1); + mCounters = new PerfCounter(mCounters, name, type, -1, true); + } +} + +void PerfDriver::addUncoreCounters(const char *const counterName, const int type, const int numCounters) { + int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1; + char *name = new char[len]; + snprintf(name, len, "%s_ccnt", counterName); + mCounters = new PerfCounter(mCounters, name, type, -1, false); + + for (int j = 0; j < numCounters; ++j) { + len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1; + name = new char[len]; + snprintf(name, len, "%s_cnt%d", counterName, j); + mCounters = new PerfCounter(mCounters, name, type, -1, false); } } @@ -139,10 +167,16 @@ bool PerfDriver::setup() { } } - if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0)) { + if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 4, 0)) { logg->logMessage("%s(%s:%i): Unsupported kernel version", __FUNCTION__, __FILE__, __LINE__); return false; } + mLegacySupport = KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0); + + if (access(EVENTS_PATH, R_OK) != 0) { + logg->logMessage("%s(%s:%i): " EVENTS_PATH " does not exist, is CONFIG_TRACING enabled?", __FUNCTION__, __FILE__, __LINE__); + return false; + } // Add supported PMUs bool foundCpu = false; @@ -174,6 +208,21 @@ bool PerfDriver::setup() { foundCpu = true; addCpuCounters(gator_cpus[i].pmnc_name, type, gator_cpus[i].pmnc_counters); } + + for (int i = 0; i < ARRAY_LENGTH(uncore_counters); ++i) { + if (strcmp(dirent->d_name, uncore_counters[i].name) != 0) { + continue; + } + + int type; + char buf[256]; + snprintf(buf, sizeof(buf), PERF_DEVICES "/%s/type", dirent->d_name); + if (DriverSource::readIntDriver(buf, &type) != 0) { + continue; + } + + addUncoreCounters(uncore_counters[i].name, type, uncore_counters[i].count); + } } closedir(dir); @@ -203,12 +252,12 @@ bool PerfDriver::setup() { id = getTracepointId("irq/softirq_exit", &printb); if (id >= 0) { - mCounters = new PerfCounter(mCounters, "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id); + mCounters = new PerfCounter(mCounters, "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id, true); } id = getTracepointId("irq/irq_handler_exit", &printb); if (id >= 0) { - mCounters = new PerfCounter(mCounters, "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id); + mCounters = new PerfCounter(mCounters, "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id, true); } //Linux_block_rq_wr @@ -218,7 +267,7 @@ bool PerfDriver::setup() { id = getTracepointId(SCHED_SWITCH, &printb); if (id >= 0) { - mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id); + mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, true); } //Linux_meminfo_memused @@ -227,7 +276,7 @@ bool PerfDriver::setup() { //Linux_power_cpu_freq //Linux_power_cpu_idle - mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1); + mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1, false); //Linux_cpu_wait_io @@ -252,15 +301,16 @@ bool PerfDriver::summary(Buffer *const buffer) { } const int64_t timestamp = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec; - if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { - logg->logMessage("%s(%s:%i): clock_gettime failed", __FUNCTION__, __FILE__, __LINE__); - return false; - } - const int64_t uptime = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec; + const int64_t uptime = getTime(); buffer->summary(timestamp, uptime, 0, buf); for (int i = 0; i < gSessionData->mCores; ++i) { + // Don't send information on a cpu we know nothing about + if (gSessionData->mCpuIds[i] == -1) { + continue; + } + int j; for (j = 0; j < ARRAY_LENGTH(gator_cpus); ++j) { if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) { @@ -270,7 +320,11 @@ bool PerfDriver::summary(Buffer *const buffer) { if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) { buffer->coreName(i, gSessionData->mCpuIds[i], gator_cpus[j].core_name); } else { - snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[i]); + if (gSessionData->mCpuIds[i] == -1) { + snprintf(buf, sizeof(buf), "Unknown"); + } else { + snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[i]); + } buffer->coreName(i, gSessionData->mCpuIds[i], buf); } } @@ -326,10 +380,10 @@ int PerfDriver::writeCounters(mxml_node_t *root) const { return count; } -bool PerfDriver::enable(PerfGroup *group, Buffer *const buffer) const { +bool PerfDriver::enable(PerfGroup *const group, Buffer *const buffer) const { for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { if (counter->isEnabled() && (counter->getType() != TYPE_DERIVED)) { - if (!group->add(buffer, counter->getKey(), counter->getType(), counter->getConfig(), counter->getCount(), 0, 0)) { + if (!group->add(buffer, counter->getKey(), counter->getType(), counter->getConfig(), counter->getCount(), counter->getCount() > 0 ? PERF_SAMPLE_TID | PERF_SAMPLE_IP : 0, counter->isPerCpu() ? PERF_GROUP_PER_CPU : 0)) { logg->logMessage("%s(%s:%i): PerfGroup::add failed", __FUNCTION__, __FILE__, __LINE__); return false; } diff --git a/tools/gator/daemon/PerfDriver.h b/tools/gator/daemon/PerfDriver.h index 3181b74f5570..2cae575a7059 100644 --- a/tools/gator/daemon/PerfDriver.h +++ b/tools/gator/daemon/PerfDriver.h @@ -27,6 +27,8 @@ public: PerfDriver(); ~PerfDriver(); + bool getLegacySupport() const { return mLegacySupport; } + bool setup(); bool summary(Buffer *const buffer); bool isSetup() const { return mIsSetup; } @@ -37,16 +39,18 @@ public: int writeCounters(mxml_node_t *root) const; - bool enable(PerfGroup *group, Buffer *const buffer) const; + bool enable(PerfGroup *const group, Buffer *const buffer) const; static long long getTracepointId(const char *const name, DynBuf *const printb); private: PerfCounter *findCounter(const Counter &counter) const; void addCpuCounters(const char *const counterName, const int type, const int numCounters); + void addUncoreCounters(const char *const counterName, const int type, const int numCounters); PerfCounter *mCounters; bool mIsSetup; + bool mLegacySupport; // Intentionally undefined PerfDriver(const PerfDriver &); diff --git a/tools/gator/daemon/PerfGroup.cpp b/tools/gator/daemon/PerfGroup.cpp index faf5fcaf15e6..2a0239f7c348 100644 --- a/tools/gator/daemon/PerfGroup.cpp +++ b/tools/gator/daemon/PerfGroup.cpp @@ -23,7 +23,9 @@ #define DEFAULT_PEA_ARGS(pea, additionalSampleType) \ pea.size = sizeof(pea); \ /* Emit time, read_format below, group leader id, and raw tracepoint info */ \ - pea.sample_type = PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_IDENTIFIER | additionalSampleType; \ + pea.sample_type = (gSessionData->perf.getLegacySupport() \ + ? PERF_SAMPLE_TID | PERF_SAMPLE_IP | PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_ID \ + : PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_IDENTIFIER ) | additionalSampleType; \ /* Emit emit value in group format */ \ pea.read_format = PERF_FORMAT_ID | PERF_FORMAT_GROUP; \ /* start out disabled */ \ @@ -39,6 +41,7 @@ static int sys_perf_event_open(struct perf_event_attr *const attr, const pid_t p PerfGroup::PerfGroup(PerfBuffer *const pb) : mPb(pb) { memset(&mAttrs, 0, sizeof(mAttrs)); + memset(&mPerCpu, 0, sizeof(mPerCpu)); memset(&mKeys, -1, sizeof(mKeys)); memset(&mFds, -1, sizeof(mFds)); } @@ -75,6 +78,7 @@ bool PerfGroup::add(Buffer *const buffer, const int key, const __u32 type, const mAttrs[i].freq = (flags & PERF_GROUP_FREQ ? 1 : 0); mAttrs[i].task = (flags & PERF_GROUP_TASK ? 1 : 0); mAttrs[i].sample_id_all = (flags & PERF_GROUP_SAMPLE_ID_ALL ? 1 : 0); + mPerCpu[i] = (flags & PERF_GROUP_PER_CPU); mKeys[i] = key; @@ -91,13 +95,17 @@ bool PerfGroup::prepareCPU(const int cpu) { continue; } + if ((cpu != 0) && !mPerCpu[i]) { + continue; + } + const int offset = i * gSessionData->mCores; if (mFds[cpu + offset] >= 0) { logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__); return false; } - logg->logMessage("%s(%s:%i): perf_event_open cpu: %i type: %lli config: %lli sample: %lli sample_type: %lli", __FUNCTION__, __FILE__, __LINE__, cpu, (long long)mAttrs[i].type, (long long)mAttrs[i].config, (long long)mAttrs[i].sample_period, (long long)mAttrs[i].sample_type); + logg->logMessage("%s(%s:%i): perf_event_open cpu: %i type: %lli config: %lli sample: %lli sample_type: 0x%llx pinned: %i mmap: %i comm: %i freq: %i task: %i sample_id_all: %i", __FUNCTION__, __FILE__, __LINE__, cpu, (long long)mAttrs[i].type, (long long)mAttrs[i].config, (long long)mAttrs[i].sample_period, (long long)mAttrs[i].sample_type, mAttrs[i].pinned, mAttrs[i].mmap, mAttrs[i].comm, mAttrs[i].freq, mAttrs[i].task, mAttrs[i].sample_id_all); mFds[cpu + offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, i == 0 ? -1 : mFds[cpu], i == 0 ? 0 : PERF_FLAG_FD_OUTPUT); if (mFds[cpu + offset] < 0) { logg->logMessage("%s(%s:%i): failed %s", __FUNCTION__, __FILE__, __LINE__, strerror(errno)); @@ -125,7 +133,9 @@ int PerfGroup::onlineCPU(const int cpu, const bool start, Buffer *const buffer, } coreKeys[idCount] = mKeys[i]; - if (ioctl(fd, PERF_EVENT_IOC_ID, &ids[idCount]) != 0) { + if (!gSessionData->perf.getLegacySupport() && ioctl(fd, PERF_EVENT_IOC_ID, &ids[idCount]) != 0 && + // Workaround for running 32-bit gatord on 64-bit systems, kernel patch in the works + ioctl(fd, (PERF_EVENT_IOC_ID & ~IOCSIZE_MASK) | (8 << _IOC_SIZESHIFT), &ids[idCount]) != 0) { logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__); return false; } @@ -137,7 +147,17 @@ int PerfGroup::onlineCPU(const int cpu, const bool start, Buffer *const buffer, return false; } - buffer->keys(idCount, ids, coreKeys); + if (!gSessionData->perf.getLegacySupport()) { + buffer->keys(idCount, ids, coreKeys); + } else { + char buf[1024]; + ssize_t bytes = read(mFds[cpu], buf, sizeof(buf)); + if (bytes < 0) { + logg->logMessage("read failed"); + return false; + } + buffer->keysOld(idCount, coreKeys, bytes, buf); + } if (start) { for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) { diff --git a/tools/gator/daemon/PerfGroup.h b/tools/gator/daemon/PerfGroup.h index af496d41334c..3f1e2bb4d1c8 100644 --- a/tools/gator/daemon/PerfGroup.h +++ b/tools/gator/daemon/PerfGroup.h @@ -24,6 +24,7 @@ enum PerfGroupFlags { PERF_GROUP_FREQ = 1 << 2, PERF_GROUP_TASK = 1 << 3, PERF_GROUP_SAMPLE_ID_ALL = 1 << 4, + PERF_GROUP_PER_CPU = 1 << 5, }; class PerfGroup { @@ -43,6 +44,7 @@ public: private: // +1 for the group leader struct perf_event_attr mAttrs[MAX_PERFORMANCE_COUNTERS + 1]; + bool mPerCpu[MAX_PERFORMANCE_COUNTERS + 1]; int mKeys[MAX_PERFORMANCE_COUNTERS + 1]; int mFds[NR_CPUS * (MAX_PERFORMANCE_COUNTERS + 1)]; PerfBuffer *const mPb; diff --git a/tools/gator/daemon/PerfSource.cpp b/tools/gator/daemon/PerfSource.cpp index 1f1cb1988f00..ecfaa66832bd 100644 --- a/tools/gator/daemon/PerfSource.cpp +++ b/tools/gator/daemon/PerfSource.cpp @@ -37,7 +37,7 @@ static bool sendTracepointFormat(Buffer *const buffer, const char *const name, D return true; } -PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAME_SUMMARY, 1024, senderSem), mBuffer(0, FRAME_PERF_ATTRS, 1024*1024, senderSem), mCountersBuf(), mCountersGroup(&mCountersBuf), mMonitor(), mUEvent(), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false) { +PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAME_SUMMARY, 1024, senderSem), mBuffer(0, FRAME_PERF_ATTRS, 4*1024*1024, senderSem), mCountersBuf(), mCountersGroup(&mCountersBuf), mMonitor(), mUEvent(), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false) { long l = sysconf(_SC_PAGE_SIZE); if (l < 0) { logg->logError(__FILE__, __LINE__, "Unable to obtain the page size"); @@ -74,6 +74,9 @@ bool PerfSource::prepare() { DynBuf b3; long long schedSwitchId; + // Reread cpuinfo since cores may have changed since startup + gSessionData->readCpuInfo(); + if (0 || !mMonitor.init() || !mUEvent.init() @@ -83,14 +86,14 @@ bool PerfSource::prepare() { || !sendTracepointFormat(&mBuffer, SCHED_SWITCH, &printb, &b1) // Only want RAW but not IP on sched_switch and don't want TID on SAMPLE_ID - || !mCountersGroup.add(&mBuffer, 100/**/, PERF_TYPE_TRACEPOINT, schedSwitchId, 1, PERF_SAMPLE_RAW, PERF_GROUP_MMAP | PERF_GROUP_COMM | PERF_GROUP_TASK | PERF_GROUP_SAMPLE_ID_ALL) + || !mCountersGroup.add(&mBuffer, 100/**/, PERF_TYPE_TRACEPOINT, schedSwitchId, 1, PERF_SAMPLE_RAW, PERF_GROUP_MMAP | PERF_GROUP_COMM | PERF_GROUP_TASK | PERF_GROUP_SAMPLE_ID_ALL | PERF_GROUP_PER_CPU) // Only want TID and IP but not RAW on timer - || (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && !mCountersGroup.add(&mBuffer, 99/**/, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP, 0)) + || (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && !mCountersGroup.add(&mBuffer, 99/**/, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP, PERF_GROUP_PER_CPU)) || !gSessionData->perf.enable(&mCountersGroup, &mBuffer) || 0) { - logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.12 or later?", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.4 or later?", __FUNCTION__, __FILE__, __LINE__); return false; } @@ -134,7 +137,7 @@ bool PerfSource::prepare() { return false; } - if (!readProc(&mBuffer, &printb, &b1, &b2, &b3)) { + if (!readProc(&mBuffer, true, &printb, &b1, &b2, &b3)) { logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__); return false; } @@ -260,6 +263,7 @@ bool PerfSource::isDone () { void PerfSource::write (Sender *sender) { if (!mSummary.isDone()) { mSummary.write(sender); + gSessionData->mSentSummary = true; } if (!mBuffer.isDone()) { mBuffer.write(sender); diff --git a/tools/gator/daemon/Proc.cpp b/tools/gator/daemon/Proc.cpp index e0b9e2259cf9..9f01770d6609 100644 --- a/tools/gator/daemon/Proc.cpp +++ b/tools/gator/daemon/Proc.cpp @@ -57,14 +57,57 @@ static bool readProcStat(ProcStat *const ps, const char *const pathname, DynBuf return true; } -static bool readProcTask(Buffer *const buffer, const int pid, const char *const image, DynBuf *const printb, DynBuf *const b) { +static const char *readProcExe(DynBuf *const printb, const int pid, const int tid, DynBuf *const b) { + if (tid == -1 ? !printb->printf("/proc/%i/exe", pid) + : !printb->printf("/proc/%i/task/%i/exe", pid, tid)) { + logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); + return NULL; + } + + const int err = b->readlink(printb->getBuf()); + const char *image; + if (err == 0) { + image = strrchr(b->getBuf(), '/'); + if (image == NULL) { + image = b->getBuf(); + } else { + ++image; + } + } else if (err == -ENOENT) { + // readlink /proc/[pid]/exe returns ENOENT for kernel threads + image = "\0"; + } else { + logg->logMessage("%s(%s:%i): DynBuf::readlink failed", __FUNCTION__, __FILE__, __LINE__); + return NULL; + } + + // Android apps are run by app_process but the cmdline is changed to reference the actual app name + if (strcmp(image, "app_process") != 0) { + return image; + } + + if (tid == -1 ? !printb->printf("/proc/%i/cmdline", pid) + : !printb->printf("/proc/%i/task/%i/cmdline", pid, tid)) { + logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); + return NULL; + } + + if (!b->read(printb->getBuf())) { + logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the thread exited", __FUNCTION__, __FILE__, __LINE__); + return NULL; + } + + return b->getBuf(); +} + +static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) { bool result = false; - if (!b->printf("/proc/%i/task", pid)) { + if (!b1->printf("/proc/%i/task", pid)) { logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); return result; } - DIR *task = opendir(b->getBuf()); + DIR *task = opendir(b1->getBuf()); if (task == NULL) { logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__); return result; @@ -84,11 +127,17 @@ static bool readProcTask(Buffer *const buffer, const int pid, const char *const goto fail; } ProcStat ps; - if (!readProcStat(&ps, printb->getBuf(), b)) { + if (!readProcStat(&ps, printb->getBuf(), b1)) { logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__); goto fail; } + const char *const image = readProcExe(printb, pid, tid, b2); + if (image == NULL) { + logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__); + goto fail; + } + buffer->comm(pid, tid, image, ps.comm); } @@ -100,7 +149,7 @@ static bool readProcTask(Buffer *const buffer, const int pid, const char *const return result; } -bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) { +bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) { bool result = false; DIR *proc = opendir("/proc"); @@ -128,42 +177,29 @@ bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynB goto fail; } - if (!printb->printf("/proc/%i/exe", pid)) { - logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); - goto fail; - } - const int err = b1->readlink(printb->getBuf()); - const char *image; - if (err == 0) { - image = strrchr(b1->getBuf(), '/'); - if (image == NULL) { - image = b1->getBuf(); - } else { - ++image; + if (sendMaps) { + if (!printb->printf("/proc/%i/maps", pid)) { + logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); + goto fail; + } + if (!b2->read(printb->getBuf())) { + logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__); + // This is not a fatal error - the process just doesn't exist any more + continue; } - } else if (err == -ENOENT) { - // readlink /proc/[pid]/exe returns ENOENT for kernel threads - image = "\0"; - } else { - logg->logMessage("%s(%s:%i): DynBuf::readlink failed", __FUNCTION__, __FILE__, __LINE__); - goto fail; - } - if (!printb->printf("/proc/%i/maps", pid)) { - logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); - goto fail; + buffer->maps(pid, pid, b2->getBuf()); } - if (!b2->read(printb->getBuf())) { - logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__); - // This is not a fatal error - the process just doesn't exist any more - continue; - } - - buffer->maps(pid, pid, b2->getBuf()); if (ps.numThreads <= 1) { + const char *const image = readProcExe(printb, pid, -1, b1); + if (image == NULL) { + logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__); + goto fail; + } + buffer->comm(pid, pid, image, ps.comm); } else { - if (!readProcTask(buffer, pid, image, printb, b3)) { + if (!readProcTask(buffer, pid, printb, b1, b3)) { logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__); goto fail; } diff --git a/tools/gator/daemon/Proc.h b/tools/gator/daemon/Proc.h index 057b6109848a..31c2eecb7aeb 100644 --- a/tools/gator/daemon/Proc.h +++ b/tools/gator/daemon/Proc.h @@ -12,6 +12,6 @@ class Buffer; class DynBuf; -bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3); +bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3); #endif // PROC_H diff --git a/tools/gator/daemon/Sender.h b/tools/gator/daemon/Sender.h index 4c359dba82f8..33b6cc3c5d8d 100644 --- a/tools/gator/daemon/Sender.h +++ b/tools/gator/daemon/Sender.h @@ -39,4 +39,4 @@ private: Sender &operator=(const Sender &); }; -#endif //__SENDER_H__ +#endif //__SENDER_H__ diff --git a/tools/gator/daemon/SessionData.cpp b/tools/gator/daemon/SessionData.cpp index c169299af872..14d995fc39fa 100644 --- a/tools/gator/daemon/SessionData.cpp +++ b/tools/gator/daemon/SessionData.cpp @@ -9,6 +9,7 @@ #include "SessionData.h" #include +#include #include "SessionXML.h" #include "Logging.h" @@ -27,6 +28,15 @@ void SessionData::initialize() { mSessionIsActive = false; mLocalCapture = false; mOneShot = false; + mSentSummary = false; + const size_t cpuIdSize = sizeof(int)*NR_CPUS; + // Share mCpuIds across all instances of gatord + mCpuIds = (int *)mmap(NULL, cpuIdSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (mCpuIds == MAP_FAILED) { + logg->logError(__FILE__, __LINE__, "Unable to mmap shared memory for cpuids"); + handleException(); + } + memset(mCpuIds, -1, cpuIdSize); readCpuInfo(); mConfigurationXMLPath = NULL; mSessionXMLPath = NULL; @@ -91,10 +101,9 @@ void SessionData::parseSessionXML(char* xmlString) { void SessionData::readCpuInfo() { char temp[256]; // arbitrarily large amount strcpy(mCoreName, "unknown"); - memset(&mCpuIds, -1, sizeof(mCpuIds)); mMaxCpuId = -1; - FILE* f = fopen("/proc/cpuinfo", "r"); + FILE* f = fopen("/proc/cpuinfo", "r"); if (f == NULL) { logg->logMessage("Error opening /proc/cpuinfo\n" "The core name in the captured xml file will be 'unknown'."); @@ -102,10 +111,18 @@ void SessionData::readCpuInfo() { } bool foundCoreName = false; - int processor = 0; + int processor = -1; while (fgets(temp, sizeof(temp), f)) { - if (strlen(temp) > 0) { - temp[strlen(temp) - 1] = 0; // Replace the line feed with a null + const size_t len = strlen(temp); + + if (len == 1) { + // New section, clear the processor. Streamline will not know the cpus if the pre Linux 3.8 format of cpuinfo is encountered but also that no incorrect information will be transmitted. + processor = -1; + continue; + } + + if (len > 0) { + temp[len - 1] = '\0'; // Replace the line feed with a null } const bool foundHardware = strstr(temp, "Hardware") != 0; @@ -127,10 +144,15 @@ void SessionData::readCpuInfo() { } if (foundCPUPart) { - mCpuIds[processor] = strtol(position, NULL, 0); + const int cpuId = strtol(position, NULL, 0); // If this does not have the full topology in /proc/cpuinfo, mCpuIds[0] may not have the 1 CPU part emitted - this guarantees it's in mMaxCpuId - if (mCpuIds[processor] > mMaxCpuId) { - mMaxCpuId = mCpuIds[processor]; + if (cpuId > mMaxCpuId) { + mMaxCpuId = cpuId; + } + if (processor >= NR_CPUS) { + logg->logMessage("Too many processors, please increase NR_CPUS"); + } else if (processor >= 0) { + mCpuIds[processor] = cpuId; } } @@ -142,10 +164,23 @@ void SessionData::readCpuInfo() { if (!foundCoreName) { logg->logMessage("Could not determine core name from /proc/cpuinfo\n" - "The core name in the captured xml file will be 'unknown'."); + "The core name in the captured xml file will be 'unknown'."); } fclose(f); - } +} + +uint64_t getTime() { + struct timespec ts; +#ifndef CLOCK_MONOTONIC_RAW + // Android doesn't have this defined but it was added in Linux 2.6.28 +#define CLOCK_MONOTONIC_RAW 4 +#endif + if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) { + logg->logError(__FILE__, __LINE__, "Failed to get uptime"); + handleException(); + } + return (NS_PER_S*ts.tv_sec + ts.tv_nsec); +} int getEventKey() { // key 0 is reserved as a timestamp diff --git a/tools/gator/daemon/SessionData.h b/tools/gator/daemon/SessionData.h index ea34240e2df7..835082d86c4b 100644 --- a/tools/gator/daemon/SessionData.h +++ b/tools/gator/daemon/SessionData.h @@ -13,12 +13,16 @@ #include "Config.h" #include "Counter.h" +#include "FSDriver.h" #include "Hwmon.h" +#include "MaliVideoDriver.h" #include "PerfDriver.h" -#define PROTOCOL_VERSION 18 +#define PROTOCOL_VERSION 19 #define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions +#define NS_PER_S ((uint64_t)1000000000) + struct ImageLinkList { char* path; struct ImageLinkList *next; @@ -32,9 +36,12 @@ public: ~SessionData(); void initialize(); void parseSessionXML(char* xmlString); + void readCpuInfo(); Hwmon hwmon; + FSDriver fsDriver; PerfDriver perf; + MaliVideoDriver maliVideo; char mCoreName[MAX_STRING_LEN]; struct ImageLinkList *mImages; @@ -49,7 +56,8 @@ public: bool mLocalCapture; bool mOneShot; // halt processing of the driver data until profiling is complete or the buffer is filled bool mIsEBS; - + bool mSentSummary; + int mBacktraceDepth; int mTotalBufferSize; // number of MB to use for the entire collection buffer int mSampleRate; @@ -57,7 +65,7 @@ public: int mDuration; int mCores; int mPageSize; - int mCpuIds[NR_CPUS]; + int *mCpuIds; int mMaxCpuId; // PMU Counters @@ -65,8 +73,6 @@ public: Counter mCounters[MAX_PERFORMANCE_COUNTERS]; private: - void readCpuInfo(); - // Intentionally unimplemented SessionData(const SessionData &); SessionData &operator=(const SessionData &); @@ -74,6 +80,7 @@ private: extern SessionData* gSessionData; +uint64_t getTime(); int getEventKey(); #endif // SESSION_DATA_H diff --git a/tools/gator/daemon/SessionXML.cpp b/tools/gator/daemon/SessionXML.cpp index 55b2f9280709..8cdc9409ca21 100644 --- a/tools/gator/daemon/SessionXML.cpp +++ b/tools/gator/daemon/SessionXML.cpp @@ -17,15 +17,15 @@ #include "SessionData.h" static const char* TAG_SESSION = "session"; -static const char* TAG_IMAGE = "image"; +static const char* TAG_IMAGE = "image"; -static const char* ATTR_VERSION = "version"; +static const char* ATTR_VERSION = "version"; static const char* ATTR_CALL_STACK_UNWINDING = "call_stack_unwinding"; static const char* ATTR_BUFFER_MODE = "buffer_mode"; -static const char* ATTR_SAMPLE_RATE = "sample_rate"; +static const char* ATTR_SAMPLE_RATE = "sample_rate"; static const char* ATTR_DURATION = "duration"; static const char* ATTR_PATH = "path"; -static const char* ATTR_LIVE_RATE = "live_rate"; +static const char* ATTR_LIVE_RATE = "live_rate"; SessionXML::SessionXML(const char *str) { parameters.buffer_mode[0] = 0; diff --git a/tools/gator/daemon/StreamlineSetup.cpp b/tools/gator/daemon/StreamlineSetup.cpp index caa665e67193..2b61eaeb290d 100644 --- a/tools/gator/daemon/StreamlineSetup.cpp +++ b/tools/gator/daemon/StreamlineSetup.cpp @@ -266,7 +266,7 @@ void StreamlineSetup::writeConfiguration(char* xml) { { ConfigurationXML configuration; } if (gSessionData->mCounterOverflow > 0) { - logg->logError(__FILE__, __LINE__, "Only %i performance counters counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow); + logg->logError(__FILE__, __LINE__, "Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow); handleException(); } } diff --git a/tools/gator/daemon/StreamlineSetup.h b/tools/gator/daemon/StreamlineSetup.h index 74bb197e35ff..b380f46b98f0 100644 --- a/tools/gator/daemon/StreamlineSetup.h +++ b/tools/gator/daemon/StreamlineSetup.h @@ -21,7 +21,7 @@ enum { COMMAND_APC_START = 2, COMMAND_APC_STOP = 3, COMMAND_DISCONNECT = 4, - COMMAND_PING = 5 + COMMAND_PING = 5 }; class StreamlineSetup { @@ -47,4 +47,4 @@ private: StreamlineSetup &operator=(const StreamlineSetup &); }; -#endif //__STREAMLINE_SETUP_H__ +#endif //__STREAMLINE_SETUP_H__ diff --git a/tools/gator/daemon/UEvent.cpp b/tools/gator/daemon/UEvent.cpp index 282e965fa67a..54d45751e3c9 100644 --- a/tools/gator/daemon/UEvent.cpp +++ b/tools/gator/daemon/UEvent.cpp @@ -8,11 +8,12 @@ #include "UEvent.h" -#include #include #include #include +#include + #include "Logging.h" static const char EMPTY[] = ""; diff --git a/tools/gator/daemon/UserSpaceSource.cpp b/tools/gator/daemon/UserSpaceSource.cpp index debe69636cff..8c328e0e0fb5 100644 --- a/tools/gator/daemon/UserSpaceSource.cpp +++ b/tools/gator/daemon/UserSpaceSource.cpp @@ -16,7 +16,6 @@ #include "Logging.h" #include "SessionData.h" -#define NS_PER_S ((uint64_t)1000000000) #define NS_PER_US 1000 extern Child *child; @@ -35,6 +34,7 @@ void UserSpaceSource::run() { prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0); gSessionData->hwmon.start(); + gSessionData->fsDriver.start(); int64_t monotonic_started = 0; while (monotonic_started <= 0) { @@ -48,16 +48,7 @@ void UserSpaceSource::run() { uint64_t next_time = 0; while (gSessionData->mSessionIsActive) { - struct timespec ts; -#ifndef CLOCK_MONOTONIC_RAW - // Android doesn't have this defined but it was added in Linux 2.6.28 -#define CLOCK_MONOTONIC_RAW 4 -#endif - if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) { - logg->logError(__FILE__, __LINE__, "Failed to get uptime"); - handleException(); - } - const uint64_t curr_time = (NS_PER_S*ts.tv_sec + ts.tv_nsec) - monotonic_started; + const uint64_t curr_time = getTime() - monotonic_started; // Sample ten times a second ignoring gSessionData->mSampleRate next_time += NS_PER_S/10;//gSessionData->mSampleRate; if (next_time < curr_time) { @@ -67,6 +58,7 @@ void UserSpaceSource::run() { if (mBuffer.eventHeader(curr_time)) { gSessionData->hwmon.read(&mBuffer); + gSessionData->fsDriver.read(&mBuffer); // Only check after writing all counters so that time and corresponding counters appear in the same frame mBuffer.check(curr_time); } diff --git a/tools/gator/daemon/UserSpaceSource.h b/tools/gator/daemon/UserSpaceSource.h index fb5889d26ffb..9b3666016dc5 100644 --- a/tools/gator/daemon/UserSpaceSource.h +++ b/tools/gator/daemon/UserSpaceSource.h @@ -14,7 +14,7 @@ #include "Buffer.h" #include "Source.h" -// User space counters - currently just hwmon +// User space counters class UserSpaceSource : public Source { public: UserSpaceSource(sem_t *senderSem); diff --git a/tools/gator/daemon/c++.cpp b/tools/gator/daemon/c++.cpp new file mode 100644 index 000000000000..6041e5e96469 --- /dev/null +++ b/tools/gator/daemon/c++.cpp @@ -0,0 +1,40 @@ +/** + * Minimal set of C++ functions so that libstdc++ is not required + * + * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +void operator delete(void *ptr) { + if (ptr != NULL) { + free(ptr); + } +} + +void operator delete[](void *ptr) { + operator delete(ptr); +} + +void *operator new(size_t size) { + void *ptr = malloc(size == 0 ? 1 : size); + if (ptr == NULL) { + abort(); + } + return ptr; +} + +void *operator new[](size_t size) { + return operator new(size); +} + +extern "C" +void __cxa_pure_virtual() { + printf("pure virtual method called\n"); + abort(); +} diff --git a/tools/gator/daemon/common.mk b/tools/gator/daemon/common.mk index d9dc14606b07..769a92e51a35 100644 --- a/tools/gator/daemon/common.mk +++ b/tools/gator/daemon/common.mk @@ -5,16 +5,17 @@ # -Werror treats warnings as errors # -std=c++0x is the planned new c++ standard # -std=c++98 is the 1998 c++ standard -CFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors +CPPFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors CXXFLAGS += -fno-rtti -Wextra # -Weffc++ ifeq ($(WERROR),1) - CFLAGS += -Werror + CPPFLAGS += -Werror endif # -s strips the binary of debug info LDFLAGS += -s +LDLIBS += -lrt -lm -pthread TARGET = gatord C_SRC = $(wildcard mxml/*.c) $(wildcard libsensors/*.c) -CPP_SRC = $(wildcard *.cpp) +CXX_SRC = $(wildcard *.cpp) all: $(TARGET) @@ -35,14 +36,15 @@ libsensors/conf-parse.c: ; ./escape $< > $@ %.o: %.c - $(GCC) -c $(CFLAGS) -o $@ $< + $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< %.o: %.cpp - $(CPP) -c $(CFLAGS) $(CXXFLAGS) -o $@ $< + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $< -$(TARGET): $(CPP_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o) - $(CPP) $(LDFLAGS) -o $@ $^ -lrt -pthread +$(TARGET): $(CXX_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o) + $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ +# Intentionally ignore CC as a native binary is required escape: escape.c gcc $^ -o $@ diff --git a/tools/gator/daemon/defaults.xml b/tools/gator/daemon/defaults.xml index 5bf096cb2a45..39a0f656f7e6 100644 --- a/tools/gator/daemon/defaults.xml +++ b/tools/gator/daemon/defaults.xml @@ -58,5 +58,10 @@ + + + + + diff --git a/tools/gator/daemon/escape.c b/tools/gator/daemon/escape.c index c54aa1c3e75d..2b0863aaf425 100644 --- a/tools/gator/daemon/escape.c +++ b/tools/gator/daemon/escape.c @@ -6,7 +6,7 @@ * published by the Free Software Foundation. */ -/* +/* * The Makefile in the daemon folder builds and executes 'escape' * 'escape' creates configuration_xml.h from configuration.xml and events_xml.h from events-*.xml * these genereated xml files are then #included and built as part of the gatord binary diff --git a/tools/gator/daemon/events-CCI-400.xml b/tools/gator/daemon/events-CCI-400.xml index 4fa77117d2d8..20002efd1543 100644 --- a/tools/gator/daemon/events-CCI-400.xml +++ b/tools/gator/daemon/events-CCI-400.xml @@ -1,7 +1,6 @@ - - - - + + + - @@ -30,13 +28,11 @@ - - @@ -45,11 +41,9 @@ - - - - - + + + - @@ -79,13 +72,11 @@ - - diff --git a/tools/gator/daemon/events-CCN-504.xml b/tools/gator/daemon/events-CCN-504.xml index cfabf65949ed..6ef3e6483717 100644 --- a/tools/gator/daemon/events-CCN-504.xml +++ b/tools/gator/daemon/events-CCN-504.xml @@ -1,7 +1,6 @@ - - @@ -56,7 +54,6 @@ - - @@ -82,7 +78,6 @@ - - @@ -102,14 +96,12 @@ - - @@ -118,5 +110,4 @@ - diff --git a/tools/gator/daemon/events-Cortex-A53.xml b/tools/gator/daemon/events-Cortex-A53.xml index 577dcd94185e..5ba17907d5ab 100644 --- a/tools/gator/daemon/events-Cortex-A53.xml +++ b/tools/gator/daemon/events-Cortex-A53.xml @@ -1,171 +1,87 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/gator/daemon/events-Cortex-A57.xml b/tools/gator/daemon/events-Cortex-A57.xml index b7178c0c7427..fbe96c2d4eb2 100644 --- a/tools/gator/daemon/events-Cortex-A57.xml +++ b/tools/gator/daemon/events-Cortex-A57.xml @@ -1,171 +1,87 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/gator/daemon/events-Filesystem.xml b/tools/gator/daemon/events-Filesystem.xml new file mode 100644 index 000000000000..5feeb9014a63 --- /dev/null +++ b/tools/gator/daemon/events-Filesystem.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/tools/gator/daemon/events-L2C-310.xml b/tools/gator/daemon/events-L2C-310.xml index 4da4d1d63431..923fb90334d0 100644 --- a/tools/gator/daemon/events-L2C-310.xml +++ b/tools/gator/daemon/events-L2C-310.xml @@ -1,18 +1,18 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/tools/gator/daemon/events-Linux.xml b/tools/gator/daemon/events-Linux.xml index 4d677e15db7e..c306dd62208e 100644 --- a/tools/gator/daemon/events-Linux.xml +++ b/tools/gator/daemon/events-Linux.xml @@ -11,7 +11,6 @@ - - + + - diff --git a/tools/gator/daemon/events-Mali-4xx.xml b/tools/gator/daemon/events-Mali-4xx.xml index 5a71386830ba..0a95dfeb6485 100644 --- a/tools/gator/daemon/events-Mali-4xx.xml +++ b/tools/gator/daemon/events-Mali-4xx.xml @@ -1,34 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -37,7 +36,6 @@ - @@ -96,11 +94,10 @@ - - + + - - - @@ -131,10 +126,9 @@ - - - - + + + - - - - - - - - - - - + + + + + + + + + - - - - + + + - - - - - - - - - - - + + + + + + + + + - + +