aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2014-11-21 17:38:28 +0000
committerMark Brown <broonie@kernel.org>2014-11-21 17:38:28 +0000
commit845187c7b4f1d0a1f6c84325d2c0f81a79e1cd9f (patch)
treeabfba82f4758f875e7807a4e758a7eb2aca2003b
parent43bc6d5b076e30d55b59daedeb205063cb6e54a2 (diff)
parent07ee5f07b467451a2018c35aee5ee513ac679967 (diff)
downloadlinux-linaro-stable-v3.14/topic/gator.tar.gz
Merge branch 'lsk-3.14-gator' of https://git.linaro.org/landing-teams/working/arm/kernel into lsk-v3.14-gatorv3.14/topic/gator
-rw-r--r--drivers/gator/Kconfig4
-rw-r--r--drivers/gator/Makefile22
-rw-r--r--drivers/gator/gator.h41
-rw-r--r--drivers/gator/gator_annotate.c67
-rw-r--r--drivers/gator/gator_annotate_kernel.c30
-rw-r--r--drivers/gator/gator_backtrace.c66
-rw-r--r--drivers/gator/gator_buffer.c71
-rw-r--r--drivers/gator/gator_buffer_write.c19
-rw-r--r--drivers/gator/gator_cookies.c67
-rw-r--r--drivers/gator/gator_events_armv6.c47
-rw-r--r--drivers/gator/gator_events_armv7.c90
-rw-r--r--drivers/gator/gator_events_block.c29
-rw-r--r--drivers/gator/gator_events_ccn-504.c346
-rw-r--r--drivers/gator/gator_events_irq.c14
-rw-r--r--drivers/gator/gator_events_l2c-310.c6
-rw-r--r--drivers/gator/gator_events_mali_4xx.c181
-rw-r--r--drivers/gator/gator_events_mali_common.c21
-rw-r--r--drivers/gator/gator_events_mali_common.h17
-rw-r--r--drivers/gator/gator_events_mali_midgard.c (renamed from drivers/gator/gator_events_mali_t6xx.c)147
-rw-r--r--drivers/gator/gator_events_mali_midgard_hw.c (renamed from drivers/gator/gator_events_mali_t6xx_hw.c)492
-rw-r--r--drivers/gator/gator_events_mali_midgard_hw_test.c (renamed from drivers/gator/gator_events_mali_t6xx_hw_test.c)8
-rw-r--r--drivers/gator/gator_events_meminfo.c197
-rw-r--r--drivers/gator/gator_events_mmapped.c6
-rw-r--r--drivers/gator/gator_events_net.c22
-rw-r--r--drivers/gator/gator_events_perf_pmu.c207
-rw-r--r--drivers/gator/gator_events_sched.c14
-rw-r--r--drivers/gator/gator_events_scorpion.c81
-rw-r--r--drivers/gator/gator_events_threads.c115
-rw-r--r--drivers/gator/gator_fs.c9
-rw-r--r--drivers/gator/gator_hrtimer_gator.c8
-rw-r--r--drivers/gator/gator_iks.c22
-rw-r--r--drivers/gator/gator_main.c349
-rw-r--r--drivers/gator/gator_marshaling.c75
-rw-r--r--drivers/gator/gator_trace_gpu.c88
-rw-r--r--drivers/gator/gator_trace_power.c61
-rw-r--r--drivers/gator/gator_trace_sched.c104
-rw-r--r--drivers/gator/mali/mali_dd_gator_api.h40
-rw-r--r--drivers/gator/mali/mali_kbase_gator_api.h219
-rw-r--r--drivers/gator/mali/mali_mjollnir_profiling_gator_api.h192
-rw-r--r--drivers/gator/mali/mali_utgard_profiling_gator_api.h214
-rw-r--r--drivers/gator/mali_midgard.mk (renamed from drivers/gator/mali_t6xx.mk)4
-rw-r--r--tools/gator/daemon/Android.mk17
-rw-r--r--tools/gator/daemon/AnnotateListener.cpp69
-rw-r--r--tools/gator/daemon/AnnotateListener.h31
-rw-r--r--tools/gator/daemon/Application.mk2
-rw-r--r--tools/gator/daemon/Buffer.cpp215
-rw-r--r--tools/gator/daemon/Buffer.h38
-rw-r--r--tools/gator/daemon/CCNDriver.cpp295
-rw-r--r--tools/gator/daemon/CCNDriver.h43
-rw-r--r--tools/gator/daemon/CPUFreqDriver.cpp58
-rw-r--r--tools/gator/daemon/CPUFreqDriver.h34
-rw-r--r--tools/gator/daemon/CapturedXML.cpp17
-rw-r--r--tools/gator/daemon/CapturedXML.h4
-rw-r--r--tools/gator/daemon/Child.cpp82
-rw-r--r--tools/gator/daemon/Child.h4
-rw-r--r--tools/gator/daemon/Command.cpp172
-rw-r--r--tools/gator/daemon/Command.h14
-rw-r--r--tools/gator/daemon/Config.h13
-rw-r--r--tools/gator/daemon/DiskIODriver.cpp125
-rw-r--r--tools/gator/daemon/DiskIODriver.h39
-rw-r--r--tools/gator/daemon/Driver.cpp81
-rw-r--r--tools/gator/daemon/Driver.h76
-rw-r--r--tools/gator/daemon/DriverSource.cpp19
-rw-r--r--tools/gator/daemon/DynBuf.cpp2
-rw-r--r--tools/gator/daemon/EventsXML.cpp2
-rw-r--r--tools/gator/daemon/ExternalSource.cpp87
-rw-r--r--tools/gator/daemon/ExternalSource.h8
-rw-r--r--tools/gator/daemon/FSDriver.cpp140
-rw-r--r--tools/gator/daemon/FSDriver.h19
-rw-r--r--tools/gator/daemon/Fifo.cpp5
-rw-r--r--tools/gator/daemon/Fifo.h10
-rw-r--r--tools/gator/daemon/FtraceDriver.cpp118
-rw-r--r--tools/gator/daemon/FtraceDriver.h31
-rw-r--r--tools/gator/daemon/FtraceSource.cpp158
-rw-r--r--tools/gator/daemon/FtraceSource.h43
-rw-r--r--tools/gator/daemon/Hwmon.h45
-rw-r--r--tools/gator/daemon/HwmonDriver.cpp (renamed from tools/gator/daemon/Hwmon.cpp)213
-rw-r--r--tools/gator/daemon/HwmonDriver.h31
-rw-r--r--tools/gator/daemon/KMod.cpp9
-rw-r--r--tools/gator/daemon/KMod.h7
-rw-r--r--tools/gator/daemon/LocalCapture.h4
-rw-r--r--tools/gator/daemon/Logging.cpp18
-rw-r--r--tools/gator/daemon/Logging.h12
-rw-r--r--tools/gator/daemon/Makefile5
-rw-r--r--tools/gator/daemon/MaliVideoDriver.cpp148
-rw-r--r--tools/gator/daemon/MaliVideoDriver.h17
-rw-r--r--tools/gator/daemon/MemInfoDriver.cpp93
-rw-r--r--tools/gator/daemon/MemInfoDriver.h37
-rw-r--r--tools/gator/daemon/Monitor.cpp14
-rw-r--r--tools/gator/daemon/NetDriver.cpp129
-rw-r--r--tools/gator/daemon/NetDriver.h39
-rw-r--r--tools/gator/daemon/OlySocket.cpp54
-rw-r--r--tools/gator/daemon/OlySocket.h9
-rw-r--r--tools/gator/daemon/PerfBuffer.cpp65
-rw-r--r--tools/gator/daemon/PerfBuffer.h4
-rw-r--r--tools/gator/daemon/PerfDriver.cpp194
-rw-r--r--tools/gator/daemon/PerfDriver.h15
-rw-r--r--tools/gator/daemon/PerfGroup.cpp66
-rw-r--r--tools/gator/daemon/PerfGroup.h14
-rw-r--r--tools/gator/daemon/PerfSource.cpp306
-rw-r--r--tools/gator/daemon/PerfSource.h3
-rw-r--r--tools/gator/daemon/Proc.cpp137
-rw-r--r--tools/gator/daemon/Proc.h6
-rw-r--r--tools/gator/daemon/Sender.cpp7
-rw-r--r--tools/gator/daemon/Sender.h4
-rw-r--r--tools/gator/daemon/SessionData.cpp91
-rw-r--r--tools/gator/daemon/SessionData.h44
-rw-r--r--tools/gator/daemon/SessionXML.cpp40
-rw-r--r--tools/gator/daemon/SessionXML.h12
-rw-r--r--tools/gator/daemon/Setup.cpp232
-rw-r--r--tools/gator/daemon/Setup.h18
-rw-r--r--tools/gator/daemon/StreamlineSetup.h4
-rw-r--r--tools/gator/daemon/UEvent.cpp3
-rw-r--r--tools/gator/daemon/UserSpaceSource.cpp23
-rw-r--r--tools/gator/daemon/defaults.xml33
-rw-r--r--tools/gator/daemon/events-Cortex-A17.xml (renamed from tools/gator/daemon/events-Cortex-A12.xml)8
-rw-r--r--tools/gator/daemon/events-Filesystem.xml12
-rw-r--r--tools/gator/daemon/events-Linux.xml11
-rw-r--r--tools/gator/daemon/events-Mali-Midgard.xml46
-rw-r--r--tools/gator/daemon/events-Mali-Midgard_hw.xml91
-rw-r--r--tools/gator/daemon/events-Mali-T60x_hw.xml108
-rw-r--r--tools/gator/daemon/events-Mali-T62x_hw.xml109
-rw-r--r--tools/gator/daemon/events-Mali-T6xx.xml46
-rw-r--r--tools/gator/daemon/events-Mali-T6xx_hw.xml91
-rw-r--r--tools/gator/daemon/events-Mali-T72x_hw.xml95
-rw-r--r--tools/gator/daemon/events-Mali-T76x_hw.xml108
-rw-r--r--tools/gator/daemon/events-Mali-V500.xml55
-rw-r--r--tools/gator/daemon/events-ftrace.xml7
-rw-r--r--tools/gator/daemon/main.cpp95
-rw-r--r--tools/gator/daemon/mxml/config.h10
-rw-r--r--tools/gator/daemon/mxml/mxml-attr.c19
-rw-r--r--tools/gator/daemon/mxml/mxml-entity.c19
-rw-r--r--tools/gator/daemon/mxml/mxml-file.c104
-rw-r--r--tools/gator/daemon/mxml/mxml-get.c27
-rw-r--r--tools/gator/daemon/mxml/mxml-index.c11
-rw-r--r--tools/gator/daemon/mxml/mxml-node.c31
-rw-r--r--tools/gator/daemon/mxml/mxml-private.c42
-rw-r--r--tools/gator/daemon/mxml/mxml-private.h8
-rw-r--r--tools/gator/daemon/mxml/mxml-search.c17
-rw-r--r--tools/gator/daemon/mxml/mxml-set.c20
-rw-r--r--tools/gator/daemon/mxml/mxml-string.c21
-rw-r--r--tools/gator/daemon/mxml/mxml.h17
142 files changed, 5885 insertions, 3431 deletions
diff --git a/drivers/gator/Kconfig b/drivers/gator/Kconfig
index 31f0c6f..a9503a9 100644
--- a/drivers/gator/Kconfig
+++ b/drivers/gator/Kconfig
@@ -23,8 +23,8 @@ config GATOR_MALI_4XXMP
bool "Mali-400MP or Mali-450MP"
select GATOR_WITH_MALI_SUPPORT
-config GATOR_MALI_T6XX
- bool "Mali-T604 or Mali-T658"
+config GATOR_MALI_MIDGARD
+ bool "Mali-T60x, Mali-T62x, Mali-T72x or Mali-T76x"
select GATOR_WITH_MALI_SUPPORT
endchoice
diff --git a/drivers/gator/Makefile b/drivers/gator/Makefile
index 2f86823..28d2070 100644
--- a/drivers/gator/Makefile
+++ b/drivers/gator/Makefile
@@ -14,17 +14,16 @@ gator-y := gator_main.o \
gator_events_net.o \
gator_events_perf_pmu.o \
gator_events_sched.o \
- gator_events_threads.o \
# Convert the old GATOR_WITH_MALI_SUPPORT to the new kernel flags
ifneq ($(GATOR_WITH_MALI_SUPPORT),)
CONFIG_GATOR_WITH_MALI_SUPPORT := y
- ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_T6xx)
+ ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_MIDGARD)
CONFIG_GATOR_MALI_4XXMP := n
- CONFIG_GATOR_MALI_T6XX := y
+ CONFIG_GATOR_MALI_MIDGARD := y
else
CONFIG_GATOR_MALI_4XXMP := y
- CONFIG_GATOR_MALI_T6XX := n
+ CONFIG_GATOR_MALI_MIDGARD := n
endif
EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT)
ifneq ($(GATOR_MALI_INTERFACE_STYLE),)
@@ -33,10 +32,10 @@ ifneq ($(GATOR_WITH_MALI_SUPPORT),)
endif
ifeq ($(CONFIG_GATOR_WITH_MALI_SUPPORT),y)
- ifeq ($(CONFIG_GATOR_MALI_T6XX),y)
- gator-y += gator_events_mali_t6xx.o \
- gator_events_mali_t6xx_hw.o
- include $(src)/mali_t6xx.mk
+ ifeq ($(CONFIG_GATOR_MALI_MIDGARD),y)
+ gator-y += gator_events_mali_midgard.o \
+ gator_events_mali_midgard_hw.o
+ include $(src)/mali_midgard.mk
else
gator-y += gator_events_mali_4xx.o
endif
@@ -46,7 +45,7 @@ ifeq ($(CONFIG_GATOR_WITH_MALI_SUPPORT),y)
ccflags-y += -I$(CONFIG_GATOR_MALI_PATH)
endif
ccflags-$(CONFIG_GATOR_MALI_4XXMP) += -DMALI_SUPPORT=MALI_4xx
- ccflags-$(CONFIG_GATOR_MALI_T6XX) += -DMALI_SUPPORT=MALI_T6xx
+ ccflags-$(CONFIG_GATOR_MALI_MIDGARD) += -DMALI_SUPPORT=MALI_MIDGARD
endif
# GATOR_TEST controls whether to include (=1) or exclude (=0) test code.
@@ -54,16 +53,15 @@ 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 $$?)
+OLD_BLOCK_RQ_COMPLETE := $(shell grep -A3 block_rq_complete $(srctree)/include/trace/events/block.h | grep nr_bytes -q; 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 \
gator_events_l2c-310.o \
gator_events_scorpion.o
-gator-$(CONFIG_ARM64) += gator_events_ccn-504.o
+gator-$(CONFIG_ARM64) +=
else
diff --git a/drivers/gator/gator.h b/drivers/gator/gator.h
index 5ad0254..5cc73a3 100644
--- a/drivers/gator/gator.h
+++ b/drivers/gator/gator.h
@@ -14,13 +14,13 @@
#include <linux/mm.h>
#include <linux/list.h>
-#define GATOR_PERF_SUPPORT LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
-#define GATOR_PERF_PMU_SUPPORT GATOR_PERF_SUPPORT && defined(CONFIG_PERF_EVENTS) && (!(defined(__arm__) || defined(__aarch64__)) || defined(CONFIG_HW_PERF_EVENTS))
+#define GATOR_PERF_SUPPORT (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+#define GATOR_PERF_PMU_SUPPORT (GATOR_PERF_SUPPORT && defined(CONFIG_PERF_EVENTS) && (!(defined(__arm__) || defined(__aarch64__)) || defined(CONFIG_HW_PERF_EVENTS)))
#define GATOR_NO_PERF_SUPPORT (!(GATOR_PERF_SUPPORT))
-#define GATOR_CPU_FREQ_SUPPORT (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) && defined(CONFIG_CPU_FREQ)
+#define GATOR_CPU_FREQ_SUPPORT ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) && defined(CONFIG_CPU_FREQ))
#define GATOR_IKS_SUPPORT defined(CONFIG_BL_SWITCHER)
-// cpu ids
+/* cpu ids */
#define ARM1136 0xb36
#define ARM1156 0xb56
#define ARM1176 0xb76
@@ -29,7 +29,6 @@
#define CORTEX_A7 0xc07
#define CORTEX_A8 0xc08
#define CORTEX_A9 0xc09
-#define CORTEX_A12 0xc0d
#define CORTEX_A15 0xc0f
#define CORTEX_A17 0xc0e
#define SCORPION 0x00f
@@ -42,20 +41,20 @@
#define AARCH64 0xd0f
#define OTHER 0xfff
-// gpu enums
+/* gpu enums */
#define MALI_4xx 1
-#define MALI_T6xx 2
+#define MALI_MIDGARD 2
#define MAXSIZE_CORE_NAME 32
struct gator_cpu {
const int cpuid;
- // Human readable name
+ /* Human readable name */
const char core_name[MAXSIZE_CORE_NAME];
- // gatorfs event and Perf PMU name
- const char * const pmnc_name;
- // compatible from Documentation/devicetree/bindings/arm/cpus.txt
- const char * const dt_name;
+ /* gatorfs event and Perf PMU name */
+ const char *const pmnc_name;
+ /* compatible from Documentation/devicetree/bindings/arm/cpus.txt */
+ const char *const dt_name;
const int pmnc_counters;
};
@@ -98,7 +97,7 @@ int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root,
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)
+ ((gator_tracepoint_##probe_name == NULL) || 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
@@ -107,15 +106,19 @@ int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root,
* Events
******************************************************************************/
struct gator_interface {
- void (*shutdown)(void); // Complementary function to init
+ /* Complementary function to init */
+ void (*shutdown)(void);
int (*create_files)(struct super_block *sb, struct dentry *root);
int (*start)(void);
- void (*stop)(void); // Complementary function to start
+ /* Complementary function to start */
+ void (*stop)(void);
int (*online)(int **buffer, bool migrate);
int (*offline)(int **buffer, bool migrate);
- void (*online_dispatch)(int cpu, bool migrate); // called in process context but may not be running on core 'cpu'
- void (*offline_dispatch)(int cpu, bool migrate); // called in process context but may not be running on core 'cpu'
- int (*read)(int **buffer);
+ /* called in process context but may not be running on core 'cpu' */
+ void (*online_dispatch)(int cpu, bool migrate);
+ /* called in process context but may not be running on core 'cpu' */
+ void (*offline_dispatch)(int cpu, bool migrate);
+ int (*read)(int **buffer, bool sched_switch);
int (*read64)(long long **buffer);
int (*read_proc)(long long **buffer, struct task_struct *);
struct list_head list;
@@ -146,4 +149,4 @@ int pcpu_to_lcpu(const int pcpu);
#define get_logical_cpu() smp_processor_id()
#define on_primary_core() (get_logical_cpu() == 0)
-#endif // GATOR_H_
+#endif /* GATOR_H_ */
diff --git a/drivers/gator/gator_annotate.c b/drivers/gator/gator_annotate.c
index 7e2c6e5..ff9a3ce 100644
--- a/drivers/gator/gator_annotate.c
+++ b/drivers/gator/gator_annotate.c
@@ -11,12 +11,12 @@
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/sched.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/current.h>
#include <linux/spinlock.h>
static DEFINE_SPINLOCK(annotate_lock);
-static bool collect_annotations = false;
+static bool collect_annotations;
static int annotate_copy(struct file *file, char const __user *buf, size_t count)
{
@@ -24,10 +24,10 @@ static int annotate_copy(struct file *file, char const __user *buf, size_t count
int write = per_cpu(gator_buffer_write, cpu)[ANNOTATE_BUF];
if (file == NULL) {
- // copy from kernel
+ /* copy from kernel */
memcpy(&per_cpu(gator_buffer, cpu)[ANNOTATE_BUF][write], buf, count);
} else {
- // copy from user space
+ /* copy from user space */
if (copy_from_user(&per_cpu(gator_buffer, cpu)[ANNOTATE_BUF][write], buf, count) != 0)
return -1;
}
@@ -41,70 +41,70 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t
int pid, cpu, header_size, available, contiguous, length1, length2, size, count = count_orig & 0x7fffffff;
bool interrupt_context;
- if (*offset) {
+ if (*offset)
return -EINVAL;
- }
interrupt_context = in_interrupt();
- // Annotations are not supported in interrupt context, but may work if you comment out the the next four lines of code.
- // By doing so, annotations in interrupt context can result in deadlocks and lost data.
+ /* Annotations are not supported in interrupt context, but may work
+ * if you comment out the the next four lines of code. By doing so,
+ * annotations in interrupt context can result in deadlocks and lost
+ * data.
+ */
if (interrupt_context) {
- printk(KERN_WARNING "gator: Annotations are not supported in interrupt context. Edit gator_annotate.c in the gator driver to enable annotations in interrupt context.\n");
+ pr_warning("gator: Annotations are not supported in interrupt context. Edit gator_annotate.c in the gator driver to enable annotations in interrupt context.\n");
return -EINVAL;
}
retry:
- // synchronize between cores and with collect_annotations
+ /* synchronize between cores and with collect_annotations */
spin_lock(&annotate_lock);
if (!collect_annotations) {
- // Not collecting annotations, tell the caller everything was written
+ /* Not collecting annotations, tell the caller everything was written */
size = count_orig;
goto annotate_write_out;
}
- // Annotation only uses a single per-cpu buffer as the data must be in order to the engine
+ /* Annotation only uses a single per-cpu buffer as the data must be in order to the engine */
cpu = 0;
- if (current == NULL) {
+ if (current == NULL)
pid = 0;
- } else {
+ else
pid = current->pid;
- }
- // determine total size of the payload
+ /* determine total size of the payload */
header_size = MAXSIZE_PACK32 * 3 + MAXSIZE_PACK64;
available = buffer_bytes_available(cpu, ANNOTATE_BUF) - header_size;
size = count < available ? count : available;
if (size <= 0) {
- // Buffer is full, wait until space is available
+ /* Buffer is full, wait until space is available */
spin_unlock(&annotate_lock);
- // Drop the annotation as blocking is not allowed in interrupt context
- if (interrupt_context) {
+ /* Drop the annotation as blocking is not allowed in interrupt context */
+ if (interrupt_context)
return -EINVAL;
- }
wait_event_interruptible(gator_annotate_wait, buffer_bytes_available(cpu, ANNOTATE_BUF) > header_size || !collect_annotations);
- // Check to see if a signal is pending
- if (signal_pending(current)) {
+ /* Check to see if a signal is pending */
+ if (signal_pending(current))
return -EINTR;
- }
goto retry;
}
- // synchronize shared variables annotateBuf and annotatePos
+ /* synchronize shared variables annotateBuf and annotatePos */
if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF]) {
u64 time = gator_get_time();
+
gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, get_physical_cpu());
gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, time);
gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, size);
- // determine the sizes to capture, length1 + length2 will equal size
+ /* determine the sizes to capture, length1 + length2 will equal size */
contiguous = contiguous_space_available(cpu, ANNOTATE_BUF);
if (size < contiguous) {
length1 = size;
@@ -124,14 +124,14 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t
goto annotate_write_out;
}
- // Check and commit; commit is set to occur once buffer is 3/4 full
+ /* Check and commit; commit is set to occur once buffer is 3/4 full */
buffer_check(cpu, ANNOTATE_BUF, time);
}
annotate_write_out:
spin_unlock(&annotate_lock);
- // return the number of bytes written
+ /* return the number of bytes written */
return size;
}
@@ -141,18 +141,21 @@ static int annotate_release(struct inode *inode, struct file *file)
{
int cpu = 0;
- // synchronize between cores
+ /* synchronize between cores */
spin_lock(&annotate_lock);
if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF] && buffer_check_space(cpu, ANNOTATE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
uint32_t pid = current->pid;
+
gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, get_physical_cpu());
gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
- gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); // time
- gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); // size
+ /* time */
+ gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0);
+ /* size */
+ gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0);
}
- // Check and commit; commit is set to occur once buffer is 3/4 full
+ /* Check and commit; commit is set to occur once buffer is 3/4 full */
buffer_check(cpu, ANNOTATE_BUF, gator_get_time());
spin_unlock(&annotate_lock);
@@ -178,7 +181,7 @@ static int gator_annotate_start(void)
static void gator_annotate_stop(void)
{
- // the spinlock here will ensure that when this function exits, we are not in the middle of an annotation
+ /* the spinlock here will ensure that when this function exits, we are not in the middle of an annotation */
spin_lock(&annotate_lock);
collect_annotations = false;
wake_up(&gator_annotate_wait);
diff --git a/drivers/gator/gator_annotate_kernel.c b/drivers/gator/gator_annotate_kernel.c
index 0108068..69471f9 100644
--- a/drivers/gator/gator_annotate_kernel.c
+++ b/drivers/gator/gator_annotate_kernel.c
@@ -19,10 +19,11 @@ static void kannotate_write(const char *ptr, unsigned int size)
int retval;
int pos = 0;
loff_t offset = 0;
+
while (pos < size) {
retval = annotate_write(NULL, &ptr[pos], size - pos, &offset);
if (retval < 0) {
- printk(KERN_WARNING "gator: kannotate_write failed with return value %d\n", retval);
+ pr_warning("gator: kannotate_write failed with return value %d\n", retval);
return;
}
pos += retval;
@@ -47,6 +48,7 @@ void gator_annotate_channel(int channel, const char *str)
{
const u16 str_size = strlen(str) & 0xffff;
char header[8];
+
header[0] = ESCAPE_CODE;
header[1] = STRING_ANNOTATION;
marshal_u32(header + 2, channel);
@@ -54,20 +56,19 @@ void gator_annotate_channel(int channel, const char *str)
kannotate_write(header, sizeof(header));
kannotate_write(str, str_size);
}
-
EXPORT_SYMBOL(gator_annotate_channel);
void gator_annotate(const char *str)
{
gator_annotate_channel(0, str);
}
-
EXPORT_SYMBOL(gator_annotate);
void gator_annotate_channel_color(int channel, int color, const char *str)
{
const u16 str_size = (strlen(str) + 4) & 0xffff;
char header[12];
+
header[0] = ESCAPE_CODE;
header[1] = STRING_ANNOTATION;
marshal_u32(header + 2, channel);
@@ -76,39 +77,37 @@ void gator_annotate_channel_color(int channel, int color, const char *str)
kannotate_write(header, sizeof(header));
kannotate_write(str, str_size - 4);
}
-
EXPORT_SYMBOL(gator_annotate_channel_color);
void gator_annotate_color(int color, const char *str)
{
gator_annotate_channel_color(0, color, str);
}
-
EXPORT_SYMBOL(gator_annotate_color);
void gator_annotate_channel_end(int channel)
{
char header[8];
+
header[0] = ESCAPE_CODE;
header[1] = STRING_ANNOTATION;
marshal_u32(header + 2, channel);
marshal_u16(header + 6, 0);
kannotate_write(header, sizeof(header));
}
-
EXPORT_SYMBOL(gator_annotate_channel_end);
void gator_annotate_end(void)
{
gator_annotate_channel_end(0);
}
-
EXPORT_SYMBOL(gator_annotate_end);
-void gator_annotate_name_channel(int channel, int group, const char* str)
+void gator_annotate_name_channel(int channel, int group, const char *str)
{
const u16 str_size = strlen(str) & 0xffff;
char header[12];
+
header[0] = ESCAPE_CODE;
header[1] = NAME_CHANNEL_ANNOTATION;
marshal_u32(header + 2, channel);
@@ -117,13 +116,13 @@ void gator_annotate_name_channel(int channel, int group, const char* str)
kannotate_write(header, sizeof(header));
kannotate_write(str, str_size);
}
-
EXPORT_SYMBOL(gator_annotate_name_channel);
-void gator_annotate_name_group(int group, const char* str)
+void gator_annotate_name_group(int group, const char *str)
{
const u16 str_size = strlen(str) & 0xffff;
char header[8];
+
header[0] = ESCAPE_CODE;
header[1] = NAME_GROUP_ANNOTATION;
marshal_u32(header + 2, group);
@@ -131,7 +130,6 @@ void gator_annotate_name_group(int group, const char* str)
kannotate_write(header, sizeof(header));
kannotate_write(str, str_size);
}
-
EXPORT_SYMBOL(gator_annotate_name_group);
void gator_annotate_visual(const char *data, unsigned int length, const char *str)
@@ -139,6 +137,7 @@ void gator_annotate_visual(const char *data, unsigned int length, const char *st
const u16 str_size = strlen(str) & 0xffff;
char header[4];
char header_length[4];
+
header[0] = ESCAPE_CODE;
header[1] = VISUAL_ANNOTATION;
marshal_u16(header + 2, str_size);
@@ -148,49 +147,49 @@ void gator_annotate_visual(const char *data, unsigned int length, const char *st
kannotate_write(header_length, sizeof(header_length));
kannotate_write(data, length);
}
-
EXPORT_SYMBOL(gator_annotate_visual);
void gator_annotate_marker(void)
{
char header[4];
+
header[0] = ESCAPE_CODE;
header[1] = MARKER_ANNOTATION;
marshal_u16(header + 2, 0);
kannotate_write(header, sizeof(header));
}
-
EXPORT_SYMBOL(gator_annotate_marker);
void gator_annotate_marker_str(const char *str)
{
const u16 str_size = strlen(str) & 0xffff;
char header[4];
+
header[0] = ESCAPE_CODE;
header[1] = MARKER_ANNOTATION;
marshal_u16(header + 2, str_size);
kannotate_write(header, sizeof(header));
kannotate_write(str, str_size);
}
-
EXPORT_SYMBOL(gator_annotate_marker_str);
void gator_annotate_marker_color(int color)
{
char header[8];
+
header[0] = ESCAPE_CODE;
header[1] = MARKER_ANNOTATION;
marshal_u16(header + 2, 4);
marshal_u32(header + 4, color);
kannotate_write(header, sizeof(header));
}
-
EXPORT_SYMBOL(gator_annotate_marker_color);
void gator_annotate_marker_color_str(int color, const char *str)
{
const u16 str_size = (strlen(str) + 4) & 0xffff;
char header[8];
+
header[0] = ESCAPE_CODE;
header[1] = MARKER_ANNOTATION;
marshal_u16(header + 2, str_size);
@@ -198,5 +197,4 @@ void gator_annotate_marker_color_str(int color, const char *str)
kannotate_write(header, sizeof(header));
kannotate_write(str, str_size - 4);
}
-
EXPORT_SYMBOL(gator_annotate_marker_color_str);
diff --git a/drivers/gator/gator_backtrace.c b/drivers/gator/gator_backtrace.c
index e03c165..76c941d 100644
--- a/drivers/gator/gator_backtrace.c
+++ b/drivers/gator/gator_backtrace.c
@@ -14,17 +14,17 @@ struct stack_frame_eabi {
union {
struct {
unsigned long fp;
- // May be the fp in the case of a leaf function or clang
+ /* May be the fp in the case of a leaf function or clang */
unsigned long lr;
- // If lr is really the fp, lr2 is the corresponding lr
+ /* If lr is really the fp, lr2 is the corresponding lr */
unsigned long lr2;
};
- // Used to read 32 bit fp/lr from a 64 bit kernel
+ /* Used to read 32 bit fp/lr from a 64 bit kernel */
struct {
u32 fp_32;
- // same as lr above
+ /* same as lr above */
u32 lr_32;
- // same as lr2 above
+ /* same as lr2 above */
u32 lr2_32;
};
};
@@ -35,9 +35,8 @@ static void gator_add_trace(int cpu, unsigned long address)
off_t offset = 0;
unsigned long cookie = get_address_cookie(cpu, current, address & ~1, &offset);
- if (cookie == NO_COOKIE || cookie == UNRESOLVED_COOKIE) {
+ if (cookie == NO_COOKIE || cookie == UNRESOLVED_COOKIE)
offset = address;
- }
marshal_backtrace(offset & ~1, cookie, 0);
}
@@ -54,36 +53,34 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs *const regs, unsigned int
unsigned long lr = regs->ARM_lr;
const int gcc_frame_offset = sizeof(unsigned long);
#else
- // Is userspace aarch32 (32 bit)
+ /* Is userspace aarch32 (32 bit) */
const bool is_compat = compat_user_mode(regs);
unsigned long fp = (is_compat ? regs->regs[11] : regs->regs[29]);
unsigned long sp = (is_compat ? regs->compat_sp : regs->sp);
unsigned long lr = (is_compat ? regs->compat_lr : regs->regs[30]);
const int gcc_frame_offset = (is_compat ? sizeof(u32) : 0);
#endif
- // clang frame offset is always zero
+ /* clang frame offset is always zero */
int is_user_mode = user_mode(regs);
- // pc (current function) has already been added
+ /* pc (current function) has already been added */
- if (!is_user_mode) {
+ if (!is_user_mode)
return;
- }
- // Add the lr (parent function)
- // entry preamble may not have executed
+ /* Add the lr (parent function), entry preamble may not have
+ * executed
+ */
gator_add_trace(cpu, lr);
- // check fp is valid
- if (fp == 0 || fp < sp) {
+ /* check fp is valid */
+ if (fp == 0 || fp < sp)
return;
- }
- // Get the current stack frame
+ /* Get the current stack frame */
curr = (struct stack_frame_eabi *)(fp - gcc_frame_offset);
- if ((unsigned long)curr & 3) {
+ if ((unsigned long)curr & 3)
return;
- }
while (depth-- && curr) {
if (!access_ok(VERIFY_READ, curr, sizeof(struct stack_frame_eabi)) ||
@@ -95,13 +92,15 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs *const regs, unsigned int
lr = (is_compat ? bufcurr.lr_32 : bufcurr.lr);
#define calc_next(reg) ((reg) - gcc_frame_offset)
- // Returns true if reg is a valid fp
+ /* Returns true if reg is a valid fp */
#define validate_next(reg, curr) \
((reg) != 0 && (calc_next(reg) & 3) == 0 && (unsigned long)(curr) < calc_next(reg))
- // Try lr from the stack as the fp because gcc leaf functions do not push lr
- // If gcc_frame_offset is non-zero, the lr will also be the clang fp
- // This assumes code is at a lower address than the stack
+ /* Try lr from the stack as the fp because gcc leaf functions do
+ * not push lr. If gcc_frame_offset is non-zero, the lr will also
+ * be the clang fp. This assumes code is at a lower address than
+ * the stack
+ */
if (validate_next(lr, curr)) {
fp = lr;
lr = (is_compat ? bufcurr.lr2_32 : bufcurr.lr2);
@@ -109,11 +108,10 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs *const regs, unsigned int
gator_add_trace(cpu, lr);
- if (!validate_next(fp, curr)) {
+ if (!validate_next(fp, curr))
return;
- }
- // Move to the next stack frame
+ /* Move to the next stack frame */
curr = (struct stack_frame_eabi *)calc_next(fp);
}
#endif
@@ -129,6 +127,7 @@ static int report_trace(struct stackframe *frame, void *d)
#if defined(MODULE)
unsigned int cpu = get_physical_cpu();
struct module *mod = __module_address(addr);
+
if (mod) {
cookie = get_cookie(cpu, current, mod->name, false);
addr = addr - (unsigned long)mod->module_core;
@@ -142,13 +141,13 @@ static int report_trace(struct stackframe *frame, void *d)
}
#endif
-// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile
-// #define GATOR_KERNEL_STACK_UNWINDING
+/* Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile */
+/* #define GATOR_KERNEL_STACK_UNWINDING */
#if (defined(__arm__) || defined(__aarch64__)) && !defined(GATOR_KERNEL_STACK_UNWINDING)
-// Disabled by default
+/* Disabled by default */
MODULE_PARM_DESC(kernel_stack_unwinding, "Allow kernel stack unwinding.");
-static bool kernel_stack_unwinding = 0;
+static bool kernel_stack_unwinding;
module_param(kernel_stack_unwinding, bool, 0644);
#endif
@@ -161,6 +160,7 @@ static void kernel_backtrace(int cpu, struct pt_regs *const regs)
int depth = (kernel_stack_unwinding ? gator_backtrace_depth : 1);
#endif
struct stackframe frame;
+
if (depth == 0)
depth = 1;
#if defined(__arm__)
@@ -196,10 +196,10 @@ static void gator_add_sample(int cpu, struct pt_regs *const regs, u64 time)
if (in_kernel) {
kernel_backtrace(cpu, regs);
} else {
- // Cookie+PC
+ /* Cookie+PC */
gator_add_trace(cpu, PC_REG);
- // Backtrace
+ /* Backtrace */
if (gator_backtrace_depth)
arm_backtrace_eabi(cpu, regs, gator_backtrace_depth);
}
diff --git a/drivers/gator/gator_buffer.c b/drivers/gator/gator_buffer.c
index dfbc97d..910d5aa 100644
--- a/drivers/gator/gator_buffer.c
+++ b/drivers/gator/gator_buffer.c
@@ -10,55 +10,65 @@
static void marshal_frame(int cpu, int buftype)
{
int frame;
+ bool write_cpu;
- if (!per_cpu(gator_buffer, cpu)[buftype]) {
+ if (!per_cpu(gator_buffer, cpu)[buftype])
return;
- }
switch (buftype) {
case SUMMARY_BUF:
+ write_cpu = false;
frame = FRAME_SUMMARY;
break;
case BACKTRACE_BUF:
+ write_cpu = true;
frame = FRAME_BACKTRACE;
break;
case NAME_BUF:
+ write_cpu = true;
frame = FRAME_NAME;
break;
case COUNTER_BUF:
+ write_cpu = false;
frame = FRAME_COUNTER;
break;
case BLOCK_COUNTER_BUF:
+ write_cpu = true;
frame = FRAME_BLOCK_COUNTER;
break;
case ANNOTATE_BUF:
+ write_cpu = false;
frame = FRAME_ANNOTATE;
break;
case SCHED_TRACE_BUF:
+ write_cpu = true;
frame = FRAME_SCHED_TRACE;
break;
case IDLE_BUF:
+ write_cpu = false;
frame = FRAME_IDLE;
break;
case ACTIVITY_BUF:
+ write_cpu = false;
frame = FRAME_ACTIVITY;
break;
default:
+ write_cpu = false;
frame = -1;
break;
}
- // add response type
- if (gator_response_type > 0) {
+ /* add response type */
+ if (gator_response_type > 0)
gator_buffer_write_packed_int(cpu, buftype, gator_response_type);
- }
- // leave space for 4-byte unpacked length
+ /* leave space for 4-byte unpacked length */
per_cpu(gator_buffer_write, cpu)[buftype] = (per_cpu(gator_buffer_write, cpu)[buftype] + sizeof(s32)) & gator_buffer_mask[buftype];
- // add frame type and core number
+ /* add frame type and core number */
gator_buffer_write_packed_int(cpu, buftype, frame);
- gator_buffer_write_packed_int(cpu, buftype, cpu);
+ if (write_cpu)
+ gator_buffer_write_packed_int(cpu, buftype, cpu);
}
static int buffer_bytes_available(int cpu, int buftype)
@@ -66,19 +76,17 @@ static int buffer_bytes_available(int cpu, int buftype)
int remaining, filled;
filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_read, cpu)[buftype];
- if (filled < 0) {
+ if (filled < 0)
filled += gator_buffer_size[buftype];
- }
remaining = gator_buffer_size[buftype] - filled;
- if (per_cpu(buffer_space_available, cpu)[buftype]) {
- // Give some extra room; also allows space to insert the overflow error packet
+ if (per_cpu(buffer_space_available, cpu)[buftype])
+ /* Give some extra room; also allows space to insert the overflow error packet */
remaining -= 200;
- } else {
- // Hysteresis, prevents multiple overflow messages
+ else
+ /* Hysteresis, prevents multiple overflow messages */
remaining -= 2000;
- }
return remaining;
}
@@ -87,11 +95,10 @@ static bool buffer_check_space(int cpu, int buftype, int bytes)
{
int remaining = buffer_bytes_available(cpu, buftype);
- if (remaining < bytes) {
+ if (remaining < bytes)
per_cpu(buffer_space_available, cpu)[buftype] = false;
- } else {
+ else
per_cpu(buffer_space_available, cpu)[buftype] = true;
- }
return per_cpu(buffer_space_available, cpu)[buftype];
}
@@ -100,10 +107,10 @@ static int contiguous_space_available(int cpu, int buftype)
{
int remaining = buffer_bytes_available(cpu, buftype);
int contiguous = gator_buffer_size[buftype] - per_cpu(gator_buffer_write, cpu)[buftype];
+
if (remaining < contiguous)
return remaining;
- else
- return contiguous;
+ return contiguous;
}
static void gator_commit_buffer(int cpu, int buftype, u64 time)
@@ -114,41 +121,38 @@ static void gator_commit_buffer(int cpu, int buftype, u64 time)
if (!per_cpu(gator_buffer, cpu)[buftype])
return;
- // post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload
+ /* post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload */
local_irq_save(flags);
type_length = gator_response_type ? 1 : 0;
commit = per_cpu(gator_buffer_commit, cpu)[buftype];
length = per_cpu(gator_buffer_write, cpu)[buftype] - commit;
- if (length < 0) {
+ if (length < 0)
length += gator_buffer_size[buftype];
- }
length = length - type_length - sizeof(s32);
if (length <= FRAME_HEADER_SIZE) {
- // Nothing to write, only the frame header is present
+ /* Nothing to write, only the frame header is present */
local_irq_restore(flags);
return;
}
- for (byte = 0; byte < sizeof(s32); byte++) {
+ for (byte = 0; byte < sizeof(s32); byte++)
per_cpu(gator_buffer, cpu)[buftype][(commit + type_length + byte) & gator_buffer_mask[buftype]] = (length >> byte * 8) & 0xFF;
- }
per_cpu(gator_buffer_commit, cpu)[buftype] = per_cpu(gator_buffer_write, cpu)[buftype];
if (gator_live_rate > 0) {
- while (time > per_cpu(gator_buffer_commit_time, cpu)) {
+ while (time > per_cpu(gator_buffer_commit_time, cpu))
per_cpu(gator_buffer_commit_time, cpu) += gator_live_rate;
- }
}
marshal_frame(cpu, buftype);
local_irq_restore(flags);
- // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
+ /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */
if (per_cpu(in_scheduler_context, cpu)) {
#ifndef CONFIG_PREEMPT_RT_FULL
- // mod_timer can not be used in interrupt context in RT-Preempt full
+ /* mod_timer can not be used in interrupt context in RT-Preempt full */
mod_timer(&gator_buffer_wake_up_timer, jiffies + 1);
#endif
} else {
@@ -159,10 +163,9 @@ static void gator_commit_buffer(int cpu, int buftype, u64 time)
static void buffer_check(int cpu, int buftype, u64 time)
{
int filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_commit, cpu)[buftype];
- if (filled < 0) {
+
+ if (filled < 0)
filled += gator_buffer_size[buftype];
- }
- if (filled >= ((gator_buffer_size[buftype] * 3) / 4)) {
+ if (filled >= ((gator_buffer_size[buftype] * 3) / 4))
gator_commit_buffer(cpu, buftype, time);
- }
}
diff --git a/drivers/gator/gator_buffer_write.c b/drivers/gator/gator_buffer_write.c
index b621ba9..654ec60 100644
--- a/drivers/gator/gator_buffer_write.c
+++ b/drivers/gator/gator_buffer_write.c
@@ -14,16 +14,17 @@ static void gator_buffer_write_packed_int(int cpu, int buftype, int x)
char *buffer = per_cpu(gator_buffer, cpu)[buftype];
int packedBytes = 0;
int more = true;
+
while (more) {
- // low order 7 bits of x
+ /* low order 7 bits of x */
char b = x & 0x7f;
+
x >>= 7;
- if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) {
+ if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0))
more = false;
- } else {
+ else
b |= 0x80;
- }
buffer[(write + packedBytes) & mask] = b;
packedBytes++;
@@ -39,16 +40,17 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, long long x)
char *buffer = per_cpu(gator_buffer, cpu)[buftype];
int packedBytes = 0;
int more = true;
+
while (more) {
- // low order 7 bits of x
+ /* low order 7 bits of x */
char b = x & 0x7f;
+
x >>= 7;
- if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) {
+ if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0))
more = false;
- } else {
+ else
b |= 0x80;
- }
buffer[(write + packedBytes) & mask] = b;
packedBytes++;
@@ -75,6 +77,7 @@ static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int le
static void gator_buffer_write_string(int cpu, int buftype, const char *x)
{
int len = strlen(x);
+
gator_buffer_write_packed_int(cpu, buftype, len);
gator_buffer_write_bytes(cpu, buftype, x, len);
}
diff --git a/drivers/gator/gator_cookies.c b/drivers/gator/gator_cookies.c
index 5c7d842..c43cce8 100644
--- a/drivers/gator/gator_cookies.c
+++ b/drivers/gator/gator_cookies.c
@@ -7,8 +7,10 @@
*
*/
-#define COOKIEMAP_ENTRIES 1024 /* must be power of 2 */
-#define TRANSLATE_BUFFER_SIZE 512 // must be a power of 2 - 512/4 = 128 entries
+/* must be power of 2 */
+#define COOKIEMAP_ENTRIES 1024
+/* must be a power of 2 - 512/4 = 128 entries */
+#define TRANSLATE_BUFFER_SIZE 512
#define TRANSLATE_TEXT_SIZE 256
#define MAX_COLLISIONS 2
@@ -38,6 +40,7 @@ static uint32_t cookiemap_code(uint64_t value64)
{
uint32_t value = (uint32_t)((value64 >> 32) + value64);
uint32_t cookiecode = (value >> 24) & 0xff;
+
cookiecode = cookiecode * 31 + ((value >> 16) & 0xff);
cookiecode = cookiecode * 31 + ((value >> 8) & 0xff);
cookiecode = cookiecode * 31 + ((value >> 0) & 0xff);
@@ -52,9 +55,8 @@ static uint32_t gator_chksum_crc32(const char *data)
int i, length = strlen(data);
crc = 0xFFFFFFFF;
- for (i = 0; i < length; i++) {
+ for (i = 0; i < length; i++)
crc = ((crc >> 8) & 0x00FFFFFF) ^ gator_crc32_table[(crc ^ *block++) & 0xFF];
- }
return (crc ^ 0xFFFFFFFF);
}
@@ -72,11 +74,12 @@ static uint32_t cookiemap_exists(uint64_t key)
uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]);
uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]);
- // Can be called from interrupt handler or from work queue
+ /* Can be called from interrupt handler or from work queue */
local_irq_save(flags);
for (x = 0; x < MAX_COLLISIONS; x++) {
if (keys[x] == key) {
uint32_t value = values[x];
+
for (; x > 0; x--) {
keys[x] = keys[x - 1];
values[x] = values[x - 1];
@@ -126,7 +129,7 @@ static void translate_buffer_write_args(int cpu, struct task_struct *task, const
write = per_cpu(translate_buffer_write, cpu);
next_write = (write + 1) & translate_buffer_mask;
- // At least one entry must always remain available as when read == write, the queue is empty not full
+ /* At least one entry must always remain available as when read == write, the queue is empty not full */
if (next_write != per_cpu(translate_buffer_read, cpu)) {
args = &per_cpu(translate_buffer, cpu)[write];
args->task = task;
@@ -178,11 +181,11 @@ static void wq_cookie_handler(struct work_struct *unused)
static void app_process_wake_up_handler(unsigned long unused_data)
{
- // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
+ /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */
schedule_work(&cookie_work);
}
-// Retrieve full name from proc/pid/cmdline for java processes on Android
+/* Retrieve full name from proc/pid/cmdline for java processes on Android */
static int translate_app_process(const char **text, int cpu, struct task_struct *task, bool from_wq)
{
void *maddr;
@@ -195,12 +198,16 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
char *buf = per_cpu(translate_text, cpu);
#ifndef CONFIG_PREEMPT_RT_FULL
- // Push work into a work queue if in atomic context as the kernel functions below might sleep
- // Rely on the in_interrupt variable rather than in_irq() or in_interrupt() kernel functions, as the value of these functions seems
- // inconsistent during a context switch between android/linux versions
+ /* Push work into a work queue if in atomic context as the kernel
+ * functions below might sleep. Rely on the in_interrupt variable
+ * rather than in_irq() or in_interrupt() kernel functions, as the
+ * value of these functions seems inconsistent during a context
+ * switch between android/linux versions
+ */
if (!from_wq) {
- // Check if already in buffer
+ /* Check if already in buffer */
int pos = per_cpu(translate_buffer_read, cpu);
+
while (pos != per_cpu(translate_buffer_write, cpu)) {
if (per_cpu(translate_buffer, cpu)[pos].task == task)
goto out;
@@ -209,7 +216,7 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
translate_buffer_write_args(cpu, task, *text);
- // Not safe to call in RT-Preempt full in schedule switch context
+ /* Not safe to call in RT-Preempt full in schedule switch context */
mod_timer(&app_process_wake_up_timer, jiffies + 1);
goto out;
}
@@ -239,7 +246,8 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
copy_from_user_page(page_vma, page, addr, buf, maddr + offset, bytes);
- kunmap(page); // release page allocated by get_user_pages()
+ /* release page allocated by get_user_pages() */
+ kunmap(page);
page_cache_release(page);
len -= bytes;
@@ -250,7 +258,7 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
retval = 1;
}
- // On app_process startup, /proc/pid/cmdline is initially "zygote" then "<pre-initialized>" but changes after an initial startup period
+ /* On app_process startup, /proc/pid/cmdline is initially "zygote" then "<pre-initialized>" but changes after an initial startup period */
if (strcmp(*text, "zygote") == 0 || strcmp(*text, "<pre-initialized>") == 0)
retval = 0;
@@ -262,6 +270,8 @@ out:
return retval;
}
+static const char APP_PROCESS[] = "app_process";
+
static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq)
{
unsigned long flags, cookie;
@@ -271,16 +281,16 @@ static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text,
key = (key << 32) | (uint32_t)task->tgid;
cookie = cookiemap_exists(key);
- if (cookie) {
+ if (cookie)
return cookie;
- }
- if (strcmp(text, "app_process") == 0) {
+ /* On 64-bit android app_process can be app_process32 or app_process64 */
+ if (strncmp(text, APP_PROCESS, sizeof(APP_PROCESS) - 1) == 0) {
if (!translate_app_process(&text, cpu, task, from_wq))
return UNRESOLVED_COOKIE;
}
- // Can be called from interrupt handler or from work queue or from scheduler trace
+ /* Can be called from interrupt handler or from work queue or from scheduler trace */
local_irq_save(flags);
cookie = UNRESOLVED_COOKIE;
@@ -300,7 +310,7 @@ static int get_exec_cookie(int cpu, struct task_struct *task)
struct mm_struct *mm = task->mm;
const char *text;
- // kernel threads have no address space
+ /* kernel threads have no address space */
if (!mm)
return NO_COOKIE;
@@ -355,7 +365,7 @@ static int cookies_initialize(void)
per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu;
size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint64_t);
- per_cpu(cookie_keys, cpu) = (uint64_t *)kmalloc(size, GFP_KERNEL);
+ per_cpu(cookie_keys, cpu) = kmalloc(size, GFP_KERNEL);
if (!per_cpu(cookie_keys, cpu)) {
err = -ENOMEM;
goto cookie_setup_error;
@@ -363,14 +373,14 @@ static int cookies_initialize(void)
memset(per_cpu(cookie_keys, cpu), 0, size);
size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint32_t);
- per_cpu(cookie_values, cpu) = (uint32_t *)kmalloc(size, GFP_KERNEL);
+ per_cpu(cookie_values, cpu) = kmalloc(size, GFP_KERNEL);
if (!per_cpu(cookie_values, cpu)) {
err = -ENOMEM;
goto cookie_setup_error;
}
memset(per_cpu(cookie_values, cpu), 0, size);
- per_cpu(translate_buffer, cpu) = (struct cookie_args *)kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL);
+ per_cpu(translate_buffer, cpu) = kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL);
if (!per_cpu(translate_buffer, cpu)) {
err = -ENOMEM;
goto cookie_setup_error;
@@ -379,16 +389,16 @@ static int cookies_initialize(void)
per_cpu(translate_buffer_write, cpu) = 0;
per_cpu(translate_buffer_read, cpu) = 0;
- per_cpu(translate_text, cpu) = (char *)kmalloc(TRANSLATE_TEXT_SIZE, GFP_KERNEL);
+ per_cpu(translate_text, cpu) = kmalloc(TRANSLATE_TEXT_SIZE, GFP_KERNEL);
if (!per_cpu(translate_text, cpu)) {
err = -ENOMEM;
goto cookie_setup_error;
}
}
- // build CRC32 table
+ /* build CRC32 table */
poly = 0x04c11db7;
- gator_crc32_table = (uint32_t *)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL);
+ gator_crc32_table = kmalloc(256 * sizeof(*gator_crc32_table), GFP_KERNEL);
if (!gator_crc32_table) {
err = -ENOMEM;
goto cookie_setup_error;
@@ -396,11 +406,10 @@ static int cookies_initialize(void)
for (i = 0; i < 256; i++) {
crc = i;
for (j = 8; j > 0; j--) {
- if (crc & 1) {
+ if (crc & 1)
crc = (crc >> 1) ^ poly;
- } else {
+ else
crc >>= 1;
- }
}
gator_crc32_table[i] = crc;
}
diff --git a/drivers/gator/gator_events_armv6.c b/drivers/gator/gator_events_armv6.c
index 3536456..a157a00 100644
--- a/drivers/gator/gator_events_armv6.c
+++ b/drivers/gator/gator_events_armv6.c
@@ -8,7 +8,7 @@
#include "gator.h"
-// gator_events_perf_pmu.c is used if perf is supported
+/* gator_events_perf_pmu.c is used if perf is supported */
#if GATOR_NO_PERF_SUPPORT
static const char *pmnc_name;
@@ -28,7 +28,7 @@ static const char *pmnc_name;
#define CCNT 2
#define CNTMAX (CCNT+1)
-static int pmnc_counters = 0;
+static int pmnc_counters;
static unsigned long pmnc_enabled[CNTMAX];
static unsigned long pmnc_event[CNTMAX];
static unsigned long pmnc_key[CNTMAX];
@@ -45,6 +45,7 @@ static inline void armv6_pmnc_write(u32 val)
static inline u32 armv6_pmnc_read(void)
{
u32 val;
+
asm volatile("mrc p15, 0, %0, c15, c12, 0" : "=r" (val));
return val;
}
@@ -52,6 +53,7 @@ static inline u32 armv6_pmnc_read(void)
static void armv6_pmnc_reset_counter(unsigned int cnt)
{
u32 val = 0;
+
switch (cnt) {
case CCNT:
asm volatile("mcr p15, 0, %0, c15, c12, 1" : : "r" (val));
@@ -74,20 +76,18 @@ int gator_events_armv6_create_files(struct super_block *sb, struct dentry *root)
for (i = PMN0; i <= CCNT; i++) {
char buf[40];
- if (i == CCNT) {
- snprintf(buf, sizeof buf, "ARM_%s_ccnt", pmnc_name);
- } else {
- snprintf(buf, sizeof buf, "ARM_%s_cnt%d", pmnc_name, i);
- }
+
+ if (i == CCNT)
+ snprintf(buf, sizeof(buf), "ARM_%s_ccnt", pmnc_name);
+ else
+ snprintf(buf, sizeof(buf), "ARM_%s_cnt%d", pmnc_name, i);
dir = gatorfs_mkdir(sb, root, buf);
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]);
gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]);
- if (i != CCNT) {
+ if (i != CCNT)
gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]);
- }
}
return 0;
@@ -98,9 +98,8 @@ static int gator_events_armv6_online(int **buffer, bool migrate)
unsigned int cnt, len = 0, cpu = smp_processor_id();
u32 pmnc;
- if (armv6_pmnc_read() & PMCR_E) {
+ if (armv6_pmnc_read() & PMCR_E)
armv6_pmnc_write(armv6_pmnc_read() & ~PMCR_E);
- }
/* initialize PMNC, reset overflow, D bit, C bit and P bit. */
armv6_pmnc_write(PMCR_OFL_PMN0 | PMCR_OFL_PMN1 | PMCR_OFL_CCNT |
@@ -115,19 +114,18 @@ static int gator_events_armv6_online(int **buffer, bool migrate)
event = pmnc_event[cnt] & 255;
- // Set event (if destined for PMNx counters)
- if (cnt == PMN0) {
+ /* Set event (if destined for PMNx counters) */
+ if (cnt == PMN0)
pmnc |= event << 20;
- } else if (cnt == PMN1) {
+ else if (cnt == PMN1)
pmnc |= event << 12;
- }
- // Reset counter
+ /* Reset counter */
armv6_pmnc_reset_counter(cnt);
}
armv6_pmnc_write(pmnc | PMCR_E);
- // return zero values, no need to read as the counters were just reset
+ /* return zero values, no need to read as the counters were just reset */
for (cnt = PMN0; cnt <= CCNT; cnt++) {
if (pmnc_enabled[cnt]) {
per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt];
@@ -146,9 +144,8 @@ static int gator_events_armv6_offline(int **buffer, bool migrate)
unsigned int cnt;
armv6_pmnc_write(armv6_pmnc_read() & ~PMCR_E);
- for (cnt = PMN0; cnt <= CCNT; cnt++) {
+ for (cnt = PMN0; cnt <= CCNT; cnt++)
armv6_pmnc_reset_counter(cnt);
- }
return 0;
}
@@ -163,19 +160,19 @@ static void gator_events_armv6_stop(void)
}
}
-static int gator_events_armv6_read(int **buffer)
+static int gator_events_armv6_read(int **buffer, bool sched_switch)
{
int cnt, len = 0;
int cpu = smp_processor_id();
- // a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled
- if (!(armv6_pmnc_read() & PMCR_E)) {
+ /* a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled */
+ if (!(armv6_pmnc_read() & PMCR_E))
return 0;
- }
for (cnt = PMN0; cnt <= CCNT; cnt++) {
if (pmnc_enabled[cnt]) {
u32 value = 0;
+
switch (cnt) {
case CCNT:
asm volatile("mrc p15, 0, %0, c15, c12, 1" : "=r" (value));
diff --git a/drivers/gator/gator_events_armv7.c b/drivers/gator/gator_events_armv7.c
index bd8a9ba..09c9422 100644
--- a/drivers/gator/gator_events_armv7.c
+++ b/drivers/gator/gator_events_armv7.c
@@ -15,16 +15,16 @@
#include "gator.h"
-// gator_events_perf_pmu.c is used if perf is supported
+/* gator_events_perf_pmu.c is used if perf is supported */
#if GATOR_NO_PERF_SUPPORT
-// Per-CPU PMNC: config reg
+/* Per-CPU PMNC: config reg */
#define PMNC_E (1 << 0) /* Enable all counters */
#define PMNC_P (1 << 1) /* Reset all counters */
#define PMNC_C (1 << 2) /* Cycle counter reset */
#define PMNC_MASK 0x3f /* Mask for writable bits */
-// ccnt reg
+/* ccnt reg */
#define CCNT_REG (1 << 31)
#define CCNT 0
@@ -49,6 +49,7 @@ inline void armv7_pmnc_write(u32 val)
inline u32 armv7_pmnc_read(void)
{
u32 val;
+
asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
return val;
}
@@ -61,10 +62,10 @@ inline u32 armv7_ccnt_read(u32 reset_value)
u32 val;
local_irq_save(flags);
- asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); // disable
- asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); // read
- asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (newval)); // new value
- asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable
+ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); /* disable */
+ asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); /* read */
+ asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (newval)); /* new value */
+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); /* enable */
local_irq_restore(flags);
return val;
@@ -79,11 +80,11 @@ inline u32 armv7_cntn_read(unsigned int cnt, u32 reset_value)
u32 oldval;
local_irq_save(flags);
- asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); // disable
- asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (sel)); // select
- asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (oldval)); // read
- asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (newval)); // new value
- asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable
+ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); /* disable */
+ asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (sel)); /* select */
+ asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (oldval)); /* read */
+ asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (newval)); /* new value */
+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); /* enable */
local_irq_restore(flags);
return oldval;
@@ -92,13 +93,15 @@ inline u32 armv7_cntn_read(unsigned int cnt, u32 reset_value)
static inline void armv7_pmnc_disable_interrupt(unsigned int cnt)
{
u32 val = cnt ? (1 << (cnt - CNT0)) : (1 << 31);
+
asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val));
}
inline u32 armv7_pmnc_reset_interrupt(void)
{
- // Get and reset overflow status flags
+ /* Get and reset overflow status flags */
u32 flags;
+
asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (flags));
flags &= 0x8000003f;
asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (flags));
@@ -108,6 +111,7 @@ inline u32 armv7_pmnc_reset_interrupt(void)
static inline u32 armv7_pmnc_enable_counter(unsigned int cnt)
{
u32 val = cnt ? (1 << (cnt - CNT0)) : CCNT_REG;
+
asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
return cnt;
}
@@ -115,6 +119,7 @@ static inline u32 armv7_pmnc_enable_counter(unsigned int cnt)
static inline u32 armv7_pmnc_disable_counter(unsigned int cnt)
{
u32 val = cnt ? (1 << (cnt - CNT0)) : CCNT_REG;
+
asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
return cnt;
}
@@ -122,15 +127,15 @@ static inline u32 armv7_pmnc_disable_counter(unsigned int cnt)
static inline int armv7_pmnc_select_counter(unsigned int cnt)
{
u32 val = (cnt - CNT0);
+
asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
return cnt;
}
static inline void armv7_pmnc_write_evtsel(unsigned int cnt, u32 val)
{
- if (armv7_pmnc_select_counter(cnt) == cnt) {
+ if (armv7_pmnc_select_counter(cnt) == cnt)
asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
- }
}
static int gator_events_armv7_create_files(struct super_block *sb, struct dentry *root)
@@ -140,20 +145,18 @@ static int gator_events_armv7_create_files(struct super_block *sb, struct dentry
for (i = 0; i < pmnc_counters; i++) {
char buf[40];
- if (i == 0) {
- snprintf(buf, sizeof buf, "%s_ccnt", pmnc_name);
- } else {
- snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i - 1);
- }
+
+ if (i == 0)
+ snprintf(buf, sizeof(buf), "%s_ccnt", pmnc_name);
+ else
+ snprintf(buf, sizeof(buf), "%s_cnt%d", pmnc_name, i - 1);
dir = gatorfs_mkdir(sb, root, buf);
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]);
gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]);
- if (i > 0) {
+ if (i > 0)
gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]);
- }
}
return 0;
@@ -163,14 +166,13 @@ static int gator_events_armv7_online(int **buffer, bool migrate)
{
unsigned int cnt, len = 0, cpu = smp_processor_id();
- if (armv7_pmnc_read() & PMNC_E) {
+ if (armv7_pmnc_read() & PMNC_E)
armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E);
- }
- // Initialize & Reset PMNC: C bit and P bit
+ /* Initialize & Reset PMNC: C bit and P bit */
armv7_pmnc_write(PMNC_P | PMNC_C);
- // Reset overflow flags
+ /* Reset overflow flags */
armv7_pmnc_reset_interrupt();
for (cnt = CCNT; cnt < CNTMAX; cnt++) {
@@ -179,28 +181,28 @@ static int gator_events_armv7_online(int **buffer, bool migrate)
if (!pmnc_enabled[cnt])
continue;
- // Disable counter
+ /* Disable counter */
armv7_pmnc_disable_counter(cnt);
event = pmnc_event[cnt] & 255;
- // Set event (if destined for PMNx counters), we don't need to set the event if it's a cycle count
+ /* Set event (if destined for PMNx counters), we don't need to set the event if it's a cycle count */
if (cnt != CCNT)
armv7_pmnc_write_evtsel(cnt, event);
armv7_pmnc_disable_interrupt(cnt);
- // Reset counter
+ /* Reset counter */
cnt ? armv7_cntn_read(cnt, 0) : armv7_ccnt_read(0);
- // Enable counter
+ /* Enable counter */
armv7_pmnc_enable_counter(cnt);
}
- // enable
+ /* enable */
armv7_pmnc_write(armv7_pmnc_read() | PMNC_E);
- // return zero values, no need to read as the counters were just reset
+ /* return zero values, no need to read as the counters were just reset */
for (cnt = 0; cnt < pmnc_counters; cnt++) {
if (pmnc_enabled[cnt]) {
per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt];
@@ -216,7 +218,7 @@ static int gator_events_armv7_online(int **buffer, bool migrate)
static int gator_events_armv7_offline(int **buffer, bool migrate)
{
- // disable all counters, including PMCCNTR; overflow IRQs will not be signaled
+ /* disable all counters, including PMCCNTR; overflow IRQs will not be signaled */
armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E);
return 0;
@@ -232,24 +234,23 @@ static void gator_events_armv7_stop(void)
}
}
-static int gator_events_armv7_read(int **buffer)
+static int gator_events_armv7_read(int **buffer, bool sched_switch)
{
int cnt, len = 0;
int cpu = smp_processor_id();
- // a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled
- if (!(armv7_pmnc_read() & PMNC_E)) {
+ /* a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled */
+ if (!(armv7_pmnc_read() & PMNC_E))
return 0;
- }
for (cnt = 0; cnt < pmnc_counters; cnt++) {
if (pmnc_enabled[cnt]) {
int value;
- if (cnt == CCNT) {
+
+ if (cnt == CCNT)
value = armv7_ccnt_read(0);
- } else {
+ else
value = armv7_cntn_read(cnt, 0);
- }
per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt];
per_cpu(perfCnt, cpu)[len++] = value;
}
@@ -290,17 +291,16 @@ int gator_events_armv7_init(void)
pmnc_name = "ARMv7_Cortex_A9";
pmnc_counters = 6;
break;
- // ARM Cortex A12 is not supported by version of Linux before 3.0
case CORTEX_A15:
pmnc_name = "ARMv7_Cortex_A15";
pmnc_counters = 6;
break;
- // ARM Cortex A17 is not supported by version of Linux before 3.0
+ /* ARM Cortex A17 is not supported by version of Linux before 3.0 */
default:
return -1;
}
- pmnc_counters++; // CNT[n] + CCNT
+ pmnc_counters++; /* CNT[n] + CCNT */
for (cnt = CCNT; cnt < CNTMAX; cnt++) {
pmnc_enabled[cnt] = 0;
diff --git a/drivers/gator/gator_events_block.c b/drivers/gator/gator_events_block.c
index 03eed4f..a352a54 100644
--- a/drivers/gator/gator_events_block.c
+++ b/drivers/gator/gator_events_block.c
@@ -28,7 +28,7 @@ static ulong block_rq_rd_key;
static atomic_t blockCnt[BLOCK_TOTAL];
static int blockGet[BLOCK_TOTAL * 4];
-// Tracepoint changed in 3.15 backported to older kernels. The Makefile tries to autodetect the correct value, but if it fails change the #if below
+/* Tracepoint changed in 3.15 backported to older kernels. The Makefile tries to autodetect the correct value, but if it fails change the #if below */
#if OLD_BLOCK_RQ_COMPLETE
GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct request *rq))
#else
@@ -52,13 +52,11 @@ GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct r
return;
if (write) {
- if (block_rq_wr_enabled) {
+ if (block_rq_wr_enabled)
atomic_add(size, &blockCnt[BLOCK_RQ_WR]);
- }
} else {
- if (block_rq_rd_enabled) {
+ if (block_rq_rd_enabled)
atomic_add(size, &blockCnt[BLOCK_RQ_RD]);
- }
}
}
@@ -68,17 +66,15 @@ static int gator_events_block_create_files(struct super_block *sb, struct dentry
/* block_complete_wr */
dir = gatorfs_mkdir(sb, root, "Linux_block_rq_wr");
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &block_rq_wr_enabled);
gatorfs_create_ro_ulong(sb, dir, "key", &block_rq_wr_key);
/* block_complete_rd */
dir = gatorfs_mkdir(sb, root, "Linux_block_rq_rd");
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &block_rq_rd_enabled);
gatorfs_create_ro_ulong(sb, dir, "key", &block_rq_rd_key);
@@ -87,7 +83,7 @@ static int gator_events_block_create_files(struct super_block *sb, struct dentry
static int gator_events_block_start(void)
{
- // register tracepoints
+ /* register tracepoints */
if (block_rq_wr_enabled || block_rq_rd_enabled)
if (GATOR_REGISTER_TRACE(block_rq_complete))
goto fail_block_rq_exit;
@@ -95,7 +91,7 @@ static int gator_events_block_start(void)
return 0;
- // unregister tracepoints on error
+ /* unregister tracepoints on error */
fail_block_rq_exit:
pr_err("gator: block event tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n");
@@ -112,19 +108,19 @@ static void gator_events_block_stop(void)
block_rq_rd_enabled = 0;
}
-static int gator_events_block_read(int **buffer)
+static int gator_events_block_read(int **buffer, bool sched_switch)
{
int len, value, data = 0;
- if (!on_primary_core()) {
+ if (!on_primary_core())
return 0;
- }
len = 0;
if (block_rq_wr_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_WR])) > 0) {
atomic_sub(value, &blockCnt[BLOCK_RQ_WR]);
blockGet[len++] = block_rq_wr_key;
- blockGet[len++] = 0; // indicates to Streamline that value bytes were written now, not since the last message
+ /* Indicates to Streamline that value bytes were written now, not since the last message */
+ blockGet[len++] = 0;
blockGet[len++] = block_rq_wr_key;
blockGet[len++] = value;
data += value;
@@ -132,7 +128,8 @@ static int gator_events_block_read(int **buffer)
if (block_rq_rd_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_RD])) > 0) {
atomic_sub(value, &blockCnt[BLOCK_RQ_RD]);
blockGet[len++] = block_rq_rd_key;
- blockGet[len++] = 0; // indicates to Streamline that value bytes were read now, not since the last message
+ /* Indicates to Streamline that value bytes were read now, not since the last message */
+ blockGet[len++] = 0;
blockGet[len++] = block_rq_rd_key;
blockGet[len++] = value;
data += value;
diff --git a/drivers/gator/gator_events_ccn-504.c b/drivers/gator/gator_events_ccn-504.c
deleted file mode 100644
index 024ffc2..0000000
--- a/drivers/gator/gator_events_ccn-504.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/io.h>
-#include <linux/module.h>
-
-#include "gator.h"
-
-#define NUM_REGIONS 256
-#define REGION_SIZE (64*1024)
-#define REGION_DEBUG 1
-#define REGION_XP 64
-#define NUM_XPS 11
-
-// DT (Debug) region
-#define PMEVCNTSR0 0x0150
-#define PMCCNTRSR 0x0190
-#define PMCR 0x01A8
-#define PMSR 0x01B0
-#define PMSR_REQ 0x01B8
-#define PMSR_CLR 0x01C0
-
-// XP region
-#define DT_CONFIG 0x0300
-#define DT_CONTROL 0x0370
-
-// Multiple
-#define PMU_EVENT_SEL 0x0600
-#define OLY_ID 0xFF00
-
-#define CCNT 4
-#define CNTMAX (CCNT + 1)
-
-#define get_pmu_event_id(event) (((event) >> 0) & 0xFF)
-#define get_node_type(event) (((event) >> 8) & 0xFF)
-#define get_region(event) (((event) >> 16) & 0xFF)
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
-
-// From kernel/params.c
-#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \
- int param_set_##name(const char *val, struct kernel_param *kp) \
- { \
- tmptype l; \
- int ret; \
- \
- if (!val) return -EINVAL; \
- ret = strtolfn(val, 0, &l); \
- if (ret == -EINVAL || ((type)l != l)) \
- return -EINVAL; \
- *((type *)kp->arg) = l; \
- return 0; \
- } \
- int param_get_##name(char *buffer, struct kernel_param *kp) \
- { \
- return sprintf(buffer, format, *((type *)kp->arg)); \
- }
-
-#else
-
-// From kernel/params.c
-#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \
- int param_set_##name(const char *val, const struct kernel_param *kp) \
- { \
- tmptype l; \
- int ret; \
- \
- ret = strtolfn(val, 0, &l); \
- if (ret < 0 || ((type)l != l)) \
- return ret < 0 ? ret : -EINVAL; \
- *((type *)kp->arg) = l; \
- return 0; \
- } \
- int param_get_##name(char *buffer, const struct kernel_param *kp) \
- { \
- return scnprintf(buffer, PAGE_SIZE, format, \
- *((type *)kp->arg)); \
- } \
- struct kernel_param_ops param_ops_##name = { \
- .set = param_set_##name, \
- .get = param_get_##name, \
- }; \
- EXPORT_SYMBOL(param_set_##name); \
- EXPORT_SYMBOL(param_get_##name); \
- EXPORT_SYMBOL(param_ops_##name)
-
-#endif
-
-STANDARD_PARAM_DEF(u64, u64, "%llu", u64, strict_strtoull);
-
-// From include/linux/moduleparam.h
-#define param_check_u64(name, p) __param_check(name, p, u64)
-
-MODULE_PARM_DESC(ccn504_addr, "CCN-504 physical base address");
-static u64 ccn504_addr = 0;
-module_param(ccn504_addr, u64, 0444);
-
-static void __iomem *gator_events_ccn504_base;
-static bool gator_events_ccn504_global_enabled;
-static unsigned long gator_events_ccn504_enabled[CNTMAX];
-static unsigned long gator_events_ccn504_event[CNTMAX];
-static unsigned long gator_events_ccn504_key[CNTMAX];
-static int gator_events_ccn504_buffer[2*CNTMAX];
-static int gator_events_ccn504_prev[CNTMAX];
-
-static void gator_events_ccn504_create_shutdown(void)
-{
- if (gator_events_ccn504_base != NULL) {
- iounmap(gator_events_ccn504_base);
- }
-}
-
-static int gator_events_ccn504_create_files(struct super_block *sb, struct dentry *root)
-{
- struct dentry *dir;
- int i;
- char buf[32];
-
- for (i = 0; i < CNTMAX; ++i) {
- if (i == CCNT) {
- snprintf(buf, sizeof(buf), "CCN-504_ccnt");
- } else {
- snprintf(buf, sizeof(buf), "CCN-504_cnt%i", i);
- }
- dir = gatorfs_mkdir(sb, root, buf);
- if (!dir) {
- return -1;
- }
-
- gatorfs_create_ulong(sb, dir, "enabled", &gator_events_ccn504_enabled[i]);
- if (i != CCNT) {
- gatorfs_create_ulong(sb, dir, "event", &gator_events_ccn504_event[i]);
- }
- gatorfs_create_ro_ulong(sb, dir, "key", &gator_events_ccn504_key[i]);
- }
-
- return 0;
-}
-
-static void gator_events_ccn504_set_dt_config(int xp_node_id, int event_num, int value)
-{
- u32 dt_config;
-
- dt_config = readl(gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG);
- dt_config |= (value + event_num) << (4*event_num);
- writel(dt_config, gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG);
-}
-
-static int gator_events_ccn504_start(void)
-{
- int i;
-
- gator_events_ccn504_global_enabled = 0;
- for (i = 0; i < CNTMAX; ++i) {
- if (gator_events_ccn504_enabled[i]) {
- gator_events_ccn504_global_enabled = 1;
- break;
- }
- }
-
- if (!gator_events_ccn504_global_enabled) {
- return 0;
- }
-
- memset(&gator_events_ccn504_prev, 0x80, sizeof(gator_events_ccn504_prev));
-
- // Disable INTREQ on overflow
- // [6] ovfl_intr_en = 0
- // perhaps set to 1?
- // [5] cntr_rst = 0
- // No register paring
- // [4:1] cntcfg = 0
- // Enable PMU features
- // [0] pmu_en = 1
- writel(0x1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMCR);
-
- // Configure the XPs
- for (i = 0; i < NUM_XPS; ++i) {
- int dt_control;
-
- // Pass on all events
- writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG);
-
- // Enable PMU capability
- // [0] dt_enable = 1
- dt_control = readl(gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL);
- dt_control |= 0x1;
- writel(dt_control, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL);
- }
-
- // Assume no other pmu_event_sel registers are set
-
- // cycle counter does not need to be enabled
- for (i = 0; i < CCNT; ++i) {
- int pmu_event_id;
- int node_type;
- int region;
- u32 pmu_event_sel;
- u32 oly_id_whole;
- u32 oly_id;
- u32 node_id;
-
- if (!gator_events_ccn504_enabled[i]) {
- continue;
- }
-
- pmu_event_id = get_pmu_event_id(gator_events_ccn504_event[i]);
- node_type = get_node_type(gator_events_ccn504_event[i]);
- region = get_region(gator_events_ccn504_event[i]);
-
- // Verify the node_type
- oly_id_whole = readl(gator_events_ccn504_base + region*REGION_SIZE + OLY_ID);
- oly_id = oly_id_whole & 0x1F;
- node_id = (oly_id_whole >> 8) & 0x7F;
- if ((oly_id != node_type) ||
- ((node_type == 0x16) && ((oly_id != 0x14) && (oly_id != 0x15) && (oly_id != 0x16) && (oly_id != 0x18) && (oly_id != 0x19) && (oly_id != 0x1A)))) {
- printk(KERN_ERR "gator: oly_id is 0x%x expected 0x%x\n", oly_id, node_type);
- return -1;
- }
-
- // Set the control register
- pmu_event_sel = readl(gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL);
- switch (node_type) {
- case 0x08: // XP
- pmu_event_sel |= pmu_event_id << (7*i);
- gator_events_ccn504_set_dt_config(node_id, i, 0x4);
- break;
- case 0x04: // HN-F
- case 0x16: // RN-I
- case 0x10: // SBAS
- pmu_event_sel |= pmu_event_id << (4*i);
- gator_events_ccn504_set_dt_config(node_id/2, i, (node_id & 1) == 0 ? 0x8 : 0xC);
- break;
- }
- writel(pmu_event_sel, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL);
- }
-
- return 0;
-}
-
-static void gator_events_ccn504_stop(void)
-{
- int i;
-
- if (!gator_events_ccn504_global_enabled) {
- return;
- }
-
- // cycle counter does not need to be disabled
- for (i = 0; i < CCNT; ++i) {
- int region;
-
- if (!gator_events_ccn504_enabled[i]) {
- continue;
- }
-
- region = get_region(gator_events_ccn504_event[i]);
-
- writel(0, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL);
- }
-
- // Clear dt_config
- for (i = 0; i < NUM_XPS; ++i) {
- writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG);
- }
-}
-
-static int gator_events_ccn504_read(int **buffer)
-{
- int i;
- int len = 0;
- int value;
-
- if (!on_primary_core() || !gator_events_ccn504_global_enabled) {
- return 0;
- }
-
- // Verify the pmsr register is zero
- while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) != 0);
-
- // Request a PMU snapshot
- writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_REQ);
-
- // Wait for the snapshot
- while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) == 0);
-
- // Read the shadow registers
- for (i = 0; i < CNTMAX; ++i) {
- if (!gator_events_ccn504_enabled[i]) {
- continue;
- }
-
- value = readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + (i == CCNT ? PMCCNTRSR : PMEVCNTSR0 + 8*i));
- if (gator_events_ccn504_prev[i] != 0x80808080) {
- gator_events_ccn504_buffer[len++] = gator_events_ccn504_key[i];
- gator_events_ccn504_buffer[len++] = value - gator_events_ccn504_prev[i];
- }
- gator_events_ccn504_prev[i] = value;
-
- // Are the counters registers cleared when read? Is that what the cntr_rst bit on the pmcr register does?
- }
-
- // Clear the PMU snapshot status
- writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_CLR);
-
- if (buffer)
- *buffer = gator_events_ccn504_buffer;
-
- return len;
-}
-
-static struct gator_interface gator_events_ccn504_interface = {
- .shutdown = gator_events_ccn504_create_shutdown,
- .create_files = gator_events_ccn504_create_files,
- .start = gator_events_ccn504_start,
- .stop = gator_events_ccn504_stop,
- .read = gator_events_ccn504_read,
-};
-
-int gator_events_ccn504_init(void)
-{
- int i;
-
- if (ccn504_addr == 0) {
- return -1;
- }
-
- gator_events_ccn504_base = ioremap(ccn504_addr, NUM_REGIONS*REGION_SIZE);
- if (gator_events_ccn504_base == NULL) {
- printk(KERN_ERR "gator: ioremap returned NULL\n");
- return -1;
- }
-
- for (i = 0; i < CNTMAX; ++i) {
- gator_events_ccn504_enabled[i] = 0;
- gator_events_ccn504_event[i] = 0;
- gator_events_ccn504_key[i] = gator_events_get_key();
- }
-
- return gator_events_install(&gator_events_ccn504_interface);
-}
diff --git a/drivers/gator/gator_events_irq.c b/drivers/gator/gator_events_irq.c
index facbdd6..5221aac 100644
--- a/drivers/gator/gator_events_irq.c
+++ b/drivers/gator/gator_events_irq.c
@@ -42,17 +42,15 @@ static int gator_events_irq_create_files(struct super_block *sb, struct dentry *
/* irq */
dir = gatorfs_mkdir(sb, root, "Linux_irq_irq");
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &hardirq_enabled);
gatorfs_create_ro_ulong(sb, dir, "key", &hardirq_key);
/* soft irq */
dir = gatorfs_mkdir(sb, root, "Linux_irq_softirq");
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &softirq_enabled);
gatorfs_create_ro_ulong(sb, dir, "key", &softirq_key);
@@ -63,7 +61,7 @@ static int gator_events_irq_online(int **buffer, bool migrate)
{
int len = 0, cpu = get_physical_cpu();
- // synchronization with the irq_exit functions is not necessary as the values are being reset
+ /* synchronization with the irq_exit functions is not necessary as the values are being reset */
if (hardirq_enabled) {
atomic_set(&per_cpu(irqCnt, cpu)[HARDIRQ], 0);
per_cpu(irqGet, cpu)[len++] = hardirq_key;
@@ -84,7 +82,7 @@ static int gator_events_irq_online(int **buffer, bool migrate)
static int gator_events_irq_start(void)
{
- // register tracepoints
+ /* register tracepoints */
if (hardirq_enabled)
if (GATOR_REGISTER_TRACE(irq_handler_exit))
goto fail_hardirq_exit;
@@ -95,7 +93,7 @@ static int gator_events_irq_start(void)
return 0;
- // unregister tracepoints on error
+ /* unregister tracepoints on error */
fail_softirq_exit:
if (hardirq_enabled)
GATOR_UNREGISTER_TRACE(irq_handler_exit);
@@ -117,7 +115,7 @@ static void gator_events_irq_stop(void)
softirq_enabled = 0;
}
-static int gator_events_irq_read(int **buffer)
+static int gator_events_irq_read(int **buffer, bool sched_switch)
{
int len, value;
int cpu = get_physical_cpu();
diff --git a/drivers/gator/gator_events_l2c-310.c b/drivers/gator/gator_events_l2c-310.c
index 553f970..73aaac3 100644
--- a/drivers/gator/gator_events_l2c-310.c
+++ b/drivers/gator/gator_events_l2c-310.c
@@ -91,7 +91,7 @@ static void gator_events_l2c310_stop(void)
writel(0, l2c310_base + L2X0_EVENT_CNT_CTRL);
}
-static int gator_events_l2c310_read(int **buffer)
+static int gator_events_l2c310_read(int **buffer, bool sched_switch)
{
static const unsigned long l2x0_event_cntx_val[L2C310_COUNTERS_NUM] = {
L2X0_EVENT_CNT0_VAL,
@@ -149,8 +149,8 @@ static void __iomem *gator_events_l2c310_probe(void)
0xa0412000,
#endif
#if defined(CONFIG_ARCH_VEXPRESS)
- 0x1e00a000, // A9x4 core tile (HBI-0191)
- 0x2c0f0000, // New memory map tiles
+ 0x1e00a000, /* A9x4 core tile (HBI-0191) */
+ 0x2c0f0000, /* New memory map tiles */
#endif
};
int i;
diff --git a/drivers/gator/gator_events_mali_4xx.c b/drivers/gator/gator_events_mali_4xx.c
index 9e1c706..9cf43fe 100644
--- a/drivers/gator/gator_events_mali_4xx.c
+++ b/drivers/gator/gator_events_mali_4xx.c
@@ -36,7 +36,7 @@
#elif GATOR_MALI_INTERFACE_STYLE == 2
#error GATOR_MALI_INTERFACE_STYLE 2 is obsolete
#elif GATOR_MALI_INTERFACE_STYLE >= 3
-// Valid GATOR_MALI_INTERFACE_STYLE
+/* Valid GATOR_MALI_INTERFACE_STYLE */
#else
#error Unknown GATOR_MALI_INTERFACE_STYLE option.
#endif
@@ -54,7 +54,7 @@
#error MALI_SUPPORT set to an invalid device code: expecting MALI_4xx
#endif
-static const char mali_name[] = "Mali-4xx";
+static const char mali_name[] = "4xx";
/* gatorfs variables for counter enable state,
* the event the counter should count and the
@@ -73,8 +73,8 @@ static u32 *counter_address[NUMBER_OF_EVENTS];
/* An array used to return the data we recorded
* as key,value pairs hence the *2
*/
-static unsigned long counter_dump[NUMBER_OF_EVENTS * 2];
-static unsigned long counter_prev[NUMBER_OF_EVENTS];
+static int counter_dump[NUMBER_OF_EVENTS * 2];
+static int counter_prev[NUMBER_OF_EVENTS];
static bool prev_set[NUMBER_OF_EVENTS];
/* Note whether tracepoints have been registered */
@@ -89,8 +89,8 @@ static unsigned int n_vp_cores = MAX_NUM_VP_CORES;
static unsigned int n_l2_cores = MAX_NUM_L2_CACHE_CORES;
static unsigned int n_fp_cores = MAX_NUM_FP_CORES;
-extern mali_counter mali_activity[2];
-static const char* const mali_activity_names[] = {
+extern struct mali_counter mali_activity[2];
+static const char *const mali_activity_names[] = {
"fragment",
"vertex",
};
@@ -112,36 +112,11 @@ static inline int is_hw_counter(unsigned int event_id)
return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER);
}
-/*
- * These are provided for utgard compatibility.
- */
-typedef void _mali_profiling_get_mali_version_type(struct _mali_profiling_mali_version *values);
-typedef u32 _mali_profiling_get_l2_counters_type(_mali_profiling_l2_counter_values *values);
-
-/* Probe for continuously sampled counter */
-#if 0 //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING
-GATOR_DEFINE_PROBE(mali_sample_address, TP_PROTO(unsigned int event_id, u32 *addr))
-{
- /* Turning on too many pr_debug statements in frequently called functions
- * can cause stability and/or performance problems
- */
- //pr_debug("gator: mali_sample_address %d %d\n", event_id, addr);
- if (event_id >= ACTIVITY_VP && event_id <= COUNTER_FP3_C1) {
- counter_address[event_id] = addr;
- }
-}
-#endif
-
/* Probe for hardware counter events */
GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int value))
{
- /* Turning on too many pr_debug statements in frequently called functions
- * can cause stability and/or performance problems
- */
- //pr_debug("gator: mali_hw_counter %d %d\n", event_id, value);
- if (is_hw_counter(event_id)) {
+ if (is_hw_counter(event_id))
counter_data[event_id] = value;
- }
}
GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surface_id, unsigned int *counters))
@@ -150,9 +125,8 @@ GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surfac
/* Copy over the values for those counters which are enabled. */
for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) {
- if (counter_enabled[i]) {
+ if (counter_enabled[i])
counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]);
- }
}
}
@@ -172,13 +146,11 @@ static int create_fs_entry(struct super_block *sb, struct dentry *root, const ch
dir = gatorfs_mkdir(sb, root, name);
- if (!dir) {
+ if (!dir)
return -1;
- }
- if (create_event_item) {
+ if (create_event_item)
gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
- }
gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
@@ -192,7 +164,7 @@ static int create_fs_entry(struct super_block *sb, struct dentry *root, const ch
*/
static void initialise_version_info(void)
{
- _mali_profiling_get_mali_version_type *mali_profiling_get_mali_version_symbol;
+ void (*mali_profiling_get_mali_version_symbol)(struct _mali_profiling_mali_version *values);
mali_profiling_get_mali_version_symbol = symbol_get(_mali_profiling_get_mali_version);
@@ -214,8 +186,8 @@ static void initialise_version_info(void)
/* Release the function - we're done with it. */
symbol_put(_mali_profiling_get_mali_version);
} else {
- printk("gator: mali online _mali_profiling_get_mali_version symbol not found\n");
- printk("gator: check your Mali DDK version versus the GATOR_MALI_INTERFACE_STYLE setting\n");
+ pr_err("gator: mali online _mali_profiling_get_mali_version symbol not found\n");
+ pr_err("gator: check your Mali DDK version versus the GATOR_MALI_INTERFACE_STYLE setting\n");
}
}
#endif
@@ -242,26 +214,24 @@ static int create_files(struct super_block *sb, struct dentry *root)
mali_activity[0].cores = n_fp_cores;
mali_activity[1].cores = n_vp_cores;
for (event = 0; event < ARRAY_SIZE(mali_activity); event++) {
- if (gator_mali_create_file_system(mali_name, mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) {
+ if (gator_mali_create_file_system(mali_name, mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0)
return -1;
- }
}
/* Vertex processor counters */
for (core_id = 0; core_id < n_vp_cores; core_id++) {
int activity_counter_id = ACTIVITY_VP_0;
- snprintf(buf, sizeof buf, "ARM_%s_VP_%d_active", mali_name, core_id);
- if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0) {
+
+ snprintf(buf, sizeof(buf), "ARM_Mali-%s_VP_%d_active", mali_name, core_id);
+ if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0)
return -1;
- }
for (counter_number = 0; counter_number < 2; counter_number++) {
int counter_id = COUNTER_VP_0_C0 + (2 * core_id) + counter_number;
- snprintf(buf, sizeof buf, "ARM_%s_VP_%d_cnt%d", mali_name, core_id, counter_number);
- if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) {
+ snprintf(buf, sizeof(buf), "ARM_Mali-%s_VP_%d_cnt%d", mali_name, core_id, counter_number);
+ if (create_fs_entry(sb, root, buf, counter_id, 1) != 0)
return -1;
- }
}
}
@@ -269,18 +239,16 @@ static int create_files(struct super_block *sb, struct dentry *root)
for (core_id = 0; core_id < n_fp_cores; core_id++) {
int activity_counter_id = ACTIVITY_FP_0 + core_id;
- snprintf(buf, sizeof buf, "ARM_%s_FP_%d_active", mali_name, core_id);
- if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0) {
+ snprintf(buf, sizeof(buf), "ARM_Mali-%s_FP_%d_active", mali_name, core_id);
+ if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0)
return -1;
- }
for (counter_number = 0; counter_number < 2; counter_number++) {
int counter_id = COUNTER_FP_0_C0 + (2 * core_id) + counter_number;
- snprintf(buf, sizeof buf, "ARM_%s_FP_%d_cnt%d", mali_name, core_id, counter_number);
- if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) {
+ snprintf(buf, sizeof(buf), "ARM_Mali-%s_FP_%d_cnt%d", mali_name, core_id, counter_number);
+ if (create_fs_entry(sb, root, buf, counter_id, 1) != 0)
return -1;
- }
}
}
@@ -289,38 +257,33 @@ static int create_files(struct super_block *sb, struct dentry *root)
for (counter_number = 0; counter_number < 2; counter_number++) {
int counter_id = COUNTER_L2_0_C0 + (2 * core_id) + counter_number;
- snprintf(buf, sizeof buf, "ARM_%s_L2_%d_cnt%d", mali_name, core_id, counter_number);
- if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) {
+ snprintf(buf, sizeof(buf), "ARM_Mali-%s_L2_%d_cnt%d", mali_name, core_id, counter_number);
+ if (create_fs_entry(sb, root, buf, counter_id, 1) != 0)
return -1;
- }
}
}
/* Now set up the software counter entries */
for (event = FIRST_SW_COUNTER; event <= LAST_SW_COUNTER; event++) {
- snprintf(buf, sizeof(buf), "ARM_%s_SW_%d", mali_name, event - FIRST_SW_COUNTER);
+ snprintf(buf, sizeof(buf), "ARM_Mali-%s_SW_%d", mali_name, event - FIRST_SW_COUNTER);
- if (create_fs_entry(sb, root, buf, event, 0) != 0) {
+ if (create_fs_entry(sb, root, buf, event, 0) != 0)
return -1;
- }
}
/* Now set up the special counter entries */
- snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip_cnt0", mali_name);
- if (create_fs_entry(sb, root, buf, COUNTER_FILMSTRIP, 1) != 0) {
+ snprintf(buf, sizeof(buf), "ARM_Mali-%s_Filmstrip_cnt0", mali_name);
+ if (create_fs_entry(sb, root, buf, COUNTER_FILMSTRIP, 1) != 0)
return -1;
- }
#ifdef DVFS_REPORTED_BY_DDK
- snprintf(buf, sizeof(buf), "ARM_%s_Frequency", mali_name);
- if (create_fs_entry(sb, root, buf, COUNTER_FREQUENCY, 1) != 0) {
+ snprintf(buf, sizeof(buf), "ARM_Mali-%s_Frequency", mali_name);
+ if (create_fs_entry(sb, root, buf, COUNTER_FREQUENCY, 1) != 0)
return -1;
- }
- snprintf(buf, sizeof(buf), "ARM_%s_Voltage", mali_name);
- if (create_fs_entry(sb, root, buf, COUNTER_VOLTAGE, 1) != 0) {
+ snprintf(buf, sizeof(buf), "ARM_Mali-%s_Voltage", mali_name);
+ if (create_fs_entry(sb, root, buf, COUNTER_VOLTAGE, 1) != 0)
return -1;
- }
#endif
return 0;
@@ -330,8 +293,8 @@ static int create_files(struct super_block *sb, struct dentry *root)
* Local store for the get_counters entry point into the DDK.
* This is stored here since it is used very regularly.
*/
-static mali_profiling_get_counters_type *mali_get_counters = NULL;
-static _mali_profiling_get_l2_counters_type *mali_get_l2_counters = NULL;
+static void (*mali_get_counters)(unsigned int *, unsigned int *, unsigned int *, unsigned int *);
+static u32 (*mali_get_l2_counters)(struct _mali_profiling_l2_counter_values *values);
/*
* Examine list of counters between two index limits and determine if any one is enabled.
@@ -342,9 +305,8 @@ static int is_any_counter_enabled(unsigned int first_counter, unsigned int last_
unsigned int i;
for (i = first_counter; i <= last_counter; i++) {
- if (counter_enabled[i]) {
+ if (counter_enabled[i])
return 1; /* At least one counter is enabled */
- }
}
return 0; /* No s/w counters enabled */
@@ -366,16 +328,15 @@ static void init_counters(unsigned int from_counter, unsigned int to_counter)
pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n", mali_set_hw_event);
for (counter_id = from_counter; counter_id <= to_counter; counter_id++) {
- if (counter_enabled[counter_id]) {
+ if (counter_enabled[counter_id])
mali_set_hw_event(counter_id, counter_event[counter_id]);
- } else {
+ else
mali_set_hw_event(counter_id, 0xFFFFFFFF);
- }
}
symbol_put(_mali_profiling_set_event);
} else {
- printk("gator: mali online _mali_profiling_set_event symbol not found\n");
+ pr_err("gator: mali online _mali_profiling_set_event symbol not found\n");
}
}
@@ -407,27 +368,23 @@ static void mali_counter_initialize(void)
symbol_put(_mali_profiling_control);
} else {
- printk("gator: mali online _mali_profiling_control symbol not found\n");
+ pr_err("gator: mali online _mali_profiling_control symbol not found\n");
}
mali_get_counters = symbol_get(_mali_profiling_get_counters);
- if (mali_get_counters) {
+ if (mali_get_counters)
pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", mali_get_counters);
-
- } else {
- pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined");
- }
+ else
+ pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined\n");
mali_get_l2_counters = symbol_get(_mali_profiling_get_l2_counters);
- if (mali_get_l2_counters) {
+ if (mali_get_l2_counters)
pr_debug("gator: mali online _mali_profiling_get_l2_counters symbol @ %p\n", mali_get_l2_counters);
-
- } else {
- pr_debug("gator WARNING: mali _mali_profiling_get_l2_counters symbol not defined");
- }
+ else
+ pr_debug("gator WARNING: mali _mali_profiling_get_l2_counters symbol not defined\n");
if (!mali_get_counters && !mali_get_l2_counters) {
- pr_debug("gator: WARNING: no L2 counters available");
+ pr_debug("gator: WARNING: no L2 counters available\n");
n_l2_cores = 0;
}
@@ -449,13 +406,12 @@ static void mali_counter_deinitialize(void)
int i;
pr_debug("gator: mali offline _mali_profiling_set_event symbol @ %p\n", mali_set_hw_event);
- for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
+ for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++)
mali_set_hw_event(i, 0xFFFFFFFF);
- }
symbol_put(_mali_profiling_set_event);
} else {
- printk("gator: mali offline _mali_profiling_set_event symbol not found\n");
+ pr_err("gator: mali offline _mali_profiling_set_event symbol not found\n");
}
/* Generic control interface for Mali DDK. */
@@ -471,29 +427,27 @@ static void mali_counter_deinitialize(void)
symbol_put(_mali_profiling_control);
} else {
- printk("gator: mali offline _mali_profiling_control symbol not found\n");
+ pr_err("gator: mali offline _mali_profiling_control symbol not found\n");
}
- if (mali_get_counters) {
+ if (mali_get_counters)
symbol_put(_mali_profiling_get_counters);
- }
- if (mali_get_l2_counters) {
+ if (mali_get_l2_counters)
symbol_put(_mali_profiling_get_l2_counters);
- }
}
static int start(void)
{
- // register tracepoints
+ /* register tracepoints */
if (GATOR_REGISTER_TRACE(mali_hw_counter)) {
- printk("gator: mali_hw_counter tracepoint failed to activate\n");
+ pr_err("gator: mali_hw_counter tracepoint failed to activate\n");
return -1;
}
/* For Mali drivers with built-in support. */
if (GATOR_REGISTER_TRACE(mali_sw_counters)) {
- printk("gator: mali_sw_counters tracepoint failed to activate\n");
+ pr_err("gator: mali_sw_counters tracepoint failed to activate\n");
return -1;
}
@@ -543,17 +497,17 @@ static void dump_counters(unsigned int from_counter, unsigned int to_counter, un
}
}
-static int read(int **buffer)
+static int read(int **buffer, bool sched_switch)
{
int len = 0;
if (!on_primary_core())
return 0;
- // Read the L2 C0 and C1 here.
+ /* Read the L2 C0 and C1 here. */
if (n_l2_cores > 0 && is_any_counter_enabled(COUNTER_L2_0_C0, COUNTER_L2_0_C0 + (2 * n_l2_cores))) {
unsigned int unavailable_l2_caches = 0;
- _mali_profiling_l2_counter_values cache_values;
+ struct _mali_profiling_l2_counter_values cache_values;
unsigned int cache_id;
struct _mali_profiling_core_counters *per_core;
@@ -572,25 +526,24 @@ static int read(int **buffer)
unsigned int counter_id_0 = COUNTER_L2_0_C0 + (2 * cache_id);
unsigned int counter_id_1 = counter_id_0 + 1;
- if ((1 << cache_id) & unavailable_l2_caches) {
+ if ((1 << cache_id) & unavailable_l2_caches)
continue; /* This cache is unavailable (powered-off, possibly). */
- }
per_core = &cache_values.cores[cache_id];
if (counter_enabled[counter_id_0] && prev_set[counter_id_0]) {
- // Calculate and save src0's counter val0
+ /* Calculate and save src0's counter val0 */
counter_dump[len++] = counter_key[counter_id_0];
counter_dump[len++] = per_core->value0 - counter_prev[counter_id_0];
}
if (counter_enabled[counter_id_1] && prev_set[counter_id_1]) {
- // Calculate and save src1's counter val1
+ /* Calculate and save src1's counter val1 */
counter_dump[len++] = counter_key[counter_id_1];
counter_dump[len++] = per_core->value1 - counter_prev[counter_id_1];
}
- // Save the previous values for the counters.
+ /* Save the previous values for the counters. */
counter_prev[counter_id_0] = per_core->value0;
prev_set[counter_id_0] = true;
counter_prev[counter_id_1] = per_core->value1;
@@ -608,8 +561,9 @@ static int read(int **buffer)
{
int cnt;
/*
- * Add in the voltage and frequency counters if enabled. Note that, since these are
- * actually passed as events, the counter value should not be cleared.
+ * Add in the voltage and frequency counters if enabled. Note
+ * that, since these are actually passed as events, the counter
+ * value should not be cleared.
*/
cnt = COUNTER_FREQUENCY;
if (counter_enabled[cnt]) {
@@ -625,9 +579,8 @@ static int read(int **buffer)
}
#endif
- if (buffer) {
- *buffer = (int *)counter_dump;
- }
+ if (buffer)
+ *buffer = counter_dump;
return len;
}
diff --git a/drivers/gator/gator_events_mali_common.c b/drivers/gator/gator_events_mali_common.c
index 4f2cce4c..1af87d6 100644
--- a/drivers/gator/gator_events_mali_common.c
+++ b/drivers/gator/gator_events_mali_common.c
@@ -8,7 +8,7 @@
*/
#include "gator_events_mali_common.h"
-extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter, unsigned long *event)
+extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, struct mali_counter *counter, unsigned long *event)
{
int err;
char buf[255];
@@ -17,36 +17,39 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even
/* If the counter name is empty ignore it */
if (strlen(event_name) != 0) {
/* Set up the filesystem entry for this event. */
- snprintf(buf, sizeof(buf), "ARM_%s_%s", mali_name, event_name);
+ if (mali_name == NULL)
+ snprintf(buf, sizeof(buf), "ARM_Mali-%s", event_name);
+ else
+ snprintf(buf, sizeof(buf), "ARM_Mali-%s_%s", mali_name, event_name);
dir = gatorfs_mkdir(sb, root, buf);
if (dir == NULL) {
- pr_debug("gator: %s: error creating file system for: %s (%s)", mali_name, event_name, buf);
+ pr_debug("gator: %s: error creating file system for: %s (%s)\n", mali_name, event_name, buf);
return -1;
}
err = gatorfs_create_ulong(sb, dir, "enabled", &counter->enabled);
if (err != 0) {
- pr_debug("gator: %s: error calling gatorfs_create_ulong for: %s (%s)", mali_name, event_name, buf);
+ pr_debug("gator: %s: error calling gatorfs_create_ulong for: %s (%s)\n", mali_name, event_name, buf);
return -1;
}
err = gatorfs_create_ro_ulong(sb, dir, "key", &counter->key);
if (err != 0) {
- pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf);
+ pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf);
return -1;
}
if (counter->cores != -1) {
err = gatorfs_create_ro_ulong(sb, dir, "cores", &counter->cores);
if (err != 0) {
- pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf);
+ pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf);
return -1;
}
}
if (event != NULL) {
err = gatorfs_create_ulong(sb, dir, "event", event);
if (err != 0) {
- pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf);
+ pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf);
return -1;
}
}
@@ -55,12 +58,12 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even
return 0;
}
-extern void gator_mali_initialise_counters(mali_counter counters[], unsigned int n_counters)
+extern void gator_mali_initialise_counters(struct mali_counter counters[], unsigned int n_counters)
{
unsigned int cnt;
for (cnt = 0; cnt < n_counters; cnt++) {
- mali_counter *counter = &counters[cnt];
+ struct mali_counter *counter = &counters[cnt];
counter->key = gator_events_get_key();
counter->enabled = 0;
diff --git a/drivers/gator/gator_events_mali_common.h b/drivers/gator/gator_events_mali_common.h
index 91d871b..e7082e6 100644
--- a/drivers/gator/gator_events_mali_common.h
+++ b/drivers/gator/gator_events_mali_common.h
@@ -16,7 +16,7 @@
#include <linux/time.h>
#include <linux/math64.h>
#include <linux/slab.h>
-#include <asm/io.h>
+#include <linux/io.h>
/* Ensure that MALI_SUPPORT has been defined to something. */
#ifndef MALI_SUPPORT
@@ -30,21 +30,20 @@
/*
* Runtime state information for a counter.
*/
-typedef struct {
- // 'key' (a unique id set by gatord and returned by gator.ko)
+struct mali_counter {
+ /* 'key' (a unique id set by gatord and returned by gator.ko) */
unsigned long key;
- // counter enable state
+ /* counter enable state */
unsigned long enabled;
- // for activity counters, the number of cores, otherwise -1
+ /* for activity counters, the number of cores, otherwise -1 */
unsigned long cores;
-} mali_counter;
+};
/*
* Mali-4xx
*/
typedef int mali_profiling_set_event_type(unsigned int, int);
typedef void mali_profiling_control_type(unsigned int, unsigned int);
-typedef void mali_profiling_get_counters_type(unsigned int *, unsigned int *, unsigned int *, unsigned int *);
/*
* Driver entry points for functions called directly by gator.
@@ -65,7 +64,7 @@ extern void _mali_profiling_get_counters(unsigned int *, unsigned int *, unsigne
*
* @return 0 if entry point was created, non-zero if not.
*/
-extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter, unsigned long *event);
+extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, struct mali_counter *counter, unsigned long *event);
/**
* Initializes the counter array.
@@ -73,6 +72,6 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even
* @param keys The array of counters
* @param n_counters The number of entries in each of the arrays.
*/
-extern void gator_mali_initialise_counters(mali_counter counters[], unsigned int n_counters);
+extern void gator_mali_initialise_counters(struct mali_counter counters[], unsigned int n_counters);
#endif /* GATOR_EVENTS_MALI_COMMON_H */
diff --git a/drivers/gator/gator_events_mali_t6xx.c b/drivers/gator/gator_events_mali_midgard.c
index e56ba84..0aec906 100644
--- a/drivers/gator/gator_events_mali_t6xx.c
+++ b/drivers/gator/gator_events_mali_midgard.c
@@ -13,7 +13,7 @@
#include <linux/time.h>
#include <linux/math64.h>
#include <linux/slab.h>
-#include <asm/io.h>
+#include <linux/io.h>
#ifdef MALI_DIR_MIDGARD
/* New DDK Directory structure with kernel/drivers/gpu/arm/midgard*/
@@ -28,13 +28,13 @@
/*
* Check that the MALI_SUPPORT define is set to one of the allowable device codes.
*/
-#if (MALI_SUPPORT != MALI_T6xx)
-#error MALI_SUPPORT set to an invalid device code: expecting MALI_T6xx
+#if (MALI_SUPPORT != MALI_MIDGARD)
+#error MALI_SUPPORT set to an invalid device code: expecting MALI_MIDGARD
#endif
-static const char mali_name[] = "Mali-T6xx";
+static const char mali_name[] = "Midgard";
-/* Counters for Mali-T6xx:
+/* Counters for Mali-Midgard:
*
* - Timeline events
* They are tracepoints, but instead of reporting a number they report a START/STOP event.
@@ -49,7 +49,7 @@ static const char mali_name[] = "Mali-T6xx";
*/
/* Timeline (start/stop) activity */
-static const char *timeline_event_names[] = {
+static const char *const timeline_event_names[] = {
"PM_SHADER_0",
"PM_SHADER_1",
"PM_SHADER_2",
@@ -88,7 +88,7 @@ enum {
#define NUM_PM_SHADER (8)
/* Software Counters */
-static const char *software_counter_names[] = {
+static const char *const software_counter_names[] = {
"MMU_PAGE_FAULT_0",
"MMU_PAGE_FAULT_1",
"MMU_PAGE_FAULT_2",
@@ -103,7 +103,7 @@ enum {
};
/* Software Counters */
-static const char *accumulators_names[] = {
+static const char *const accumulators_names[] = {
"TOTAL_ALLOC_PAGES"
};
@@ -123,17 +123,18 @@ enum {
/*
* gatorfs variables for counter enable state
*/
-static mali_counter counters[NUMBER_OF_EVENTS];
+static struct mali_counter counters[NUMBER_OF_EVENTS];
static unsigned long filmstrip_event;
/* An array used to return the data we recorded
* as key,value pairs hence the *2
*/
-static unsigned long counter_dump[NUMBER_OF_EVENTS * 2];
+static int counter_dump[NUMBER_OF_EVENTS * 2];
/*
- * Array holding counter start times (in ns) for each counter. A zero here
- * indicates that the activity monitored by this counter is not running.
+ * Array holding counter start times (in ns) for each counter. A zero
+ * here indicates that the activity monitored by this counter is not
+ * running.
*/
static struct timespec timeline_event_starttime[NUMBER_OF_TIMELINE_EVENTS];
@@ -156,6 +157,7 @@ static struct timespec prev_timestamp;
static inline long get_duration_us(const struct timespec *start, const struct timespec *end)
{
long event_duration_us = (end->tv_nsec - start->tv_nsec) / 1000;
+
event_duration_us += (end->tv_sec - start->tv_sec) * 1000000;
return event_duration_us;
@@ -172,9 +174,8 @@ static void record_timeline_event(unsigned int timeline_index, unsigned int type
getnstimeofday(&event_timestamp);
/* Remember the start time if the activity is not already started */
- if (event_start->tv_sec == 0) {
+ if (event_start->tv_sec == 0)
*event_start = event_timestamp; /* Structure copy */
- }
break;
case ACTIVITY_STOP:
@@ -208,9 +209,9 @@ GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long
#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */
#define BIT_AT(value, pos) ((value >> pos) & 1)
- static unsigned long long previous_shader_bitmask = 0;
- static unsigned long long previous_tiler_bitmask = 0;
- static unsigned long long previous_l2_bitmask = 0;
+ static unsigned long long previous_shader_bitmask;
+ static unsigned long long previous_tiler_bitmask;
+ static unsigned long long previous_l2_bitmask;
switch (event_id) {
case SHADER_PRESENT_LO:
@@ -219,9 +220,8 @@ GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long
int pos;
for (pos = 0; pos < NUM_PM_SHADER; ++pos) {
- if (BIT_AT(changed_bitmask, pos)) {
+ if (BIT_AT(changed_bitmask, pos))
record_timeline_event(PM_SHADER_0 + pos, BIT_AT(value, pos) ? ACTIVITY_START : ACTIVITY_STOP);
- }
}
previous_shader_bitmask = value;
@@ -232,9 +232,8 @@ GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long
{
unsigned long long changed = previous_tiler_bitmask ^ value;
- if (BIT_AT(changed, 0)) {
+ if (BIT_AT(changed, 0))
record_timeline_event(PM_TILER_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP);
- }
previous_tiler_bitmask = value;
break;
@@ -244,12 +243,10 @@ GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long
{
unsigned long long changed = previous_l2_bitmask ^ value;
- if (BIT_AT(changed, 0)) {
+ if (BIT_AT(changed, 0))
record_timeline_event(PM_L2_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP);
- }
- if (BIT_AT(changed, 4)) {
+ if (BIT_AT(changed, 4))
record_timeline_event(PM_L2_1, BIT_AT(value, 4) ? ACTIVITY_START : ACTIVITY_STOP);
- }
previous_l2_bitmask = value;
break;
@@ -297,31 +294,27 @@ static int create_files(struct super_block *sb, struct dentry *root)
mali_profiling_control_type *mali_control;
for (event = FIRST_TIMELINE_EVENT; event < FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS; event++) {
- if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event], NULL) != 0) {
+ if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event], NULL) != 0)
return -1;
- }
counter_index++;
}
counter_index = 0;
for (event = FIRST_SOFTWARE_COUNTER; event < FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS; event++) {
- if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event], NULL) != 0) {
+ if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event], NULL) != 0)
return -1;
- }
counter_index++;
}
counter_index = 0;
for (event = FIRST_ACCUMULATOR; event < FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS; event++) {
- if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event], NULL) != 0) {
+ if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event], NULL) != 0)
return -1;
- }
counter_index++;
}
mali_control = symbol_get(_mali_profiling_control);
if (mali_control) {
- if (gator_mali_create_file_system(mali_name, "Filmstrip_cnt0", sb, root, &counters[FILMSTRIP], &filmstrip_event) != 0) {
+ if (gator_mali_create_file_system(mali_name, "Filmstrip_cnt0", sb, root, &counters[FILMSTRIP], &filmstrip_event) != 0)
return -1;
- }
symbol_put(_mali_profiling_control);
}
@@ -331,36 +324,36 @@ static int create_files(struct super_block *sb, struct dentry *root)
static int register_tracepoints(void)
{
if (GATOR_REGISTER_TRACE(mali_pm_status)) {
- pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint failed to activate\n");
+ pr_debug("gator: Mali-Midgard: mali_pm_status tracepoint failed to activate\n");
return 0;
}
if (GATOR_REGISTER_TRACE(mali_page_fault_insert_pages)) {
- pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint failed to activate\n");
+ pr_debug("gator: Mali-Midgard: mali_page_fault_insert_pages tracepoint failed to activate\n");
return 0;
}
if (GATOR_REGISTER_TRACE(mali_mmu_as_in_use)) {
- pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint failed to activate\n");
+ pr_debug("gator: Mali-Midgard: mali_mmu_as_in_use tracepoint failed to activate\n");
return 0;
}
if (GATOR_REGISTER_TRACE(mali_mmu_as_released)) {
- pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint failed to activate\n");
+ pr_debug("gator: Mali-Midgard: mali_mmu_as_released tracepoint failed to activate\n");
return 0;
}
if (GATOR_REGISTER_TRACE(mali_total_alloc_pages_change)) {
- pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint failed to activate\n");
+ pr_debug("gator: Mali-Midgard: mali_total_alloc_pages_change tracepoint failed to activate\n");
return 0;
}
- pr_debug("gator: Mali-T6xx: start\n");
- pr_debug("gator: Mali-T6xx: mali_pm_status probe is at %p\n", &probe_mali_pm_status);
- pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages probe is at %p\n", &probe_mali_page_fault_insert_pages);
- pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use probe is at %p\n", &probe_mali_mmu_as_in_use);
- pr_debug("gator: Mali-T6xx: mali_mmu_as_released probe is at %p\n", &probe_mali_mmu_as_released);
- pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change probe is at %p\n", &probe_mali_total_alloc_pages_change);
+ pr_debug("gator: Mali-Midgard: start\n");
+ pr_debug("gator: Mali-Midgard: mali_pm_status probe is at %p\n", &probe_mali_pm_status);
+ pr_debug("gator: Mali-Midgard: mali_page_fault_insert_pages probe is at %p\n", &probe_mali_page_fault_insert_pages);
+ pr_debug("gator: Mali-Midgard: mali_mmu_as_in_use probe is at %p\n", &probe_mali_mmu_as_in_use);
+ pr_debug("gator: Mali-Midgard: mali_mmu_as_released probe is at %p\n", &probe_mali_mmu_as_released);
+ pr_debug("gator: Mali-Midgard: mali_total_alloc_pages_change probe is at %p\n", &probe_mali_total_alloc_pages_change);
return 1;
}
@@ -376,18 +369,15 @@ static int start(void)
timeline_data[cnt] = 0;
}
- for (cnt = 0; cnt < NUMBER_OF_SOFTWARE_COUNTERS; cnt++) {
+ for (cnt = 0; cnt < NUMBER_OF_SOFTWARE_COUNTERS; cnt++)
sw_counter_data[cnt] = 0;
- }
- for (cnt = 0; cnt < NUMBER_OF_ACCUMULATORS; cnt++) {
+ for (cnt = 0; cnt < NUMBER_OF_ACCUMULATORS; cnt++)
accumulators_data[cnt] = 0;
- }
/* Register tracepoints */
- if (register_tracepoints() == 0) {
+ if (register_tracepoints() == 0)
return -1;
- }
/* Generic control interface for Mali DDK. */
mali_control = symbol_get(_mali_profiling_control);
@@ -410,7 +400,7 @@ static int start(void)
symbol_put(_mali_profiling_control);
} else {
- printk("gator: mali online _mali_profiling_control symbol not found\n");
+ pr_err("gator: mali online _mali_profiling_control symbol not found\n");
}
/*
@@ -427,26 +417,26 @@ static void stop(void)
{
mali_profiling_control_type *mali_control;
- pr_debug("gator: Mali-T6xx: stop\n");
+ pr_debug("gator: Mali-Midgard: stop\n");
/*
* It is safe to unregister traces even if they were not successfully
* registered, so no need to check.
*/
GATOR_UNREGISTER_TRACE(mali_pm_status);
- pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint deactivated\n");
+ pr_debug("gator: Mali-Midgard: mali_pm_status tracepoint deactivated\n");
GATOR_UNREGISTER_TRACE(mali_page_fault_insert_pages);
- pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint deactivated\n");
+ pr_debug("gator: Mali-Midgard: mali_page_fault_insert_pages tracepoint deactivated\n");
GATOR_UNREGISTER_TRACE(mali_mmu_as_in_use);
- pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint deactivated\n");
+ pr_debug("gator: Mali-Midgard: mali_mmu_as_in_use tracepoint deactivated\n");
GATOR_UNREGISTER_TRACE(mali_mmu_as_released);
- pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint deactivated\n");
+ pr_debug("gator: Mali-Midgard: mali_mmu_as_released tracepoint deactivated\n");
GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change);
- pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint deactivated\n");
+ pr_debug("gator: Mali-Midgard: mali_total_alloc_pages_change tracepoint deactivated\n");
/* Generic control interface for Mali DDK. */
mali_control = symbol_get(_mali_profiling_control);
@@ -457,20 +447,19 @@ static void stop(void)
symbol_put(_mali_profiling_control);
} else {
- printk("gator: mali offline _mali_profiling_control symbol not found\n");
+ pr_err("gator: mali offline _mali_profiling_control symbol not found\n");
}
}
-static int read(int **buffer)
+static int read(int **buffer, bool sched_switch)
{
int cnt;
int len = 0;
long sample_interval_us = 0;
struct timespec read_timestamp;
- if (!on_primary_core()) {
+ if (!on_primary_core())
return 0;
- }
/* Get the start of this sample period. */
getnstimeofday(&read_timestamp);
@@ -479,9 +468,8 @@ static int read(int **buffer)
* Calculate the sample interval if the previous sample time is valid.
* We use tv_sec since it will not be 0.
*/
- if (prev_timestamp.tv_sec != 0) {
+ if (prev_timestamp.tv_sec != 0)
sample_interval_us = get_duration_us(&prev_timestamp, &read_timestamp);
- }
/* Structure copy. Update the previous timestamp. */
prev_timestamp = read_timestamp;
@@ -490,15 +478,19 @@ static int read(int **buffer)
* Report the timeline counters (ACTIVITY_START/STOP)
*/
for (cnt = FIRST_TIMELINE_EVENT; cnt < (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS); cnt++) {
- mali_counter *counter = &counters[cnt];
+ struct mali_counter *counter = &counters[cnt];
+
if (counter->enabled) {
const int index = cnt - FIRST_TIMELINE_EVENT;
unsigned int value;
- /* If the activity is still running, reset its start time to the start of this sample period
- * to correct the count. Add the time up to the end of the sample onto the count. */
+ /* If the activity is still running, reset its start time to the
+ * start of this sample period to correct the count. Add the
+ * time up to the end of the sample onto the count.
+ */
if (timeline_event_starttime[index].tv_sec != 0) {
const long event_duration = get_duration_us(&timeline_event_starttime[index], &read_timestamp);
+
timeline_data[index] += event_duration;
timeline_event_starttime[index] = read_timestamp; /* Activity is still running. */
}
@@ -507,7 +499,7 @@ static int read(int **buffer)
/* Convert the counter to a percent-of-sample value */
value = (timeline_data[index] * 100) / sample_interval_us;
} else {
- pr_debug("gator: Mali-T6xx: setting value to zero\n");
+ pr_debug("gator: Mali-Midgard: setting value to zero\n");
value = 0;
}
@@ -521,9 +513,11 @@ static int read(int **buffer)
/* Report the software counters */
for (cnt = FIRST_SOFTWARE_COUNTER; cnt < (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS); cnt++) {
- const mali_counter *counter = &counters[cnt];
+ const struct mali_counter *counter = &counters[cnt];
+
if (counter->enabled) {
const int index = cnt - FIRST_SOFTWARE_COUNTER;
+
counter_dump[len++] = counter->key;
counter_dump[len++] = sw_counter_data[index];
/* Set the value to zero for the next time */
@@ -533,9 +527,11 @@ static int read(int **buffer)
/* Report the accumulators */
for (cnt = FIRST_ACCUMULATOR; cnt < (FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS); cnt++) {
- const mali_counter *counter = &counters[cnt];
+ const struct mali_counter *counter = &counters[cnt];
+
if (counter->enabled) {
const int index = cnt - FIRST_ACCUMULATOR;
+
counter_dump[len++] = counter->key;
counter_dump[len++] = accumulators_data[index];
/* Do not zero the accumulator */
@@ -543,25 +539,24 @@ static int read(int **buffer)
}
/* Update the buffer */
- if (buffer) {
- *buffer = (int *)counter_dump;
- }
+ if (buffer)
+ *buffer = counter_dump;
return len;
}
-static struct gator_interface gator_events_mali_t6xx_interface = {
+static struct gator_interface gator_events_mali_midgard_interface = {
.create_files = create_files,
.start = start,
.stop = stop,
.read = read
};
-extern int gator_events_mali_t6xx_init(void)
+extern int gator_events_mali_midgard_init(void)
{
- pr_debug("gator: Mali-T6xx: sw_counters init\n");
+ pr_debug("gator: Mali-Midgard: sw_counters init\n");
gator_mali_initialise_counters(counters, NUMBER_OF_EVENTS);
- return gator_events_install(&gator_events_mali_t6xx_interface);
+ return gator_events_install(&gator_events_mali_midgard_interface);
}
diff --git a/drivers/gator/gator_events_mali_t6xx_hw.c b/drivers/gator/gator_events_mali_midgard_hw.c
index 3a072bb..c8065da 100644
--- a/drivers/gator/gator_events_mali_t6xx_hw.c
+++ b/drivers/gator/gator_events_mali_midgard_hw.c
@@ -13,19 +13,19 @@
#include <linux/time.h>
#include <linux/math64.h>
#include <linux/slab.h>
-#include <asm/io.h>
+#include <linux/io.h>
-/* Mali T6xx DDK includes */
+/* Mali Midgard DDK includes */
#if defined(MALI_SIMPLE_API)
/* Header with wrapper functions to kbase structures and functions */
-#include "mali/mali_dd_gator_api.h"
+#include "mali/mali_kbase_gator_api.h"
#elif defined(MALI_DIR_MIDGARD)
-/* New DDK Directory structure with kernel/drivers/gpu/arm/midgard*/
+/* New DDK Directory structure with kernel/drivers/gpu/arm/midgard */
#include "mali_linux_trace.h"
#include "mali_kbase.h"
#include "mali_kbase_mem_linux.h"
#else
-/* Old DDK Directory structure with kernel/drivers/gpu/arm/t6xx*/
+/* Old DDK Directory structure with kernel/drivers/gpu/arm/t6xx */
#include "linux/mali_linux_trace.h"
#include "kbase/src/common/mali_kbase.h"
#include "kbase/src/linux/mali_kbase_mem_linux.h"
@@ -37,76 +37,63 @@
#endif
#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).
+#error MALI_DDK_GATOR_API_VERSION is invalid (must be 1 for r1/r2 DDK, or 2 for r3/r4 DDK, or 3 for r5 and later DDK).
#endif
#include "gator_events_mali_common.h"
/*
- * Mali-T6xx
+ * Mali-Midgard
*/
#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;
+static uint32_t (*kbase_gator_instr_hwcnt_dump_irq_symbol)(struct kbase_gator_hwcnt_handles *);
+static uint32_t (*kbase_gator_instr_hwcnt_dump_complete_symbol)(struct kbase_gator_hwcnt_handles *, uint32_t *const);
+static struct kbase_gator_hwcnt_handles *(*kbase_gator_hwcnt_init_symbol)(struct kbase_gator_hwcnt_info *);
+static void (*kbase_gator_hwcnt_term_symbol)(struct kbase_gator_hwcnt_info *, struct kbase_gator_hwcnt_handles *);
#else
-typedef struct kbase_device *kbase_find_device_type(int);
-typedef struct kbase_context *kbase_create_context_type(struct kbase_device *);
-typedef void kbase_destroy_context_type(struct kbase_context *);
+static struct kbase_device *(*kbase_find_device_symbol)(int);
+static struct kbase_context *(*kbase_create_context_symbol)(struct kbase_device *);
+static void (*kbase_destroy_context_symbol)(struct kbase_context *);
#if MALI_DDK_GATOR_API_VERSION == 1
-typedef void *kbase_va_alloc_type(struct kbase_context *, u32);
-typedef void kbase_va_free_type(struct kbase_context *, void *);
+static void *(*kbase_va_alloc_symbol)(struct kbase_context *, u32);
+static void (*kbase_va_free_symbol)(struct kbase_context *, void *);
#elif MALI_DDK_GATOR_API_VERSION == 2
-typedef void *kbase_va_alloc_type(struct kbase_context *, u32, kbase_hwc_dma_mapping * handle);
-typedef void kbase_va_free_type(struct kbase_context *, kbase_hwc_dma_mapping * handle);
+static void *(*kbase_va_alloc_symbol)(struct kbase_context *, u32, struct kbase_hwc_dma_mapping *);
+static void (*kbase_va_free_symbol)(struct kbase_context *, struct kbase_hwc_dma_mapping *);
#endif
-typedef mali_error kbase_instr_hwcnt_enable_type(struct kbase_context *, struct kbase_uk_hwcnt_setup *);
-typedef mali_error kbase_instr_hwcnt_disable_type(struct kbase_context *);
-typedef mali_error kbase_instr_hwcnt_clear_type(struct kbase_context *);
-typedef mali_error kbase_instr_hwcnt_dump_irq_type(struct kbase_context *);
-typedef mali_bool kbase_instr_hwcnt_dump_complete_type(struct kbase_context *, mali_bool *);
-
-static kbase_find_device_type *kbase_find_device_symbol;
-static kbase_create_context_type *kbase_create_context_symbol;
-static kbase_va_alloc_type *kbase_va_alloc_symbol;
-static kbase_instr_hwcnt_enable_type *kbase_instr_hwcnt_enable_symbol;
-static kbase_instr_hwcnt_clear_type *kbase_instr_hwcnt_clear_symbol;
-static kbase_instr_hwcnt_dump_irq_type *kbase_instr_hwcnt_dump_irq_symbol;
-static kbase_instr_hwcnt_dump_complete_type *kbase_instr_hwcnt_dump_complete_symbol;
-static kbase_instr_hwcnt_disable_type *kbase_instr_hwcnt_disable_symbol;
-static kbase_va_free_type *kbase_va_free_symbol;
-static kbase_destroy_context_type *kbase_destroy_context_symbol;
-#endif
+static mali_error (*kbase_instr_hwcnt_enable_symbol)(struct kbase_context *, struct kbase_uk_hwcnt_setup *);
+static mali_error (*kbase_instr_hwcnt_disable_symbol)(struct kbase_context *);
+static mali_error (*kbase_instr_hwcnt_clear_symbol)(struct kbase_context *);
+static mali_error (*kbase_instr_hwcnt_dump_irq_symbol)(struct kbase_context *);
+static mali_bool (*kbase_instr_hwcnt_dump_complete_symbol)(struct kbase_context *, mali_bool *);
-static long shader_present_low = 0;
+static long shader_present_low;
+#endif
/** The interval between reads, in ns.
*
- * Earlier we introduced
- * a 'hold off for 1ms after last read' to resolve MIDBASE-2178 and MALINE-724.
- * However, the 1ms hold off is too long if no context switches occur as there is a race
- * between this value and the tick of the read clock in gator which is also 1ms. If we 'miss' the
- * current read, the counter values are effectively 'spread' over 2ms and the values seen are half
- * what they should be (since Streamline averages over sample time). In the presence of context switches
- * this spread can vary and markedly affect the counters. Currently there is no 'proper' solution to
- * this, but empirically we have found that reducing the minimum read interval to 950us causes the
- * counts to be much more stable.
+ * Earlier we introduced a 'hold off for 1ms after last read' to
+ * resolve MIDBASE-2178 and MALINE-724. However, the 1ms hold off is
+ * too long if no context switches occur as there is a race between
+ * this value and the tick of the read clock in gator which is also
+ * 1ms. If we 'miss' the current read, the counter values are
+ * effectively 'spread' over 2ms and the values seen are half what
+ * they should be (since Streamline averages over sample time). In the
+ * presence of context switches this spread can vary and markedly
+ * affect the counters. Currently there is no 'proper' solution to
+ * this, but empirically we have found that reducing the minimum read
+ * interval to 950us causes the counts to be much more stable.
*/
static const int READ_INTERVAL_NSEC = 950000;
#if GATOR_TEST
-#include "gator_events_mali_t6xx_hw_test.c"
+#include "gator_events_mali_midgard_hw_test.c"
#endif
+#if MALI_DDK_GATOR_API_VERSION != 3
/* Blocks for HW counters */
enum {
JM_BLOCK = 0,
@@ -114,12 +101,12 @@ enum {
SHADER_BLOCK,
MMU_BLOCK
};
+#endif
-static const char mali_name[] = "Mali-T6xx";
+static const char *mali_name;
-/* Counters for Mali-T6xx:
+/* Counters for Mali-Midgard:
*
- * - HW counters, 4 blocks
* For HW counters we need strings to create /dev/gator/events files.
* Enums are not needed because the position of the HW name in the array is the same
* of the corresponding value in the received block of memory.
@@ -128,6 +115,13 @@ static const char mali_name[] = "Mali-T6xx";
*/
/* Hardware Counters */
+#if MALI_DDK_GATOR_API_VERSION == 3
+
+static const char *const *hardware_counter_names;
+static int number_of_hardware_counters;
+
+#else
+
static const char *const hardware_counter_names[] = {
/* Job Manager */
"",
@@ -394,17 +388,19 @@ static const char *const hardware_counter_names[] = {
"L2_REPLAY_FULL"
};
-#define NUMBER_OF_HARDWARE_COUNTERS (sizeof(hardware_counter_names) / sizeof(hardware_counter_names[0]))
+static const int number_of_hardware_counters = ARRAY_SIZE(hardware_counter_names);
+
+#endif
#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;
+static struct kbase_gator_hwcnt_handles *handles;
/* Information about hardware counters */
-static struct mali_dd_hwcnt_info *in_out_info;
+static struct kbase_gator_hwcnt_info *in_out_info;
#else
/* Memory to dump hardware counters into */
@@ -412,56 +408,58 @@ static void *kernel_dump_buffer;
#if MALI_DDK_GATOR_API_VERSION == 2
/* DMA state used to manage lifetime of the buffer */
-kbase_hwc_dma_mapping kernel_dump_buffer_handle;
+struct kbase_hwc_dma_mapping kernel_dump_buffer_handle;
#endif
/* kbase context and device */
-static struct kbase_context *kbcontext = NULL;
-static struct kbase_device *kbdevice = NULL;
+static struct kbase_context *kbcontext;
+static struct kbase_device *kbdevice;
+
+/*
+ * The following function has no external prototype in older DDK
+ * revisions. When the DDK is updated then this should be removed.
+ */
+struct kbase_device *kbase_find_device(int minor);
#endif
-static volatile bool kbase_device_busy = false;
+static volatile bool kbase_device_busy;
static unsigned int num_hardware_counters_enabled;
-/*
- * gatorfs variables for counter enable state
- */
-static mali_counter counters[NUMBER_OF_HARDWARE_COUNTERS];
+/* gatorfs variables for counter enable state */
+static struct mali_counter *counters;
-/* An array used to return the data we recorded
- * as key,value pairs hence the *2
- */
-static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2];
+/* An array used to return the data we recorded as key,value pairs */
+static int *counter_dump;
+
+extern struct mali_counter mali_activity[3];
-extern mali_counter mali_activity[3];
-static const char* const mali_activity_names[] = {
+static const char *const mali_activity_names[] = {
"fragment",
"vertex",
"opencl",
};
#define SYMBOL_GET(FUNCTION, ERROR_COUNT) \
- if(FUNCTION ## _symbol) \
- { \
- printk("gator: mali " #FUNCTION " symbol was already registered\n"); \
- (ERROR_COUNT)++; \
- } \
- else \
- { \
- FUNCTION ## _symbol = symbol_get(FUNCTION); \
- if(! FUNCTION ## _symbol) \
- { \
- printk("gator: mali online " #FUNCTION " symbol not found\n"); \
+ do { \
+ if (FUNCTION ## _symbol) { \
+ pr_err("gator: mali " #FUNCTION " symbol was already registered\n"); \
(ERROR_COUNT)++; \
+ } else { \
+ FUNCTION ## _symbol = symbol_get(FUNCTION); \
+ if (!FUNCTION ## _symbol) { \
+ pr_err("gator: mali online " #FUNCTION " symbol not found\n"); \
+ (ERROR_COUNT)++; \
+ } \
} \
- }
+ } while (0)
#define SYMBOL_CLEANUP(FUNCTION) \
- if(FUNCTION ## _symbol) \
- { \
- symbol_put(FUNCTION); \
- FUNCTION ## _symbol = NULL; \
- }
+ do { \
+ if (FUNCTION ## _symbol) { \
+ symbol_put(FUNCTION); \
+ FUNCTION ## _symbol = NULL; \
+ } \
+ } while (0)
/**
* Execute symbol_get for all the Mali symbols and check for success.
@@ -471,10 +469,10 @@ 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);
+ SYMBOL_GET(kbase_gator_instr_hwcnt_dump_irq, error_count);
+ SYMBOL_GET(kbase_gator_instr_hwcnt_dump_complete, error_count);
+ SYMBOL_GET(kbase_gator_hwcnt_init, error_count);
+ SYMBOL_GET(kbase_gator_hwcnt_term, error_count);
#else
SYMBOL_GET(kbase_find_device, error_count);
SYMBOL_GET(kbase_create_context, error_count);
@@ -497,10 +495,10 @@ 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);
+ SYMBOL_CLEANUP(kbase_gator_instr_hwcnt_dump_irq);
+ SYMBOL_CLEANUP(kbase_gator_instr_hwcnt_dump_complete);
+ SYMBOL_CLEANUP(kbase_gator_hwcnt_init);
+ SYMBOL_CLEANUP(kbase_gator_hwcnt_term);
#else
SYMBOL_CLEANUP(kbase_find_device);
SYMBOL_CLEANUP(kbase_create_context);
@@ -526,14 +524,12 @@ static void clean_symbols(void)
static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns)
{
/* If the current ns count rolls over a second, roll the next read time too. */
- if (current_time->tv_sec != *prev_time_s) {
+ if (current_time->tv_sec != *prev_time_s)
*next_read_time_ns = *next_read_time_ns - NSEC_PER_SEC;
- }
/* Abort the read if the next read time has not arrived. */
- if (current_time->tv_nsec < *next_read_time_ns) {
+ if (current_time->tv_nsec < *next_read_time_ns)
return 0;
- }
/* Set the next read some fixed time after this one, and update the read timestamp. */
*next_read_time_ns = current_time->tv_nsec + READ_INTERVAL_NSEC;
@@ -544,7 +540,7 @@ static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time
static int start(void)
{
-#if MALI_DDK_GATOR_API_VERSION < 3
+#if MALI_DDK_GATOR_API_VERSION != 3
struct kbase_uk_hwcnt_setup setup;
unsigned long long shadersPresent = 0;
u16 bitmask[] = { 0, 0, 0, 0 };
@@ -552,37 +548,27 @@ static int start(void)
#endif
int cnt;
+#if MALI_DDK_GATOR_API_VERSION == 3
/* Setup HW counters */
num_hardware_counters_enabled = 0;
- if (NUMBER_OF_HARDWARE_COUNTERS != 256) {
- pr_debug("Unexpected number of hardware counters defined: expecting 256, got %d\n", NUMBER_OF_HARDWARE_COUNTERS);
- }
-
-#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++){
+ /* Declare and initialise kbase_gator_hwcnt_info structure */
+ in_out_info = kmalloc(sizeof(*in_out_info), GFP_KERNEL);
+ for (cnt = 0; cnt < ARRAY_SIZE(in_out_info->bitmask); cnt++)
in_out_info->bitmask[cnt] = 0;
- }
-#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) {
+ for (cnt = 0; cnt < number_of_hardware_counters; cnt++) {
+ if (counters[cnt].enabled) {
int block = GET_HW_BLOCK(cnt);
int enable_bit = GET_COUNTER_OFFSET(cnt) / 4;
-#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);
+ pr_debug("gator: Mali-Midgard: 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) {
@@ -591,20 +577,33 @@ static int start(void)
return 0;
}
- handles = mali_dd_hwcnt_init_symbol(in_out_info);
+ handles = kbase_gator_hwcnt_init_symbol(in_out_info);
- if(handles == NULL) {
+ 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
+ /* Setup HW counters */
+ num_hardware_counters_enabled = 0;
+
+ /* Calculate enable bitmasks based on counters_enabled array */
+ for (cnt = 0; cnt < number_of_hardware_counters; cnt++) {
+ const struct mali_counter *counter = &counters[cnt];
+
+ if (counter->enabled) {
+ int block = GET_HW_BLOCK(cnt);
+ int enable_bit = GET_COUNTER_OFFSET(cnt) / 4;
+
+ bitmask[block] |= (1 << enable_bit);
+ pr_debug("gator: Mali-Midgard: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt);
+ num_hardware_counters_enabled++;
+ }
+ }
+
/* Create a kbase context for HW counters */
if (num_hardware_counters_enabled > 0) {
if (init_symbols() > 0) {
@@ -617,18 +616,17 @@ static int start(void)
/* If we already got a context, fail */
if (kbcontext) {
- pr_debug("gator: Mali-T6xx: error context already present\n");
+ pr_debug("gator: Mali-Midgard: error context already present\n");
goto out;
}
/* kbcontext will only be valid after all the Mali symbols are loaded successfully */
kbcontext = kbase_create_context_symbol(kbdevice);
if (!kbcontext) {
- pr_debug("gator: Mali-T6xx: error creating kbase context\n");
+ pr_debug("gator: Mali-Midgard: error creating kbase context\n");
goto out;
}
-
/* See if we can get the number of shader cores */
shadersPresent = kbdevice->shader_present_bitmap;
shader_present_low = (unsigned long)shadersPresent;
@@ -639,8 +637,8 @@ static int start(void)
* * number of blocks (always 8 for midgard)
* * number of counters per block (always 64 for midgard)
* * number of bytes per counter (always 4 in midgard)
- * For a Mali-T6xx with a single core group = 1 * 8 * 64 * 4 = 2048
- * For a Mali-T6xx with a dual core group = 2 * 8 * 64 * 4 = 4096
+ * For a Mali-Midgard with a single core group = 1 * 8 * 64 * 4 = 2048
+ * For a Mali-Midgard with a dual core group = 2 * 8 * 64 * 4 = 4096
*/
#if MALI_DDK_GATOR_API_VERSION == 1
kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 4096);
@@ -648,7 +646,7 @@ static int start(void)
kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 4096, &kernel_dump_buffer_handle);
#endif
if (!kernel_dump_buffer) {
- pr_debug("gator: Mali-T6xx: error trying to allocate va\n");
+ pr_debug("gator: Mali-Midgard: error trying to allocate va\n");
goto destroy_context;
}
@@ -663,12 +661,12 @@ static int start(void)
/* Use kbase API to enable hardware counters and provide dump buffer */
err = kbase_instr_hwcnt_enable_symbol(kbcontext, &setup);
if (err != MALI_ERROR_NONE) {
- pr_debug("gator: Mali-T6xx: can't setup hardware counters\n");
+ pr_debug("gator: Mali-Midgard: can't setup hardware counters\n");
goto free_buffer;
}
- pr_debug("gator: Mali-T6xx: hardware counters enabled\n");
+ pr_debug("gator: Mali-Midgard: hardware counters enabled\n");
kbase_instr_hwcnt_clear_symbol(kbcontext);
- pr_debug("gator: Mali-T6xx: hardware counters cleared \n");
+ pr_debug("gator: Mali-Midgard: hardware counters cleared\n");
kbase_device_busy = false;
}
@@ -695,17 +693,16 @@ static void stop(void)
{
unsigned int cnt;
#if MALI_DDK_GATOR_API_VERSION == 3
- struct mali_dd_hwcnt_handles *temp_hand;
+ struct kbase_gator_hwcnt_handles *temp_hand;
#else
struct kbase_context *temp_kbcontext;
#endif
- pr_debug("gator: Mali-T6xx: stop\n");
+ pr_debug("gator: Mali-Midgard: stop\n");
/* Set all counters as disabled */
- for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) {
+ for (cnt = 0; cnt < number_of_hardware_counters; cnt++)
counters[cnt].enabled = 0;
- }
/* Destroy the context for HW counters */
#if MALI_DDK_GATOR_API_VERSION == 3
@@ -717,7 +714,7 @@ static void stop(void)
temp_hand = handles;
handles = NULL;
- mali_dd_hwcnt_clear_symbol(in_out_info, temp_hand);
+ kbase_gator_hwcnt_term_symbol(in_out_info, temp_hand);
kfree(in_out_info);
@@ -741,60 +738,117 @@ static void stop(void)
kbase_destroy_context_symbol(temp_kbcontext);
#endif
- pr_debug("gator: Mali-T6xx: hardware counters stopped\n");
+ pr_debug("gator: Mali-Midgard: hardware counters stopped\n");
clean_symbols();
}
}
-static int read(int **buffer)
+static int read_counter(const int cnt, const int len, const struct mali_counter *counter)
+{
+ const int block = GET_HW_BLOCK(cnt);
+ const int counter_offset = GET_COUNTER_OFFSET(cnt);
+
+#if MALI_DDK_GATOR_API_VERSION == 3
+ const char *block_base_address = (char *)in_out_info->kernel_dump_buffer;
+ int i;
+ int shader_core_count = 0;
+ u32 value = 0;
+
+ for (i = 0; i < in_out_info->nr_hwc_blocks; i++) {
+ if (block == in_out_info->hwc_layout[i]) {
+ value += *((u32 *)(block_base_address + (0x100 * i)) + counter_offset);
+ if (block == SHADER_BLOCK)
+ ++shader_core_count;
+ }
+ }
+
+ if (shader_core_count > 1)
+ value /= shader_core_count;
+#else
+ const char *block_base_address = (char *)kernel_dump_buffer + vithar_blocks[block];
+
+ /* If counter belongs to shader block need to take into account all cores */
+ if (block == SHADER_BLOCK) {
+ int i = 0;
+ int shader_core_count = 0;
+
+ value = 0;
+
+ for (i = 0; i < 4; i++) {
+ if ((shader_present_low >> i) & 1) {
+ value += *((u32 *)(block_base_address + (0x100 * i)) + counter_offset);
+ shader_core_count++;
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ if ((shader_present_low >> (i+4)) & 1) {
+ value += *((u32 *)(block_base_address + (0x100 * i) + 0x800) + counter_offset);
+ shader_core_count++;
+ }
+ }
+
+ /* Need to total by number of cores to produce an average */
+ if (shader_core_count != 0)
+ value /= shader_core_count;
+ } else {
+ value = *((u32 *)block_base_address + counter_offset);
+ }
+#endif
+
+ counter_dump[len + 0] = counter->key;
+ counter_dump[len + 1] = value;
+
+ return 2;
+}
+
+static int read(int **buffer, bool sched_switch)
{
int cnt;
int len = 0;
- u32 value = 0;
uint32_t success;
struct timespec current_time;
- static u32 prev_time_s = 0;
- static s32 next_read_time_ns = 0;
+ static u32 prev_time_s;
+ static s32 next_read_time_ns;
- if (!on_primary_core()) {
+ if (!on_primary_core() || sched_switch)
return 0;
- }
getnstimeofday(&current_time);
/*
- * Discard reads unless a respectable time has passed. This reduces the load on the GPU without sacrificing
- * accuracy on the Streamline display.
+ * Discard reads unless a respectable time has passed. This
+ * reduces the load on the GPU without sacrificing accuracy on
+ * the Streamline display.
*/
- if (!is_read_scheduled(&current_time, &prev_time_s, &next_read_time_ns)) {
+ if (!is_read_scheduled(&current_time, &prev_time_s, &next_read_time_ns))
return 0;
- }
/*
* Report the HW counters
* Only process hardware counters if at least one of the hardware counters is enabled.
*/
if (num_hardware_counters_enabled > 0) {
+#if MALI_DDK_GATOR_API_VERSION != 3
const unsigned int vithar_blocks[] = {
0x700, /* VITHAR_JOB_MANAGER, Block 0 */
0x400, /* VITHAR_TILER, Block 1 */
0x000, /* VITHAR_SHADER_CORE, Block 2 */
0x500 /* VITHAR_MEMORY_SYSTEM, Block 3 */
};
+#endif
#if MALI_DDK_GATOR_API_VERSION == 3
- if (!handles) {
+ if (!handles)
return -1;
- }
/* Mali symbols can be called safely since a kbcontext is valid */
- if (kbase_dd_instr_hwcnt_dump_complete_symbol(handles, &success) == MALI_TRUE) {
+ if (kbase_gator_instr_hwcnt_dump_complete_symbol(handles, &success) == MALI_TRUE) {
#else
- if (!kbcontext) {
+ if (!kbcontext)
return -1;
- }
/* Mali symbols can be called safely since a kbcontext is valid */
if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE) {
@@ -803,49 +857,11 @@ static int read(int **buffer)
if (success == MALI_TRUE) {
/* Cycle through hardware counters and accumulate totals */
- for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) {
- const mali_counter *counter = &counters[cnt];
- if (counter->enabled) {
- const int block = GET_HW_BLOCK(cnt);
- const int counter_offset = GET_COUNTER_OFFSET(cnt);
-
-#if MALI_DDK_GATOR_API_VERSION == 3
- const char* block_base_address = (char*)in_out_info->kernel_dump_buffer + vithar_blocks[block];
-#else
- const char* block_base_address = (char*)kernel_dump_buffer + vithar_blocks[block];
-#endif
+ for (cnt = 0; cnt < number_of_hardware_counters; cnt++) {
+ const struct mali_counter *counter = &counters[cnt];
- /* If counter belongs to shader block need to take into account all cores */
- if (block == SHADER_BLOCK) {
- int i = 0;
- int shader_core_count = 0;
- value = 0;
-
- for (i = 0; i < 4; i++) {
- if ((shader_present_low >> i) & 1) {
- value += *((u32*) (block_base_address + (0x100 * i)) + counter_offset);
- shader_core_count++;
- }
- }
-
- for (i = 0; i < 4; i++) {
- if((shader_present_low >> (i+4)) & 1) {
- value += *((u32*)(block_base_address + (0x100 * i) + 0x800) + counter_offset);
- shader_core_count++;
- }
- }
-
- /* Need to total by number of cores to produce an average */
- if (shader_core_count != 0) {
- value /= shader_core_count;
- }
- } else {
- value = *((u32*)block_base_address + counter_offset);
- }
-
- counter_dump[len++] = counter->key;
- counter_dump[len++] = value;
- }
+ if (counter->enabled)
+ len += read_counter(cnt, len, counter);
}
}
}
@@ -853,7 +869,7 @@ 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);
+ kbase_gator_instr_hwcnt_dump_irq_symbol(handles);
#else
kbase_instr_hwcnt_dump_irq_symbol(kbcontext);
#endif
@@ -861,9 +877,8 @@ static int read(int **buffer)
}
/* Update the buffer */
- if (buffer) {
- *buffer = (int *)counter_dump;
- }
+ if (buffer)
+ *buffer = counter_dump;
return len;
}
@@ -874,40 +889,89 @@ static int create_files(struct super_block *sb, struct dentry *root)
/*
* Create the filesystem for all events
*/
- int counter_index = 0;
-
for (event = 0; event < ARRAY_SIZE(mali_activity); event++) {
- if (gator_mali_create_file_system(mali_name, mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) {
+ if (gator_mali_create_file_system("Midgard", mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0)
return -1;
- }
}
- for (event = 0; event < NUMBER_OF_HARDWARE_COUNTERS; event++) {
- if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event], NULL) != 0)
+ for (event = 0; event < number_of_hardware_counters; event++) {
+ if (gator_mali_create_file_system(mali_name, hardware_counter_names[event], sb, root, &counters[event], NULL) != 0)
return -1;
- counter_index++;
}
return 0;
}
-static struct gator_interface gator_events_mali_t6xx_interface = {
+static void shutdown(void)
+{
+#if MALI_DDK_GATOR_API_VERSION == 3
+ void (*kbase_gator_hwcnt_term_names_symbol)(void) = NULL;
+ int error_count = 0;
+#endif
+
+ kfree(counters);
+ kfree(counter_dump);
+
+#if MALI_DDK_GATOR_API_VERSION == 3
+ SYMBOL_GET(kbase_gator_hwcnt_term_names, error_count);
+
+ number_of_hardware_counters = -1;
+ hardware_counter_names = NULL;
+ if (kbase_gator_hwcnt_term_names_symbol != NULL) {
+ kbase_gator_hwcnt_term_names_symbol();
+ pr_err("Released symbols\n");
+ }
+
+ SYMBOL_CLEANUP(kbase_gator_hwcnt_term_names);
+#endif
+}
+
+static struct gator_interface gator_events_mali_midgard_interface = {
+ .shutdown = shutdown,
.create_files = create_files,
.start = start,
.stop = stop,
.read = read
};
-int gator_events_mali_t6xx_hw_init(void)
+int gator_events_mali_midgard_hw_init(void)
{
- pr_debug("gator: Mali-T6xx: sw_counters init\n");
+#if MALI_DDK_GATOR_API_VERSION == 3
+ const char *const *(*kbase_gator_hwcnt_init_names_symbol)(uint32_t *) = NULL;
+ int error_count = 0;
+#endif
+
+ pr_debug("gator: Mali-Midgard: sw_counters init\n");
#if GATOR_TEST
test_all_is_read_scheduled();
#endif
+#if MALI_DDK_GATOR_API_VERSION == 3
+ SYMBOL_GET(kbase_gator_hwcnt_init_names, error_count);
+ if (error_count > 0) {
+ SYMBOL_CLEANUP(kbase_gator_hwcnt_init_names);
+ return 1;
+ }
+
+ number_of_hardware_counters = -1;
+ hardware_counter_names = kbase_gator_hwcnt_init_names_symbol(&number_of_hardware_counters);
+
+ SYMBOL_CLEANUP(kbase_gator_hwcnt_init_names);
+
+ if ((hardware_counter_names == NULL) || (number_of_hardware_counters <= 0)) {
+ pr_err("gator: Error reading hardware counters names: got %d names\n", number_of_hardware_counters);
+ return -1;
+ }
+#else
+ mali_name = "Midgard";
+#endif
+
+ counters = kmalloc(sizeof(*counters)*number_of_hardware_counters, GFP_KERNEL);
+ counter_dump = kmalloc(sizeof(*counter_dump)*number_of_hardware_counters*2, GFP_KERNEL);
+
gator_mali_initialise_counters(mali_activity, ARRAY_SIZE(mali_activity));
- gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS);
+ gator_mali_initialise_counters(counters, number_of_hardware_counters);
- return gator_events_install(&gator_events_mali_t6xx_interface);
+ return gator_events_install(&gator_events_mali_midgard_interface);
}
diff --git a/drivers/gator/gator_events_mali_t6xx_hw_test.c b/drivers/gator/gator_events_mali_midgard_hw_test.c
index ba6553f..31a91e1 100644
--- a/drivers/gator/gator_events_mali_t6xx_hw_test.c
+++ b/drivers/gator/gator_events_mali_midgard_hw_test.c
@@ -23,12 +23,12 @@ static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int ex
current_time.tv_nsec = ns;
if (is_read_scheduled(&current_time, &prev_time_s, &next_read_time_ns) != expected_result) {
- printk("Failed do_read(%u, %u, %u, %d): expected %d\n", s, ns, prev_s, next_ns, expected_result);
+ pr_err("Failed do_read(%u, %u, %u, %d): expected %d\n", s, ns, prev_s, next_ns, expected_result);
return 0;
}
if (next_read_time_ns != expected_next_ns) {
- printk("Failed: next_read_ns expected=%d, actual=%d\n", expected_next_ns, next_read_time_ns);
+ pr_err("Failed: next_read_ns expected=%d, actual=%d\n", expected_next_ns, next_read_time_ns);
return 0;
}
@@ -40,7 +40,7 @@ static void test_all_is_read_scheduled(void)
const int HIGHEST_NS = 999999999;
int n_tests_passed = 0;
- printk("gator: running tests on %s\n", __FILE__);
+ pr_err("gator: running tests on %s\n", __FILE__);
n_tests_passed += test_is_read_scheduled(0, 0, 0, 0, 1, READ_INTERVAL_NSEC); /* Null time */
n_tests_passed += test_is_read_scheduled(100, 1000, 0, 0, 1, READ_INTERVAL_NSEC + 1000); /* Initial values */
@@ -51,5 +51,5 @@ static void test_all_is_read_scheduled(void)
n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500, 1, 600 + READ_INTERVAL_NSEC);
- printk("gator: %d tests passed\n", n_tests_passed);
+ pr_err("gator: %d tests passed\n", n_tests_passed);
}
diff --git a/drivers/gator/gator_events_meminfo.c b/drivers/gator/gator_events_meminfo.c
index c633dfd..c625ac5 100644
--- a/drivers/gator/gator_events_meminfo.c
+++ b/drivers/gator/gator_events_meminfo.c
@@ -16,6 +16,8 @@
#include <linux/workqueue.h>
#include <trace/events/kmem.h>
+#define USE_THREAD defined(CONFIG_PREEMPT_RT_FULL)
+
enum {
MEMINFO_MEMFREE,
MEMINFO_MEMUSED,
@@ -48,7 +50,7 @@ static bool meminfo_global_enabled;
static ulong meminfo_enabled[MEMINFO_TOTAL];
static ulong meminfo_keys[MEMINFO_TOTAL];
static long long meminfo_buffer[2 * (MEMINFO_TOTAL + 2)];
-static int meminfo_length = 0;
+static int meminfo_length;
static bool new_data_avail;
static bool proc_global_enabled;
@@ -56,22 +58,44 @@ static ulong proc_enabled[PROC_COUNT];
static ulong proc_keys[PROC_COUNT];
static DEFINE_PER_CPU(long long, proc_buffer[2 * (PROC_COUNT + 3)]);
+#if USE_THREAD
+
static int gator_meminfo_func(void *data);
static bool gator_meminfo_run;
-// Initialize semaphore unlocked to initialize memory values
+/* Initialize semaphore unlocked to initialize memory values */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
static DECLARE_MUTEX(gator_meminfo_sem);
#else
static DEFINE_SEMAPHORE(gator_meminfo_sem);
#endif
+static void notify(void)
+{
+ up(&gator_meminfo_sem);
+}
+
+#else
+
+static unsigned int mem_event;
+static void wq_sched_handler(struct work_struct *wsptr);
+DECLARE_WORK(work, wq_sched_handler);
+static struct timer_list meminfo_wake_up_timer;
+static void meminfo_wake_up_handler(unsigned long unused_data);
+
+static void notify(void)
+{
+ mem_event++;
+}
+
+#endif
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order))
#else
GATOR_DEFINE_PROBE(mm_page_free, TP_PROTO(struct page *page, unsigned int order))
#endif
{
- up(&gator_meminfo_sem);
+ notify();
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
@@ -80,12 +104,12 @@ GATOR_DEFINE_PROBE(mm_pagevec_free, TP_PROTO(struct page *page, int cold))
GATOR_DEFINE_PROBE(mm_page_free_batched, TP_PROTO(struct page *page, int cold))
#endif
{
- up(&gator_meminfo_sem);
+ notify();
}
GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype))
{
- up(&gator_meminfo_sem);
+ notify();
}
static int gator_events_meminfo_create_files(struct super_block *sb, struct dentry *root)
@@ -95,18 +119,16 @@ static int gator_events_meminfo_create_files(struct super_block *sb, struct dent
for (i = 0; i < MEMINFO_TOTAL; i++) {
dir = gatorfs_mkdir(sb, root, meminfo_names[i]);
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &meminfo_enabled[i]);
gatorfs_create_ro_ulong(sb, dir, "key", &meminfo_keys[i]);
}
for (i = 0; i < PROC_COUNT; ++i) {
dir = gatorfs_mkdir(sb, root, proc_names[i]);
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &proc_enabled[i]);
gatorfs_create_ro_ulong(sb, dir, "key", &proc_keys[i]);
}
@@ -134,9 +156,8 @@ static int gator_events_meminfo_start(void)
break;
}
}
- if (meminfo_enabled[MEMINFO_MEMUSED]) {
+ if (meminfo_enabled[MEMINFO_MEMUSED])
proc_global_enabled = 1;
- }
if (meminfo_global_enabled == 0)
return 0;
@@ -156,16 +177,22 @@ static int gator_events_meminfo_start(void)
if (GATOR_REGISTER_TRACE(mm_page_alloc))
goto mm_page_alloc_exit;
- // Start worker thread
+#if USE_THREAD
+ /* Start worker thread */
gator_meminfo_run = true;
- // Since the mutex starts unlocked, memory values will be initialized
+ /* Since the mutex starts unlocked, memory values will be initialized */
if (IS_ERR(kthread_run(gator_meminfo_func, NULL, "gator_meminfo")))
goto kthread_run_exit;
+#else
+ setup_timer(&meminfo_wake_up_timer, meminfo_wake_up_handler, 0);
+#endif
return 0;
+#if USE_THREAD
kthread_run_exit:
GATOR_UNREGISTER_TRACE(mm_page_alloc);
+#endif
mm_page_alloc_exit:
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
GATOR_UNREGISTER_TRACE(mm_pagevec_free);
@@ -194,75 +221,111 @@ static void gator_events_meminfo_stop(void)
#endif
GATOR_UNREGISTER_TRACE(mm_page_alloc);
- // Stop worker thread
+#if USE_THREAD
+ /* Stop worker thread */
gator_meminfo_run = false;
up(&gator_meminfo_sem);
+#else
+ del_timer_sync(&meminfo_wake_up_timer);
+#endif
}
}
-// Must be run in process context as the kernel function si_meminfo() can sleep
-static int gator_meminfo_func(void *data)
+static void do_read(void)
{
struct sysinfo info;
int i, len;
unsigned long long value;
- for (;;) {
- if (down_killable(&gator_meminfo_sem)) {
- break;
+ meminfo_length = len = 0;
+
+ si_meminfo(&info);
+ for (i = 0; i < MEMINFO_TOTAL; i++) {
+ if (meminfo_enabled[i]) {
+ switch (i) {
+ case MEMINFO_MEMFREE:
+ value = info.freeram * PAGE_SIZE;
+ break;
+ case MEMINFO_MEMUSED:
+ /* pid -1 means system wide */
+ meminfo_buffer[len++] = 1;
+ meminfo_buffer[len++] = -1;
+ /* Emit value */
+ meminfo_buffer[len++] = meminfo_keys[MEMINFO_MEMUSED];
+ meminfo_buffer[len++] = (info.totalram - info.freeram) * PAGE_SIZE;
+ /* Clear pid */
+ meminfo_buffer[len++] = 1;
+ meminfo_buffer[len++] = 0;
+ continue;
+ case MEMINFO_BUFFERRAM:
+ value = info.bufferram * PAGE_SIZE;
+ break;
+ default:
+ value = 0;
+ break;
+ }
+ meminfo_buffer[len++] = meminfo_keys[i];
+ meminfo_buffer[len++] = value;
}
+ }
- // Eat up any pending events
- while (!down_trylock(&gator_meminfo_sem));
+ meminfo_length = len;
+ new_data_avail = true;
+}
- if (!gator_meminfo_run) {
+#if USE_THREAD
+
+static int gator_meminfo_func(void *data)
+{
+ for (;;) {
+ if (down_killable(&gator_meminfo_sem))
break;
- }
- meminfo_length = len = 0;
-
- si_meminfo(&info);
- for (i = 0; i < MEMINFO_TOTAL; i++) {
- if (meminfo_enabled[i]) {
- switch (i) {
- case MEMINFO_MEMFREE:
- value = info.freeram * PAGE_SIZE;
- break;
- case MEMINFO_MEMUSED:
- // pid -1 means system wide
- meminfo_buffer[len++] = 1;
- meminfo_buffer[len++] = -1;
- // Emit value
- meminfo_buffer[len++] = meminfo_keys[MEMINFO_MEMUSED];
- meminfo_buffer[len++] = (info.totalram - info.freeram) * PAGE_SIZE;
- // Clear pid
- meminfo_buffer[len++] = 1;
- meminfo_buffer[len++] = 0;
- continue;
- case MEMINFO_BUFFERRAM:
- value = info.bufferram * PAGE_SIZE;
- break;
- default:
- value = 0;
- break;
- }
- meminfo_buffer[len++] = meminfo_keys[i];
- meminfo_buffer[len++] = value;
- }
- }
+ /* Eat up any pending events */
+ while (!down_trylock(&gator_meminfo_sem))
+ ;
+
+ if (!gator_meminfo_run)
+ break;
- meminfo_length = len;
- new_data_avail = true;
+ do_read();
}
return 0;
}
+#else
+
+/* Must be run in process context as the kernel function si_meminfo() can sleep */
+static void wq_sched_handler(struct work_struct *wsptr)
+{
+ do_read();
+}
+
+static void meminfo_wake_up_handler(unsigned long unused_data)
+{
+ /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */
+ schedule_work(&work);
+}
+
+#endif
+
static int gator_events_meminfo_read(long long **buffer)
{
+#if !USE_THREAD
+ static unsigned int last_mem_event;
+#endif
+
if (!on_primary_core() || !meminfo_global_enabled)
return 0;
+#if !USE_THREAD
+ if (last_mem_event != mem_event) {
+ last_mem_event = mem_event;
+ mod_timer(&meminfo_wake_up_timer, jiffies + 1);
+ }
+#endif
+
if (!new_data_avail)
return 0;
@@ -280,6 +343,7 @@ static inline unsigned long gator_get_mm_counter(struct mm_struct *mm, int membe
{
#ifdef SPLIT_RSS_COUNTING
long val = atomic_long_read(&mm->rss_stat.count[member]);
+
if (val < 0)
val = 0;
return (unsigned long)val;
@@ -306,22 +370,19 @@ static int gator_events_meminfo_read_proc(long long **buffer, struct task_struct
int cpu = get_physical_cpu();
long long *buf = per_cpu(proc_buffer, cpu);
- if (!proc_global_enabled) {
+ if (!proc_global_enabled)
return 0;
- }
- // Collect the memory stats of the process instead of the thread
- if (task->group_leader != NULL) {
+ /* Collect the memory stats of the process instead of the thread */
+ if (task->group_leader != NULL)
task = task->group_leader;
- }
- // get_task_mm/mmput is not needed in this context because the task and it's mm are required as part of the sched_switch
+ /* get_task_mm/mmput is not needed in this context because the task and it's mm are required as part of the sched_switch */
mm = task->mm;
- if (mm == NULL) {
+ if (mm == NULL)
return 0;
- }
- // Derived from task_statm in fs/proc/task_mmu.c
+ /* Derived from task_statm in fs/proc/task_mmu.c */
if (meminfo_enabled[MEMINFO_MEMUSED] || proc_enabled[PROC_SHARE]) {
share = get_mm_counter(mm,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
@@ -332,7 +393,7 @@ static int gator_events_meminfo_read_proc(long long **buffer, struct task_struct
);
}
- // key of 1 indicates a pid
+ /* key of 1 indicates a pid */
buf[len++] = 1;
buf[len++] = task->pid;
@@ -366,12 +427,12 @@ static int gator_events_meminfo_read_proc(long long **buffer, struct task_struct
MM_ANONPAGES
#endif
);
- // Send resident for this pid
+ /* Send resident for this pid */
buf[len++] = meminfo_keys[MEMINFO_MEMUSED];
buf[len++] = value * PAGE_SIZE;
}
- // Clear pid
+ /* Clear pid */
buf[len++] = 1;
buf[len++] = 0;
diff --git a/drivers/gator/gator_events_mmapped.c b/drivers/gator/gator_events_mmapped.c
index 5bc01c4..6b2af99 100644
--- a/drivers/gator/gator_events_mmapped.c
+++ b/drivers/gator/gator_events_mmapped.c
@@ -103,7 +103,7 @@ static int mmapped_simulate(int counter, int delta_in_us)
switch (counter) {
case 0: /* sort-of-sine */
{
- static int t = 0;
+ static int t;
int x;
t += delta_in_us;
@@ -140,7 +140,7 @@ static int mmapped_simulate(int counter, int delta_in_us)
break;
case 2: /* PWM signal */
{
- static int dc, x, t = 0;
+ static int dc, x, t;
t += delta_in_us;
if (t > 1000000)
@@ -157,7 +157,7 @@ static int mmapped_simulate(int counter, int delta_in_us)
return result;
}
-static int gator_events_mmapped_read(int **buffer)
+static int gator_events_mmapped_read(int **buffer, bool sched_switch)
{
int i;
int len = 0;
diff --git a/drivers/gator/gator_events_net.c b/drivers/gator/gator_events_net.c
index 11c10e3..d21b4db 100644
--- a/drivers/gator/gator_events_net.c
+++ b/drivers/gator/gator_events_net.c
@@ -25,7 +25,7 @@ static int netGet[TOTALNET * 4];
static struct timer_list net_wake_up_timer;
-// Must be run in process context as the kernel function dev_get_stats() can sleep
+/* Must be run in process context as the kernel function dev_get_stats() can sleep */
static void get_network_stats(struct work_struct *wsptr)
{
int rx = 0, tx = 0;
@@ -49,7 +49,7 @@ DECLARE_WORK(wq_get_stats, get_network_stats);
static void net_wake_up_handler(unsigned long unused_data)
{
- // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
+ /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */
schedule_work(&wq_get_stats);
}
@@ -73,21 +73,19 @@ static void calculate_delta(int *rx, int *tx)
static int gator_events_net_create_files(struct super_block *sb, struct dentry *root)
{
- // Network counters are not currently supported in RT-Preempt full because mod_timer is used
+ /* Network counters are not currently supported in RT-Preempt full because mod_timer is used */
#ifndef CONFIG_PREEMPT_RT_FULL
struct dentry *dir;
dir = gatorfs_mkdir(sb, root, "Linux_net_rx");
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &netrx_enabled);
gatorfs_create_ro_ulong(sb, dir, "key", &netrx_key);
dir = gatorfs_mkdir(sb, root, "Linux_net_tx");
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &nettx_enabled);
gatorfs_create_ro_ulong(sb, dir, "key", &nettx_key);
#endif
@@ -115,10 +113,10 @@ static void gator_events_net_stop(void)
nettx_enabled = 0;
}
-static int gator_events_net_read(int **buffer)
+static int gator_events_net_read(int **buffer, bool sched_switch)
{
int len, rx_delta, tx_delta;
- static int last_rx_delta = 0, last_tx_delta = 0;
+ static int last_rx_delta, last_tx_delta;
if (!on_primary_core())
return 0;
@@ -134,7 +132,8 @@ static int gator_events_net_read(int **buffer)
if (netrx_enabled && last_rx_delta != rx_delta) {
last_rx_delta = rx_delta;
netGet[len++] = netrx_key;
- netGet[len++] = 0; // indicates to Streamline that rx_delta bytes were transmitted now, not since the last message
+ /* indicates to Streamline that rx_delta bytes were transmitted now, not since the last message */
+ netGet[len++] = 0;
netGet[len++] = netrx_key;
netGet[len++] = rx_delta;
}
@@ -142,7 +141,8 @@ static int gator_events_net_read(int **buffer)
if (nettx_enabled && last_tx_delta != tx_delta) {
last_tx_delta = tx_delta;
netGet[len++] = nettx_key;
- netGet[len++] = 0; // indicates to Streamline that tx_delta bytes were transmitted now, not since the last message
+ /* indicates to Streamline that tx_delta bytes were transmitted now, not since the last message */
+ netGet[len++] = 0;
netGet[len++] = nettx_key;
netGet[len++] = tx_delta;
}
diff --git a/drivers/gator/gator_events_perf_pmu.c b/drivers/gator/gator_events_perf_pmu.c
index 06bbad5..47cf278 100644
--- a/drivers/gator/gator_events_perf_pmu.c
+++ b/drivers/gator/gator_events_perf_pmu.c
@@ -8,7 +8,7 @@
#include "gator.h"
-// gator_events_armvX.c is used for Linux 2.6.x
+/* gator_events_armvX.c is used for Linux 2.6.x */
#if GATOR_PERF_PMU_SUPPORT
#include <linux/io.h>
@@ -20,39 +20,41 @@
extern bool event_based_sampling;
-// Maximum number of per-core counters - currently reserves enough space for two full hardware PMUs for big.LITTLE
+/* Maximum number of per-core counters - currently reserves enough space for two full hardware PMUs for big.LITTLE */
#define CNTMAX 16
#define CCI_400 4
-// Maximum number of uncore counters
-// + 1 for the cci-400 cycles counter
-#define UCCNT (CCI_400 + 1)
+#define CCN_5XX 8
+/* Maximum number of uncore counters */
+/* + 1 for the cci-400 cycles counter */
+/* + 1 for the CCN-5xx cycles counter */
+#define UCCNT (CCI_400 + 1 + CCN_5XX + 1)
-// Default to 0 if unable to probe the revision which was the previous behavior
+/* Default to 0 if unable to probe the revision which was the previous behavior */
#define DEFAULT_CCI_REVISION 0
-// A gator_attr is needed for every counter
+/* A gator_attr is needed for every counter */
struct gator_attr {
- // Set once in gator_events_perf_pmu_*_init - the name of the event in the gatorfs
+ /* Set once in gator_events_perf_pmu_*_init - the name of the event in the gatorfs */
char name[40];
- // Exposed in gatorfs - set by gatord to enable this counter
+ /* Exposed in gatorfs - set by gatord to enable this counter */
unsigned long enabled;
- // Set once in gator_events_perf_pmu_*_init - the perf type to use, see perf_type_id in the perf_event.h header file.
+ /* Set once in gator_events_perf_pmu_*_init - the perf type to use, see perf_type_id in the perf_event.h header file. */
unsigned long type;
- // Exposed in gatorfs - set by gatord to select the event to collect
+ /* Exposed in gatorfs - set by gatord to select the event to collect */
unsigned long event;
- // Exposed in gatorfs - set by gatord with the sample period to use and enable EBS for this counter
+ /* Exposed in gatorfs - set by gatord with the sample period to use and enable EBS for this counter */
unsigned long count;
- // Exposed as read only in gatorfs - set once in __attr_init as the key to use in the APC data
+ /* Exposed as read only in gatorfs - set once in __attr_init as the key to use in the APC data */
unsigned long key;
};
-// Per-core counter attributes
+/* Per-core counter attributes */
static struct gator_attr attrs[CNTMAX];
-// Number of initialized per-core counters
+/* Number of initialized per-core counters */
static int attr_count;
-// Uncore counter attributes
+/* Uncore counter attributes */
static struct gator_attr uc_attrs[UCCNT];
-// Number of initialized uncore counters
+/* Number of initialized uncore counters */
static int uc_attr_count;
struct gator_event {
@@ -74,13 +76,11 @@ static int __create_files(struct super_block *sb, struct dentry *root, struct ga
{
struct dentry *dir;
- if (attr->name[0] == '\0') {
+ if (attr->name[0] == '\0')
return 0;
- }
dir = gatorfs_mkdir(sb, root, attr->name);
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &attr->enabled);
gatorfs_create_ulong(sb, dir, "count", &attr->count);
gatorfs_create_ro_ulong(sb, dir, "key", &attr->key);
@@ -94,15 +94,13 @@ static int gator_events_perf_pmu_create_files(struct super_block *sb, struct den
int cnt;
for (cnt = 0; cnt < attr_count; cnt++) {
- if (__create_files(sb, root, &attrs[cnt]) != 0) {
+ if (__create_files(sb, root, &attrs[cnt]) != 0)
return -1;
- }
}
for (cnt = 0; cnt < uc_attr_count; cnt++) {
- if (__create_files(sb, root, &uc_attrs[cnt]) != 0) {
+ if (__create_files(sb, root, &uc_attrs[cnt]) != 0)
return -1;
- }
}
return 0;
@@ -123,14 +121,14 @@ static void dummy_handler(struct perf_event *event, int unused, struct perf_samp
static void dummy_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
#endif
{
-// Required as perf_event_create_kernel_counter() requires an overflow handler, even though all we do is poll
+ /* Required as perf_event_create_kernel_counter() requires an overflow handler, even though all we do is poll */
}
-static int gator_events_perf_pmu_read(int **buffer);
+static int gator_events_perf_pmu_read(int **buffer, bool sched_switch);
static int gator_events_perf_pmu_online(int **buffer, bool migrate)
{
- return gator_events_perf_pmu_read(buffer);
+ return gator_events_perf_pmu_read(buffer, false);
}
static void __online_dispatch(int cpu, bool migrate, struct gator_attr *const attr, struct gator_event *const event)
@@ -139,15 +137,13 @@ static void __online_dispatch(int cpu, bool migrate, struct gator_attr *const at
event->zero = true;
- if (event->pevent != NULL || event->pevent_attr == 0 || migrate) {
+ if (event->pevent != NULL || event->pevent_attr == 0 || migrate)
return;
- }
- if (attr->count > 0) {
+ if (attr->count > 0)
handler = ebs_overflow_handler;
- } else {
+ else
handler = dummy_handler;
- }
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
event->pevent = perf_event_create_kernel_counter(event->pevent_attr, cpu, 0, handler);
@@ -174,14 +170,12 @@ static void gator_events_perf_pmu_online_dispatch(int cpu, bool migrate)
cpu = pcpu_to_lcpu(cpu);
- for (cnt = 0; cnt < attr_count; cnt++) {
+ for (cnt = 0; cnt < attr_count; cnt++)
__online_dispatch(cpu, migrate, &attrs[cnt], &per_cpu(events, cpu)[cnt]);
- }
if (cpu == 0) {
- for (cnt = 0; cnt < uc_attr_count; cnt++) {
+ for (cnt = 0; cnt < uc_attr_count; cnt++)
__online_dispatch(cpu, migrate, &uc_attrs[cnt], &uc_events[cnt]);
- }
}
}
@@ -194,28 +188,24 @@ static void __offline_dispatch(int cpu, struct gator_event *const event)
event->pevent = NULL;
}
- if (pe) {
+ if (pe)
perf_event_release_kernel(pe);
- }
}
static void gator_events_perf_pmu_offline_dispatch(int cpu, bool migrate)
{
int cnt;
- if (migrate) {
+ if (migrate)
return;
- }
cpu = pcpu_to_lcpu(cpu);
- for (cnt = 0; cnt < attr_count; cnt++) {
+ for (cnt = 0; cnt < attr_count; cnt++)
__offline_dispatch(cpu, &per_cpu(events, cpu)[cnt]);
- }
if (cpu == 0) {
- for (cnt = 0; cnt < uc_attr_count; cnt++) {
+ for (cnt = 0; cnt < uc_attr_count; cnt++)
__offline_dispatch(cpu, &uc_events[cnt]);
- }
}
}
@@ -225,7 +215,7 @@ static int __check_ebs(struct gator_attr *const attr)
if (!event_based_sampling) {
event_based_sampling = true;
} else {
- printk(KERN_WARNING "gator: Only one ebs counter is allowed\n");
+ pr_warning("gator: Only one ebs counter is allowed\n");
return -1;
}
}
@@ -238,9 +228,9 @@ static int __start(struct gator_attr *const attr, struct gator_event *const even
u32 size = sizeof(struct perf_event_attr);
event->pevent = NULL;
- if (!attr->enabled) { // Skip disabled counters
+ /* Skip disabled counters */
+ if (!attr->enabled)
return 0;
- }
event->prev = 0;
event->curr = 0;
@@ -267,29 +257,25 @@ static int gator_events_perf_pmu_start(void)
event_based_sampling = false;
for (cnt = 0; cnt < attr_count; cnt++) {
- if (__check_ebs(&attrs[cnt]) != 0) {
+ if (__check_ebs(&attrs[cnt]) != 0)
return -1;
- }
}
for (cnt = 0; cnt < uc_attr_count; cnt++) {
- if (__check_ebs(&uc_attrs[cnt]) != 0) {
+ if (__check_ebs(&uc_attrs[cnt]) != 0)
return -1;
- }
}
for_each_present_cpu(cpu) {
for (cnt = 0; cnt < attr_count; cnt++) {
- if (__start(&attrs[cnt], &per_cpu(events, cpu)[cnt]) != 0) {
+ if (__start(&attrs[cnt], &per_cpu(events, cpu)[cnt]) != 0)
return -1;
- }
}
}
for (cnt = 0; cnt < uc_attr_count; cnt++) {
- if (__start(&uc_attrs[cnt], &uc_events[cnt]) != 0) {
+ if (__start(&uc_attrs[cnt], &uc_events[cnt]) != 0)
return -1;
- }
}
return 0;
@@ -297,10 +283,8 @@ static int gator_events_perf_pmu_start(void)
static void __event_stop(struct gator_event *const event)
{
- if (event->pevent_attr) {
- kfree(event->pevent_attr);
- event->pevent_attr = NULL;
- }
+ kfree(event->pevent_attr);
+ event->pevent_attr = NULL;
}
static void __attr_stop(struct gator_attr *const attr)
@@ -315,29 +299,25 @@ static void gator_events_perf_pmu_stop(void)
unsigned int cnt, cpu;
for_each_present_cpu(cpu) {
- for (cnt = 0; cnt < attr_count; cnt++) {
+ for (cnt = 0; cnt < attr_count; cnt++)
__event_stop(&per_cpu(events, cpu)[cnt]);
- }
}
- for (cnt = 0; cnt < uc_attr_count; cnt++) {
+ for (cnt = 0; cnt < uc_attr_count; cnt++)
__event_stop(&uc_events[cnt]);
- }
- for (cnt = 0; cnt < attr_count; cnt++) {
+ for (cnt = 0; cnt < attr_count; cnt++)
__attr_stop(&attrs[cnt]);
- }
- for (cnt = 0; cnt < uc_attr_count; cnt++) {
+ for (cnt = 0; cnt < uc_attr_count; cnt++)
__attr_stop(&uc_attrs[cnt]);
- }
}
static void __read(int *const len, int cpu, struct gator_attr *const attr, struct gator_event *const event)
{
int delta;
-
struct perf_event *const ev = event->pevent;
+
if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
/* After creating the perf counter in __online_dispatch, there
* is a race condition between gator_events_perf_pmu_online and
@@ -361,33 +341,29 @@ static void __read(int *const len, int cpu, struct gator_attr *const attr, struc
event->prev_delta = delta;
event->prev = event->curr;
per_cpu(perf_cnt, cpu)[(*len)++] = attr->key;
- if (delta < 0) {
+ if (delta < 0)
delta *= -1;
- }
per_cpu(perf_cnt, cpu)[(*len)++] = delta;
}
}
}
}
-static int gator_events_perf_pmu_read(int **buffer)
+static int gator_events_perf_pmu_read(int **buffer, bool sched_switch)
{
int cnt, len = 0;
const int cpu = get_logical_cpu();
- for (cnt = 0; cnt < attr_count; cnt++) {
+ for (cnt = 0; cnt < attr_count; cnt++)
__read(&len, cpu, &attrs[cnt], &per_cpu(events, cpu)[cnt]);
- }
if (cpu == 0) {
- for (cnt = 0; cnt < uc_attr_count; cnt++) {
+ for (cnt = 0; cnt < uc_attr_count; cnt++)
__read(&len, cpu, &uc_attrs[cnt], &uc_events[cnt]);
- }
}
- if (buffer) {
+ if (buffer)
*buffer = per_cpu(perf_cnt, cpu);
- }
return len;
}
@@ -428,23 +404,20 @@ static int probe_cci_revision(void)
int ret = DEFAULT_CCI_REVISION;
np = of_find_matching_node(NULL, arm_cci_matches);
- if (!np) {
+ if (!np)
return ret;
- }
- if (of_address_to_resource(np, 0, &res)) {
+ if (of_address_to_resource(np, 0, &res))
goto node_put;
- }
cci_ctrl_base = ioremap(res.start, resource_size(&res));
rev = (readl_relaxed(cci_ctrl_base + 0xfe8) >> 4) & 0xf;
- if (rev <= 4) {
+ if (rev <= 4)
ret = 0;
- } else if (rev <= 6) {
+ else if (rev <= 6)
ret = 1;
- }
iounmap(cci_ctrl_base);
@@ -463,9 +436,24 @@ static int probe_cci_revision(void)
#endif
-static void gator_events_perf_pmu_cci_init(const int type)
+static void gator_events_perf_pmu_uncore_init(const char *const name, const int type, const int count)
{
int cnt;
+
+ snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", name);
+ uc_attrs[uc_attr_count].type = type;
+ ++uc_attr_count;
+
+ for (cnt = 0; cnt < count; ++cnt, ++uc_attr_count) {
+ struct gator_attr *const attr = &uc_attrs[uc_attr_count];
+
+ snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", name, cnt);
+ attr->type = type;
+ }
+}
+
+static void gator_events_perf_pmu_cci_init(const int type)
+{
const char *cci_name;
switch (probe_cci_revision()) {
@@ -480,15 +468,7 @@ static void gator_events_perf_pmu_cci_init(const int type)
return;
}
- snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", cci_name);
- uc_attrs[uc_attr_count].type = type;
- ++uc_attr_count;
-
- for (cnt = 0; cnt < CCI_400; ++cnt, ++uc_attr_count) {
- struct gator_attr *const attr = &uc_attrs[uc_attr_count];
- snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", cci_name, cnt);
- attr->type = type;
- }
+ gator_events_perf_pmu_uncore_init(cci_name, type, CCI_400);
}
static void gator_events_perf_pmu_cpu_init(const struct gator_cpu *const gator_cpu, const int type)
@@ -501,6 +481,7 @@ static void gator_events_perf_pmu_cpu_init(const struct gator_cpu *const gator_c
for (cnt = 0; cnt < gator_cpu->pmnc_counters; ++cnt, ++attr_count) {
struct gator_attr *const attr = &attrs[attr_count];
+
snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", gator_cpu->pmnc_name, cnt);
attr->type = type;
}
@@ -516,12 +497,10 @@ int gator_events_perf_pmu_init(void)
int cnt;
bool found_cpu = false;
- for (cnt = 0; cnt < CNTMAX; cnt++) {
+ for (cnt = 0; cnt < CNTMAX; cnt++)
__attr_init(&attrs[cnt]);
- }
- for (cnt = 0; cnt < UCCNT; cnt++) {
+ for (cnt = 0; cnt < UCCNT; cnt++)
__attr_init(&uc_attrs[cnt]);
- }
memset(&pea, 0, sizeof(pea));
pea.size = sizeof(pea);
@@ -531,7 +510,7 @@ int gator_events_perf_pmu_init(void)
for (type = PERF_TYPE_MAX; type < 0x20; ++type) {
pea.type = type;
- // A particular PMU may work on some but not all cores, so try on each core
+ /* A particular PMU may work on some but not all cores, so try on each core */
pe = NULL;
for_each_present_cpu(cpu) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
@@ -539,23 +518,31 @@ int gator_events_perf_pmu_init(void)
#else
pe = perf_event_create_kernel_counter(&pea, cpu, 0, dummy_handler, 0);
#endif
- if (!IS_ERR(pe)) {
+ if (!IS_ERR(pe))
break;
- }
}
- // Assume that valid PMUs are contiguous
+ /* Assume that valid PMUs are contiguous */
if (IS_ERR(pe)) {
- break;
+ pea.config = 0xff00;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
+ pe = perf_event_create_kernel_counter(&pea, 0, 0, dummy_handler);
+#else
+ pe = perf_event_create_kernel_counter(&pea, 0, 0, dummy_handler, 0);
+#endif
+ if (IS_ERR(pe))
+ break;
}
if (pe->pmu != NULL && type == pe->pmu->type) {
if (strcmp("CCI", pe->pmu->name) == 0 || strcmp("CCI_400", pe->pmu->name) == 0 || strcmp("CCI_400-r1", pe->pmu->name) == 0) {
gator_events_perf_pmu_cci_init(type);
+ } else if (strcmp("ccn", pe->pmu->name) == 0) {
+ gator_events_perf_pmu_uncore_init("ARM_CCN_5XX", type, CCN_5XX);
} else if ((gator_cpu = gator_find_cpu_by_pmu_name(pe->pmu->name)) != NULL) {
found_cpu = true;
gator_events_perf_pmu_cpu_init(gator_cpu, type);
}
- // Initialize gator_attrs for dynamic PMUs here
+ /* Initialize gator_attrs for dynamic PMUs here */
}
perf_event_release_kernel(pe);
@@ -563,21 +550,21 @@ int gator_events_perf_pmu_init(void)
if (!found_cpu) {
const struct gator_cpu *const gator_cpu = gator_find_cpu_by_cpuid(gator_cpuid());
- if (gator_cpu == NULL) {
+
+ if (gator_cpu == NULL)
return -1;
- }
gator_events_perf_pmu_cpu_init(gator_cpu, PERF_TYPE_RAW);
}
- // Initialize gator_attrs for non-dynamic PMUs here
+ /* Initialize gator_attrs for non-dynamic PMUs here */
if (attr_count > CNTMAX) {
- printk(KERN_ERR "gator: Too many perf counters\n");
+ pr_err("gator: Too many perf counters\n");
return -1;
}
if (uc_attr_count > UCCNT) {
- printk(KERN_ERR "gator: Too many perf uncore counters\n");
+ pr_err("gator: Too many perf uncore counters\n");
return -1;
}
diff --git a/drivers/gator/gator_events_sched.c b/drivers/gator/gator_events_sched.c
index 9e39158..637107d 100644
--- a/drivers/gator/gator_events_sched.c
+++ b/drivers/gator/gator_events_sched.c
@@ -26,8 +26,9 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_
{
unsigned long flags;
- // disable interrupts to synchronize with gator_events_sched_read()
- // spinlocks not needed since percpu buffers are used
+ /* disable interrupts to synchronize with gator_events_sched_read()
+ * spinlocks not needed since percpu buffers are used
+ */
local_irq_save(flags);
per_cpu(schedCnt, get_physical_cpu())[SCHED_SWITCH]++;
local_irq_restore(flags);
@@ -39,9 +40,8 @@ static int gator_events_sched_create_files(struct super_block *sb, struct dentry
/* switch */
dir = gatorfs_mkdir(sb, root, "Linux_sched_switch");
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &sched_switch_enabled);
gatorfs_create_ro_ulong(sb, dir, "key", &sched_switch_key);
@@ -50,7 +50,7 @@ static int gator_events_sched_create_files(struct super_block *sb, struct dentry
static int gator_events_sched_start(void)
{
- // register tracepoints
+ /* register tracepoints */
if (sched_switch_enabled)
if (GATOR_REGISTER_TRACE(sched_switch))
goto sched_switch_exit;
@@ -58,7 +58,7 @@ static int gator_events_sched_start(void)
return 0;
- // unregister tracepoints on error
+ /* unregister tracepoints on error */
sched_switch_exit:
pr_err("gator: scheduler event tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n");
@@ -74,7 +74,7 @@ static void gator_events_sched_stop(void)
sched_switch_enabled = 0;
}
-static int gator_events_sched_read(int **buffer)
+static int gator_events_sched_read(int **buffer, bool sched_switch)
{
unsigned long flags;
int len, value;
diff --git a/drivers/gator/gator_events_scorpion.c b/drivers/gator/gator_events_scorpion.c
index 2e5be8d..4921936 100644
--- a/drivers/gator/gator_events_scorpion.c
+++ b/drivers/gator/gator_events_scorpion.c
@@ -8,13 +8,13 @@
#include "gator.h"
-// gator_events_perf_pmu.c is used if perf is supported
+/* gator_events_perf_pmu.c is used if perf is supported */
#if GATOR_NO_PERF_SUPPORT
static const char *pmnc_name;
static int pmnc_counters;
-// Per-CPU PMNC: config reg
+/* Per-CPU PMNC: config reg */
#define PMNC_E (1 << 0) /* Enable all counters */
#define PMNC_P (1 << 1) /* Reset all counters */
#define PMNC_C (1 << 2) /* Cycle counter reset */
@@ -23,7 +23,7 @@ static int pmnc_counters;
#define PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug */
#define PMNC_MASK 0x3f /* Mask for writable bits */
-// ccnt reg
+/* ccnt reg */
#define CCNT_REG (1 << 31)
#define CCNT 0
@@ -243,6 +243,7 @@ static inline void scorpion_pmnc_write(u32 val)
static inline u32 scorpion_pmnc_read(void)
{
u32 val;
+
asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
return val;
}
@@ -250,6 +251,7 @@ static inline u32 scorpion_pmnc_read(void)
static inline u32 scorpion_ccnt_read(void)
{
u32 val;
+
asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
return val;
}
@@ -257,6 +259,7 @@ static inline u32 scorpion_ccnt_read(void)
static inline u32 scorpion_cntn_read(void)
{
u32 val;
+
asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
return val;
}
@@ -317,6 +320,7 @@ static inline int scorpion_pmnc_select_counter(unsigned int cnt)
static u32 scorpion_read_lpm0(void)
{
u32 val;
+
asm volatile("mrc p15, 0, %0, c15, c0, 0" : "=r" (val));
return val;
}
@@ -329,6 +333,7 @@ static void scorpion_write_lpm0(u32 val)
static u32 scorpion_read_lpm1(void)
{
u32 val;
+
asm volatile("mrc p15, 1, %0, c15, c0, 0" : "=r" (val));
return val;
}
@@ -341,6 +346,7 @@ static void scorpion_write_lpm1(u32 val)
static u32 scorpion_read_lpm2(void)
{
u32 val;
+
asm volatile("mrc p15, 2, %0, c15, c0, 0" : "=r" (val));
return val;
}
@@ -353,6 +359,7 @@ static void scorpion_write_lpm2(u32 val)
static u32 scorpion_read_l2lpm(void)
{
u32 val;
+
asm volatile("mrc p15, 3, %0, c15, c2, 0" : "=r" (val));
return val;
}
@@ -365,6 +372,7 @@ static void scorpion_write_l2lpm(u32 val)
static u32 scorpion_read_vlpm(void)
{
u32 val;
+
asm volatile("mrc p10, 7, %0, c11, c0, 0" : "=r" (val));
return val;
}
@@ -375,7 +383,7 @@ static void scorpion_write_vlpm(u32 val)
}
struct scorpion_access_funcs {
- u32(*read)(void);
+ u32 (*read)(void);
void (*write)(u32);
};
@@ -420,17 +428,17 @@ static u32 scorpion_get_columnmask(u32 setval)
{
if (setval & COLMN0MASK)
return 0xffffff00;
- else if (setval & COLMN1MASK)
+ if (setval & COLMN1MASK)
return 0xffff00ff;
- else if (setval & COLMN2MASK)
+ if (setval & COLMN2MASK)
return 0xff00ffff;
- else
- return 0x80ffffff;
+ return 0x80ffffff;
}
static void scorpion_evt_setup(u32 gr, u32 setval)
{
u32 val;
+
if (gr == 4)
scorpion_pre_vlpm();
val = scorpion_get_columnmask(setval) & scor_func[gr].read();
@@ -443,6 +451,7 @@ static void scorpion_evt_setup(u32 gr, u32 setval)
static int get_scorpion_evtinfo(unsigned int evt_type, struct scorp_evt *evtinfo)
{
u32 idx;
+
if ((evt_type < 0x4c) || (evt_type >= MSM_MAX_EVT))
return 0;
idx = evt_type - 0x4c;
@@ -463,7 +472,7 @@ static inline void scorpion_pmnc_write_evtsel(unsigned int cnt, u32 val)
} else {
u32 zero = 0;
struct scorp_evt evtinfo;
- // extract evtinfo.grp and evtinfo.tevt_type_act from val
+ /* extract evtinfo.grp and evtinfo.tevt_type_act from val */
if (get_scorpion_evtinfo(val, &evtinfo) == 0)
return;
asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (evtinfo.evt_type_act));
@@ -505,20 +514,18 @@ static int gator_events_scorpion_create_files(struct super_block *sb, struct den
for (i = 0; i < pmnc_counters; i++) {
char buf[40];
- if (i == 0) {
- snprintf(buf, sizeof buf, "%s_ccnt", pmnc_name);
- } else {
- snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i - 1);
- }
+
+ if (i == 0)
+ snprintf(buf, sizeof(buf), "%s_ccnt", pmnc_name);
+ else
+ snprintf(buf, sizeof(buf), "%s_cnt%d", pmnc_name, i - 1);
dir = gatorfs_mkdir(sb, root, buf);
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]);
gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]);
- if (i > 0) {
+ if (i > 0)
gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]);
- }
}
return 0;
@@ -528,9 +535,8 @@ static int gator_events_scorpion_online(int **buffer, bool migrate)
{
unsigned int cnt, len = 0, cpu = smp_processor_id();
- if (scorpion_pmnc_read() & PMNC_E) {
+ if (scorpion_pmnc_read() & PMNC_E)
scorpion_pmnc_write(scorpion_pmnc_read() & ~PMNC_E);
- }
/* Initialize & Reset PMNC: C bit and P bit */
scorpion_pmnc_write(PMNC_P | PMNC_C);
@@ -541,33 +547,32 @@ static int gator_events_scorpion_online(int **buffer, bool migrate)
if (!pmnc_enabled[cnt])
continue;
- // disable counter
+ /* disable counter */
scorpion_pmnc_disable_counter(cnt);
event = pmnc_event[cnt] & 255;
- // Set event (if destined for PMNx counters), We don't need to set the event if it's a cycle count
+ /* Set event (if destined for PMNx counters), We don't need to set the event if it's a cycle count */
if (cnt != CCNT)
scorpion_pmnc_write_evtsel(cnt, event);
- // reset counter
+ /* reset counter */
scorpion_pmnc_reset_counter(cnt);
- // Enable counter, do not enable interrupt for this counter
+ /* Enable counter, do not enable interrupt for this counter */
scorpion_pmnc_enable_counter(cnt);
}
- // enable
+ /* enable */
scorpion_pmnc_write(scorpion_pmnc_read() | PMNC_E);
- // read the counters and toss the invalid data, return zero instead
+ /* read the counters and toss the invalid data, return zero instead */
for (cnt = 0; cnt < pmnc_counters; cnt++) {
if (pmnc_enabled[cnt]) {
- if (cnt == CCNT) {
+ if (cnt == CCNT)
scorpion_ccnt_read();
- } else if (scorpion_pmnc_select_counter(cnt) == cnt) {
+ else if (scorpion_pmnc_select_counter(cnt) == cnt)
scorpion_cntn_read();
- }
scorpion_pmnc_reset_counter(cnt);
per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt];
@@ -597,26 +602,25 @@ static void gator_events_scorpion_stop(void)
}
}
-static int gator_events_scorpion_read(int **buffer)
+static int gator_events_scorpion_read(int **buffer, bool sched_switch)
{
int cnt, len = 0;
int cpu = smp_processor_id();
- // a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled
- if (!(scorpion_pmnc_read() & PMNC_E)) {
+ /* a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled */
+ if (!(scorpion_pmnc_read() & PMNC_E))
return 0;
- }
for (cnt = 0; cnt < pmnc_counters; cnt++) {
if (pmnc_enabled[cnt]) {
int value;
- if (cnt == CCNT) {
+
+ if (cnt == CCNT)
value = scorpion_ccnt_read();
- } else if (scorpion_pmnc_select_counter(cnt) == cnt) {
+ else if (scorpion_pmnc_select_counter(cnt) == cnt)
value = scorpion_cntn_read();
- } else {
+ else
value = 0;
- }
scorpion_pmnc_reset_counter(cnt);
per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt];
@@ -655,7 +659,8 @@ int gator_events_scorpion_init(void)
return -1;
}
- pmnc_counters++; // CNT[n] + CCNT
+ /* CNT[n] + CCNT */
+ pmnc_counters++;
for (cnt = CCNT; cnt < CNTMAX; cnt++) {
pmnc_enabled[cnt] = 0;
diff --git a/drivers/gator/gator_events_threads.c b/drivers/gator/gator_events_threads.c
deleted file mode 100644
index 9de8586..0000000
--- a/drivers/gator/gator_events_threads.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Sample activity provider
- *
- * Copyright (C) ARM Limited 2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * See gator_events_mmapped.c for additional directions and
- * troubleshooting.
- *
- * For this sample to work these entries must be present in the
- * events.xml file. So create an events-threads.xml in the gator
- * daemon source directory with the following contents and rebuild
- * gatord:
- *
- * <category name="threads">
- * <event counter="Linux_threads" title="Linux" name="Threads" class="activity" activity1="odd" activity_color1="0x000000ff" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" description="Linux syscall activity"/>
- * </category>
- */
-
-#include <trace/events/sched.h>
-
-#include "gator.h"
-
-static ulong threads_enabled;
-static ulong threads_key;
-static ulong threads_cores;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
-GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next))
-#else
-GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_struct *next))
-#endif
-{
- int cpu = get_physical_cpu();
- int pid = next->pid;
- if (pid == 0) {
- // idle
- gator_marshal_activity_switch(cpu, threads_key, 0, 0);
- } else if (pid & 1) {
- // odd
- gator_marshal_activity_switch(cpu, threads_key, 1, pid);
- } else {
- // even
- //gator_marshal_activity_switch(cpu, threads_key, 2, current->pid);
- // Multiple activities are not yet supported so emit idle
- gator_marshal_activity_switch(cpu, threads_key, 0, 0);
- }
-}
-
-// Adds Linux_threads directory and enabled, key, and cores files to /dev/gator/events
-static int gator_events_threads_create_files(struct super_block *sb, struct dentry *root)
-{
- struct dentry *dir;
-
- dir = gatorfs_mkdir(sb, root, "Linux_threads");
- if (!dir) {
- return -1;
- }
- gatorfs_create_ulong(sb, dir, "enabled", &threads_enabled);
- gatorfs_create_ro_ulong(sb, dir, "key", &threads_key);
- // Number of cores associated with this activity
- gatorfs_create_ro_ulong(sb, dir, "cores", &threads_cores);
-
- return 0;
-}
-
-static int gator_events_threads_start(void)
-{
- int cpu;
-
- if (threads_enabled) {
- preempt_disable();
- for (cpu = 0; cpu < nr_cpu_ids; ++cpu) {
- gator_marshal_activity_switch(cpu, threads_key, 0, 0);
- }
- preempt_enable();
-
- if (GATOR_REGISTER_TRACE(sched_switch)) {
- goto fail_sched_switch;
- }
- }
-
- return 0;
-
-fail_sched_switch:
- return -1;
-}
-
-static void gator_events_threads_stop(void)
-{
- if (threads_enabled) {
- GATOR_UNREGISTER_TRACE(sched_switch);
- }
-
- threads_enabled = 0;
-}
-
-static struct gator_interface gator_events_threads_interface = {
- .create_files = gator_events_threads_create_files,
- .start = gator_events_threads_start,
- .stop = gator_events_threads_stop,
-};
-
-// Must not be static. Ensure that this init function is added to GATOR_EVENTS_LIST in gator_main.c
-int __init gator_events_threads_init(void)
-{
- threads_enabled = 0;
- threads_key = gator_events_get_key();
- threads_cores = nr_cpu_ids;
-
- return gator_events_install(&gator_events_threads_interface);
-}
diff --git a/drivers/gator/gator_fs.c b/drivers/gator/gator_fs.c
index 166cfe7..d8fb357 100644
--- a/drivers/gator/gator_fs.c
+++ b/drivers/gator/gator_fs.c
@@ -14,7 +14,7 @@
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#define gatorfs_MAGIC 0x24051020
#define TMPBUFSIZE 50
@@ -43,6 +43,7 @@ static ssize_t gatorfs_ulong_to_user(unsigned long val, char __user *buf, size_t
{
char tmpbuf[TMPBUFSIZE];
size_t maxlen = snprintf(tmpbuf, TMPBUFSIZE, "%lu\n", val);
+
if (maxlen > TMPBUFSIZE)
maxlen = TMPBUFSIZE;
return simple_read_from_buffer(buf, count, offset, tmpbuf, maxlen);
@@ -52,6 +53,7 @@ static ssize_t gatorfs_u64_to_user(u64 val, char __user *buf, size_t count, loff
{
char tmpbuf[TMPBUFSIZE];
size_t maxlen = snprintf(tmpbuf, TMPBUFSIZE, "%llu\n", val);
+
if (maxlen > TMPBUFSIZE)
maxlen = TMPBUFSIZE;
return simple_read_from_buffer(buf, count, offset, tmpbuf, maxlen);
@@ -104,12 +106,14 @@ static int gatorfs_u64_from_user(u64 *val, char const __user *buf, size_t count)
static ssize_t ulong_read_file(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
unsigned long *val = file->private_data;
+
return gatorfs_ulong_to_user(*val, buf, count, offset);
}
static ssize_t u64_read_file(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
u64 *val = file->private_data;
+
return gatorfs_u64_to_user(*val, buf, count, offset);
}
@@ -231,7 +235,7 @@ int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root,
}
static int gatorfs_create_ro_u64(struct super_block *sb, struct dentry *root,
- char const *name, u64 * val)
+ char const *name, u64 *val)
{
struct dentry *d =
__gatorfs_create_file(sb, root, name, &u64_ro_fops, 0444);
@@ -245,6 +249,7 @@ static int gatorfs_create_ro_u64(struct super_block *sb, struct dentry *root,
static ssize_t atomic_read_file(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
atomic_t *val = file->private_data;
+
return gatorfs_ulong_to_user(atomic_read(val), buf, count, offset);
}
diff --git a/drivers/gator/gator_hrtimer_gator.c b/drivers/gator/gator_hrtimer_gator.c
index 7658455..c1525e1 100644
--- a/drivers/gator/gator_hrtimer_gator.c
+++ b/drivers/gator/gator_hrtimer_gator.c
@@ -18,6 +18,7 @@ static void gator_hrtimer_offline(void);
static enum hrtimer_restart gator_hrtimer_notify(struct hrtimer *hrtimer)
{
int cpu = get_logical_cpu();
+
hrtimer_forward(hrtimer, per_cpu(hrtimer_expire, cpu), profiling_interval);
per_cpu(hrtimer_expire, cpu) = ktime_add(per_cpu(hrtimer_expire, cpu), profiling_interval);
(*callback)();
@@ -64,12 +65,11 @@ static int gator_hrtimer_init(int interval, void (*func)(void))
per_cpu(hrtimer_is_active, cpu) = 0;
}
- // calculate profiling interval
- if (interval > 0) {
+ /* calculate profiling interval */
+ if (interval > 0)
profiling_interval = ns_to_ktime(1000000000UL / interval);
- } else {
+ else
profiling_interval.tv64 = 0;
- }
return 0;
}
diff --git a/drivers/gator/gator_iks.c b/drivers/gator/gator_iks.c
index 9180b874..fb78c10 100644
--- a/drivers/gator/gator_iks.c
+++ b/drivers/gator/gator_iks.c
@@ -16,7 +16,7 @@
static bool map_cpuids;
static int mpidr_cpuids[NR_CPUS];
-static const struct gator_cpu * mpidr_cpus[NR_CPUS];
+static const struct gator_cpu *mpidr_cpus[NR_CPUS];
static int __lcpu_to_pcpu[NR_CPUS];
static const struct gator_cpu *gator_find_cpu_by_dt_name(const char *const name)
@@ -25,9 +25,9 @@ static const struct gator_cpu *gator_find_cpu_by_dt_name(const char *const name)
for (i = 0; gator_cpus[i].cpuid != 0; ++i) {
const struct gator_cpu *const gator_cpu = &gator_cpus[i];
- if (gator_cpu->dt_name != NULL && strcmp(gator_cpu->dt_name, name) == 0) {
+
+ if (gator_cpu->dt_name != NULL && strcmp(gator_cpu->dt_name, name) == 0)
return gator_cpu;
- }
}
return NULL;
@@ -41,7 +41,7 @@ static void calc_first_cluster_size(void)
struct device_node *cn = NULL;
int mpidr_cpuids_count = 0;
- // Zero is a valid cpuid, so initialize the array to 0xff's
+ /* Zero is a valid cpuid, so initialize the array to 0xff's */
memset(&mpidr_cpuids, 0xff, sizeof(mpidr_cpuids));
memset(&mpidr_cpus, 0, sizeof(mpidr_cpus));
@@ -70,10 +70,10 @@ static void calc_first_cluster_size(void)
static int linearize_mpidr(int mpidr)
{
int i;
+
for (i = 0; i < nr_cpu_ids; ++i) {
- if (mpidr_cpuids[i] == mpidr) {
+ if (mpidr_cpuids[i] == mpidr)
return i;
- }
}
BUG();
@@ -113,6 +113,7 @@ static void gator_update_cpu_mapping(u32 cpu_hwid)
{
int lcpu = smp_processor_id();
int pcpu = linearize_mpidr(cpu_hwid & MPIDR_HWID_BITMASK);
+
BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0);
BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0);
__lcpu_to_pcpu[lcpu] = pcpu;
@@ -132,7 +133,7 @@ GATOR_DEFINE_PROBE(cpu_migrate_finish, TP_PROTO(u64 timestamp, u32 cpu_hwid))
gator_update_cpu_mapping(cpu_hwid);
- // get_physical_cpu must be called after gator_update_cpu_mapping
+ /* get_physical_cpu must be called after gator_update_cpu_mapping */
cpu = get_physical_cpu();
gator_timer_online_dispatch(cpu, true);
gator_timer_online((void *)1);
@@ -146,12 +147,11 @@ GATOR_DEFINE_PROBE(cpu_migrate_current, TP_PROTO(u64 timestamp, u32 cpu_hwid))
static void gator_send_iks_core_names(void)
{
int cpu;
- // Send the cpu names
+ /* Send the cpu names */
preempt_disable();
for (cpu = 0; cpu < nr_cpu_ids; ++cpu) {
- if (mpidr_cpus[cpu] != NULL) {
+ if (mpidr_cpus[cpu] != NULL)
gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid);
- }
}
preempt_enable();
}
@@ -170,7 +170,7 @@ static int gator_migrate_start(void)
if (retval == 0)
retval = GATOR_REGISTER_TRACE(cpu_migrate_current);
if (retval == 0) {
- // Initialize the logical to physical cpu mapping
+ /* Initialize the logical to physical cpu mapping */
memset(&__lcpu_to_pcpu, 0xff, sizeof(__lcpu_to_pcpu));
bL_switcher_trace_trigger();
}
diff --git a/drivers/gator/gator_main.c b/drivers/gator/gator_main.c
index 0d867f2..30bf60d 100644
--- a/drivers/gator/gator_main.c
+++ b/drivers/gator/gator_main.c
@@ -7,8 +7,8 @@
*
*/
-// This version must match the gator daemon version
-#define PROTOCOL_VERSION 19
+/* This version must match the gator daemon version */
+#define PROTOCOL_VERSION 20
static unsigned long gator_protocol_version = PROTOCOL_VERSION;
#include <linux/slab.h>
@@ -25,7 +25,7 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION;
#include <linux/utsname.h>
#include <linux/kthread.h>
#include <asm/stacktrace.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "gator.h"
@@ -67,11 +67,11 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION;
#define SUMMARY_BUFFER_SIZE (1*1024)
#define BACKTRACE_BUFFER_SIZE (128*1024)
#define NAME_BUFFER_SIZE (64*1024)
-#define COUNTER_BUFFER_SIZE (64*1024) // counters have the core as part of the data and the core value in the frame header may be discarded
+#define COUNTER_BUFFER_SIZE (64*1024) /* counters have the core as part of the data and the core value in the frame header may be discarded */
#define BLOCK_COUNTER_BUFFER_SIZE (128*1024)
-#define ANNOTATE_BUFFER_SIZE (128*1024) // annotate counters have the core as part of the data and the core value in the frame header may be discarded
+#define ANNOTATE_BUFFER_SIZE (128*1024) /* annotate counters have the core as part of the data and the core value in the frame header may be discarded */
#define SCHED_TRACE_BUFFER_SIZE (128*1024)
-#define IDLE_BUFFER_SIZE (32*1024) // idle counters have the core as part of the data and the core value in the frame header may be discarded
+#define IDLE_BUFFER_SIZE (32*1024) /* idle counters have the core as part of the data and the core value in the frame header may be discarded */
#define ACTIVITY_BUFFER_SIZE (128*1024)
#define NO_COOKIE 0U
@@ -89,24 +89,24 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION;
#define MESSAGE_END_BACKTRACE 1
-// Name Frame Messages
+/* Name Frame Messages */
#define MESSAGE_COOKIE 1
#define MESSAGE_THREAD_NAME 2
#define MESSAGE_LINK 4
-// Scheduler Trace Frame Messages
+/* Scheduler Trace Frame Messages */
#define MESSAGE_SCHED_SWITCH 1
#define MESSAGE_SCHED_EXIT 2
-// Idle Frame Messages
+/* Idle Frame Messages */
#define MESSAGE_IDLE_ENTER 1
#define MESSAGE_IDLE_EXIT 2
-// Summary Frame Messages
+/* Summary Frame Messages */
#define MESSAGE_SUMMARY 1
#define MESSAGE_CORE_NAME 3
-// Activity Frame Messages
+/* Activity Frame Messages */
#define MESSAGE_SWITCH 2
#define MESSAGE_EXIT 3
@@ -140,14 +140,15 @@ enum {
* Globals
******************************************************************************/
static unsigned long gator_cpu_cores;
-// Size of the largest buffer. Effectively constant, set in gator_op_create_files
+/* Size of the largest buffer. Effectively constant, set in gator_op_create_files */
static unsigned long userspace_buffer_size;
static unsigned long gator_backtrace_depth;
-// How often to commit the buffers for live in nanoseconds
+/* How often to commit the buffers for live in nanoseconds */
static u64 gator_live_rate;
static unsigned long gator_started;
static u64 gator_monotonic_started;
+static u64 gator_sync_time;
static u64 gator_hibernate_time;
static unsigned long gator_buffer_opened;
static unsigned long gator_timer_count;
@@ -161,7 +162,7 @@ static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
static DECLARE_WAIT_QUEUE_HEAD(gator_annotate_wait);
static struct timer_list gator_buffer_wake_up_timer;
static bool gator_buffer_wake_run;
-// Initialize semaphore unlocked to initialize memory values
+/* Initialize semaphore unlocked to initialize memory values */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
static DECLARE_MUTEX(gator_buffer_wake_sem);
#else
@@ -183,33 +184,43 @@ static DEFINE_PER_CPU(bool, in_scheduler_context);
* Prototypes
******************************************************************************/
static u64 gator_get_time(void);
+static void gator_emit_perf_time(u64 time);
static void gator_op_create_files(struct super_block *sb, struct dentry *root);
-// gator_buffer is protected by being per_cpu and by having IRQs disabled when writing to it.
-// Most marshal_* calls take care of this except for marshal_cookie*, marshal_backtrace* and marshal_frame where the caller is responsible for doing so.
-// No synchronization is needed with the backtrace buffer as it is per cpu and is only used from the hrtimer.
-// The annotate_lock must be held when using the annotation buffer as it is not per cpu.
-// collect_counters which is the sole writer to the block counter frame is additionally protected by the per cpu collecting flag
+/* gator_buffer is protected by being per_cpu and by having IRQs
+ * disabled when writing to it. Most marshal_* calls take care of this
+ * except for marshal_cookie*, marshal_backtrace* and marshal_frame
+ * where the caller is responsible for doing so. No synchronization is
+ * needed with the backtrace buffer as it is per cpu and is only used
+ * from the hrtimer. The annotate_lock must be held when using the
+ * annotation buffer as it is not per cpu. collect_counters which is
+ * the sole writer to the block counter frame is additionally
+ * protected by the per cpu collecting flag.
+ */
-// Size of the buffer, must be a power of 2. Effectively constant, set in gator_op_setup.
+/* Size of the buffer, must be a power of 2. Effectively constant, set in gator_op_setup. */
static uint32_t gator_buffer_size[NUM_GATOR_BUFS];
-// gator_buffer_size - 1, bitwise and with pos to get offset into the array. Effectively constant, set in gator_op_setup.
+/* gator_buffer_size - 1, bitwise and with pos to get offset into the array. Effectively constant, set in gator_op_setup. */
static uint32_t gator_buffer_mask[NUM_GATOR_BUFS];
-// Read position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are read by userspace in userspace_buffer_read
+/* Read position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are read by userspace in userspace_buffer_read */
static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_read);
-// Write position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are written to the buffer
+/* Write position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are written to the buffer */
static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_write);
-// Commit position in the buffer. Initialized to zero in gator_op_setup and incremented after a frame is ready to be read by userspace
+/* Commit position in the buffer. Initialized to zero in gator_op_setup and incremented after a frame is ready to be read by userspace */
static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_commit);
-// If set to false, decreases the number of bytes returned by buffer_bytes_available. Set in buffer_check_space if no space is remaining. Initialized to true in gator_op_setup
-// This means that if we run out of space, continue to report that no space is available until bytes are read by userspace
+/* If set to false, decreases the number of bytes returned by
+ * buffer_bytes_available. Set in buffer_check_space if no space is
+ * remaining. Initialized to true in gator_op_setup. This means that
+ * if we run out of space, continue to report that no space is
+ * available until bytes are read by userspace
+ */
static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], buffer_space_available);
-// The buffer. Allocated in gator_op_setup
+/* The buffer. Allocated in gator_op_setup */
static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer);
-// The time after which the buffer should be committed for live display
+/* The time after which the buffer should be committed for live display */
static DEFINE_PER_CPU(u64, gator_buffer_commit_time);
-// List of all gator events - new events must be added to this list
+/* List of all gator events - new events must be added to this list */
#define GATOR_EVENTS_LIST \
GATOR_EVENT(gator_events_armv6_init) \
GATOR_EVENT(gator_events_armv7_init) \
@@ -218,15 +229,14 @@ static DEFINE_PER_CPU(u64, gator_buffer_commit_time);
GATOR_EVENT(gator_events_irq_init) \
GATOR_EVENT(gator_events_l2c310_init) \
GATOR_EVENT(gator_events_mali_init) \
- GATOR_EVENT(gator_events_mali_t6xx_hw_init) \
- GATOR_EVENT(gator_events_mali_t6xx_init) \
+ GATOR_EVENT(gator_events_mali_midgard_hw_init) \
+ GATOR_EVENT(gator_events_mali_midgard_init) \
GATOR_EVENT(gator_events_meminfo_init) \
GATOR_EVENT(gator_events_mmapped_init) \
GATOR_EVENT(gator_events_net_init) \
GATOR_EVENT(gator_events_perf_pmu_init) \
GATOR_EVENT(gator_events_sched_init) \
GATOR_EVENT(gator_events_scorpion_init) \
- GATOR_EVENT(gator_events_threads_init) \
#define GATOR_EVENT(EVENT_INIT) __weak int EVENT_INIT(void);
GATOR_EVENTS_LIST
@@ -315,13 +325,6 @@ static const struct gator_cpu gator_cpus[] = {
.pmnc_counters = 6,
},
{
- .cpuid = CORTEX_A12,
- .core_name = "Cortex-A12",
- .pmnc_name = "ARMv7_Cortex_A12",
- .dt_name = "arm,cortex-a12",
- .pmnc_counters = 6,
- },
- {
.cpuid = CORTEX_A15,
.core_name = "Cortex-A15",
.pmnc_name = "ARMv7_Cortex_A15",
@@ -400,23 +403,32 @@ const struct gator_cpu *gator_find_cpu_by_cpuid(const u32 cpuid)
for (i = 0; gator_cpus[i].cpuid != 0; ++i) {
const struct gator_cpu *const gator_cpu = &gator_cpus[i];
- if (gator_cpu->cpuid == cpuid) {
+
+ if (gator_cpu->cpuid == cpuid)
return gator_cpu;
- }
}
return NULL;
}
+static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-";
+static const char NEW_PMU_PREFIX[] = "ARMv7_Cortex_";
+
const struct gator_cpu *gator_find_cpu_by_pmu_name(const char *const name)
{
int i;
for (i = 0; gator_cpus[i].cpuid != 0; ++i) {
const struct gator_cpu *const gator_cpu = &gator_cpus[i];
- if (gator_cpu->pmnc_name != NULL && strcmp(gator_cpu->pmnc_name, name) == 0) {
+
+ if (gator_cpu->pmnc_name != NULL &&
+ /* Do the names match exactly? */
+ (strcasecmp(gator_cpu->pmnc_name, name) == 0 ||
+ /* Do these names match but have the old vs new prefix? */
+ ((strncasecmp(name, OLD_PMU_PREFIX, sizeof(OLD_PMU_PREFIX) - 1) == 0 &&
+ strncasecmp(gator_cpu->pmnc_name, NEW_PMU_PREFIX, sizeof(NEW_PMU_PREFIX) - 1) == 0 &&
+ strcasecmp(name + sizeof(OLD_PMU_PREFIX) - 1, gator_cpu->pmnc_name + sizeof(NEW_PMU_PREFIX) - 1) == 0))))
return gator_cpu;
- }
}
return NULL;
@@ -445,16 +457,15 @@ static void gator_buffer_wake_up(unsigned long data)
static int gator_buffer_wake_func(void *data)
{
for (;;) {
- if (down_killable(&gator_buffer_wake_sem)) {
+ if (down_killable(&gator_buffer_wake_sem))
break;
- }
- // Eat up any pending events
- while (!down_trylock(&gator_buffer_wake_sem));
+ /* Eat up any pending events */
+ while (!down_trylock(&gator_buffer_wake_sem))
+ ;
- if (!gator_buffer_wake_run) {
+ if (!gator_buffer_wake_run)
break;
- }
gator_buffer_wake_up(0);
}
@@ -468,6 +479,7 @@ static int gator_buffer_wake_func(void *data)
static bool buffer_commit_ready(int *cpu, int *buftype)
{
int cpu_x, x;
+
for_each_present_cpu(cpu_x) {
for (x = 0; x < NUM_GATOR_BUFS; x++)
if (per_cpu(gator_buffer_commit, cpu_x)[x] != per_cpu(gator_buffer_read, cpu_x)[x]) {
@@ -487,6 +499,7 @@ static bool buffer_commit_ready(int *cpu, int *buftype)
static void gator_timer_interrupt(void)
{
struct pt_regs *const regs = get_irq_regs();
+
gator_backtrace_handler(regs);
}
@@ -495,15 +508,14 @@ void gator_backtrace_handler(struct pt_regs *const regs)
u64 time = gator_get_time();
int cpu = get_physical_cpu();
- // Output backtrace
+ /* Output backtrace */
gator_add_sample(cpu, regs, time);
- // Collect counters
- if (!per_cpu(collecting, cpu)) {
- collect_counters(time, NULL);
- }
+ /* Collect counters */
+ if (!per_cpu(collecting, cpu))
+ collect_counters(time, current, false);
- // No buffer flushing occurs during sched switch for RT-Preempt full. The block counter frame will be flushed by collect_counters, but the sched buffer needs to be explicitly flushed
+ /* No buffer flushing occurs during sched switch for RT-Preempt full. The block counter frame will be flushed by collect_counters, but the sched buffer needs to be explicitly flushed */
#ifdef CONFIG_PREEMPT_RT_FULL
buffer_check(cpu, SCHED_TRACE_BUF, time);
#endif
@@ -511,7 +523,7 @@ void gator_backtrace_handler(struct pt_regs *const regs)
static int gator_running;
-// This function runs in interrupt context and on the appropriate core
+/* This function runs in interrupt context and on the appropriate core */
static void gator_timer_offline(void *migrate)
{
struct gator_interface *gi;
@@ -522,11 +534,10 @@ static void gator_timer_offline(void *migrate)
gator_trace_sched_offline();
gator_trace_power_offline();
- if (!migrate) {
+ if (!migrate)
gator_hrtimer_offline();
- }
- // Offline any events and output counters
+ /* Offline any events and output counters */
time = gator_get_time();
if (marshal_event_header(time)) {
list_for_each_entry(gi, &gator_events, list) {
@@ -535,24 +546,23 @@ static void gator_timer_offline(void *migrate)
marshal_event(len, buffer);
}
}
- // Only check after writing all counters so that time and corresponding counters appear in the same frame
+ /* Only check after writing all counters so that time and corresponding counters appear in the same frame */
buffer_check(cpu, BLOCK_COUNTER_BUF, time);
}
- // Flush all buffers on this core
+ /* Flush all buffers on this core */
for (i = 0; i < NUM_GATOR_BUFS; i++)
gator_commit_buffer(cpu, i, time);
}
-// This function runs in interrupt context and may be running on a core other than core 'cpu'
+/* This function runs in interrupt context and may be running on a core other than core 'cpu' */
static void gator_timer_offline_dispatch(int cpu, bool migrate)
{
struct gator_interface *gi;
list_for_each_entry(gi, &gator_events, list) {
- if (gi->offline_dispatch) {
+ if (gi->offline_dispatch)
gi->offline_dispatch(cpu, migrate);
- }
}
}
@@ -579,16 +589,15 @@ static void gator_send_core_name(const int cpu, const u32 cpuid)
const char *core_name = NULL;
char core_name_buf[32];
- // Save off this cpuid
+ /* Save off this cpuid */
gator_cpuids[cpu] = cpuid;
if (gator_cpu != NULL) {
core_name = gator_cpu->core_name;
} else {
- if (cpuid == -1) {
+ if (cpuid == -1)
snprintf(core_name_buf, sizeof(core_name_buf), "Unknown");
- } else {
+ else
snprintf(core_name_buf, sizeof(core_name_buf), "Unknown (0x%.3x)", cpuid);
- }
core_name = core_name_buf;
}
@@ -598,12 +607,12 @@ static void gator_send_core_name(const int cpu, const u32 cpuid)
#endif
}
-static void gator_read_cpuid(void * arg)
+static void gator_read_cpuid(void *arg)
{
gator_cpuids[get_physical_cpu()] = gator_cpuid();
}
-// This function runs in interrupt context and on the appropriate core
+/* This function runs in interrupt context and on the appropriate core */
static void gator_timer_online(void *migrate)
{
struct gator_interface *gi;
@@ -611,12 +620,12 @@ static void gator_timer_online(void *migrate)
int *buffer;
u64 time;
- // Send what is currently running on this core
+ /* Send what is currently running on this core */
marshal_sched_trace_switch(current->pid, 0);
gator_trace_power_online();
- // online any events and output counters
+ /* online any events and output counters */
time = gator_get_time();
if (marshal_event_header(time)) {
list_for_each_entry(gi, &gator_events, list) {
@@ -625,26 +634,24 @@ static void gator_timer_online(void *migrate)
marshal_event(len, buffer);
}
}
- // Only check after writing all counters so that time and corresponding counters appear in the same frame
+ /* Only check after writing all counters so that time and corresponding counters appear in the same frame */
buffer_check(cpu, BLOCK_COUNTER_BUF, time);
}
- if (!migrate) {
+ if (!migrate)
gator_hrtimer_online();
- }
gator_send_core_name(cpu, gator_cpuid());
}
-// This function runs in interrupt context and may be running on a core other than core 'cpu'
+/* This function runs in interrupt context and may be running on a core other than core 'cpu' */
static void gator_timer_online_dispatch(int cpu, bool migrate)
{
struct gator_interface *gi;
list_for_each_entry(gi, &gator_events, list) {
- if (gi->online_dispatch) {
+ if (gi->online_dispatch)
gi->online_dispatch(cpu, migrate);
- }
}
}
@@ -661,15 +668,14 @@ static int gator_timer_start(unsigned long sample_rate)
gator_running = 1;
- // event based sampling trumps hr timer based sampling
- if (event_based_sampling) {
+ /* event based sampling trumps hr timer based sampling */
+ if (event_based_sampling)
sample_rate = 0;
- }
if (gator_hrtimer_init(sample_rate, gator_timer_interrupt) == -1)
return -1;
- // Send off the previously saved cpuids
+ /* Send off the previously saved cpuids */
for_each_present_cpu(cpu) {
preempt_disable();
gator_send_core_name(cpu, gator_cpuids[cpu]);
@@ -693,21 +699,24 @@ static u64 gator_get_time(void)
u64 delta;
int cpu = smp_processor_id();
- // Match clock_gettime(CLOCK_MONOTONIC_RAW, &ts) from userspace
+ /* Match clock_gettime(CLOCK_MONOTONIC_RAW, &ts) from userspace */
getrawmonotonic(&ts);
timestamp = timespec_to_ns(&ts);
- // getrawmonotonic is not monotonic on all systems. Detect and attempt to correct these cases.
- // up to 0.5ms delta has been seen on some systems, which can skew Streamline data when viewing at high resolution.
- // This doesn't work well with interrupts, but that it's OK - the real concern is to catch big jumps in time
+ /* getrawmonotonic is not monotonic on all systems. Detect and
+ * attempt to correct these cases. up to 0.5ms delta has been seen
+ * on some systems, which can skew Streamline data when viewing at
+ * high resolution. This doesn't work well with interrupts, but that
+ * it's OK - the real concern is to catch big jumps in time
+ */
prev_timestamp = per_cpu(last_timestamp, cpu);
if (prev_timestamp <= timestamp) {
per_cpu(last_timestamp, cpu) = timestamp;
} else {
delta = prev_timestamp - timestamp;
- // Log the error once
+ /* Log the error once */
if (!printed_monotonic_warning && delta > 500000) {
- printk(KERN_ERR "%s: getrawmonotonic is not monotonic cpu: %i delta: %lli\nSkew in Streamline data may be present at the fine zoom levels\n", __FUNCTION__, cpu, delta);
+ pr_err("%s: getrawmonotonic is not monotonic cpu: %i delta: %lli\nSkew in Streamline data may be present at the fine zoom levels\n", __func__, cpu, delta);
printed_monotonic_warning = true;
}
timestamp = prev_timestamp;
@@ -716,6 +725,19 @@ static u64 gator_get_time(void)
return timestamp - gator_monotonic_started;
}
+static void gator_emit_perf_time(u64 time)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+ if (time >= gator_sync_time) {
+ int cpu = get_physical_cpu();
+
+ marshal_event_single64(0, -1, local_clock());
+ gator_sync_time += NSEC_PER_SEC;
+ gator_commit_buffer(cpu, COUNTER_BUF, time);
+ }
+#endif
+}
+
/******************************************************************************
* cpu hotplug and pm notifiers
******************************************************************************/
@@ -743,8 +765,10 @@ static struct notifier_block __refdata gator_hotcpu_notifier = {
.notifier_call = gator_hotcpu_notify,
};
-// n.b. calling "on_each_cpu" only runs on those that are online
-// Registered linux events are not disabled, so their counters will continue to collect
+/* n.b. calling "on_each_cpu" only runs on those that are online.
+ * Registered linux events are not disabled, so their counters will
+ * continue to collect
+ */
static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy)
{
int cpu;
@@ -760,13 +784,13 @@ static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void
gator_timer_offline_dispatch(lcpu_to_pcpu(cpu), false);
}
- // Record the wallclock hibernate time
+ /* Record the wallclock hibernate time */
getnstimeofday(&ts);
gator_hibernate_time = timespec_to_ns(&ts) - gator_get_time();
break;
case PM_POST_HIBERNATION:
case PM_POST_SUSPEND:
- // Adjust gator_monotonic_started for the time spent sleeping, as gator_get_time does not account for it
+ /* Adjust gator_monotonic_started for the time spent sleeping, as gator_get_time does not account for it */
if (gator_hibernate_time > 0) {
getnstimeofday(&ts);
gator_monotonic_started += gator_hibernate_time + gator_get_time() - timespec_to_ns(&ts);
@@ -792,6 +816,7 @@ static struct notifier_block gator_pm_notifier = {
static int gator_notifier_start(void)
{
int retval;
+
retval = register_hotcpu_notifier(&gator_hotcpu_notifier);
if (retval == 0)
retval = register_pm_notifier(&gator_pm_notifier);
@@ -812,28 +837,37 @@ static void gator_summary(void)
u64 timestamp, uptime;
struct timespec ts;
char uname_buf[512];
- void (*m2b)(struct timespec *ts);
snprintf(uname_buf, sizeof(uname_buf), "%s %s %s %s %s GNU/Linux", utsname()->sysname, utsname()->nodename, utsname()->release, utsname()->version, utsname()->machine);
getnstimeofday(&ts);
timestamp = timespec_to_ns(&ts);
- do_posix_clock_monotonic_gettime(&ts);
- // monotonic_to_bootbased is not defined for some versions of Android
- m2b = symbol_get(monotonic_to_bootbased);
- if (m2b) {
- m2b(&ts);
+ /* Similar to reading /proc/uptime from fs/proc/uptime.c, calculate uptime */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)
+ {
+ void (*m2b)(struct timespec *ts);
+
+ do_posix_clock_monotonic_gettime(&ts);
+ /* monotonic_to_bootbased is not defined for some versions of Android */
+ m2b = symbol_get(monotonic_to_bootbased);
+ if (m2b)
+ m2b(&ts);
}
+#else
+ get_monotonic_boottime(&ts);
+#endif
uptime = timespec_to_ns(&ts);
- // Disable preemption as gator_get_time calls smp_processor_id to verify time is monotonic
+ /* Disable preemption as gator_get_time calls smp_processor_id to verify time is monotonic */
preempt_disable();
- // Set monotonic_started to zero as gator_get_time is uptime minus monotonic_started
+ /* Set monotonic_started to zero as gator_get_time is uptime minus monotonic_started */
gator_monotonic_started = 0;
gator_monotonic_started = gator_get_time();
marshal_summary(timestamp, uptime, gator_monotonic_started, uname_buf);
+ gator_sync_time = 0;
+ gator_emit_perf_time(gator_monotonic_started);
preempt_enable();
}
@@ -846,12 +880,14 @@ int gator_events_install(struct gator_interface *interface)
int gator_events_get_key(void)
{
- // key 0 is reserved as a timestamp
- // key 1 is reserved as the marker for thread specific counters
- // Odd keys are assigned by the driver, even keys by the daemon
+ /* key 0 is reserved as a timestamp. key 1 is reserved as the marker
+ * for thread specific counters. key 2 is reserved as the marker for
+ * core. Odd keys are assigned by the driver, even keys by the
+ * daemon.
+ */
static int key = 3;
-
const int ret = key;
+
key += 2;
return ret;
}
@@ -862,7 +898,7 @@ static int gator_init(void)
calc_first_cluster_size();
- // events sources
+ /* events sources */
for (i = 0; i < ARRAY_SIZE(gator_events_list); i++)
if (gator_events_list[i])
gator_events_list[i]();
@@ -888,26 +924,25 @@ static int gator_start(void)
struct gator_interface *gi;
gator_buffer_wake_run = true;
- if (IS_ERR(gator_buffer_wake_thread = kthread_run(gator_buffer_wake_func, NULL, "gator_bwake"))) {
+ gator_buffer_wake_thread = kthread_run(gator_buffer_wake_func, NULL, "gator_bwake");
+ if (IS_ERR(gator_buffer_wake_thread))
goto bwake_failure;
- }
if (gator_migrate_start())
goto migrate_failure;
- // Initialize the buffer with the frame type and core
+ /* Initialize the buffer with the frame type and core */
for_each_present_cpu(cpu) {
- for (i = 0; i < NUM_GATOR_BUFS; i++) {
+ for (i = 0; i < NUM_GATOR_BUFS; i++)
marshal_frame(cpu, i);
- }
per_cpu(last_timestamp, cpu) = 0;
}
printed_monotonic_warning = false;
- // Capture the start time
+ /* Capture the start time */
gator_summary();
- // start all events
+ /* start all events */
list_for_each_entry(gi, &gator_events, list) {
if (gi->start && gi->start() != 0) {
struct list_head *ptr = gi->list.prev;
@@ -924,7 +959,7 @@ static int gator_start(void)
}
}
- // cookies shall be initialized before trace_sched_start() and gator_timer_start()
+ /* cookies shall be initialized before trace_sched_start() and gator_timer_start() */
if (cookies_initialize())
goto cookies_failure;
if (gator_annotate_start())
@@ -955,7 +990,7 @@ sched_failure:
annotate_failure:
cookies_release();
cookies_failure:
- // stop all events
+ /* stop all events */
list_for_each_entry(gi, &gator_events, list)
if (gi->stop)
gi->stop();
@@ -979,11 +1014,11 @@ static void gator_stop(void)
gator_trace_power_stop();
gator_trace_gpu_stop();
- // stop all interrupt callback reads before tearing down other interfaces
- gator_notifier_stop(); // should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined
+ /* stop all interrupt callback reads before tearing down other interfaces */
+ gator_notifier_stop(); /* should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined */
gator_timer_stop();
- // stop all events
+ /* stop all events */
list_for_each_entry(gi, &gator_events, list)
if (gi->stop)
gi->stop();
@@ -1033,9 +1068,9 @@ static int gator_op_setup(void)
gator_buffer_size[ACTIVITY_BUF] = ACTIVITY_BUFFER_SIZE;
gator_buffer_mask[ACTIVITY_BUF] = ACTIVITY_BUFFER_SIZE - 1;
- // Initialize percpu per buffer variables
+ /* Initialize percpu per buffer variables */
for (i = 0; i < NUM_GATOR_BUFS; i++) {
- // Verify buffers are a power of 2
+ /* Verify buffers are a power of 2 */
if (gator_buffer_size[i] & (gator_buffer_size[i] - 1)) {
err = -ENOEXEC;
goto setup_error;
@@ -1048,7 +1083,7 @@ static int gator_op_setup(void)
per_cpu(buffer_space_available, cpu)[i] = true;
per_cpu(gator_buffer_commit_time, cpu) = gator_live_rate;
- // Annotation is a special case that only uses a single buffer
+ /* Annotation is a special case that only uses a single buffer */
if (cpu > 0 && i == ANNOTATE_BUF) {
per_cpu(gator_buffer, cpu)[i] = NULL;
continue;
@@ -1188,7 +1223,8 @@ static int userspace_buffer_open(struct inode *inode, struct file *file)
if (test_and_set_bit_lock(0, &gator_buffer_opened))
return -EBUSY;
- if ((err = gator_op_setup()))
+ err = gator_op_setup();
+ if (err)
goto fail;
/* NB: the actual start happens from userspace
@@ -1218,22 +1254,20 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf, size_t
int cpu, buftype;
int written = 0;
- // ensure there is enough space for a whole frame
- if (count < userspace_buffer_size || *offset) {
+ /* ensure there is enough space for a whole frame */
+ if (count < userspace_buffer_size || *offset)
return -EINVAL;
- }
- // sleep until the condition is true or a signal is received
- // the condition is checked each time gator_buffer_wait is woken up
+ /* sleep until the condition is true or a signal is received the
+ * condition is checked each time gator_buffer_wait is woken up
+ */
wait_event_interruptible(gator_buffer_wait, buffer_commit_ready(&cpu, &buftype) || !gator_started);
- if (signal_pending(current)) {
+ if (signal_pending(current))
return -EINTR;
- }
- if (buftype == -1 || cpu == -1) {
+ if (buftype == -1 || cpu == -1)
return 0;
- }
mutex_lock(&gator_buffer_mutex);
@@ -1241,12 +1275,11 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf, size_t
read = per_cpu(gator_buffer_read, cpu)[buftype];
commit = per_cpu(gator_buffer_commit, cpu)[buftype];
- // May happen if the buffer is freed during pending reads.
- if (!per_cpu(gator_buffer, cpu)[buftype]) {
+ /* May happen if the buffer is freed during pending reads. */
+ if (!per_cpu(gator_buffer, cpu)[buftype])
break;
- }
- // determine the size of two halves
+ /* determine the size of two halves */
length1 = commit - read;
length2 = 0;
buffer1 = &(per_cpu(gator_buffer, cpu)[buftype][read]);
@@ -1256,32 +1289,28 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf, size_t
length2 = commit;
}
- if (length1 + length2 > count - written) {
+ if (length1 + length2 > count - written)
break;
- }
- // start, middle or end
- if (length1 > 0 && copy_to_user(&buf[written], buffer1, length1)) {
+ /* start, middle or end */
+ if (length1 > 0 && copy_to_user(&buf[written], buffer1, length1))
break;
- }
- // possible wrap around
- if (length2 > 0 && copy_to_user(&buf[written + length1], buffer2, length2)) {
+ /* possible wrap around */
+ if (length2 > 0 && copy_to_user(&buf[written + length1], buffer2, length2))
break;
- }
per_cpu(gator_buffer_read, cpu)[buftype] = commit;
written += length1 + length2;
- // Wake up annotate_write if more space is available
- if (buftype == ANNOTATE_BUF) {
+ /* Wake up annotate_write if more space is available */
+ if (buftype == ANNOTATE_BUF)
wake_up(&gator_annotate_wait);
- }
} while (buffer_commit_ready(&cpu, &buftype));
mutex_unlock(&gator_buffer_mutex);
- // kick just in case we've lost an SMP event
+ /* kick just in case we've lost an SMP event */
wake_up(&gator_buffer_wait);
return written > 0 ? written : -EFAULT;
@@ -1348,19 +1377,19 @@ static void gator_op_create_files(struct super_block *sb, struct dentry *root)
gatorfs_create_ro_u64(sb, root, "started", &gator_monotonic_started);
gatorfs_create_u64(sb, root, "live_rate", &gator_live_rate);
- // Annotate interface
+ /* Annotate interface */
gator_annotate_create_files(sb, root);
- // Linux Events
+ /* Linux Events */
dir = gatorfs_mkdir(sb, root, "events");
list_for_each_entry(gi, &gator_events, list)
if (gi->create_files)
gi->create_files(sb, dir);
- // Sched Events
+ /* Sched Events */
sched_trace_create_files(sb, dir);
- // Power interface
+ /* Power interface */
gator_trace_power_create_files(sb, dir);
}
@@ -1396,19 +1425,22 @@ static void gator_op_create_files(struct super_block *sb, struct dentry *root)
GATOR_HANDLE_TRACEPOINT(sched_process_free); \
GATOR_HANDLE_TRACEPOINT(sched_switch); \
GATOR_HANDLE_TRACEPOINT(softirq_exit); \
+ GATOR_HANDLE_TRACEPOINT(task_rename); \
#define GATOR_HANDLE_TRACEPOINT(probe_name) \
struct tracepoint *gator_tracepoint_##probe_name
GATOR_TRACEPOINTS;
#undef GATOR_HANDLE_TRACEPOINT
-static void gator_fct(struct tracepoint *tp, void *priv)
+static void gator_save_tracepoint(struct tracepoint *tp, void *priv)
{
#define GATOR_HANDLE_TRACEPOINT(probe_name) \
- if (strcmp(tp->name, #probe_name) == 0) { \
- gator_tracepoint_##probe_name = tp; \
- return; \
- }
+ do { \
+ if (strcmp(tp->name, #probe_name) == 0) { \
+ gator_tracepoint_##probe_name = tp; \
+ return; \
+ } \
+ } while (0)
GATOR_TRACEPOINTS;
#undef GATOR_HANDLE_TRACEPOINT
}
@@ -1421,11 +1453,10 @@ GATOR_TRACEPOINTS;
static int __init gator_module_init(void)
{
- for_each_kernel_tracepoint(gator_fct, NULL);
+ for_each_kernel_tracepoint(gator_save_tracepoint, NULL);
- if (gatorfs_register()) {
+ if (gatorfs_register())
return -1;
- }
if (gator_init()) {
gatorfs_unregister();
@@ -1434,7 +1465,7 @@ static int __init gator_module_init(void)
setup_timer(&gator_buffer_wake_up_timer, gator_buffer_wake_up, 0);
- // Initialize the list of cpuids
+ /* Initialize the list of cpuids */
memset(gator_cpuids, -1, sizeof(gator_cpuids));
on_each_cpu(gator_read_cpuid, NULL, 1);
diff --git a/drivers/gator/gator_marshaling.c b/drivers/gator/gator_marshaling.c
index 97b4ae6..0d11676 100644
--- a/drivers/gator/gator_marshaling.c
+++ b/drivers/gator/gator_marshaling.c
@@ -23,7 +23,7 @@
#include "gator_events_mali_common.h"
#endif
-static void marshal_summary(long long timestamp, long long uptime, long long monotonic_delta, const char * uname)
+static void marshal_summary(long long timestamp, long long uptime, long long monotonic_delta, const char *uname)
{
unsigned long flags;
int cpu = 0;
@@ -40,19 +40,27 @@ static void marshal_summary(long long timestamp, long long uptime, long long mon
gator_buffer_write_string(cpu, SUMMARY_BUF, "iks");
gator_buffer_write_string(cpu, SUMMARY_BUF, "");
#endif
- // Let Streamline know which GPU is used so that it can label the GPU Activity appropriately. This is a temporary fix, to be improved in a future release.
+#ifdef CONFIG_PREEMPT_RTB
+ gator_buffer_write_string(cpu, SUMMARY_BUF, "preempt_rtb");
+ gator_buffer_write_string(cpu, SUMMARY_BUF, "");
+#endif
+#ifdef CONFIG_PREEMPT_RT_FULL
+ gator_buffer_write_string(cpu, SUMMARY_BUF, "preempt_rt_full");
+ gator_buffer_write_string(cpu, SUMMARY_BUF, "");
+#endif
+ /* Let Streamline know which GPU is used so that it can label the GPU Activity appropriately. This is a temporary fix, to be improved in a future release. */
#ifdef MALI_SUPPORT
gator_buffer_write_string(cpu, SUMMARY_BUF, "mali_type");
#if (MALI_SUPPORT == MALI_4xx)
gator_buffer_write_string(cpu, SUMMARY_BUF, "4xx");
-#elif (MALI_SUPPORT == MALI_T6xx)
+#elif (MALI_SUPPORT == MALI_MIDGARD)
gator_buffer_write_string(cpu, SUMMARY_BUF, "6xx");
#else
gator_buffer_write_string(cpu, SUMMARY_BUF, "unknown");
#endif
#endif
gator_buffer_write_string(cpu, SUMMARY_BUF, "");
- // Commit the buffer now so it can be one of the first frames read by Streamline
+ /* Commit the buffer now so it can be one of the first frames read by Streamline */
local_irq_restore(flags);
gator_commit_buffer(cpu, SUMMARY_BUF, gator_get_time());
}
@@ -60,13 +68,14 @@ static void marshal_summary(long long timestamp, long long uptime, long long mon
static bool marshal_cookie_header(const char *text)
{
int cpu = get_physical_cpu();
+
return buffer_check_space(cpu, NAME_BUF, strlen(text) + 3 * MAXSIZE_PACK32);
}
static void marshal_cookie(int cookie, const char *text)
{
int cpu = get_physical_cpu();
- // buffer_check_space already called by marshal_cookie_header
+ /* buffer_check_space already called by marshal_cookie_header */
gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_COOKIE);
gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
gator_buffer_write_string(cpu, NAME_BUF, text);
@@ -77,6 +86,7 @@ static void marshal_thread_name(int pid, char *name)
{
unsigned long flags, cpu;
u64 time;
+
local_irq_save(flags);
cpu = get_physical_cpu();
time = gator_get_time();
@@ -105,15 +115,16 @@ static void marshal_link(int cookie, int tgid, int pid)
gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
}
local_irq_restore(flags);
- // Check and commit; commit is set to occur once buffer is 3/4 full
+ /* Check and commit; commit is set to occur once buffer is 3/4 full */
buffer_check(cpu, NAME_BUF, time);
}
static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, u64 time)
{
int cpu = get_physical_cpu();
+
if (!buffer_check_space(cpu, BACKTRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32 + gator_backtrace_depth * 2 * MAXSIZE_PACK32)) {
- // Check and commit; commit is set to occur once buffer is 3/4 full
+ /* Check and commit; commit is set to occur once buffer is 3/4 full */
buffer_check(cpu, BACKTRACE_BUF, time);
return false;
@@ -130,9 +141,9 @@ static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, u64 tim
static void marshal_backtrace(unsigned long address, int cookie, int in_kernel)
{
int cpu = get_physical_cpu();
- if (cookie == 0 && !in_kernel) {
+
+ if (cookie == 0 && !in_kernel)
cookie = UNRESOLVED_COOKIE;
- }
gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie);
gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, address);
}
@@ -140,9 +151,10 @@ static void marshal_backtrace(unsigned long address, int cookie, int in_kernel)
static void marshal_backtrace_footer(u64 time)
{
int cpu = get_physical_cpu();
+
gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_END_BACKTRACE);
- // Check and commit; commit is set to occur once buffer is 3/4 full
+ /* Check and commit; commit is set to occur once buffer is 3/4 full */
buffer_check(cpu, BACKTRACE_BUF, time);
}
@@ -153,7 +165,7 @@ static bool marshal_event_header(u64 time)
local_irq_save(flags);
if (buffer_check_space(cpu, BLOCK_COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
- gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0); // key of zero indicates a timestamp
+ gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0); /* key of zero indicates a timestamp */
gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, time);
retval = true;
}
@@ -169,18 +181,17 @@ static void marshal_event(int len, int *buffer)
if (len <= 0)
return;
- // length must be even since all data is a (key, value) pair
+ /* length must be even since all data is a (key, value) pair */
if (len & 0x1) {
- pr_err("gator: invalid counter data detected and discarded");
+ pr_err("gator: invalid counter data detected and discarded\n");
return;
}
- // events must be written in key,value pairs
+ /* events must be written in key,value pairs */
local_irq_save(flags);
for (i = 0; i < len; i += 2) {
- if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK32)) {
+ if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK32))
break;
- }
gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i]);
gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i + 1]);
}
@@ -194,26 +205,24 @@ static void marshal_event64(int len, long long *buffer64)
if (len <= 0)
return;
- // length must be even since all data is a (key, value) pair
+ /* length must be even since all data is a (key, value) pair */
if (len & 0x1) {
- pr_err("gator: invalid counter data detected and discarded");
+ pr_err("gator: invalid counter data detected and discarded\n");
return;
}
- // events must be written in key,value pairs
+ /* events must be written in key,value pairs */
local_irq_save(flags);
for (i = 0; i < len; i += 2) {
- if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK64)) {
+ if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK64))
break;
- }
gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i]);
gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i + 1]);
}
local_irq_restore(flags);
}
-#if GATOR_CPU_FREQ_SUPPORT
-static void marshal_event_single(int core, int key, int value)
+static void __maybe_unused marshal_event_single(int core, int key, int value)
{
unsigned long flags, cpu;
u64 time;
@@ -228,11 +237,11 @@ static void marshal_event_single(int core, int key, int value)
gator_buffer_write_packed_int(cpu, COUNTER_BUF, value);
}
local_irq_restore(flags);
- // Check and commit; commit is set to occur once buffer is 3/4 full
+ /* Check and commit; commit is set to occur once buffer is 3/4 full */
buffer_check(cpu, COUNTER_BUF, time);
}
-static void marshal_event_single64(int core, int key, long long value)
+static void __maybe_unused marshal_event_single64(int core, int key, long long value)
{
unsigned long flags, cpu;
u64 time;
@@ -247,10 +256,9 @@ static void marshal_event_single64(int core, int key, long long value)
gator_buffer_write_packed_int64(cpu, COUNTER_BUF, value);
}
local_irq_restore(flags);
- // Check and commit; commit is set to occur once buffer is 3/4 full
+ /* Check and commit; commit is set to occur once buffer is 3/4 full */
buffer_check(cpu, COUNTER_BUF, time);
}
-#endif
static void marshal_sched_trace_switch(int pid, int state)
{
@@ -269,7 +277,7 @@ static void marshal_sched_trace_switch(int pid, int state)
gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state);
}
local_irq_restore(flags);
- // Check and commit; commit is set to occur once buffer is 3/4 full
+ /* Check and commit; commit is set to occur once buffer is 3/4 full */
buffer_check(cpu, SCHED_TRACE_BUF, time);
}
@@ -289,7 +297,7 @@ static void marshal_sched_trace_exit(int tgid, int pid)
gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
}
local_irq_restore(flags);
- // Check and commit; commit is set to occur once buffer is 3/4 full
+ /* Check and commit; commit is set to occur once buffer is 3/4 full */
buffer_check(cpu, SCHED_TRACE_BUF, time);
}
@@ -308,7 +316,7 @@ static void marshal_idle(int core, int state)
gator_buffer_write_packed_int(cpu, IDLE_BUF, core);
}
local_irq_restore(flags);
- // Check and commit; commit is set to occur once buffer is 3/4 full
+ /* Check and commit; commit is set to occur once buffer is 3/4 full */
buffer_check(cpu, IDLE_BUF, time);
}
#endif
@@ -318,6 +326,7 @@ static void marshal_core_name(const int core, const int cpuid, const char *name)
{
int cpu = get_physical_cpu();
unsigned long flags;
+
local_irq_save(flags);
if (buffer_check_space(cpu, SUMMARY_BUF, MAXSIZE_PACK32 + MAXSIZE_CORE_NAME)) {
gator_buffer_write_packed_int(cpu, SUMMARY_BUF, MESSAGE_CORE_NAME);
@@ -325,7 +334,7 @@ static void marshal_core_name(const int core, const int cpuid, const char *name)
gator_buffer_write_packed_int(cpu, SUMMARY_BUF, cpuid);
gator_buffer_write_string(cpu, SUMMARY_BUF, name);
}
- // Commit core names now so that they can show up in live
+ /* Commit core names now so that they can show up in live */
local_irq_restore(flags);
gator_commit_buffer(cpu, SUMMARY_BUF, gator_get_time());
}
@@ -351,12 +360,12 @@ static void marshal_activity_switch(int core, int key, int activity, int pid, in
gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, state);
}
local_irq_restore(flags);
- // Check and commit; commit is set to occur once buffer is 3/4 full
+ /* Check and commit; commit is set to occur once buffer is 3/4 full */
buffer_check(cpu, ACTIVITY_BUF, time);
}
void gator_marshal_activity_switch(int core, int key, int activity, int pid)
{
- // state is reserved for cpu use only
+ /* state is reserved for cpu use only */
marshal_activity_switch(core, key, activity, pid, 0);
}
diff --git a/drivers/gator/gator_trace_gpu.c b/drivers/gator/gator_trace_gpu.c
index a8b9e7d..5de9152 100644
--- a/drivers/gator/gator_trace_gpu.c
+++ b/drivers/gator/gator_trace_gpu.c
@@ -58,11 +58,12 @@ struct mali_activity {
static struct mali_activity mali_activities[NUMBER_OF_GPU_UNITS*NUMBER_OF_GPU_CORES];
static DEFINE_SPINLOCK(mali_activities_lock);
-/* Only one event should be running on a unit and core at a time (ie, a start
- * event can only be followed by a stop and vice versa), but because the kernel
- * only knows when a job is enqueued and not started, it is possible for a
- * start1, start2, stop1, stop2. Change it back into start1, stop1, start2,
- * stop2 by queueing up start2 and releasing it when stop1 is received.
+/* Only one event should be running on a unit and core at a time (ie,
+ * a start event can only be followed by a stop and vice versa), but
+ * because the kernel only knows when a job is enqueued and not
+ * started, it is possible for a start1, start2, stop1, stop2. Change
+ * it back into start1, stop1, start2, stop2 by queueing up start2 and
+ * releasing it when stop1 is received.
*/
static int mali_activity_index(int core, int key)
@@ -70,9 +71,8 @@ static int mali_activity_index(int core, int key)
int i;
for (i = 0; i < ARRAY_SIZE(mali_activities); ++i) {
- if ((mali_activities[i].core == core) && (mali_activities[i].key == key)) {
+ if ((mali_activities[i].core == core) && (mali_activities[i].key == key))
break;
- }
if ((mali_activities[i].core == 0) && (mali_activities[i].key == 0)) {
mali_activities[i].core = core;
mali_activities[i].key = key;
@@ -101,9 +101,8 @@ static void mali_activity_enqueue(int core, int key, int activity, int pid)
}
spin_unlock(&mali_activities_lock);
- if (!count) {
+ if (!count)
gator_marshal_activity_switch(core, key, activity, pid);
- }
}
static void mali_activity_stop(int core, int key)
@@ -129,12 +128,11 @@ static void mali_activity_stop(int core, int key)
spin_unlock(&mali_activities_lock);
gator_marshal_activity_switch(core, key, 0, 0);
- if (count) {
+ if (count)
gator_marshal_activity_switch(core, key, last_activity, last_pid);
- }
}
-void mali_activity_clear(mali_counter mali_activity[], size_t mali_activity_size)
+void mali_activity_clear(struct mali_counter mali_activity[], size_t mali_activity_size)
{
int activity;
int cores;
@@ -142,12 +140,13 @@ void mali_activity_clear(mali_counter mali_activity[], size_t mali_activity_size
for (activity = 0; activity < mali_activity_size; ++activity) {
cores = mali_activity[activity].cores;
- if (cores < 0) {
+ if (cores < 0)
cores = 1;
- }
for (core = 0; core < cores; ++core) {
if (mali_activity[activity].enabled) {
+ preempt_disable();
gator_marshal_activity_switch(core, mali_activity[activity].key, 0, 0);
+ preempt_enable();
}
}
}
@@ -155,7 +154,7 @@ void mali_activity_clear(mali_counter mali_activity[], size_t mali_activity_size
#endif
-#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
+#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD)
#include "gator_events_mali_4xx.h"
/*
@@ -183,40 +182,36 @@ enum {
EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1,
};
-mali_counter mali_activity[2];
+struct mali_counter mali_activity[2];
GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned int d2, unsigned int d3, unsigned int d4))
{
unsigned int component, state;
- // do as much work as possible before disabling interrupts
- component = (event_id >> 16) & 0xFF; // component is an 8-bit field
- state = (event_id >> 24) & 0xF; // state is a 4-bit field
+ /* do as much work as possible before disabling interrupts */
+ component = (event_id >> 16) & 0xFF; /* component is an 8-bit field */
+ state = (event_id >> 24) & 0xF; /* state is a 4-bit field */
switch (state) {
case EVENT_TYPE_START:
if (component == EVENT_CHANNEL_VP0) {
/* tgid = d0; pid = d1; */
- if (mali_activity[1].enabled) {
+ if (mali_activity[1].enabled)
mali_activity_enqueue(0, mali_activity[1].key, 1, d1);
- }
} else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
/* tgid = d0; pid = d1; */
- if (mali_activity[0].enabled) {
+ if (mali_activity[0].enabled)
mali_activity_enqueue(component - EVENT_CHANNEL_FP0, mali_activity[0].key, 1, d1);
- }
}
break;
case EVENT_TYPE_STOP:
if (component == EVENT_CHANNEL_VP0) {
- if (mali_activity[1].enabled) {
+ if (mali_activity[1].enabled)
mali_activity_stop(0, mali_activity[1].key);
- }
} else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
- if (mali_activity[0].enabled) {
+ if (mali_activity[0].enabled)
mali_activity_stop(component - EVENT_CHANNEL_FP0, mali_activity[0].key);
- }
}
break;
@@ -224,9 +219,8 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned
if (component == EVENT_CHANNEL_GPU) {
unsigned int reason = (event_id & 0xffff);
- if (reason == EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE) {
+ if (reason == EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE)
gator_events_mali_log_dvfs_event(d0, d1);
- }
}
break;
@@ -236,9 +230,9 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned
}
#endif
-#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
+#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD)
-mali_counter mali_activity[3];
+struct mali_counter mali_activity[3];
#if defined(MALI_JOB_SLOTS_EVENT_CHANGED)
GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid, unsigned char job_id))
@@ -251,8 +245,8 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne
unsigned char job_id = 0;
#endif
- component = (event_id >> 16) & 0xFF; // component is an 8-bit field
- state = (event_id >> 24) & 0xF; // state is a 4-bit field
+ component = (event_id >> 16) & 0xFF; /* component is an 8-bit field */
+ state = (event_id >> 24) & 0xF; /* state is a 4-bit field */
switch (component) {
case 0:
@@ -271,15 +265,13 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne
if (unit != GPU_UNIT_NONE) {
switch (state) {
case EVENT_TYPE_START:
- if (mali_activity[component].enabled) {
+ if (mali_activity[component].enabled)
mali_activity_enqueue(0, mali_activity[component].key, 1, (pid != 0 ? pid : tgid));
- }
break;
case EVENT_TYPE_STOP:
- default: // Some jobs can be soft-stopped, so ensure that this terminates the activity trace.
- if (mali_activity[component].enabled) {
+ default: /* Some jobs can be soft-stopped, so ensure that this terminates the activity trace. */
+ if (mali_activity[component].enabled)
mali_activity_stop(0, mali_activity[component].key);
- }
break;
}
}
@@ -298,18 +290,16 @@ static int gator_trace_gpu_start(void)
#endif
mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
-#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
+#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD)
mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity));
- if (!GATOR_REGISTER_TRACE(mali_timeline_event)) {
+ if (!GATOR_REGISTER_TRACE(mali_timeline_event))
mali_timeline_trace_registered = 1;
- }
#endif
-#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
+#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD)
mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity));
- if (!GATOR_REGISTER_TRACE(mali_job_slots_event)) {
+ if (!GATOR_REGISTER_TRACE(mali_job_slots_event))
mali_job_slots_trace_registered = 1;
- }
#endif
return 0;
@@ -317,16 +307,14 @@ static int gator_trace_gpu_start(void)
static void gator_trace_gpu_stop(void)
{
-#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
- if (mali_timeline_trace_registered) {
+#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD)
+ if (mali_timeline_trace_registered)
GATOR_UNREGISTER_TRACE(mali_timeline_event);
- }
#endif
-#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
- if (mali_job_slots_trace_registered) {
+#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD)
+ if (mali_job_slots_trace_registered)
GATOR_UNREGISTER_TRACE(mali_job_slots_event);
- }
#endif
mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
diff --git a/drivers/gator/gator_trace_power.c b/drivers/gator/gator_trace_power.c
index f2754b1..46e04b2 100644
--- a/drivers/gator/gator_trace_power.c
+++ b/drivers/gator/gator_trace_power.c
@@ -22,18 +22,20 @@
#endif
-// cpu_frequency and cpu_idle trace points were introduced in Linux kernel v2.6.38
-// the now deprecated power_frequency trace point was available prior to 2.6.38, but only for x86
+/* cpu_frequency and cpu_idle trace points were introduced in Linux
+ * kernel v2.6.38 the now deprecated power_frequency trace point was
+ * available prior to 2.6.38, but only for x86
+ */
#if GATOR_CPU_FREQ_SUPPORT
enum {
POWER_CPU_FREQ,
- POWER_CPU_IDLE,
POWER_TOTAL
};
static DEFINE_PER_CPU(ulong, idle_prev_state);
static ulong power_cpu_enabled[POWER_TOTAL];
static ulong power_cpu_key[POWER_TOTAL];
+static ulong power_cpu_cores;
static int gator_trace_power_create_files(struct super_block *sb, struct dentry *root)
{
@@ -41,8 +43,9 @@ static int gator_trace_power_create_files(struct super_block *sb, struct dentry
int cpu;
bool found_nonzero_freq = false;
- // Even if CONFIG_CPU_FREQ is defined, it still may not be used. Check
- // for non-zero values from cpufreq_quick_get
+ /* Even if CONFIG_CPU_FREQ is defined, it still may not be
+ * used. Check for non-zero values from cpufreq_quick_get
+ */
for_each_online_cpu(cpu) {
if (cpufreq_quick_get(cpu) > 0) {
found_nonzero_freq = true;
@@ -51,27 +54,18 @@ static int gator_trace_power_create_files(struct super_block *sb, struct dentry
}
if (found_nonzero_freq) {
- // cpu_frequency
+ /* cpu_frequency */
dir = gatorfs_mkdir(sb, root, "Linux_power_cpu_freq");
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &power_cpu_enabled[POWER_CPU_FREQ]);
gatorfs_create_ro_ulong(sb, dir, "key", &power_cpu_key[POWER_CPU_FREQ]);
}
- // cpu_idle
- dir = gatorfs_mkdir(sb, root, "Linux_power_cpu_idle");
- if (!dir) {
- return -1;
- }
- gatorfs_create_ulong(sb, dir, "enabled", &power_cpu_enabled[POWER_CPU_IDLE]);
- gatorfs_create_ro_ulong(sb, dir, "key", &power_cpu_key[POWER_CPU_IDLE]);
-
return 0;
}
-// 'cpu' may not equal smp_processor_id(), i.e. may not be running on the core that is having the freq/idle state change
+/* 'cpu' may not equal smp_processor_id(), i.e. may not be running on the core that is having the freq/idle state change */
GATOR_DEFINE_PROBE(cpu_frequency, TP_PROTO(unsigned int frequency, unsigned int cpu))
{
cpu = lcpu_to_pcpu(cpu);
@@ -82,56 +76,50 @@ GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu))
{
cpu = lcpu_to_pcpu(cpu);
- if (state == per_cpu(idle_prev_state, cpu)) {
+ if (state == per_cpu(idle_prev_state, cpu))
return;
- }
if (implements_wfi()) {
if (state == PWR_EVENT_EXIT) {
- // transition from wfi to non-wfi
+ /* transition from wfi to non-wfi */
marshal_idle(cpu, MESSAGE_IDLE_EXIT);
} else {
- // transition from non-wfi to wfi
+ /* transition from non-wfi to wfi */
marshal_idle(cpu, MESSAGE_IDLE_ENTER);
}
}
per_cpu(idle_prev_state, cpu) = state;
-
- if (power_cpu_enabled[POWER_CPU_IDLE]) {
- // Increment state so that no negative numbers are sent
- marshal_event_single(cpu, power_cpu_key[POWER_CPU_IDLE], state + 1);
- }
}
static void gator_trace_power_online(void)
{
int pcpu = get_physical_cpu();
int lcpu = get_logical_cpu();
- if (power_cpu_enabled[POWER_CPU_FREQ]) {
+
+ if (power_cpu_enabled[POWER_CPU_FREQ])
marshal_event_single64(pcpu, power_cpu_key[POWER_CPU_FREQ], cpufreq_quick_get(lcpu) * 1000L);
- }
}
static void gator_trace_power_offline(void)
{
- // Set frequency to zero on an offline
+ /* Set frequency to zero on an offline */
int cpu = get_physical_cpu();
- if (power_cpu_enabled[POWER_CPU_FREQ]) {
+
+ if (power_cpu_enabled[POWER_CPU_FREQ])
marshal_event_single(cpu, power_cpu_key[POWER_CPU_FREQ], 0);
- }
}
static int gator_trace_power_start(void)
{
int cpu;
- // register tracepoints
+ /* register tracepoints */
if (power_cpu_enabled[POWER_CPU_FREQ])
if (GATOR_REGISTER_TRACE(cpu_frequency))
goto fail_cpu_frequency_exit;
- // Always register for cpu:idle for detecting WFI, independent of power_cpu_enabled[POWER_CPU_IDLE]
+ /* Always register for cpu_idle for detecting WFI */
if (GATOR_REGISTER_TRACE(cpu_idle))
goto fail_cpu_idle_exit;
pr_debug("gator: registered power event tracepoints\n");
@@ -142,7 +130,7 @@ static int gator_trace_power_start(void)
return 0;
- // unregister tracepoints on error
+ /* unregister tracepoints on error */
fail_cpu_idle_exit:
if (power_cpu_enabled[POWER_CPU_FREQ])
GATOR_UNREGISTER_TRACE(cpu_frequency);
@@ -161,14 +149,15 @@ static void gator_trace_power_stop(void)
GATOR_UNREGISTER_TRACE(cpu_idle);
pr_debug("gator: unregistered power event tracepoints\n");
- for (i = 0; i < POWER_TOTAL; i++) {
+ for (i = 0; i < POWER_TOTAL; i++)
power_cpu_enabled[i] = 0;
- }
}
static void gator_trace_power_init(void)
{
int i;
+
+ power_cpu_cores = nr_cpu_ids;
for (i = 0; i < POWER_TOTAL; i++) {
power_cpu_enabled[i] = 0;
power_cpu_key[i] = gator_events_get_key();
diff --git a/drivers/gator/gator_trace_sched.c b/drivers/gator/gator_trace_sched.c
index 6550086..6d7cbd73 100644
--- a/drivers/gator/gator_trace_sched.c
+++ b/drivers/gator/gator_trace_sched.c
@@ -8,6 +8,10 @@
*/
#include <trace/events/sched.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+#include <trace/events/task.h>
+#endif
+
#include "gator.h"
#define TASK_MAP_ENTRIES 1024 /* must be power of 2 */
@@ -23,8 +27,10 @@ enum {
static DEFINE_PER_CPU(uint64_t *, taskname_keys);
static DEFINE_PER_CPU(int, collecting);
-// this array is never read as the cpu wait charts are derived counters
-// the files are needed, nonetheless, to show that these counters are available
+/* this array is never read as the cpu wait charts are derived
+ * counters the files are needed, nonetheless, to show that these
+ * counters are available
+ */
static ulong cpu_wait_enabled[CPU_WAIT_TOTAL];
static ulong sched_cpu_key[CPU_WAIT_TOTAL];
@@ -32,26 +38,24 @@ static int sched_trace_create_files(struct super_block *sb, struct dentry *root)
{
struct dentry *dir;
- // CPU Wait - Contention
+ /* CPU Wait - Contention */
dir = gatorfs_mkdir(sb, root, "Linux_cpu_wait_contention");
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &cpu_wait_enabled[STATE_CONTENTION]);
gatorfs_create_ro_ulong(sb, dir, "key", &sched_cpu_key[STATE_CONTENTION]);
- // CPU Wait - I/O
+ /* CPU Wait - I/O */
dir = gatorfs_mkdir(sb, root, "Linux_cpu_wait_io");
- if (!dir) {
+ if (!dir)
return -1;
- }
gatorfs_create_ulong(sb, dir, "enabled", &cpu_wait_enabled[STATE_WAIT_ON_IO]);
gatorfs_create_ro_ulong(sb, dir, "key", &sched_cpu_key[STATE_WAIT_ON_IO]);
return 0;
}
-static void emit_pid_name(struct task_struct *task)
+static void emit_pid_name(const char *comm, struct task_struct *task)
{
bool found = false;
char taskcomm[TASK_COMM_LEN + 3];
@@ -59,10 +63,10 @@ static void emit_pid_name(struct task_struct *task)
uint64_t *keys = &(per_cpu(taskname_keys, cpu)[(task->pid & 0xFF) * TASK_MAX_COLLISIONS]);
uint64_t value;
- value = gator_chksum_crc32(task->comm);
+ value = gator_chksum_crc32(comm);
value = (value << 32) | (uint32_t)task->pid;
- // determine if the thread name was emitted already
+ /* determine if the thread name was emitted already */
for (x = 0; x < TASK_MAX_COLLISIONS; x++) {
if (keys[x] == value) {
found = true;
@@ -71,17 +75,18 @@ static void emit_pid_name(struct task_struct *task)
}
if (!found) {
- // shift values, new value always in front
+ /* shift values, new value always in front */
uint64_t oldv, newv = value;
+
for (x = 0; x < TASK_MAX_COLLISIONS; x++) {
oldv = keys[x];
keys[x] = newv;
newv = oldv;
}
- // emit pid names, cannot use get_task_comm, as it's not exported on all kernel versions
- if (strlcpy(taskcomm, task->comm, TASK_COMM_LEN) == TASK_COMM_LEN - 1) {
- // append ellipses if task->comm has length of TASK_COMM_LEN - 1
+ /* emit pid names, cannot use get_task_comm, as it's not exported on all kernel versions */
+ if (strlcpy(taskcomm, comm, TASK_COMM_LEN) == TASK_COMM_LEN - 1) {
+ /* append ellipses if comm has length of TASK_COMM_LEN - 1 */
strcat(taskcomm, "...");
}
@@ -89,7 +94,7 @@ static void emit_pid_name(struct task_struct *task)
}
}
-static void collect_counters(u64 time, struct task_struct *task)
+static void collect_counters(u64 time, struct task_struct *task, bool sched_switch)
{
int *buffer, len, cpu = get_physical_cpu();
long long *buffer64;
@@ -98,7 +103,7 @@ static void collect_counters(u64 time, struct task_struct *task)
if (marshal_event_header(time)) {
list_for_each_entry(gi, &gator_events, list) {
if (gi->read) {
- len = gi->read(&buffer);
+ len = gi->read(&buffer, sched_switch);
marshal_event(len, buffer);
} else if (gi->read64) {
len = gi->read64(&buffer64);
@@ -109,22 +114,26 @@ static void collect_counters(u64 time, struct task_struct *task)
marshal_event64(len, buffer64);
}
}
- // Only check after writing all counters so that time and corresponding counters appear in the same frame
+ if (cpu == 0)
+ gator_emit_perf_time(time);
+ /* Only check after writing all counters so that time and corresponding counters appear in the same frame */
buffer_check(cpu, BLOCK_COUNTER_BUF, time);
- // Commit buffers on timeout
+ /* Commit buffers on timeout */
if (gator_live_rate > 0 && time >= per_cpu(gator_buffer_commit_time, cpu)) {
static const int buftypes[] = { NAME_BUF, COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF, ACTIVITY_BUF };
int i;
- for (i = 0; i < ARRAY_SIZE(buftypes); ++i) {
+ for (i = 0; i < ARRAY_SIZE(buftypes); ++i)
gator_commit_buffer(cpu, buftypes[i], time);
- }
- // spinlocks are noops on uniprocessor machines and mutexes do not work in sched_switch context in
- // RT-Preempt full, so disable proactive flushing of the annotate frame on uniprocessor machines.
+ /* spinlocks are noops on uniprocessor machines and mutexes do
+ * not work in sched_switch context in RT-Preempt full, so
+ * disable proactive flushing of the annotate frame on
+ * uniprocessor machines.
+ */
#ifdef CONFIG_SMP
- // Try to preemptively flush the annotate buffer to reduce the chance of the buffer being full
+ /* Try to preemptively flush the annotate buffer to reduce the chance of the buffer being full */
if (on_primary_core() && spin_trylock(&annotate_lock)) {
gator_commit_buffer(0, ANNOTATE_BUF, time);
spin_unlock(&annotate_lock);
@@ -134,7 +143,7 @@ static void collect_counters(u64 time, struct task_struct *task)
}
}
-// special case used during a suspend of the system
+/* special case used during a suspend of the system */
static void trace_sched_insert_idle(void)
{
marshal_sched_trace_switch(0, 0);
@@ -146,7 +155,7 @@ static void gator_trace_emit_link(struct task_struct *p)
int cpu = get_physical_cpu();
cookie = get_exec_cookie(cpu, p);
- emit_pid_name(p);
+ emit_pid_name(p->comm, p);
marshal_link(cookie, p->tgid, p->pid);
}
@@ -161,6 +170,15 @@ GATOR_DEFINE_PROBE(sched_process_exec, TP_PROTO(struct task_struct *p, pid_t old
{
gator_trace_emit_link(p);
}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)
+GATOR_DEFINE_PROBE(task_rename, TP_PROTO(struct task_struct *task, char *comm))
+#else
+GATOR_DEFINE_PROBE(task_rename, TP_PROTO(struct task_struct *task, const char *comm))
+#endif
+{
+ emit_pid_name(comm, task);
+}
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
@@ -174,17 +192,16 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_
per_cpu(in_scheduler_context, cpu) = true;
- // do as much work as possible before disabling interrupts
- if (prev->state == TASK_RUNNING) {
+ /* do as much work as possible before disabling interrupts */
+ if (prev->state == TASK_RUNNING)
state = STATE_CONTENTION;
- } else if (prev->in_iowait) {
+ else if (prev->in_iowait)
state = STATE_WAIT_ON_IO;
- } else {
+ else
state = STATE_WAIT_ON_OTHER;
- }
per_cpu(collecting, cpu) = 1;
- collect_counters(gator_get_time(), prev);
+ collect_counters(gator_get_time(), prev, true);
per_cpu(collecting, cpu) = 0;
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
@@ -202,18 +219,20 @@ GATOR_DEFINE_PROBE(sched_process_free, TP_PROTO(struct task_struct *p))
static void do_nothing(void *info)
{
- // Intentionally do nothing
+ /* Intentionally do nothing */
(void)info;
}
static int register_scheduler_tracepoints(void)
{
- // register tracepoints
+ /* register tracepoints */
if (GATOR_REGISTER_TRACE(sched_process_fork))
goto fail_sched_process_fork;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
if (GATOR_REGISTER_TRACE(sched_process_exec))
goto fail_sched_process_exec;
+ if (GATOR_REGISTER_TRACE(task_rename))
+ goto fail_task_rename;
#endif
if (GATOR_REGISTER_TRACE(sched_switch))
goto fail_sched_switch;
@@ -221,21 +240,24 @@ static int register_scheduler_tracepoints(void)
goto fail_sched_process_free;
pr_debug("gator: registered tracepoints\n");
- // Now that the scheduler tracepoint is registered, force a context switch
- // on all cpus to capture what is currently running.
+ /* Now that the scheduler tracepoint is registered, force a context
+ * switch on all cpus to capture what is currently running.
+ */
on_each_cpu(do_nothing, NULL, 0);
return 0;
- // unregister tracepoints on error
+ /* unregister tracepoints on error */
fail_sched_process_free:
GATOR_UNREGISTER_TRACE(sched_switch);
fail_sched_switch:
- GATOR_UNREGISTER_TRACE(sched_process_fork);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
-fail_sched_process_exec:
+ GATOR_UNREGISTER_TRACE(task_rename);
+fail_task_rename:
GATOR_UNREGISTER_TRACE(sched_process_exec);
+fail_sched_process_exec:
#endif
+ GATOR_UNREGISTER_TRACE(sched_process_fork);
fail_sched_process_fork:
pr_err("gator: tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n");
@@ -247,6 +269,7 @@ static void unregister_scheduler_tracepoints(void)
GATOR_UNREGISTER_TRACE(sched_process_fork);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
GATOR_UNREGISTER_TRACE(sched_process_exec);
+ GATOR_UNREGISTER_TRACE(task_rename);
#endif
GATOR_UNREGISTER_TRACE(sched_switch);
GATOR_UNREGISTER_TRACE(sched_process_free);
@@ -271,7 +294,7 @@ static int gator_trace_sched_start(void)
for_each_present_cpu(cpu) {
size = TASK_MAP_ENTRIES * TASK_MAX_COLLISIONS * sizeof(uint64_t);
- per_cpu(taskname_keys, cpu) = (uint64_t *)kmalloc(size, GFP_KERNEL);
+ per_cpu(taskname_keys, cpu) = kmalloc(size, GFP_KERNEL);
if (!per_cpu(taskname_keys, cpu))
return -1;
memset(per_cpu(taskname_keys, cpu), 0, size);
@@ -290,6 +313,7 @@ static void gator_trace_sched_offline(void)
static void gator_trace_sched_init(void)
{
int i;
+
for (i = 0; i < CPU_WAIT_TOTAL; i++) {
cpu_wait_enabled[i] = 0;
sched_cpu_key[i] = gator_events_get_key();
diff --git a/drivers/gator/mali/mali_dd_gator_api.h b/drivers/gator/mali/mali_dd_gator_api.h
deleted file mode 100644
index 104b34f..0000000
--- a/drivers/gator/mali/mali_dd_gator_api.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#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/mali_kbase_gator_api.h b/drivers/gator/mali/mali_kbase_gator_api.h
new file mode 100644
index 0000000..5ed0697
--- /dev/null
+++ b/drivers/gator/mali/mali_kbase_gator_api.h
@@ -0,0 +1,219 @@
+/**
+ * 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 _KBASE_GATOR_API_H_
+#define _KBASE_GATOR_API_H_
+
+/**
+ * @brief This file describes the API used by Gator to collect hardware counters data from a Mali device.
+ */
+
+/* This define is used by the gator kernel module compile to select which DDK
+ * API calling convention to use. If not defined (legacy DDK) gator assumes
+ * version 1. The version to DDK release mapping is:
+ * Version 1 API: DDK versions r1px, r2px
+ * Version 2 API: DDK versions r3px, r4px
+ * Version 3 API: DDK version r5p0 and newer
+ *
+ * API Usage
+ * =========
+ *
+ * 1] Call kbase_gator_hwcnt_init_names() to return the list of short counter
+ * names for the GPU present in this device.
+ *
+ * 2] Create a kbase_gator_hwcnt_info structure and set the counter enables for
+ * the counters you want enabled. The enables can all be set for simplicity in
+ * most use cases, but disabling some will let you minimize bandwidth impact.
+ *
+ * 3] Call kbase_gator_hwcnt_init() using the above structure, to create a
+ * counter context. On successful return the DDK will have populated the
+ * structure with a variety of useful information.
+ *
+ * 4] Call kbase_gator_hwcnt_dump_irq() to queue a non-blocking request for a
+ * counter dump. If this returns a non-zero value the request has been queued,
+ * otherwise the driver has been unable to do so (typically because of another
+ * user of the instrumentation exists concurrently).
+ *
+ * 5] Call kbase_gator_hwcnt_dump_complete() to test whether the previously
+ * requested dump has been succesful. If this returns non-zero the counter dump
+ * has resolved, but the value of *success must also be tested as the dump
+ * may have not been successful. If it returns zero the counter dump was
+ * abandoned due to the device being busy (typically because of another
+ * user of the instrumentation exists concurrently).
+ *
+ * 6] Process the counters stored in the buffer pointed to by ...
+ *
+ * kbase_gator_hwcnt_info->kernel_dump_buffer
+ *
+ * In pseudo code you can find all of the counters via this approach:
+ *
+ *
+ * hwcnt_info # pointer to kbase_gator_hwcnt_info structure
+ * hwcnt_name # pointer to name list
+ *
+ * u32 * hwcnt_data = (u32*)hwcnt_info->kernel_dump_buffer
+ *
+ * # Iterate over each 64-counter block in this GPU configuration
+ * for( i = 0; i < hwcnt_info->nr_hwc_blocks; i++) {
+ * hwc_type type = hwcnt_info->hwc_layout[i];
+ *
+ * # Skip reserved type blocks - they contain no counters at all
+ * if( type == RESERVED_BLOCK ) {
+ * continue;
+ * }
+ *
+ * size_t name_offset = type * 64;
+ * size_t data_offset = i * 64;
+ *
+ * # Iterate over the names of the counters in this block type
+ * for( j = 0; j < 64; j++) {
+ * const char * name = hwcnt_name[name_offset+j];
+ *
+ * # Skip empty name strings - there is no counter here
+ * if( name[0] == '\0' ) {
+ * continue;
+ * }
+ *
+ * u32 data = hwcnt_data[data_offset+j];
+ *
+ * printk( "COUNTER: %s DATA: %u\n", name, data );
+ * }
+ * }
+ *
+ *
+ * Note that in most implementations you typically want to either SUM or
+ * AVERAGE multiple instances of the same counter if, for example, you have
+ * multiple shader cores or multiple L2 caches. The most sensible view for
+ * analysis is to AVERAGE shader core counters, but SUM L2 cache and MMU
+ * counters.
+ *
+ * 7] Goto 4, repeating until you want to stop collecting counters.
+ *
+ * 8] Release the dump resources by calling kbase_gator_hwcnt_term().
+ *
+ * 9] Release the name table resources by calling kbase_gator_hwcnt_term_names().
+ * This function must only be called if init_names() returned a non-NULL value.
+ **/
+
+#define MALI_DDK_GATOR_API_VERSION 3
+
+#if !defined(MALI_TRUE)
+ #define MALI_TRUE ((uint32_t)1)
+#endif
+
+#if !defined(MALI_FALSE)
+ #define MALI_FALSE ((uint32_t)0)
+#endif
+
+enum hwc_type {
+ JM_BLOCK = 0,
+ TILER_BLOCK,
+ SHADER_BLOCK,
+ MMU_L2_BLOCK,
+ RESERVED_BLOCK
+};
+
+struct kbase_gator_hwcnt_info {
+
+ /* Passed from Gator to kbase */
+
+ /* the bitmask of enabled hardware counters for each counter block */
+ uint16_t bitmask[4];
+
+ /* Passed from kbase to Gator */
+
+ /* ptr to counter dump memory */
+ void *kernel_dump_buffer;
+
+ /* size of counter dump memory */
+ uint32_t size;
+
+ /* the ID of the Mali device */
+ uint32_t gpu_id;
+
+ /* the number of shader cores in the GPU */
+ uint32_t nr_cores;
+
+ /* the number of core groups */
+ uint32_t nr_core_groups;
+
+ /* the memory layout of the performance counters */
+ enum hwc_type *hwc_layout;
+
+ /* the total number of hardware couter blocks */
+ uint32_t nr_hwc_blocks;
+};
+
+/**
+ * @brief Opaque block of Mali data which Gator needs to return to the API later.
+ */
+struct kbase_gator_hwcnt_handles;
+
+/**
+ * @brief Initialize the resources Gator needs for performance profiling.
+ *
+ * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the Mali
+ * specific information that will be returned to Gator. On entry Gator must have populated the
+ * 'bitmask' field with the counters it wishes to enable for each class of counter block.
+ * Each entry in the array corresponds to a single counter class based on the "hwc_type"
+ * enumeration, and each bit corresponds to an enable for 4 sequential counters (LSB enables
+ * the first 4 counters in the block, and so on). See the GPU counter array as returned by
+ * kbase_gator_hwcnt_get_names() for the index values of each counter for the curernt GPU.
+ *
+ * @return Pointer to an opaque handle block on success, NULL on error.
+ */
+extern struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info);
+
+/**
+ * @brief Free all resources once Gator has finished using performance counters.
+ *
+ * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the
+ * Mali specific information that will be returned to Gator.
+ * @param opaque_handles A wrapper structure for kbase structures.
+ */
+extern void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles);
+
+/**
+ * @brief Poll whether a counter dump is successful.
+ *
+ * @param opaque_handles A wrapper structure for kbase structures.
+ * @param[out] success Non-zero on success, zero on failure.
+ *
+ * @return Zero if the dump is still pending, non-zero if the dump has completed. Note that a
+ * completed dump may not have dumped succesfully, so the caller must test for both
+ * a completed and successful dump before processing counters.
+ */
+extern uint32_t kbase_gator_instr_hwcnt_dump_complete(struct kbase_gator_hwcnt_handles *opaque_handles, uint32_t * const success);
+
+/**
+ * @brief Request the generation of a new counter dump.
+ *
+ * @param opaque_handles A wrapper structure for kbase structures.
+ *
+ * @return Zero if the hardware device is busy and cannot handle the request, non-zero otherwise.
+ */
+extern uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles);
+
+/**
+ * @brief This function is used to fetch the names table based on the Mali device in use.
+ *
+ * @param[out] total_number_of_counters The total number of counters short names in the Mali devices' list.
+ *
+ * @return Pointer to an array of strings of length *total_number_of_counters.
+ */
+extern const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_number_of_counters);
+
+/**
+ * @brief This function is used to terminate the use of the names table.
+ *
+ * This function must only be called if the initial call to kbase_gator_hwcnt_init_names returned a non-NULL value.
+ */
+extern void kbase_gator_hwcnt_term_names(void);
+
+#endif
diff --git a/drivers/gator/mali/mali_mjollnir_profiling_gator_api.h b/drivers/gator/mali/mali_mjollnir_profiling_gator_api.h
index ff00d90..2bc0b03 100644
--- a/drivers/gator/mali/mali_mjollnir_profiling_gator_api.h
+++ b/drivers/gator/mali/mali_mjollnir_profiling_gator_api.h
@@ -23,83 +23,82 @@ extern "C"
#define MAX_NUM_VP_CORES (1)
#define MAX_NUM_L2_CACHE_CORES (1)
-enum counters
-{
- /* Timeline activity */
- ACTIVITY_VP_0 = 0,
- ACTIVITY_FP_0,
- ACTIVITY_FP_1,
- ACTIVITY_FP_2,
- ACTIVITY_FP_3,
-
- /* L2 cache counters */
- COUNTER_L2_0_C0,
- COUNTER_L2_0_C1,
-
- /* Vertex processor counters */
- COUNTER_VP_0_C0,
- COUNTER_VP_0_C1,
-
- /* Fragment processor counters */
- COUNTER_FP_0_C0,
- COUNTER_FP_0_C1,
- COUNTER_FP_1_C0,
- COUNTER_FP_1_C1,
- COUNTER_FP_2_C0,
- COUNTER_FP_2_C1,
- COUNTER_FP_3_C0,
- COUNTER_FP_3_C1,
-
- /* EGL Software Counters */
- COUNTER_EGL_BLIT_TIME,
-
- /* GLES Software Counters */
- COUNTER_GLES_DRAW_ELEMENTS_CALLS,
- COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES,
- COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED,
- COUNTER_GLES_DRAW_ARRAYS_CALLS,
- COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED,
- COUNTER_GLES_DRAW_POINTS,
- COUNTER_GLES_DRAW_LINES,
- COUNTER_GLES_DRAW_LINE_LOOP,
- COUNTER_GLES_DRAW_LINE_STRIP,
- COUNTER_GLES_DRAW_TRIANGLES,
- COUNTER_GLES_DRAW_TRIANGLE_STRIP,
- COUNTER_GLES_DRAW_TRIANGLE_FAN,
- COUNTER_GLES_NON_VBO_DATA_COPY_TIME,
- COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI,
- COUNTER_GLES_UPLOAD_TEXTURE_TIME,
- COUNTER_GLES_UPLOAD_VBO_TIME,
- COUNTER_GLES_NUM_FLUSHES,
- COUNTER_GLES_NUM_VSHADERS_GENERATED,
- COUNTER_GLES_NUM_FSHADERS_GENERATED,
- COUNTER_GLES_VSHADER_GEN_TIME,
- COUNTER_GLES_FSHADER_GEN_TIME,
- COUNTER_GLES_INPUT_TRIANGLES,
- COUNTER_GLES_VXCACHE_HIT,
- COUNTER_GLES_VXCACHE_MISS,
- COUNTER_GLES_VXCACHE_COLLISION,
- COUNTER_GLES_CULLED_TRIANGLES,
- COUNTER_GLES_CULLED_LINES,
- COUNTER_GLES_BACKFACE_TRIANGLES,
- COUNTER_GLES_GBCLIP_TRIANGLES,
- COUNTER_GLES_GBCLIP_LINES,
- COUNTER_GLES_TRIANGLES_DRAWN,
- COUNTER_GLES_DRAWCALL_TIME,
- COUNTER_GLES_TRIANGLES_COUNT,
- COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT,
- COUNTER_GLES_STRIP_TRIANGLES_COUNT,
- COUNTER_GLES_FAN_TRIANGLES_COUNT,
- COUNTER_GLES_LINES_COUNT,
- COUNTER_GLES_INDEPENDENT_LINES_COUNT,
- COUNTER_GLES_STRIP_LINES_COUNT,
- COUNTER_GLES_LOOP_LINES_COUNT,
-
- COUNTER_FILMSTRIP,
- COUNTER_FREQUENCY,
- COUNTER_VOLTAGE,
-
- NUMBER_OF_EVENTS
+enum counters {
+ /* Timeline activity */
+ ACTIVITY_VP_0 = 0,
+ ACTIVITY_FP_0,
+ ACTIVITY_FP_1,
+ ACTIVITY_FP_2,
+ ACTIVITY_FP_3,
+
+ /* L2 cache counters */
+ COUNTER_L2_0_C0,
+ COUNTER_L2_0_C1,
+
+ /* Vertex processor counters */
+ COUNTER_VP_0_C0,
+ COUNTER_VP_0_C1,
+
+ /* Fragment processor counters */
+ COUNTER_FP_0_C0,
+ COUNTER_FP_0_C1,
+ COUNTER_FP_1_C0,
+ COUNTER_FP_1_C1,
+ COUNTER_FP_2_C0,
+ COUNTER_FP_2_C1,
+ COUNTER_FP_3_C0,
+ COUNTER_FP_3_C1,
+
+ /* EGL Software Counters */
+ COUNTER_EGL_BLIT_TIME,
+
+ /* GLES Software Counters */
+ COUNTER_GLES_DRAW_ELEMENTS_CALLS,
+ COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES,
+ COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED,
+ COUNTER_GLES_DRAW_ARRAYS_CALLS,
+ COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED,
+ COUNTER_GLES_DRAW_POINTS,
+ COUNTER_GLES_DRAW_LINES,
+ COUNTER_GLES_DRAW_LINE_LOOP,
+ COUNTER_GLES_DRAW_LINE_STRIP,
+ COUNTER_GLES_DRAW_TRIANGLES,
+ COUNTER_GLES_DRAW_TRIANGLE_STRIP,
+ COUNTER_GLES_DRAW_TRIANGLE_FAN,
+ COUNTER_GLES_NON_VBO_DATA_COPY_TIME,
+ COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI,
+ COUNTER_GLES_UPLOAD_TEXTURE_TIME,
+ COUNTER_GLES_UPLOAD_VBO_TIME,
+ COUNTER_GLES_NUM_FLUSHES,
+ COUNTER_GLES_NUM_VSHADERS_GENERATED,
+ COUNTER_GLES_NUM_FSHADERS_GENERATED,
+ COUNTER_GLES_VSHADER_GEN_TIME,
+ COUNTER_GLES_FSHADER_GEN_TIME,
+ COUNTER_GLES_INPUT_TRIANGLES,
+ COUNTER_GLES_VXCACHE_HIT,
+ COUNTER_GLES_VXCACHE_MISS,
+ COUNTER_GLES_VXCACHE_COLLISION,
+ COUNTER_GLES_CULLED_TRIANGLES,
+ COUNTER_GLES_CULLED_LINES,
+ COUNTER_GLES_BACKFACE_TRIANGLES,
+ COUNTER_GLES_GBCLIP_TRIANGLES,
+ COUNTER_GLES_GBCLIP_LINES,
+ COUNTER_GLES_TRIANGLES_DRAWN,
+ COUNTER_GLES_DRAWCALL_TIME,
+ COUNTER_GLES_TRIANGLES_COUNT,
+ COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT,
+ COUNTER_GLES_STRIP_TRIANGLES_COUNT,
+ COUNTER_GLES_FAN_TRIANGLES_COUNT,
+ COUNTER_GLES_LINES_COUNT,
+ COUNTER_GLES_INDEPENDENT_LINES_COUNT,
+ COUNTER_GLES_STRIP_LINES_COUNT,
+ COUNTER_GLES_LOOP_LINES_COUNT,
+
+ COUNTER_FILMSTRIP,
+ COUNTER_FREQUENCY,
+ COUNTER_VOLTAGE,
+
+ NUMBER_OF_EVENTS
};
#define FIRST_ACTIVITY_EVENT ACTIVITY_VP_0
@@ -117,34 +116,31 @@ enum counters
/**
* Structure to pass performance counter data of a Mali core
*/
-typedef struct _mali_profiling_core_counters
-{
- u32 source0;
- u32 value0;
- u32 source1;
- u32 value1;
-} _mali_profiling_core_counters;
+struct _mali_profiling_core_counters {
+ u32 source0;
+ u32 value0;
+ u32 source1;
+ u32 value1;
+};
/*
* For compatibility with utgard.
*/
-typedef struct _mali_profiling_l2_counter_values
-{
- struct _mali_profiling_core_counters cores[MAX_NUM_L2_CACHE_CORES];
-} _mali_profiling_l2_counter_values;
+struct _mali_profiling_l2_counter_values {
+ struct _mali_profiling_core_counters cores[MAX_NUM_L2_CACHE_CORES];
+};
-typedef struct _mali_profiling_mali_version
-{
- u32 mali_product_id;
- u32 mali_version_major;
- u32 mali_version_minor;
- u32 num_of_l2_cores;
- u32 num_of_fp_cores;
- u32 num_of_vp_cores;
-} _mali_profiling_mali_version;
+struct _mali_profiling_mali_version {
+ u32 mali_product_id;
+ u32 mali_version_major;
+ u32 mali_version_minor;
+ u32 num_of_l2_cores;
+ u32 num_of_fp_cores;
+ u32 num_of_vp_cores;
+};
extern void _mali_profiling_get_mali_version(struct _mali_profiling_mali_version *values);
-extern u32 _mali_profiling_get_l2_counters(_mali_profiling_l2_counter_values *values);
+extern u32 _mali_profiling_get_l2_counters(struct _mali_profiling_l2_counter_values *values);
/*
* List of possible actions allowing DDK to be controlled by Streamline.
diff --git a/drivers/gator/mali/mali_utgard_profiling_gator_api.h b/drivers/gator/mali/mali_utgard_profiling_gator_api.h
index 43c5760..d646531 100644
--- a/drivers/gator/mali/mali_utgard_profiling_gator_api.h
+++ b/drivers/gator/mali/mali_utgard_profiling_gator_api.h
@@ -22,105 +22,104 @@ extern "C"
#define MAX_NUM_VP_CORES 1
/** The list of events supported by the Mali DDK. */
-typedef enum
-{
- /* Vertex processor activity */
- ACTIVITY_VP_0 = 0,
-
- /* Fragment processor activity */
- ACTIVITY_FP_0, /* 1 */
- ACTIVITY_FP_1,
- ACTIVITY_FP_2,
- ACTIVITY_FP_3,
- ACTIVITY_FP_4,
- ACTIVITY_FP_5,
- ACTIVITY_FP_6,
- ACTIVITY_FP_7,
-
- /* L2 cache counters */
- COUNTER_L2_0_C0,
- COUNTER_L2_0_C1,
- COUNTER_L2_1_C0,
- COUNTER_L2_1_C1,
- COUNTER_L2_2_C0,
- COUNTER_L2_2_C1,
-
- /* Vertex processor counters */
- COUNTER_VP_0_C0, /*15*/
- COUNTER_VP_0_C1,
-
- /* Fragment processor counters */
- COUNTER_FP_0_C0,
- COUNTER_FP_0_C1,
- COUNTER_FP_1_C0,
- COUNTER_FP_1_C1,
- COUNTER_FP_2_C0,
- COUNTER_FP_2_C1,
- COUNTER_FP_3_C0,
- COUNTER_FP_3_C1,
- COUNTER_FP_4_C0,
- COUNTER_FP_4_C1,
- COUNTER_FP_5_C0,
- COUNTER_FP_5_C1,
- COUNTER_FP_6_C0,
- COUNTER_FP_6_C1,
- COUNTER_FP_7_C0,
- COUNTER_FP_7_C1, /* 32 */
-
- /*
- * If more hardware counters are added, the _mali_osk_hw_counter_table
- * below should also be updated.
- */
-
- /* EGL software counters */
- COUNTER_EGL_BLIT_TIME,
-
- /* GLES software counters */
- COUNTER_GLES_DRAW_ELEMENTS_CALLS,
- COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES,
- COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED,
- COUNTER_GLES_DRAW_ARRAYS_CALLS,
- COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED,
- COUNTER_GLES_DRAW_POINTS,
- COUNTER_GLES_DRAW_LINES,
- COUNTER_GLES_DRAW_LINE_LOOP,
- COUNTER_GLES_DRAW_LINE_STRIP,
- COUNTER_GLES_DRAW_TRIANGLES,
- COUNTER_GLES_DRAW_TRIANGLE_STRIP,
- COUNTER_GLES_DRAW_TRIANGLE_FAN,
- COUNTER_GLES_NON_VBO_DATA_COPY_TIME,
- COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI,
- COUNTER_GLES_UPLOAD_TEXTURE_TIME,
- COUNTER_GLES_UPLOAD_VBO_TIME,
- COUNTER_GLES_NUM_FLUSHES,
- COUNTER_GLES_NUM_VSHADERS_GENERATED,
- COUNTER_GLES_NUM_FSHADERS_GENERATED,
- COUNTER_GLES_VSHADER_GEN_TIME,
- COUNTER_GLES_FSHADER_GEN_TIME,
- COUNTER_GLES_INPUT_TRIANGLES,
- COUNTER_GLES_VXCACHE_HIT,
- COUNTER_GLES_VXCACHE_MISS,
- COUNTER_GLES_VXCACHE_COLLISION,
- COUNTER_GLES_CULLED_TRIANGLES,
- COUNTER_GLES_CULLED_LINES,
- COUNTER_GLES_BACKFACE_TRIANGLES,
- COUNTER_GLES_GBCLIP_TRIANGLES,
- COUNTER_GLES_GBCLIP_LINES,
- COUNTER_GLES_TRIANGLES_DRAWN,
- COUNTER_GLES_DRAWCALL_TIME,
- COUNTER_GLES_TRIANGLES_COUNT,
- COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT,
- COUNTER_GLES_STRIP_TRIANGLES_COUNT,
- COUNTER_GLES_FAN_TRIANGLES_COUNT,
- COUNTER_GLES_LINES_COUNT,
- COUNTER_GLES_INDEPENDENT_LINES_COUNT,
- COUNTER_GLES_STRIP_LINES_COUNT,
- COUNTER_GLES_LOOP_LINES_COUNT,
-
- /* Framebuffer capture pseudo-counter */
- COUNTER_FILMSTRIP,
-
- NUMBER_OF_EVENTS
+enum {
+ /* Vertex processor activity */
+ ACTIVITY_VP_0 = 0,
+
+ /* Fragment processor activity */
+ ACTIVITY_FP_0, /* 1 */
+ ACTIVITY_FP_1,
+ ACTIVITY_FP_2,
+ ACTIVITY_FP_3,
+ ACTIVITY_FP_4,
+ ACTIVITY_FP_5,
+ ACTIVITY_FP_6,
+ ACTIVITY_FP_7,
+
+ /* L2 cache counters */
+ COUNTER_L2_0_C0,
+ COUNTER_L2_0_C1,
+ COUNTER_L2_1_C0,
+ COUNTER_L2_1_C1,
+ COUNTER_L2_2_C0,
+ COUNTER_L2_2_C1,
+
+ /* Vertex processor counters */
+ COUNTER_VP_0_C0, /*15*/
+ COUNTER_VP_0_C1,
+
+ /* Fragment processor counters */
+ COUNTER_FP_0_C0,
+ COUNTER_FP_0_C1,
+ COUNTER_FP_1_C0,
+ COUNTER_FP_1_C1,
+ COUNTER_FP_2_C0,
+ COUNTER_FP_2_C1,
+ COUNTER_FP_3_C0,
+ COUNTER_FP_3_C1,
+ COUNTER_FP_4_C0,
+ COUNTER_FP_4_C1,
+ COUNTER_FP_5_C0,
+ COUNTER_FP_5_C1,
+ COUNTER_FP_6_C0,
+ COUNTER_FP_6_C1,
+ COUNTER_FP_7_C0,
+ COUNTER_FP_7_C1, /* 32 */
+
+ /*
+ * If more hardware counters are added, the _mali_osk_hw_counter_table
+ * below should also be updated.
+ */
+
+ /* EGL software counters */
+ COUNTER_EGL_BLIT_TIME,
+
+ /* GLES software counters */
+ COUNTER_GLES_DRAW_ELEMENTS_CALLS,
+ COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES,
+ COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED,
+ COUNTER_GLES_DRAW_ARRAYS_CALLS,
+ COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED,
+ COUNTER_GLES_DRAW_POINTS,
+ COUNTER_GLES_DRAW_LINES,
+ COUNTER_GLES_DRAW_LINE_LOOP,
+ COUNTER_GLES_DRAW_LINE_STRIP,
+ COUNTER_GLES_DRAW_TRIANGLES,
+ COUNTER_GLES_DRAW_TRIANGLE_STRIP,
+ COUNTER_GLES_DRAW_TRIANGLE_FAN,
+ COUNTER_GLES_NON_VBO_DATA_COPY_TIME,
+ COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI,
+ COUNTER_GLES_UPLOAD_TEXTURE_TIME,
+ COUNTER_GLES_UPLOAD_VBO_TIME,
+ COUNTER_GLES_NUM_FLUSHES,
+ COUNTER_GLES_NUM_VSHADERS_GENERATED,
+ COUNTER_GLES_NUM_FSHADERS_GENERATED,
+ COUNTER_GLES_VSHADER_GEN_TIME,
+ COUNTER_GLES_FSHADER_GEN_TIME,
+ COUNTER_GLES_INPUT_TRIANGLES,
+ COUNTER_GLES_VXCACHE_HIT,
+ COUNTER_GLES_VXCACHE_MISS,
+ COUNTER_GLES_VXCACHE_COLLISION,
+ COUNTER_GLES_CULLED_TRIANGLES,
+ COUNTER_GLES_CULLED_LINES,
+ COUNTER_GLES_BACKFACE_TRIANGLES,
+ COUNTER_GLES_GBCLIP_TRIANGLES,
+ COUNTER_GLES_GBCLIP_LINES,
+ COUNTER_GLES_TRIANGLES_DRAWN,
+ COUNTER_GLES_DRAWCALL_TIME,
+ COUNTER_GLES_TRIANGLES_COUNT,
+ COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT,
+ COUNTER_GLES_STRIP_TRIANGLES_COUNT,
+ COUNTER_GLES_FAN_TRIANGLES_COUNT,
+ COUNTER_GLES_LINES_COUNT,
+ COUNTER_GLES_INDEPENDENT_LINES_COUNT,
+ COUNTER_GLES_STRIP_LINES_COUNT,
+ COUNTER_GLES_LOOP_LINES_COUNT,
+
+ /* Framebuffer capture pseudo-counter */
+ COUNTER_FILMSTRIP,
+
+ NUMBER_OF_EVENTS
} _mali_osk_counter_id;
#define FIRST_ACTIVITY_EVENT ACTIVITY_VP_0
@@ -138,21 +137,19 @@ typedef enum
/**
* Structure to pass performance counter data of a Mali core
*/
-typedef struct _mali_profiling_core_counters
-{
+struct _mali_profiling_core_counters {
u32 source0;
u32 value0;
u32 source1;
u32 value1;
-} _mali_profiling_core_counters;
+};
/**
* Structure to pass performance counter data of Mali L2 cache cores
*/
-typedef struct _mali_profiling_l2_counter_values
-{
+struct _mali_profiling_l2_counter_values {
struct _mali_profiling_core_counters cores[MAX_NUM_L2_CACHE_CORES];
-} _mali_profiling_l2_counter_values;
+};
/**
* Structure to pass data defining Mali instance in use:
@@ -164,15 +161,14 @@ typedef struct _mali_profiling_l2_counter_values
* num_of_fp_cores - number of fragment processor cores
* num_of_vp_cores - number of vertex processor cores
*/
-typedef struct _mali_profiling_mali_version
-{
+struct _mali_profiling_mali_version {
u32 mali_product_id;
u32 mali_version_major;
u32 mali_version_minor;
u32 num_of_l2_cores;
u32 num_of_fp_cores;
u32 num_of_vp_cores;
-} _mali_profiling_mali_version;
+};
/*
* List of possible actions to be controlled by Streamline.
@@ -186,7 +182,7 @@ typedef struct _mali_profiling_mali_version
void _mali_profiling_control(u32 action, u32 value);
-u32 _mali_profiling_get_l2_counters(_mali_profiling_l2_counter_values *values);
+u32 _mali_profiling_get_l2_counters(struct _mali_profiling_l2_counter_values *values);
int _mali_profiling_set_event(u32 counter_id, s32 event_id);
diff --git a/drivers/gator/mali_t6xx.mk b/drivers/gator/mali_midgard.mk
index fa7571d..1b784d5 100644
--- a/drivers/gator/mali_t6xx.mk
+++ b/drivers/gator/mali_midgard.mk
@@ -1,4 +1,4 @@
-# Defines for Mali-T6xx driver
+# Defines for Mali-Midgard driver
EXTRA_CFLAGS += -DMALI_USE_UMP=1 \
-DMALI_LICENSE_IS_GPL=1 \
-DMALI_BASE_TRACK_MEMLEAK=0 \
@@ -21,7 +21,7 @@ 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),)
+ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/midgard/mali_kbase_gator_api.h),)
EXTRA_CFLAGS += -DMALI_SIMPLE_API=1
endif
diff --git a/tools/gator/daemon/Android.mk b/tools/gator/daemon/Android.mk
index 44c069c..970ac69 100644
--- a/tools/gator/daemon/Android.mk
+++ b/tools/gator/daemon/Android.mk
@@ -3,13 +3,16 @@ include $(CLEAR_VARS)
XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h)
-LOCAL_CFLAGS += -Wall -O3 -mthumb-interwork -fno-exceptions -pthread -DETCDIR=\"/etc\" -Ilibsensors
-
LOCAL_SRC_FILES := \
+ AnnotateListener.cpp \
Buffer.cpp \
+ CCNDriver.cpp \
+ CPUFreqDriver.cpp \
CapturedXML.cpp \
Child.cpp \
+ Command.cpp \
ConfigurationXML.cpp \
+ DiskIODriver.cpp \
Driver.cpp \
DriverSource.cpp \
DynBuf.cpp \
@@ -17,13 +20,17 @@ LOCAL_SRC_FILES := \
ExternalSource.cpp \
FSDriver.cpp \
Fifo.cpp \
- Hwmon.cpp \
+ FtraceDriver.cpp \
+ FtraceSource.cpp \
+ HwmonDriver.cpp \
KMod.cpp \
LocalCapture.cpp \
Logging.cpp \
main.cpp \
MaliVideoDriver.cpp \
+ MemInfoDriver.cpp\
Monitor.cpp \
+ NetDriver.cpp \
OlySocket.cpp \
OlyUtility.cpp \
PerfBuffer.cpp \
@@ -34,6 +41,7 @@ LOCAL_SRC_FILES := \
Sender.cpp \
SessionData.cpp \
SessionXML.cpp \
+ Setup.cpp \
Source.cpp \
StreamlineSetup.cpp \
UEvent.cpp \
@@ -57,6 +65,9 @@ LOCAL_SRC_FILES := \
mxml/mxml-set.c \
mxml/mxml-string.c
+LOCAL_CFLAGS += -Wall -O3 -fno-exceptions -pthread -DETCDIR=\"/etc\" -Ilibsensors -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_MODULE := gatord
diff --git a/tools/gator/daemon/AnnotateListener.cpp b/tools/gator/daemon/AnnotateListener.cpp
new file mode 100644
index 0000000..50110b4
--- /dev/null
+++ b/tools/gator/daemon/AnnotateListener.cpp
@@ -0,0 +1,69 @@
+/**
+ * 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 "AnnotateListener.h"
+
+#include <unistd.h>
+
+#include "OlySocket.h"
+
+struct AnnotateClient {
+ AnnotateClient *next;
+ int fd;
+};
+
+AnnotateListener::AnnotateListener() : mClients(NULL), mSock(NULL) {
+}
+
+AnnotateListener::~AnnotateListener() {
+ close();
+ delete mSock;
+}
+
+void AnnotateListener::setup() {
+ mSock = new OlyServerSocket(8082);
+}
+
+int AnnotateListener::getFd() {
+ return mSock->getFd();
+}
+
+void AnnotateListener::handle() {
+ AnnotateClient *const client = new AnnotateClient();
+ client->fd = mSock->acceptConnection();
+ client->next = mClients;
+ mClients = client;
+}
+
+void AnnotateListener::close() {
+ mSock->closeServerSocket();
+ while (mClients != NULL) {
+ ::close(mClients->fd);
+ AnnotateClient *next = mClients->next;
+ delete mClients;
+ mClients = next;
+ }
+}
+
+void AnnotateListener::signal() {
+ const char ch = 0;
+ AnnotateClient **ptr = &mClients;
+ AnnotateClient *client = mClients;
+ while (client != NULL) {
+ if (write(client->fd, &ch, sizeof(ch)) != 1) {
+ ::close(client->fd);
+ AnnotateClient *next = client->next;
+ delete client;
+ *ptr = next;
+ client = next;
+ continue;
+ }
+ ptr = &client->next;
+ client = client->next;
+ }
+}
diff --git a/tools/gator/daemon/AnnotateListener.h b/tools/gator/daemon/AnnotateListener.h
new file mode 100644
index 0000000..cdefef1
--- /dev/null
+++ b/tools/gator/daemon/AnnotateListener.h
@@ -0,0 +1,31 @@
+/**
+ * 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.
+ */
+
+class AnnotateClient;
+class OlyServerSocket;
+
+class AnnotateListener {
+public:
+ AnnotateListener();
+ ~AnnotateListener();
+
+ void setup();
+ int getFd();
+
+ void handle();
+ void close();
+ void signal();
+
+private:
+ AnnotateClient *mClients;
+ OlyServerSocket *mSock;
+
+ // Intentionally unimplemented
+ AnnotateListener(const AnnotateListener &);
+ AnnotateListener &operator=(const AnnotateListener &);
+};
diff --git a/tools/gator/daemon/Application.mk b/tools/gator/daemon/Application.mk
index 631ba54..3ada471 100644
--- a/tools/gator/daemon/Application.mk
+++ b/tools/gator/daemon/Application.mk
@@ -1 +1,3 @@
APP_PLATFORM := android-8
+# Replace armeabi-v7a with arm64-v8a to build an arm64 gatord or with armeabi to build an ARM11 gatord
+APP_ABI := armeabi-v7a
diff --git a/tools/gator/daemon/Buffer.cpp b/tools/gator/daemon/Buffer.cpp
index dd19f7f..8fa6280 100644
--- a/tools/gator/daemon/Buffer.cpp
+++ b/tools/gator/daemon/Buffer.cpp
@@ -15,12 +15,15 @@
#define mask (mSize - 1)
enum {
- CODE_PEA = 1,
- CODE_KEYS = 2,
- CODE_FORMAT = 3,
- CODE_MAPS = 4,
- CODE_COMM = 5,
- CODE_KEYS_OLD = 6,
+ CODE_PEA = 1,
+ CODE_KEYS = 2,
+ CODE_FORMAT = 3,
+ CODE_MAPS = 4,
+ CODE_COMM = 5,
+ CODE_KEYS_OLD = 6,
+ CODE_ONLINE_CPU = 7,
+ CODE_OFFLINE_CPU = 8,
+ CODE_KALLSYMS = 9,
};
// Summary Frame Messages
@@ -42,16 +45,18 @@ enum {
/* Add another character so the length isn't 0x0a bytes */ \
"5"
-Buffer::Buffer(const int32_t core, const int32_t buftype, const int size, sem_t *const readerSem) : mCore(core), mBufType(buftype), mSize(size), mReadPos(0), mWritePos(0), mCommitPos(0), mAvailable(true), mIsDone(false), mBuf(new char[mSize]), mCommitTime(gSessionData->mLiveRate), mReaderSem(readerSem) {
+Buffer::Buffer(const int32_t core, const int32_t buftype, const int size, sem_t *const readerSem) : mBuf(new char[size]), mReaderSem(readerSem), mCommitTime(gSessionData->mLiveRate), mSize(size), mReadPos(0), mWritePos(0), mCommitPos(0), mAvailable(true), mIsDone(false), mCore(core), mBufType(buftype) {
if ((mSize & mask) != 0) {
logg->logError(__FILE__, __LINE__, "Buffer size is not a power of 2");
handleException();
}
+ sem_init(&mWriterSem, 0, 0);
frame();
}
Buffer::~Buffer() {
delete [] mBuf;
+ sem_destroy(&mWriterSem);
}
void Buffer::write(Sender *const sender) {
@@ -59,14 +64,18 @@ void Buffer::write(Sender *const sender) {
return;
}
+ // commit and read are updated by the writer, only read them once
+ int commitPos = mCommitPos;
+ int readPos = mReadPos;
+
// determine the size of two halves
- int length1 = mCommitPos - mReadPos;
- char *buffer1 = mBuf + mReadPos;
+ int length1 = commitPos - readPos;
+ char *buffer1 = mBuf + readPos;
int length2 = 0;
char *buffer2 = mBuf;
if (length1 < 0) {
- length1 = mSize - mReadPos;
- length2 = mCommitPos;
+ length1 = mSize - readPos;
+ length2 = commitPos;
}
logg->logMessage("Sending data length1: %i length2: %i", length1, length2);
@@ -81,7 +90,10 @@ void Buffer::write(Sender *const sender) {
sender->writeData(buffer2, length2, RESPONSE_APC_DATA);
}
- mReadPos = mCommitPos;
+ mReadPos = commitPos;
+
+ // send a notification that space is available
+ sem_post(&mWriterSem);
}
bool Buffer::commitReady() const {
@@ -193,7 +205,7 @@ void Buffer::packInt(int32_t x) {
packInt(mBuf, mSize, mWritePos, x);
}
-void Buffer::packInt64(int64_t x) {
+void Buffer::packInt64(char *const buf, const int size, int &writePos, int64_t x) {
int packedBytes = 0;
int more = true;
while (more) {
@@ -207,11 +219,15 @@ void Buffer::packInt64(int64_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::packInt64(int64_t x) {
+ packInt64(mBuf, mSize, mWritePos, x);
}
void Buffer::writeBytes(const void *const data, size_t count) {
@@ -236,10 +252,12 @@ void Buffer::frame() {
// Reserve space for the length
mWritePos += sizeof(int32_t);
packInt(mBufType);
- packInt(mCore);
+ if ((mBufType == FRAME_BLOCK_COUNTER) || (mBufType == FRAME_PERF_ATTRS) || (mBufType == FRAME_PERF)) {
+ packInt(mCore);
+ }
}
-void Buffer::summary(const int64_t timestamp, const int64_t uptime, const int64_t monotonicDelta, const char *const uname) {
+void Buffer::summary(const uint64_t currTime, const int64_t timestamp, const int64_t uptime, const int64_t monotonicDelta, const char *const uname) {
packInt(MESSAGE_SUMMARY);
writeString(NEWLINE_CANARY);
packInt64(timestamp);
@@ -248,23 +266,24 @@ void Buffer::summary(const int64_t timestamp, const int64_t uptime, const int64_
writeString("uname");
writeString(uname);
writeString("");
- check(1);
+ check(currTime);
}
-void Buffer::coreName(const int core, const int cpuid, const char *const name) {
+void Buffer::coreName(const uint64_t currTime, const int core, const int cpuid, const char *const name) {
if (checkSpace(3 * MAXSIZE_PACK32 + 0x100)) {
packInt(MESSAGE_CORE_NAME);
packInt(core);
packInt(cpuid);
writeString(name);
}
- check(1);
+ check(currTime);
}
bool Buffer::eventHeader(const uint64_t curr_time) {
bool retval = false;
if (checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
- packInt(0); // key of zero indicates a timestamp
+ // key of zero indicates a timestamp
+ packInt(0);
packInt64(curr_time);
retval = true;
}
@@ -275,7 +294,8 @@ bool Buffer::eventHeader(const uint64_t curr_time) {
bool Buffer::eventTid(const int tid) {
bool retval = false;
if (checkSpace(2 * MAXSIZE_PACK32)) {
- packInt(1); // key of 1 indicates a tid
+ // key of 1 indicates a tid
+ packInt(1);
packInt(tid);
retval = true;
}
@@ -283,102 +303,119 @@ bool Buffer::eventTid(const int tid) {
return retval;
}
-void Buffer::event(const int32_t key, const int32_t value) {
+void Buffer::event(const int key, const int32_t value) {
if (checkSpace(2 * MAXSIZE_PACK32)) {
packInt(key);
packInt(value);
}
}
-void Buffer::event64(const int64_t key, const int64_t value) {
- if (checkSpace(2 * MAXSIZE_PACK64)) {
- packInt64(key);
+void Buffer::event64(const int key, const int64_t value) {
+ if (checkSpace(MAXSIZE_PACK64 + MAXSIZE_PACK32)) {
+ packInt(key);
packInt64(value);
}
}
-void Buffer::pea(const struct perf_event_attr *const pea, int key) {
- if (checkSpace(2 * MAXSIZE_PACK32 + pea->size)) {
- packInt(CODE_PEA);
- writeBytes(pea, pea->size);
- packInt(key);
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
+void Buffer::pea(const uint64_t currTime, const struct perf_event_attr *const pea, int key) {
+ while (!checkSpace(2 * MAXSIZE_PACK32 + pea->size)) {
+ sem_wait(&mWriterSem);
}
- // Don't know the real perf time so use 1 as it will work for now
- check(1);
+ packInt(CODE_PEA);
+ writeBytes(pea, pea->size);
+ packInt(key);
+ check(currTime);
}
-void Buffer::keys(const int count, const __u64 *const ids, const int *const keys) {
- if (checkSpace(2 * MAXSIZE_PACK32 + count * (MAXSIZE_PACK32 + MAXSIZE_PACK64))) {
- packInt(CODE_KEYS);
- packInt(count);
- for (int i = 0; i < count; ++i) {
- packInt64(ids[i]);
- packInt(keys[i]);
- }
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
+void Buffer::keys(const uint64_t currTime, const int count, const __u64 *const ids, const int *const keys) {
+ while (!checkSpace(2 * MAXSIZE_PACK32 + count * (MAXSIZE_PACK32 + MAXSIZE_PACK64))) {
+ sem_wait(&mWriterSem);
+ }
+ packInt(CODE_KEYS);
+ packInt(count);
+ for (int i = 0; i < count; ++i) {
+ packInt64(ids[i]);
+ packInt(keys[i]);
}
- check(1);
+ check(currTime);
}
-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();
+void Buffer::keysOld(const uint64_t currTime, const int keyCount, const int *const keys, const int bytes, const char *const buf) {
+ while (!checkSpace((2 + keyCount) * MAXSIZE_PACK32 + bytes)) {
+ sem_wait(&mWriterSem);
+ }
+ packInt(CODE_KEYS_OLD);
+ packInt(keyCount);
+ for (int i = 0; i < keyCount; ++i) {
+ packInt(keys[i]);
}
- check(1);
+ writeBytes(buf, bytes);
+ check(currTime);
}
-void Buffer::format(const int length, const char *const format) {
- if (checkSpace(MAXSIZE_PACK32 + length + 1)) {
- packInt(CODE_FORMAT);
- writeBytes(format, length + 1);
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
+void Buffer::format(const uint64_t currTime, const int length, const char *const format) {
+ while (!checkSpace(MAXSIZE_PACK32 + length + 1)) {
+ sem_wait(&mWriterSem);
}
- check(1);
+ packInt(CODE_FORMAT);
+ writeBytes(format, length + 1);
+ check(currTime);
}
-void Buffer::maps(const int pid, const int tid, const char *const maps) {
+void Buffer::maps(const uint64_t currTime, const int pid, const int tid, const char *const maps) {
const int mapsLen = strlen(maps) + 1;
- if (checkSpace(3 * MAXSIZE_PACK32 + mapsLen)) {
- packInt(CODE_MAPS);
- packInt(pid);
- packInt(tid);
- writeBytes(maps, mapsLen);
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
+ while (!checkSpace(3 * MAXSIZE_PACK32 + mapsLen)) {
+ sem_wait(&mWriterSem);
}
- check(1);
+ packInt(CODE_MAPS);
+ packInt(pid);
+ packInt(tid);
+ writeBytes(maps, mapsLen);
+ check(currTime);
}
-void Buffer::comm(const int pid, const int tid, const char *const image, const char *const comm) {
+void Buffer::comm(const uint64_t currTime, const int pid, const int tid, const char *const image, const char *const comm) {
const int imageLen = strlen(image) + 1;
const int commLen = strlen(comm) + 1;
- if (checkSpace(3 * MAXSIZE_PACK32 + imageLen + commLen)) {
- packInt(CODE_COMM);
- packInt(pid);
- packInt(tid);
- writeBytes(image, imageLen);
- writeBytes(comm, commLen);
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
+ while (!checkSpace(3 * MAXSIZE_PACK32 + imageLen + commLen)) {
+ sem_wait(&mWriterSem);
+ }
+ packInt(CODE_COMM);
+ packInt(pid);
+ packInt(tid);
+ writeBytes(image, imageLen);
+ writeBytes(comm, commLen);
+ check(currTime);
+}
+
+void Buffer::onlineCPU(const uint64_t currTime, const uint64_t time, const int cpu) {
+ while (!checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
+ sem_wait(&mWriterSem);
+ }
+ packInt(CODE_ONLINE_CPU);
+ packInt64(time);
+ packInt(cpu);
+ check(currTime);
+}
+
+void Buffer::offlineCPU(const uint64_t currTime, const uint64_t time, const int cpu) {
+ while (!checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
+ sem_wait(&mWriterSem);
+ }
+ packInt(CODE_OFFLINE_CPU);
+ packInt64(time);
+ packInt(cpu);
+ check(currTime);
+}
+
+void Buffer::kallsyms(const uint64_t currTime, const char *const kallsyms) {
+ const int kallsymsLen = strlen(kallsyms) + 1;
+ while (!checkSpace(3 * MAXSIZE_PACK32 + kallsymsLen)) {
+ sem_wait(&mWriterSem);
}
- check(1);
+ packInt(CODE_KALLSYMS);
+ writeBytes(kallsyms, kallsymsLen);
+ check(currTime);
}
void Buffer::setDone() {
diff --git a/tools/gator/daemon/Buffer.h b/tools/gator/daemon/Buffer.h
index 2de1b97..6cffd8e 100644
--- a/tools/gator/daemon/Buffer.h
+++ b/tools/gator/daemon/Buffer.h
@@ -39,25 +39,26 @@ public:
void commit(const uint64_t time);
void check(const uint64_t time);
- void frame();
-
// Summary messages
- void summary(const int64_t timestamp, const int64_t uptime, const int64_t monotonicDelta, const char *const uname);
- void coreName(const int core, const int cpuid, const char *const name);
+ void summary(const uint64_t currTime, const int64_t timestamp, const int64_t uptime, const int64_t monotonicDelta, const char *const uname);
+ void coreName(const uint64_t currTime, const int core, const int cpuid, const char *const name);
// Block Counter messages
bool eventHeader(uint64_t curr_time);
bool eventTid(int tid);
- void event(int32_t key, int32_t value);
- void event64(int64_t key, int64_t value);
+ void event(int key, int32_t value);
+ void event64(int key, int64_t value);
// 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);
+ void pea(const uint64_t currTime, const struct perf_event_attr *const pea, int key);
+ void keys(const uint64_t currTime, const int count, const __u64 *const ids, const int *const keys);
+ void keysOld(const uint64_t currTime, const int keyCount, const int *const keys, const int bytes, const char *const buf);
+ void format(const uint64_t currTime, const int length, const char *const format);
+ void maps(const uint64_t currTime, const int pid, const int tid, const char *const maps);
+ void comm(const uint64_t currTime, const int pid, const int tid, const char *const image, const char *const comm);
+ void onlineCPU(const uint64_t currTime, const uint64_t time, const int cpu);
+ void offlineCPU(const uint64_t currTime, const uint64_t time, const int cpu);
+ void kallsyms(const uint64_t currTime, const char *const kallsyms);
void setDone();
bool isDone() const;
@@ -67,6 +68,7 @@ public:
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);
+ static void packInt64(char *const buf, const int size, int &writePos, int64_t x);
void packInt64(int64_t x);
void writeBytes(const void *const data, size_t count);
void writeString(const char *const str);
@@ -79,20 +81,22 @@ public:
}
private:
+ void frame();
bool commitReady() const;
bool checkSpace(int bytes);
- const int32_t mCore;
- const int32_t mBufType;
+ char *const mBuf;
+ sem_t *const mReaderSem;
+ uint64_t mCommitTime;
+ sem_t mWriterSem;
const int mSize;
int mReadPos;
int mWritePos;
int mCommitPos;
bool mAvailable;
bool mIsDone;
- char *const mBuf;
- uint64_t mCommitTime;
- sem_t *const mReaderSem;
+ const int32_t mCore;
+ const int32_t mBufType;
// Intentionally unimplemented
Buffer(const Buffer &);
diff --git a/tools/gator/daemon/CCNDriver.cpp b/tools/gator/daemon/CCNDriver.cpp
new file mode 100644
index 0000000..dd1a2b1
--- /dev/null
+++ b/tools/gator/daemon/CCNDriver.cpp
@@ -0,0 +1,295 @@
+/**
+ * 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 "CCNDriver.h"
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "k/perf_event.h"
+
+#include "Config.h"
+#include "DriverSource.h"
+#include "Logging.h"
+
+static const char TAG_CATEGORY[] = "category";
+static const char TAG_COUNTER_SET[] = "counter_set";
+static const char TAG_EVENT[] = "event";
+static const char TAG_OPTION[] = "option";
+static const char TAG_OPTION_SET[] = "option_set";
+
+static const char ATTR_AVERAGE_SELECTION[] = "average_selection";
+static const char ATTR_COUNTER[] = "counter";
+static const char ATTR_COUNTER_SET[] = "counter_set";
+static const char ATTR_COUNT[] = "count";
+static const char ATTR_DESCRIPTION[] = "description";
+static const char ATTR_DISPLAY[] = "display";
+static const char ATTR_EVENT[] = "event";
+static const char ATTR_EVENT_DELTA[] = "event_delta";
+static const char ATTR_NAME[] = "name";
+static const char ATTR_OPTION_SET[] = "option_set";
+static const char ATTR_TITLE[] = "title";
+static const char ATTR_UNITS[] = "units";
+
+static const char XP_REGION[] = "XP_Region";
+static const char HNF_REGION[] = "HN-F_Region";
+static const char RNI_REGION[] = "RN-I_Region";
+static const char SBAS_REGION[] = "SBAS_Region";
+static const char CCN_5XX[] = "CCN-5xx";
+#define ARM_CCN_5XX "ARM_CCN_5XX_"
+
+static const char *const VC_TYPES[] = { "REQ", "RSP", "SNP", "DAT" };
+static const char *const XP_EVENT_NAMES[] = { NULL, "H-bit", "S-bit", "P-Cnt", "TknV" };
+static const char *const XP_EVENT_DESCRIPTIONS[] = { NULL, "Set H-bit, signaled when this XP sets the H-bit.", "Set S-bit, signaled when this XP sets the S-bit.", "Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC.", "No TknV, signaled when this XP transmits a valid packet." };
+static const char *const HNF_EVENT_NAMES[] = { NULL, "Cache Miss", "L3 SF Cache Access", "Cache Fill", "POCQ Retry", "POCQ Reqs Recvd", "SF Hit", "SF Evictions", "Snoops Sent", "Snoops Broadcast", "L3 Eviction", "L3 Fill Invalid Way", "MC Retries", "MC Reqs", "QOS HH Retry" };
+static const char *const HNF_EVENT_DESCRIPTIONS[] = { NULL, "Counts the total cache misses. This is the first time lookup result, and is high priority.", "Counts the number of cache accesses. This is the first time access, and is high priority.", "Counts the total allocations in the HN L3 cache, and all cache line allocations to the L3 cache.", "Counts the number of requests that have been retried.", "Counts the number of requests received by HN.", "Counts the number of snoop filter hits.", "Counts the number of snoop filter evictions. Cache invalidations are initiated.", "Counts the number of snoops sent. Does not differentiate between broadcast or directed snoops.", "Counts the number of snoop broadcasts sent.", "Counts the number of L3 evictions.", "Counts the number of L3 fills to an invalid way.", "Counts the number of transactions retried by the memory controller.", "Counts the number of requests to the memory controller.", "Counts the number of times a highest-priority QoS class was retried at the HN-F." };
+static const char *const RNI_EVENT_NAMES[] = { NULL, "S0 RDataBeats", "S1 RDataBeats", "S2 RDataBeats", "RXDAT Flits received", "TXDAT Flits sent", "Total TXREQ Flits sent", "Retried TXREQ Flits sent", "RRT full", "WRT full", "Replayed TXREQ Flits" };
+static const char *const RNI_EVENT_DESCRIPTIONS[] = { NULL, "S0 RDataBeats.", "S1 RDataBeats.", "S2 RDataBeats.", "RXDAT Flits received.", "TXDAT Flits sent.", "Total TXREQ Flits sent.", "Retried TXREQ Flits sent.", "RRT full.", "WRT full.", "Replayed TXREQ Flits." };
+static const char *const SBAS_EVENT_NAMES[] = { NULL, "S0 RDataBeats", NULL, NULL, "RXDAT Flits received", "TXDAT Flits sent", "Total TXREQ Flits sent", "Retried TXREQ Flits sent", "RRT full", "WRT full", "Replayed TXREQ Flits" };
+static const char *const SBAS_EVENT_DESCRIPTIONS[] = { NULL, "S0 RDataBeats.", NULL, NULL, "RXDAT Flits received.", "TXDAT Flits sent.", "Total TXREQ Flits sent.", "Retried TXREQ Flits sent.", "RRT full.", "WRT full.", "Replayed TXREQ Flits." };
+
+// This class is used only to poll for CCN-5xx configuration and emit events XML for it. All other operations are handled by PerfDriver
+
+static int sys_perf_event_open(struct perf_event_attr *const attr, const pid_t pid, const int cpu, const int group_fd, const unsigned long flags) {
+ return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
+}
+
+static unsigned int getConfig(unsigned int node, unsigned int type, unsigned int event, unsigned int port, unsigned int vc) {
+ return
+ ((node & 0xff) << 0) |
+ ((type & 0xff) << 8) |
+ ((event & 0xff) << 16) |
+ ((port & 0x03) << 24) |
+ ((vc & 0x07) << 26) |
+ 0;
+}
+
+static bool perfPoll(struct perf_event_attr *const pea) {
+ int fd = sys_perf_event_open(pea, -1, 0, -1, 0);
+ if (fd < 0) {
+ return false;
+ }
+ close(fd);
+ return true;
+}
+
+CCNDriver::CCNDriver() : mNodeTypes(NULL), mXpCount(0) {
+}
+
+CCNDriver::~CCNDriver() {
+ delete mNodeTypes;
+}
+
+bool CCNDriver::claimCounter(const Counter &) const {
+ // Handled by PerfDriver
+ return false;
+}
+
+void CCNDriver::resetCounters() {
+ // Handled by PerfDriver
+}
+
+void CCNDriver::setupCounter(Counter &) {
+ // Handled by PerfDriver
+}
+
+void CCNDriver::readEvents(mxml_node_t *const) {
+ struct stat st;
+ if (stat("/sys/bus/event_source/devices/ccn", &st) != 0) {
+ // Not found
+ return;
+ }
+
+ int type;
+ if (DriverSource::readIntDriver("/sys/bus/event_source/devices/ccn/type", &type) != 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to read CCN-5xx type");
+ handleException();
+ }
+
+ // Detect number of xps
+ struct perf_event_attr pea;
+ memset(&pea, 0, sizeof(pea));
+ pea.type = type;
+ pea.size = sizeof(pea);
+
+ mXpCount = 1;
+ while (true) {
+ pea.config = getConfig(0, 0x08, 1, 0, 1) | mXpCount;
+ if (!perfPoll(&pea)) {
+ break;
+ }
+ mXpCount *= 2;
+ };
+ {
+ int lower = mXpCount/2 + 1;
+ while (lower < mXpCount) {
+ int mid = (lower + mXpCount)/2;
+ pea.config = getConfig(0, 0x08, 1, 0, 1) | mid;
+ if (perfPoll(&pea)) {
+ lower = mid + 1;
+ } else {
+ mXpCount = mid;
+ }
+ }
+ }
+
+ mNodeTypes = new NodeType[2*mXpCount];
+
+ // Detect node types
+ for (int i = 0; i < 2*mXpCount; ++i) {
+ pea.config = getConfig(0, 0x04, 1, 0, 0) | i;
+ if (perfPoll(&pea)) {
+ mNodeTypes[i] = NT_HNF;
+ continue;
+ }
+
+ pea.config = getConfig(0, 0x16, 1, 0, 0) | i;
+ if (perfPoll(&pea)) {
+ mNodeTypes[i] = NT_RNI;
+ continue;
+ }
+
+ pea.config = getConfig(0, 0x10, 1, 0, 0) | i;
+ if (perfPoll(&pea)) {
+ mNodeTypes[i] = NT_SBAS;
+ continue;
+ }
+
+ mNodeTypes[i] = NT_UNKNOWN;
+ }
+}
+
+int CCNDriver::writeCounters(mxml_node_t *const) const {
+ // Handled by PerfDriver
+ return 0;
+}
+
+void CCNDriver::writeEvents(mxml_node_t *const root) const {
+ mxml_node_t *const counter_set = mxmlNewElement(root, TAG_COUNTER_SET);
+ mxmlElementSetAttr(counter_set, ATTR_NAME, ARM_CCN_5XX "cnt");
+ mxmlElementSetAttr(counter_set, ATTR_COUNT, "8");
+
+ mxml_node_t *const category = mxmlNewElement(root, TAG_CATEGORY);
+ mxmlElementSetAttr(category, ATTR_NAME, CCN_5XX);
+ mxmlElementSetAttr(category, TAG_COUNTER_SET, ARM_CCN_5XX "cnt");
+
+ mxml_node_t *const clock_event = mxmlNewElement(category, TAG_EVENT);
+ mxmlElementSetAttr(clock_event, ATTR_COUNTER, ARM_CCN_5XX "ccnt");
+ mxmlElementSetAttr(clock_event, ATTR_EVENT, "0xff00");
+ mxmlElementSetAttr(clock_event, ATTR_TITLE, "CCN-5xx Clock");
+ mxmlElementSetAttr(clock_event, ATTR_NAME, "Cycles");
+ mxmlElementSetAttr(clock_event, ATTR_DISPLAY, "hertz");
+ mxmlElementSetAttr(clock_event, ATTR_UNITS, "Hz");
+ mxmlElementSetAttr(clock_event, ATTR_AVERAGE_SELECTION, "yes");
+ mxmlElementSetAttr(clock_event, ATTR_DESCRIPTION, "The number of core clock cycles");
+
+ mxml_node_t *const xp_option_set = mxmlNewElement(category, TAG_OPTION_SET);
+ mxmlElementSetAttr(xp_option_set, ATTR_NAME, XP_REGION);
+
+ for (int i = 0; i < mXpCount; ++i) {
+ mxml_node_t *const option = mxmlNewElement(xp_option_set, TAG_OPTION);
+ mxmlElementSetAttrf(option, ATTR_EVENT_DELTA, "0x%x", getConfig(i, 0, 0, 0, 0));
+ mxmlElementSetAttrf(option, ATTR_NAME, "XP %i", i);
+ mxmlElementSetAttrf(option, ATTR_DESCRIPTION, "Crosspoint %i", i);
+ }
+
+ for (int vc = 0; vc < ARRAY_LENGTH(VC_TYPES); ++vc) {
+ if (VC_TYPES[vc] == NULL) {
+ continue;
+ }
+ for (int bus = 0; bus < 2; ++bus) {
+ for (int eventId = 0; eventId < ARRAY_LENGTH(XP_EVENT_NAMES); ++eventId) {
+ if (XP_EVENT_NAMES[eventId] == NULL) {
+ continue;
+ }
+ mxml_node_t *const event = mxmlNewElement(category, TAG_EVENT);
+ mxmlElementSetAttrf(event, ATTR_EVENT, "0x%x", getConfig(0, 0x08, eventId, bus, vc));
+ mxmlElementSetAttr(event, ATTR_OPTION_SET, XP_REGION);
+ mxmlElementSetAttr(event, ATTR_TITLE, CCN_5XX);
+ mxmlElementSetAttrf(event, ATTR_NAME, "Bus %i: %s: %s", bus, VC_TYPES[vc], XP_EVENT_NAMES[eventId]);
+ mxmlElementSetAttrf(event, ATTR_DESCRIPTION, "Bus %i: %s: %s", bus, VC_TYPES[vc], XP_EVENT_DESCRIPTIONS[eventId]);
+ }
+ }
+ }
+
+ mxml_node_t *const hnf_option_set = mxmlNewElement(category, TAG_OPTION_SET);
+ mxmlElementSetAttr(hnf_option_set, ATTR_NAME, HNF_REGION);
+
+ for (int eventId = 0; eventId < ARRAY_LENGTH(HNF_EVENT_NAMES); ++eventId) {
+ if (HNF_EVENT_NAMES[eventId] == NULL) {
+ continue;
+ }
+ mxml_node_t *const event = mxmlNewElement(category, TAG_EVENT);
+ mxmlElementSetAttrf(event, ATTR_EVENT, "0x%x", getConfig(0, 0x04, eventId, 0, 0));
+ mxmlElementSetAttr(event, ATTR_OPTION_SET, HNF_REGION);
+ mxmlElementSetAttr(event, ATTR_TITLE, CCN_5XX);
+ mxmlElementSetAttr(event, ATTR_NAME, HNF_EVENT_NAMES[eventId]);
+ mxmlElementSetAttr(event, ATTR_DESCRIPTION, HNF_EVENT_DESCRIPTIONS[eventId]);
+ }
+
+ mxml_node_t *const rni_option_set = mxmlNewElement(category, TAG_OPTION_SET);
+ mxmlElementSetAttr(rni_option_set, ATTR_NAME, RNI_REGION);
+
+ for (int eventId = 0; eventId < ARRAY_LENGTH(RNI_EVENT_NAMES); ++eventId) {
+ if (RNI_EVENT_NAMES[eventId] == NULL) {
+ continue;
+ }
+ mxml_node_t *const event = mxmlNewElement(category, TAG_EVENT);
+ mxmlElementSetAttrf(event, ATTR_EVENT, "0x%x", getConfig(0, 0x16, eventId, 0, 0));
+ mxmlElementSetAttr(event, ATTR_OPTION_SET, RNI_REGION);
+ mxmlElementSetAttr(event, ATTR_TITLE, CCN_5XX);
+ mxmlElementSetAttr(event, ATTR_NAME, RNI_EVENT_NAMES[eventId]);
+ mxmlElementSetAttr(event, ATTR_DESCRIPTION, RNI_EVENT_DESCRIPTIONS[eventId]);
+ }
+
+ mxml_node_t *const sbas_option_set = mxmlNewElement(category, TAG_OPTION_SET);
+ mxmlElementSetAttr(sbas_option_set, ATTR_NAME, SBAS_REGION);
+
+ for (int eventId = 0; eventId < ARRAY_LENGTH(SBAS_EVENT_NAMES); ++eventId) {
+ if (SBAS_EVENT_NAMES[eventId] == NULL) {
+ continue;
+ }
+ mxml_node_t *const event = mxmlNewElement(category, TAG_EVENT);
+ mxmlElementSetAttrf(event, ATTR_EVENT, "0x%x", getConfig(0, 0x10, eventId, 0, 0));
+ mxmlElementSetAttr(event, ATTR_OPTION_SET, SBAS_REGION);
+ mxmlElementSetAttr(event, ATTR_TITLE, CCN_5XX);
+ mxmlElementSetAttr(event, ATTR_NAME, SBAS_EVENT_NAMES[eventId]);
+ mxmlElementSetAttr(event, ATTR_DESCRIPTION, SBAS_EVENT_DESCRIPTIONS[eventId]);
+ }
+
+ for (int i = 0; i < 2*mXpCount; ++i) {
+ switch (mNodeTypes[i]) {
+ case NT_HNF: {
+ mxml_node_t *const option = mxmlNewElement(hnf_option_set, TAG_OPTION);
+ mxmlElementSetAttrf(option, ATTR_EVENT_DELTA, "0x%x", getConfig(i, 0, 0, 0, 0));
+ mxmlElementSetAttrf(option, ATTR_NAME, "HN-F %i", i);
+ mxmlElementSetAttrf(option, ATTR_DESCRIPTION, "Fully-coherent Home Node %i", i);
+ break;
+ }
+ case NT_RNI: {
+ mxml_node_t *const option = mxmlNewElement(rni_option_set, TAG_OPTION);
+ mxmlElementSetAttrf(option, ATTR_EVENT_DELTA, "0x%x", getConfig(i, 0, 0, 0, 0));
+ mxmlElementSetAttrf(option, ATTR_NAME, "RN-I %i", i);
+ mxmlElementSetAttrf(option, ATTR_DESCRIPTION, "I/O-coherent Requesting Node %i", i);
+ break;
+ }
+ case NT_SBAS: {
+ mxml_node_t *const option = mxmlNewElement(sbas_option_set, TAG_OPTION);
+ mxmlElementSetAttrf(option, ATTR_EVENT_DELTA, "0x%x", getConfig(i, 0, 0, 0, 0));
+ mxmlElementSetAttrf(option, ATTR_NAME, "SBAS %i", i);
+ mxmlElementSetAttrf(option, ATTR_DESCRIPTION, "ACE master to CHI protocol bridge %i", i);
+ break;
+ }
+ default:
+ continue;
+ }
+ }
+}
diff --git a/tools/gator/daemon/CCNDriver.h b/tools/gator/daemon/CCNDriver.h
new file mode 100644
index 0000000..fb4c717
--- /dev/null
+++ b/tools/gator/daemon/CCNDriver.h
@@ -0,0 +1,43 @@
+/**
+ * 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 CCNDRIVER_H
+#define CCNDRIVER_H
+
+#include "Driver.h"
+
+class CCNDriver : public Driver {
+public:
+ CCNDriver();
+ ~CCNDriver();
+
+ bool claimCounter(const Counter &counter) const;
+ void resetCounters();
+ void setupCounter(Counter &counter);
+
+ void readEvents(mxml_node_t *const);
+ int writeCounters(mxml_node_t *const root) const;
+ void writeEvents(mxml_node_t *const) const;
+
+private:
+ enum NodeType {
+ NT_UNKNOWN,
+ NT_HNF,
+ NT_RNI,
+ NT_SBAS,
+ };
+
+ NodeType *mNodeTypes;
+ int mXpCount;
+
+ // Intentionally unimplemented
+ CCNDriver(const CCNDriver &);
+ CCNDriver &operator=(const CCNDriver &);
+};
+
+#endif // CCNDRIVER_H
diff --git a/tools/gator/daemon/CPUFreqDriver.cpp b/tools/gator/daemon/CPUFreqDriver.cpp
new file mode 100644
index 0000000..41f9d6f
--- /dev/null
+++ b/tools/gator/daemon/CPUFreqDriver.cpp
@@ -0,0 +1,58 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "CPUFreqDriver.h"
+
+#include "Buffer.h"
+#include "DriverSource.h"
+#include "Logging.h"
+#include "SessionData.h"
+
+CPUFreqDriver::CPUFreqDriver() : mPrev() {
+}
+
+CPUFreqDriver::~CPUFreqDriver() {
+}
+
+void CPUFreqDriver::readEvents(mxml_node_t *const) {
+ // Only for use with perf
+ if (!gSessionData->perf.isSetup()) {
+ return;
+ }
+
+ setCounters(new DriverCounter(getCounters(), strdup("Linux_power_cpu_freq")));
+}
+
+void CPUFreqDriver::read(Buffer *const buffer) {
+ char buf[64];
+ const DriverCounter *const counter = getCounters();
+ if ((counter == NULL) || !counter->isEnabled()) {
+ return;
+ }
+
+ const int key = getCounters()->getKey();
+ bool resetCores = false;
+ for (int i = 0; i < gSessionData->mCores; ++i) {
+ snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%i/cpufreq/cpuinfo_cur_freq", i);
+ int64_t freq;
+ if (DriverSource::readInt64Driver(buf, &freq) != 0) {
+ freq = 0;
+ }
+ if (mPrev[i] != freq) {
+ mPrev[i] = freq;
+ // Change cores
+ buffer->event64(2, i);
+ resetCores = true;
+ buffer->event64(key, 1000*freq);
+ }
+ }
+ if (resetCores) {
+ // Revert cores, UserSpaceSource is all on core 0
+ buffer->event64(2, 0);
+ }
+}
diff --git a/tools/gator/daemon/CPUFreqDriver.h b/tools/gator/daemon/CPUFreqDriver.h
new file mode 100644
index 0000000..ad8c9aa
--- /dev/null
+++ b/tools/gator/daemon/CPUFreqDriver.h
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef CPUFREQDRIVER_H
+#define CPUFREQDRIVER_H
+
+#include "Config.h"
+#include "Driver.h"
+
+class CPUFreqDriver : public PolledDriver {
+private:
+ typedef PolledDriver super;
+
+public:
+ CPUFreqDriver();
+ ~CPUFreqDriver();
+
+ void readEvents(mxml_node_t *const root);
+ void read(Buffer *const buffer);
+
+private:
+ int64_t mPrev[NR_CPUS];
+
+ // Intentionally unimplemented
+ CPUFreqDriver(const CPUFreqDriver &);
+ CPUFreqDriver &operator=(const CPUFreqDriver &);
+};
+
+#endif // CPUFREQDRIVER_H
diff --git a/tools/gator/daemon/CapturedXML.cpp b/tools/gator/daemon/CapturedXML.cpp
index 4a11415..0b5802c 100644
--- a/tools/gator/daemon/CapturedXML.cpp
+++ b/tools/gator/daemon/CapturedXML.cpp
@@ -34,6 +34,7 @@ mxml_node_t* CapturedXML::getTree(bool includeTime) {
mxmlElementSetAttr(captured, "version", "1");
if (gSessionData->perf.isSetup()) {
mxmlElementSetAttr(captured, "type", "Perf");
+ mxmlElementSetAttr(captured, "perf_beta", "yes");
}
mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION);
if (includeTime) { // Send the following only after the capture is complete
@@ -113,32 +114,32 @@ const char * mxmlWhitespaceCB(mxml_node_t *node, int loc) {
if (loc == MXML_WS_BEFORE_OPEN) {
// Single indentation
if (!strcmp(name, "target") || !strcmp(name, "counters"))
- return("\n ");
+ return "\n ";
// Double indentation
if (!strcmp(name, "counter"))
- return("\n ");
+ return "\n ";
// Avoid a carriage return on the first line of the xml file
if (!strncmp(name, "?xml", 4))
- return(NULL);
+ return NULL;
// Default - no indentation
- return("\n");
+ return "\n";
}
if (loc == MXML_WS_BEFORE_CLOSE) {
// No indentation
if (!strcmp(name, "captured"))
- return("\n");
+ return "\n";
// Single indentation
if (!strcmp(name, "counters"))
- return("\n ");
+ return "\n ";
// Default - no carriage return
- return(NULL);
+ return NULL;
}
- return(NULL);
+ return NULL;
}
diff --git a/tools/gator/daemon/CapturedXML.h b/tools/gator/daemon/CapturedXML.h
index ed08c44..b704f6e 100644
--- a/tools/gator/daemon/CapturedXML.h
+++ b/tools/gator/daemon/CapturedXML.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __CAPTURED_XML_H__
-#define __CAPTURED_XML_H__
+#ifndef __CAPTURED_XML_H__
+#define __CAPTURED_XML_H__
#include "mxml/mxml.h"
diff --git a/tools/gator/daemon/Child.cpp b/tools/gator/daemon/Child.cpp
index 1901ecc..6b5bbb3 100644
--- a/tools/gator/daemon/Child.cpp
+++ b/tools/gator/daemon/Child.cpp
@@ -14,25 +14,28 @@
#include <unistd.h>
#include <sys/prctl.h>
-#include "Logging.h"
#include "CapturedXML.h"
-#include "SessionData.h"
-#include "LocalCapture.h"
-#include "Sender.h"
-#include "OlyUtility.h"
-#include "OlySocket.h"
-#include "StreamlineSetup.h"
+#include "Command.h"
#include "ConfigurationXML.h"
#include "Driver.h"
-#include "PerfSource.h"
#include "DriverSource.h"
#include "ExternalSource.h"
+#include "FtraceSource.h"
+#include "LocalCapture.h"
+#include "Logging.h"
+#include "OlySocket.h"
+#include "OlyUtility.h"
+#include "PerfSource.h"
+#include "Sender.h"
+#include "SessionData.h"
+#include "StreamlineSetup.h"
#include "UserSpaceSource.h"
static sem_t haltPipeline, senderThreadStarted, startProfile, senderSem; // Shared by Child and spawned threads
static Source *primarySource = NULL;
static Source *externalSource = NULL;
static Source *userSpaceSource = NULL;
+static Source *ftraceSource = NULL;
static Sender* sender = NULL; // Shared by Child.cpp and spawned threads
Child* child = NULL; // shared by Child.cpp and main.cpp
@@ -149,7 +152,8 @@ static void *senderThread(void *) {
while (!primarySource->isDone() ||
!externalSource->isDone() ||
- (userSpaceSource != NULL && !userSpaceSource->isDone())) {
+ (userSpaceSource != NULL && !userSpaceSource->isDone()) ||
+ (ftraceSource != NULL && !ftraceSource->isDone())) {
sem_wait(&senderSem);
primarySource->write(sender);
@@ -157,6 +161,9 @@ static void *senderThread(void *) {
if (userSpaceSource != NULL) {
userSpaceSource->write(sender);
}
+ if (ftraceSource != NULL) {
+ ftraceSource->write(sender);
+ }
}
// write end-of-capture sequence
@@ -206,6 +213,9 @@ void Child::endSession() {
if (userSpaceSource != NULL) {
userSpaceSource->interrupt();
}
+ if (ftraceSource != NULL) {
+ ftraceSource->interrupt();
+ }
sem_post(&haltPipeline);
}
@@ -269,15 +279,32 @@ void Child::run() {
free(xmlString);
}
+ if (gSessionData->kmod.isMaliCapture() && (gSessionData->mSampleRate == 0)) {
+ logg->logError(__FILE__, __LINE__, "Mali counters are not supported with Sample Rate: None.");
+ handleException();
+ }
+
// Must be after session XML is parsed
if (!primarySource->prepare()) {
- logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
+ if (gSessionData->perf.isSetup()) {
+ logg->logError(__FILE__, __LINE__, "Unable to prepare gator driver for capture");
+ } else {
+ logg->logError(__FILE__, __LINE__, "Unable to communicate with the perf API, please ensure that CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER are enabled. Please refer to README_Streamline.txt for more information.");
+ }
handleException();
}
// Sender thread shall be halted until it is signaled for one shot mode
sem_init(&haltPipeline, 0, gSessionData->mOneShot ? 0 : 2);
+ // Must be initialized before senderThread is started as senderThread checks externalSource
+ externalSource = new ExternalSource(&senderSem);
+ if (!externalSource->prepare()) {
+ logg->logError(__FILE__, __LINE__, "Unable to prepare external source for capture");
+ handleException();
+ }
+ externalSource->start();
+
// Create the duration, stop, and sender threads
bool thread_creation_success = true;
if (gSessionData->mDuration > 0 && pthread_create(&durationThreadID, NULL, durationThread, NULL)) {
@@ -288,22 +315,37 @@ void Child::run() {
thread_creation_success = false;
}
- externalSource = new ExternalSource(&senderSem);
- if (!externalSource->prepare()) {
- logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
- handleException();
+ bool startUSSource = false;
+ for (int i = 0; i < ARRAY_LENGTH(gSessionData->usDrivers); ++i) {
+ if (gSessionData->usDrivers[i]->countersEnabled()) {
+ startUSSource = true;
+ }
}
- externalSource->start();
-
- if (gSessionData->hwmon.countersEnabled() || gSessionData->fsDriver.countersEnabled()) {
+ if (startUSSource) {
userSpaceSource = new UserSpaceSource(&senderSem);
if (!userSpaceSource->prepare()) {
- logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
+ logg->logError(__FILE__, __LINE__, "Unable to prepare userspace source for capture");
handleException();
}
userSpaceSource->start();
}
+ if (gSessionData->ftraceDriver.countersEnabled()) {
+ ftraceSource = new FtraceSource(&senderSem);
+ if (!ftraceSource->prepare()) {
+ logg->logError(__FILE__, __LINE__, "Unable to prepare userspace source for capture");
+ handleException();
+ }
+ ftraceSource->start();
+ }
+
+ if (gSessionData->mAllowCommands && (gSessionData->mCaptureCommand != NULL)) {
+ pthread_t thread;
+ if (pthread_create(&thread, NULL, commandThread, NULL)) {
+ thread_creation_success = false;
+ }
+ }
+
if (!thread_creation_success) {
logg->logError(__FILE__, __LINE__, "Failed to create gator threads");
handleException();
@@ -315,6 +357,9 @@ void Child::run() {
// Start profiling
primarySource->run();
+ if (ftraceSource != NULL) {
+ ftraceSource->join();
+ }
if (userSpaceSource != NULL) {
userSpaceSource->join();
}
@@ -338,6 +383,7 @@ void Child::run() {
logg->logMessage("Profiling ended.");
+ delete ftraceSource;
delete userSpaceSource;
delete externalSource;
delete primarySource;
diff --git a/tools/gator/daemon/Child.h b/tools/gator/daemon/Child.h
index a306a77..cc78202 100644
--- a/tools/gator/daemon/Child.h
+++ b/tools/gator/daemon/Child.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __CHILD_H__
-#define __CHILD_H__
+#ifndef __CHILD_H__
+#define __CHILD_H__
class OlySocket;
diff --git a/tools/gator/daemon/Command.cpp b/tools/gator/daemon/Command.cpp
new file mode 100644
index 0000000..28d73cf
--- /dev/null
+++ b/tools/gator/daemon/Command.cpp
@@ -0,0 +1,172 @@
+/**
+ * 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 "Command.h"
+
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "Logging.h"
+#include "SessionData.h"
+
+static int getUid(const char *const name, char *const shPath, const char *const tmpDir) {
+ // Lookups may fail when using a different libc or a statically compiled executable
+ char gatorTemp[32];
+ snprintf(gatorTemp, sizeof(gatorTemp), "%s/gator_temp", tmpDir);
+
+ const int fd = open(gatorTemp, 600, O_CREAT | O_CLOEXEC);
+ if (fd < 0) {
+ return -1;
+ }
+ close(fd);
+
+ char cmd[128];
+ snprintf(cmd, sizeof(cmd), "chown %s %s || rm %s", name, gatorTemp, gatorTemp);
+
+ const int pid = fork();
+ if (pid < 0) {
+ logg->logError(__FILE__, __LINE__, "fork failed");
+ handleException();
+ }
+ if (pid == 0) {
+ char cargv1[] = "-c";
+ char *cargv[] = {
+ shPath,
+ cargv1,
+ cmd,
+ NULL,
+ };
+
+ execv(cargv[0], cargv);
+ exit(-1);
+ }
+ while ((waitpid(pid, NULL, 0) < 0) && (errno == EINTR));
+
+ struct stat st;
+ int result = -1;
+ if (stat(gatorTemp, &st) == 0) {
+ result = st.st_uid;
+ }
+ unlink(gatorTemp);
+ return result;
+}
+
+static int getUid(const char *const name) {
+ // Look up the username
+ struct passwd *const user = getpwnam(name);
+ if (user != NULL) {
+ return user->pw_uid;
+ }
+
+
+ // Are we on Linux
+ char cargv0l[] = "/bin/sh";
+ if ((access(cargv0l, X_OK) == 0) && (access("/tmp", W_OK) == 0)) {
+ return getUid(name, cargv0l, "/tmp");
+ }
+
+ // Are we on android
+ char cargv0a[] = "/system/bin/sh";
+ if ((access(cargv0a, X_OK) == 0) && (access("/data", W_OK) == 0)) {
+ return getUid(name, cargv0a, "/data");
+ }
+
+ return -1;
+}
+
+void *commandThread(void *) {
+ prctl(PR_SET_NAME, (unsigned long)&"gatord-command", 0, 0, 0);
+
+ const char *const name = gSessionData->mCaptureUser == NULL ? "nobody" : gSessionData->mCaptureUser;
+ const int uid = getUid(name);
+ if (uid < 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to lookup the user %s, please double check that the user exists", name);
+ handleException();
+ }
+
+ sleep(3);
+
+ char buf[128];
+ int pipefd[2];
+ if (pipe_cloexec(pipefd) != 0) {
+ logg->logError(__FILE__, __LINE__, "pipe failed");
+ handleException();
+ }
+
+ const int pid = fork();
+ if (pid < 0) {
+ logg->logError(__FILE__, __LINE__, "fork failed");
+ handleException();
+ }
+ if (pid == 0) {
+ char cargv0l[] = "/bin/sh";
+ char cargv0a[] = "/system/bin/sh";
+ char cargv1[] = "-c";
+ char *cargv[] = {
+ cargv0l,
+ cargv1,
+ gSessionData->mCaptureCommand,
+ NULL,
+ };
+
+ buf[0] = '\0';
+ close(pipefd[0]);
+
+ // Gator runs at a high priority, reset the priority to the default
+ if (setpriority(PRIO_PROCESS, syscall(__NR_gettid), 0) == -1) {
+ snprintf(buf, sizeof(buf), "setpriority failed");
+ goto fail_exit;
+ }
+
+ if (setuid(uid) != 0) {
+ snprintf(buf, sizeof(buf), "setuid failed");
+ goto fail_exit;
+ }
+
+ {
+ const char *const path = gSessionData->mCaptureWorkingDir == NULL ? "/" : gSessionData->mCaptureWorkingDir;
+ if (chdir(path) != 0) {
+ snprintf(buf, sizeof(buf), "Unable to cd to %s, please verify the directory exists and is accessable to %s", path, name);
+ goto fail_exit;
+ }
+ }
+
+ execv(cargv[0], cargv);
+ cargv[0] = cargv0a;
+ execv(cargv[0], cargv);
+ snprintf(buf, sizeof(buf), "execv failed");
+
+ fail_exit:
+ if (buf[0] != '\0') {
+ const ssize_t bytes = write(pipefd[1], buf, sizeof(buf));
+ // Can't do anything if this fails
+ (void)bytes;
+ }
+
+ exit(-1);
+ }
+
+ close(pipefd[1]);
+ const ssize_t bytes = read(pipefd[0], buf, sizeof(buf));
+ if (bytes > 0) {
+ logg->logError(__FILE__, __LINE__, buf);
+ handleException();
+ }
+ close(pipefd[0]);
+
+ return NULL;
+}
diff --git a/tools/gator/daemon/Command.h b/tools/gator/daemon/Command.h
new file mode 100644
index 0000000..17244b7
--- /dev/null
+++ b/tools/gator/daemon/Command.h
@@ -0,0 +1,14 @@
+/**
+ * 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 COMMAND_H
+#define COMMAND_H
+
+void *commandThread(void *);
+
+#endif // COMMAND_H
diff --git a/tools/gator/daemon/Config.h b/tools/gator/daemon/Config.h
index 6f5e2aa..bee383a 100644
--- a/tools/gator/daemon/Config.h
+++ b/tools/gator/daemon/Config.h
@@ -10,8 +10,19 @@
#define CONFIG_H
#define ARRAY_LENGTH(A) static_cast<int>(sizeof(A)/sizeof((A)[0]))
+#define ACCESS_ONCE(x) (*(volatile typeof(x)*)&(x))
#define MAX_PERFORMANCE_COUNTERS 50
-#define NR_CPUS 16
+#define NR_CPUS 32
+
+template<typename T>
+static inline T min(const T a, const T b) {
+ return (a < b ? a : b);
+}
+
+template<typename T>
+static inline T max(const T a, const T b) {
+ return (a > b ? a : b);
+}
#endif // CONFIG_H
diff --git a/tools/gator/daemon/DiskIODriver.cpp b/tools/gator/daemon/DiskIODriver.cpp
new file mode 100644
index 0000000..5deb0f3
--- /dev/null
+++ b/tools/gator/daemon/DiskIODriver.cpp
@@ -0,0 +1,125 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+// Define to get format macros from inttypes.h
+#define __STDC_FORMAT_MACROS
+
+#include "DiskIODriver.h"
+
+#include <inttypes.h>
+
+#include "Logging.h"
+#include "SessionData.h"
+
+class DiskIOCounter : public DriverCounter {
+public:
+ DiskIOCounter(DriverCounter *next, char *const name, int64_t *const value);
+ ~DiskIOCounter();
+
+ int64_t read();
+
+private:
+ int64_t *const mValue;
+ int64_t mPrev;
+
+ // Intentionally unimplemented
+ DiskIOCounter(const DiskIOCounter &);
+ DiskIOCounter &operator=(const DiskIOCounter &);
+};
+
+DiskIOCounter::DiskIOCounter(DriverCounter *next, char *const name, int64_t *const value) : DriverCounter(next, name), mValue(value), mPrev(0) {
+}
+
+DiskIOCounter::~DiskIOCounter() {
+}
+
+int64_t DiskIOCounter::read() {
+ int64_t result = *mValue - mPrev;
+ mPrev = *mValue;
+ // Kernel assumes a sector is 512 bytes
+ return result << 9;
+}
+
+DiskIODriver::DiskIODriver() : mBuf(), mReadBytes(0), mWriteBytes(0) {
+}
+
+DiskIODriver::~DiskIODriver() {
+}
+
+void DiskIODriver::readEvents(mxml_node_t *const) {
+ // Only for use with perf
+ if (!gSessionData->perf.isSetup()) {
+ return;
+ }
+
+ setCounters(new DiskIOCounter(getCounters(), strdup("Linux_block_rq_rd"), &mReadBytes));
+ setCounters(new DiskIOCounter(getCounters(), strdup("Linux_block_rq_wr"), &mWriteBytes));
+}
+
+void DiskIODriver::doRead() {
+ if (!countersEnabled()) {
+ return;
+ }
+
+ if (!mBuf.read("/proc/diskstats")) {
+ logg->logError(__FILE__, __LINE__, "Unable to read /proc/diskstats");
+ handleException();
+ }
+
+ mReadBytes = 0;
+ mWriteBytes = 0;
+
+ char *lastName = NULL;
+ int lastNameLen = -1;
+ char *start = mBuf.getBuf();
+ while (*start != '\0') {
+ char *end = strchr(start, '\n');
+ if (end != NULL) {
+ *end = '\0';
+ }
+
+ int nameStart = -1;
+ int nameEnd = -1;
+ int64_t readBytes = -1;
+ int64_t writeBytes = -1;
+ const int count = sscanf(start, "%*d %*d %n%*s%n %*u %*u %" SCNu64 " %*u %*u %*u %" SCNu64, &nameStart, &nameEnd, &readBytes, &writeBytes);
+ if (count != 2) {
+ logg->logError(__FILE__, __LINE__, "Unable to parse /proc/diskstats");
+ handleException();
+ }
+
+ // Skip partitions which are identified if the name is a substring of the last non-partition
+ if ((lastName == NULL) || (strncmp(lastName, start + nameStart, lastNameLen) != 0)) {
+ lastName = start + nameStart;
+ lastNameLen = nameEnd - nameStart;
+ mReadBytes += readBytes;
+ mWriteBytes += writeBytes;
+ }
+
+ if (end == NULL) {
+ break;
+ }
+ start = end + 1;
+ }
+}
+
+void DiskIODriver::start() {
+ doRead();
+ // Initialize previous values
+ for (DriverCounter *counter = getCounters(); counter != NULL; counter = counter->getNext()) {
+ if (!counter->isEnabled()) {
+ continue;
+ }
+ counter->read();
+ }
+}
+
+void DiskIODriver::read(Buffer *const buffer) {
+ doRead();
+ super::read(buffer);
+}
diff --git a/tools/gator/daemon/DiskIODriver.h b/tools/gator/daemon/DiskIODriver.h
new file mode 100644
index 0000000..d0db18c7
--- /dev/null
+++ b/tools/gator/daemon/DiskIODriver.h
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef DISKIODRIVER_H
+#define DISKIODRIVER_H
+
+#include "Driver.h"
+#include "DynBuf.h"
+
+class DiskIODriver : public PolledDriver {
+private:
+ typedef PolledDriver super;
+
+public:
+ DiskIODriver();
+ ~DiskIODriver();
+
+ void readEvents(mxml_node_t *const root);
+ void start();
+ void read(Buffer *const buffer);
+
+private:
+ void doRead();
+
+ DynBuf mBuf;
+ int64_t mReadBytes;
+ int64_t mWriteBytes;
+
+ // Intentionally unimplemented
+ DiskIODriver(const DiskIODriver &);
+ DiskIODriver &operator=(const DiskIODriver &);
+};
+
+#endif // DISKIODRIVER_H
diff --git a/tools/gator/daemon/Driver.cpp b/tools/gator/daemon/Driver.cpp
index 09e0401..275da31 100644
--- a/tools/gator/daemon/Driver.cpp
+++ b/tools/gator/daemon/Driver.cpp
@@ -8,8 +8,89 @@
#include "Driver.h"
+#include "Buffer.h"
+#include "SessionData.h"
+
+DriverCounter::DriverCounter(DriverCounter *const next, const char *const name) : mNext(next), mName(name), mKey(getEventKey()), mEnabled(false) {
+}
+
+DriverCounter::~DriverCounter() {
+ delete mName;
+}
+
Driver *Driver::head = NULL;
Driver::Driver() : next(head) {
head = this;
}
+
+SimpleDriver::~SimpleDriver() {
+ DriverCounter *counters = mCounters;
+ while (counters != NULL) {
+ DriverCounter *counter = counters;
+ counters = counter->getNext();
+ delete counter;
+ }
+}
+
+DriverCounter *SimpleDriver::findCounter(const Counter &counter) const {
+ for (DriverCounter *driverCounter = mCounters; driverCounter != NULL; driverCounter = driverCounter->getNext()) {
+ if (strcmp(driverCounter->getName(), counter.getType()) == 0) {
+ return driverCounter;
+ }
+ }
+
+ return NULL;
+}
+
+bool SimpleDriver::claimCounter(const Counter &counter) const {
+ return findCounter(counter) != NULL;
+}
+
+bool SimpleDriver::countersEnabled() const {
+ for (DriverCounter *counter = mCounters; counter != NULL; counter = counter->getNext()) {
+ if (counter->isEnabled()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void SimpleDriver::resetCounters() {
+ for (DriverCounter *counter = mCounters; counter != NULL; counter = counter->getNext()) {
+ counter->setEnabled(false);
+ }
+}
+
+void SimpleDriver::setupCounter(Counter &counter) {
+ DriverCounter *const driverCounter = findCounter(counter);
+ if (driverCounter == NULL) {
+ counter.setEnabled(false);
+ return;
+ }
+ driverCounter->setEnabled(true);
+ counter.setKey(driverCounter->getKey());
+}
+
+int SimpleDriver::writeCounters(mxml_node_t *root) const {
+ int count = 0;
+ for (DriverCounter *counter = mCounters; counter != NULL; counter = counter->getNext()) {
+ mxml_node_t *node = mxmlNewElement(root, "counter");
+ mxmlElementSetAttr(node, "name", counter->getName());
+ ++count;
+ }
+
+ return count;
+}
+
+PolledDriver::~PolledDriver() {
+}
+
+void PolledDriver::read(Buffer *const buffer) {
+ for (DriverCounter *counter = getCounters(); counter != NULL; counter = counter->getNext()) {
+ if (!counter->isEnabled()) {
+ continue;
+ }
+ buffer->event64(counter->getKey(), counter->read());
+ }
+}
diff --git a/tools/gator/daemon/Driver.h b/tools/gator/daemon/Driver.h
index e5ed7b6..72870e3 100644
--- a/tools/gator/daemon/Driver.h
+++ b/tools/gator/daemon/Driver.h
@@ -9,10 +9,36 @@
#ifndef DRIVER_H
#define DRIVER_H
+#include <stdint.h>
+
#include "mxml/mxml.h"
+class Buffer;
class Counter;
+class DriverCounter {
+public:
+ DriverCounter(DriverCounter *const next, const char *const name);
+ virtual ~DriverCounter();
+
+ DriverCounter *getNext() const { return mNext; }
+ const char *getName() const { return mName; }
+ int getKey() const { return mKey; }
+ bool isEnabled() const { return mEnabled; }
+ void setEnabled(const bool enabled) { mEnabled = enabled; }
+ virtual int64_t read() { return -1; }
+
+private:
+ DriverCounter *const mNext;
+ const char *const mName;
+ const int mKey;
+ bool mEnabled;
+
+ // Intentionally unimplemented
+ DriverCounter(const DriverCounter &);
+ DriverCounter &operator=(const DriverCounter &);
+};
+
class Driver {
public:
static Driver *getHead() { return head; }
@@ -26,15 +52,17 @@ public:
// Enables and prepares the counter for capture
virtual void setupCounter(Counter &counter) = 0;
+ // Performs any actions needed for setup or based on eventsXML
+ virtual void readEvents(mxml_node_t *const) {}
// Emits available counters
- virtual int writeCounters(mxml_node_t *root) const = 0;
+ virtual int writeCounters(mxml_node_t *const root) const = 0;
// Emits possible dynamically generated events/counters
- virtual void writeEvents(mxml_node_t *) const {}
+ virtual void writeEvents(mxml_node_t *const) const {}
Driver *getNext() const { return next; }
protected:
- Driver ();
+ Driver();
private:
static Driver *head;
@@ -45,4 +73,46 @@ private:
Driver &operator=(const Driver &);
};
+class SimpleDriver : public Driver {
+public:
+ virtual ~SimpleDriver();
+
+ bool claimCounter(const Counter &counter) const;
+ bool countersEnabled() const;
+ void resetCounters();
+ void setupCounter(Counter &counter);
+ int writeCounters(mxml_node_t *root) const;
+
+protected:
+ SimpleDriver() : mCounters(NULL) {}
+
+ DriverCounter *getCounters() const { return mCounters; }
+ void setCounters(DriverCounter *const counter) { mCounters = counter; }
+
+ DriverCounter *findCounter(const Counter &counter) const;
+
+private:
+ DriverCounter *mCounters;
+
+ // Intentionally unimplemented
+ SimpleDriver(const SimpleDriver &);
+ SimpleDriver &operator=(const SimpleDriver &);
+};
+
+class PolledDriver : public SimpleDriver {
+public:
+ virtual ~PolledDriver();
+
+ virtual void start() {}
+ virtual void read(Buffer *const buffer);
+
+protected:
+ PolledDriver() {}
+
+private:
+ // Intentionally unimplemented
+ PolledDriver(const PolledDriver &);
+ PolledDriver &operator=(const PolledDriver &);
+};
+
#endif // DRIVER_H
diff --git a/tools/gator/daemon/DriverSource.cpp b/tools/gator/daemon/DriverSource.cpp
index 11d3095..7f299b6 100644
--- a/tools/gator/daemon/DriverSource.cpp
+++ b/tools/gator/daemon/DriverSource.cpp
@@ -6,6 +6,7 @@
* published by the Free Software Foundation.
*/
+// Define to get format macros from inttypes.h
#define __STDC_FORMAT_MACROS
#include "DriverSource.h"
@@ -93,19 +94,19 @@ bool DriverSource::prepare() {
}
void DriverSource::bootstrapThread() {
- prctl(PR_SET_NAME, (unsigned long)&"gatord-bootstrap", 0, 0, 0);
+ prctl(PR_SET_NAME, (unsigned long)&"gatord-proc", 0, 0, 0);
DynBuf printb;
DynBuf b1;
DynBuf b2;
- DynBuf b3;
+ const uint64_t currTime = getTime();
- if (!readProc(mBuffer, false, &printb, &b1, &b2, &b3)) {
- logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__);
+ if (!readProcComms(currTime, mBuffer, &printb, &b1, &b2)) {
+ logg->logError(__FILE__, __LINE__, "readProcComms failed");
handleException();
}
- mBuffer->commit(1);
+ mBuffer->commit(currTime);
mBuffer->setDone();
}
@@ -128,7 +129,7 @@ void DriverSource::run() {
}
// open the buffer which calls userspace_buffer_open() in the driver
- mBufferFD = open("/dev/gator/buffer", O_RDONLY);
+ mBufferFD = open("/dev/gator/buffer", O_RDONLY | O_CLOEXEC);
if (mBufferFD < 0) {
logg->logError(__FILE__, __LINE__, "The gator driver did not set up properly. Please view the linux console or dmesg log for more information on the failure.");
handleException();
@@ -232,7 +233,7 @@ void DriverSource::write(Sender *sender) {
int DriverSource::readIntDriver(const char *fullpath, int *value) {
char data[40]; // Sufficiently large to hold any integer
- const int fd = open(fullpath, O_RDONLY);
+ const int fd = open(fullpath, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
return -1;
}
@@ -257,7 +258,7 @@ int DriverSource::readIntDriver(const char *fullpath, int *value) {
int DriverSource::readInt64Driver(const char *fullpath, int64_t *value) {
char data[40]; // Sufficiently large to hold any integer
- const int fd = open(fullpath, O_RDONLY);
+ const int fd = open(fullpath, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
return -1;
}
@@ -281,7 +282,7 @@ int DriverSource::readInt64Driver(const char *fullpath, int64_t *value) {
}
int DriverSource::writeDriver(const char *fullpath, const char *data) {
- int fd = open(fullpath, O_WRONLY);
+ int fd = open(fullpath, O_WRONLY | O_CLOEXEC);
if (fd < 0) {
return -1;
}
diff --git a/tools/gator/daemon/DynBuf.cpp b/tools/gator/daemon/DynBuf.cpp
index 6f92b33..df20713 100644
--- a/tools/gator/daemon/DynBuf.cpp
+++ b/tools/gator/daemon/DynBuf.cpp
@@ -40,7 +40,7 @@ int DynBuf::resize(const size_t minCapacity) {
bool DynBuf::read(const char *const path) {
int result = false;
- const int fd = open(path, O_RDONLY);
+ const int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
logg->logMessage("%s(%s:%i): open failed", __FUNCTION__, __FILE__, __LINE__);
return false;
diff --git a/tools/gator/daemon/EventsXML.cpp b/tools/gator/daemon/EventsXML.cpp
index cf0192e..d905bba 100644
--- a/tools/gator/daemon/EventsXML.cpp
+++ b/tools/gator/daemon/EventsXML.cpp
@@ -47,7 +47,7 @@ char *EventsXML::getXML() {
// Add dynamic events from the drivers
mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND);
if (!events) {
- logg->logMessage("Unable to find <events> node in the events.xml");
+ logg->logError(__FILE__, __LINE__, "Unable to find <events> node in the events.xml");
handleException();
}
for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) {
diff --git a/tools/gator/daemon/ExternalSource.cpp b/tools/gator/daemon/ExternalSource.cpp
index b6ec301..8f5e6b6 100644
--- a/tools/gator/daemon/ExternalSource.cpp
+++ b/tools/gator/daemon/ExternalSource.cpp
@@ -19,6 +19,9 @@
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 const char MALI_GRAPHICS[] = "\0mali_thirdparty_server";
+static const char MALI_GRAPHICS_STARTUP[] = "\0mali_thirdparty_client";
+static const char MALI_GRAPHICS_V1[] = "MALI_GRAPHICS 1\n";
static bool setNonblock(const int fd) {
int flags;
@@ -37,16 +40,15 @@ static bool setNonblock(const int fd) {
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) {
+ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 128*1024, senderSem), mMonitor(), mMveStartupUds(MALI_VIDEO_STARTUP, sizeof(MALI_VIDEO_STARTUP)), mMaliStartupUds(MALI_GRAPHICS_STARTUP, sizeof(MALI_GRAPHICS_STARTUP)), mAnnotate(8083), mInterruptFd(-1), mMaliUds(-1), mMveUds(-1) {
sem_init(&mBufferSem, 0, 0);
}
ExternalSource::~ExternalSource() {
}
-void ExternalSource::waitFor(const uint64_t currTime, const int bytes) {
+void ExternalSource::waitFor(const int bytes) {
while (mBuffer.bytesAvailable() <= bytes) {
- mBuffer.check(currTime);
sem_wait(&mBufferSem);
}
}
@@ -63,11 +65,21 @@ void ExternalSource::configureConnection(const int fd, const char *const handsha
}
// Write the handshake to the circular buffer
- waitFor(1, Buffer::MAXSIZE_PACK32 + 4 + size - 1);
+ waitFor(Buffer::MAXSIZE_PACK32 + size - 1);
mBuffer.packInt(fd);
- mBuffer.writeLEInt((unsigned char *)mBuffer.getWritePos(), size - 1);
- mBuffer.advanceWrite(4);
mBuffer.writeBytes(handshake, size - 1);
+ mBuffer.commit(1);
+}
+
+bool ExternalSource::connectMali() {
+ mMaliUds = OlySocket::connect(MALI_GRAPHICS, sizeof(MALI_GRAPHICS));
+ if (mMaliUds < 0) {
+ return false;
+ }
+
+ configureConnection(mMaliUds, MALI_GRAPHICS_V1, sizeof(MALI_GRAPHICS_V1));
+
+ return true;
}
bool ExternalSource::connectMve() {
@@ -90,10 +102,15 @@ bool ExternalSource::connectMve() {
}
bool ExternalSource::prepare() {
- if (!mMonitor.init() || !setNonblock(mMveStartupUds.getFd()) || !mMonitor.add(mMveStartupUds.getFd())) {
+ if (!mMonitor.init() ||
+ !setNonblock(mMveStartupUds.getFd()) || !mMonitor.add(mMveStartupUds.getFd()) ||
+ !setNonblock(mMaliStartupUds.getFd()) || !mMonitor.add(mMaliStartupUds.getFd()) ||
+ !setNonblock(mAnnotate.getFd()) || !mMonitor.add(mAnnotate.getFd()) ||
+ false) {
return false;
}
+ connectMali();
connectMve();
return true;
@@ -104,7 +121,7 @@ void ExternalSource::run() {
prctl(PR_SET_NAME, (unsigned long)&"gatord-external", 0, 0, 0);
- if (pipe(pipefd) != 0) {
+ if (pipe_cloexec(pipefd) != 0) {
logg->logError(__FILE__, __LINE__, "pipe failed");
handleException();
}
@@ -115,6 +132,9 @@ void ExternalSource::run() {
handleException();
}
+ // Notify annotate clients to retry connecting to gatord
+ gSessionData->annotateListener.signal();
+
while (gSessionData->mSessionIsActive) {
struct epoll_event events[16];
// Clear any pending sem posts
@@ -138,36 +158,60 @@ void ExternalSource::run() {
logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali video connection");
handleException();
}
+ } else if (fd == mMaliStartupUds.getFd()) {
+ // Mali Graphics says it's alive
+ int client = mMaliStartupUds.acceptConnection();
+ // Don't read from this connection, establish a new connection to Mali Graphics
+ close(client);
+ if (!connectMali()) {
+ logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali graphics connection");
+ handleException();
+ }
+ } else if (fd == mAnnotate.getFd()) {
+ int client = mAnnotate.acceptConnection();
+ if (!setNonblock(client) || !mMonitor.add(client)) {
+ logg->logError(__FILE__, __LINE__, "Unable to set socket options on incoming annotation 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);
-
+ /* This can result in some starvation if there are multiple
+ * threads which are annotating heavily, but it is not
+ * recommended that threads annotate that much as it can also
+ * starve out the gator data.
+ */
+ while (gSessionData->mSessionIsActive) {
+ // Wait until there is enough room for the fd, two headers and two ints
+ waitFor(7*Buffer::MAXSIZE_PACK32 + 2*sizeof(uint32_t));
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);
+ // Nothing left to read
+ mBuffer.commit(currTime);
break;
}
// Something else failed, close the socket
- mBuffer.writeLEInt((unsigned char *)bytesPos, -1);
+ mBuffer.commit(currTime);
+ mBuffer.packInt(-1);
+ mBuffer.packInt(fd);
+ mBuffer.commit(currTime);
close(fd);
break;
} else if (bytes == 0) {
// The other side is closed
- mBuffer.writeLEInt((unsigned char *)bytesPos, -1);
+ mBuffer.commit(currTime);
+ mBuffer.packInt(-1);
+ mBuffer.packInt(fd);
+ mBuffer.commit(currTime);
close(fd);
break;
}
- mBuffer.writeLEInt((unsigned char *)bytesPos, bytes);
mBuffer.advanceWrite(bytes);
+ mBuffer.commit(currTime);
// Short reads also mean nothing is left to read
if (bytes < contiguous) {
@@ -176,13 +220,14 @@ void ExternalSource::run() {
}
}
}
-
- // Only call mBufferCheck once per iteration
- mBuffer.check(currTime);
}
mBuffer.setDone();
+ if (mMveUds >= 0) {
+ gSessionData->maliVideo.stop(mMveUds);
+ }
+
mInterruptFd = -1;
close(pipefd[0]);
close(pipefd[1]);
diff --git a/tools/gator/daemon/ExternalSource.h b/tools/gator/daemon/ExternalSource.h
index 2e7ed27..919e75e 100644
--- a/tools/gator/daemon/ExternalSource.h
+++ b/tools/gator/daemon/ExternalSource.h
@@ -16,7 +16,7 @@
#include "OlySocket.h"
#include "Source.h"
-// Unix domain socket counters from external sources like graphics drivers
+// Counters from external sources like graphics drivers and annotations
class ExternalSource : public Source {
public:
ExternalSource(sem_t *senderSem);
@@ -30,15 +30,19 @@ public:
void write(Sender *sender);
private:
- void waitFor(const uint64_t currTime, const int bytes);
+ void waitFor(const int bytes);
void configureConnection(const int fd, const char *const handshake, size_t size);
+ bool connectMali();
bool connectMve();
sem_t mBufferSem;
Buffer mBuffer;
Monitor mMonitor;
OlyServerSocket mMveStartupUds;
+ OlyServerSocket mMaliStartupUds;
+ OlyServerSocket mAnnotate;
int mInterruptFd;
+ int mMaliUds;
int mMveUds;
// Intentionally unimplemented
diff --git a/tools/gator/daemon/FSDriver.cpp b/tools/gator/daemon/FSDriver.cpp
index 40c8df1..dd8eb80 100644
--- a/tools/gator/daemon/FSDriver.cpp
+++ b/tools/gator/daemon/FSDriver.cpp
@@ -14,43 +14,34 @@
#include <sys/types.h>
#include <unistd.h>
-#include "Buffer.h"
-#include "Counter.h"
#include "DriverSource.h"
#include "Logging.h"
-#include "SessionData.h"
-class FSCounter {
+class FSCounter : public DriverCounter {
public:
- FSCounter(FSCounter *next, char *name, const char *regex);
+ FSCounter(DriverCounter *next, char *name, char *path, 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; }
+ const char *getPath() const { return mPath; }
+
int64_t read();
private:
- FSCounter *const next;
- regex_t reg;
- char *name;
- const int key;
- int enabled : 1,
- useRegex : 1;
+ char *const mPath;
+ regex_t mReg;
+ bool mUseRegex;
// 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(&reg, regex, REG_EXTENDED);
+FSCounter::FSCounter(DriverCounter *next, char *name, char *path, const char *regex) : DriverCounter(next, name), mPath(path), mUseRegex(regex != NULL) {
+ if (mUseRegex) {
+ int result = regcomp(&mReg, regex, REG_EXTENDED);
if (result != 0) {
char buf[128];
- regerror(result, &reg, buf, sizeof(buf));
+ regerror(result, &mReg, buf, sizeof(buf));
logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf);
handleException();
}
@@ -58,18 +49,18 @@ FSCounter::FSCounter(FSCounter *next, char *name, const char *regex) : next(next
}
FSCounter::~FSCounter() {
- free(name);
- if (useRegex) {
- regfree(&reg);
+ free(mPath);
+ if (mUseRegex) {
+ regfree(&mReg);
}
}
int64_t FSCounter::read() {
int64_t value;
- if (useRegex) {
+ if (mUseRegex) {
char buf[4096];
size_t pos = 0;
- const int fd = open(name, O_RDONLY);
+ const int fd = open(mPath, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
goto fail;
}
@@ -86,53 +77,43 @@ int64_t FSCounter::read() {
buf[pos] = '\0';
regmatch_t match[2];
- int result = regexec(&reg, buf, 2, match, 0);
+ int result = regexec(&mReg, buf, 2, match, 0);
if (result != 0) {
- regerror(result, &reg, buf, sizeof(buf));
- logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, buf);
+ regerror(result, &mReg, buf, sizeof(buf));
+ logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", mPath, buf);
handleException();
}
if (match[1].rm_so < 0) {
- logg->logError(__FILE__, __LINE__, "Parsing %s failed", name);
+ logg->logError(__FILE__, __LINE__, "Parsing %s failed", mPath);
handleException();
}
- char *endptr;
+
errno = 0;
- value = strtoll(buf + match[1].rm_so, &endptr, 0);
+ value = strtoll(buf + match[1].rm_so, NULL, 0);
if (errno != 0) {
- logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, strerror(errno));
+ logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", mPath, strerror(errno));
handleException();
}
} else {
- if (DriverSource::readInt64Driver(name, &value) != 0) {
+ if (DriverSource::readInt64Driver(mPath, &value) != 0) {
goto fail;
}
}
return value;
fail:
- logg->logError(__FILE__, __LINE__, "Unable to read %s", name);
+ logg->logError(__FILE__, __LINE__, "Unable to read %s", mPath);
handleException();
}
-FSDriver::FSDriver() : counters(NULL) {
+FSDriver::FSDriver() {
}
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;
- }
-
+void FSDriver::readEvents(mxml_node_t *const xml) {
mxml_node_t *node = xml;
while (true) {
node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
@@ -140,56 +121,33 @@ void FSDriver::setup(mxml_node_t *const xml) {
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);
+ if (counter == NULL) {
+ continue;
}
- }
-}
-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;
+ if (counter[0] == '/') {
+ logg->logError(__FILE__, __LINE__, "Old style filesystem counter (%s) detected, please create a new unique counter value and move the filename into the path attribute, see events-Filesystem.xml for examples", counter);
+ handleException();
}
- }
-
- 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;
+ if (strncmp(counter, "filesystem_", 11) != 0) {
+ continue;
}
- }
- 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;
+ const char *path = mxmlElementGetAttr(node, "path");
+ if (path == NULL) {
+ logg->logError(__FILE__, __LINE__, "The filesystem counter %s is missing the required path attribute", counter);
+ handleException();
+ }
+ const char *regex = mxmlElementGetAttr(node, "regex");
+ setCounters(new FSCounter(getCounters(), strdup(counter), strdup(path), regex));
}
- 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) {
+ for (FSCounter *counter = static_cast<FSCounter *>(getCounters()); counter != NULL; counter = static_cast<FSCounter *>(counter->getNext())) {
+ if (access(counter->getPath(), R_OK) == 0) {
mxml_node_t *node = mxmlNewElement(root, "counter");
mxmlElementSetAttr(node, "name", counter->getName());
++count;
@@ -198,15 +156,3 @@ int FSDriver::writeCounters(mxml_node_t *root) const {
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
index ef395536..a7dc8b4 100644
--- a/tools/gator/daemon/FSDriver.h
+++ b/tools/gator/daemon/FSDriver.h
@@ -11,31 +11,16 @@
#include "Driver.h"
-class Buffer;
-class FSCounter;
-
-class FSDriver : public Driver {
+class FSDriver : public PolledDriver {
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);
+ void readEvents(mxml_node_t *const xml);
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 &);
diff --git a/tools/gator/daemon/Fifo.cpp b/tools/gator/daemon/Fifo.cpp
index f672e92..41275fd 100644
--- a/tools/gator/daemon/Fifo.cpp
+++ b/tools/gator/daemon/Fifo.cpp
@@ -9,9 +9,6 @@
#include "Fifo.h"
#include <stdlib.h>
-#ifdef WIN32
-#define valloc malloc
-#endif
#include "Logging.h"
@@ -23,7 +20,7 @@ Fifo::Fifo(int singleBufferSize, int bufferSize, sem_t* readerSem) {
mWrapThreshold = bufferSize;
mSingleBufferSize = singleBufferSize;
mReaderSem = readerSem;
- mBuffer = (char*)valloc(bufferSize + singleBufferSize);
+ mBuffer = (char*)malloc(bufferSize + singleBufferSize);
mEnd = false;
if (mBuffer == NULL) {
diff --git a/tools/gator/daemon/Fifo.h b/tools/gator/daemon/Fifo.h
index bdda3f5..21c8d85 100644
--- a/tools/gator/daemon/Fifo.h
+++ b/tools/gator/daemon/Fifo.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __FIFO_H__
-#define __FIFO_H__
+#ifndef __FIFO_H__
+#define __FIFO_H__
#ifdef WIN32
#include <windows.h>
@@ -35,10 +35,10 @@ public:
private:
int mSingleBufferSize, mWrite, mRead, mReadCommit, mRaggedEnd, mWrapThreshold;
- sem_t mWaitForSpaceSem;
+ sem_t mWaitForSpaceSem;
sem_t* mReaderSem;
- char* mBuffer;
- bool mEnd;
+ char* mBuffer;
+ bool mEnd;
// Intentionally unimplemented
Fifo(const Fifo &);
diff --git a/tools/gator/daemon/FtraceDriver.cpp b/tools/gator/daemon/FtraceDriver.cpp
new file mode 100644
index 0000000..b156f1c
--- /dev/null
+++ b/tools/gator/daemon/FtraceDriver.cpp
@@ -0,0 +1,118 @@
+/**
+ * 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 "FtraceDriver.h"
+
+#include <regex.h>
+
+#include "Logging.h"
+
+class FtraceCounter : public DriverCounter {
+public:
+ FtraceCounter(DriverCounter *next, char *name, const char *regex);
+ ~FtraceCounter();
+
+ int read(const char *const line, int64_t *values);
+
+private:
+ regex_t reg;
+
+ // Intentionally unimplemented
+ FtraceCounter(const FtraceCounter &);
+ FtraceCounter &operator=(const FtraceCounter &);
+};
+
+FtraceCounter::FtraceCounter(DriverCounter *next, char *name, const char *regex) : DriverCounter(next, name) {
+ int result = regcomp(&reg, regex, REG_EXTENDED);
+ if (result != 0) {
+ char buf[128];
+ regerror(result, &reg, buf, sizeof(buf));
+ logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf);
+ handleException();
+ }
+}
+
+FtraceCounter::~FtraceCounter() {
+ regfree(&reg);
+}
+
+int FtraceCounter::read(const char *const line, int64_t *values) {
+ regmatch_t match[2];
+ int result = regexec(&reg, line, 2, match, 0);
+ if (result != 0) {
+ // No match
+ return 0;
+ }
+
+ if (match[1].rm_so < 0) {
+ logg->logError(__FILE__, __LINE__, "Parsing %s failed", getName());
+ handleException();
+ }
+
+ errno = 0;
+ int64_t value = strtoll(line + match[1].rm_so, NULL, 0);
+ if (errno != 0) {
+ logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", getName(), strerror(errno));
+ handleException();
+ }
+
+ values[0] = getKey();
+ values[1] = value;
+
+ return 1;
+}
+
+FtraceDriver::FtraceDriver() : mValues(NULL) {
+}
+
+FtraceDriver::~FtraceDriver() {
+ delete [] mValues;
+}
+
+void FtraceDriver::readEvents(mxml_node_t *const xml) {
+ mxml_node_t *node = xml;
+ int count = 0;
+ while (true) {
+ node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ break;
+ }
+ const char *counter = mxmlElementGetAttr(node, "counter");
+ if (counter == NULL) {
+ continue;
+ }
+
+ if (strncmp(counter, "ftrace_", 7) != 0) {
+ continue;
+ }
+
+ const char *regex = mxmlElementGetAttr(node, "regex");
+ if (regex == NULL) {
+ logg->logError(__FILE__, __LINE__, "The regex counter %s is missing the required regex attribute", counter);
+ handleException();
+ }
+ setCounters(new FtraceCounter(getCounters(), strdup(counter), regex));
+ ++count;
+ }
+
+ mValues = new int64_t[2*count];
+}
+
+int FtraceDriver::read(const char *line, int64_t **buf) {
+ int count = 0;
+
+ for (FtraceCounter *counter = static_cast<FtraceCounter *>(getCounters()); counter != NULL; counter = static_cast<FtraceCounter *>(counter->getNext())) {
+ if (!counter->isEnabled()) {
+ continue;
+ }
+ count += counter->read(line, mValues + 2*count);
+ }
+
+ *buf = mValues;
+ return count;
+}
diff --git a/tools/gator/daemon/FtraceDriver.h b/tools/gator/daemon/FtraceDriver.h
new file mode 100644
index 0000000..5f958be
--- /dev/null
+++ b/tools/gator/daemon/FtraceDriver.h
@@ -0,0 +1,31 @@
+/**
+ * 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 FTRACEDRIVER_H
+#define FTRACEDRIVER_H
+
+#include "Driver.h"
+
+class FtraceDriver : public SimpleDriver {
+public:
+ FtraceDriver();
+ ~FtraceDriver();
+
+ void readEvents(mxml_node_t *const xml);
+
+ int read(const char *line, int64_t **buf);
+
+private:
+ int64_t *mValues;
+
+ // Intentionally unimplemented
+ FtraceDriver(const FtraceDriver &);
+ FtraceDriver &operator=(const FtraceDriver &);
+};
+
+#endif // FTRACEDRIVER_H
diff --git a/tools/gator/daemon/FtraceSource.cpp b/tools/gator/daemon/FtraceSource.cpp
new file mode 100644
index 0000000..5216333
--- /dev/null
+++ b/tools/gator/daemon/FtraceSource.cpp
@@ -0,0 +1,158 @@
+/**
+ * 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 "FtraceSource.h"
+
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include "DriverSource.h"
+#include "Logging.h"
+#include "SessionData.h"
+
+static void handler(int signum)
+{
+ (void)signum;
+};
+
+FtraceSource::FtraceSource(sem_t *senderSem) : mFtraceFh(NULL), mBuffer(0, FRAME_BLOCK_COUNTER, 128*1024, senderSem), mTid(-1), mTracingOn(0) {
+}
+
+FtraceSource::~FtraceSource() {
+}
+
+bool FtraceSource::prepare() {
+ {
+ struct sigaction act;
+ act.sa_handler = handler;
+ act.sa_flags = (int)SA_RESETHAND;
+ if (sigaction(SIGUSR1, &act, NULL) != 0) {
+ logg->logError(__FILE__, __LINE__, "sigaction failed: %s\n", strerror(errno));
+ handleException();
+ }
+ }
+
+ if (DriverSource::readIntDriver("/sys/kernel/debug/tracing/tracing_on", &mTracingOn)) {
+ logg->logError(__FILE__, __LINE__, "Unable to read if ftrace is enabled");
+ handleException();
+ }
+
+ if (DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", "0") != 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to turn ftrace off before truncating the buffer");
+ handleException();
+ }
+
+ {
+ int fd;
+ fd = open("/sys/kernel/debug/tracing/trace", O_WRONLY | O_TRUNC | O_CLOEXEC, 0666);
+ if (fd < 0) {
+ logg->logError(__FILE__, __LINE__, "Unable truncate ftrace buffer: %s", strerror(errno));
+ handleException();
+ }
+ close(fd);
+ }
+
+ if (DriverSource::writeDriver("/sys/kernel/debug/tracing/trace_clock", "perf") != 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to switch ftrace to the perf clock, please ensure you are running Linux 3.10 or later");
+ handleException();
+ }
+
+ mFtraceFh = fopen_cloexec("/sys/kernel/debug/tracing/trace_pipe", "rb");
+ if (mFtraceFh == NULL) {
+ logg->logError(__FILE__, __LINE__, "Unable to open trace_pipe");
+ handleException();
+ }
+
+ return true;
+}
+
+void FtraceSource::run() {
+ prctl(PR_SET_NAME, (unsigned long)&"gatord-ftrace", 0, 0, 0);
+ mTid = syscall(__NR_gettid);
+
+ if (DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", "1") != 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to turn ftrace on");
+ handleException();
+ }
+
+ while (gSessionData->mSessionIsActive) {
+ char buf[1<<12];
+
+ if (fgets(buf, sizeof(buf), mFtraceFh) == NULL) {
+ if (errno == EINTR) {
+ // Interrupted by interrupt - likely user request to terminate
+ break;
+ }
+ logg->logError(__FILE__, __LINE__, "Unable read trace data: %s", strerror(errno));
+ handleException();
+ }
+
+ const uint64_t currTime = getTime();
+
+ char *const colon = strstr(buf, ": ");
+ if (colon == NULL) {
+ logg->logError(__FILE__, __LINE__, "Unable find colon: %s", buf);
+ handleException();
+ }
+ *colon = '\0';
+
+ char *const space = strrchr(buf, ' ');
+ if (space == NULL) {
+ logg->logError(__FILE__, __LINE__, "Unable find space: %s", buf);
+ handleException();
+ }
+ *colon = ':';
+
+ int64_t *data = NULL;
+ int count = gSessionData->ftraceDriver.read(colon + 2, &data);
+ if (count > 0) {
+ errno = 0;
+ const long long time = strtod(space, NULL) * 1000000000;
+ if (errno != 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to parse time: %s", strerror(errno));
+ handleException();
+ }
+ mBuffer.event64(-1, time);
+
+ for (int i = 0; i < count; ++i) {
+ mBuffer.event64(data[2*i + 0], data[2*i + 1]);
+ }
+
+ mBuffer.check(currTime);
+ }
+
+ }
+
+ mBuffer.setDone();
+
+ DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", mTracingOn);
+ fclose(mFtraceFh);
+ DriverSource::writeDriver("/sys/kernel/debug/tracing/trace_clock", "local");
+}
+
+void FtraceSource::interrupt() {
+ // Closing the underlying file handle does not result in the read on the ftrace file handle to return, so send a signal to the thread
+ syscall(__NR_tgkill, getpid(), mTid, SIGUSR1);
+}
+
+bool FtraceSource::isDone() {
+ return mBuffer.isDone();
+}
+
+void FtraceSource::write(Sender *sender) {
+ // Don't send ftrace data until the summary packet is sent so that monotonic delta is available
+ if (!gSessionData->mSentSummary) {
+ return;
+ }
+ if (!mBuffer.isDone()) {
+ mBuffer.write(sender);
+ }
+}
diff --git a/tools/gator/daemon/FtraceSource.h b/tools/gator/daemon/FtraceSource.h
new file mode 100644
index 0000000..2391b881
--- /dev/null
+++ b/tools/gator/daemon/FtraceSource.h
@@ -0,0 +1,43 @@
+/**
+ * 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.
+ */
+
+#ifndef FTRACESOURCE_H
+#define FTRACESOURCE_H
+
+#include <semaphore.h>
+#include <stdio.h>
+
+#include "Buffer.h"
+#include "Source.h"
+
+class FtraceSource : public Source {
+public:
+ FtraceSource(sem_t *senderSem);
+ ~FtraceSource();
+
+ bool prepare();
+ void run();
+ void interrupt();
+
+ bool isDone();
+ void write(Sender *sender);
+
+private:
+ void waitFor(const int bytes);
+
+ FILE *mFtraceFh;
+ Buffer mBuffer;
+ int mTid;
+ int mTracingOn;
+
+ // Intentionally unimplemented
+ FtraceSource(const FtraceSource &);
+ FtraceSource &operator=(const FtraceSource &);
+};
+
+#endif // FTRACESOURCE_H
diff --git a/tools/gator/daemon/Hwmon.h b/tools/gator/daemon/Hwmon.h
deleted file mode 100644
index a22a360..0000000
--- a/tools/gator/daemon/Hwmon.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef HWMON_H
-#define HWMON_H
-
-#include "Driver.h"
-
-class Buffer;
-class HwmonCounter;
-
-class Hwmon : public Driver {
-public:
- Hwmon();
- ~Hwmon();
-
- void setup();
-
- bool claimCounter(const Counter &counter) const;
- bool countersEnabled() const;
- void resetCounters();
- void setupCounter(Counter &counter);
-
- int writeCounters(mxml_node_t *root) const;
- void writeEvents(mxml_node_t *root) const;
-
- void start();
- void read(Buffer * buffer);
-
-private:
- HwmonCounter *findCounter(const Counter &counter) const;
-
- HwmonCounter *counters;
-
- // Intentionally unimplemented
- Hwmon(const Hwmon &);
- Hwmon &operator=(const Hwmon &);
-};
-
-#endif // HWMON_H
diff --git a/tools/gator/daemon/Hwmon.cpp b/tools/gator/daemon/HwmonDriver.cpp
index e444247..9d161ae 100644
--- a/tools/gator/daemon/Hwmon.cpp
+++ b/tools/gator/daemon/HwmonDriver.cpp
@@ -6,24 +6,33 @@
* published by the Free Software Foundation.
*/
-#include "Hwmon.h"
+#include "HwmonDriver.h"
#include "libsensors/sensors.h"
-#include "Buffer.h"
-#include "Counter.h"
#include "Logging.h"
-#include "SessionData.h"
-class HwmonCounter {
+// feature->type to input map
+static sensors_subfeature_type getInput(const sensors_feature_type type) {
+ switch (type) {
+ case SENSORS_FEATURE_IN: return SENSORS_SUBFEATURE_IN_INPUT;
+ case SENSORS_FEATURE_FAN: return SENSORS_SUBFEATURE_FAN_INPUT;
+ case SENSORS_FEATURE_TEMP: return SENSORS_SUBFEATURE_TEMP_INPUT;
+ case SENSORS_FEATURE_POWER: return SENSORS_SUBFEATURE_POWER_INPUT;
+ case SENSORS_FEATURE_ENERGY: return SENSORS_SUBFEATURE_ENERGY_INPUT;
+ case SENSORS_FEATURE_CURR: return SENSORS_SUBFEATURE_CURR_INPUT;
+ case SENSORS_FEATURE_HUMIDITY: return SENSORS_SUBFEATURE_HUMIDITY_INPUT;
+ default:
+ logg->logError(__FILE__, __LINE__, "Unsupported hwmon feature %i", type);
+ handleException();
+ }
+};
+
+class HwmonCounter : public DriverCounter {
public:
- HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, const sensors_feature *feature);
+ HwmonCounter(DriverCounter *next, char *const name, const sensors_chip_name *chip, const sensors_feature *feature);
~HwmonCounter();
- HwmonCounter *getNext() const { return next; }
- int getKey() const { return key; }
- bool isEnabled() const { return enabled; }
- const char *getName() const { return name; }
const char *getLabel() const { return label; }
const char *getTitle() const { return title; }
bool isDuplicate() const { return duplicate; }
@@ -32,63 +41,34 @@ public:
const char *getUnit() const { return unit; }
int getModifier() const { return modifier; }
- void setEnabled(const bool enabled) {
- this->enabled = enabled;
- // canRead will clear enabled if the counter is not readable
- canRead();
- }
-
- double read();
- bool canRead();
+ int64_t read();
private:
void init(const sensors_chip_name *chip, const sensors_feature *feature);
- HwmonCounter *const next;
- const int key;
- int polled : 1,
- readable : 1,
- enabled : 1,
- monotonic: 1,
- duplicate : 1;
-
const sensors_chip_name *chip;
const sensors_feature *feature;
-
- char *name;
char *label;
const char *title;
const char *display;
const char *counter_class;
const char *unit;
- int modifier;
double previous_value;
-
- sensors_subfeature_type input;
+ int modifier;
+ int monotonic: 1,
+ duplicate : 1;
// Intentionally unimplemented
HwmonCounter(const HwmonCounter &);
HwmonCounter &operator=(const HwmonCounter &);
};
-HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, const sensors_feature *feature) : next(next), key(getEventKey()), polled(false), readable(false), enabled(false), duplicate(false), chip(chip), feature(feature) {
-
- int len = sensors_snprintf_chip_name(NULL, 0, chip) + 1;
- char *chip_name = new char[len];
- sensors_snprintf_chip_name(chip_name, len, chip);
-
- len = snprintf(NULL, 0, "hwmon_%s_%d", chip_name, feature->number) + 1;
- name = new char[len];
- snprintf(name, len, "hwmon_%s_%d", chip_name, feature->number);
-
- delete [] chip_name;
-
+HwmonCounter::HwmonCounter(DriverCounter *next, char *const name, const sensors_chip_name *chip, const sensors_feature *feature) : DriverCounter(next, name), chip(chip), feature(feature), duplicate(false) {
label = sensors_get_label(chip, feature);
switch (feature->type) {
case SENSORS_FEATURE_IN:
title = "Voltage";
- input = SENSORS_SUBFEATURE_IN_INPUT;
display = "maximum";
counter_class = "absolute";
unit = "V";
@@ -97,7 +77,6 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
break;
case SENSORS_FEATURE_FAN:
title = "Fan";
- input = SENSORS_SUBFEATURE_FAN_INPUT;
display = "average";
counter_class = "absolute";
unit = "RPM";
@@ -106,7 +85,6 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
break;
case SENSORS_FEATURE_TEMP:
title = "Temperature";
- input = SENSORS_SUBFEATURE_TEMP_INPUT;
display = "maximum";
counter_class = "absolute";
unit = "°C";
@@ -115,7 +93,6 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
break;
case SENSORS_FEATURE_POWER:
title = "Power";
- input = SENSORS_SUBFEATURE_POWER_INPUT;
display = "maximum";
counter_class = "absolute";
unit = "W";
@@ -124,7 +101,6 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
break;
case SENSORS_FEATURE_ENERGY:
title = "Energy";
- input = SENSORS_SUBFEATURE_ENERGY_INPUT;
display = "accumulate";
counter_class = "delta";
unit = "J";
@@ -133,7 +109,6 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
break;
case SENSORS_FEATURE_CURR:
title = "Current";
- input = SENSORS_SUBFEATURE_CURR_INPUT;
display = "maximum";
counter_class = "absolute";
unit = "A";
@@ -142,7 +117,6 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
break;
case SENSORS_FEATURE_HUMIDITY:
title = "Humidity";
- input = SENSORS_SUBFEATURE_HUMIDITY_INPUT;
display = "average";
counter_class = "absolute";
unit = "%";
@@ -154,7 +128,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
handleException();
}
- for (HwmonCounter * counter = next; counter != NULL; counter = counter->getNext()) {
+ for (HwmonCounter * counter = static_cast<HwmonCounter *>(next); counter != NULL; counter = static_cast<HwmonCounter *>(counter->getNext())) {
if (strcmp(label, counter->getLabel()) == 0 && strcmp(title, counter->getTitle()) == 0) {
duplicate = true;
counter->duplicate = true;
@@ -165,16 +139,15 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
HwmonCounter::~HwmonCounter() {
free((void *)label);
- delete [] name;
}
-double HwmonCounter::read() {
+int64_t HwmonCounter::read() {
double value;
double result;
const sensors_subfeature *subfeature;
- // Keep in sync with canRead
- subfeature = sensors_get_subfeature(chip, feature, input);
+ // Keep in sync with the read check in HwmonDriver::readEvents
+ subfeature = sensors_get_subfeature(chip, feature, getInput(feature->type));
if (!subfeature) {
logg->logError(__FILE__, __LINE__, "No input value for hwmon sensor %s", label);
handleException();
@@ -191,46 +164,14 @@ double HwmonCounter::read() {
return result;
}
-bool HwmonCounter::canRead() {
- if (!polled) {
- double value;
- const sensors_subfeature *subfeature;
- bool result = true;
-
- subfeature = sensors_get_subfeature(chip, feature, input);
- if (!subfeature) {
- result = false;
- } else {
- result = sensors_get_value(chip, subfeature->number, &value) == 0;
- }
-
- polled = true;
- readable = result;
- }
-
- enabled &= readable;
-
- return readable;
-}
-
-Hwmon::Hwmon() : counters(NULL) {
+HwmonDriver::HwmonDriver() {
}
-Hwmon::~Hwmon() {
- while (counters != NULL) {
- HwmonCounter * counter = counters;
- counters = counter->getNext();
- delete counter;
- }
+HwmonDriver::~HwmonDriver() {
sensors_cleanup();
}
-void Hwmon::setup() {
- // hwmon does not currently work with perf
- if (gSessionData->perf.isSetup()) {
- return;
- }
-
+void HwmonDriver::readEvents(mxml_node_t *const) {
int err = sensors_init(NULL);
if (err) {
logg->logMessage("Failed to initialize libsensors! (%d)", err);
@@ -244,73 +185,34 @@ void Hwmon::setup() {
int feature_nr = 0;
const sensors_feature *feature;
while ((feature = sensors_get_features(chip, &feature_nr))) {
- counters = new HwmonCounter(counters, chip, feature);
+ // Keep in sync with HwmonCounter::read
+ // Can this counter be read?
+ double value;
+ const sensors_subfeature *const subfeature = sensors_get_subfeature(chip, feature, getInput(feature->type));
+ if ((subfeature == NULL) || (sensors_get_value(chip, subfeature->number, &value) != 0)) {
+ continue;
+ }
+
+ // Get the name of the counter
+ int len = sensors_snprintf_chip_name(NULL, 0, chip) + 1;
+ char *chip_name = new char[len];
+ sensors_snprintf_chip_name(chip_name, len, chip);
+ len = snprintf(NULL, 0, "hwmon_%s_%d_%d", chip_name, chip_nr, feature->number) + 1;
+ char *const name = new char[len];
+ snprintf(name, len, "hwmon_%s_%d_%d", chip_name, chip_nr, feature->number);
+ delete [] chip_name;
+
+ setCounters(new HwmonCounter(getCounters(), name, chip, feature));
}
}
}
-HwmonCounter *Hwmon::findCounter(const Counter &counter) const {
- for (HwmonCounter * hwmonCounter = counters; hwmonCounter != NULL; hwmonCounter = hwmonCounter->getNext()) {
- if (hwmonCounter->canRead() && strcmp(hwmonCounter->getName(), counter.getType()) == 0) {
- return hwmonCounter;
- }
- }
-
- return NULL;
-}
-
-bool Hwmon::claimCounter(const Counter &counter) const {
- return findCounter(counter) != NULL;
-}
-
-bool Hwmon::countersEnabled() const {
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (counter->isEnabled()) {
- return true;
- }
- }
- return false;
-}
-
-void Hwmon::resetCounters() {
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- counter->setEnabled(false);
- }
-}
-
-void Hwmon::setupCounter(Counter &counter) {
- HwmonCounter *const hwmonCounter = findCounter(counter);
- if (hwmonCounter == NULL) {
- counter.setEnabled(false);
- return;
- }
- hwmonCounter->setEnabled(true);
- counter.setKey(hwmonCounter->getKey());
-}
-
-int Hwmon::writeCounters(mxml_node_t *root) const {
- int count = 0;
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (!counter->canRead()) {
- continue;
- }
- mxml_node_t *node = mxmlNewElement(root, "counter");
- mxmlElementSetAttr(node, "name", counter->getName());
- ++count;
- }
-
- return count;
-}
-
-void Hwmon::writeEvents(mxml_node_t *root) const {
+void HwmonDriver::writeEvents(mxml_node_t *root) const {
root = mxmlNewElement(root, "category");
mxmlElementSetAttr(root, "name", "hwmon");
char buf[1024];
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (!counter->canRead()) {
- continue;
- }
+ for (HwmonCounter *counter = static_cast<HwmonCounter *>(getCounters()); counter != NULL; counter = static_cast<HwmonCounter *>(counter->getNext())) {
mxml_node_t *node = mxmlNewElement(root, "event");
mxmlElementSetAttr(node, "counter", counter->getName());
mxmlElementSetAttr(node, "title", counter->getTitle());
@@ -333,20 +235,11 @@ void Hwmon::writeEvents(mxml_node_t *root) const {
}
}
-void Hwmon::start() {
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
+void HwmonDriver::start() {
+ for (DriverCounter *counter = getCounters(); counter != NULL; counter = counter->getNext()) {
if (!counter->isEnabled()) {
continue;
}
counter->read();
}
}
-
-void Hwmon::read(Buffer * const buffer) {
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (!counter->isEnabled()) {
- continue;
- }
- buffer->event(counter->getKey(), counter->read());
- }
-}
diff --git a/tools/gator/daemon/HwmonDriver.h b/tools/gator/daemon/HwmonDriver.h
new file mode 100644
index 0000000..f28d825
--- /dev/null
+++ b/tools/gator/daemon/HwmonDriver.h
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef HWMONDRIVER_H
+#define HWMONDRIVER_H
+
+#include "Driver.h"
+
+class HwmonDriver : public PolledDriver {
+public:
+ HwmonDriver();
+ ~HwmonDriver();
+
+ void readEvents(mxml_node_t *const root);
+
+ void writeEvents(mxml_node_t *root) const;
+
+ void start();
+
+private:
+ // Intentionally unimplemented
+ HwmonDriver(const HwmonDriver &);
+ HwmonDriver &operator=(const HwmonDriver &);
+};
+
+#endif // HWMONDRIVER_H
diff --git a/tools/gator/daemon/KMod.cpp b/tools/gator/daemon/KMod.cpp
index 73e123d..fe9dc6a 100644
--- a/tools/gator/daemon/KMod.cpp
+++ b/tools/gator/daemon/KMod.cpp
@@ -16,6 +16,7 @@
#include "Counter.h"
#include "DriverSource.h"
#include "Logging.h"
+#include "SessionData.h"
// Claim all the counters in /dev/gator/events
bool KMod::claimCounter(const Counter &counter) const {
@@ -46,11 +47,19 @@ void KMod::resetCounters() {
}
}
+static const char ARM_MALI_MIDGARD[] = "ARM_Mali-Midgard_";
+static const char ARM_MALI_T[] = "ARM_Mali-T";
+
void KMod::setupCounter(Counter &counter) {
char base[128];
char text[128];
snprintf(base, sizeof(base), "/dev/gator/events/%s", counter.getType());
+ if ((strncmp(counter.getType(), ARM_MALI_MIDGARD, sizeof(ARM_MALI_MIDGARD) - 1) == 0 ||
+ strncmp(counter.getType(), ARM_MALI_T, sizeof(ARM_MALI_T) - 1) == 0)) {
+ mIsMaliCapture = true;
+ }
+
snprintf(text, sizeof(text), "%s/enabled", base);
int enabled = true;
if (DriverSource::writeReadDriver(text, &enabled) || !enabled) {
diff --git a/tools/gator/daemon/KMod.h b/tools/gator/daemon/KMod.h
index fb7fc8a..900a60e 100644
--- a/tools/gator/daemon/KMod.h
+++ b/tools/gator/daemon/KMod.h
@@ -14,7 +14,7 @@
// Driver for the gator kernel module
class KMod : public Driver {
public:
- KMod() {}
+ KMod() : mIsMaliCapture(false) {}
~KMod() {}
bool claimCounter(const Counter &counter) const;
@@ -22,6 +22,11 @@ public:
void setupCounter(Counter &counter);
int writeCounters(mxml_node_t *root) const;
+
+ bool isMaliCapture() const { return mIsMaliCapture; }
+
+private:
+ bool mIsMaliCapture;
};
#endif // KMOD_H
diff --git a/tools/gator/daemon/LocalCapture.h b/tools/gator/daemon/LocalCapture.h
index b1e7219..25d281f 100644
--- a/tools/gator/daemon/LocalCapture.h
+++ b/tools/gator/daemon/LocalCapture.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __LOCAL_CAPTURE_H__
-#define __LOCAL_CAPTURE_H__
+#ifndef __LOCAL_CAPTURE_H__
+#define __LOCAL_CAPTURE_H__
struct ImageLinkList;
diff --git a/tools/gator/daemon/Logging.cpp b/tools/gator/daemon/Logging.cpp
index b8d3178..41ffa1a 100644
--- a/tools/gator/daemon/Logging.cpp
+++ b/tools/gator/daemon/Logging.cpp
@@ -14,15 +14,15 @@
#include <string.h>
#ifdef WIN32
-#define MUTEX_INIT() mLoggingMutex = CreateMutex(NULL, false, NULL);
-#define MUTEX_LOCK() WaitForSingleObject(mLoggingMutex, 0xFFFFFFFF);
-#define MUTEX_UNLOCK() ReleaseMutex(mLoggingMutex);
-#define snprintf _snprintf
+#define MUTEX_INIT() mLoggingMutex = CreateMutex(NULL, false, NULL);
+#define MUTEX_LOCK() WaitForSingleObject(mLoggingMutex, 0xFFFFFFFF);
+#define MUTEX_UNLOCK() ReleaseMutex(mLoggingMutex);
+#define snprintf _snprintf
#else
#include <pthread.h>
-#define MUTEX_INIT() pthread_mutex_init(&mLoggingMutex, NULL)
-#define MUTEX_LOCK() pthread_mutex_lock(&mLoggingMutex)
-#define MUTEX_UNLOCK() pthread_mutex_unlock(&mLoggingMutex)
+#define MUTEX_INIT() pthread_mutex_init(&mLoggingMutex, NULL)
+#define MUTEX_LOCK() pthread_mutex_lock(&mLoggingMutex)
+#define MUTEX_UNLOCK() pthread_mutex_unlock(&mLoggingMutex)
#endif
// Global thread-safe logging
@@ -40,7 +40,7 @@ Logging::~Logging() {
}
void Logging::logError(const char* file, int line, const char* fmt, ...) {
- va_list args;
+ va_list args;
MUTEX_LOCK();
if (mDebug) {
@@ -61,7 +61,7 @@ void Logging::logError(const char* file, int line, const char* fmt, ...) {
void Logging::logMessage(const char* fmt, ...) {
if (mDebug) {
- va_list args;
+ va_list args;
MUTEX_LOCK();
strcpy(mLogBuf, "INFO: ");
diff --git a/tools/gator/daemon/Logging.h b/tools/gator/daemon/Logging.h
index 4934bb0..09e93ff 100644
--- a/tools/gator/daemon/Logging.h
+++ b/tools/gator/daemon/Logging.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __LOGGING_H__
-#define __LOGGING_H__
+#ifndef __LOGGING_H__
+#define __LOGGING_H__
#include <pthread.h>
@@ -23,10 +23,10 @@ public:
char* getLastMessage() {return mLogBuf;}
private:
- char mErrBuf[4096]; // Arbitrarily large buffer to hold a string
- char mLogBuf[4096]; // Arbitrarily large buffer to hold a string
- bool mDebug;
- pthread_mutex_t mLoggingMutex;
+ char mErrBuf[4096]; // Arbitrarily large buffer to hold a string
+ char mLogBuf[4096]; // Arbitrarily large buffer to hold a string
+ bool mDebug;
+ pthread_mutex_t mLoggingMutex;
};
extern Logging* logg;
diff --git a/tools/gator/daemon/Makefile b/tools/gator/daemon/Makefile
index 2ed49fd..27531b4 100644
--- a/tools/gator/daemon/Makefile
+++ b/tools/gator/daemon/Makefile
@@ -11,11 +11,8 @@
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
-# -mthumb-interwork is required for interworking to ARM or Thumb stdlibc
-CPPFLAGS += -mthumb-interwork
-
ifeq ($(SOFTFLOAT),1)
- CPPFLAGS += -marm -march=armv4t -mfloat-abi=soft
+ CPPFLAGS += -marm -mthumb-interwork -march=armv4t -mfloat-abi=soft
LDFLAGS += -marm -march=armv4t -mfloat-abi=soft
endif
ifneq ($(SYSROOT),)
diff --git a/tools/gator/daemon/MaliVideoDriver.cpp b/tools/gator/daemon/MaliVideoDriver.cpp
index 18b413b..5eef264 100644
--- a/tools/gator/daemon/MaliVideoDriver.cpp
+++ b/tools/gator/daemon/MaliVideoDriver.cpp
@@ -34,51 +34,30 @@ 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 {
+class MaliVideoCounter : public DriverCounter {
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(DriverCounter *next, const char *name, const MaliVideoCounterType type, const int id) : DriverCounter(next, name), mType(type), mId(id) {
}
~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() {
}
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;
- }
-
+void MaliVideoDriver::readEvents(mxml_node_t *const xml) {
mxml_node_t *node = xml;
while (true) {
node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
@@ -90,62 +69,15 @@ void MaliVideoDriver::setup(mxml_node_t *const xml) {
// 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);
+ setCounters(new MaliVideoCounter(getCounters(), 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;
+ setCounters(new MaliVideoCounter(getCounters(), strdup(counter), MVCT_EVENT, i));
+ } else if (strncmp(counter, ACTIVITY, sizeof(ACTIVITY) - 1) == 0) {
+ const int i = strtol(counter + sizeof(ACTIVITY) - 1, NULL, 10);
+ setCounters(new MaliVideoCounter(getCounters(), strdup(counter), MVCT_ACTIVITY, i));
}
}
- 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 {
@@ -153,32 +85,39 @@ int MaliVideoDriver::writeCounters(mxml_node_t *root) const {
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;
+ return super::writeCounters(root);
}
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()) {
+ for (MaliVideoCounter *counter = static_cast<MaliVideoCounter *>(getCounters()); counter != NULL; counter = static_cast<MaliVideoCounter *>(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()) {
+ for (MaliVideoCounter *counter = static_cast<MaliVideoCounter *>(getCounters()); counter != NULL; counter = static_cast<MaliVideoCounter *>(counter->getNext())) {
if (counter->isEnabled() && (counter->getType() == type)) {
Buffer::packInt(buf, bufsize, pos, counter->getId());
}
}
}
+static bool writeAll(const int mveUds, const char *const buf, const int pos) {
+ 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;
+}
+
bool MaliVideoDriver::start(const int mveUds) {
char buf[256];
int pos = 0;
@@ -225,29 +164,28 @@ bool MaliVideoDriver::start(const int mveUds) {
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);
- }
- */
+ marshalEnable(MVCT_ACTIVITY, buf, sizeof(buf), pos);
- 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 writeAll(mveUds, buf, pos);
+}
- return true;
+void MaliVideoDriver::stop(const int mveUds) {
+ char buf[8];
+ int pos = 0;
+
+ // code - MVE_INSTR_STOP
+ buf[pos++] = 'S';
+ buf[pos++] = 'T';
+ buf[pos++] = 'O';
+ buf[pos++] = 'P';
+ marshalEnable(MVCT_COUNTER, buf, sizeof(buf), pos);
+
+ writeAll(mveUds, buf, pos);
+
+ close(mveUds);
}
diff --git a/tools/gator/daemon/MaliVideoDriver.h b/tools/gator/daemon/MaliVideoDriver.h
index 00cb808..204a57a 100644
--- a/tools/gator/daemon/MaliVideoDriver.h
+++ b/tools/gator/daemon/MaliVideoDriver.h
@@ -19,29 +19,24 @@ enum MaliVideoCounterType {
MVCT_ACTIVITY,
};
-class MaliVideoDriver : public Driver {
+class MaliVideoDriver : public SimpleDriver {
+private:
+ typedef SimpleDriver super;
+
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);
+ void readEvents(mxml_node_t *const root);
int writeCounters(mxml_node_t *root) const;
bool start(const int mveUds);
+ void stop(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 &);
diff --git a/tools/gator/daemon/MemInfoDriver.cpp b/tools/gator/daemon/MemInfoDriver.cpp
new file mode 100644
index 0000000..cce15c1
--- /dev/null
+++ b/tools/gator/daemon/MemInfoDriver.cpp
@@ -0,0 +1,93 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "MemInfoDriver.h"
+
+#include "Logging.h"
+#include "SessionData.h"
+
+class MemInfoCounter : public DriverCounter {
+public:
+ MemInfoCounter(DriverCounter *next, char *const name, int64_t *const value);
+ ~MemInfoCounter();
+
+ int64_t read();
+
+private:
+ int64_t *const mValue;
+
+ // Intentionally unimplemented
+ MemInfoCounter(const MemInfoCounter &);
+ MemInfoCounter &operator=(const MemInfoCounter &);
+};
+
+MemInfoCounter::MemInfoCounter(DriverCounter *next, char *const name, int64_t *const value) : DriverCounter(next, name), mValue(value) {
+}
+
+MemInfoCounter::~MemInfoCounter() {
+}
+
+int64_t MemInfoCounter::read() {
+ return *mValue;
+}
+
+MemInfoDriver::MemInfoDriver() : mBuf(), mMemUsed(0), mMemFree(0), mBuffers(0) {
+}
+
+MemInfoDriver::~MemInfoDriver() {
+}
+
+void MemInfoDriver::readEvents(mxml_node_t *const) {
+ // Only for use with perf
+ if (!gSessionData->perf.isSetup()) {
+ return;
+ }
+
+ setCounters(new MemInfoCounter(getCounters(), strdup("Linux_meminfo_memused2"), &mMemUsed));
+ setCounters(new MemInfoCounter(getCounters(), strdup("Linux_meminfo_memfree"), &mMemFree));
+ setCounters(new MemInfoCounter(getCounters(), strdup("Linux_meminfo_bufferram"), &mBuffers));
+}
+
+void MemInfoDriver::read(Buffer *const buffer) {
+ if (!countersEnabled()) {
+ return;
+ }
+
+ if (!mBuf.read("/proc/meminfo")) {
+ logg->logError(__FILE__, __LINE__, "Failed to read /proc/meminfo");
+ handleException();
+ }
+
+ char *key = mBuf.getBuf();
+ char *colon;
+ int64_t memTotal = 0;
+ while ((colon = strchr(key, ':')) != NULL) {
+ char *end = strchr(colon + 1, '\n');
+ if (end != NULL) {
+ *end = '\0';
+ }
+ *colon = '\0';
+
+ if (strcmp(key, "MemTotal") == 0) {
+ memTotal = strtoll(colon + 1, NULL, 10) << 10;
+ } else if (strcmp(key, "MemFree") == 0) {
+ mMemFree = strtoll(colon + 1, NULL, 10) << 10;
+ } else if (strcmp(key, "Buffers") == 0) {
+ mBuffers = strtoll(colon + 1, NULL, 10) << 10;
+ }
+
+ if (end == NULL) {
+ break;
+ }
+ key = end + 1;
+ }
+
+ mMemUsed = memTotal - mMemFree;
+
+ super::read(buffer);
+}
diff --git a/tools/gator/daemon/MemInfoDriver.h b/tools/gator/daemon/MemInfoDriver.h
new file mode 100644
index 0000000..eb1b041
--- /dev/null
+++ b/tools/gator/daemon/MemInfoDriver.h
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MEMINFODRIVER_H
+#define MEMINFODRIVER_H
+
+#include "Driver.h"
+#include "DynBuf.h"
+
+class MemInfoDriver : public PolledDriver {
+private:
+ typedef PolledDriver super;
+
+public:
+ MemInfoDriver();
+ ~MemInfoDriver();
+
+ void readEvents(mxml_node_t *const root);
+ void read(Buffer *const buffer);
+
+private:
+ DynBuf mBuf;
+ int64_t mMemUsed;
+ int64_t mMemFree;
+ int64_t mBuffers;
+
+ // Intentionally unimplemented
+ MemInfoDriver(const MemInfoDriver &);
+ MemInfoDriver &operator=(const MemInfoDriver &);
+};
+
+#endif // MEMINFODRIVER_H
diff --git a/tools/gator/daemon/Monitor.cpp b/tools/gator/daemon/Monitor.cpp
index b34a15f..74f22ee 100644
--- a/tools/gator/daemon/Monitor.cpp
+++ b/tools/gator/daemon/Monitor.cpp
@@ -9,6 +9,7 @@
#include "Monitor.h"
#include <errno.h>
+#include <fcntl.h>
#include <string.h>
#include <unistd.h>
@@ -31,12 +32,25 @@ void Monitor::close() {
}
bool Monitor::init() {
+#ifdef EPOLL_CLOEXEC
+ mFd = epoll_create1(EPOLL_CLOEXEC);
+#else
mFd = epoll_create(16);
+#endif
if (mFd < 0) {
logg->logMessage("%s(%s:%i): epoll_create1 failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
+#ifndef EPOLL_CLOEXEC
+ int fdf = fcntl(mFd, F_GETFD);
+ if ((fdf == -1) || (fcntl(mFd, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
+ logg->logMessage("%s(%s:%i): fcntl failed", __FUNCTION__, __FILE__, __LINE__);
+ ::close(mFd);
+ return -1;
+ }
+#endif
+
return true;
}
diff --git a/tools/gator/daemon/NetDriver.cpp b/tools/gator/daemon/NetDriver.cpp
new file mode 100644
index 0000000..e75c069
--- /dev/null
+++ b/tools/gator/daemon/NetDriver.cpp
@@ -0,0 +1,129 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+// Define to get format macros from inttypes.h
+#define __STDC_FORMAT_MACROS
+
+#include "NetDriver.h"
+
+#include <inttypes.h>
+
+#include "Logging.h"
+#include "SessionData.h"
+
+class NetCounter : public DriverCounter {
+public:
+ NetCounter(DriverCounter *next, char *const name, int64_t *const value);
+ ~NetCounter();
+
+ int64_t read();
+
+private:
+ int64_t *const mValue;
+ int64_t mPrev;
+
+ // Intentionally unimplemented
+ NetCounter(const NetCounter &);
+ NetCounter &operator=(const NetCounter &);
+};
+
+NetCounter::NetCounter(DriverCounter *next, char *const name, int64_t *const value) : DriverCounter(next, name), mValue(value), mPrev(0) {
+}
+
+NetCounter::~NetCounter() {
+}
+
+int64_t NetCounter::read() {
+ int64_t result = *mValue - mPrev;
+ mPrev = *mValue;
+ return result;
+}
+
+NetDriver::NetDriver() : mBuf(), mReceiveBytes(0), mTransmitBytes(0) {
+}
+
+NetDriver::~NetDriver() {
+}
+
+void NetDriver::readEvents(mxml_node_t *const) {
+ // Only for use with perf
+ if (!gSessionData->perf.isSetup()) {
+ return;
+ }
+
+ setCounters(new NetCounter(getCounters(), strdup("Linux_net_rx"), &mReceiveBytes));
+ setCounters(new NetCounter(getCounters(), strdup("Linux_net_tx"), &mTransmitBytes));
+}
+
+bool NetDriver::doRead() {
+ if (!countersEnabled()) {
+ return true;
+ }
+
+ if (!mBuf.read("/proc/net/dev")) {
+ return false;
+ }
+
+ // Skip the header
+ char *key;
+ if (((key = strchr(mBuf.getBuf(), '\n')) == NULL) ||
+ ((key = strchr(key + 1, '\n')) == NULL)) {
+ return false;
+ }
+ key = key + 1;
+
+ mReceiveBytes = 0;
+ mTransmitBytes = 0;
+
+ char *colon;
+ while ((colon = strchr(key, ':')) != NULL) {
+ char *end = strchr(colon + 1, '\n');
+ if (end != NULL) {
+ *end = '\0';
+ }
+ *colon = '\0';
+
+ int64_t receiveBytes;
+ int64_t transmitBytes;
+ const int count = sscanf(colon + 1, " %" SCNu64 " %*u %*u %*u %*u %*u %*u %*u %" SCNu64, &receiveBytes, &transmitBytes);
+ if (count != 2) {
+ return false;
+ }
+ mReceiveBytes += receiveBytes;
+ mTransmitBytes += transmitBytes;
+
+ if (end == NULL) {
+ break;
+ }
+ key = end + 1;
+ }
+
+ return true;
+}
+
+void NetDriver::start() {
+ if (!doRead()) {
+ logg->logError(__FILE__, __LINE__, "Unable to read network stats");
+ handleException();
+ }
+ // Initialize previous values
+ for (DriverCounter *counter = getCounters(); counter != NULL; counter = counter->getNext()) {
+ if (!counter->isEnabled()) {
+ continue;
+ }
+ counter->read();
+ }
+}
+
+void NetDriver::read(Buffer *const buffer) {
+ if (!doRead()) {
+ logg->logError(__FILE__, __LINE__, "Unable to read network stats");
+ handleException();
+ }
+ super::read(buffer);
+}
diff --git a/tools/gator/daemon/NetDriver.h b/tools/gator/daemon/NetDriver.h
new file mode 100644
index 0000000..50ff850
--- /dev/null
+++ b/tools/gator/daemon/NetDriver.h
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef NETDRIVER_H
+#define NETDRIVER_H
+
+#include "Driver.h"
+#include "DynBuf.h"
+
+class NetDriver : public PolledDriver {
+private:
+ typedef PolledDriver super;
+
+public:
+ NetDriver();
+ ~NetDriver();
+
+ void readEvents(mxml_node_t *const root);
+ void start();
+ void read(Buffer *const buffer);
+
+private:
+ bool doRead();
+
+ DynBuf mBuf;
+ int64_t mReceiveBytes;
+ int64_t mTransmitBytes;
+
+ // Intentionally unimplemented
+ NetDriver(const NetDriver &);
+ NetDriver &operator=(const NetDriver &);
+};
+
+#endif // NETDRIVER_H
diff --git a/tools/gator/daemon/OlySocket.cpp b/tools/gator/daemon/OlySocket.cpp
index 28774e3..aa0ce49 100644
--- a/tools/gator/daemon/OlySocket.cpp
+++ b/tools/gator/daemon/OlySocket.cpp
@@ -15,10 +15,10 @@
#include <ws2tcpip.h>
#else
#include <netinet/in.h>
-#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <netdb.h>
+#include <fcntl.h>
#endif
#include "Logging.h"
@@ -32,6 +32,48 @@
#define SHUTDOWN_RX_TX SHUT_RDWR
#endif
+int socket_cloexec(int domain, int type, int protocol) {
+#ifdef SOCK_CLOEXEC
+ return socket(domain, type | SOCK_CLOEXEC, protocol);
+#else
+ int sock = socket(domain, type, protocol);
+#ifdef FD_CLOEXEC
+ if (sock < 0) {
+ return -1;
+ }
+ int fdf = fcntl(sock, F_GETFD);
+ if ((fdf == -1) || (fcntl(sock, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
+ close(sock);
+ return -1;
+ }
+#endif
+ return sock;
+#endif
+}
+
+int accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
+ int sock;
+#ifdef SOCK_CLOEXEC
+ sock = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
+ if (sock >= 0) {
+ return sock;
+ }
+ // accept4 with SOCK_CLOEXEC may not work on all kernels, so fallback
+#endif
+ sock = accept(sockfd, addr, addrlen);
+#ifdef FD_CLOEXEC
+ if (sock < 0) {
+ return -1;
+ }
+ int fdf = fcntl(sock, F_GETFD);
+ if ((fdf == -1) || (fcntl(sock, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
+ close(sock);
+ return -1;
+ }
+#endif
+ return sock;
+}
+
OlyServerSocket::OlyServerSocket(int port) {
#ifdef WIN32
WSADATA wsaData;
@@ -57,7 +99,7 @@ OlySocket::OlySocket(int socketID) : mSocketID(socketID) {
OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize) {
// Create socket
- mFDServer = socket(PF_UNIX, SOCK_STREAM, 0);
+ mFDServer = socket_cloexec(PF_UNIX, SOCK_STREAM, 0);
if (mFDServer < 0) {
logg->logError(__FILE__, __LINE__, "Error creating server socket");
handleException();
@@ -84,7 +126,7 @@ OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize) {
}
int OlySocket::connect(const char* path, const size_t pathSize) {
- int fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ int fd = socket_cloexec(PF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
return -1;
}
@@ -143,10 +185,10 @@ void OlyServerSocket::createServerSocket(int port) {
int family = AF_INET6;
// Create socket
- mFDServer = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ mFDServer = socket_cloexec(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (mFDServer < 0) {
family = AF_INET;
- mFDServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ mFDServer = socket_cloexec(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (mFDServer < 0) {
logg->logError(__FILE__, __LINE__, "Error creating server socket");
handleException();
@@ -190,7 +232,7 @@ int OlyServerSocket::acceptConnection() {
}
// Accept a connection, note that this call blocks until a client connects
- socketID = accept(mFDServer, NULL, NULL);
+ socketID = accept_cloexec(mFDServer, NULL, NULL);
if (socketID < 0) {
logg->logError(__FILE__, __LINE__, "Socket acceptance failed");
handleException();
diff --git a/tools/gator/daemon/OlySocket.h b/tools/gator/daemon/OlySocket.h
index 20c67cc..6b53b01 100644
--- a/tools/gator/daemon/OlySocket.h
+++ b/tools/gator/daemon/OlySocket.h
@@ -11,6 +11,12 @@
#include <stddef.h>
+#ifdef WIN32
+typedef socklen_t int;
+#else
+#include <sys/socket.h>
+#endif
+
class OlySocket {
public:
#ifndef WIN32
@@ -52,4 +58,7 @@ private:
void createServerSocket(int port);
};
+int socket_cloexec(int domain, int type, int protocol);
+int accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
#endif //__OLY_SOCKET_H__
diff --git a/tools/gator/daemon/PerfBuffer.cpp b/tools/gator/daemon/PerfBuffer.cpp
index 5fad583..f127c99 100644
--- a/tools/gator/daemon/PerfBuffer.cpp
+++ b/tools/gator/daemon/PerfBuffer.cpp
@@ -20,6 +20,7 @@ PerfBuffer::PerfBuffer() {
for (int cpu = 0; cpu < ARRAY_LENGTH(mBuf); ++cpu) {
mBuf[cpu] = MAP_FAILED;
mDiscard[cpu] = false;
+ mFds[cpu] = -1;
}
}
@@ -31,8 +32,8 @@ PerfBuffer::~PerfBuffer() {
}
}
-bool PerfBuffer::useFd(const int cpu, const int fd, const int groupFd) {
- if (fd == groupFd) {
+bool PerfBuffer::useFd(const int cpu, const int fd) {
+ if (mFds[cpu] < 0) {
if (mBuf[cpu] != MAP_FAILED) {
logg->logMessage("%s(%s:%i): cpu %i already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__, cpu);
return false;
@@ -44,6 +45,7 @@ bool PerfBuffer::useFd(const int cpu, const int fd, const int groupFd) {
logg->logMessage("%s(%s:%i): mmap failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
+ mFds[cpu] = fd;
// Check the version
struct perf_event_mmap_page *pemp = static_cast<struct perf_event_mmap_page *>(mBuf[cpu]);
@@ -57,7 +59,7 @@ bool PerfBuffer::useFd(const int cpu, const int fd, const int groupFd) {
return false;
}
- if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, groupFd) < 0) {
+ if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, mFds[cpu]) < 0) {
logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
@@ -89,6 +91,41 @@ bool PerfBuffer::isEmpty() {
return true;
}
+static void compressAndSend(const int cpu, const __u64 head, __u64 tail, const uint8_t *const b, Sender *const sender) {
+ // Pick a big size but something smaller than the chunkSize in Sender::writeData which is 100k
+ char buf[1<<16];
+ int writePos = 0;
+ const int typeLength = gSessionData->mLocalCapture ? 0 : 1;
+
+ while (head > tail) {
+ writePos = 0;
+ if (!gSessionData->mLocalCapture) {
+ buf[writePos++] = RESPONSE_APC_DATA;
+ }
+ // Reserve space for size
+ writePos += sizeof(uint32_t);
+ Buffer::packInt(buf, sizeof(buf), writePos, FRAME_PERF);
+ Buffer::packInt(buf, sizeof(buf), writePos, cpu);
+
+ while (head > tail) {
+ const int count = reinterpret_cast<const struct perf_event_header *>(b + (tail & BUF_MASK))->size/sizeof(uint64_t);
+ // Can this whole message be written as Streamline assumes events are not split between frames
+ if (sizeof(buf) <= writePos + count*Buffer::MAXSIZE_PACK64) {
+ break;
+ }
+ for (int i = 0; i < count; ++i) {
+ // Must account for message size
+ Buffer::packInt64(buf, sizeof(buf), writePos, *reinterpret_cast<const uint64_t *>(b + (tail & BUF_MASK)));
+ tail += sizeof(uint64_t);
+ }
+ }
+
+ // Write size
+ Buffer::writeLEInt(reinterpret_cast<unsigned char *>(buf + typeLength), writePos - typeLength - sizeof(uint32_t));
+ sender->writeData(buf, writePos, RESPONSE_APC_DATA);
+ }
+}
+
bool PerfBuffer::send(Sender *const sender) {
for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
if (mBuf[cpu] == MAP_FAILED) {
@@ -102,26 +139,7 @@ bool PerfBuffer::send(Sender *const sender) {
if (head > tail) {
const uint8_t *const b = static_cast<uint8_t *>(mBuf[cpu]) + gSessionData->mPageSize;
- const int offset = gSessionData->mLocalCapture ? 1 : 0;
- unsigned char header[7];
- header[0] = RESPONSE_APC_DATA;
- Buffer::writeLEInt(header + 1, head - tail + sizeof(header) - 5);
- // Should use real packing functions
- header[5] = FRAME_PERF;
- header[6] = cpu;
-
- // Write header
- sender->writeData(reinterpret_cast<const char *>(&header) + offset, sizeof(header) - offset, RESPONSE_APC_DATA);
-
- // Write data
- if ((head & ~BUF_MASK) == (tail & ~BUF_MASK)) {
- // Not wrapped
- sender->writeData(reinterpret_cast<const char *>(b + (tail & BUF_MASK)), head - tail, RESPONSE_APC_DATA);
- } else {
- // Wrapped
- sender->writeData(reinterpret_cast<const char *>(b + (tail & BUF_MASK)), BUF_SIZE - (tail & BUF_MASK), RESPONSE_APC_DATA);
- sender->writeData(reinterpret_cast<const char *>(b), head & BUF_MASK, RESPONSE_APC_DATA);
- }
+ compressAndSend(cpu, head, tail, b, sender);
// Update tail with the data read
pemp->data_tail = head;
@@ -131,6 +149,7 @@ bool PerfBuffer::send(Sender *const sender) {
munmap(mBuf[cpu], gSessionData->mPageSize + BUF_SIZE);
mBuf[cpu] = MAP_FAILED;
mDiscard[cpu] = false;
+ mFds[cpu] = -1;
logg->logMessage("%s(%s:%i): Unmaped cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu);
}
}
diff --git a/tools/gator/daemon/PerfBuffer.h b/tools/gator/daemon/PerfBuffer.h
index 278a3b9..25a10625 100644
--- a/tools/gator/daemon/PerfBuffer.h
+++ b/tools/gator/daemon/PerfBuffer.h
@@ -21,7 +21,7 @@ public:
PerfBuffer();
~PerfBuffer();
- bool useFd(const int cpu, const int fd, const int groupFd);
+ bool useFd(const int cpu, const int fd);
void discard(const int cpu);
bool isEmpty();
bool send(Sender *const sender);
@@ -30,6 +30,8 @@ private:
void *mBuf[NR_CPUS];
// After the buffer is flushed it should be unmaped
bool mDiscard[NR_CPUS];
+ // fd that corresponds to the mBuf
+ int mFds[NR_CPUS];
// Intentionally undefined
PerfBuffer(const PerfBuffer &);
diff --git a/tools/gator/daemon/PerfDriver.cpp b/tools/gator/daemon/PerfDriver.cpp
index ac97a07..ee90284 100644
--- a/tools/gator/daemon/PerfDriver.cpp
+++ b/tools/gator/daemon/PerfDriver.cpp
@@ -22,6 +22,7 @@
#include "Logging.h"
#include "PerfGroup.h"
#include "SessionData.h"
+#include "Setup.h"
#define PERF_DEVICES "/sys/bus/event_source/devices"
@@ -47,7 +48,6 @@ static const struct gator_cpu gator_cpus[] = {
{ 0xc07, "Cortex-A7", "ARMv7_Cortex_A7", 4 },
{ 0xc08, "Cortex-A8", "ARMv7_Cortex_A8", 4 },
{ 0xc09, "Cortex-A9", "ARMv7_Cortex_A9", 6 },
- { 0xc0d, "Cortex-A12", "ARMv7_Cortex_A12", 6 },
{ 0xc0f, "Cortex-A15", "ARMv7_Cortex_A15", 6 },
{ 0xc0e, "Cortex-A17", "ARMv7_Cortex_A17", 6 },
{ 0x00f, "Scorpion", "Scorpion", 4 },
@@ -64,68 +64,57 @@ 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;
+ // Perf PMU name
+ const char *const perfName;
+ // gatorfs event name
+ const char *const gatorName;
const int count;
};
static const struct uncore_counter uncore_counters[] = {
- { "CCI_400", 4 },
- { "CCI_400-r1", 4 },
+ { "CCI_400", "CCI_400", 4 },
+ { "CCI_400-r1", "CCI_400-r1", 4 },
+ { "ccn", "ARM_CCN_5XX", 8 },
};
-class PerfCounter {
+class PerfCounter : public DriverCounter {
public:
- 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(DriverCounter *next, const char *name, uint32_t type, uint64_t config, bool perCpu) : DriverCounter(next, name), mType(type), mCount(0), mConfig(config), mPerCpu(perCpu) {}
+
~PerfCounter() {
- delete [] mName;
}
- PerfCounter *getNext() const { return mNext; }
- const char *getName() const { return mName; }
uint32_t getType() const { return mType; }
int getCount() const { return mCount; }
void setCount(const int count) { mCount = count; }
- int getKey() const { return mKey; }
uint64_t getConfig() const { return mConfig; }
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;
- const char *const mName;
const uint32_t mType;
int mCount;
- const int mKey;
uint64_t mConfig;
- int mEnabled : 1,
- mPerCpu : 1;
+ bool mPerCpu;
};
-PerfDriver::PerfDriver() : mCounters(NULL), mIsSetup(false), mLegacySupport(false) {
+PerfDriver::PerfDriver() : mIsSetup(false), mLegacySupport(false) {
}
PerfDriver::~PerfDriver() {
- while (mCounters != NULL) {
- PerfCounter *counter = mCounters;
- mCounters = counter->getNext();
- delete counter;
- }
}
void PerfDriver::addCpuCounters(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, true);
+ setCounters(new PerfCounter(getCounters(), 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, true);
+ setCounters(new PerfCounter(getCounters(), name, type, -1, true));
}
}
@@ -133,40 +122,24 @@ void PerfDriver::addUncoreCounters(const char *const counterName, const int type
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);
+ setCounters(new PerfCounter(getCounters(), 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);
+ setCounters(new PerfCounter(getCounters(), name, type, -1, false));
}
}
-// From include/generated/uapi/linux/version.h
-#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-
bool PerfDriver::setup() {
// Check the kernel version
- struct utsname utsname;
- if (uname(&utsname) != 0) {
- logg->logMessage("%s(%s:%i): uname failed", __FUNCTION__, __FILE__, __LINE__);
+ int release[3];
+ if (!getLinuxVersion(release)) {
+ logg->logMessage("%s(%s:%i): getLinuxVersion failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
- int release[3] = { 0, 0, 0 };
- int part = 0;
- char *ch = utsname.release;
- while (*ch >= '0' && *ch <= '9' && part < ARRAY_LENGTH(release)) {
- release[part] = 10*release[part] + *ch - '0';
-
- ++ch;
- if (*ch == '.') {
- ++part;
- ++ch;
- }
- }
-
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;
@@ -174,7 +147,7 @@ bool PerfDriver::setup() {
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__);
+ logg->logMessage("%s(%s:%i): " EVENTS_PATH " does not exist, is CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER enabled?", __FUNCTION__, __FILE__, __LINE__);
return false;
}
@@ -189,12 +162,14 @@ bool PerfDriver::setup() {
struct dirent *dirent;
while ((dirent = readdir(dir)) != NULL) {
for (int i = 0; i < ARRAY_LENGTH(gator_cpus); ++i) {
+ const struct gator_cpu *const gator_cpu = &gator_cpus[i];
+
// Do the names match exactly?
- if (strcmp(dirent->d_name, gator_cpus[i].pmnc_name) != 0 &&
- // Do these names match but have the old vs new prefix?
- (strncmp(dirent->d_name, OLD_PMU_PREFIX, sizeof(OLD_PMU_PREFIX) - 1) != 0 ||
- strncmp(gator_cpus[i].pmnc_name, NEW_PMU_PREFIX, sizeof(NEW_PMU_PREFIX) - 1) != 0 ||
- strcmp(dirent->d_name + sizeof(OLD_PMU_PREFIX) - 1, gator_cpus[i].pmnc_name + sizeof(NEW_PMU_PREFIX) - 1) != 0)) {
+ if (strcasecmp(gator_cpu->pmnc_name, dirent->d_name) != 0 &&
+ // Do these names match but have the old vs new prefix?
+ ((strncasecmp(dirent->d_name, OLD_PMU_PREFIX, sizeof(OLD_PMU_PREFIX) - 1) != 0 ||
+ strncasecmp(gator_cpu->pmnc_name, NEW_PMU_PREFIX, sizeof(NEW_PMU_PREFIX) - 1) != 0 ||
+ strcasecmp(dirent->d_name + sizeof(OLD_PMU_PREFIX) - 1, gator_cpu->pmnc_name + sizeof(NEW_PMU_PREFIX) - 1) != 0))) {
continue;
}
@@ -206,11 +181,12 @@ bool PerfDriver::setup() {
}
foundCpu = true;
- addCpuCounters(gator_cpus[i].pmnc_name, type, gator_cpus[i].pmnc_counters);
+ logg->logMessage("Adding cpu counters for %s", gator_cpu->pmnc_name);
+ addCpuCounters(gator_cpu->pmnc_name, type, gator_cpu->pmnc_counters);
}
for (int i = 0; i < ARRAY_LENGTH(uncore_counters); ++i) {
- if (strcmp(dirent->d_name, uncore_counters[i].name) != 0) {
+ if (strcmp(dirent->d_name, uncore_counters[i].perfName) != 0) {
continue;
}
@@ -221,7 +197,8 @@ bool PerfDriver::setup() {
continue;
}
- addUncoreCounters(uncore_counters[i].name, type, uncore_counters[i].count);
+ logg->logMessage("Adding uncore counters for %s", uncore_counters[i].gatorName);
+ addUncoreCounters(uncore_counters[i].gatorName, type, uncore_counters[i].count);
}
}
closedir(dir);
@@ -234,6 +211,7 @@ bool PerfDriver::setup() {
}
foundCpu = true;
+ logg->logMessage("Adding cpu counters (based on cpuid) for %s", gator_cpus[i].pmnc_name);
addCpuCounters(gator_cpus[i].pmnc_name, PERF_TYPE_RAW, gator_cpus[i].pmnc_counters);
}
}
@@ -252,31 +230,20 @@ bool PerfDriver::setup() {
id = getTracepointId("irq/softirq_exit", &printb);
if (id >= 0) {
- mCounters = new PerfCounter(mCounters, "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id, true);
+ setCounters(new PerfCounter(getCounters(), "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, true);
+ setCounters(new PerfCounter(getCounters(), "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id, true));
}
- //Linux_block_rq_wr
- //Linux_block_rq_rd
- //Linux_net_rx
- //Linux_net_tx
-
id = getTracepointId(SCHED_SWITCH, &printb);
if (id >= 0) {
- mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, true);
+ setCounters(new PerfCounter(getCounters(), "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, true));
}
- //Linux_meminfo_memused
- //Linux_meminfo_memfree
- //Linux_meminfo_bufferram
- //Linux_power_cpu_freq
- //Linux_power_cpu_idle
-
- mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1, false);
+ setCounters(new PerfCounter(getCounters(), "Linux_cpu_wait_contention", TYPE_DERIVED, -1, false));
//Linux_cpu_wait_io
@@ -299,62 +266,48 @@ bool PerfDriver::summary(Buffer *const buffer) {
logg->logMessage("%s(%s:%i): clock_gettime failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
- const int64_t timestamp = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec;
+ const int64_t timestamp = (int64_t)ts.tv_sec * NS_PER_S + ts.tv_nsec;
- const int64_t uptime = getTime();
+ const uint64_t monotonicStarted = getTime();
+ gSessionData->mMonotonicStarted = monotonicStarted;
- buffer->summary(timestamp, uptime, 0, buf);
+ buffer->summary(monotonicStarted, timestamp, monotonicStarted, monotonicStarted, 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]) {
- break;
- }
- }
- if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) {
- buffer->coreName(i, gSessionData->mCpuIds[i], gator_cpus[j].core_name);
- } else {
- 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);
- }
+ coreName(monotonicStarted, buffer, i);
}
- buffer->commit(1);
+ buffer->commit(monotonicStarted);
return true;
}
-PerfCounter *PerfDriver::findCounter(const Counter &counter) const {
- for (PerfCounter * perfCounter = mCounters; perfCounter != NULL; perfCounter = perfCounter->getNext()) {
- if (strcmp(perfCounter->getName(), counter.getType()) == 0) {
- return perfCounter;
- }
+void PerfDriver::coreName(const uint32_t startTime, Buffer *const buffer, const int cpu) {
+ // Don't send information on a cpu we know nothing about
+ if (gSessionData->mCpuIds[cpu] == -1) {
+ return;
}
- return NULL;
-}
-
-bool PerfDriver::claimCounter(const Counter &counter) const {
- return findCounter(counter) != NULL;
-}
-
-void PerfDriver::resetCounters() {
- for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
- counter->setEnabled(false);
+ int j;
+ for (j = 0; j < ARRAY_LENGTH(gator_cpus); ++j) {
+ if (gator_cpus[j].cpuid == gSessionData->mCpuIds[cpu]) {
+ break;
+ }
+ }
+ if (gator_cpus[j].cpuid == gSessionData->mCpuIds[cpu]) {
+ buffer->coreName(startTime, cpu, gSessionData->mCpuIds[cpu], gator_cpus[j].core_name);
+ } else {
+ char buf[32];
+ if (gSessionData->mCpuIds[cpu] == -1) {
+ snprintf(buf, sizeof(buf), "Unknown");
+ } else {
+ snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[cpu]);
+ }
+ buffer->coreName(startTime, cpu, gSessionData->mCpuIds[cpu], buf);
}
}
void PerfDriver::setupCounter(Counter &counter) {
- PerfCounter *const perfCounter = findCounter(counter);
+ PerfCounter *const perfCounter = static_cast<PerfCounter *>(findCounter(counter));
if (perfCounter == NULL) {
counter.setEnabled(false);
return;
@@ -369,21 +322,10 @@ void PerfDriver::setupCounter(Counter &counter) {
counter.setKey(perfCounter->getKey());
}
-int PerfDriver::writeCounters(mxml_node_t *root) const {
- int count = 0;
- for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
- mxml_node_t *node = mxmlNewElement(root, "counter");
- mxmlElementSetAttr(node, "name", counter->getName());
- ++count;
- }
-
- return count;
-}
-
-bool PerfDriver::enable(PerfGroup *const group, Buffer *const buffer) const {
- for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
+bool PerfDriver::enable(const uint64_t currTime, PerfGroup *const group, Buffer *const buffer) const {
+ for (PerfCounter *counter = static_cast<PerfCounter *>(getCounters()); counter != NULL; counter = static_cast<PerfCounter *>(counter->getNext())) {
if (counter->isEnabled() && (counter->getType() != TYPE_DERIVED)) {
- 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)) {
+ if (!group->add(currTime, 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 2cae575..846203a 100644
--- a/tools/gator/daemon/PerfDriver.h
+++ b/tools/gator/daemon/PerfDriver.h
@@ -9,6 +9,8 @@
#ifndef PERFDRIVER_H
#define PERFDRIVER_H
+#include <stdint.h>
+
#include "Driver.h"
// If debugfs is not mounted at /sys/kernel/debug, update DEBUGFS_PATH
@@ -16,13 +18,13 @@
#define EVENTS_PATH DEBUGFS_PATH "/tracing/events"
#define SCHED_SWITCH "sched/sched_switch"
+#define CPU_IDLE "power/cpu_idle"
class Buffer;
class DynBuf;
-class PerfCounter;
class PerfGroup;
-class PerfDriver : public Driver {
+class PerfDriver : public SimpleDriver {
public:
PerfDriver();
~PerfDriver();
@@ -31,24 +33,19 @@ public:
bool setup();
bool summary(Buffer *const buffer);
+ void coreName(const uint32_t startTime, Buffer *const buffer, const int cpu);
bool isSetup() const { return mIsSetup; }
- bool claimCounter(const Counter &counter) const;
- void resetCounters();
void setupCounter(Counter &counter);
- int writeCounters(mxml_node_t *root) const;
-
- bool enable(PerfGroup *const group, Buffer *const buffer) const;
+ bool enable(const uint64_t currTime, 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;
diff --git a/tools/gator/daemon/PerfGroup.cpp b/tools/gator/daemon/PerfGroup.cpp
index 2a0239f..4fd960a 100644
--- a/tools/gator/daemon/PerfGroup.cpp
+++ b/tools/gator/daemon/PerfGroup.cpp
@@ -9,6 +9,7 @@
#include "PerfGroup.h"
#include <errno.h>
+#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
@@ -33,10 +34,19 @@
/* have a sampling interrupt happen when we cross the wakeup_watermark boundary */ \
pea.watermark = 1; \
/* Be conservative in flush size as only one buffer set is monitored */ \
- pea.wakeup_watermark = 3 * BUF_SIZE / 4
+ pea.wakeup_watermark = BUF_SIZE / 2
static int sys_perf_event_open(struct perf_event_attr *const attr, const pid_t pid, const int cpu, const int group_fd, const unsigned long flags) {
- return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
+ int fd = syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
+ if (fd < 0) {
+ return -1;
+ }
+ int fdf = fcntl(fd, F_GETFD);
+ if ((fdf == -1) || (fcntl(fd, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
+ close(fd);
+ return -1;
+ }
+ return fd;
}
PerfGroup::PerfGroup(PerfBuffer *const pb) : mPb(pb) {
@@ -54,7 +64,7 @@ PerfGroup::~PerfGroup() {
}
}
-bool PerfGroup::add(Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags) {
+bool PerfGroup::add(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags) {
int i;
for (i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
if (mKeys[i] < 0) {
@@ -82,12 +92,12 @@ bool PerfGroup::add(Buffer *const buffer, const int key, const __u32 type, const
mKeys[i] = key;
- buffer->pea(&mAttrs[i], key);
+ buffer->pea(currTime, &mAttrs[i], key);
return true;
}
-bool PerfGroup::prepareCPU(const int cpu) {
+int PerfGroup::prepareCPU(const int cpu, Monitor *const monitor) {
logg->logMessage("%s(%s:%i): Onlining cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu);
for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
@@ -102,26 +112,35 @@ bool PerfGroup::prepareCPU(const int cpu) {
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;
+ return PG_FAILURE;
}
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));
+ if (errno == ENODEV) {
+ return PG_CPU_OFFLINE;
+ }
continue;
}
- if (!mPb->useFd(cpu, mFds[cpu + offset], mFds[cpu])) {
+ if (!mPb->useFd(cpu, mFds[cpu + offset])) {
logg->logMessage("%s(%s:%i): PerfBuffer::useFd failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
+ return PG_FAILURE;
+ }
+
+
+ if (!monitor->add(mFds[cpu + offset])) {
+ logg->logMessage("%s(%s:%i): Monitor::add failed", __FUNCTION__, __FILE__, __LINE__);
+ return PG_FAILURE;
}
}
- return true;
+ return PG_SUCCESS;
}
-int PerfGroup::onlineCPU(const int cpu, const bool start, Buffer *const buffer, Monitor *const monitor) {
+int PerfGroup::onlineCPU(const uint64_t currTime, const int cpu, const bool start, Buffer *const buffer) {
__u64 ids[ARRAY_LENGTH(mKeys)];
int coreKeys[ARRAY_LENGTH(mKeys)];
int idCount = 0;
@@ -137,38 +156,37 @@ int PerfGroup::onlineCPU(const int cpu, const bool start, Buffer *const buffer,
// 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;
+ return 0;
}
++idCount;
}
- if (!monitor->add(mFds[cpu])) {
- logg->logMessage("%s(%s:%i): Monitor::add failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
if (!gSessionData->perf.getLegacySupport()) {
- buffer->keys(idCount, ids, coreKeys);
+ buffer->keys(currTime, 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;
+ return 0;
}
- buffer->keysOld(idCount, coreKeys, bytes, buf);
+ buffer->keysOld(currTime, idCount, coreKeys, bytes, buf);
}
if (start) {
for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
int offset = i * gSessionData->mCores + cpu;
- if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_ENABLE) < 0) {
+ if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_ENABLE, 0) < 0) {
logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
+ return 0;
}
}
}
+ if (idCount == 0) {
+ logg->logMessage("%s(%s:%i): no events came online", __FUNCTION__, __FILE__, __LINE__);
+ }
+
return idCount;
}
@@ -177,7 +195,7 @@ bool PerfGroup::offlineCPU(const int cpu) {
for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
int offset = i * gSessionData->mCores + cpu;
- if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_DISABLE) < 0) {
+ if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_DISABLE, 0) < 0) {
logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
@@ -203,7 +221,7 @@ bool PerfGroup::offlineCPU(const int cpu) {
bool PerfGroup::start() {
for (int pos = 0; pos < ARRAY_LENGTH(mFds); ++pos) {
- if (mFds[pos] >= 0 && ioctl(mFds[pos], PERF_EVENT_IOC_ENABLE) < 0) {
+ if (mFds[pos] >= 0 && ioctl(mFds[pos], PERF_EVENT_IOC_ENABLE, 0) < 0) {
logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
goto fail;
}
@@ -220,7 +238,7 @@ bool PerfGroup::start() {
void PerfGroup::stop() {
for (int pos = ARRAY_LENGTH(mFds) - 1; pos >= 0; --pos) {
if (mFds[pos] >= 0) {
- ioctl(mFds[pos], PERF_EVENT_IOC_DISABLE);
+ ioctl(mFds[pos], PERF_EVENT_IOC_DISABLE, 0);
}
}
}
diff --git a/tools/gator/daemon/PerfGroup.h b/tools/gator/daemon/PerfGroup.h
index 3f1e2bb..f7b3d72 100644
--- a/tools/gator/daemon/PerfGroup.h
+++ b/tools/gator/daemon/PerfGroup.h
@@ -9,6 +9,8 @@
#ifndef PERF_GROUP
#define PERF_GROUP
+#include <stdint.h>
+
// Use a snapshot of perf_event.h as it may be more recent than what is on the target and if not newer features won't be supported anyways
#include "k/perf_event.h"
@@ -27,16 +29,22 @@ enum PerfGroupFlags {
PERF_GROUP_PER_CPU = 1 << 5,
};
+enum {
+ PG_SUCCESS = 0,
+ PG_FAILURE,
+ PG_CPU_OFFLINE,
+};
+
class PerfGroup {
public:
PerfGroup(PerfBuffer *const pb);
~PerfGroup();
- bool add(Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags);
+ bool add(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags);
// Safe to call concurrently
- bool prepareCPU(const int cpu);
+ int prepareCPU(const int cpu, Monitor *const monitor);
// Not safe to call concurrently. Returns the number of events enabled
- int onlineCPU(const int cpu, const bool start, Buffer *const buffer, Monitor *const monitor);
+ int onlineCPU(const uint64_t currTime, const int cpu, const bool start, Buffer *const buffer);
bool offlineCPU(int cpu);
bool start();
void stop();
diff --git a/tools/gator/daemon/PerfSource.cpp b/tools/gator/daemon/PerfSource.cpp
index ecfaa66..193b778 100644
--- a/tools/gator/daemon/PerfSource.cpp
+++ b/tools/gator/daemon/PerfSource.cpp
@@ -8,8 +8,14 @@
#include "PerfSource.h"
+#include <dirent.h>
#include <errno.h>
+#include <signal.h>
#include <string.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
#include <unistd.h>
#include "Child.h"
@@ -19,11 +25,13 @@
#include "Proc.h"
#include "SessionData.h"
-#define MS_PER_US 1000000
+#ifndef SCHED_RESET_ON_FORK
+#define SCHED_RESET_ON_FORK 0x40000000
+#endif
extern Child *child;
-static bool sendTracepointFormat(Buffer *const buffer, const char *const name, DynBuf *const printb, DynBuf *const b) {
+static bool sendTracepointFormat(const uint64_t currTime, Buffer *const buffer, const char *const name, DynBuf *const printb, DynBuf *const b) {
if (!printb->printf(EVENTS_PATH "/%s/format", name)) {
logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
return false;
@@ -32,47 +40,112 @@ static bool sendTracepointFormat(Buffer *const buffer, const char *const name, D
logg->logMessage("%s(%s:%i): DynBuf::read failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
- buffer->format(b->getLength(), b->getBuf());
+ buffer->format(currTime, b->getLength(), b->getBuf());
return true;
}
-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");
+static void *syncFunc(void *arg)
+{
+ struct timespec ts;
+ int64_t nextTime = gSessionData->mMonotonicStarted;
+ int err;
+ (void)arg;
+
+ prctl(PR_SET_NAME, (unsigned long)&"gatord-sync", 0, 0, 0);
+
+ // Mask all signals so that this thread will not be woken up
+ {
+ sigset_t set;
+ if (sigfillset(&set) != 0) {
+ logg->logError(__FILE__, __LINE__, "sigfillset failed");
+ handleException();
+ }
+ if ((err = pthread_sigmask(SIG_SETMASK, &set, NULL)) != 0) {
+ logg->logError(__FILE__, __LINE__, "pthread_sigmask failed");
+ handleException();
+ }
+ }
+
+ for (;;) {
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
+ logg->logError(__FILE__, __LINE__, "clock_gettime failed");
+ handleException();
+ }
+ const int64_t currTime = ts.tv_sec * NS_PER_S + ts.tv_nsec;
+
+ // Wake up once a second
+ nextTime += NS_PER_S;
+
+ // Always sleep more than 1 ms, hopefully things will line up better next time
+ const int64_t sleepTime = max(nextTime - currTime, (int64_t)(NS_PER_MS + 1));
+ ts.tv_sec = sleepTime/NS_PER_S;
+ ts.tv_nsec = sleepTime % NS_PER_S;
+
+ err = nanosleep(&ts, NULL);
+ if (err != 0) {
+ fprintf(stderr, "clock_nanosleep failed: %s\n", strerror(err));
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+static long getMaxCoreNum() {
+ DIR *dir = opendir("/sys/devices/system/cpu");
+ if (dir == NULL) {
+ logg->logError(__FILE__, __LINE__, "Unable to determine the number of cores on the target, opendir failed");
handleException();
}
- gSessionData->mPageSize = static_cast<int>(l);
- l = sysconf(_SC_NPROCESSORS_CONF);
- if (l < 0) {
- logg->logError(__FILE__, __LINE__, "Unable to obtain the number of cores");
+ long maxCoreNum = -1;
+ struct dirent *dirent;
+ while ((dirent = readdir(dir)) != NULL) {
+ if (strncmp(dirent->d_name, "cpu", 3) == 0) {
+ char *endptr;
+ errno = 0;
+ long coreNum = strtol(dirent->d_name + 3, &endptr, 10);
+ if ((errno == 0) && (*endptr == '\0') && (coreNum >= maxCoreNum)) {
+ maxCoreNum = coreNum + 1;
+ }
+ }
+ }
+ closedir(dir);
+
+ if (maxCoreNum < 1) {
+ logg->logError(__FILE__, __LINE__, "Unable to determine the number of cores on the target, no cpu# directories found");
handleException();
}
- gSessionData->mCores = static_cast<int>(l);
-}
-PerfSource::~PerfSource() {
+ if (maxCoreNum >= NR_CPUS) {
+ logg->logError(__FILE__, __LINE__, "Too many cores on the target, please increase NR_CPUS in Config.h");
+ handleException();
+ }
+
+ return maxCoreNum;
}
-struct PrepareParallelArgs {
- PerfGroup *pg;
- int cpu;
-};
+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), mIdleGroup(&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");
+ handleException();
+ }
+ gSessionData->mPageSize = static_cast<int>(l);
+ gSessionData->mCores = static_cast<int>(getMaxCoreNum());
+}
-void *prepareParallel(void *arg) {
- const PrepareParallelArgs *const args = (PrepareParallelArgs *)arg;
- args->pg->prepareCPU(args->cpu);
- return NULL;
+PerfSource::~PerfSource() {
}
bool PerfSource::prepare() {
DynBuf printb;
DynBuf b1;
- DynBuf b2;
- DynBuf b3;
long long schedSwitchId;
+ long long cpuIdleId;
+
+ const uint64_t currTime = getTime();
// Reread cpuinfo since cores may have changed since startup
gSessionData->readCpuInfo();
@@ -83,76 +156,146 @@ bool PerfSource::prepare() {
|| !mMonitor.add(mUEvent.getFd())
|| (schedSwitchId = PerfDriver::getTracepointId(SCHED_SWITCH, &printb)) < 0
- || !sendTracepointFormat(&mBuffer, SCHED_SWITCH, &printb, &b1)
+ || !sendTracepointFormat(currTime, &mBuffer, SCHED_SWITCH, &printb, &b1)
+
+ || (cpuIdleId = PerfDriver::getTracepointId(CPU_IDLE, &printb)) < 0
+ || !sendTracepointFormat(currTime, &mBuffer, CPU_IDLE, &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 | PERF_GROUP_PER_CPU)
+ || !mCountersGroup.add(currTime, &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)
+ || !mIdleGroup.add(currTime, &mBuffer, 101/**/, PERF_TYPE_TRACEPOINT, cpuIdleId, 1, PERF_SAMPLE_RAW, 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, PERF_GROUP_PER_CPU))
+ || (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && !mCountersGroup.add(currTime, &mBuffer, 102/**/, 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)
+ || !gSessionData->perf.enable(currTime, &mCountersGroup, &mBuffer)
|| 0) {
logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.4 or later?", __FUNCTION__, __FILE__, __LINE__);
return false;
}
- if (!gSessionData->perf.summary(&mSummary)) {
- logg->logMessage("%s(%s:%i): PerfDriver::summary failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- {
- // Run prepareCPU in parallel as perf_event_open can take more than 1 sec in some cases
- pthread_t threads[NR_CPUS];
- PrepareParallelArgs args[NR_CPUS];
- for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
- args[cpu].pg = &mCountersGroup;
- args[cpu].cpu = cpu;
- if (pthread_create(&threads[cpu], NULL, prepareParallel, &args[cpu]) != 0) {
- logg->logMessage("%s(%s:%i): pthread_create failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
+ for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
+ const int result = mCountersGroup.prepareCPU(cpu, &mMonitor);
+ if ((result != PG_SUCCESS) && (result != PG_CPU_OFFLINE)) {
+ logg->logError(__FILE__, __LINE__, "PerfGroup::prepareCPU on mCountersGroup failed");
+ handleException();
}
- for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
- if (pthread_join(threads[cpu], NULL) != 0) {
- logg->logMessage("%s(%s:%i): pthread_join failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
+ }
+ for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
+ const int result = mIdleGroup.prepareCPU(cpu, &mMonitor);
+ if ((result != PG_SUCCESS) && (result != PG_CPU_OFFLINE)) {
+ logg->logError(__FILE__, __LINE__, "PerfGroup::prepareCPU on mIdleGroup failed");
+ handleException();
}
}
int numEvents = 0;
for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
- numEvents += mCountersGroup.onlineCPU(cpu, false, &mBuffer, &mMonitor);
+ numEvents += mCountersGroup.onlineCPU(currTime, cpu, false, &mBuffer);
+ }
+ for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
+ numEvents += mIdleGroup.onlineCPU(currTime, cpu, false, &mBuffer);
}
if (numEvents <= 0) {
logg->logMessage("%s(%s:%i): PerfGroup::onlineCPU failed on all cores", __FUNCTION__, __FILE__, __LINE__);
return false;
}
- // Start events before reading proc to avoid race conditions
- if (!mCountersGroup.start()) {
- logg->logMessage("%s(%s:%i): PerfGroup::start failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
+ // Send the summary right before the start so that the monotonic delta is close to the start time
+ if (!gSessionData->perf.summary(&mSummary)) {
+ logg->logError(__FILE__, __LINE__, "PerfDriver::summary failed", __FUNCTION__, __FILE__, __LINE__);
+ handleException();
}
- if (!readProc(&mBuffer, true, &printb, &b1, &b2, &b3)) {
- logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
+ // Start the timer thread to used to sync perf and monotonic raw times
+ pthread_t syncThread;
+ if (pthread_create(&syncThread, NULL, syncFunc, NULL)) {
+ logg->logError(__FILE__, __LINE__, "pthread_create failed", __FUNCTION__, __FILE__, __LINE__);
+ handleException();
+ }
+ struct sched_param param;
+ param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+ if (pthread_setschedparam(syncThread, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
+ logg->logError(__FILE__, __LINE__, "pthread_setschedparam failed");
+ handleException();
}
- mBuffer.commit(1);
+ mBuffer.commit(currTime);
return true;
}
+struct ProcThreadArgs {
+ Buffer *mBuffer;
+ uint64_t mCurrTime;
+ bool mIsDone;
+};
+
+void *procFunc(void *arg) {
+ DynBuf printb;
+ DynBuf b;
+ const ProcThreadArgs *const args = (ProcThreadArgs *)arg;
+
+ prctl(PR_SET_NAME, (unsigned long)&"gatord-proc", 0, 0, 0);
+
+ // Gator runs at a high priority, reset the priority to the default
+ if (setpriority(PRIO_PROCESS, syscall(__NR_gettid), 0) == -1) {
+ logg->logError(__FILE__, __LINE__, "setpriority failed");
+ handleException();
+ }
+
+ if (!readProcMaps(args->mCurrTime, args->mBuffer, &printb, &b)) {
+ logg->logError(__FILE__, __LINE__, "readProcMaps failed");
+ handleException();
+ }
+ args->mBuffer->commit(args->mCurrTime);
+
+ if (!readKallsyms(args->mCurrTime, args->mBuffer, &args->mIsDone)) {
+ logg->logError(__FILE__, __LINE__, "readKallsyms failed");
+ handleException();
+ }
+ args->mBuffer->commit(args->mCurrTime);
+
+ return NULL;
+}
+
static const char CPU_DEVPATH[] = "/devices/system/cpu/cpu";
void PerfSource::run() {
int pipefd[2];
+ pthread_t procThread;
+ ProcThreadArgs procThreadArgs;
+
+ {
+ DynBuf printb;
+ DynBuf b1;
+ DynBuf b2;
- if (pipe(pipefd) != 0) {
+ const uint64_t currTime = getTime();
+
+ // Start events before reading proc to avoid race conditions
+ if (!mCountersGroup.start() || !mIdleGroup.start()) {
+ logg->logError(__FILE__, __LINE__, "PerfGroup::start failed", __FUNCTION__, __FILE__, __LINE__);
+ handleException();
+ }
+
+ if (!readProcComms(currTime, &mBuffer, &printb, &b1, &b2)) {
+ logg->logError(__FILE__, __LINE__, "readProcComms failed");
+ handleException();
+ }
+ mBuffer.commit(currTime);
+
+ // Postpone reading kallsyms as on android adb gets too backed up and data is lost
+ procThreadArgs.mBuffer = &mBuffer;
+ procThreadArgs.mCurrTime = currTime;
+ procThreadArgs.mIsDone = false;
+ if (pthread_create(&procThread, NULL, procFunc, &procThreadArgs)) {
+ logg->logError(__FILE__, __LINE__, "pthread_create failed", __FUNCTION__, __FILE__, __LINE__);
+ handleException();
+ }
+ }
+
+ if (pipe_cloexec(pipefd) != 0) {
logg->logError(__FILE__, __LINE__, "pipe failed");
handleException();
}
@@ -165,7 +308,7 @@ void PerfSource::run() {
int timeout = -1;
if (gSessionData->mLiveRate > 0) {
- timeout = gSessionData->mLiveRate/MS_PER_US;
+ timeout = gSessionData->mLiveRate/NS_PER_MS;
}
sem_post(mStartProfile);
@@ -178,10 +321,11 @@ void PerfSource::run() {
logg->logError(__FILE__, __LINE__, "Monitor::wait failed");
handleException();
}
+ const uint64_t currTime = getTime();
for (int i = 0; i < ready; ++i) {
if (events[i].data.fd == mUEvent.getFd()) {
- if (!handleUEvent()) {
+ if (!handleUEvent(currTime)) {
logg->logError(__FILE__, __LINE__, "PerfSource::handleUEvent failed");
handleException();
}
@@ -200,6 +344,9 @@ void PerfSource::run() {
}
}
+ procThreadArgs.mIsDone = true;
+ pthread_join(procThread, NULL);
+ mIdleGroup.stop();
mCountersGroup.stop();
mBuffer.setDone();
mIsDone = true;
@@ -212,7 +359,7 @@ void PerfSource::run() {
close(pipefd[1]);
}
-bool PerfSource::handleUEvent() {
+bool PerfSource::handleUEvent(const uint64_t currTime) {
UEventResult result;
if (!mUEvent.read(&result)) {
logg->logMessage("%s(%s:%i): UEvent::Read failed", __FUNCTION__, __FILE__, __LINE__);
@@ -231,14 +378,41 @@ bool PerfSource::handleUEvent() {
logg->logMessage("%s(%s:%i): strtol failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
+
+ if (cpu >= gSessionData->mCores) {
+ logg->logError(__FILE__, __LINE__, "Only %i cores are expected but core %i reports %s", gSessionData->mCores, cpu, result.mAction);
+ handleException();
+ }
+
if (strcmp(result.mAction, "online") == 0) {
+ mBuffer.onlineCPU(currTime, currTime - gSessionData->mMonotonicStarted, cpu);
// Only call onlineCPU if prepareCPU succeeded
- const bool result = mCountersGroup.prepareCPU(cpu) &&
- mCountersGroup.onlineCPU(cpu, true, &mBuffer, &mMonitor);
- mBuffer.commit(1);
+ bool result = false;
+ int err = mCountersGroup.prepareCPU(cpu, &mMonitor);
+ if (err == PG_CPU_OFFLINE) {
+ result = true;
+ } else if (err == PG_SUCCESS) {
+ if (mCountersGroup.onlineCPU(currTime, cpu, true, &mBuffer)) {
+ err = mIdleGroup.prepareCPU(cpu, &mMonitor);
+ if (err == PG_CPU_OFFLINE) {
+ result = true;
+ } else if (err == PG_SUCCESS) {
+ if (mIdleGroup.onlineCPU(currTime, cpu, true, &mBuffer)) {
+ result = true;
+ }
+ }
+ }
+ }
+ mBuffer.commit(currTime);
+
+ gSessionData->readCpuInfo();
+ gSessionData->perf.coreName(currTime, &mSummary, cpu);
+ mSummary.commit(currTime);
return result;
} else if (strcmp(result.mAction, "offline") == 0) {
- return mCountersGroup.offlineCPU(cpu);
+ const bool result = mCountersGroup.offlineCPU(cpu) && mIdleGroup.offlineCPU(cpu);
+ mBuffer.offlineCPU(currTime, currTime - gSessionData->mMonotonicStarted, cpu);
+ return result;
}
}
diff --git a/tools/gator/daemon/PerfSource.h b/tools/gator/daemon/PerfSource.h
index 3f471c8..ce1eafe 100644
--- a/tools/gator/daemon/PerfSource.h
+++ b/tools/gator/daemon/PerfSource.h
@@ -33,12 +33,13 @@ public:
void write(Sender *sender);
private:
- bool handleUEvent();
+ bool handleUEvent(const uint64_t currTime);
Buffer mSummary;
Buffer mBuffer;
PerfBuffer mCountersBuf;
PerfGroup mCountersGroup;
+ PerfGroup mIdleGroup;
Monitor mMonitor;
UEvent mUEvent;
sem_t *const mSenderSem;
diff --git a/tools/gator/daemon/Proc.cpp b/tools/gator/daemon/Proc.cpp
index 9f01770..e6b26b1 100644
--- a/tools/gator/daemon/Proc.cpp
+++ b/tools/gator/daemon/Proc.cpp
@@ -10,13 +10,16 @@
#include <dirent.h>
#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "Buffer.h"
#include "DynBuf.h"
#include "Logging.h"
+#include "SessionData.h"
struct ProcStat {
// From linux-dev/include/linux/sched.h
@@ -57,6 +60,8 @@ static bool readProcStat(ProcStat *const ps, const char *const pathname, DynBuf
return true;
}
+static const char APP_PROCESS[] = "app_process";
+
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)) {
@@ -82,7 +87,8 @@ static const char *readProcExe(DynBuf *const printb, const int pid, const int ti
}
// Android apps are run by app_process but the cmdline is changed to reference the actual app name
- if (strcmp(image, "app_process") != 0) {
+ // On 64-bit android app_process can be app_process32 or app_process64
+ if (strncmp(image, APP_PROCESS, sizeof(APP_PROCESS) - 1) != 0) {
return image;
}
@@ -100,7 +106,7 @@ static const char *readProcExe(DynBuf *const printb, const int pid, const int ti
return b->getBuf();
}
-static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) {
+static bool readProcTask(const uint64_t currTime, Buffer *const buffer, const int pid, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) {
bool result = false;
if (!b1->printf("/proc/%i/task", pid)) {
@@ -110,7 +116,8 @@ static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const prin
DIR *task = opendir(b1->getBuf());
if (task == NULL) {
logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__);
- return result;
+ // This is not a fatal error - the thread just doesn't exist any more
+ return true;
}
struct dirent *dirent;
@@ -138,7 +145,7 @@ static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const prin
goto fail;
}
- buffer->comm(pid, tid, image, ps.comm);
+ buffer->comm(currTime, pid, tid, image, ps.comm);
}
result = true;
@@ -149,7 +156,7 @@ static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const prin
return result;
}
-bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) {
+bool readProcComms(const uint64_t currTime, Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) {
bool result = false;
DIR *proc = opendir("/proc");
@@ -177,19 +184,6 @@ bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf
goto fail;
}
- 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;
- }
-
- buffer->maps(pid, pid, b2->getBuf());
- }
if (ps.numThreads <= 1) {
const char *const image = readProcExe(printb, pid, -1, b1);
if (image == NULL) {
@@ -197,9 +191,9 @@ bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf
goto fail;
}
- buffer->comm(pid, pid, image, ps.comm);
+ buffer->comm(currTime, pid, pid, image, ps.comm);
} else {
- if (!readProcTask(buffer, pid, printb, b1, b3)) {
+ if (!readProcTask(currTime, buffer, pid, printb, b1, b2)) {
logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__);
goto fail;
}
@@ -213,3 +207,106 @@ bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf
return result;
}
+
+bool readProcMaps(const uint64_t currTime, Buffer *const buffer, DynBuf *const printb, DynBuf *const b) {
+ bool result = false;
+
+ DIR *proc = opendir("/proc");
+ if (proc == NULL) {
+ logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__);
+ return result;
+ }
+
+ struct dirent *dirent;
+ while ((dirent = readdir(proc)) != NULL) {
+ char *endptr;
+ const int pid = strtol(dirent->d_name, &endptr, 10);
+ if (*endptr != '\0') {
+ // Ignore proc items that are not integers like ., cpuinfo, etc...
+ continue;
+ }
+
+ if (!printb->printf("/proc/%i/maps", pid)) {
+ logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+ goto fail;
+ }
+ if (!b->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(currTime, pid, pid, b->getBuf());
+ }
+
+ result = true;
+
+ fail:
+ closedir(proc);
+
+ return result;
+}
+
+bool readKallsyms(const uint64_t currTime, Buffer *const buffer, const bool *const isDone) {
+ int fd = ::open("/proc/kallsyms", O_RDONLY | O_CLOEXEC);
+
+ if (fd < 0) {
+ logg->logMessage("%s(%s:%i): open failed", __FUNCTION__, __FILE__, __LINE__);
+ return true;
+ };
+
+ char buf[1<<12];
+ ssize_t pos = 0;
+ while (gSessionData->mSessionIsActive && !ACCESS_ONCE(*isDone)) {
+ // Assert there is still space in the buffer
+ if (sizeof(buf) - pos - 1 == 0) {
+ logg->logError(__FILE__, __LINE__, "no space left in buffer");
+ handleException();
+ }
+
+ {
+ // -1 to reserve space for \0
+ const ssize_t bytes = ::read(fd, buf + pos, sizeof(buf) - pos - 1);
+ if (bytes < 0) {
+ logg->logError(__FILE__, __LINE__, "read failed", __FUNCTION__, __FILE__, __LINE__);
+ handleException();
+ }
+ if (bytes == 0) {
+ // Assert the buffer is empty
+ if (pos != 0) {
+ logg->logError(__FILE__, __LINE__, "buffer not empty on eof");
+ handleException();
+ }
+ break;
+ }
+ pos += bytes;
+ }
+
+ ssize_t newline;
+ // Find the last '\n'
+ for (newline = pos - 1; newline >= 0; --newline) {
+ if (buf[newline] == '\n') {
+ const char was = buf[newline + 1];
+ buf[newline + 1] = '\0';
+ buffer->kallsyms(currTime, buf);
+ // Sleep 3 ms to avoid sending out too much data too quickly
+ usleep(3000);
+ buf[0] = was;
+ // Assert the memory regions do not overlap
+ if (pos - newline >= newline + 1) {
+ logg->logError(__FILE__, __LINE__, "memcpy src and dst overlap");
+ handleException();
+ }
+ if (pos - newline - 2 > 0) {
+ memcpy(buf + 1, buf + newline + 2, pos - newline - 2);
+ }
+ pos -= newline + 1;
+ break;
+ }
+ }
+ }
+
+ close(fd);
+
+ return true;
+}
diff --git a/tools/gator/daemon/Proc.h b/tools/gator/daemon/Proc.h
index 31c2eec..2a1a7cb 100644
--- a/tools/gator/daemon/Proc.h
+++ b/tools/gator/daemon/Proc.h
@@ -9,9 +9,13 @@
#ifndef PROC_H
#define PROC_H
+#include <stdint.h>
+
class Buffer;
class DynBuf;
-bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3);
+bool readProcComms(const uint64_t currTime, Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2);
+bool readProcMaps(const uint64_t currTime, Buffer *const buffer, DynBuf *const printb, DynBuf *const b);
+bool readKallsyms(const uint64_t currTime, Buffer *const buffer, const bool *const isDone);
#endif // PROC_H
diff --git a/tools/gator/daemon/Sender.cpp b/tools/gator/daemon/Sender.cpp
index 3a981a6..8a54a66 100644
--- a/tools/gator/daemon/Sender.cpp
+++ b/tools/gator/daemon/Sender.cpp
@@ -65,18 +65,13 @@ void Sender::createDataFile(char* apcDir) {
mDataFileName = (char*)malloc(strlen(apcDir) + 12);
sprintf(mDataFileName, "%s/0000000000", apcDir);
- mDataFile = fopen(mDataFileName, "wb");
+ mDataFile = fopen_cloexec(mDataFileName, "wb");
if (!mDataFile) {
logg->logError(__FILE__, __LINE__, "Failed to open binary file: %s", mDataFileName);
handleException();
}
}
-template<typename T>
-inline T min(const T a, const T b) {
- return (a < b ? a : b);
-}
-
void Sender::writeData(const char* data, int length, int type) {
if (length < 0 || (data == NULL && length > 0)) {
return;
diff --git a/tools/gator/daemon/Sender.h b/tools/gator/daemon/Sender.h
index 33b6cc3..5aa9117 100644
--- a/tools/gator/daemon/Sender.h
+++ b/tools/gator/daemon/Sender.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __SENDER_H__
-#define __SENDER_H__
+#ifndef __SENDER_H__
+#define __SENDER_H__
#include <stdio.h>
#include <pthread.h>
diff --git a/tools/gator/daemon/SessionData.cpp b/tools/gator/daemon/SessionData.cpp
index 14d995f..0e65d78 100644
--- a/tools/gator/daemon/SessionData.cpp
+++ b/tools/gator/daemon/SessionData.cpp
@@ -8,15 +8,31 @@
#include "SessionData.h"
+#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
+#include <unistd.h>
-#include "SessionXML.h"
+#include "CPUFreqDriver.h"
+#include "DiskIODriver.h"
+#include "FSDriver.h"
+#include "HwmonDriver.h"
#include "Logging.h"
+#include "MemInfoDriver.h"
+#include "NetDriver.h"
+#include "SessionXML.h"
+
+#define CORE_NAME_UNKNOWN "unknown"
SessionData* gSessionData = NULL;
SessionData::SessionData() {
+ usDrivers[0] = new HwmonDriver();
+ usDrivers[1] = new FSDriver();
+ usDrivers[2] = new MemInfoDriver();
+ usDrivers[3] = new NetDriver();
+ usDrivers[4] = new CPUFreqDriver();
+ usDrivers[5] = new DiskIODriver();
initialize();
}
@@ -29,6 +45,7 @@ void SessionData::initialize() {
mLocalCapture = false;
mOneShot = false;
mSentSummary = false;
+ mAllowCommands = 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);
@@ -37,15 +54,22 @@ void SessionData::initialize() {
handleException();
}
memset(mCpuIds, -1, cpuIdSize);
+ strcpy(mCoreName, CORE_NAME_UNKNOWN);
+ readModel();
readCpuInfo();
+ mImages = NULL;
mConfigurationXMLPath = NULL;
mSessionXMLPath = NULL;
mEventsXMLPath = NULL;
mTargetPath = NULL;
mAPCDir = NULL;
+ mCaptureWorkingDir = NULL;
+ mCaptureCommand = NULL;
+ mCaptureUser = NULL;
mSampleRate = 0;
mLiveRate = 0;
mDuration = 0;
+ mMonotonicStarted = -1;
mBacktraceDepth = 0;
mTotalBufferSize = 0;
// sysconf(_SC_NPROCESSORS_CONF) is unreliable on 2.6 Android, get the value from the kernel module
@@ -71,7 +95,6 @@ void SessionData::parseSessionXML(char* xmlString) {
handleException();
}
mBacktraceDepth = session.parameters.call_stack_unwinding == true ? 128 : 0;
- mDuration = session.parameters.duration;
// Determine buffer size (in MB) based on buffer mode
mOneShot = true;
@@ -89,21 +112,38 @@ void SessionData::parseSessionXML(char* xmlString) {
handleException();
}
- mImages = session.parameters.images;
// Convert milli- to nanoseconds
mLiveRate = session.parameters.live_rate * (int64_t)1000000;
if (mLiveRate > 0 && mLocalCapture) {
logg->logMessage("Local capture is not compatable with live, disabling live");
mLiveRate = 0;
}
+
+ if (!mAllowCommands && (mCaptureCommand != NULL)) {
+ logg->logError(__FILE__, __LINE__, "Running a command during a capture is not currently allowed. Please restart gatord with the -a flag.");
+ handleException();
+ }
+}
+
+void SessionData::readModel() {
+ FILE *fh = fopen("/proc/device-tree/model", "rb");
+ if (fh == NULL) {
+ return;
+ }
+
+ char buf[256];
+ if (fgets(buf, sizeof(buf), fh) != NULL) {
+ strcpy(mCoreName, buf);
+ }
+
+ fclose(fh);
}
void SessionData::readCpuInfo() {
char temp[256]; // arbitrarily large amount
- strcpy(mCoreName, "unknown");
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'.");
@@ -122,7 +162,8 @@ void SessionData::readCpuInfo() {
}
if (len > 0) {
- temp[len - 1] = '\0'; // Replace the line feed with a null
+ // Replace the line feed with a null
+ temp[len - 1] = '\0';
}
const bool foundHardware = strstr(temp, "Hardware") != 0;
@@ -137,7 +178,7 @@ void SessionData::readCpuInfo() {
}
position += 2;
- if (foundHardware) {
+ if (foundHardware && (strcmp(mCoreName, CORE_NAME_UNKNOWN) == 0)) {
strncpy(mCoreName, position, sizeof(mCoreName));
mCoreName[sizeof(mCoreName) - 1] = 0; // strncpy does not guarantee a null-terminated string
foundCoreName = true;
@@ -171,10 +212,6 @@ void SessionData::readCpuInfo() {
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();
@@ -185,10 +222,40 @@ uint64_t getTime() {
int getEventKey() {
// key 0 is reserved as a timestamp
// key 1 is reserved as the marker for thread specific counters
+ // key 2 is reserved as the marker for core
// Odd keys are assigned by the driver, even keys by the daemon
- static int key = 2;
+ static int key = 4;
const int ret = key;
key += 2;
return ret;
}
+
+int pipe_cloexec(int pipefd[2]) {
+ if (pipe(pipefd) != 0) {
+ return -1;
+ }
+
+ int fdf;
+ if (((fdf = fcntl(pipefd[0], F_GETFD)) == -1) || (fcntl(pipefd[0], F_SETFD, fdf | FD_CLOEXEC) != 0) ||
+ ((fdf = fcntl(pipefd[1], F_GETFD)) == -1) || (fcntl(pipefd[1], F_SETFD, fdf | FD_CLOEXEC) != 0)) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return -1;
+ }
+ return 0;
+}
+
+FILE *fopen_cloexec(const char *path, const char *mode) {
+ FILE *fh = fopen(path, mode);
+ if (fh == NULL) {
+ return NULL;
+ }
+ int fd = fileno(fh);
+ int fdf = fcntl(fd, F_GETFD);
+ if ((fdf == -1) || (fcntl(fd, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
+ fclose(fh);
+ return NULL;
+ }
+ return fh;
+}
diff --git a/tools/gator/daemon/SessionData.h b/tools/gator/daemon/SessionData.h
index 835082d..ed282af 100644
--- a/tools/gator/daemon/SessionData.h
+++ b/tools/gator/daemon/SessionData.h
@@ -11,17 +11,21 @@
#include <stdint.h>
+#include "AnnotateListener.h"
#include "Config.h"
#include "Counter.h"
-#include "FSDriver.h"
-#include "Hwmon.h"
+#include "FtraceDriver.h"
+#include "KMod.h"
#include "MaliVideoDriver.h"
#include "PerfDriver.h"
-#define PROTOCOL_VERSION 19
-#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions
+#define PROTOCOL_VERSION 20
+// Differentiates development versions (timestamp) from release versions
+#define PROTOCOL_DEV 1000
-#define NS_PER_S ((uint64_t)1000000000)
+#define NS_PER_S 1000000000LL
+#define NS_PER_MS 1000000LL
+#define NS_PER_US 1000LL
struct ImageLinkList {
char* path;
@@ -36,30 +40,40 @@ public:
~SessionData();
void initialize();
void parseSessionXML(char* xmlString);
+ void readModel();
void readCpuInfo();
- Hwmon hwmon;
- FSDriver fsDriver;
+ PolledDriver *usDrivers[6];
+ KMod kmod;
PerfDriver perf;
MaliVideoDriver maliVideo;
+ FtraceDriver ftraceDriver;
+ AnnotateListener annotateListener;
char mCoreName[MAX_STRING_LEN];
struct ImageLinkList *mImages;
- char* mConfigurationXMLPath;
- char* mSessionXMLPath;
- char* mEventsXMLPath;
- char* mTargetPath;
- char* mAPCDir;
+ char *mConfigurationXMLPath;
+ char *mSessionXMLPath;
+ char *mEventsXMLPath;
+ char *mTargetPath;
+ char *mAPCDir;
+ char *mCaptureWorkingDir;
+ char *mCaptureCommand;
+ char *mCaptureUser;
bool mWaitingOnCommand;
bool mSessionIsActive;
bool mLocalCapture;
- bool mOneShot; // halt processing of the driver data until profiling is complete or the buffer is filled
+ // halt processing of the driver data until profiling is complete or the buffer is filled
+ bool mOneShot;
bool mIsEBS;
bool mSentSummary;
+ bool mAllowCommands;
+ int64_t mMonotonicStarted;
int mBacktraceDepth;
- int mTotalBufferSize; // number of MB to use for the entire collection buffer
+ // number of MB to use for the entire collection buffer
+ int mTotalBufferSize;
int mSampleRate;
int64_t mLiveRate;
int mDuration;
@@ -82,5 +96,7 @@ extern SessionData* gSessionData;
uint64_t getTime();
int getEventKey();
+int pipe_cloexec(int pipefd[2]);
+FILE *fopen_cloexec(const char *path, const char *mode);
#endif // SESSION_DATA_H
diff --git a/tools/gator/daemon/SessionXML.cpp b/tools/gator/daemon/SessionXML.cpp
index 8cdc940..dea4c8f 100644
--- a/tools/gator/daemon/SessionXML.cpp
+++ b/tools/gator/daemon/SessionXML.cpp
@@ -16,33 +16,30 @@
#include "OlyUtility.h"
#include "SessionData.h"
-static const char* TAG_SESSION = "session";
-static const char* TAG_IMAGE = "image";
-
-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_DURATION = "duration";
-static const char* ATTR_PATH = "path";
-static const char* ATTR_LIVE_RATE = "live_rate";
+static const char *TAG_SESSION = "session";
+static const char *TAG_IMAGE = "image";
+
+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_DURATION = "duration";
+static const char *ATTR_PATH = "path";
+static const char *ATTR_LIVE_RATE = "live_rate";
+static const char *ATTR_CAPTURE_WORKING_DIR = "capture_working_dir";
+static const char *ATTR_CAPTURE_COMMAND = "capture_command";
+static const char *ATTR_CAPTURE_USER = "capture_user";
SessionXML::SessionXML(const char *str) {
parameters.buffer_mode[0] = 0;
parameters.sample_rate[0] = 0;
- parameters.duration = 0;
parameters.call_stack_unwinding = false;
parameters.live_rate = 0;
- parameters.images = NULL;
- mPath = 0;
- mSessionXML = (const char *)str;
+ mSessionXML = str;
logg->logMessage(mSessionXML);
}
SessionXML::~SessionXML() {
- if (mPath != 0) {
- free((char *)mSessionXML);
- }
}
void SessionXML::parse() {
@@ -79,10 +76,13 @@ void SessionXML::sessionTag(mxml_node_t *tree, mxml_node_t *node) {
strncpy(parameters.sample_rate, mxmlElementGetAttr(node, ATTR_SAMPLE_RATE), sizeof(parameters.sample_rate));
parameters.sample_rate[sizeof(parameters.sample_rate) - 1] = 0; // strncpy does not guarantee a null-terminated string
}
+ if (mxmlElementGetAttr(node, ATTR_CAPTURE_WORKING_DIR)) gSessionData->mCaptureWorkingDir = strdup(mxmlElementGetAttr(node, ATTR_CAPTURE_WORKING_DIR));
+ if (mxmlElementGetAttr(node, ATTR_CAPTURE_COMMAND)) gSessionData->mCaptureCommand = strdup(mxmlElementGetAttr(node, ATTR_CAPTURE_COMMAND));
+ if (mxmlElementGetAttr(node, ATTR_CAPTURE_USER)) gSessionData->mCaptureUser = strdup(mxmlElementGetAttr(node, ATTR_CAPTURE_USER));
// integers/bools
parameters.call_stack_unwinding = util->stringToBool(mxmlElementGetAttr(node, ATTR_CALL_STACK_UNWINDING), false);
- if (mxmlElementGetAttr(node, ATTR_DURATION)) parameters.duration = strtol(mxmlElementGetAttr(node, ATTR_DURATION), NULL, 10);
+ if (mxmlElementGetAttr(node, ATTR_DURATION)) gSessionData->mDuration = strtol(mxmlElementGetAttr(node, ATTR_DURATION), NULL, 10);
if (mxmlElementGetAttr(node, ATTR_LIVE_RATE)) parameters.live_rate = strtol(mxmlElementGetAttr(node, ATTR_LIVE_RATE), NULL, 10);
// parse subtags
@@ -106,6 +106,6 @@ void SessionXML::sessionImage(mxml_node_t *node) {
image = (struct ImageLinkList *)malloc(sizeof(struct ImageLinkList));
image->path = (char*)malloc(length + 1);
image->path = strdup(mxmlElementGetAttr(node, ATTR_PATH));
- image->next = parameters.images;
- parameters.images = image;
+ image->next = gSessionData->mImages;
+ gSessionData->mImages = image;
}
diff --git a/tools/gator/daemon/SessionXML.h b/tools/gator/daemon/SessionXML.h
index e146094..5396574 100644
--- a/tools/gator/daemon/SessionXML.h
+++ b/tools/gator/daemon/SessionXML.h
@@ -14,12 +14,13 @@
struct ImageLinkList;
struct ConfigParameters {
- char buffer_mode[64]; // buffer mode, "streaming", "low", "normal", "high" defines oneshot and buffer size
- char sample_rate[64]; // capture mode, "high", "normal", or "low"
- int duration; // length of profile in seconds
- bool call_stack_unwinding; // whether stack unwinding is performed
+ // buffer mode, "streaming", "low", "normal", "high" defines oneshot and buffer size
+ char buffer_mode[64];
+ // capture mode, "high", "normal", or "low"
+ char sample_rate[64];
+ // whether stack unwinding is performed
+ bool call_stack_unwinding;
int live_rate;
- struct ImageLinkList *images; // linked list of image strings
};
class SessionXML {
@@ -30,7 +31,6 @@ public:
ConfigParameters parameters;
private:
const char *mSessionXML;
- const char *mPath;
void sessionTag(mxml_node_t *tree, mxml_node_t *node);
void sessionImage(mxml_node_t *node);
diff --git a/tools/gator/daemon/Setup.cpp b/tools/gator/daemon/Setup.cpp
new file mode 100644
index 0000000..d4ce032
--- /dev/null
+++ b/tools/gator/daemon/Setup.cpp
@@ -0,0 +1,232 @@
+/**
+ * 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 "Setup.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "Config.h"
+#include "DynBuf.h"
+#include "Logging.h"
+
+bool getLinuxVersion(int version[3]) {
+ // Check the kernel version
+ struct utsname utsname;
+ if (uname(&utsname) != 0) {
+ logg->logMessage("%s(%s:%i): uname failed", __FUNCTION__, __FILE__, __LINE__);
+ return false;
+ }
+
+ version[0] = 0;
+ version[1] = 0;
+ version[2] = 0;
+
+ int part = 0;
+ char *ch = utsname.release;
+ while (*ch >= '0' && *ch <= '9' && part < 3) {
+ version[part] = 10*version[part] + *ch - '0';
+
+ ++ch;
+ if (*ch == '.') {
+ ++part;
+ ++ch;
+ }
+ }
+
+ return true;
+}
+
+static int pgrep_gator(DynBuf *const printb) {
+ DynBuf b;
+
+ DIR *proc = opendir("/proc");
+ if (proc == NULL) {
+ logg->logError(__FILE__, __LINE__, "gator: error: opendir failed");
+ handleException();
+ }
+
+ int self = getpid();
+
+ struct dirent *dirent;
+ while ((dirent = readdir(proc)) != NULL) {
+ char *endptr;
+ const int pid = strtol(dirent->d_name, &endptr, 10);
+ if (*endptr != '\0' || (pid == self)) {
+ // Ignore proc items that are not integers like ., cpuinfo, etc...
+ continue;
+ }
+
+ if (!printb->printf("/proc/%i/stat", pid)) {
+ logg->logError(__FILE__, __LINE__, "gator: error: DynBuf::printf failed");
+ handleException();
+ }
+
+ if (!b.read(printb->getBuf())) {
+ // This is not a fatal error - the thread just doesn't exist any more
+ continue;
+ }
+
+ char *comm = strchr(b.getBuf(), '(');
+ if (comm == NULL) {
+ logg->logError(__FILE__, __LINE__, "gator: error: parsing stat begin failed");
+ handleException();
+ }
+ ++comm;
+ char *const str = strrchr(comm, ')');
+ if (str == NULL) {
+ logg->logError(__FILE__, __LINE__, "gator: error: parsing stat end failed");
+ handleException();
+ }
+ *str = '\0';
+
+ if (strncmp(comm, "gator", 5) == 0) {
+ // Assume there is only one gator process
+ return pid;
+ }
+ }
+
+ closedir(proc);
+
+ return -1;
+}
+
+int update(const char *const gatorPath) {
+ printf("gator: starting\n");
+
+ int version[3];
+ if (!getLinuxVersion(version)) {
+ logg->logError(__FILE__, __LINE__, "gator: error: getLinuxVersion failed");
+ handleException();
+ }
+
+ if (KERNEL_VERSION(version[0], version[1], version[2]) < KERNEL_VERSION(2, 6, 32)) {
+ logg->logError(__FILE__, __LINE__, "gator: error: Streamline can't automatically setup gator as this kernel version is not supported. Please upgrade the kernel on your device.");
+ handleException();
+ }
+
+ if (KERNEL_VERSION(version[0], version[1], version[2]) < KERNEL_VERSION(3, 4, 0)) {
+ logg->logError(__FILE__, __LINE__, "gator: error: Streamline can't automatically setup gator as gator.ko is required for this version of Linux. Please build gator.ko and gatord and install them on your device.");
+ handleException();
+ }
+
+ if (access("/sys/module/gator", F_OK) == 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: Streamline has detected that the gator kernel module is loaded on your device. Please build an updated version of gator.ko and gatord and install them on your device.");
+ handleException();
+ }
+
+ if (geteuid() != 0) {
+ printf("gator: trying sudo\n");
+ execlp("sudo", "sudo", gatorPath, "-u", NULL);
+ // Streamline will provide the password if needed
+
+ printf("gator: trying su\n");
+ char buf[1<<10];
+ snprintf(buf, sizeof(buf), "%s -u", gatorPath);
+ execlp("su", "su", "-", "-c", buf, NULL);
+ // Streamline will provide the password if needed
+
+ logg->logError(__FILE__, __LINE__, "gator: error: Streamline was unable to sudo to root on your device. Please double check passwords, ensure sudo or su work with this user or try a different username.");
+ handleException();
+ }
+ printf("gator: now root\n");
+
+ // setenforce 0 not needed for userspace gator
+
+ // Kill existing gator
+ DynBuf gatorStatPath;
+ int gator_main = pgrep_gator(&gatorStatPath);
+ if (gator_main > 0) {
+ if (kill(gator_main, SIGTERM) != 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: kill SIGTERM failed");
+ handleException();
+ }
+ for (int i = 0; ; ++i) {
+ if (access(gatorStatPath.getBuf(), F_OK) != 0) {
+ break;
+ }
+ if (i == 5) {
+ if (kill(gator_main, SIGKILL) != 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: kill SIGKILL failed");
+ handleException();
+ }
+ } else if (i >= 10) {
+ logg->logError(__FILE__, __LINE__, "gator: error: unable to kill running gator");
+ handleException();
+ }
+ sleep(1);
+ }
+ }
+ printf("gator: no gatord running\n");
+
+ rename("gatord", "gatord.old");
+ rename("gator.ko", "gator.ko.old");
+
+ // Rename gatord.YYYYMMDDHHMMSSMMMM to gatord
+ char *newGatorPath = strdup(gatorPath);
+ char *dot = strrchr(newGatorPath, '.');
+ if (dot != NULL) {
+ *dot = '\0';
+ if (rename(gatorPath, newGatorPath) != 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: rename failed");
+ handleException();
+ }
+ }
+
+ // Fork and start gatord (redirect stdout and stderr)
+ int child = fork();
+ if (child < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: fork failed");
+ handleException();
+ } else if (child == 0) {
+ int inFd = open("/dev/null", O_RDONLY | O_CLOEXEC);
+ if (inFd < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: open of /dev/null failed");
+ handleException();
+ }
+ int outFd = open("gatord.out", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0600);
+ if (outFd < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: open of gatord.out failed");
+ handleException();
+ }
+ int errFd = open("gatord.err", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0600);
+ if (errFd < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: open of gatord.err failed");
+ handleException();
+ }
+ if (dup2(inFd, STDIN_FILENO) < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stdin failed");
+ handleException();
+ }
+ if (dup2(outFd, STDOUT_FILENO) < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stdout failed");
+ handleException();
+ }
+ if (dup2(errFd, STDERR_FILENO) < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stderr failed");
+ handleException();
+ }
+ execlp(newGatorPath, newGatorPath, "-a", NULL);
+ logg->logError(__FILE__, __LINE__, "gator: error: execlp failed");
+ handleException();
+ }
+
+ printf("gator: done\n");
+
+ return 0;
+}
diff --git a/tools/gator/daemon/Setup.h b/tools/gator/daemon/Setup.h
new file mode 100644
index 0000000..280d611
--- /dev/null
+++ b/tools/gator/daemon/Setup.h
@@ -0,0 +1,18 @@
+/**
+ * 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 SETUP_H
+#define SETUP_H
+
+// From include/generated/uapi/linux/version.h
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+
+bool getLinuxVersion(int version[3]);
+int update(const char *const gatorPath);
+
+#endif // SETUP_H
diff --git a/tools/gator/daemon/StreamlineSetup.h b/tools/gator/daemon/StreamlineSetup.h
index b380f46..623e14f 100644
--- a/tools/gator/daemon/StreamlineSetup.h
+++ b/tools/gator/daemon/StreamlineSetup.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __STREAMLINE_SETUP_H__
-#define __STREAMLINE_SETUP_H__
+#ifndef __STREAMLINE_SETUP_H__
+#define __STREAMLINE_SETUP_H__
#include <stdint.h>
#include <string.h>
diff --git a/tools/gator/daemon/UEvent.cpp b/tools/gator/daemon/UEvent.cpp
index 54d4575..f94a995 100644
--- a/tools/gator/daemon/UEvent.cpp
+++ b/tools/gator/daemon/UEvent.cpp
@@ -15,6 +15,7 @@
#include <linux/netlink.h>
#include "Logging.h"
+#include "OlySocket.h"
static const char EMPTY[] = "";
static const char ACTION[] = "ACTION=";
@@ -31,7 +32,7 @@ UEvent::~UEvent() {
}
bool UEvent::init() {
- mFd = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
+ mFd = socket_cloexec(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
if (mFd < 0) {
logg->logMessage("%s(%s:%i): socket failed", __FUNCTION__, __FILE__, __LINE__);
return false;
diff --git a/tools/gator/daemon/UserSpaceSource.cpp b/tools/gator/daemon/UserSpaceSource.cpp
index 8c328e0..4a9b22f 100644
--- a/tools/gator/daemon/UserSpaceSource.cpp
+++ b/tools/gator/daemon/UserSpaceSource.cpp
@@ -16,8 +16,6 @@
#include "Logging.h"
#include "SessionData.h"
-#define NS_PER_US 1000
-
extern Child *child;
UserSpaceSource::UserSpaceSource(sem_t *senderSem) : mBuffer(0, FRAME_BLOCK_COUNTER, gSessionData->mTotalBufferSize*1024*1024, senderSem) {
@@ -33,16 +31,22 @@ bool UserSpaceSource::prepare() {
void UserSpaceSource::run() {
prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0);
- gSessionData->hwmon.start();
- gSessionData->fsDriver.start();
+ for (int i = 0; i < ARRAY_LENGTH(gSessionData->usDrivers); ++i) {
+ gSessionData->usDrivers[i]->start();
+ }
int64_t monotonic_started = 0;
while (monotonic_started <= 0) {
usleep(10);
- if (DriverSource::readInt64Driver("/dev/gator/started", &monotonic_started) == -1) {
- logg->logError(__FILE__, __LINE__, "Error reading gator driver start time");
- handleException();
+ if (gSessionData->perf.isSetup()) {
+ monotonic_started = gSessionData->mMonotonicStarted;
+ } else {
+ if (DriverSource::readInt64Driver("/dev/gator/started", &monotonic_started) == -1) {
+ logg->logError(__FILE__, __LINE__, "Error reading gator driver start time");
+ handleException();
+ }
+ gSessionData->mMonotonicStarted = monotonic_started;
}
}
@@ -57,8 +61,9 @@ void UserSpaceSource::run() {
}
if (mBuffer.eventHeader(curr_time)) {
- gSessionData->hwmon.read(&mBuffer);
- gSessionData->fsDriver.read(&mBuffer);
+ for (int i = 0; i < ARRAY_LENGTH(gSessionData->usDrivers); ++i) {
+ gSessionData->usDrivers[i]->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/defaults.xml b/tools/gator/daemon/defaults.xml
index 39a0f65..086eca1 100644
--- a/tools/gator/daemon/defaults.xml
+++ b/tools/gator/daemon/defaults.xml
@@ -24,16 +24,16 @@
<configuration counter="ARMv7_Cortex_A9_cnt2" event="0x07"/>
<configuration counter="ARMv7_Cortex_A9_cnt3" event="0x03"/>
<configuration counter="ARMv7_Cortex_A9_cnt4" event="0x04"/>
- <configuration counter="ARMv7_Cortex_A12_ccnt" event="0xff"/>
- <configuration counter="ARMv7_Cortex_A12_cnt0" event="0x08"/>
- <configuration counter="ARMv7_Cortex_A12_cnt1" event="0x16"/>
- <configuration counter="ARMv7_Cortex_A12_cnt2" event="0x10"/>
- <configuration counter="ARMv7_Cortex_A12_cnt3" event="0x19"/>
<configuration counter="ARMv7_Cortex_A15_ccnt" event="0xff"/>
<configuration counter="ARMv7_Cortex_A15_cnt0" event="0x8"/>
<configuration counter="ARMv7_Cortex_A15_cnt1" event="0x16"/>
<configuration counter="ARMv7_Cortex_A15_cnt2" event="0x10"/>
<configuration counter="ARMv7_Cortex_A15_cnt3" event="0x19"/>
+ <configuration counter="ARMv7_Cortex_A17_ccnt" event="0xff"/>
+ <configuration counter="ARMv7_Cortex_A17_cnt0" event="0x08"/>
+ <configuration counter="ARMv7_Cortex_A17_cnt1" event="0x16"/>
+ <configuration counter="ARMv7_Cortex_A17_cnt2" event="0x10"/>
+ <configuration counter="ARMv7_Cortex_A17_cnt3" event="0x19"/>
<configuration counter="ARM_Cortex-A53_ccnt" event="0x11"/>
<configuration counter="ARM_Cortex-A53_cnt0" event="0x8"/>
<configuration counter="ARM_Cortex-A53_cnt1" event="0x16"/>
@@ -56,12 +56,29 @@
<configuration counter="Linux_block_rq_wr"/>
<configuration counter="Linux_block_rq_rd"/>
<configuration counter="Linux_meminfo_memused"/>
+ <configuration counter="Linux_meminfo_memused2"/>
<configuration counter="Linux_meminfo_memfree"/>
<configuration counter="Linux_power_cpu_freq"/>
<configuration counter="ARM_Mali-4xx_fragment"/>
<configuration counter="ARM_Mali-4xx_vertex"/>
- <configuration counter="ARM_Mali-T6xx_fragment" cores="1"/>
- <configuration counter="ARM_Mali-T6xx_vertex" cores="1"/>
- <configuration counter="ARM_Mali-T6xx_opencl" cores="1"/>
+ <configuration counter="ARM_Mali-Midgard_fragment" cores="1"/>
+ <configuration counter="ARM_Mali-Midgard_vertex" cores="1"/>
+ <configuration counter="ARM_Mali-Midgard_opencl" cores="1"/>
+ <configuration counter="ARM_Mali-T60x_GPU_ACTIVE"/>
+ <configuration counter="ARM_Mali-T60x_JS0_ACTIVE"/>
+ <configuration counter="ARM_Mali-T60x_JS1_ACTIVE"/>
+ <configuration counter="ARM_Mali-T60x_JS2_ACTIVE"/>
+ <configuration counter="ARM_Mali-T62x_GPU_ACTIVE"/>
+ <configuration counter="ARM_Mali-T62x_JS0_ACTIVE"/>
+ <configuration counter="ARM_Mali-T62x_JS1_ACTIVE"/>
+ <configuration counter="ARM_Mali-T62x_JS2_ACTIVE"/>
+ <configuration counter="ARM_Mali-T72x_GPU_ACTIVE"/>
+ <configuration counter="ARM_Mali-T72x_JS0_ACTIVE"/>
+ <configuration counter="ARM_Mali-T72x_JS1_ACTIVE"/>
+ <configuration counter="ARM_Mali-T72x_JS2_ACTIVE"/>
+ <configuration counter="ARM_Mali-T76x_GPU_ACTIVE"/>
+ <configuration counter="ARM_Mali-T76x_JS0_ACTIVE"/>
+ <configuration counter="ARM_Mali-T76x_JS1_ACTIVE"/>
+ <configuration counter="ARM_Mali-T76x_JS2_ACTIVE"/>
<configuration counter="L2C-310_cnt0" event="0x1"/>
</configurations>
diff --git a/tools/gator/daemon/events-Cortex-A12.xml b/tools/gator/daemon/events-Cortex-A17.xml
index 9c04354..4dd08c1 100644
--- a/tools/gator/daemon/events-Cortex-A12.xml
+++ b/tools/gator/daemon/events-Cortex-A17.xml
@@ -1,6 +1,6 @@
- <counter_set name="ARMv7_Cortex_A12_cnt" count="6"/>
- <category name="Cortex-A12" counter_set="ARMv7_Cortex_A12_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <event counter="ARMv7_Cortex_A12_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
+ <counter_set name="ARMv7_Cortex_A17_cnt" count="6"/>
+ <category name="Cortex-A17" counter_set="ARMv7_Cortex_A17_cnt" per_cpu="yes" supports_event_based_sampling="yes">
+ <event counter="ARMv7_Cortex_A17_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
<event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
<event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
<event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
@@ -62,7 +62,7 @@
<event event="0xc2" title="Cache" name="4 Ways Read" description="Number of set of 4 ways read in the instruction cache - Tag RAM"/>
<event event="0xc3" title="Cache" name="Ways Read" description="Number of ways read in the instruction cache - Data RAM"/>
<event event="0xc4" title="Cache" name="BATC Read" description="Number of ways read in the instruction BTAC RAM"/>
- <event event="0xca" title="Memory" name="Snoop" description="Data snooped from other processor. This event counts memory-read operations that read data from another processor within the local Cortex-A12 cluster, rather than accessing the L2 cache or issuing an external read. It increments on each transaction, rather than on each beat of data"/>
+ <event event="0xca" title="Memory" name="Snoop" description="Data snooped from other processor. This event counts memory-read operations that read data from another processor within the local Cortex-A17 cluster, rather than accessing the L2 cache or issuing an external read. It increments on each transaction, rather than on each beat of data"/>
<event event="0xd3" title="Slots" name="Load-Store Unit" description="Duration during which all slots in the Load-Store Unit are busy"/>
<event event="0xd8" title="Slots" name="Load-Store Issue Queue" description="Duration during which all slots in the Load-Store Issue queue are busy"/>
<event event="0xd9" title="Slots" name="Data Processing Issue Queue" description="Duration during which all slots in the Data Processing issue queue are busy"/>
diff --git a/tools/gator/daemon/events-Filesystem.xml b/tools/gator/daemon/events-Filesystem.xml
index 5feeb90..9ef61dd 100644
--- a/tools/gator/daemon/events-Filesystem.xml
+++ b/tools/gator/daemon/events-Filesystem.xml
@@ -1,11 +1,11 @@
<category name="Filesystem">
- <!-- counter attributes must be unique -->
+ <!-- counter attribute must start with filesystem_ and be unique -->
<!-- regex item in () is the value shown -->
- <!-- these counters are not compatible with userspace gator, i.e. gator.ko must be loaded -->
<!--
- <event counter="/sys/devices/system/cpu/cpu1/online" title="online" name="cpu 1" class="absolute" description="If cpu 1 is online"/>
- <event counter="/proc/self/loginuid" title="loginuid" name="loginuid" class="absolute" description="loginuid"/>
- <event counter="/proc/self/stat" title="stat" name="rss" class="absolute" regex="-?[0-9]+ \(.*\) . -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ (-?[0-9]+)" units="pages" description="resident set size"/>
- <event counter="/proc/stat" title="proc-stat" name="processes" class="absolute" regex="processes ([0-9]+)" description="Number of processes and threads created"/>
+ <event counter="filesystem_cpu1_online" path="/sys/devices/system/cpu/cpu1/online" title="online" name="cpu 1" class="absolute" description="If cpu 1 is online"/>
+ <event counter="filesystem_loginuid" path="/proc/self/loginuid" title="loginuid" name="loginuid" class="absolute" description="loginuid"/>
+ <event counter="filesystem_gatord_rss" path="/proc/self/stat" title="stat" name="rss" class="absolute" regex="-?[0-9]+ \(.*\) . -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ (-?[0-9]+)" units="pages" description="resident set size"/>
+ <event counter="filesystem_processes" path="/proc/stat" title="proc-stat" name="processes" class="absolute" regex="processes ([0-9]+)" description="Number of processes and threads created"/>
+ <event counter="filesystem_context_switches" path="/proc/stat" title="proc-stat" name="context switches" class="absolute" regex="ctxt ([0-9]+)" description="Number of processes and threads created"/>
-->
</category>
diff --git a/tools/gator/daemon/events-Linux.xml b/tools/gator/daemon/events-Linux.xml
index c306dd6..62a7018 100644
--- a/tools/gator/daemon/events-Linux.xml
+++ b/tools/gator/daemon/events-Linux.xml
@@ -1,16 +1,17 @@
<category name="Linux">
<event counter="Linux_irq_softirq" title="Interrupts" name="SoftIRQ" per_cpu="yes" description="Linux SoftIRQ taken"/>
<event counter="Linux_irq_irq" title="Interrupts" name="IRQ" per_cpu="yes" description="Linux IRQ taken"/>
- <event counter="Linux_block_rq_wr" title="Disk IO" name="Write" units="B" description="Disk IO Bytes Written"/>
- <event counter="Linux_block_rq_rd" title="Disk IO" name="Read" units="B" description="Disk IO Bytes Read"/>
+ <event counter="Linux_block_rq_wr" title="Disk I/O" name="Write" units="B" description="Disk I/O Bytes Written"/>
+ <event counter="Linux_block_rq_rd" title="Disk I/O" name="Read" units="B" description="Disk I/O Bytes Read"/>
<event counter="Linux_net_rx" title="Network" name="Receive" units="B" description="Receive network traffic, including effect from Streamline"/>
<event counter="Linux_net_tx" title="Network" name="Transmit" units="B" description="Transmit network traffic, including effect from Streamline"/>
<event counter="Linux_sched_switch" title="Scheduler" name="Switch" per_cpu="yes" description="Context switch events"/>
<event counter="Linux_meminfo_memused" title="Memory" name="Used" class="absolute" units="B" proc="yes" description="Total used memory size. Note: a process' used memory includes shared memory that may be counted more than once (equivalent to RES from top). Kernel threads are not filterable."/>
+ <event counter="Linux_meminfo_memused2" title="Memory" name="Used" class="absolute" units="B" description="Total used memory size"/>
<event counter="Linux_meminfo_memfree" title="Memory" name="Free" class="absolute" display="minimum" units="B" description="Available memory size"/>
<event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" class="absolute" units="B" description="Memory used by OS disk buffers"/>
<event counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" class="absolute" units="Hz" series_composition="overlay" average_cores="yes" description="Frequency setting of the CPU"/>
- <event counter="Linux_power_cpu_idle" title="Idle" name="State" per_cpu="yes" class="absolute" description="CPU Idle State + 1, set the Sample Rate to None to prevent the hrtimer from interrupting the system"/>
- <event counter="Linux_cpu_wait_contention" title="CPU Contention" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" color="0x003c96fb" description="Thread waiting on contended resource"/>
- <event counter="Linux_cpu_wait_io" title="CPU I/O" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" color="0x00b30000" description="Thread waiting on I/O resource"/>
+ <event counter="Linux_cpu_wait_contention" title="CPU Contention" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" color="0x003c96fb" description="One or more threads are runnable but waiting due to CPU contention"/>
+ <event counter="Linux_cpu_wait_io" title="CPU I/O" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" color="0x00b30000" description="One or more threads are blocked on an I/O resource"/>
+ <event counter="Linux_power_cpu" title="CPU Status" name="Activity" class="activity" activity1="Off" activity_color1="0x0000ff00" activity2="WFI" activity_color2="0x000000ff" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" description="CPU Status"/>
</category>
diff --git a/tools/gator/daemon/events-Mali-Midgard.xml b/tools/gator/daemon/events-Mali-Midgard.xml
new file mode 100644
index 0000000..b6ab4b8
--- /dev/null
+++ b/tools/gator/daemon/events-Mali-Midgard.xml
@@ -0,0 +1,46 @@
+ <category name="Mali-Midgard Software Counters" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_TOTAL_ALLOC_PAGES" title="Mali Total Alloc Pages" name="Total number of allocated pages" description="Mali total number of allocated pages."/>
+ </category>
+ <category name="Mali-Midgard PM Shader" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_PM_SHADER_0" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 0" description="Mali PM Shader: PM Shader Core 0."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_1" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 1" description="Mali PM Shader: PM Shader Core 1."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_2" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 2" description="Mali PM Shader: PM Shader Core 2."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_3" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 3" description="Mali PM Shader: PM Shader Core 3."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_4" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 4" description="Mali PM Shader: PM Shader Core 4."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_5" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 5" description="Mali PM Shader: PM Shader Core 5."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_6" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 6" description="Mali PM Shader: PM Shader Core 6."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_7" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 7" description="Mali PM Shader: PM Shader Core 7."/>
+ </category>
+ <category name="Mali-Midgard PM Tiler" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_PM_TILER_0" display="average" average_selection="yes" percentage="yes" title="Mali PM Tiler" name="PM Tiler Core 0" description="Mali PM Tiler: PM Tiler Core 0."/>
+ </category>
+ <category name="Mali-Midgard PM L2" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_PM_L2_0" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 0" description="Mali PM L2: PM L2 Core 0."/>
+ <event counter="ARM_Mali-Midgard_PM_L2_1" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 1" description="Mali PM L2: PM L2 Core 1."/>
+ </category>
+ <category name="Mali-Midgard MMU Address Space" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_MMU_AS_0" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 0" description="Mali MMU Address Space 0 usage."/>
+ <event counter="ARM_Mali-Midgard_MMU_AS_1" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 1" description="Mali MMU Address Space 1 usage."/>
+ <event counter="ARM_Mali-Midgard_MMU_AS_2" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 2" description="Mali MMU Address Space 2 usage."/>
+ <event counter="ARM_Mali-Midgard_MMU_AS_3" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 3" description="Mali MMU Address Space 3 usage."/>
+ </category>
+ <category name="Mali-Midgard MMU Page Fault" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_MMU_PAGE_FAULT_0" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 0" description="Reports the number of newly allocated pages after a MMU page fault in address space 0."/>
+ <event counter="ARM_Mali-Midgard_MMU_PAGE_FAULT_1" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 1" description="Reports the number of newly allocated pages after a MMU page fault in address space 1."/>
+ <event counter="ARM_Mali-Midgard_MMU_PAGE_FAULT_2" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 2" description="Reports the number of newly allocated pages after a MMU page fault in address space 2."/>
+ <event counter="ARM_Mali-Midgard_MMU_PAGE_FAULT_3" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 3" description="Reports the number of newly allocated pages after a MMU page fault in address space 3."/>
+ </category>
+ <counter_set name="ARM_Mali-Midgard_Filmstrip_cnt" count="1"/>
+ <category name="Mali-Midgard Filmstrip" counter_set="ARM_Mali-Midgard_Filmstrip_cnt" per_cpu="no">
+ <option_set name="fs">
+ <option event_delta="0x3c" name="1:60" description="captures every 60th frame"/>
+ <option event_delta="0x1e" name="1:30" description="captures every 30th frame"/>
+ <option event_delta="0xa" name="1:10" description="captures every 10th frame"/>
+ </option_set>
+ <event event="0x0400" option_set="fs" title="ARM Mali-Midgard" name="Filmstrip" description="Scaled framebuffer"/>
+ </category>
+ <category name="Mali-Midgard Activity" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_fragment" title="GPU Fragment" name="Activity" class="activity" activity1="Activity" activity_color1="0x00006fcc" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 0 Activity"/>
+ <event counter="ARM_Mali-Midgard_vertex" title="GPU Vertex-Tiling-Compute" name="Activity" class="activity" activity1="Activity" activity_color1="0x00eda000" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 1 Activity"/>
+ <event counter="ARM_Mali-Midgard_opencl" title="GPU Vertex-Compute" name="Activity" class="activity" activity1="Activity" activity_color1="0x00ef022f" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 2 Activity"/>
+ </category>
diff --git a/tools/gator/daemon/events-Mali-Midgard_hw.xml b/tools/gator/daemon/events-Mali-Midgard_hw.xml
new file mode 100644
index 0000000..4f3323f
--- /dev/null
+++ b/tools/gator/daemon/events-Mali-Midgard_hw.xml
@@ -0,0 +1,91 @@
+ <category name="Mali-Midgard Job Manager" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles the GPU was active"/>
+ <event counter="ARM_Mali-Midgard_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles the GPU had a pending interrupt"/>
+ <event counter="ARM_Mali-Midgard_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) was active"/>
+ <event counter="ARM_Mali-Midgard_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) was active"/>
+ <event counter="ARM_Mali-Midgard_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) was active"/>
+ <event counter="ARM_Mali-Midgard_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+ <event counter="ARM_Mali-Midgard_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+ <event counter="ARM_Mali-Midgard_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+ <event counter="ARM_Mali-Midgard_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+ <event counter="ARM_Mali-Midgard_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
+ <event counter="ARM_Mali-Midgard_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+ </category>
+ <category name="Mali-Midgard Tiler" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
+ <event counter="ARM_Mali-Midgard_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
+ <event counter="ARM_Mali-Midgard_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
+ <event counter="ARM_Mali-Midgard_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
+ <event counter="ARM_Mali-Midgard_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+ <event counter="ARM_Mali-Midgard_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
+ <event counter="ARM_Mali-Midgard_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
+ <event counter="ARM_Mali-Midgard_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
+ <event counter="ARM_Mali-Midgard_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
+ <event counter="ARM_Mali-Midgard_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+ <event counter="ARM_Mali-Midgard_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
+ <event counter="ARM_Mali-Midgard_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
+ <event counter="ARM_Mali-Midgard_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
+ <event counter="ARM_Mali-Midgard_LEVEL3" title="Mali Tiler Hierarchy" name="L3 prims" description="Number of primitives in hierarchy level 3"/>
+ <event counter="ARM_Mali-Midgard_LEVEL4" title="Mali Tiler Hierarchy" name="L4 prims" description="Number of primitives in hierarchy level 4"/>
+ <event counter="ARM_Mali-Midgard_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
+ <event counter="ARM_Mali-Midgard_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
+ <event counter="ARM_Mali-Midgard_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_1" title="Mali Tiler Commands" name="Prims in 1 command" description="Number of primitives producing 1 command"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_2" title="Mali Tiler Commands" name="Prims in 2 command" description="Number of primitives producing 2 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_3" title="Mali Tiler Commands" name="Prims in 3 command" description="Number of primitives producing 3 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_4" title="Mali Tiler Commands" name="Prims in 4 command" description="Number of primitives producing 4 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_4_7" title="Mali Tiler Commands" name="Prims in 4-7 commands" description="Number of primitives producing 4-7 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_5_7" title="Mali Tiler Commands" name="Prims in 5-7 commands" description="Number of primitives producing 5-7 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_8_15" title="Mali Tiler Commands" name="Prims in 8-15 commands" description="Number of primitives producing 8-15 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_16_63" title="Mali Tiler Commands" name="Prims in 16-63 commands" description="Number of primitives producing 16-63 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_64" title="Mali Tiler Commands" name="Prims in &gt;= 64 commands" description="Number of primitives producing &gt;= 64 commands"/>
+ </category>
+ <category name="Mali-Midgard Shader Core" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles the Tripipe was active"/>
+ <event counter="ARM_Mali-Midgard_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
+ <event counter="ARM_Mali-Midgard_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
+ <event counter="ARM_Mali-Midgard_FRAG_CYCLE_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+ <event counter="ARM_Mali-Midgard_FRAG_THREADS" title="Mali Core Threads" name="Fragment threads" description="Number of fragment threads started"/>
+ <event counter="ARM_Mali-Midgard_FRAG_DUMMY_THREADS" title="Mali Core Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
+ <event counter="ARM_Mali-Midgard_FRAG_QUADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
+ <event counter="ARM_Mali-Midgard_FRAG_QUADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
+ <event counter="ARM_Mali-Midgard_FRAG_THREADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
+ <event counter="ARM_Mali-Midgard_FRAG_THREADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
+ <event counter="ARM_Mali-Midgard_COMPUTE_TASKS" title="Mali Compute Threads" name="Compute tasks" description="Number of compute tasks"/>
+ <event counter="ARM_Mali-Midgard_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads started" description="Number of compute threads started"/>
+ <event counter="ARM_Mali-Midgard_COMPUTE_CYCLES_DESC" title="Mali Compute Threads" name="Compute cycles awaiting descriptors" description="Number of compute cycles spent waiting for descriptors"/>
+ <event counter="ARM_Mali-Midgard_FRAG_PRIMATIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+ <event counter="ARM_Mali-Midgard_FRAG_PRIMATIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+ <event counter="ARM_Mali-Midgard_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+ <event counter="ARM_Mali-Midgard_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+ <event counter="ARM_Mali-Midgard_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
+ <event counter="ARM_Mali-Midgard_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
+ <event counter="ARM_Mali-Midgard_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+ <event counter="ARM_Mali-Midgard_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
+ <event counter="ARM_Mali-Midgard_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+ <event counter="ARM_Mali-Midgard_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
+ <event counter="ARM_Mali-Midgard_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
+ <event counter="ARM_Mali-Midgard_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+ <event counter="ARM_Mali-Midgard_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
+ <event counter="ARM_Mali-Midgard_TEX_THREADS" title="Mali Texture Pipe" name="T instruction issues" description="Number of instructions issused to the T-pipe, including restarts"/>
+ <event counter="ARM_Mali-Midgard_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
+ <event counter="ARM_Mali-Midgard_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+ </category>
+ <category name="Mali-Midgard L2 and MMU" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_L2_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
+ <event counter="ARM_Mali-Midgard_L2_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
+ <event counter="ARM_Mali-Midgard_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
+ <event counter="ARM_Mali-Midgard_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+ <event counter="ARM_Mali-Midgard_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
+ <event counter="ARM_Mali-Midgard_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+ <event counter="ARM_Mali-Midgard_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-Midgard_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+ </category>
diff --git a/tools/gator/daemon/events-Mali-T60x_hw.xml b/tools/gator/daemon/events-Mali-T60x_hw.xml
new file mode 100644
index 0000000..50797e6
--- /dev/null
+++ b/tools/gator/daemon/events-Mali-T60x_hw.xml
@@ -0,0 +1,108 @@
+
+ <category name="Mali Job Manager" per_cpu="no">
+
+ <event counter="ARM_Mali-T60x_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles GPU active"/>
+ <event counter="ARM_Mali-T60x_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles GPU interrupt pending"/>
+ <event counter="ARM_Mali-T60x_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) active"/>
+ <event counter="ARM_Mali-T60x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
+ <event counter="ARM_Mali-T60x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
+
+ <event counter="ARM_Mali-T60x_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+ <event counter="ARM_Mali-T60x_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+ <event counter="ARM_Mali-T60x_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+ <event counter="ARM_Mali-T60x_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+ <event counter="ARM_Mali-T60x_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
+ <event counter="ARM_Mali-T60x_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+ </category>
+
+ <category name="Mali Tiler" per_cpu="no">
+
+ <event counter="ARM_Mali-T60x_TI_ACTIVE" title="Mali Tiler Cycles" name="Tiler cycles" description="Number of cycles Tiler active"/>
+
+ <event counter="ARM_Mali-T60x_TI_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
+ <event counter="ARM_Mali-T60x_TI_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
+ <event counter="ARM_Mali-T60x_TI_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
+ <event counter="ARM_Mali-T60x_TI_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
+ <event counter="ARM_Mali-T60x_TI_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+
+ <event counter="ARM_Mali-T60x_TI_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
+ <event counter="ARM_Mali-T60x_TI_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
+ <event counter="ARM_Mali-T60x_TI_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
+ <event counter="ARM_Mali-T60x_TI_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
+ <event counter="ARM_Mali-T60x_TI_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+
+ <event counter="ARM_Mali-T60x_TI_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL3" title="Mali Tiler Hierarchy" name="L3 prims" description="Number of primitives in hierarchy level 3"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL4" title="Mali Tiler Hierarchy" name="L4 prims" description="Number of primitives in hierarchy level 4"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
+
+ </category>
+
+ <category name="Mali Shader Core" per_cpu="no">
+
+ <event counter="ARM_Mali-T60x_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles tripipe was active"/>
+ <event counter="ARM_Mali-T60x_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
+ <event counter="ARM_Mali-T60x_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
+ <event counter="ARM_Mali-T60x_FRAG_CYCLES_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+
+ <event counter="ARM_Mali-T60x_FRAG_THREADS" title="Mali Fragment Threads" name="Fragment threads" description="Number of fragment threads started"/>
+ <event counter="ARM_Mali-T60x_FRAG_DUMMY_THREADS" title="Mali Fragment Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
+ <event counter="ARM_Mali-T60x_FRAG_THREADS_LZS_TEST" title="Mali Fragment Threads" name="Fragment threads doing late ZS" description="Number of threads doing late ZS test"/>
+ <event counter="ARM_Mali-T60x_FRAG_THREADS_LZS_KILLED" title="Mali Fragment Threads" name="Fragment threads killed late ZS" description="Number of threads killed by late ZS test"/>
+
+ <event counter="ARM_Mali-T60x_COMPUTE_TASKS" title="Mali Compute Tasks" name="Compute tasks" description="Number of compute tasks"/>
+ <event counter="ARM_Mali-T60x_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads" description="Number of compute threads started"/>
+
+ <event counter="ARM_Mali-T60x_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+ <event counter="ARM_Mali-T60x_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+
+ <event counter="ARM_Mali-T60x_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
+ <event counter="ARM_Mali-T60x_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
+ <event counter="ARM_Mali-T60x_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+
+ <event counter="ARM_Mali-T60x_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
+ <event counter="ARM_Mali-T60x_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+
+ <event counter="ARM_Mali-T60x_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
+
+ <event counter="ARM_Mali-T60x_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
+ <event counter="ARM_Mali-T60x_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+
+ <event counter="ARM_Mali-T60x_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
+ <event counter="ARM_Mali-T60x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
+ <event counter="ARM_Mali-T60x_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
+
+ <event counter="ARM_Mali-T60x_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+
+ </category>
+
+ <category name="Mali L2 Cache" per_cpu="no">
+
+ <event counter="ARM_Mali-T60x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
+ <event counter="ARM_Mali-T60x_L2_EXT_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
+ <event counter="ARM_Mali-T60x_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
+ <event counter="ARM_Mali-T60x_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T60x_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
+ <event counter="ARM_Mali-T60x_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T60x_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T60x_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T60x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
+ <event counter="ARM_Mali-T60x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
+ <event counter="ARM_Mali-T60x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
+ <event counter="ARM_Mali-T60x_L2_READ_LOOKUP" title="Mali L2 Cache" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+ <event counter="ARM_Mali-T60x_L2_WRITE_LOOKUP" title="Mali L2 Cache" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+
+ </category>
diff --git a/tools/gator/daemon/events-Mali-T62x_hw.xml b/tools/gator/daemon/events-Mali-T62x_hw.xml
new file mode 100644
index 0000000..6ecc53c
--- /dev/null
+++ b/tools/gator/daemon/events-Mali-T62x_hw.xml
@@ -0,0 +1,109 @@
+
+ <category name="Mali Job Manager" per_cpu="no">
+
+ <event counter="ARM_Mali-T62x_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles GPU active"/>
+ <event counter="ARM_Mali-T62x_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles GPU interrupt pending"/>
+ <event counter="ARM_Mali-T62x_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) active"/>
+ <event counter="ARM_Mali-T62x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
+ <event counter="ARM_Mali-T62x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
+
+ <event counter="ARM_Mali-T62x_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+ <event counter="ARM_Mali-T62x_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+ <event counter="ARM_Mali-T62x_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+ <event counter="ARM_Mali-T62x_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+ <event counter="ARM_Mali-T62x_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
+ <event counter="ARM_Mali-T62x_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+ </category>
+
+ <category name="Mali Tiler" per_cpu="no">
+
+ <event counter="ARM_Mali-T62x_TI_ACTIVE" title="Mali Tiler Cycles" name="Tiler cycles" description="Number of cycles Tiler active"/>
+
+ <event counter="ARM_Mali-T62x_TI_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
+ <event counter="ARM_Mali-T62x_TI_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
+ <event counter="ARM_Mali-T62x_TI_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
+ <event counter="ARM_Mali-T62x_TI_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
+ <event counter="ARM_Mali-T62x_TI_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+
+ <event counter="ARM_Mali-T62x_TI_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
+ <event counter="ARM_Mali-T62x_TI_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
+ <event counter="ARM_Mali-T62x_TI_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
+ <event counter="ARM_Mali-T62x_TI_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
+ <event counter="ARM_Mali-T62x_TI_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+
+ <event counter="ARM_Mali-T62x_TI_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL3" title="Mali Tiler Hierarchy" name="L3 prims" description="Number of primitives in hierarchy level 3"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL4" title="Mali Tiler Hierarchy" name="L4 prims" description="Number of primitives in hierarchy level 4"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
+
+ </category>
+
+ <category name="Mali Shader Core" per_cpu="no">
+
+ <event counter="ARM_Mali-T62x_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles tripipe was active"/>
+ <event counter="ARM_Mali-T62x_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
+ <event counter="ARM_Mali-T62x_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
+ <event counter="ARM_Mali-T62x_FRAG_CYCLES_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+ <event counter="ARM_Mali-T62x_FRAG_CYCLES_FPKQ_ACTIVE" title="Mali Core Cycles" name="Fragment cycles pre-pipe buffer not empty" description="Number of cycles the pre-pipe queue contains quads"/>
+
+ <event counter="ARM_Mali-T62x_FRAG_THREADS" title="Mali Fragment Threads" name="Fragment threads" description="Number of fragment threads started"/>
+ <event counter="ARM_Mali-T62x_FRAG_DUMMY_THREADS" title="Mali Fragment Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
+ <event counter="ARM_Mali-T62x_FRAG_THREADS_LZS_TEST" title="Mali Fragment Threads" name="Fragment threads doing late ZS" description="Number of threads doing late ZS test"/>
+ <event counter="ARM_Mali-T62x_FRAG_THREADS_LZS_KILLED" title="Mali Fragment Threads" name="Fragment threads killed late ZS" description="Number of threads killed by late ZS test"/>
+
+ <event counter="ARM_Mali-T62x_COMPUTE_TASKS" title="Mali Compute Tasks" name="Compute tasks" description="Number of compute tasks"/>
+ <event counter="ARM_Mali-T62x_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads" description="Number of compute threads started"/>
+
+ <event counter="ARM_Mali-T62x_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+ <event counter="ARM_Mali-T62x_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+
+ <event counter="ARM_Mali-T62x_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
+ <event counter="ARM_Mali-T62x_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
+ <event counter="ARM_Mali-T62x_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+
+ <event counter="ARM_Mali-T62x_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
+ <event counter="ARM_Mali-T62x_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+
+ <event counter="ARM_Mali-T62x_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
+
+ <event counter="ARM_Mali-T62x_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
+ <event counter="ARM_Mali-T62x_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+
+ <event counter="ARM_Mali-T62x_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
+ <event counter="ARM_Mali-T62x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
+ <event counter="ARM_Mali-T62x_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
+
+ <event counter="ARM_Mali-T62x_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+
+ </category>
+
+ <category name="Mali L2 Cache" per_cpu="no">
+
+ <event counter="ARM_Mali-T62x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
+ <event counter="ARM_Mali-T62x_L2_EXT_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
+ <event counter="ARM_Mali-T62x_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
+ <event counter="ARM_Mali-T62x_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T62x_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
+ <event counter="ARM_Mali-T62x_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T62x_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T62x_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T62x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
+ <event counter="ARM_Mali-T62x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
+ <event counter="ARM_Mali-T62x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
+ <event counter="ARM_Mali-T62x_L2_READ_LOOKUP" title="Mali L2 Cache" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+ <event counter="ARM_Mali-T62x_L2_WRITE_LOOKUP" title="Mali L2 Cache" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+
+ </category>
diff --git a/tools/gator/daemon/events-Mali-T6xx.xml b/tools/gator/daemon/events-Mali-T6xx.xml
deleted file mode 100644
index 5e89797..0000000
--- a/tools/gator/daemon/events-Mali-T6xx.xml
+++ /dev/null
@@ -1,46 +0,0 @@
- <category name="Mali-T6xx Software Counters" per_cpu="no">
- <event counter="ARM_Mali-T6xx_TOTAL_ALLOC_PAGES" title="Mali Total Alloc Pages" name="Total number of allocated pages" description="Mali total number of allocated pages."/>
- </category>
- <category name="Mali-T6xx PM Shader" per_cpu="no">
- <event counter="ARM_Mali-T6xx_PM_SHADER_0" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 0" description="Mali PM Shader: PM Shader Core 0."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_1" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 1" description="Mali PM Shader: PM Shader Core 1."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_2" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 2" description="Mali PM Shader: PM Shader Core 2."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_3" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 3" description="Mali PM Shader: PM Shader Core 3."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_4" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 4" description="Mali PM Shader: PM Shader Core 4."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_5" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 5" description="Mali PM Shader: PM Shader Core 5."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_6" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 6" description="Mali PM Shader: PM Shader Core 6."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_7" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 7" description="Mali PM Shader: PM Shader Core 7."/>
- </category>
- <category name="Mali-T6xx PM Tiler" per_cpu="no">
- <event counter="ARM_Mali-T6xx_PM_TILER_0" display="average" average_selection="yes" percentage="yes" title="Mali PM Tiler" name="PM Tiler Core 0" description="Mali PM Tiler: PM Tiler Core 0."/>
- </category>
- <category name="Mali-T6xx PM L2" per_cpu="no">
- <event counter="ARM_Mali-T6xx_PM_L2_0" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 0" description="Mali PM L2: PM L2 Core 0."/>
- <event counter="ARM_Mali-T6xx_PM_L2_1" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 1" description="Mali PM L2: PM L2 Core 1."/>
- </category>
- <category name="Mali-T6xx MMU Address Space" per_cpu="no">
- <event counter="ARM_Mali-T6xx_MMU_AS_0" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 0" description="Mali MMU Address Space 0 usage."/>
- <event counter="ARM_Mali-T6xx_MMU_AS_1" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 1" description="Mali MMU Address Space 1 usage."/>
- <event counter="ARM_Mali-T6xx_MMU_AS_2" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 2" description="Mali MMU Address Space 2 usage."/>
- <event counter="ARM_Mali-T6xx_MMU_AS_3" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 3" description="Mali MMU Address Space 3 usage."/>
- </category>
- <category name="Mali-T6xx MMU Page Fault" per_cpu="no">
- <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_0" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 0" description="Reports the number of newly allocated pages after a MMU page fault in address space 0."/>
- <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_1" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 1" description="Reports the number of newly allocated pages after a MMU page fault in address space 1."/>
- <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_2" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 2" description="Reports the number of newly allocated pages after a MMU page fault in address space 2."/>
- <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_3" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 3" description="Reports the number of newly allocated pages after a MMU page fault in address space 3."/>
- </category>
- <counter_set name="ARM_Mali-T6xx_Filmstrip_cnt" count="1"/>
- <category name="Mali-T6xx Filmstrip" counter_set="ARM_Mali-T6xx_Filmstrip_cnt" per_cpu="no">
- <option_set name="fs">
- <option event_delta="0x3c" name="1:60" description="captures every 60th frame"/>
- <option event_delta="0x1e" name="1:30" description="captures every 30th frame"/>
- <option event_delta="0xa" name="1:10" description="captures every 10th frame"/>
- </option_set>
- <event event="0x0400" option_set="fs" title="ARM Mali-T6xx" name="Filmstrip" description="Scaled framebuffer"/>
- </category>
- <category name="Mali-T6xx Activity" per_cpu="no">
- <event counter="ARM_Mali-T6xx_fragment" title="GPU Fragment" name="Activity" class="activity" activity1="Activity" activity_color1="0x00006fcc" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 0 Activity"/>
- <event counter="ARM_Mali-T6xx_vertex" title="GPU Vertex-Tiling-Compute" name="Activity" class="activity" activity1="Activity" activity_color1="0x00eda000" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 1 Activity"/>
- <event counter="ARM_Mali-T6xx_opencl" title="GPU Vertex-Compute" name="Activity" class="activity" activity1="Activity" activity_color1="0x00ef022f" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 2 Activity"/>
- </category>
diff --git a/tools/gator/daemon/events-Mali-T6xx_hw.xml b/tools/gator/daemon/events-Mali-T6xx_hw.xml
deleted file mode 100644
index df27962..0000000
--- a/tools/gator/daemon/events-Mali-T6xx_hw.xml
+++ /dev/null
@@ -1,91 +0,0 @@
- <category name="Mali-T6xx Job Manager" per_cpu="no">
- <event counter="ARM_Mali-T6xx_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles the GPU was active"/>
- <event counter="ARM_Mali-T6xx_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles the GPU had a pending interrupt"/>
- <event counter="ARM_Mali-T6xx_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) was active"/>
- <event counter="ARM_Mali-T6xx_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) was active"/>
- <event counter="ARM_Mali-T6xx_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) was active"/>
- <event counter="ARM_Mali-T6xx_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
- <event counter="ARM_Mali-T6xx_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
- <event counter="ARM_Mali-T6xx_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
- <event counter="ARM_Mali-T6xx_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
- <event counter="ARM_Mali-T6xx_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
- <event counter="ARM_Mali-T6xx_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
- </category>
- <category name="Mali-T6xx Tiler" per_cpu="no">
- <event counter="ARM_Mali-T6xx_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
- <event counter="ARM_Mali-T6xx_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
- <event counter="ARM_Mali-T6xx_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
- <event counter="ARM_Mali-T6xx_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
- <event counter="ARM_Mali-T6xx_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
- <event counter="ARM_Mali-T6xx_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
- <event counter="ARM_Mali-T6xx_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
- <event counter="ARM_Mali-T6xx_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
- <event counter="ARM_Mali-T6xx_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
- <event counter="ARM_Mali-T6xx_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
- <event counter="ARM_Mali-T6xx_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
- <event counter="ARM_Mali-T6xx_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
- <event counter="ARM_Mali-T6xx_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
- <event counter="ARM_Mali-T6xx_LEVEL3" title="Mali Tiler Hierarchy" name="L3 prims" description="Number of primitives in hierarchy level 3"/>
- <event counter="ARM_Mali-T6xx_LEVEL4" title="Mali Tiler Hierarchy" name="L4 prims" description="Number of primitives in hierarchy level 4"/>
- <event counter="ARM_Mali-T6xx_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
- <event counter="ARM_Mali-T6xx_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
- <event counter="ARM_Mali-T6xx_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
- <event counter="ARM_Mali-T6xx_COMMAND_1" title="Mali Tiler Commands" name="Prims in 1 command" description="Number of primitives producing 1 command"/>
- <event counter="ARM_Mali-T6xx_COMMAND_2" title="Mali Tiler Commands" name="Prims in 2 command" description="Number of primitives producing 2 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_3" title="Mali Tiler Commands" name="Prims in 3 command" description="Number of primitives producing 3 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_4" title="Mali Tiler Commands" name="Prims in 4 command" description="Number of primitives producing 4 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_4_7" title="Mali Tiler Commands" name="Prims in 4-7 commands" description="Number of primitives producing 4-7 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_5_7" title="Mali Tiler Commands" name="Prims in 5-7 commands" description="Number of primitives producing 5-7 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_8_15" title="Mali Tiler Commands" name="Prims in 8-15 commands" description="Number of primitives producing 8-15 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_16_63" title="Mali Tiler Commands" name="Prims in 16-63 commands" description="Number of primitives producing 16-63 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_64" title="Mali Tiler Commands" name="Prims in &gt;= 64 commands" description="Number of primitives producing &gt;= 64 commands"/>
- </category>
- <category name="Mali-T6xx Shader Core" per_cpu="no">
- <event counter="ARM_Mali-T6xx_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles the Tripipe was active"/>
- <event counter="ARM_Mali-T6xx_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
- <event counter="ARM_Mali-T6xx_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
- <event counter="ARM_Mali-T6xx_FRAG_CYCLE_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
- <event counter="ARM_Mali-T6xx_FRAG_THREADS" title="Mali Core Threads" name="Fragment threads" description="Number of fragment threads started"/>
- <event counter="ARM_Mali-T6xx_FRAG_DUMMY_THREADS" title="Mali Core Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_THREADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_THREADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
- <event counter="ARM_Mali-T6xx_COMPUTE_TASKS" title="Mali Compute Threads" name="Compute tasks" description="Number of compute tasks"/>
- <event counter="ARM_Mali-T6xx_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads started" description="Number of compute threads started"/>
- <event counter="ARM_Mali-T6xx_COMPUTE_CYCLES_DESC" title="Mali Compute Threads" name="Compute cycles awaiting descriptors" description="Number of compute cycles spent waiting for descriptors"/>
- <event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
- <event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
- <event counter="ARM_Mali-T6xx_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
- <event counter="ARM_Mali-T6xx_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
- <event counter="ARM_Mali-T6xx_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
- <event counter="ARM_Mali-T6xx_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
- <event counter="ARM_Mali-T6xx_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
- <event counter="ARM_Mali-T6xx_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
- <event counter="ARM_Mali-T6xx_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
- <event counter="ARM_Mali-T6xx_TEX_THREADS" title="Mali Texture Pipe" name="T instruction issues" description="Number of instructions issused to the T-pipe, including restarts"/>
- <event counter="ARM_Mali-T6xx_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
- <event counter="ARM_Mali-T6xx_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
- </category>
- <category name="Mali-T6xx L2 and MMU" per_cpu="no">
- <event counter="ARM_Mali-T6xx_L2_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
- <event counter="ARM_Mali-T6xx_L2_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
- <event counter="ARM_Mali-T6xx_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
- <event counter="ARM_Mali-T6xx_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
- <event counter="ARM_Mali-T6xx_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
- <event counter="ARM_Mali-T6xx_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
- <event counter="ARM_Mali-T6xx_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
- <event counter="ARM_Mali-T6xx_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
- </category>
diff --git a/tools/gator/daemon/events-Mali-T72x_hw.xml b/tools/gator/daemon/events-Mali-T72x_hw.xml
new file mode 100644
index 0000000..5587534
--- /dev/null
+++ b/tools/gator/daemon/events-Mali-T72x_hw.xml
@@ -0,0 +1,95 @@
+
+ <category name="Mali Job Manager" per_cpu="no">
+
+ <event counter="ARM_Mali-T72x_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles GPU active"/>
+ <event counter="ARM_Mali-T72x_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles GPU interrupt pending"/>
+ <event counter="ARM_Mali-T72x_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) active"/>
+ <event counter="ARM_Mali-T72x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
+ <event counter="ARM_Mali-T72x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
+
+ <event counter="ARM_Mali-T72x_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+ <event counter="ARM_Mali-T72x_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+ <event counter="ARM_Mali-T72x_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+ <event counter="ARM_Mali-T72x_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+ <event counter="ARM_Mali-T72x_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
+ <event counter="ARM_Mali-T72x_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+ </category>
+
+ <category name="Mali Tiler" per_cpu="no">
+
+ <event counter="ARM_Mali-T72x_TI_ACTIVE" title="Mali Tiler Cycles" name="Tiler cycles" description="Number of cycles Tiler active"/>
+
+ <event counter="ARM_Mali-T72x_TI_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
+ <event counter="ARM_Mali-T72x_TI_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
+ <event counter="ARM_Mali-T72x_TI_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
+ <event counter="ARM_Mali-T72x_TI_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
+ <event counter="ARM_Mali-T72x_TI_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+
+ <event counter="ARM_Mali-T72x_TI_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
+ <event counter="ARM_Mali-T72x_TI_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
+ <event counter="ARM_Mali-T72x_TI_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
+ <event counter="ARM_Mali-T72x_TI_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
+ <event counter="ARM_Mali-T72x_TI_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+
+ </category>
+
+ <category name="Mali Shader Core" per_cpu="no">
+
+ <event counter="ARM_Mali-T72x_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles tripipe was active"/>
+ <event counter="ARM_Mali-T72x_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
+ <event counter="ARM_Mali-T72x_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
+ <event counter="ARM_Mali-T72x_FRAG_CYCLES_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+
+ <event counter="ARM_Mali-T72x_FRAG_THREADS" title="Mali Fragment Threads" name="Fragment threads" description="Number of fragment threads started"/>
+ <event counter="ARM_Mali-T72x_FRAG_DUMMY_THREADS" title="Mali Fragment Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
+ <event counter="ARM_Mali-T72x_FRAG_THREADS_LZS_TEST" title="Mali Fragment Threads" name="Fragment threads doing late ZS" description="Number of threads doing late ZS test"/>
+ <event counter="ARM_Mali-T72x_FRAG_THREADS_LZS_KILLED" title="Mali Fragment Threads" name="Fragment threads killed late ZS" description="Number of threads killed by late ZS test"/>
+
+ <event counter="ARM_Mali-T72x_COMPUTE_TASKS" title="Mali Compute Tasks" name="Compute tasks" description="Number of compute tasks"/>
+ <event counter="ARM_Mali-T72x_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads" description="Number of compute threads started"/>
+
+ <event counter="ARM_Mali-T72x_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+ <event counter="ARM_Mali-T72x_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+
+ <event counter="ARM_Mali-T72x_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
+ <event counter="ARM_Mali-T72x_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
+ <event counter="ARM_Mali-T72x_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+
+ <event counter="ARM_Mali-T72x_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
+ <event counter="ARM_Mali-T72x_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+
+ <event counter="ARM_Mali-T72x_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of batched instructions executed by the A-pipe"/>
+
+ <event counter="ARM_Mali-T72x_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
+ <event counter="ARM_Mali-T72x_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+
+ <event counter="ARM_Mali-T72x_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
+ <event counter="ARM_Mali-T72x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
+
+ <event counter="ARM_Mali-T72x_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+
+ </category>
+
+ <category name="Mali L2 Cache" per_cpu="no">
+
+ <event counter="ARM_Mali-T72x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
+ <event counter="ARM_Mali-T72x_L2_EXT_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
+ <event counter="ARM_Mali-T72x_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
+ <event counter="ARM_Mali-T72x_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T72x_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
+ <event counter="ARM_Mali-T72x_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T72x_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T72x_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T72x_L2_READ_LOOKUP" title="Mali L2 Cache" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+ <event counter="ARM_Mali-T72x_L2_WRITE_LOOKUP" title="Mali L2 Cache" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+
+ </category>
diff --git a/tools/gator/daemon/events-Mali-T76x_hw.xml b/tools/gator/daemon/events-Mali-T76x_hw.xml
new file mode 100644
index 0000000..be74c5a
--- /dev/null
+++ b/tools/gator/daemon/events-Mali-T76x_hw.xml
@@ -0,0 +1,108 @@
+
+ <category name="Mali Job Manager" per_cpu="no">
+
+ <event counter="ARM_Mali-T76x_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles GPU active"/>
+ <event counter="ARM_Mali-T76x_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles GPU interrupt pending"/>
+ <event counter="ARM_Mali-T76x_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) active"/>
+ <event counter="ARM_Mali-T76x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
+ <event counter="ARM_Mali-T76x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
+
+ <event counter="ARM_Mali-T76x_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+ <event counter="ARM_Mali-T76x_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+ <event counter="ARM_Mali-T76x_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+ <event counter="ARM_Mali-T76x_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+ <event counter="ARM_Mali-T76x_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
+ <event counter="ARM_Mali-T76x_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+ </category>
+
+ <category name="Mali Tiler" per_cpu="no">
+
+ <event counter="ARM_Mali-T76x_TI_ACTIVE" title="Mali Tiler Cycles" name="Tiler cycles" description="Number of cycles Tiler active"/>
+
+ <event counter="ARM_Mali-T76x_TI_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
+ <event counter="ARM_Mali-T76x_TI_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
+ <event counter="ARM_Mali-T76x_TI_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
+ <event counter="ARM_Mali-T76x_TI_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
+ <event counter="ARM_Mali-T76x_TI_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+
+ <event counter="ARM_Mali-T76x_TI_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
+ <event counter="ARM_Mali-T76x_TI_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
+ <event counter="ARM_Mali-T76x_TI_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
+ <event counter="ARM_Mali-T76x_TI_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
+ <event counter="ARM_Mali-T76x_TI_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+
+ <event counter="ARM_Mali-T76x_TI_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL3" title="Mali Tiler Hierarchy" name="L3 prims" description="Number of primitives in hierarchy level 3"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL4" title="Mali Tiler Hierarchy" name="L4 prims" description="Number of primitives in hierarchy level 4"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
+
+ </category>
+
+ <category name="Mali Shader Core" per_cpu="no">
+
+ <event counter="ARM_Mali-T76x_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles tripipe was active"/>
+ <event counter="ARM_Mali-T76x_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
+ <event counter="ARM_Mali-T76x_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
+ <event counter="ARM_Mali-T76x_FRAG_CYCLES_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+ <event counter="ARM_Mali-T76x_FRAG_CYCLES_FPKQ_ACTIVE" title="Mali Core Cycles" name="Fragment cycles pre-pipe buffer not empty" description="Number of cycles the pre-pipe queue contains quads"/>
+
+ <event counter="ARM_Mali-T76x_FRAG_THREADS" title="Mali Fragment Threads" name="Fragment threads" description="Number of fragment threads started"/>
+ <event counter="ARM_Mali-T76x_FRAG_DUMMY_THREADS" title="Mali Fragment Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
+ <event counter="ARM_Mali-T76x_FRAG_THREADS_LZS_TEST" title="Mali Fragment Threads" name="Fragment threads doing late ZS" description="Number of threads doing late ZS test"/>
+ <event counter="ARM_Mali-T76x_FRAG_THREADS_LZS_KILLED" title="Mali Fragment Threads" name="Fragment threads killed late ZS" description="Number of threads killed by late ZS test"/>
+
+ <event counter="ARM_Mali-T76x_COMPUTE_TASKS" title="Mali Compute Tasks" name="Compute tasks" description="Number of compute tasks"/>
+ <event counter="ARM_Mali-T76x_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads" description="Number of compute threads started"/>
+
+ <event counter="ARM_Mali-T76x_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+ <event counter="ARM_Mali-T76x_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+
+ <event counter="ARM_Mali-T76x_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
+ <event counter="ARM_Mali-T76x_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
+ <event counter="ARM_Mali-T76x_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+
+ <event counter="ARM_Mali-T76x_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
+ <event counter="ARM_Mali-T76x_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+
+ <event counter="ARM_Mali-T76x_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
+
+ <event counter="ARM_Mali-T76x_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
+ <event counter="ARM_Mali-T76x_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+