gator: Version 5.20
authorJon Medhurst <tixy@linaro.org>
Thu, 30 Oct 2014 18:01:15 +0000 (18:01 +0000)
committerJon Medhurst <tixy@linaro.org>
Thu, 30 Oct 2014 18:04:22 +0000 (18:04 +0000)
Signed-off-by: Jon Medhurst <tixy@linaro.org>
148 files changed:
drivers/gator/Kconfig
drivers/gator/Makefile
drivers/gator/gator.h
drivers/gator/gator_annotate.c
drivers/gator/gator_annotate_kernel.c
drivers/gator/gator_backtrace.c
drivers/gator/gator_buffer.c
drivers/gator/gator_buffer_write.c
drivers/gator/gator_cookies.c
drivers/gator/gator_events_armv6.c
drivers/gator/gator_events_armv7.c
drivers/gator/gator_events_block.c
drivers/gator/gator_events_ccn-504.c [deleted file]
drivers/gator/gator_events_irq.c
drivers/gator/gator_events_l2c-310.c
drivers/gator/gator_events_mali_4xx.c
drivers/gator/gator_events_mali_common.c
drivers/gator/gator_events_mali_common.h
drivers/gator/gator_events_mali_midgard.c [new file with mode: 0644]
drivers/gator/gator_events_mali_midgard_hw.c [new file with mode: 0644]
drivers/gator/gator_events_mali_midgard_hw_test.c [new file with mode: 0644]
drivers/gator/gator_events_mali_t6xx.c [deleted file]
drivers/gator/gator_events_mali_t6xx_hw.c [deleted file]
drivers/gator/gator_events_mali_t6xx_hw_test.c [deleted file]
drivers/gator/gator_events_meminfo.c
drivers/gator/gator_events_mmapped.c
drivers/gator/gator_events_net.c
drivers/gator/gator_events_perf_pmu.c
drivers/gator/gator_events_sched.c
drivers/gator/gator_events_scorpion.c
drivers/gator/gator_events_threads.c [deleted file]
drivers/gator/gator_fs.c
drivers/gator/gator_hrtimer_gator.c
drivers/gator/gator_iks.c
drivers/gator/gator_main.c
drivers/gator/gator_marshaling.c
drivers/gator/gator_trace_gpu.c
drivers/gator/gator_trace_power.c
drivers/gator/gator_trace_sched.c
drivers/gator/mali/mali_dd_gator_api.h [deleted file]
drivers/gator/mali/mali_kbase_gator_api.h [new file with mode: 0644]
drivers/gator/mali/mali_mjollnir_profiling_gator_api.h
drivers/gator/mali/mali_utgard_profiling_gator_api.h
drivers/gator/mali_midgard.mk [new file with mode: 0644]
drivers/gator/mali_t6xx.mk [deleted file]
tools/gator/daemon/Android.mk
tools/gator/daemon/AnnotateListener.cpp [new file with mode: 0644]
tools/gator/daemon/AnnotateListener.h [new file with mode: 0644]
tools/gator/daemon/Application.mk
tools/gator/daemon/Buffer.cpp
tools/gator/daemon/Buffer.h
tools/gator/daemon/CCNDriver.cpp [new file with mode: 0644]
tools/gator/daemon/CCNDriver.h [new file with mode: 0644]
tools/gator/daemon/CPUFreqDriver.cpp [new file with mode: 0644]
tools/gator/daemon/CPUFreqDriver.h [new file with mode: 0644]
tools/gator/daemon/CapturedXML.cpp
tools/gator/daemon/CapturedXML.h
tools/gator/daemon/Child.cpp
tools/gator/daemon/Child.h
tools/gator/daemon/Command.cpp [new file with mode: 0644]
tools/gator/daemon/Command.h [new file with mode: 0644]
tools/gator/daemon/Config.h
tools/gator/daemon/DiskIODriver.cpp [new file with mode: 0644]
tools/gator/daemon/DiskIODriver.h [new file with mode: 0644]
tools/gator/daemon/Driver.cpp
tools/gator/daemon/Driver.h
tools/gator/daemon/DriverSource.cpp
tools/gator/daemon/DynBuf.cpp
tools/gator/daemon/EventsXML.cpp
tools/gator/daemon/ExternalSource.cpp
tools/gator/daemon/ExternalSource.h
tools/gator/daemon/FSDriver.cpp
tools/gator/daemon/FSDriver.h
tools/gator/daemon/Fifo.cpp
tools/gator/daemon/Fifo.h
tools/gator/daemon/FtraceDriver.cpp [new file with mode: 0644]
tools/gator/daemon/FtraceDriver.h [new file with mode: 0644]
tools/gator/daemon/FtraceSource.cpp [new file with mode: 0644]
tools/gator/daemon/FtraceSource.h [new file with mode: 0644]
tools/gator/daemon/Hwmon.cpp [deleted file]
tools/gator/daemon/Hwmon.h [deleted file]
tools/gator/daemon/HwmonDriver.cpp [new file with mode: 0644]
tools/gator/daemon/HwmonDriver.h [new file with mode: 0644]
tools/gator/daemon/KMod.cpp
tools/gator/daemon/KMod.h
tools/gator/daemon/LocalCapture.h
tools/gator/daemon/Logging.cpp
tools/gator/daemon/Logging.h
tools/gator/daemon/Makefile
tools/gator/daemon/MaliVideoDriver.cpp
tools/gator/daemon/MaliVideoDriver.h
tools/gator/daemon/MemInfoDriver.cpp [new file with mode: 0644]
tools/gator/daemon/MemInfoDriver.h [new file with mode: 0644]
tools/gator/daemon/Monitor.cpp
tools/gator/daemon/NetDriver.cpp [new file with mode: 0644]
tools/gator/daemon/NetDriver.h [new file with mode: 0644]
tools/gator/daemon/OlySocket.cpp
tools/gator/daemon/OlySocket.h
tools/gator/daemon/PerfBuffer.cpp
tools/gator/daemon/PerfBuffer.h
tools/gator/daemon/PerfDriver.cpp
tools/gator/daemon/PerfDriver.h
tools/gator/daemon/PerfGroup.cpp
tools/gator/daemon/PerfGroup.h
tools/gator/daemon/PerfSource.cpp
tools/gator/daemon/PerfSource.h
tools/gator/daemon/Proc.cpp
tools/gator/daemon/Proc.h
tools/gator/daemon/Sender.cpp
tools/gator/daemon/Sender.h
tools/gator/daemon/SessionData.cpp
tools/gator/daemon/SessionData.h
tools/gator/daemon/SessionXML.cpp
tools/gator/daemon/SessionXML.h
tools/gator/daemon/Setup.cpp [new file with mode: 0644]
tools/gator/daemon/Setup.h [new file with mode: 0644]
tools/gator/daemon/StreamlineSetup.h
tools/gator/daemon/UEvent.cpp
tools/gator/daemon/UserSpaceSource.cpp
tools/gator/daemon/defaults.xml
tools/gator/daemon/events-Cortex-A12.xml [deleted file]
tools/gator/daemon/events-Cortex-A17.xml [new file with mode: 0644]
tools/gator/daemon/events-Filesystem.xml
tools/gator/daemon/events-Linux.xml
tools/gator/daemon/events-Mali-Midgard.xml [new file with mode: 0644]
tools/gator/daemon/events-Mali-Midgard_hw.xml [new file with mode: 0644]
tools/gator/daemon/events-Mali-T60x_hw.xml [new file with mode: 0644]
tools/gator/daemon/events-Mali-T62x_hw.xml [new file with mode: 0644]
tools/gator/daemon/events-Mali-T6xx.xml [deleted file]
tools/gator/daemon/events-Mali-T6xx_hw.xml [deleted file]
tools/gator/daemon/events-Mali-T72x_hw.xml [new file with mode: 0644]
tools/gator/daemon/events-Mali-T76x_hw.xml [new file with mode: 0644]
tools/gator/daemon/events-Mali-V500.xml
tools/gator/daemon/events-ftrace.xml [new file with mode: 0644]
tools/gator/daemon/main.cpp
tools/gator/daemon/mxml/config.h
tools/gator/daemon/mxml/mxml-attr.c
tools/gator/daemon/mxml/mxml-entity.c
tools/gator/daemon/mxml/mxml-file.c
tools/gator/daemon/mxml/mxml-get.c
tools/gator/daemon/mxml/mxml-index.c
tools/gator/daemon/mxml/mxml-node.c
tools/gator/daemon/mxml/mxml-private.c
tools/gator/daemon/mxml/mxml-private.h
tools/gator/daemon/mxml/mxml-search.c
tools/gator/daemon/mxml/mxml-set.c
tools/gator/daemon/mxml/mxml-string.c
tools/gator/daemon/mxml/mxml.h

index e46ccb9b8064546102c13832763becf2b0b71273..b2358bbc1293a721c47c37981afa54bb0606f409 100644 (file)
@@ -24,8 +24,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
index 2f86823313c644b83c7b0f522df5637e4cafbb7d..28d2070b11d54304605612c05b1dd198f3afc783 100644 (file)
@@ -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
 
index 5ad0254d86a9d7bb514fbbebafbc1de61ca475a0..5cc73a388c4f71a13fd5baecf4a42e68c36f3922 100644 (file)
 #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
 #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_ */
index 7e2c6e5d871510033cb92c971a9a53235023b601..ff9a3cef7b2e3b8b3bc51d7dc4d5d632e46cf70f 100644 (file)
 #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);
index 0108068255297285859854a15bc632579365de15..69471f99e5fb3769957dc2d341a4792cf89c1302 100644 (file)
@@ -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 charstr)
+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 charstr)
+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);
index e03c1653c5b5f63a3b4dcde8a5ef3ed1c5d5f781..76c941d009a9afdcaf15fa682b3bd40004b39166 100644 (file)
@@ -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);
        }
index dfbc97d80221bbe883434fa3db49e7a2669ecdbe..910d5aa1506697d0c22dc0120547b92e6f24a0bd 100644 (file)
 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);
-       }
 }
index b621ba93ee5e452e89bd8ab32a49e11118e0c496..654ec606cfad66d1dd776bd5c44039a856e36f20 100644 (file)
@@ -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);
 }
index 5c7d842070e0097325cf6b4602dcfb8688e94c50..c43cce81522649c00e61bfbde8bde4da178cfd0e 100644 (file)
@@ -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;
        }
index 353645622306048fbcd6f06e6af15da68a1544b0..a157a0013302e8e5aaaf998c074352135a22be4c 100644 (file)
@@ -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));
index bd8a9ba24e99913e197b4403f2f32479396edf2d..09c94220114ca018f0a42986ba24dce7e579b255 100644 (file)
 
 #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;
index 03eed4fb9ebb057003e0e5d7b8e61f14490ba69e..a352a54afa025d5ab4927fd3936f9807fb815b8e 100644 (file)
@@ -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 (file)
index 024ffc2..0000000
+++ /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);
-}
index facbdd62325eccbc722a82f516ac15652a7ad860..5221aac581b3327aa34fda11f5e2c3bd7b879aed 100644 (file)
@@ -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();
index 553f9707bdbf6161b3b0d850c6e41556d8e7a1e8..73aaac32327e8ea1582557e6839f718c8da5d94c 100644 (file)
@@ -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;
index 9e1c7064bd738024e11aeb54ae6504eab81b2bfc..9cf43fe2c29b3565d93096a58cf8ad73b3c2eccd 100644 (file)
@@ -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 charconst 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;
 }
index 4f2cce4ce67bda42e47156ed7d31c343b960137a..1af87d649afe0f763b5f617ba88c5bc04cdcd16f 100644 (file)
@@ -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;
index 91d871bc915a1cd4c7b5409cdaf1e719e46e8ec1..e7082e62fe88c3b0250b5a52dbcc283bcbb84c63 100644 (file)
@@ -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
 /*
  * 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_midgard.c b/drivers/gator/gator_events_mali_midgard.c
new file mode 100644 (file)
index 0000000..0aec906
--- /dev/null
@@ -0,0 +1,562 @@
+/**
+ * Copyright (C) ARM Limited 2011-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 "gator.h"
+
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/math64.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+#ifdef MALI_DIR_MIDGARD
+/* New DDK Directory structure with kernel/drivers/gpu/arm/midgard*/
+#include "mali_linux_trace.h"
+#else
+/* Old DDK Directory structure with kernel/drivers/gpu/arm/t6xx*/
+#include "linux/mali_linux_trace.h"
+#endif
+
+#include "gator_events_mali_common.h"
+
+/*
+ * Check that the MALI_SUPPORT define is set to one of the allowable device codes.
+ */
+#if (MALI_SUPPORT != MALI_MIDGARD)
+#error MALI_SUPPORT set to an invalid device code: expecting MALI_MIDGARD
+#endif
+
+static const char mali_name[] = "Midgard";
+
+/* Counters for Mali-Midgard:
+ *
+ *  - Timeline events
+ *    They are tracepoints, but instead of reporting a number they report a START/STOP event.
+ *    They are reported in Streamline as number of microseconds while that particular counter was active.
+ *
+ *  - SW counters
+ *    They are tracepoints reporting a particular number.
+ *    They are accumulated in sw_counter_data array until they are passed to Streamline, then they are zeroed.
+ *
+ *  - Accumulators
+ *    They are the same as software counters but their value is not zeroed.
+ */
+
+/* Timeline (start/stop) activity */
+static const char *const timeline_event_names[] = {
+       "PM_SHADER_0",
+       "PM_SHADER_1",
+       "PM_SHADER_2",
+       "PM_SHADER_3",
+       "PM_SHADER_4",
+       "PM_SHADER_5",
+       "PM_SHADER_6",
+       "PM_SHADER_7",
+       "PM_TILER_0",
+       "PM_L2_0",
+       "PM_L2_1",
+       "MMU_AS_0",
+       "MMU_AS_1",
+       "MMU_AS_2",
+       "MMU_AS_3"
+};
+
+enum {
+       PM_SHADER_0 = 0,
+       PM_SHADER_1,
+       PM_SHADER_2,
+       PM_SHADER_3,
+       PM_SHADER_4,
+       PM_SHADER_5,
+       PM_SHADER_6,
+       PM_SHADER_7,
+       PM_TILER_0,
+       PM_L2_0,
+       PM_L2_1,
+       MMU_AS_0,
+       MMU_AS_1,
+       MMU_AS_2,
+       MMU_AS_3
+};
+/* The number of shader blocks in the enum above */
+#define NUM_PM_SHADER (8)
+
+/* Software Counters */
+static const char *const software_counter_names[] = {
+       "MMU_PAGE_FAULT_0",
+       "MMU_PAGE_FAULT_1",
+       "MMU_PAGE_FAULT_2",
+       "MMU_PAGE_FAULT_3"
+};
+
+enum {
+       MMU_PAGE_FAULT_0 = 0,
+       MMU_PAGE_FAULT_1,
+       MMU_PAGE_FAULT_2,
+       MMU_PAGE_FAULT_3
+};
+
+/* Software Counters */
+static const char *const accumulators_names[] = {
+       "TOTAL_ALLOC_PAGES"
+};
+
+enum {
+       TOTAL_ALLOC_PAGES = 0
+};
+
+#define FIRST_TIMELINE_EVENT (0)
+#define NUMBER_OF_TIMELINE_EVENTS (sizeof(timeline_event_names) / sizeof(timeline_event_names[0]))
+#define FIRST_SOFTWARE_COUNTER (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS)
+#define NUMBER_OF_SOFTWARE_COUNTERS (sizeof(software_counter_names) / sizeof(software_counter_names[0]))
+#define FIRST_ACCUMULATOR (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS)
+#define NUMBER_OF_ACCUMULATORS (sizeof(accumulators_names) / sizeof(accumulators_names[0]))
+#define FILMSTRIP (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS)
+#define NUMBER_OF_EVENTS (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS + 1)
+
+/*
+ * gatorfs variables for counter enable state
+ */
+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 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.
+ */
+static struct timespec timeline_event_starttime[NUMBER_OF_TIMELINE_EVENTS];
+
+/* The data we have recorded */
+static unsigned int timeline_data[NUMBER_OF_TIMELINE_EVENTS];
+static unsigned int sw_counter_data[NUMBER_OF_SOFTWARE_COUNTERS];
+static unsigned int accumulators_data[NUMBER_OF_ACCUMULATORS];
+
+/* Hold the previous timestamp, used to calculate the sample interval. */
+static struct timespec prev_timestamp;
+
+/**
+ * Returns the timespan (in microseconds) between the two specified timestamps.
+ *
+ * @param start Ptr to the start timestamp
+ * @param end Ptr to the end timestamp
+ *
+ * @return Number of microseconds between the two timestamps (can be negative if start follows end).
+ */
+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;
+}
+
+static void record_timeline_event(unsigned int timeline_index, unsigned int type)
+{
+       struct timespec event_timestamp;
+       struct timespec *event_start = &timeline_event_starttime[timeline_index];
+
+       switch (type) {
+       case ACTIVITY_START:
+               /* Get the event time... */
+               getnstimeofday(&event_timestamp);
+
+               /* Remember the start time if the activity is not already started */
+               if (event_start->tv_sec == 0)
+                       *event_start = event_timestamp; /* Structure copy */
+               break;
+
+       case ACTIVITY_STOP:
+               /* if the counter was started... */
+               if (event_start->tv_sec != 0) {
+                       /* Get the event time... */
+                       getnstimeofday(&event_timestamp);
+
+                       /* Accumulate the duration in us */
+                       timeline_data[timeline_index] += get_duration_us(event_start, &event_timestamp);
+
+                       /* Reset the start time to indicate the activity is stopped. */
+                       event_start->tv_sec = 0;
+               }
+               break;
+
+       default:
+               /* Other activity events are ignored. */
+               break;
+       }
+}
+
+/*
+ * Documentation about the following tracepoints is in mali_linux_trace.h
+ */
+
+GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long long value))
+{
+#define SHADER_PRESENT_LO       0x100  /* (RO) Shader core present bitmap, low word */
+#define TILER_PRESENT_LO        0x110  /* (RO) Tiler core present bitmap, low word */
+#define L2_PRESENT_LO           0x120  /* (RO) Level 2 cache present bitmap, low word */
+#define BIT_AT(value, pos) ((value >> pos) & 1)
+
+       static unsigned long long previous_shader_bitmask;
+       static unsigned long long previous_tiler_bitmask;
+       static unsigned long long previous_l2_bitmask;
+
+       switch (event_id) {
+       case SHADER_PRESENT_LO:
+               {
+                       unsigned long long changed_bitmask = previous_shader_bitmask ^ value;
+                       int pos;
+
+                       for (pos = 0; pos < NUM_PM_SHADER; ++pos) {
+                               if (BIT_AT(changed_bitmask, pos))
+                                       record_timeline_event(PM_SHADER_0 + pos, BIT_AT(value, pos) ? ACTIVITY_START : ACTIVITY_STOP);
+                       }
+
+                       previous_shader_bitmask = value;
+                       break;
+               }
+
+       case TILER_PRESENT_LO:
+               {
+                       unsigned long long changed = previous_tiler_bitmask ^ value;
+
+                       if (BIT_AT(changed, 0))
+                               record_timeline_event(PM_TILER_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP);
+
+                       previous_tiler_bitmask = value;
+                       break;
+               }
+
+       case L2_PRESENT_LO:
+               {
+                       unsigned long long changed = previous_l2_bitmask ^ value;
+
+                       if (BIT_AT(changed, 0))
+                               record_timeline_event(PM_L2_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP);
+                       if (BIT_AT(changed, 4))
+                               record_timeline_event(PM_L2_1, BIT_AT(value, 4) ? ACTIVITY_START : ACTIVITY_STOP);
+
+                       previous_l2_bitmask = value;
+                       break;
+               }
+
+       default:
+               /* No other blocks are supported at present */
+               break;
+       }
+
+#undef SHADER_PRESENT_LO
+#undef TILER_PRESENT_LO
+#undef L2_PRESENT_LO
+#undef BIT_AT
+}
+
+GATOR_DEFINE_PROBE(mali_page_fault_insert_pages, TP_PROTO(int event_id, unsigned long value))
+{
+       /* We add to the previous since we may receive many tracepoints in one sample period */
+       sw_counter_data[MMU_PAGE_FAULT_0 + event_id] += value;
+}
+
+GATOR_DEFINE_PROBE(mali_mmu_as_in_use, TP_PROTO(int event_id))
+{
+       record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_START);
+}
+
+GATOR_DEFINE_PROBE(mali_mmu_as_released, TP_PROTO(int event_id))
+{
+       record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_STOP);
+}
+
+GATOR_DEFINE_PROBE(mali_total_alloc_pages_change, TP_PROTO(long long int event_id))
+{
+       accumulators_data[TOTAL_ALLOC_PAGES] = event_id;
+}
+
+static int create_files(struct super_block *sb, struct dentry *root)
+{
+       int event;
+       /*
+        * Create the filesystem for all events
+        */
+       int counter_index = 0;
+       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)
+                       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)
+                       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)
+                       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)
+                       return -1;
+               symbol_put(_mali_profiling_control);
+       }
+
+       return 0;
+}
+
+static int register_tracepoints(void)
+{
+       if (GATOR_REGISTER_TRACE(mali_pm_status)) {
+               pr_debug("gator: Mali-Midgard: mali_pm_status tracepoint failed to activate\n");
+               return 0;
+       }
+
+       if (GATOR_REGISTER_TRACE(mali_page_fault_insert_pages)) {
+               pr_debug("gator: Mali-Midgard: mali_page_fault_insert_pages tracepoint failed to activate\n");
+               return 0;
+       }
+
+       if (GATOR_REGISTER_TRACE(mali_mmu_as_in_use)) {
+               pr_debug("gator: Mali-Midgard: mali_mmu_as_in_use tracepoint failed to activate\n");
+               return 0;
+       }
+
+       if (GATOR_REGISTER_TRACE(mali_mmu_as_released)) {
+               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-Midgard: mali_total_alloc_pages_change tracepoint failed to activate\n");
+               return 0;
+       }
+
+       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;
+}
+
+static int start(void)
+{
+       unsigned int cnt;
+       mali_profiling_control_type *mali_control;
+
+       /* Clean all data for the next capture */
+       for (cnt = 0; cnt < NUMBER_OF_TIMELINE_EVENTS; cnt++) {
+               timeline_event_starttime[cnt].tv_sec = timeline_event_starttime[cnt].tv_nsec = 0;
+               timeline_data[cnt] = 0;
+       }
+
+       for (cnt = 0; cnt < NUMBER_OF_SOFTWARE_COUNTERS; cnt++)
+               sw_counter_data[cnt] = 0;
+
+       for (cnt = 0; cnt < NUMBER_OF_ACCUMULATORS; cnt++)
+               accumulators_data[cnt] = 0;
+
+       /* Register tracepoints */
+       if (register_tracepoints() == 0)
+               return -1;
+
+       /* Generic control interface for Mali DDK. */
+       mali_control = symbol_get(_mali_profiling_control);
+       if (mali_control) {
+               /* The event attribute in the XML file keeps the actual frame rate. */
+               unsigned int enabled = counters[FILMSTRIP].enabled ? 1 : 0;
+               unsigned int rate = filmstrip_event & 0xff;
+               unsigned int resize_factor = (filmstrip_event >> 8) & 0xff;
+
+               pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control);
+
+#define FBDUMP_CONTROL_ENABLE (1)
+#define FBDUMP_CONTROL_RATE (2)
+#define FBDUMP_CONTROL_RESIZE_FACTOR (4)
+               mali_control(FBDUMP_CONTROL_ENABLE, enabled);
+               mali_control(FBDUMP_CONTROL_RATE, rate);
+               mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor);
+
+               pr_debug("gator: sent mali_control enabled=%d, rate=%d, resize_factor=%d\n", enabled, rate, resize_factor);
+
+               symbol_put(_mali_profiling_control);
+       } else {
+               pr_err("gator: mali online _mali_profiling_control symbol not found\n");
+       }
+
+       /*
+        * Set the first timestamp for calculating the sample interval. The first interval could be quite long,
+        * since it will be the time between 'start' and the first 'read'.
+        * This means that timeline values will be divided by a big number for the first sample.
+        */
+       getnstimeofday(&prev_timestamp);
+
+       return 0;
+}
+
+static void stop(void)
+{
+       mali_profiling_control_type *mali_control;
+
+       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-Midgard: mali_pm_status tracepoint deactivated\n");
+
+       GATOR_UNREGISTER_TRACE(mali_page_fault_insert_pages);
+       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-Midgard: mali_mmu_as_in_use tracepoint deactivated\n");
+
+       GATOR_UNREGISTER_TRACE(mali_mmu_as_released);
+       pr_debug("gator: Mali-Midgard: mali_mmu_as_released tracepoint deactivated\n");
+
+       GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change);
+       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);
+       if (mali_control) {
+               pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_control);
+
+               mali_control(FBDUMP_CONTROL_ENABLE, 0);
+
+               symbol_put(_mali_profiling_control);
+       } else {
+               pr_err("gator: mali offline _mali_profiling_control symbol not found\n");
+       }
+}
+
+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())
+               return 0;
+
+       /* Get the start of this sample period. */
+       getnstimeofday(&read_timestamp);
+
+       /*
+        * Calculate the sample interval if the previous sample time is valid.
+        * We use tv_sec since it will not be 0.
+        */
+       if (prev_timestamp.tv_sec != 0)
+               sample_interval_us = get_duration_us(&prev_timestamp, &read_timestamp);
+
+       /* Structure copy. Update the previous timestamp. */
+       prev_timestamp = read_timestamp;
+
+       /*
+        * Report the timeline counters (ACTIVITY_START/STOP)
+        */
+       for (cnt = FIRST_TIMELINE_EVENT; cnt < (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS); cnt++) {
+               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 (timeline_event_starttime[index].tv_sec != 0) {
+                               const long event_duration = get_duration_us(&timeline_event_starttime[index], &read_timestamp);
+
+                               timeline_data[index] += event_duration;
+                               timeline_event_starttime[index] = read_timestamp;       /* Activity is still running. */
+                       }
+
+                       if (sample_interval_us != 0) {
+                               /* Convert the counter to a percent-of-sample value */
+                               value = (timeline_data[index] * 100) / sample_interval_us;
+                       } else {
+                               pr_debug("gator: Mali-Midgard: setting value to zero\n");
+                               value = 0;
+                       }
+
+                       /* Clear the counter value ready for the next sample. */
+                       timeline_data[index] = 0;
+
+                       counter_dump[len++] = counter->key;
+                       counter_dump[len++] = value;
+               }
+       }
+
+       /* Report the software counters */
+       for (cnt = FIRST_SOFTWARE_COUNTER; cnt < (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS); cnt++) {
+               const 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 */
+                       sw_counter_data[index] = 0;
+               }
+       }
+
+       /* Report the accumulators */
+       for (cnt = FIRST_ACCUMULATOR; cnt < (FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS); 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 */
+               }
+       }
+
+       /* Update the buffer */
+       if (buffer)
+               *buffer = counter_dump;
+
+       return len;
+}
+
+static struct gator_interface gator_events_mali_midgard_interface = {
+       .create_files = create_files,
+       .start = start,
+       .stop = stop,
+       .read = read
+};
+
+extern int gator_events_mali_midgard_init(void)
+{
+       pr_debug("gator: Mali-Midgard: sw_counters init\n");
+
+       gator_mali_initialise_counters(counters, NUMBER_OF_EVENTS);
+
+       return gator_events_install(&gator_events_mali_midgard_interface);
+}
diff --git a/drivers/gator/gator_events_mali_midgard_hw.c b/drivers/gator/gator_events_mali_midgard_hw.c
new file mode 100644 (file)
index 0000000..c8065da
--- /dev/null
@@ -0,0 +1,977 @@
+/**
+ * Copyright (C) ARM Limited 2012-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 "gator.h"
+
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/math64.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+/* Mali Midgard DDK includes */
+#if defined(MALI_SIMPLE_API)
+/* Header with wrapper functions to kbase structures and functions */
+#include "mali/mali_kbase_gator_api.h"
+#elif defined(MALI_DIR_MIDGARD)
+/* New DDK Directory structure with kernel/drivers/gpu/arm/midgard */
+#include "mali_linux_trace.h"
+#include "mali_kbase.h"
+#include "mali_kbase_mem_linux.h"
+#else
+/* 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"
+#endif
+
+/* If API version is not specified then assume API version 1. */
+#ifndef MALI_DDK_GATOR_API_VERSION
+#define MALI_DDK_GATOR_API_VERSION 1
+#endif
+
+#if (MALI_DDK_GATOR_API_VERSION != 1) && (MALI_DDK_GATOR_API_VERSION != 2) && (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/r4 DDK, or 3 for r5 and later DDK).
+#endif
+
+#include "gator_events_mali_common.h"
+
+/*
+ * Mali-Midgard
+ */
+#if MALI_DDK_GATOR_API_VERSION == 3
+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
+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
+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
+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
+
+static mali_error (*kbase_instr_hwcnt_enable_symbol)(struct kbase_context *, struct kbase_uk_hwcnt_setup *);
+static mali_error (*kbase_instr_hwcnt_disable_symbol)(struct kbase_context *);
+static mali_error (*kbase_instr_hwcnt_clear_symbol)(struct kbase_context *);
+static mali_error (*kbase_instr_hwcnt_dump_irq_symbol)(struct kbase_context *);
+static mali_bool (*kbase_instr_hwcnt_dump_complete_symbol)(struct kbase_context *, mali_bool *);
+
+static long shader_present_low;
+#endif
+
+/** The interval between reads, in ns.
+ *
+ * Earlier we introduced a 'hold off for 1ms after last read' to
+ * resolve MIDBASE-2178 and MALINE-724. However, the 1ms hold off is
+ * too long if no context switches occur as there is a race between
+ * this value and the tick of the read clock in gator which is also
+ * 1ms. If we 'miss' the current read, the counter values are
+ * effectively 'spread' over 2ms and the values seen are half what
+ * they should be (since Streamline averages over sample time). In the
+ * presence of context switches this spread can vary and markedly
+ * affect the counters. Currently there is no 'proper' solution to
+ * this, but empirically we have found that reducing the minimum read
+ * interval to 950us causes the counts to be much more stable.
+ */
+static const int READ_INTERVAL_NSEC = 950000;
+
+#if GATOR_TEST
+#include "gator_events_mali_midgard_hw_test.c"
+#endif
+
+#if MALI_DDK_GATOR_API_VERSION != 3
+/* Blocks for HW counters */
+enum {
+       JM_BLOCK = 0,
+       TILER_BLOCK,
+       SHADER_BLOCK,
+       MMU_BLOCK
+};
+#endif
+
+static const char *mali_name;
+
+/* Counters for Mali-Midgard:
+ *
+ *    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.
+ *    HW counters are requested by calculating a bitmask, passed then to the driver.
+ *    Every millisecond a HW counters dump is requested, and if the previous has been completed they are read.
+ */
+
+/* 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 */
+       "",
+       "",
+       "",
+       "",
+       "MESSAGES_SENT",
+       "MESSAGES_RECEIVED",
+       "GPU_ACTIVE",           /* 6 */
+       "IRQ_ACTIVE",
+       "JS0_JOBS",
+       "JS0_TASKS",
+       "JS0_ACTIVE",
+       "",
+       "JS0_WAIT_READ",
+       "JS0_WAIT_ISSUE",
+       "JS0_WAIT_DEPEND",
+       "JS0_WAIT_FINISH",
+       "JS1_JOBS",
+       "JS1_TASKS",
+       "JS1_ACTIVE",
+       "",
+       "JS1_WAIT_READ",
+       "JS1_WAIT_ISSUE",
+       "JS1_WAIT_DEPEND",
+       "JS1_WAIT_FINISH",
+       "JS2_JOBS",
+       "JS2_TASKS",
+       "JS2_ACTIVE",
+       "",
+       "JS2_WAIT_READ",
+       "JS2_WAIT_ISSUE",
+       "JS2_WAIT_DEPEND",
+       "JS2_WAIT_FINISH",
+       "JS3_JOBS",
+       "JS3_TASKS",
+       "JS3_ACTIVE",
+       "",
+       "JS3_WAIT_READ",
+       "JS3_WAIT_ISSUE",
+       "JS3_WAIT_DEPEND",
+       "JS3_WAIT_FINISH",
+       "JS4_JOBS",
+       "JS4_TASKS",
+       "JS4_ACTIVE",
+       "",
+       "JS4_WAIT_READ",
+       "JS4_WAIT_ISSUE",
+       "JS4_WAIT_DEPEND",
+       "JS4_WAIT_FINISH",
+       "JS5_JOBS",
+       "JS5_TASKS",
+       "JS5_ACTIVE",
+       "",
+       "JS5_WAIT_READ",
+       "JS5_WAIT_ISSUE",
+       "JS5_WAIT_DEPEND",
+       "JS5_WAIT_FINISH",
+       "JS6_JOBS",
+       "JS6_TASKS",
+       "JS6_ACTIVE",
+       "",
+       "JS6_WAIT_READ",
+       "JS6_WAIT_ISSUE",
+       "JS6_WAIT_DEPEND",
+       "JS6_WAIT_FINISH",
+
+       /*Tiler */
+       "",
+       "",
+       "",
+       "JOBS_PROCESSED",
+       "TRIANGLES",
+       "QUADS",
+       "POLYGONS",
+       "POINTS",
+       "LINES",
+       "VCACHE_HIT",
+       "VCACHE_MISS",
+       "FRONT_FACING",
+       "BACK_FACING",
+       "PRIM_VISIBLE",
+       "PRIM_CULLED",
+       "PRIM_CLIPPED",
+       "LEVEL0",
+       "LEVEL1",
+       "LEVEL2",
+       "LEVEL3",
+       "LEVEL4",
+       "LEVEL5",
+       "LEVEL6",
+       "LEVEL7",
+       "COMMAND_1",
+       "COMMAND_2",
+       "COMMAND_3",
+       "COMMAND_4",
+       "COMMAND_4_7",
+       "COMMAND_8_15",
+       "COMMAND_16_63",
+       "COMMAND_64",
+       "COMPRESS_IN",
+       "COMPRESS_OUT",
+       "COMPRESS_FLUSH",
+       "TIMESTAMPS",
+       "PCACHE_HIT",
+       "PCACHE_MISS",
+       "PCACHE_LINE",
+       "PCACHE_STALL",
+       "WRBUF_HIT",
+       "WRBUF_MISS",
+       "WRBUF_LINE",
+       "WRBUF_PARTIAL",
+       "WRBUF_STALL",
+       "ACTIVE",
+       "LOADING_DESC",
+       "INDEX_WAIT",
+       "INDEX_RANGE_WAIT",
+       "VERTEX_WAIT",
+       "PCACHE_WAIT",
+       "WRBUF_WAIT",
+       "BUS_READ",
+       "BUS_WRITE",
+       "",
+       "",
+       "",
+       "",
+       "",
+       "UTLB_STALL",
+       "UTLB_REPLAY_MISS",
+       "UTLB_REPLAY_FULL",
+       "UTLB_NEW_MISS",
+       "UTLB_HIT",
+
+       /* Shader Core */
+       "",
+       "",
+       "",
+       "SHADER_CORE_ACTIVE",
+       "FRAG_ACTIVE",
+       "FRAG_PRIMATIVES",
+       "FRAG_PRIMATIVES_DROPPED",
+       "FRAG_CYCLE_DESC",
+       "FRAG_CYCLES_PLR",
+       "FRAG_CYCLES_VERT",
+       "FRAG_CYCLES_TRISETUP",
+       "FRAG_CYCLES_RAST",
+       "FRAG_THREADS",
+       "FRAG_DUMMY_THREADS",
+       "FRAG_QUADS_RAST",
+       "FRAG_QUADS_EZS_TEST",
+       "FRAG_QUADS_EZS_KILLED",
+       "FRAG_QUADS_LZS_TEST",
+       "FRAG_QUADS_LZS_KILLED",
+       "FRAG_CYCLE_NO_TILE",
+       "FRAG_NUM_TILES",
+       "FRAG_TRANS_ELIM",
+       "COMPUTE_ACTIVE",
+       "COMPUTE_TASKS",
+       "COMPUTE_THREADS",
+       "COMPUTE_CYCLES_DESC",
+       "TRIPIPE_ACTIVE",
+       "ARITH_WORDS",
+       "ARITH_CYCLES_REG",
+       "ARITH_CYCLES_L0",
+       "ARITH_FRAG_DEPEND",
+       "LS_WORDS",
+       "LS_ISSUES",
+       "LS_RESTARTS",
+       "LS_REISSUES_MISS",
+       "LS_REISSUES_VD",
+       "LS_REISSUE_ATTRIB_MISS",
+       "LS_NO_WB",
+       "TEX_WORDS",
+       "TEX_BUBBLES",
+       "TEX_WORDS_L0",
+       "TEX_WORDS_DESC",
+       "TEX_THREADS",
+       "TEX_RECIRC_FMISS",
+       "TEX_RECIRC_DESC",
+       "TEX_RECIRC_MULTI",
+       "TEX_RECIRC_PMISS",
+       "TEX_RECIRC_CONF",
+       "LSC_READ_HITS",
+       "LSC_READ_MISSES",
+       "LSC_WRITE_HITS",
+       "LSC_WRITE_MISSES",
+       "LSC_ATOMIC_HITS",
+       "LSC_ATOMIC_MISSES",
+       "LSC_LINE_FETCHES",
+       "LSC_DIRTY_LINE",
+       "LSC_SNOOPS",
+       "AXI_TLB_STALL",
+       "AXI_TLB_MIESS",
+       "AXI_TLB_TRANSACTION",
+       "LS_TLB_MISS",
+       "LS_TLB_HIT",
+       "AXI_BEATS_READ",
+       "AXI_BEATS_WRITTEN",
+
+       /*L2 and MMU */
+       "",
+       "",
+       "",
+       "",
+       "MMU_HIT",
+       "MMU_NEW_MISS",
+       "MMU_REPLAY_FULL",
+       "MMU_REPLAY_MISS",
+       "MMU_TABLE_WALK",
+       "",
+       "",
+       "",
+       "",
+       "",
+       "",
+       "",
+       "UTLB_HIT",
+       "UTLB_NEW_MISS",
+       "UTLB_REPLAY_FULL",
+       "UTLB_REPLAY_MISS",
+       "UTLB_STALL",
+       "",
+       "",
+       "",
+       "",
+       "",
+       "",
+       "",
+       "",
+       "",
+       "L2_WRITE_BEATS",
+       "L2_READ_BEATS",
+       "L2_ANY_LOOKUP",
+       "L2_READ_LOOKUP",
+       "L2_SREAD_LOOKUP",
+       "L2_READ_REPLAY",
+       "L2_READ_SNOOP",
+       "L2_READ_HIT",
+       "L2_CLEAN_MISS",
+       "L2_WRITE_LOOKUP",
+       "L2_SWRITE_LOOKUP",
+       "L2_WRITE_REPLAY",
+       "L2_WRITE_SNOOP",
+       "L2_WRITE_HIT",
+       "L2_EXT_READ_FULL",
+       "L2_EXT_READ_HALF",
+       "L2_EXT_WRITE_FULL",
+       "L2_EXT_WRITE_HALF",
+       "L2_EXT_READ",
+       "L2_EXT_READ_LINE",
+       "L2_EXT_WRITE",
+       "L2_EXT_WRITE_LINE",
+       "L2_EXT_WRITE_SMALL",
+       "L2_EXT_BARRIER",
+       "L2_EXT_AR_STALL",
+       "L2_EXT_R_BUF_FULL",
+       "L2_EXT_RD_BUF_FULL",
+       "L2_EXT_R_RAW",
+       "L2_EXT_W_STALL",
+       "L2_EXT_W_BUF_FULL",
+       "L2_EXT_R_W_HAZARD",
+       "L2_TAG_HAZARD",
+       "L2_SNOOP_FULL",
+       "L2_REPLAY_FULL"
+};
+
+static const 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 kbase_gator_hwcnt_handles *handles;
+
+/* Information about hardware counters */
+static struct kbase_gator_hwcnt_info *in_out_info;
+
+#else
+/* Memory to dump hardware counters into */
+static void *kernel_dump_buffer;
+
+#if MALI_DDK_GATOR_API_VERSION == 2
+/* DMA state used to manage lifetime of the buffer */
+struct kbase_hwc_dma_mapping kernel_dump_buffer_handle;
+#endif
+
+/* kbase context and device */
+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;
+static unsigned int num_hardware_counters_enabled;
+
+/* gatorfs variables for counter enable state */
+static struct mali_counter *counters;
+
+/* An array used to return the data we recorded as key,value pairs */
+static int *counter_dump;
+
+extern struct mali_counter mali_activity[3];
+
+static const char *const mali_activity_names[] = {
+       "fragment",
+       "vertex",
+       "opencl",
+};
+
+#define SYMBOL_GET(FUNCTION, ERROR_COUNT) \
+       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) \
+       do { \
+               if (FUNCTION ## _symbol) { \
+                       symbol_put(FUNCTION); \
+                       FUNCTION ## _symbol = NULL; \
+               } \
+       } while (0)
+
+/**
+ * Execute symbol_get for all the Mali symbols and check for success.
+ * @return the number of symbols not loaded.
+ */
+static int init_symbols(void)
+{
+       int error_count = 0;
+#if MALI_DDK_GATOR_API_VERSION == 3
+       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);
+       SYMBOL_GET(kbase_va_alloc, error_count);
+       SYMBOL_GET(kbase_instr_hwcnt_enable, error_count);
+       SYMBOL_GET(kbase_instr_hwcnt_clear, error_count);
+       SYMBOL_GET(kbase_instr_hwcnt_dump_irq, error_count);
+       SYMBOL_GET(kbase_instr_hwcnt_dump_complete, error_count);
+       SYMBOL_GET(kbase_instr_hwcnt_disable, error_count);
+       SYMBOL_GET(kbase_va_free, error_count);
+       SYMBOL_GET(kbase_destroy_context, error_count);
+#endif
+
+       return error_count;
+}
+
+/**
+ * Execute symbol_put for all the registered Mali symbols.
+ */
+static void clean_symbols(void)
+{
+#if MALI_DDK_GATOR_API_VERSION == 3
+       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);
+       SYMBOL_CLEANUP(kbase_va_alloc);
+       SYMBOL_CLEANUP(kbase_instr_hwcnt_enable);
+       SYMBOL_CLEANUP(kbase_instr_hwcnt_clear);
+       SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_irq);
+       SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_complete);
+       SYMBOL_CLEANUP(kbase_instr_hwcnt_disable);
+       SYMBOL_CLEANUP(kbase_va_free);
+       SYMBOL_CLEANUP(kbase_destroy_context);
+#endif
+}
+
+/**
+ * Determines whether a read should take place
+ * @param current_time The current time, obtained from getnstimeofday()
+ * @param prev_time_s The number of seconds at the previous read attempt.
+ * @param next_read_time_ns The time (in ns) when the next read should be allowed.
+ *
+ * Note that this function has been separated out here to allow it to be tested.
+ */
+static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns)
+{
+       /* If the current ns count rolls over a second, roll the next read time too. */
+       if (current_time->tv_sec != *prev_time_s)
+               *next_read_time_ns = *next_read_time_ns - NSEC_PER_SEC;
+
+       /* Abort the read if the next read time has not arrived. */
+       if (current_time->tv_nsec < *next_read_time_ns)
+               return 0;
+
+       /* Set the next read some fixed time after this one, and update the read timestamp. */
+       *next_read_time_ns = current_time->tv_nsec + READ_INTERVAL_NSEC;
+
+       *prev_time_s = current_time->tv_sec;
+       return 1;
+}
+
+static int start(void)
+{
+#if MALI_DDK_GATOR_API_VERSION != 3
+       struct kbase_uk_hwcnt_setup setup;
+       unsigned long long shadersPresent = 0;
+       u16 bitmask[] = { 0, 0, 0, 0 };
+       mali_error err;
+#endif
+       int cnt;
+
+#if MALI_DDK_GATOR_API_VERSION == 3
+       /* Setup HW counters */
+       num_hardware_counters_enabled = 0;
+
+       /* 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;
+
+       /* Calculate enable bitmasks based on counters_enabled array */
+       for (cnt = 0; cnt < number_of_hardware_counters; cnt++) {
+               if (counters[cnt].enabled) {
+                       int block = GET_HW_BLOCK(cnt);
+                       int enable_bit = GET_COUNTER_OFFSET(cnt) / 4;
+
+                       in_out_info->bitmask[block] |= (1 << enable_bit);
+                       pr_debug("gator: Mali-Midgard: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt);
+                       num_hardware_counters_enabled++;
+               }
+       }
+
+       /* Create a kbase context for HW counters */
+       if (num_hardware_counters_enabled > 0) {
+               if (init_symbols() > 0) {
+                       clean_symbols();
+                       /* No Mali driver code entrypoints found - not a fault. */
+                       return 0;
+               }
+
+               handles = kbase_gator_hwcnt_init_symbol(in_out_info);
+
+               if (handles == NULL)
+                       goto out;
+
+               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) {
+                       clean_symbols();
+                       /* No Mali driver code entrypoints found - not a fault. */
+                       return 0;
+               }
+
+               kbdevice = kbase_find_device_symbol(-1);
+
+               /* If we already got a context, fail */
+               if (kbcontext) {
+                       pr_debug("gator: Mali-Midgard: error context already present\n");
+                       goto out;
+               }
+
+               /* kbcontext will only be valid after all the Mali symbols are loaded successfully */
+               kbcontext = kbase_create_context_symbol(kbdevice);
+               if (!kbcontext) {
+                       pr_debug("gator: Mali-Midgard: error creating kbase context\n");
+                       goto out;
+               }
+
+               /* See if we can get the number of shader cores */
+               shadersPresent = kbdevice->shader_present_bitmap;
+               shader_present_low = (unsigned long)shadersPresent;
+
+               /*
+                * The amount of memory needed to store the dump (bytes)
+                * DUMP_SIZE = number of core groups
+                *             * number of blocks (always 8 for midgard)
+                *             * number of counters per block (always 64 for midgard)
+                *             * number of bytes per counter (always 4 in midgard)
+                * For a Mali-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);
+#elif MALI_DDK_GATOR_API_VERSION == 2
+               kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 4096, &kernel_dump_buffer_handle);
+#endif
+               if (!kernel_dump_buffer) {
+                       pr_debug("gator: Mali-Midgard: error trying to allocate va\n");
+                       goto destroy_context;
+               }
+
+               setup.dump_buffer = (uintptr_t)kernel_dump_buffer;
+               setup.jm_bm = bitmask[JM_BLOCK];
+               setup.tiler_bm = bitmask[TILER_BLOCK];
+               setup.shader_bm = bitmask[SHADER_BLOCK];
+               setup.mmu_l2_bm = bitmask[MMU_BLOCK];
+               /* These counters do not exist on Mali-T60x */
+               setup.l3_cache_bm = 0;
+
+               /* Use kbase API to enable hardware counters and provide dump buffer */
+               err = kbase_instr_hwcnt_enable_symbol(kbcontext, &setup);
+               if (err != MALI_ERROR_NONE) {
+                       pr_debug("gator: Mali-Midgard: can't setup hardware counters\n");
+                       goto free_buffer;
+               }
+               pr_debug("gator: Mali-Midgard: hardware counters enabled\n");
+               kbase_instr_hwcnt_clear_symbol(kbcontext);
+               pr_debug("gator: Mali-Midgard: hardware counters cleared\n");
+
+               kbase_device_busy = false;
+       }
+
+       return 0;
+
+free_buffer:
+#if MALI_DDK_GATOR_API_VERSION == 1
+       kbase_va_free_symbol(kbcontext, kernel_dump_buffer);
+#elif MALI_DDK_GATOR_API_VERSION == 2
+       kbase_va_free_symbol(kbcontext, &kernel_dump_buffer_handle);
+#endif
+
+destroy_context:
+       kbase_destroy_context_symbol(kbcontext);
+#endif
+
+out:
+       clean_symbols();
+       return -1;
+}
+
+static void stop(void)
+{
+       unsigned int cnt;
+#if MALI_DDK_GATOR_API_VERSION == 3
+       struct kbase_gator_hwcnt_handles *temp_hand;
+#else
+       struct kbase_context *temp_kbcontext;
+#endif
+
+       pr_debug("gator: Mali-Midgard: stop\n");
+
+       /* Set all counters as disabled */
+       for (cnt = 0; cnt < number_of_hardware_counters; cnt++)
+               counters[cnt].enabled = 0;
+
+       /* Destroy the context for HW counters */
+#if MALI_DDK_GATOR_API_VERSION == 3
+       if (num_hardware_counters_enabled > 0 && handles != NULL) {
+               /*
+                * Set the global variable to NULL before destroying it, because
+                * other function will check this before using it.
+                */
+               temp_hand = handles;
+               handles = NULL;
+
+               kbase_gator_hwcnt_term_symbol(in_out_info, temp_hand);
+
+               kfree(in_out_info);
+
+#else
+       if (num_hardware_counters_enabled > 0 && kbcontext != NULL) {
+               /*
+                * Set the global variable to NULL before destroying it, because
+                * other function will check this before using it.
+                */
+               temp_kbcontext = kbcontext;
+               kbcontext = NULL;
+
+               kbase_instr_hwcnt_disable_symbol(temp_kbcontext);
+
+#if MALI_DDK_GATOR_API_VERSION == 1
+               kbase_va_free_symbol(temp_kbcontext, kernel_dump_buffer);
+#elif MALI_DDK_GATOR_API_VERSION == 2
+               kbase_va_free_symbol(temp_kbcontext, &kernel_dump_buffer_handle);
+#endif
+
+               kbase_destroy_context_symbol(temp_kbcontext);
+#endif
+
+               pr_debug("gator: Mali-Midgard: hardware counters stopped\n");
+
+               clean_symbols();
+       }
+}
+
+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;
+       uint32_t success;
+
+       struct timespec current_time;
+       static u32 prev_time_s;
+       static s32 next_read_time_ns;
+
+       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.
+        */
+       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)
+                       return -1;
+
+               /* Mali symbols can be called safely since a kbcontext is valid */
+               if (kbase_gator_instr_hwcnt_dump_complete_symbol(handles, &success) == MALI_TRUE) {
+#else
+               if (!kbcontext)
+                       return -1;
+
+               /* Mali symbols can be called safely since a kbcontext is valid */
+               if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE) {
+#endif
+                       kbase_device_busy = false;
+
+                       if (success == MALI_TRUE) {
+                               /* Cycle through hardware counters and accumulate totals */
+                               for (cnt = 0; cnt < number_of_hardware_counters; cnt++) {
+                                       const struct mali_counter *counter = &counters[cnt];
+
+                                       if (counter->enabled)
+                                               len += read_counter(cnt, len, counter);
+                               }
+                       }
+               }
+
+               if (!kbase_device_busy) {
+                       kbase_device_busy = true;
+#if MALI_DDK_GATOR_API_VERSION == 3
+                       kbase_gator_instr_hwcnt_dump_irq_symbol(handles);
+#else
+                       kbase_instr_hwcnt_dump_irq_symbol(kbcontext);
+#endif
+               }
+       }
+
+       /* Update the buffer */
+       if (buffer)
+               *buffer = counter_dump;
+
+       return len;
+}
+
+static int create_files(struct super_block *sb, struct dentry *root)
+{
+       unsigned int event;
+       /*
+        * Create the filesystem for all events
+        */
+       for (event = 0; event < ARRAY_SIZE(mali_activity); event++) {
+               if (gator_mali_create_file_system("Midgard", mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0)
+                       return -1;
+       }
+
+       for (event = 0; event < number_of_hardware_counters; event++) {
+               if (gator_mali_create_file_system(mali_name, hardware_counter_names[event], sb, root, &counters[event], NULL) != 0)
+                       return -1;
+       }
+
+       return 0;
+}
+
+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_midgard_hw_init(void)
+{
+#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);
+
+       return gator_events_install(&gator_events_mali_midgard_interface);
+}
diff --git a/drivers/gator/gator_events_mali_midgard_hw_test.c b/drivers/gator/gator_events_mali_midgard_hw_test.c
new file mode 100644 (file)
index 0000000..31a91e1
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ * Copyright (C) ARM Limited 2012-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.
+ *
+ */
+
+/**
+ * Test functions for mali_t600_hw code.
+ */
+
+static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns);
+
+static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int expected_result, s32 expected_next_ns)
+{
+       struct timespec current_time;
+       u32 prev_time_s = prev_s;
+       s32 next_read_time_ns = next_ns;
+
+       current_time.tv_sec = s;
+       current_time.tv_nsec = ns;
+
+       if (is_read_scheduled(&current_time, &prev_time_s, &next_read_time_ns) != expected_result) {
+               pr_err("Failed do_read(%u, %u, %u, %d): expected %d\n", s, ns, prev_s, next_ns, expected_result);
+               return 0;
+       }
+
+       if (next_read_time_ns != expected_next_ns) {
+               pr_err("Failed: next_read_ns expected=%d, actual=%d\n", expected_next_ns, next_read_time_ns);
+               return 0;
+       }
+
+       return 1;
+}
+
+static void test_all_is_read_scheduled(void)
+{
+       const int HIGHEST_NS = 999999999;
+       int n_tests_passed = 0;
+
+       pr_err("gator: running tests on %s\n", __FILE__);
+
+       n_tests_passed += test_is_read_scheduled(0, 0, 0, 0, 1, READ_INTERVAL_NSEC);    /* Null time */
+       n_tests_passed += test_is_read_scheduled(100, 1000, 0, 0, 1, READ_INTERVAL_NSEC + 1000);        /* Initial values */
+
+       n_tests_passed += test_is_read_scheduled(100, HIGHEST_NS, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500);
+       n_tests_passed += test_is_read_scheduled(101, 0001, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500 - NSEC_PER_SEC);
+       n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500 - NSEC_PER_SEC, 1, 600 + READ_INTERVAL_NSEC);
+
+       n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500, 1, 600 + READ_INTERVAL_NSEC);
+
+       pr_err("gator: %d tests passed\n", n_tests_passed);
+}
diff --git a/drivers/gator/gator_events_mali_t6xx.c b/drivers/gator/gator_events_mali_t6xx.c
deleted file mode 100644 (file)
index e56ba84..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2011-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 "gator.h"
-
-#include <linux/module.h>
-#include <linux/time.h>
-#include <linux/math64.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-
-#ifdef MALI_DIR_MIDGARD
-/* New DDK Directory structure with kernel/drivers/gpu/arm/midgard*/
-#include "mali_linux_trace.h"
-#else
-/* Old DDK Directory structure with kernel/drivers/gpu/arm/t6xx*/
-#include "linux/mali_linux_trace.h"
-#endif
-
-#include "gator_events_mali_common.h"
-
-/*
- * 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
-#endif
-
-static const char mali_name[] = "Mali-T6xx";
-
-/* Counters for Mali-T6xx:
- *
- *  - Timeline events
- *    They are tracepoints, but instead of reporting a number they report a START/STOP event.
- *    They are reported in Streamline as number of microseconds while that particular counter was active.
- *
- *  - SW counters
- *    They are tracepoints reporting a particular number.
- *    They are accumulated in sw_counter_data array until they are passed to Streamline, then they are zeroed.
- *
- *  - Accumulators
- *    They are the same as software counters but their value is not zeroed.
- */
-
-/* Timeline (start/stop) activity */
-static const char *timeline_event_names[] = {
-       "PM_SHADER_0",
-       "PM_SHADER_1",
-       "PM_SHADER_2",
-       "PM_SHADER_3",
-       "PM_SHADER_4",
-       "PM_SHADER_5",
-       "PM_SHADER_6",
-       "PM_SHADER_7",
-       "PM_TILER_0",
-       "PM_L2_0",
-       "PM_L2_1",
-       "MMU_AS_0",
-       "MMU_AS_1",
-       "MMU_AS_2",
-       "MMU_AS_3"
-};
-
-enum {
-       PM_SHADER_0 = 0,
-       PM_SHADER_1,
-       PM_SHADER_2,
-       PM_SHADER_3,
-       PM_SHADER_4,
-       PM_SHADER_5,
-       PM_SHADER_6,
-       PM_SHADER_7,
-       PM_TILER_0,
-       PM_L2_0,
-       PM_L2_1,
-       MMU_AS_0,
-       MMU_AS_1,
-       MMU_AS_2,
-       MMU_AS_3
-};
-/* The number of shader blocks in the enum above */
-#define NUM_PM_SHADER (8)
-
-/* Software Counters */
-static const char *software_counter_names[] = {
-       "MMU_PAGE_FAULT_0",
-       "MMU_PAGE_FAULT_1",
-       "MMU_PAGE_FAULT_2",
-       "MMU_PAGE_FAULT_3"
-};
-
-enum {
-       MMU_PAGE_FAULT_0 = 0,
-       MMU_PAGE_FAULT_1,
-       MMU_PAGE_FAULT_2,
-       MMU_PAGE_FAULT_3
-};
-
-/* Software Counters */
-static const char *accumulators_names[] = {
-       "TOTAL_ALLOC_PAGES"
-};
-
-enum {
-       TOTAL_ALLOC_PAGES = 0
-};
-
-#define FIRST_TIMELINE_EVENT (0)
-#define NUMBER_OF_TIMELINE_EVENTS (sizeof(timeline_event_names) / sizeof(timeline_event_names[0]))
-#define FIRST_SOFTWARE_COUNTER (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS)
-#define NUMBER_OF_SOFTWARE_COUNTERS (sizeof(software_counter_names) / sizeof(software_counter_names[0]))
-#define FIRST_ACCUMULATOR (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS)
-#define NUMBER_OF_ACCUMULATORS (sizeof(accumulators_names) / sizeof(accumulators_names[0]))
-#define FILMSTRIP (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS)
-#define NUMBER_OF_EVENTS (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS + 1)
-
-/*
- * gatorfs variables for counter enable state
- */
-static 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];
-
-/*
- * 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];
-
-/* The data we have recorded */
-static unsigned int timeline_data[NUMBER_OF_TIMELINE_EVENTS];
-static unsigned int sw_counter_data[NUMBER_OF_SOFTWARE_COUNTERS];
-static unsigned int accumulators_data[NUMBER_OF_ACCUMULATORS];
-
-/* Hold the previous timestamp, used to calculate the sample interval. */
-static struct timespec prev_timestamp;
-
-/**
- * Returns the timespan (in microseconds) between the two specified timestamps.
- *
- * @param start Ptr to the start timestamp
- * @param end Ptr to the end timestamp
- *
- * @return Number of microseconds between the two timestamps (can be negative if start follows end).
- */
-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;
-}
-
-static void record_timeline_event(unsigned int timeline_index, unsigned int type)
-{
-       struct timespec event_timestamp;
-       struct timespec *event_start = &timeline_event_starttime[timeline_index];
-
-       switch (type) {
-       case ACTIVITY_START:
-               /* Get the event time... */
-               getnstimeofday(&event_timestamp);
-
-               /* Remember the start time if the activity is not already started */
-               if (event_start->tv_sec == 0) {
-                       *event_start = event_timestamp; /* Structure copy */
-               }
-               break;
-
-       case ACTIVITY_STOP:
-               /* if the counter was started... */
-               if (event_start->tv_sec != 0) {
-                       /* Get the event time... */
-                       getnstimeofday(&event_timestamp);
-
-                       /* Accumulate the duration in us */
-                       timeline_data[timeline_index] += get_duration_us(event_start, &event_timestamp);
-
-                       /* Reset the start time to indicate the activity is stopped. */
-                       event_start->tv_sec = 0;
-               }
-               break;
-
-       default:
-               /* Other activity events are ignored. */
-               break;
-       }
-}
-
-/*
- * Documentation about the following tracepoints is in mali_linux_trace.h
- */
-
-GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long long value))
-{
-#define SHADER_PRESENT_LO       0x100  /* (RO) Shader core present bitmap, low word */
-#define TILER_PRESENT_LO        0x110  /* (RO) Tiler core present bitmap, low word */
-#define L2_PRESENT_LO           0x120  /* (RO) Level 2 cache present bitmap, low word */
-#define BIT_AT(value, pos) ((value >> pos) & 1)
-
-       static unsigned long long previous_shader_bitmask = 0;
-       static unsigned long long previous_tiler_bitmask = 0;
-       static unsigned long long previous_l2_bitmask = 0;
-
-       switch (event_id) {
-       case SHADER_PRESENT_LO:
-               {
-                       unsigned long long changed_bitmask = previous_shader_bitmask ^ value;
-                       int pos;
-
-                       for (pos = 0; pos < NUM_PM_SHADER; ++pos) {
-                               if (BIT_AT(changed_bitmask, pos)) {
-                                       record_timeline_event(PM_SHADER_0 + pos, BIT_AT(value, pos) ? ACTIVITY_START : ACTIVITY_STOP);
-                               }
-                       }
-
-                       previous_shader_bitmask = value;
-                       break;
-               }
-
-       case TILER_PRESENT_LO:
-               {
-                       unsigned long long changed = previous_tiler_bitmask ^ value;
-
-                       if (BIT_AT(changed, 0)) {
-                               record_timeline_event(PM_TILER_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP);
-                       }
-
-                       previous_tiler_bitmask = value;
-                       break;
-               }
-
-       case L2_PRESENT_LO:
-               {
-                       unsigned long long changed = previous_l2_bitmask ^ value;
-
-                       if (BIT_AT(changed, 0)) {
-                               record_timeline_event(PM_L2_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP);
-                       }
-                       if (BIT_AT(changed, 4)) {
-                               record_timeline_event(PM_L2_1, BIT_AT(value, 4) ? ACTIVITY_START : ACTIVITY_STOP);
-                       }
-
-                       previous_l2_bitmask = value;
-                       break;
-               }
-
-       default:
-               /* No other blocks are supported at present */
-               break;
-       }
-
-#undef SHADER_PRESENT_LO
-#undef TILER_PRESENT_LO
-#undef L2_PRESENT_LO
-#undef BIT_AT
-}
-
-GATOR_DEFINE_PROBE(mali_page_fault_insert_pages, TP_PROTO(int event_id, unsigned long value))
-{
-       /* We add to the previous since we may receive many tracepoints in one sample period */
-       sw_counter_data[MMU_PAGE_FAULT_0 + event_id] += value;
-}
-
-GATOR_DEFINE_PROBE(mali_mmu_as_in_use, TP_PROTO(int event_id))
-{
-       record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_START);
-}
-
-GATOR_DEFINE_PROBE(mali_mmu_as_released, TP_PROTO(int event_id))
-{
-       record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_STOP);
-}
-
-GATOR_DEFINE_PROBE(mali_total_alloc_pages_change, TP_PROTO(long long int event_id))
-{
-       accumulators_data[TOTAL_ALLOC_PAGES] = event_id;
-}
-
-static int create_files(struct super_block *sb, struct dentry *root)
-{
-       int event;
-       /*
-        * Create the filesystem for all events
-        */
-       int counter_index = 0;
-       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) {
-                       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) {
-                       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) {
-                       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) {
-                       return -1;
-               }
-               symbol_put(_mali_profiling_control);
-       }
-
-       return 0;
-}
-
-static int register_tracepoints(void)
-{
-       if (GATOR_REGISTER_TRACE(mali_pm_status)) {
-               pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint failed to activate\n");
-               return 0;
-       }
-
-       if (GATOR_REGISTER_TRACE(mali_page_fault_insert_pages)) {
-               pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint failed to activate\n");
-               return 0;
-       }
-
-       if (GATOR_REGISTER_TRACE(mali_mmu_as_in_use)) {
-               pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint failed to activate\n");
-               return 0;
-       }
-
-       if (GATOR_REGISTER_TRACE(mali_mmu_as_released)) {
-               pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint failed to activate\n");
-               return 0;
-       }
-
-       if (GATOR_REGISTER_TRACE(mali_total_alloc_pages_change)) {
-               pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint failed to activate\n");
-               return 0;
-       }
-
-       pr_debug("gator: Mali-T6xx: start\n");
-       pr_debug("gator: Mali-T6xx: mali_pm_status probe is at %p\n", &probe_mali_pm_status);
-       pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages probe is at %p\n", &probe_mali_page_fault_insert_pages);
-       pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use probe is at %p\n", &probe_mali_mmu_as_in_use);
-       pr_debug("gator: Mali-T6xx: mali_mmu_as_released probe is at %p\n", &probe_mali_mmu_as_released);
-       pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change probe is at %p\n", &probe_mali_total_alloc_pages_change);
-
-       return 1;
-}
-
-static int start(void)
-{
-       unsigned int cnt;
-       mali_profiling_control_type *mali_control;
-
-       /* Clean all data for the next capture */
-       for (cnt = 0; cnt < NUMBER_OF_TIMELINE_EVENTS; cnt++) {
-               timeline_event_starttime[cnt].tv_sec = timeline_event_starttime[cnt].tv_nsec = 0;
-               timeline_data[cnt] = 0;
-       }
-
-       for (cnt = 0; cnt < NUMBER_OF_SOFTWARE_COUNTERS; cnt++) {
-               sw_counter_data[cnt] = 0;
-       }
-
-       for (cnt = 0; cnt < NUMBER_OF_ACCUMULATORS; cnt++) {
-               accumulators_data[cnt] = 0;
-       }
-
-       /* Register tracepoints */
-       if (register_tracepoints() == 0) {
-               return -1;
-       }
-
-       /* Generic control interface for Mali DDK. */
-       mali_control = symbol_get(_mali_profiling_control);
-       if (mali_control) {
-               /* The event attribute in the XML file keeps the actual frame rate. */
-               unsigned int enabled = counters[FILMSTRIP].enabled ? 1 : 0;
-               unsigned int rate = filmstrip_event & 0xff;
-               unsigned int resize_factor = (filmstrip_event >> 8) & 0xff;
-
-               pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control);
-
-#define FBDUMP_CONTROL_ENABLE (1)
-#define FBDUMP_CONTROL_RATE (2)
-#define FBDUMP_CONTROL_RESIZE_FACTOR (4)
-               mali_control(FBDUMP_CONTROL_ENABLE, enabled);
-               mali_control(FBDUMP_CONTROL_RATE, rate);
-               mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor);
-
-               pr_debug("gator: sent mali_control enabled=%d, rate=%d, resize_factor=%d\n", enabled, rate, resize_factor);
-
-               symbol_put(_mali_profiling_control);
-       } else {
-               printk("gator: mali online _mali_profiling_control symbol not found\n");
-       }
-
-       /*
-        * Set the first timestamp for calculating the sample interval. The first interval could be quite long,
-        * since it will be the time between 'start' and the first 'read'.
-        * This means that timeline values will be divided by a big number for the first sample.
-        */
-       getnstimeofday(&prev_timestamp);
-
-       return 0;
-}
-
-static void stop(void)
-{
-       mali_profiling_control_type *mali_control;
-
-       pr_debug("gator: Mali-T6xx: stop\n");
-
-       /*
-        * It is safe to unregister traces even if they were not successfully
-        * registered, so no need to check.
-        */
-       GATOR_UNREGISTER_TRACE(mali_pm_status);
-       pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint deactivated\n");
-
-       GATOR_UNREGISTER_TRACE(mali_page_fault_insert_pages);
-       pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint deactivated\n");
-
-       GATOR_UNREGISTER_TRACE(mali_mmu_as_in_use);
-       pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint deactivated\n");
-
-       GATOR_UNREGISTER_TRACE(mali_mmu_as_released);
-       pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint deactivated\n");
-
-       GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change);
-       pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint deactivated\n");
-
-       /* Generic control interface for Mali DDK. */
-       mali_control = symbol_get(_mali_profiling_control);
-       if (mali_control) {
-               pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_control);
-
-               mali_control(FBDUMP_CONTROL_ENABLE, 0);
-
-               symbol_put(_mali_profiling_control);
-       } else {
-               printk("gator: mali offline _mali_profiling_control symbol not found\n");
-       }
-}
-
-static int read(int **buffer)
-{
-       int cnt;
-       int len = 0;
-       long sample_interval_us = 0;
-       struct timespec read_timestamp;
-
-       if (!on_primary_core()) {
-               return 0;
-       }
-
-       /* Get the start of this sample period. */
-       getnstimeofday(&read_timestamp);
-
-       /*
-        * Calculate the sample interval if the previous sample time is valid.
-        * We use tv_sec since it will not be 0.
-        */
-       if (prev_timestamp.tv_sec != 0) {
-               sample_interval_us = get_duration_us(&prev_timestamp, &read_timestamp);
-       }
-
-       /* Structure copy. Update the previous timestamp. */
-       prev_timestamp = read_timestamp;
-
-       /*
-        * Report the timeline counters (ACTIVITY_START/STOP)
-        */
-       for (cnt = FIRST_TIMELINE_EVENT; cnt < (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS); cnt++) {
-               mali_counter *counter = &counters[cnt];
-               if (counter->enabled) {
-                       const int index = cnt - FIRST_TIMELINE_EVENT;
-                       unsigned int value;
-
-                       /* If the activity is still running, reset its start time to the start of this sample period
-                        * to correct the count.  Add the time up to the end of the sample onto the count. */
-                       if (timeline_event_starttime[index].tv_sec != 0) {
-                               const long event_duration = get_duration_us(&timeline_event_starttime[index], &read_timestamp);
-                               timeline_data[index] += event_duration;
-                               timeline_event_starttime[index] = read_timestamp;       /* Activity is still running. */
-                       }
-
-                       if (sample_interval_us != 0) {
-                               /* Convert the counter to a percent-of-sample value */
-                               value = (timeline_data[index] * 100) / sample_interval_us;
-                       } else {
-                               pr_debug("gator: Mali-T6xx: setting value to zero\n");
-                               value = 0;
-                       }
-
-                       /* Clear the counter value ready for the next sample. */
-                       timeline_data[index] = 0;
-
-                       counter_dump[len++] = counter->key;
-                       counter_dump[len++] = value;
-               }
-       }
-
-       /* Report the software counters */
-       for (cnt = FIRST_SOFTWARE_COUNTER; cnt < (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS); cnt++) {
-               const mali_counter *counter = &counters[cnt];
-               if (counter->enabled) {
-                       const int index = cnt - FIRST_SOFTWARE_COUNTER;
-                       counter_dump[len++] = counter->key;
-                       counter_dump[len++] = sw_counter_data[index];
-                       /* Set the value to zero for the next time */
-                       sw_counter_data[index] = 0;
-               }
-       }
-
-       /* Report the accumulators */
-       for (cnt = FIRST_ACCUMULATOR; cnt < (FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS); cnt++) {
-               const mali_counter *counter = &counters[cnt];
-               if (counter->enabled) {
-                       const int index = cnt - FIRST_ACCUMULATOR;
-                       counter_dump[len++] = counter->key;
-                       counter_dump[len++] = accumulators_data[index];
-                       /* Do not zero the accumulator */
-               }
-       }
-
-       /* Update the buffer */
-       if (buffer) {
-               *buffer = (int *)counter_dump;
-       }
-
-       return len;
-}
-
-static struct gator_interface gator_events_mali_t6xx_interface = {
-       .create_files = create_files,
-       .start = start,
-       .stop = stop,
-       .read = read
-};
-
-extern int gator_events_mali_t6xx_init(void)
-{
-       pr_debug("gator: Mali-T6xx: sw_counters init\n");
-
-       gator_mali_initialise_counters(counters, NUMBER_OF_EVENTS);
-
-       return gator_events_install(&gator_events_mali_t6xx_interface);
-}
diff --git a/drivers/gator/gator_events_mali_t6xx_hw.c b/drivers/gator/gator_events_mali_t6xx_hw.c
deleted file mode 100644 (file)
index 3a072bb..0000000
+++ /dev/null
@@ -1,913 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2012-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 "gator.h"
-
-#include <linux/module.h>
-#include <linux/time.h>
-#include <linux/math64.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-
-/* Mali T6xx DDK includes */
-#if defined(MALI_SIMPLE_API)
-/* Header with wrapper functions to kbase structures and functions */
-#include "mali/mali_dd_gator_api.h"
-#elif defined(MALI_DIR_MIDGARD)
-/* New DDK Directory structure with kernel/drivers/gpu/arm/midgard*/
-#include "mali_linux_trace.h"
-#include "mali_kbase.h"
-#include "mali_kbase_mem_linux.h"
-#else
-/* 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"
-#endif
-
-/* If API version is not specified then assume API version 1. */
-#ifndef MALI_DDK_GATOR_API_VERSION
-#define MALI_DDK_GATOR_API_VERSION 1
-#endif
-
-#if (MALI_DDK_GATOR_API_VERSION != 1) && (MALI_DDK_GATOR_API_VERSION != 2) && (MALI_DDK_GATOR_API_VERSION != 3)
-#error MALI_DDK_GATOR_API_VERSION is invalid (must be 1 for r1/r2 DDK, or 2 for r3 DDK, or 3 for r? DDK).
-#endif
-
-#include "gator_events_mali_common.h"
-
-/*
- * Mali-T6xx
- */
-#if MALI_DDK_GATOR_API_VERSION == 3
-typedef uint32_t kbase_dd_instr_hwcnt_dump_irq_type(struct mali_dd_hwcnt_handles *);
-typedef uint32_t kbase_dd_instr_hwcnt_dump_complete_type(struct mali_dd_hwcnt_handles *, uint32_t *);
-typedef struct mali_dd_hwcnt_handles* mali_dd_hwcnt_init_type(struct mali_dd_hwcnt_info *);
-typedef void mali_dd_hwcnt_clear_type(struct mali_dd_hwcnt_info *, struct mali_dd_hwcnt_handles *);
-
-static kbase_dd_instr_hwcnt_dump_irq_type *kbase_dd_instr_hwcnt_dump_irq_symbol;
-static kbase_dd_instr_hwcnt_dump_complete_type *kbase_dd_instr_hwcnt_dump_complete_symbol;
-static mali_dd_hwcnt_init_type *mali_dd_hwcnt_init_symbol;
-static mali_dd_hwcnt_clear_type *mali_dd_hwcnt_clear_symbol;
-
-#else
-typedef struct kbase_device *kbase_find_device_type(int);
-typedef struct kbase_context *kbase_create_context_type(struct kbase_device *);
-typedef void kbase_destroy_context_type(struct kbase_context *);
-
-#if MALI_DDK_GATOR_API_VERSION == 1
-typedef void *kbase_va_alloc_type(struct kbase_context *, u32);
-typedef void kbase_va_free_type(struct kbase_context *, void *);
-#elif MALI_DDK_GATOR_API_VERSION == 2
-typedef void *kbase_va_alloc_type(struct kbase_context *, u32, kbase_hwc_dma_mapping * handle);
-typedef void kbase_va_free_type(struct kbase_context *, kbase_hwc_dma_mapping * handle);
-#endif
-
-typedef mali_error kbase_instr_hwcnt_enable_type(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 long shader_present_low = 0;
-
-/** The interval between reads, in ns.
- *
- * Earlier we introduced
- * a 'hold off for 1ms after last read' to resolve MIDBASE-2178 and MALINE-724.
- * However, the 1ms hold off is too long if no context switches occur as there is a race
- * between this value and the tick of the read clock in gator which is also 1ms. If we 'miss' the
- * current read, the counter values are effectively 'spread' over 2ms and the values seen are half
- * what they should be (since Streamline averages over sample time). In the presence of context switches
- * this spread can vary and markedly affect the counters.  Currently there is no 'proper' solution to
- * this, but empirically we have found that reducing the minimum read interval to 950us causes the
- * counts to be much more stable.
- */
-static const int READ_INTERVAL_NSEC = 950000;
-
-#if GATOR_TEST
-#include "gator_events_mali_t6xx_hw_test.c"
-#endif
-
-/* Blocks for HW counters */
-enum {
-       JM_BLOCK = 0,
-       TILER_BLOCK,
-       SHADER_BLOCK,
-       MMU_BLOCK
-};
-
-static const char mali_name[] = "Mali-T6xx";
-
-/* Counters for Mali-T6xx:
- *
- *  - 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.
- *    HW counters are requested by calculating a bitmask, passed then to the driver.
- *    Every millisecond a HW counters dump is requested, and if the previous has been completed they are read.
- */
-
-/* Hardware Counters */
-static const char *const hardware_counter_names[] = {
-       /* Job Manager */
-       "",
-       "",
-       "",
-       "",
-       "MESSAGES_SENT",
-       "MESSAGES_RECEIVED",
-       "GPU_ACTIVE",           /* 6 */
-       "IRQ_ACTIVE",
-       "JS0_JOBS",
-       "JS0_TASKS",
-       "JS0_ACTIVE",
-       "",
-       "JS0_WAIT_READ",
-       "JS0_WAIT_ISSUE",
-       "JS0_WAIT_DEPEND",
-       "JS0_WAIT_FINISH",
-       "JS1_JOBS",
-       "JS1_TASKS",
-       "JS1_ACTIVE",
-       "",
-       "JS1_WAIT_READ",
-       "JS1_WAIT_ISSUE",
-       "JS1_WAIT_DEPEND",
-       "JS1_WAIT_FINISH",
-       "JS2_JOBS",
-       "JS2_TASKS",
-       "JS2_ACTIVE",
-       "",
-       "JS2_WAIT_READ",
-       "JS2_WAIT_ISSUE",
-       "JS2_WAIT_DEPEND",
-       "JS2_WAIT_FINISH",
-       "JS3_JOBS",
-       "JS3_TASKS",
-       "JS3_ACTIVE",
-       "",
-       "JS3_WAIT_READ",
-       "JS3_WAIT_ISSUE",
-       "JS3_WAIT_DEPEND",
-       "JS3_WAIT_FINISH",
-       "JS4_JOBS",
-       "JS4_TASKS",
-       "JS4_ACTIVE",
-       "",
-       "JS4_WAIT_READ",
-       "JS4_WAIT_ISSUE",
-       "JS4_WAIT_DEPEND",
-       "JS4_WAIT_FINISH",
-       "JS5_JOBS",
-       "JS5_TASKS",
-       "JS5_ACTIVE",
-       "",
-       "JS5_WAIT_READ",
-       "JS5_WAIT_ISSUE",
-       "JS5_WAIT_DEPEND",
-       "JS5_WAIT_FINISH",
-       "JS6_JOBS",
-       "JS6_TASKS",
-       "JS6_ACTIVE",
-       "",
-       "JS6_WAIT_READ",
-       "JS6_WAIT_ISSUE",
-       "JS6_WAIT_DEPEND",
-       "JS6_WAIT_FINISH",
-
-       /*Tiler */
-       "",
-       "",
-       "",
-       "JOBS_PROCESSED",
-       "TRIANGLES",
-       "QUADS",
-       "POLYGONS",
-       "POINTS",
-       "LINES",
-       "VCACHE_HIT",
-       "VCACHE_MISS",
-       "FRONT_FACING",
-       "BACK_FACING",
-       "PRIM_VISIBLE",
-       "PRIM_CULLED",
-       "PRIM_CLIPPED",
-       "LEVEL0",
-       "LEVEL1",
-       "LEVEL2",
-       "LEVEL3",
-       "LEVEL4",
-       "LEVEL5",
-       "LEVEL6",
-       "LEVEL7",
-       "COMMAND_1",
-       "COMMAND_2",
-       "COMMAND_3",
-       "COMMAND_4",
-       "COMMAND_4_7",
-       "COMMAND_8_15",
-       "COMMAND_16_63",
-       "COMMAND_64",
-       "COMPRESS_IN",
-       "COMPRESS_OUT",
-       "COMPRESS_FLUSH",
-       "TIMESTAMPS",
-       "PCACHE_HIT",
-       "PCACHE_MISS",
-       "PCACHE_LINE",
-       "PCACHE_STALL",
-       "WRBUF_HIT",
-       "WRBUF_MISS",
-       "WRBUF_LINE",
-       "WRBUF_PARTIAL",
-       "WRBUF_STALL",
-       "ACTIVE",
-       "LOADING_DESC",
-       "INDEX_WAIT",
-       "INDEX_RANGE_WAIT",
-       "VERTEX_WAIT",
-       "PCACHE_WAIT",
-       "WRBUF_WAIT",
-       "BUS_READ",
-       "BUS_WRITE",
-       "",
-       "",
-       "",
-       "",
-       "",
-       "UTLB_STALL",
-       "UTLB_REPLAY_MISS",
-       "UTLB_REPLAY_FULL",
-       "UTLB_NEW_MISS",
-       "UTLB_HIT",
-
-       /* Shader Core */
-       "",
-       "",
-       "",
-       "SHADER_CORE_ACTIVE",
-       "FRAG_ACTIVE",
-       "FRAG_PRIMATIVES",
-       "FRAG_PRIMATIVES_DROPPED",
-       "FRAG_CYCLE_DESC",
-       "FRAG_CYCLES_PLR",
-       "FRAG_CYCLES_VERT",
-       "FRAG_CYCLES_TRISETUP",
-       "FRAG_CYCLES_RAST",
-       "FRAG_THREADS",
-       "FRAG_DUMMY_THREADS",
-       "FRAG_QUADS_RAST",
-       "FRAG_QUADS_EZS_TEST",
-       "FRAG_QUADS_EZS_KILLED",
-       "FRAG_QUADS_LZS_TEST",
-       "FRAG_QUADS_LZS_KILLED",
-       "FRAG_CYCLE_NO_TILE",
-       "FRAG_NUM_TILES",
-       "FRAG_TRANS_ELIM",
-       "COMPUTE_ACTIVE",
-       "COMPUTE_TASKS",
-       "COMPUTE_THREADS",
-       "COMPUTE_CYCLES_DESC",
-       "TRIPIPE_ACTIVE",
-       "ARITH_WORDS",
-       "ARITH_CYCLES_REG",
-       "ARITH_CYCLES_L0",
-       "ARITH_FRAG_DEPEND",
-       "LS_WORDS",
-       "LS_ISSUES",
-       "LS_RESTARTS",
-       "LS_REISSUES_MISS",
-       "LS_REISSUES_VD",
-       "LS_REISSUE_ATTRIB_MISS",
-       "LS_NO_WB",
-       "TEX_WORDS",
-       "TEX_BUBBLES",
-       "TEX_WORDS_L0",
-       "TEX_WORDS_DESC",
-       "TEX_THREADS",
-       "TEX_RECIRC_FMISS",
-       "TEX_RECIRC_DESC",
-       "TEX_RECIRC_MULTI",
-       "TEX_RECIRC_PMISS",
-       "TEX_RECIRC_CONF",
-       "LSC_READ_HITS",
-       "LSC_READ_MISSES",
-       "LSC_WRITE_HITS",
-       "LSC_WRITE_MISSES",
-       "LSC_ATOMIC_HITS",
-       "LSC_ATOMIC_MISSES",
-       "LSC_LINE_FETCHES",
-       "LSC_DIRTY_LINE",
-       "LSC_SNOOPS",
-       "AXI_TLB_STALL",
-       "AXI_TLB_MIESS",
-       "AXI_TLB_TRANSACTION",
-       "LS_TLB_MISS",
-       "LS_TLB_HIT",
-       "AXI_BEATS_READ",
-       "AXI_BEATS_WRITTEN",
-
-       /*L2 and MMU */
-       "",
-       "",
-       "",
-       "",
-       "MMU_HIT",
-       "MMU_NEW_MISS",
-       "MMU_REPLAY_FULL",
-       "MMU_REPLAY_MISS",
-       "MMU_TABLE_WALK",
-       "",
-       "",
-       "",
-       "",
-       "",
-       "",
-       "",
-       "UTLB_HIT",
-       "UTLB_NEW_MISS",
-       "UTLB_REPLAY_FULL",
-       "UTLB_REPLAY_MISS",
-       "UTLB_STALL",
-       "",
-       "",
-       "",
-       "",
-       "",
-       "",
-       "",
-       "",
-       "",
-       "L2_WRITE_BEATS",
-       "L2_READ_BEATS",
-       "L2_ANY_LOOKUP",
-       "L2_READ_LOOKUP",
-       "L2_SREAD_LOOKUP",
-       "L2_READ_REPLAY",
-       "L2_READ_SNOOP",
-       "L2_READ_HIT",
-       "L2_CLEAN_MISS",
-       "L2_WRITE_LOOKUP",
-       "L2_SWRITE_LOOKUP",
-       "L2_WRITE_REPLAY",
-       "L2_WRITE_SNOOP",
-       "L2_WRITE_HIT",
-       "L2_EXT_READ_FULL",
-       "L2_EXT_READ_HALF",
-       "L2_EXT_WRITE_FULL",
-       "L2_EXT_WRITE_HALF",
-       "L2_EXT_READ",
-       "L2_EXT_READ_LINE",
-       "L2_EXT_WRITE",
-       "L2_EXT_WRITE_LINE",
-       "L2_EXT_WRITE_SMALL",
-       "L2_EXT_BARRIER",
-       "L2_EXT_AR_STALL",
-       "L2_EXT_R_BUF_FULL",
-       "L2_EXT_RD_BUF_FULL",
-       "L2_EXT_R_RAW",
-       "L2_EXT_W_STALL",
-       "L2_EXT_W_BUF_FULL",
-       "L2_EXT_R_W_HAZARD",
-       "L2_TAG_HAZARD",
-       "L2_SNOOP_FULL",
-       "L2_REPLAY_FULL"
-};
-
-#define NUMBER_OF_HARDWARE_COUNTERS (sizeof(hardware_counter_names) / sizeof(hardware_counter_names[0]))
-
-#define GET_HW_BLOCK(c) (((c) >> 6) & 0x3)
-#define GET_COUNTER_OFFSET(c) ((c) & 0x3f)
-
-#if MALI_DDK_GATOR_API_VERSION == 3
-/* Opaque handles for kbase_context and kbase_hwc_dma_mapping */
-static struct mali_dd_hwcnt_handles *handles;
-
-/* Information about hardware counters */
-static struct mali_dd_hwcnt_info *in_out_info;
-
-#else
-/* Memory to dump hardware counters into */
-static void *kernel_dump_buffer;
-
-#if MALI_DDK_GATOR_API_VERSION == 2
-/* DMA state used to manage lifetime of the buffer */
-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;
-#endif
-
-static volatile bool kbase_device_busy = false;
-static unsigned int num_hardware_counters_enabled;
-
-/*
- * gatorfs variables for counter enable state
- */
-static mali_counter counters[NUMBER_OF_HARDWARE_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];
-
-extern mali_counter mali_activity[3];
-static const char* const mali_activity_names[] = {
-       "fragment",
-       "vertex",
-       "opencl",
-};
-
-#define SYMBOL_GET(FUNCTION, ERROR_COUNT) \
-       if(FUNCTION ## _symbol) \
-       { \
-               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"); \
-                       (ERROR_COUNT)++; \
-               } \
-       }
-
-#define SYMBOL_CLEANUP(FUNCTION) \
-       if(FUNCTION ## _symbol) \
-       { \
-               symbol_put(FUNCTION); \
-               FUNCTION ## _symbol = NULL; \
-       }
-
-/**
- * Execute symbol_get for all the Mali symbols and check for success.
- * @return the number of symbols not loaded.
- */
-static int init_symbols(void)
-{
-       int error_count = 0;
-#if MALI_DDK_GATOR_API_VERSION == 3
-       SYMBOL_GET(kbase_dd_instr_hwcnt_dump_irq, error_count);
-       SYMBOL_GET(kbase_dd_instr_hwcnt_dump_complete, error_count);
-       SYMBOL_GET(mali_dd_hwcnt_init, error_count);
-       SYMBOL_GET(mali_dd_hwcnt_clear, error_count);
-#else
-       SYMBOL_GET(kbase_find_device, error_count);
-       SYMBOL_GET(kbase_create_context, error_count);
-       SYMBOL_GET(kbase_va_alloc, error_count);
-       SYMBOL_GET(kbase_instr_hwcnt_enable, error_count);
-       SYMBOL_GET(kbase_instr_hwcnt_clear, error_count);
-       SYMBOL_GET(kbase_instr_hwcnt_dump_irq, error_count);
-       SYMBOL_GET(kbase_instr_hwcnt_dump_complete, error_count);
-       SYMBOL_GET(kbase_instr_hwcnt_disable, error_count);
-       SYMBOL_GET(kbase_va_free, error_count);
-       SYMBOL_GET(kbase_destroy_context, error_count);
-#endif
-
-       return error_count;
-}
-
-/**
- * Execute symbol_put for all the registered Mali symbols.
- */
-static void clean_symbols(void)
-{
-#if MALI_DDK_GATOR_API_VERSION == 3
-       SYMBOL_CLEANUP(kbase_dd_instr_hwcnt_dump_irq);
-       SYMBOL_CLEANUP(kbase_dd_instr_hwcnt_dump_complete);
-       SYMBOL_CLEANUP(mali_dd_hwcnt_init);
-       SYMBOL_CLEANUP(mali_dd_hwcnt_clear);
-#else
-       SYMBOL_CLEANUP(kbase_find_device);
-       SYMBOL_CLEANUP(kbase_create_context);
-       SYMBOL_CLEANUP(kbase_va_alloc);
-       SYMBOL_CLEANUP(kbase_instr_hwcnt_enable);
-       SYMBOL_CLEANUP(kbase_instr_hwcnt_clear);
-       SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_irq);
-       SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_complete);
-       SYMBOL_CLEANUP(kbase_instr_hwcnt_disable);
-       SYMBOL_CLEANUP(kbase_va_free);
-       SYMBOL_CLEANUP(kbase_destroy_context);
-#endif
-}
-
-/**
- * Determines whether a read should take place
- * @param current_time The current time, obtained from getnstimeofday()
- * @param prev_time_s The number of seconds at the previous read attempt.
- * @param next_read_time_ns The time (in ns) when the next read should be allowed.
- *
- * Note that this function has been separated out here to allow it to be tested.
- */
-static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns)
-{
-       /* If the current ns count rolls over a second, roll the next read time too. */
-       if (current_time->tv_sec != *prev_time_s) {
-               *next_read_time_ns = *next_read_time_ns - NSEC_PER_SEC;
-       }
-
-       /* Abort the read if the next read time has not arrived. */
-       if (current_time->tv_nsec < *next_read_time_ns) {
-               return 0;
-       }
-
-       /* Set the next read some fixed time after this one, and update the read timestamp. */
-       *next_read_time_ns = current_time->tv_nsec + READ_INTERVAL_NSEC;
-
-       *prev_time_s = current_time->tv_sec;
-       return 1;
-}
-
-static int start(void)
-{
-#if MALI_DDK_GATOR_API_VERSION < 3
-       struct kbase_uk_hwcnt_setup setup;
-       unsigned long long shadersPresent = 0;
-       u16 bitmask[] = { 0, 0, 0, 0 };
-       mali_error err;
-#endif
-       int cnt;
-
-       /* 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++){
-               in_out_info->bitmask[cnt] = 0;
-       }
-#endif
-       /* Calculate enable bitmasks based on counters_enabled array */
-       for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) {
-               const mali_counter *counter = &counters[cnt];
-               if (counter->enabled) {
-                       int block = GET_HW_BLOCK(cnt);
-                       int enable_bit = GET_COUNTER_OFFSET(cnt) / 4;
-#if MALI_DDK_GATOR_API_VERSION == 3
-                       in_out_info->bitmask[block] |= (1 << enable_bit);
-#else
-                       bitmask[block] |= (1 << enable_bit);
-#endif
-                       pr_debug("gator: Mali-T6xx: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt);
-                       num_hardware_counters_enabled++;
-               }
-       }
-
-#if MALI_DDK_GATOR_API_VERSION == 3
-       /* Create a kbase context for HW counters */
-       if (num_hardware_counters_enabled > 0) {
-               if (init_symbols() > 0) {
-                       clean_symbols();
-                       /* No Mali driver code entrypoints found - not a fault. */
-                       return 0;
-               }
-
-               handles = mali_dd_hwcnt_init_symbol(in_out_info);
-
-               if(handles == NULL) {
-                       goto out;
-               }
-
-               /* See if we can get the number of shader cores */
-               shader_present_low = (unsigned long)in_out_info->shader_present_bitmap;
-
-               kbase_device_busy = false;
-       }
-
-       return 0;
-#else
-       /* Create a kbase context for HW counters */
-       if (num_hardware_counters_enabled > 0) {
-               if (init_symbols() > 0) {
-                       clean_symbols();
-                       /* No Mali driver code entrypoints found - not a fault. */
-                       return 0;
-               }
-
-               kbdevice = kbase_find_device_symbol(-1);
-
-               /* If we already got a context, fail */
-               if (kbcontext) {
-                       pr_debug("gator: Mali-T6xx: error context already present\n");
-                       goto out;
-               }
-
-               /* kbcontext will only be valid after all the Mali symbols are loaded successfully */
-               kbcontext = kbase_create_context_symbol(kbdevice);
-               if (!kbcontext) {
-                       pr_debug("gator: Mali-T6xx: error creating kbase context\n");
-                       goto out;
-               }
-
-
-               /* See if we can get the number of shader cores */
-               shadersPresent = kbdevice->shader_present_bitmap;
-               shader_present_low = (unsigned long)shadersPresent;
-
-               /*
-                * The amount of memory needed to store the dump (bytes)
-                * DUMP_SIZE = number of core groups
-                *             * number of blocks (always 8 for midgard)
-                *             * number of counters per block (always 64 for midgard)
-                *             * number of bytes per counter (always 4 in midgard)
-                * For a Mali-T6xx with a single core group = 1 * 8 * 64 * 4 = 2048
-                * For a Mali-T6xx 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);
-#elif MALI_DDK_GATOR_API_VERSION == 2
-               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");
-                       goto destroy_context;
-               }
-
-               setup.dump_buffer = (uintptr_t)kernel_dump_buffer;
-               setup.jm_bm = bitmask[JM_BLOCK];
-               setup.tiler_bm = bitmask[TILER_BLOCK];
-               setup.shader_bm = bitmask[SHADER_BLOCK];
-               setup.mmu_l2_bm = bitmask[MMU_BLOCK];
-               /* These counters do not exist on Mali-T60x */
-               setup.l3_cache_bm = 0;
-
-               /* Use kbase API to enable hardware counters and provide dump buffer */
-               err = kbase_instr_hwcnt_enable_symbol(kbcontext, &setup);
-               if (err != MALI_ERROR_NONE) {
-                       pr_debug("gator: Mali-T6xx: can't setup hardware counters\n");
-                       goto free_buffer;
-               }
-               pr_debug("gator: Mali-T6xx: hardware counters enabled\n");
-               kbase_instr_hwcnt_clear_symbol(kbcontext);
-               pr_debug("gator: Mali-T6xx: hardware counters cleared \n");
-
-               kbase_device_busy = false;
-       }
-
-       return 0;
-
-free_buffer:
-#if MALI_DDK_GATOR_API_VERSION == 1
-       kbase_va_free_symbol(kbcontext, kernel_dump_buffer);
-#elif MALI_DDK_GATOR_API_VERSION == 2
-       kbase_va_free_symbol(kbcontext, &kernel_dump_buffer_handle);
-#endif
-
-destroy_context:
-       kbase_destroy_context_symbol(kbcontext);
-#endif
-
-out:
-       clean_symbols();
-       return -1;
-}
-
-static void stop(void)
-{
-       unsigned int cnt;
-#if MALI_DDK_GATOR_API_VERSION == 3
-       struct mali_dd_hwcnt_handles *temp_hand;
-#else
-       struct kbase_context *temp_kbcontext;
-#endif
-
-       pr_debug("gator: Mali-T6xx: stop\n");
-
-       /* Set all counters as disabled */
-       for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) {
-               counters[cnt].enabled = 0;
-       }
-
-       /* Destroy the context for HW counters */
-#if MALI_DDK_GATOR_API_VERSION == 3
-       if (num_hardware_counters_enabled > 0 && handles != NULL) {
-               /*
-                * Set the global variable to NULL before destroying it, because
-                * other function will check this before using it.
-                */
-               temp_hand = handles;
-               handles = NULL;
-
-               mali_dd_hwcnt_clear_symbol(in_out_info, temp_hand);
-
-               kfree(in_out_info);
-
-#else
-       if (num_hardware_counters_enabled > 0 && kbcontext != NULL) {
-               /*
-                * Set the global variable to NULL before destroying it, because
-                * other function will check this before using it.
-                */
-               temp_kbcontext = kbcontext;
-               kbcontext = NULL;
-
-               kbase_instr_hwcnt_disable_symbol(temp_kbcontext);
-
-#if MALI_DDK_GATOR_API_VERSION == 1
-               kbase_va_free_symbol(temp_kbcontext, kernel_dump_buffer);
-#elif MALI_DDK_GATOR_API_VERSION == 2
-               kbase_va_free_symbol(temp_kbcontext, &kernel_dump_buffer_handle);
-#endif
-
-               kbase_destroy_context_symbol(temp_kbcontext);
-#endif
-
-               pr_debug("gator: Mali-T6xx: hardware counters stopped\n");
-
-               clean_symbols();
-       }
-}
-
-static int read(int **buffer)
-{
-       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;
-
-       if (!on_primary_core()) {
-               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.
-        */
-       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) {
-               const unsigned int vithar_blocks[] = {
-                       0x700,  /* VITHAR_JOB_MANAGER,     Block 0 */
-                       0x400,  /* VITHAR_TILER,           Block 1 */
-                       0x000,  /* VITHAR_SHADER_CORE,     Block 2 */
-                       0x500   /* VITHAR_MEMORY_SYSTEM,   Block 3 */
-               };
-
-#if MALI_DDK_GATOR_API_VERSION == 3
-               if (!handles) {
-                       return -1;
-               }
-
-               /* Mali symbols can be called safely since a kbcontext is valid */
-               if (kbase_dd_instr_hwcnt_dump_complete_symbol(handles, &success) == MALI_TRUE) {
-#else
-               if (!kbcontext) {
-                       return -1;
-               }
-
-               /* Mali symbols can be called safely since a kbcontext is valid */
-               if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE) {
-#endif
-                       kbase_device_busy = false;
-
-                       if (success == MALI_TRUE) {
-                               /* 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
-
-                                               /* 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 (!kbase_device_busy) {
-                       kbase_device_busy = true;
-#if MALI_DDK_GATOR_API_VERSION == 3
-                       kbase_dd_instr_hwcnt_dump_irq_symbol(handles);
-#else
-                       kbase_instr_hwcnt_dump_irq_symbol(kbcontext);
-#endif
-               }
-       }
-
-       /* Update the buffer */
-       if (buffer) {
-               *buffer = (int *)counter_dump;
-       }
-
-       return len;
-}
-
-static int create_files(struct super_block *sb, struct dentry *root)
-{
-       unsigned int event;
-       /*
-        * Create the filesystem for all events
-        */
-       int counter_index = 0;
-
-       for (event = 0; event < ARRAY_SIZE(mali_activity); event++) {
-               if (gator_mali_create_file_system(mali_name, mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) {
-                       return -1;
-               }
-       }
-
-       for (event = 0; event < NUMBER_OF_HARDWARE_COUNTERS; event++) {
-               if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event], NULL) != 0)
-                       return -1;
-               counter_index++;
-       }
-
-       return 0;
-}
-
-static struct gator_interface gator_events_mali_t6xx_interface = {
-       .create_files = create_files,
-       .start = start,
-       .stop = stop,
-       .read = read
-};
-
-int gator_events_mali_t6xx_hw_init(void)
-{
-       pr_debug("gator: Mali-T6xx: sw_counters init\n");
-
-#if GATOR_TEST
-       test_all_is_read_scheduled();
-#endif
-
-       gator_mali_initialise_counters(mali_activity, ARRAY_SIZE(mali_activity));
-       gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS);
-
-       return gator_events_install(&gator_events_mali_t6xx_interface);
-}
diff --git a/drivers/gator/gator_events_mali_t6xx_hw_test.c b/drivers/gator/gator_events_mali_t6xx_hw_test.c
deleted file mode 100644 (file)
index ba6553f..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2012-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.
- *
- */
-
-/**
- * Test functions for mali_t600_hw code.
- */
-
-static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns);
-
-static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int expected_result, s32 expected_next_ns)
-{
-       struct timespec current_time;
-       u32 prev_time_s = prev_s;
-       s32 next_read_time_ns = next_ns;
-
-       current_time.tv_sec = s;
-       current_time.tv_nsec = ns;
-
-       if (is_read_scheduled(&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);
-               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);
-               return 0;
-       }
-
-       return 1;
-}
-
-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__);
-
-       n_tests_passed += test_is_read_scheduled(0, 0, 0, 0, 1, READ_INTERVAL_NSEC);    /* Null time */
-       n_tests_passed += test_is_read_scheduled(100, 1000, 0, 0, 1, READ_INTERVAL_NSEC + 1000);        /* Initial values */
-
-       n_tests_passed += test_is_read_scheduled(100, HIGHEST_NS, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500);
-       n_tests_passed += test_is_read_scheduled(101, 0001, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500 - NSEC_PER_SEC);
-       n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500 - NSEC_PER_SEC, 1, 600 + READ_INTERVAL_NSEC);
-
-       n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500, 1, 600 + READ_INTERVAL_NSEC);
-
-       printk("gator: %d tests passed\n", n_tests_passed);
-}
index c633dfdce3069c91ac6c19bb8b2d2ab694945dbb..c625ac5af9cd37fac1951535ba4092f08e6b0e59 100644 (file)
@@ -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;
 
index 5bc01c42c3a2cf983e7937737e63104ec454a5f6..6b2af995ed41e7623ca06473e1e0724819496e5c 100644 (file)
@@ -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;
index 11c10e3755117ae317abfcebd720ad2d2f9b12f7..d21b4db7b77cde5455ac91da54548651358d2947 100644 (file)
@@ -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;
        }
index 06bbad5b10c34847468b8a0dcf2a3f26052ba4f7..47cf278e508b110fa7746fb2bf8d9a7d2420eeb5 100644 (file)
@@ -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>
 
 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;
        }
 
index 9e39158301820e0b33bd80d204650f59710ff2c0..637107d6af1d6c8b4c8048d0f352380d17ee0d3f 100644 (file)
@@ -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;
index 2e5be8d50e9d96ccc75aa37bf18f44e3cc5d605b..49219362db092515ee590c002dbc66cff870d977 100644 (file)
@@ -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 (file)
index 9de8586..0000000
+++ /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);
-}
index 166cfe7d681de292396163897aa4023d623b81d0..d8fb357b9edac1d61c9420e97a0dc4f0b55925f8 100644 (file)
@@ -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);
 }
 
index 76584554b00fd1c0ae08a85af1ea1f21351488db..c1525e10a8da37cd67c91a5a41ab947c78d6e612 100644 (file)
@@ -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;
 }
index 9180b874457a21425b98305df612f8f7a32f95f9..fb78c10fd987458f7bcdb99cacc55b3e3ab0e22c 100644 (file)
@@ -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();
        }
index 0d867f22364f069626fbb327e7eb68ea885b4d62..30bf60d952869d83280c16c0bb6390405954b3d1 100644 (file)
@@ -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
@@ -314,13 +324,6 @@ static const struct gator_cpu gator_cpus[] = {
                .dt_name = "arm,cortex-a9",
                .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",
@@ -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);
 
index 97b4ae6f9d4d28e8f0bc7b02c170c1722aa1553b..0d11676436429640d91b41fec7f0ce79c5a40321 100644 (file)
@@ -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);
 }
index a8b9e7d61eceacf398c9ebe70bde67135a2581b1..5de9152e365aa4cdf4229c515fa9144df1efe07c 100644 (file)
@@ -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;
index f2754b1c2b56cc7c86c25f8944df97ea053963c1..46e04b29a18748c3058819850fbd6664d4329f7c 100644 (file)
 
 #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();
index 655008628933d71d937ff26aceb49b55abbf7953..6d7cbd7348e151d43fe992b521caf89311fe5be6 100644 (file)
@@ -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 (file)
index 104b34f..0000000
+++ /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 (file)
index 0000000..5ed0697
--- /dev/null
@@ -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
index ff00d90cee78e79c1dff955ccfcff6ecbbc85a10..2bc0b037eee6c668e5948a4751678324dafb92a9 100644 (file)
@@ -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.
index 43c57604288037e4d3f453285b79a1f2e087a25b..d6465312628ed1a5479fff8611271201dc997749 100644 (file)
@@ -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_midgard.mk b/drivers/gator/mali_midgard.mk
new file mode 100644 (file)
index 0000000..1b784d5
--- /dev/null
@@ -0,0 +1,39 @@
+# Defines for Mali-Midgard driver
+EXTRA_CFLAGS += -DMALI_USE_UMP=1 \
+                -DMALI_LICENSE_IS_GPL=1 \
+                -DMALI_BASE_TRACK_MEMLEAK=0 \
+                -DMALI_DEBUG=0 \
+                -DMALI_ERROR_INJECT_ON=0 \
+                -DMALI_CUSTOMER_RELEASE=1 \
+                -DMALI_UNIT_TEST=0 \
+                -DMALI_BACKEND_KERNEL=1 \
+                -DMALI_NO_MALI=0
+
+DDK_DIR ?= .
+ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/t6xx),)
+KBASE_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase
+OSK_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase/osk
+endif
+
+ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/midgard),)
+KBASE_DIR = $(DDK_DIR)/drivers/gpu/arm/midgard
+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_kbase_gator_api.h),)
+EXTRA_CFLAGS += -DMALI_SIMPLE_API=1
+endif
+
+UMP_DIR = $(DDK_DIR)/include/linux
+
+# Include directories in the DDK
+EXTRA_CFLAGS += -I$(KBASE_DIR)/ \
+                -I$(KBASE_DIR)/.. \
+                -I$(OSK_DIR)/.. \
+                -I$(UMP_DIR)/.. \
+                -I$(DDK_DIR)/include \
+                -I$(KBASE_DIR)/osk/src/linux/include \
+                -I$(KBASE_DIR)/platform_dummy \
+                -I$(KBASE_DIR)/src
+
diff --git a/drivers/gator/mali_t6xx.mk b/drivers/gator/mali_t6xx.mk
deleted file mode 100644 (file)
index fa7571d..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-# Defines for Mali-T6xx driver
-EXTRA_CFLAGS += -DMALI_USE_UMP=1 \
-                -DMALI_LICENSE_IS_GPL=1 \
-                -DMALI_BASE_TRACK_MEMLEAK=0 \
-                -DMALI_DEBUG=0 \
-                -DMALI_ERROR_INJECT_ON=0 \
-                -DMALI_CUSTOMER_RELEASE=1 \
-                -DMALI_UNIT_TEST=0 \
-                -DMALI_BACKEND_KERNEL=1 \
-                -DMALI_NO_MALI=0
-
-DDK_DIR ?= .
-ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/t6xx),)
-KBASE_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase
-OSK_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase/osk
-endif
-
-ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/midgard),)
-KBASE_DIR = $(DDK_DIR)/drivers/gpu/arm/midgard
-OSK_DIR = $(DDK_DIR)/drivers/gpu/arm/midgard/osk
-EXTRA_CFLAGS += -DMALI_DIR_MIDGARD=1
-endif
-
-ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/midgard/mali_dd_gator_api.h),)
-EXTRA_CFLAGS += -DMALI_SIMPLE_API=1
-endif
-
-UMP_DIR = $(DDK_DIR)/include/linux
-
-# Include directories in the DDK
-EXTRA_CFLAGS += -I$(KBASE_DIR)/ \
-                -I$(KBASE_DIR)/.. \
-                -I$(OSK_DIR)/.. \
-                -I$(UMP_DIR)/.. \
-                -I$(DDK_DIR)/include \
-                -I$(KBASE_DIR)/osk/src/linux/include \
-                -I$(KBASE_DIR)/platform_dummy \
-                -I$(KBASE_DIR)/src
-
index 44c069cc7e2453d6f8e62b5b2deeb22cf43f7966..970ac6946150905d164af642eeddb571e6c95d77 100644 (file)
@@ -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 (file)
index 0000000..50110b4
--- /dev/null
@@ -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 (file)
index 0000000..cdefef1
--- /dev/null
@@ -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 &);
+};
index 631ba54148d1559c41866b9a841b17a3d42c9444..3ada471cac19eeebb9a53d7cc36a7bc423c4be52 100644 (file)
@@ -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
index dd19f7f8be76b7fb200075914b476e23554e4f2e..8fa6280150694d1b681a209d5f1eded1930a4686 100644 (file)
 #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() {
index 2de1b97ac091f92040485489818b337d81104359..6cffd8e39a36748d9b2a447bb46ebaff926b662c 100644 (file)
@@ -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 (file)
index 0000000..dd1a2b1
--- /dev/null
@@ -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 (file)
index 0000000..fb4c717
--- /dev/null
@@ -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 (file)
index 0000000..41f9d6f
--- /dev/null
@@ -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 (file)
index 0000000..ad8c9aa
--- /dev/null
@@ -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
index 4a11415a00c978bfe9be2d350d4e95644522c3dd..0b5802c893bbbfe10573041bfe26a1141ed6e8a4 100644 (file)
@@ -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;
 }
index ed08c44bc3ffa21a4bc336281440da39b437517d..b704f6e53bb593bcca46326b4a87b1525e4bc04c 100644 (file)
@@ -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"
 
index 1901ecc6a7248a498ce67b559fcf5f3c85abf312..6b5bbb3bf6afb8c727809b56313de32080ae0a69 100644 (file)
 #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;
index a306a776081938fe93320ca8134ea6b8b68f677a..cc78202ceb5caaba8996a92409e7a4fc31cce0c2 100644 (file)
@@ -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 (file)
index 0000000..28d73cf
--- /dev/null
@@ -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 (file)
index 0000000..17244b7
--- /dev/null
@@ -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
index 6f5e2aae50e1df685b26f9a1a6be162554b93fad..bee383a1c797054cb95af2e2817ba96293dd2369 100644 (file)
 #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 (file)
index 0000000..5deb0f3
--- /dev/null
@@ -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 (file)
index 0000000..d0db18c
--- /dev/null
@@ -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
index 09e04016291232477fc2d4d38ff8a75ec48b0dc9..275da31c7a0d9d266a4d8e3865b0c9f8802b84c0 100644 (file)
@@ -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());
+       }
+}
index e5ed7b6c1295993bcc454a5b55efbb814b129129..72870e3dbca1a9ec99aa31686e43587d314ad4da 100644 (file)
@@ -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
index 11d3095ef6d20a39cd3c84e466d7c7c886c7cbbf..7f299b646952c101c511d59f4985d0bc4fcf6775 100644 (file)
@@ -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;
        }
index 6f92b336ae1955c33e902c66ad48fe8607fcb1c5..df20713ad63cac928b96b6e9bbd9faf09951a575 100644 (file)
@@ -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;
index cf0192ef671fe4e26da883e4065c44c18994a782..d905bbabe98853cb760dfc3ad0c951e3c449faab 100644 (file)
@@ -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()) {
index b6ec301d0c0830cdaf0adb5260b2fe80c7ff5f56..8f5e6b684c538b192c03ab40529836d61a4d2157 100644 (file)
@@ -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]);
index 2e7ed27df255d9d8b614b6a0dd114072ce49dc83..919e75e8a41af34d8935d8b58e3d6395602f87b6 100644 (file)
@@ -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
index 40c8df1af22211202e064e30b08332f9250ce622..dd8eb804dc99863f67aa42825c0f34b7ff317aca 100644 (file)
 #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());
-       }
-}
index ef395536233103736d4384e2ef2f8dd0142936e8..a7dc8b4df9dde673f92af1d2829f045e2cc9402e 100644 (file)
 
 #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 &);
index f672e92a6807403c43274ad3705cc16a2dd2aee6..41275fd287b8c7a803ced309fd0d5f5e30d49848 100644 (file)
@@ -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) {
index bdda3f549b50c8a3368c6a2a3c63f1c4a2def45e..21c8d8580391230eb992e8032b92c6d84a6d627a 100644 (file)
@@ -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 (file)
index 0000000..b156f1c
--- /dev/null
@@ -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 (file)
index 0000000..5f958be
--- /dev/null
@@ -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 (file)
index 0000000..5216333
--- /dev/null
@@ -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 (file)
index 0000000..2391b88
--- /dev/null
@@ -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.cpp b/tools/gator/daemon/Hwmon.cpp
deleted file mode 100644 (file)
index e444247..0000000
+++ /dev/null
@@ -1,352 +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 "Hwmon.h"
-
-#include "libsensors/sensors.h"
-
-#include "Buffer.h"
-#include "Counter.h"
-#include "Logging.h"
-#include "SessionData.h"
-
-class HwmonCounter {
-public:
-       HwmonCounter(HwmonCounter *next, 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; }
-       const char *getDisplay() const { return display; }
-       const char *getCounterClass() const { return counter_class; }
-       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();
-
-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;
-
-       // 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;
-
-       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";
-               modifier = 1000;
-               monotonic = false;
-               break;
-       case SENSORS_FEATURE_FAN:
-               title = "Fan";
-               input = SENSORS_SUBFEATURE_FAN_INPUT;
-               display = "average";
-               counter_class = "absolute";
-               unit = "RPM";
-               modifier = 1;
-               monotonic = false;
-               break;
-       case SENSORS_FEATURE_TEMP:
-               title = "Temperature";
-               input = SENSORS_SUBFEATURE_TEMP_INPUT;
-               display = "maximum";
-               counter_class = "absolute";
-               unit = "°C";
-               modifier = 1000;
-               monotonic = false;
-               break;
-       case SENSORS_FEATURE_POWER:
-               title = "Power";
-               input = SENSORS_SUBFEATURE_POWER_INPUT;
-               display = "maximum";
-               counter_class = "absolute";
-               unit = "W";
-               modifier = 1000000;
-               monotonic = false;
-               break;
-       case SENSORS_FEATURE_ENERGY:
-               title = "Energy";
-               input = SENSORS_SUBFEATURE_ENERGY_INPUT;
-               display = "accumulate";
-               counter_class = "delta";
-               unit = "J";
-               modifier = 1000000;
-               monotonic = true;
-               break;
-       case SENSORS_FEATURE_CURR:
-               title = "Current";
-               input = SENSORS_SUBFEATURE_CURR_INPUT;
-               display = "maximum";
-               counter_class = "absolute";
-               unit = "A";
-               modifier = 1000;
-               monotonic = false;
-               break;
-       case SENSORS_FEATURE_HUMIDITY:
-               title = "Humidity";
-               input = SENSORS_SUBFEATURE_HUMIDITY_INPUT;
-               display = "average";
-               counter_class = "absolute";
-               unit = "%";
-               modifier = 1000;
-               monotonic = false;
-               break;
-       default:
-               logg->logError(__FILE__, __LINE__, "Unsupported hwmon feature %i", feature->type);
-               handleException();
-       }
-
-       for (HwmonCounter * counter = next; counter != NULL; counter = counter->getNext()) {
-               if (strcmp(label, counter->getLabel()) == 0 && strcmp(title, counter->getTitle()) == 0) {
-                       duplicate = true;
-                       counter->duplicate = true;
-                       break;
-               }
-       }
-}
-
-HwmonCounter::~HwmonCounter() {
-       free((void *)label);
-       delete [] name;
-}
-
-double HwmonCounter::read() {
-       double value;
-       double result;
-       const sensors_subfeature *subfeature;
-
-       // Keep in sync with canRead
-       subfeature = sensors_get_subfeature(chip, feature, input);
-       if (!subfeature) {
-               logg->logError(__FILE__, __LINE__, "No input value for hwmon sensor %s", label);
-               handleException();
-       }
-
-       if (sensors_get_value(chip, subfeature->number, &value) != 0) {
-               logg->logError(__FILE__, __LINE__, "Can't get input value for hwmon sensor %s", label);
-               handleException();
-       }
-
-       result = (monotonic ? value - previous_value : value);
-       previous_value = value;
-
-       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) {
-}
-
-Hwmon::~Hwmon() {
-       while (counters != NULL) {
-               HwmonCounter * counter = counters;
-               counters = counter->getNext();
-               delete counter;
-       }
-       sensors_cleanup();
-}
-
-void Hwmon::setup() {
-       // hwmon does not currently work with perf
-       if (gSessionData->perf.isSetup()) {
-               return;
-       }
-
-       int err = sensors_init(NULL);
-       if (err) {
-               logg->logMessage("Failed to initialize libsensors! (%d)", err);
-               return;
-       }
-       sensors_sysfs_no_scaling = 1;
-
-       int chip_nr = 0;
-       const sensors_chip_name *chip;
-       while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
-               int feature_nr = 0;
-               const sensors_feature *feature;
-               while ((feature = sensors_get_features(chip, &feature_nr))) {
-                       counters = new HwmonCounter(counters, 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 {
-       root = mxmlNewElement(root, "category");
-       mxmlElementSetAttr(root, "name", "hwmon");
-
-       char buf[1024];
-       for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
-               if (!counter->canRead()) {
-                       continue;
-               }
-               mxml_node_t *node = mxmlNewElement(root, "event");
-               mxmlElementSetAttr(node, "counter", counter->getName());
-               mxmlElementSetAttr(node, "title", counter->getTitle());
-               if (counter->isDuplicate()) {
-                       mxmlElementSetAttrf(node, "name", "%s (0x%x)", counter->getLabel(), counter->getKey());
-               } else {
-                       mxmlElementSetAttr(node, "name", counter->getLabel());
-               }
-               mxmlElementSetAttr(node, "display", counter->getDisplay());
-               mxmlElementSetAttr(node, "class", counter->getCounterClass());
-               mxmlElementSetAttr(node, "units", counter->getUnit());
-               if (counter->getModifier() != 1) {
-                       mxmlElementSetAttrf(node, "modifier", "%d", counter->getModifier());
-               }
-               if (strcmp(counter->getDisplay(), "average") == 0 || strcmp(counter->getDisplay(), "maximum") == 0) {
-                       mxmlElementSetAttr(node, "average_selection", "yes");
-               }
-               snprintf(buf, sizeof(buf), "libsensors %s sensor %s (%s)", counter->getTitle(), counter->getLabel(), counter->getName());
-               mxmlElementSetAttr(node, "description", buf);
-       }
-}
-
-void Hwmon::start() {
-       for (HwmonCounter * counter = counters; 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/Hwmon.h b/tools/gator/daemon/Hwmon.h
deleted file mode 100644 (file)
index a22a360..0000000
+++ /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/HwmonDriver.cpp b/tools/gator/daemon/HwmonDriver.cpp
new file mode 100644 (file)
index 0000000..9d161ae
--- /dev/null
@@ -0,0 +1,245 @@
+/**
+ * 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 "HwmonDriver.h"
+
+#include "libsensors/sensors.h"
+
+#include "Logging.h"
+
+// 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(DriverCounter *next, char *const name, const sensors_chip_name *chip, const sensors_feature *feature);
+       ~HwmonCounter();
+
+       const char *getLabel() const { return label; }
+       const char *getTitle() const { return title; }
+       bool isDuplicate() const { return duplicate; }
+       const char *getDisplay() const { return display; }
+       const char *getCounterClass() const { return counter_class; }
+       const char *getUnit() const { return unit; }
+       int getModifier() const { return modifier; }
+
+       int64_t read();
+
+private:
+       void init(const sensors_chip_name *chip, const sensors_feature *feature);
+
+       const sensors_chip_name *chip;
+       const sensors_feature *feature;
+       char *label;
+       const char *title;
+       const char *display;
+       const char *counter_class;
+       const char *unit;
+       double previous_value;
+       int modifier;
+       int monotonic: 1,
+               duplicate : 1;
+
+       // Intentionally unimplemented
+       HwmonCounter(const HwmonCounter &);
+       HwmonCounter &operator=(const HwmonCounter &);
+};
+
+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";
+               display = "maximum";
+               counter_class = "absolute";
+               unit = "V";
+               modifier = 1000;
+               monotonic = false;
+               break;
+       case SENSORS_FEATURE_FAN:
+               title = "Fan";
+               display = "average";
+               counter_class = "absolute";
+               unit = "RPM";
+               modifier = 1;
+               monotonic = false;
+               break;
+       case SENSORS_FEATURE_TEMP:
+               title = "Temperature";
+               display = "maximum";
+               counter_class = "absolute";
+               unit = "°C";
+               modifier = 1000;
+               monotonic = false;
+               break;
+       case SENSORS_FEATURE_POWER:
+               title = "Power";
+               display = "maximum";
+               counter_class = "absolute";
+               unit = "W";
+               modifier = 1000000;
+               monotonic = false;
+               break;
+       case SENSORS_FEATURE_ENERGY:
+               title = "Energy";
+               display = "accumulate";
+               counter_class = "delta";
+               unit = "J";
+               modifier = 1000000;
+               monotonic = true;
+               break;
+       case SENSORS_FEATURE_CURR:
+               title = "Current";
+               display = "maximum";
+               counter_class = "absolute";
+               unit = "A";
+               modifier = 1000;
+               monotonic = false;
+               break;
+       case SENSORS_FEATURE_HUMIDITY:
+               title = "Humidity";
+               display = "average";
+               counter_class = "absolute";
+               unit = "%";
+               modifier = 1000;
+               monotonic = false;
+               break;
+       default:
+               logg->logError(__FILE__, __LINE__, "Unsupported hwmon feature %i", feature->type);
+               handleException();
+       }
+
+       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;
+                       break;
+               }
+       }
+}
+
+HwmonCounter::~HwmonCounter() {
+       free((void *)label);
+}
+
+int64_t HwmonCounter::read() {
+       double value;
+       double result;
+       const sensors_subfeature *subfeature;
+
+       // 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();
+       }
+
+       if (sensors_get_value(chip, subfeature->number, &value) != 0) {
+               logg->logError(__FILE__, __LINE__, "Can't get input value for hwmon sensor %s", label);
+               handleException();
+       }
+
+       result = (monotonic ? value - previous_value : value);
+       previous_value = value;
+
+       return result;
+}
+
+HwmonDriver::HwmonDriver() {
+}
+
+HwmonDriver::~HwmonDriver() {
+       sensors_cleanup();
+}
+
+void HwmonDriver::readEvents(mxml_node_t *const) {
+       int err = sensors_init(NULL);
+       if (err) {
+               logg->logMessage("Failed to initialize libsensors! (%d)", err);
+               return;
+       }
+       sensors_sysfs_no_scaling = 1;
+
+       int chip_nr = 0;
+       const sensors_chip_name *chip;
+       while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
+               int feature_nr = 0;
+               const sensors_feature *feature;
+               while ((feature = sensors_get_features(chip, &feature_nr))) {
+                       // 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));
+               }
+       }
+}
+
+void HwmonDriver::writeEvents(mxml_node_t *root) const {
+       root = mxmlNewElement(root, "category");
+       mxmlElementSetAttr(root, "name", "hwmon");
+
+       char buf[1024];
+       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());
+               if (counter->isDuplicate()) {
+                       mxmlElementSetAttrf(node, "name", "%s (0x%x)", counter->getLabel(), counter->getKey());
+               } else {
+                       mxmlElementSetAttr(node, "name", counter->getLabel());
+               }
+               mxmlElementSetAttr(node, "display", counter->getDisplay());
+               mxmlElementSetAttr(node, "class", counter->getCounterClass());
+               mxmlElementSetAttr(node, "units", counter->getUnit());
+               if (counter->getModifier() != 1) {
+                       mxmlElementSetAttrf(node, "modifier", "%d", counter->getModifier());
+               }
+               if (strcmp(counter->getDisplay(), "average") == 0 || strcmp(counter->getDisplay(), "maximum") == 0) {
+                       mxmlElementSetAttr(node, "average_selection", "yes");
+               }
+               snprintf(buf, sizeof(buf), "libsensors %s sensor %s (%s)", counter->getTitle(), counter->getLabel(), counter->getName());
+               mxmlElementSetAttr(node, "description", buf);
+       }
+}
+
+void HwmonDriver::start() {
+       for (DriverCounter *counter = getCounters(); counter != NULL; counter = counter->getNext()) {
+               if (!counter->isEnabled()) {
+                       continue;
+               }
+               counter->read();
+       }
+}
diff --git a/tools/gator/daemon/HwmonDriver.h b/tools/gator/daemon/HwmonDriver.h
new file mode 100644 (file)
index 0000000..f28d825
--- /dev/null
@@ -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
index 73e123d2f14ec781e93ecb5f1fa7e37f77c13c9f..fe9dc6a7e4f7027919743189dd52c5a9c1905266 100644 (file)
@@ -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) {
index fb7fc8a8f9c6200fc31a9fe190d36d3d309370df..900a60e87d24d605957fc58eb4653a1ffd7840d9 100644 (file)
@@ -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
index b1e7219795cfd6c7788c9d851a038502bc2bca1b..25d281f8328b4d2b433f9ea037503baf626f4cdf 100644 (file)
@@ -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;
 
index b8d3178950d6c5a119e69ac03b0faf706608bbaf..41ffa1a45151c814aa0de13971a55fc7b17e08be 100644 (file)
 #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: ");
index 4934bb079754095540adff94216366ea41d2e9fa..09e93ff13f7a95b9f564da4c9f92e1f720df24df 100644 (file)
@@ -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;
index 2ed49fdb688b8f96cc2ee3d28e43211b5bbfb70c..27531b438b6391ebd1ff08dcca57e66e090e119f 100644 (file)
 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),)
index 18b413b01a37dd981792a67fb63bae02c11c4e73..5eef2643ab15349587dcd9e32be9ecb29d3625fc 100644 (file)
@@ -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);
 }
index 00cb80889a7439d4aab3e3e8c7437c05cfbc6737..204a57a447ace84b5db1103b25c146d551bf1698 100644 (file)
@@ -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 (file)
index 0000000..cce15c1
--- /dev/null
@@ -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 (file)
index 0000000..eb1b041
--- /dev/null
@@ -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
index b34a15f0eb0ccac547ee1162c2b429f8ca360e57..74f22ee29fec7dcb776a7999e34353e1100a8a6d 100644 (file)
@@ -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 (file)
index 0000000..e75c069
--- /dev/null
@@ -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 (file)
index 0000000..50ff850
--- /dev/null
@@ -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
index 28774e36e5102dfee04832e9066b7c3b295753a6..aa0ce4929916eb57d1637ff63acf5a07af87548b 100644 (file)
 #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"
 #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();
index 20c67cc695e1733036b38e2610e944ef99e5a6fa..6b53b01fc3ee6e6c9221e219f26aca43a28882a9 100644 (file)
 
 #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__
index 5fad583f7bd095661d213d1f3d8f113b3bf63743..f127c996d43b9c6559c1ad0fd25faec11017e2a6 100644 (file)
@@ -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);
                }
        }
index 278a3b9d6db7d0a117be461a42a6d1eab6374219..25a10625a9e8006b255b4c4a0183e741b0620e9e 100644 (file)
@@ -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 &);
index ac97a077d266fad9d33fbf711d34a44f98b3fc89..ee90284cee41434cef36690e753a5089039092b4 100644 (file)
@@ -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;
                        }
index 2cae575a7059dca60cd4d1031441496689dc5f22..846203a9e18b3def479ea20c58e3cc488d384fb6 100644 (file)
@@ -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
 #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;
 
index 2a0239f7c348f3d0649bc89f956b2f82e5aacb86..4fd960a9058c5ebcd194b20fbb5f70979efbee34 100644 (file)
@@ -9,6 +9,7 @@
 #include "PerfGroup.h"
 
 #include <errno.h>
+#include <fcntl.h>
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/syscall.h>
        /* 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);
                }
        }
 }
index 3f1e2bb4d1c86033daa0ffce073c2b9ca99c7910..f7b3d725bac71d924ca466f11549ce9ddea669b8 100644 (file)
@@ -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();
index ecfaa66832bd783995086ea8fdb91a2ab9de9fc6..193b7789a290bb1583db307568ec94a2043599ed 100644 (file)
@@ -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"
 #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;
                }
        }
 
index 3f471c8de414609129867b5c48958c2ee1bfabfe..ce1eafe8e9532091ebcfb6fc6e65d06baae36b22 100644 (file)
@@ -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;
index 9f01770d6609afdd21e4c1287f072024c47fc134..e6b26b1199fa9d997f16a5305871e5515caf7bc9 100644 (file)
 
 #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;
+}
index 31c2eecb7aeb994888283670e0938c1fcb8ad585..2a1a7cbc1e9981829c323e1a7208b201ae8182f2 100644 (file)
@@ -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
index 3a981a6427be01ebbe0aa525cbb8b65ebed91184..8a54a6678974a76b9b3991c3924793301dead028 100644 (file)
@@ -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;
index 33b6cc3c5d8d13d2e0576200973fb323e3836c87..5aa911713820cf347901715430e39b8e0cf01806 100644 (file)
@@ -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>
index 14d995fc39fad2507616c05d572ef8f435c1bcea..0e65d7842647d95c48cc1f5950ed550a4a368062 100644 (file)
@@ -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;
 
-       FILEf = 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;
+}
index 835082d86c4bf921aa773269922189bba5dada76..ed282af4a869d9b34913dfec4f6fa61c095d3eec 100644 (file)
 
 #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
index 8cdc9409ca213e73fd1c46bc164db7996330d83d..dea4c8f299ecc1d8661654b41153b67533a74fae 100644 (file)
 #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;
 }
index e146094a4d1751c260e356075fd36b322b1db849..53965749c74b054005e7cee0ff17676aeb8696ba 100644 (file)
 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 (file)
index 0000000..d4ce032
--- /dev/null
@@ -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 (file)
index 0000000..280d611
--- /dev/null
@@ -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
index b380f46b98f0df912ff7abb685d2d804a0094e1c..623e14f2b64a7c1bb68521464fc2f8e89dd8f8c5 100644 (file)
@@ -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>
index 54d45751e3c9e8f4322d257efaac952108dc3abb..f94a995393e844f5675ac1e67b160855281033fb 100644 (file)
@@ -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;
index 8c328e0e0fb5c44c41c784309e65f6750644e192..4a9b22f4b555d66e39057004fe6d3ebdb6188b93 100644 (file)
@@ -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);
                }
index 39a0f656f7e6479cbe4a292a3bd347d82fe4b24c..086eca1e804e805059660350a55809e6d0f7b625 100644 (file)
   <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"/>
   <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-A12.xml
deleted file mode 100644 (file)
index 9c04354..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-  <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"/>
-    <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"/>
-    <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
-    <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
-    <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
-    <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
-    <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
-    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
-    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
-    <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
-    <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
-    <event event="0x14" title="Cache" name="L1 inst access" description="Instruction cache access"/>
-    <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
-    <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
-    <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
-    <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
-    <event event="0x19" title="Bus" name="Access" description="Bus - Access"/>
-    <event event="0x1b" title="Instruction" name="Speculative" description="Instruction speculatively executed"/>
-    <event event="0x1c" title="Memory" name="Translation table" description="Write to translation table base architecturally executed"/>
-    <event event="0x1d" title="Bus" name="Cycle" description="Bus - Cycle"/>
-    <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
-    <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
-    <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
-    <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
-    <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-Back - Victim"/>
-    <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-Back - Cleaning and coherency"/>
-    <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/>
-    <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
-    <event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/>
-    <event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/>
-    <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/>
-    <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/>
-    <event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/>
-    <event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/>
-    <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/>
-    <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/>
-    <event event="0x6a" title="Memory" name="Unaligned" description="Unaligned access"/>
-    <event event="0x6c" title="Intrinsic" name="LDREX" description="Exclusive instruction speculatively executed - LDREX"/>
-    <event event="0x6e" title="Intrinsic" name="STREX fail" description="Exclusive instruction speculatively executed - STREX fail"/>
-    <event event="0x6f" title="Intrinsic" name="STREX" description="Exclusive instruction speculatively executed - STREX"/>
-    <event event="0x70" title="Instruction" name="Load" description="Instruction speculatively executed - Load"/>
-    <event event="0x71" title="Instruction" name="Store" description="Instruction speculatively executed - Store"/>
-    <event event="0x72" title="Instruction" name="Load/Store" description="Instruction speculatively executed - Load or store"/>
-    <event event="0x73" title="Instruction" name="Integer" description="Instruction speculatively executed - Integer data processing"/>
-    <event event="0x74" title="Instruction" name="Advanced SIMD" description="Instruction speculatively executed - Advanced SIMD"/>
-    <event event="0x75" title="Instruction" name="VFP" description="Instruction speculatively executed - VFP"/>
-    <event event="0x76" title="Instruction" name="Software change" description="Instruction speculatively executed - Software change of the PC"/>
-    <event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
-    <event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
-    <event event="0x7a" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
-    <event event="0x7c" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
-    <event event="0x7d" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
-    <event event="0x7e" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
-    <event event="0x81" title="Exception" name="Undefined" description="Exception taken, other synchronous"/>
-    <event event="0x8a" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/>
-    <event event="0xc0" title="Instruction" name="Stalled Linefill" description="Instruction side stalled due to a Linefill"/>
-    <event event="0xc1" title="Instruction" name="Stalled Page Table Walk" description="Instruction Side stalled due to a Page Table Walk"/>
-    <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="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"/>
-    <event event="0xda" title="Slots" name="Data Engine Issue Queue" description="Duration during which all slots in the Data Engine issue queue are busy"/>
-    <event event="0xdb" title="NEON" name="Flush" description="Number of NEON instruction which fail their condition code and lead to a flush of the DE pipe"/>
-    <event event="0xdc" title="Hypervisor" name="Traps" description="Number of Trap to hypervisor"/>
-    <event event="0xde" title="PTM" name="EXTOUT 0" description="PTM EXTOUT 0"/>
-    <event event="0xdf" title="PTM" name="EXTOUT 1" description="PTM EXTOUT 1"/>
-    <event event="0xe0" title="MMU" name="Table Walk" description="Duration during which the MMU handle a Page table walk"/>
-    <event event="0xe1" title="MMU" name="Stage1 Table Walk" description="Duration during which the MMU handle a Stage1 Page table walk"/>
-    <event event="0xe2" title="MMU" name="Stage2 Table Walk" description="Duration during which the MMU handle a Stage2 Page table walk"/>
-    <event event="0xe3" title="MMU" name="LSU Table Walk" description="Duration during which the MMU handle a Page table walk requested by the Load Store Unit"/>
-    <event event="0xe4" title="MMU" name="Instruction Table Walk" description="Duration during which the MMU handle a Page table walk requested by the Instruction side"/>
-    <event event="0xe5" title="MMU" name="Preload Table Walk" description="Duration during which the MMU handle a Page table walk requested by a Preload instruction or Prefetch request"/>
-    <event event="0xe6" title="MMU" name="cp15 Table Walk" description="Duration during which the MMU handle a Page table walk requested by a cp15 operation (maintenance by MVA and VA-to-PA operation)"/>
-    <event event="0xe7" title="Cache" name="L1 PLD TLB refill" description="Level 1 PLD TLB refill"/>
-    <event event="0xe8" title="Cache" name="L1 CP15 TLB refill" description="Level 1 CP15 TLB refill"/>
-    <event event="0xe9" title="Cache" name="L1 TLB flush" description="Level 1 TLB flush"/>
-    <event event="0xea" title="Cache" name="L2 TLB access" description="Level 2 TLB access"/>
-    <event event="0xeb" title="Cache" name="L2 TLB miss" description="Level 2 TLB miss"/>
-  </category>
diff --git a/tools/gator/daemon/events-Cortex-A17.xml b/tools/gator/daemon/events-Cortex-A17.xml
new file mode 100644 (file)
index 0000000..4dd08c1
--- /dev/null
@@ -0,0 +1,86 @@
+  <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"/>
+    <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
+    <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
+    <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
+    <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
+    <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
+    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
+    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
+    <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
+    <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
+    <event event="0x14" title="Cache" name="L1 inst access" description="Instruction cache access"/>
+    <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
+    <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
+    <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
+    <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
+    <event event="0x19" title="Bus" name="Access" description="Bus - Access"/>
+    <event event="0x1b" title="Instruction" name="Speculative" description="Instruction speculatively executed"/>
+    <event event="0x1c" title="Memory" name="Translation table" description="Write to translation table base architecturally executed"/>
+    <event event="0x1d" title="Bus" name="Cycle" description="Bus - Cycle"/>
+    <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
+    <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
+    <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
+    <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
+    <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-Back - Victim"/>
+    <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-Back - Cleaning and coherency"/>
+    <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/>
+    <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
+    <event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/>
+    <event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/>
+    <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/>
+    <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/>
+    <event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/>
+    <event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/>
+    <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/>
+    <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/>
+    <event event="0x6a" title="Memory" name="Unaligned" description="Unaligned access"/>
+    <event event="0x6c" title="Intrinsic" name="LDREX" description="Exclusive instruction speculatively executed - LDREX"/>
+    <event event="0x6e" title="Intrinsic" name="STREX fail" description="Exclusive instruction speculatively executed - STREX fail"/>
+    <event event="0x6f" title="Intrinsic" name="STREX" description="Exclusive instruction speculatively executed - STREX"/>
+    <event event="0x70" title="Instruction" name="Load" description="Instruction speculatively executed - Load"/>
+    <event event="0x71" title="Instruction" name="Store" description="Instruction speculatively executed - Store"/>
+    <event event="0x72" title="Instruction" name="Load/Store" description="Instruction speculatively executed - Load or store"/>
+    <event event="0x73" title="Instruction" name="Integer" description="Instruction speculatively executed - Integer data processing"/>
+    <event event="0x74" title="Instruction" name="Advanced SIMD" description="Instruction speculatively executed - Advanced SIMD"/>
+    <event event="0x75" title="Instruction" name="VFP" description="Instruction speculatively executed - VFP"/>
+    <event event="0x76" title="Instruction" name="Software change" description="Instruction speculatively executed - Software change of the PC"/>
+    <event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
+    <event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
+    <event event="0x7a" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
+    <event event="0x7c" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
+    <event event="0x7d" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
+    <event event="0x7e" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
+    <event event="0x81" title="Exception" name="Undefined" description="Exception taken, other synchronous"/>
+    <event event="0x8a" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/>
+    <event event="0xc0" title="Instruction" name="Stalled Linefill" description="Instruction side stalled due to a Linefill"/>
+    <event event="0xc1" title="Instruction" name="Stalled Page Table Walk" description="Instruction Side stalled due to a Page Table Walk"/>
+    <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-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"/>
+    <event event="0xda" title="Slots" name="Data Engine Issue Queue" description="Duration during which all slots in the Data Engine issue queue are busy"/>
+    <event event="0xdb" title="NEON" name="Flush" description="Number of NEON instruction which fail their condition code and lead to a flush of the DE pipe"/>
+    <event event="0xdc" title="Hypervisor" name="Traps" description="Number of Trap to hypervisor"/>
+    <event event="0xde" title="PTM" name="EXTOUT 0" description="PTM EXTOUT 0"/>
+    <event event="0xdf" title="PTM" name="EXTOUT 1" description="PTM EXTOUT 1"/>
+    <event event="0xe0" title="MMU" name="Table Walk" description="Duration during which the MMU handle a Page table walk"/>
+    <event event="0xe1" title="MMU" name="Stage1 Table Walk" description="Duration during which the MMU handle a Stage1 Page table walk"/>
+    <event event="0xe2" title="MMU" name="Stage2 Table Walk" description="Duration during which the MMU handle a Stage2 Page table walk"/>
+    <event event="0xe3" title="MMU" name="LSU Table Walk" description="Duration during which the MMU handle a Page table walk requested by the Load Store Unit"/>
+    <event event="0xe4" title="MMU" name="Instruction Table Walk" description="Duration during which the MMU handle a Page table walk requested by the Instruction side"/>
+    <event event="0xe5" title="MMU" name="Preload Table Walk" description="Duration during which the MMU handle a Page table walk requested by a Preload instruction or Prefetch request"/>
+    <event event="0xe6" title="MMU" name="cp15 Table Walk" description="Duration during which the MMU handle a Page table walk requested by a cp15 operation (maintenance by MVA and VA-to-PA operation)"/>
+    <event event="0xe7" title="Cache" name="L1 PLD TLB refill" description="Level 1 PLD TLB refill"/>
+    <event event="0xe8" title="Cache" name="L1 CP15 TLB refill" description="Level 1 CP15 TLB refill"/>
+    <event event="0xe9" title="Cache" name="L1 TLB flush" description="Level 1 TLB flush"/>
+    <event event="0xea" title="Cache" name="L2 TLB access" description="Level 2 TLB access"/>
+    <event event="0xeb" title="Cache" name="L2 TLB miss" description="Level 2 TLB miss"/>
+  </category>
index 5feeb9014a63d3c2bcf96ae471dd2b2982c3d887..9ef61ddac811a5054ef6aff4518efce418c89677 100644 (file)
@@ -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>
index c306dd62208ed93b23c0331eb3b97989055ded04..62a7018d038f733ee9e67a56828318ca10a59815 100644 (file)
@@ -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 (file)
index 0000000..b6ab4b8
--- /dev/null
@@ -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 (file)
index 0000000..4f3323f
--- /dev/null
@@ -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 (file)
index 0000000..50797e6
--- /dev/null
@@ -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 (file)
index 0000000..6ecc53c
--- /dev/null
@@ -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 (file)
index 5e89797..0000000
+++ /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 (file)
index df27962..0000000
+++ /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 (file)
index 0000000..5587534
--- /dev/null
@@ -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 (file)
index 0000000..be74c5a
--- /dev/null
@@ -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"/>
+
+    <event counter="ARM_Mali-T76x_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
+    <event counter="ARM_Mali-T76x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
+    <event counter="ARM_Mali-T76x_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-T76x_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-T76x_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-T76x_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-T76x_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-T76x_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-T76x_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-T76x_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-T76x_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-T76x_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-T76x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
+    <event counter="ARM_Mali-T76x_L2_EXT_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
+    <event counter="ARM_Mali-T76x_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
+    <event counter="ARM_Mali-T76x_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+    <event counter="ARM_Mali-T76x_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
+    <event counter="ARM_Mali-T76x_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+    <event counter="ARM_Mali-T76x_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-T76x_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-T76x_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-T76x_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-T76x_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-T76x_L2_READ_LOOKUP" title="Mali L2 Cache" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+    <event counter="ARM_Mali-T76x_L2_WRITE_LOOKUP" title="Mali L2 Cache" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+  </category>
index d2751e7239b50d703aa86cdd2f36f7f75c82680f..89bc7f4734dfe353002d1de6ae37ef0f48b776f5 100644 (file)
@@ -1,29 +1,30 @@
   <category name="Mali-V500">
-    <event counter="ARM_Mali-V500_cnt0" title="Mali Video Engine" name="Samples" class="absolute" description="The number of times we have taken a sample"/>
-    <event counter="ARM_Mali-V500_cnt1" title="Mali Video Engine" name="Queued input-buffers" class="absolute" description="The number of input-buffers that has been queued for consumption by the MVE"/>
-    <event counter="ARM_Mali-V500_cnt2" title="Mali Video Engine" name="Consumed input-buffers" class="absolute" description="The number of input-buffers that has been consumed by the MVE and returned to the application"/>
-    <event counter="ARM_Mali-V500_cnt3" title="Mali Video Engine" name="Queued output-buffers" class="absolute" description="The number of output-buffers that has been queued for usage by the MVE"/>
-    <event counter="ARM_Mali-V500_cnt4" title="Mali Video Engine" name="Consumed output-buffers" class="absolute" description="The number of output-buffers that has been consumed by the MVE and returned to the application"/>
-    <event counter="ARM_Mali-V500_cnt5" title="Mali Video Engine" name="Created Sessions" class="absolute" description="The number of created sessions throughout the lifetime of the process"/>
-    <event counter="ARM_Mali-V500_cnt6" title="Mali Video Engine" name="Active Sessions" description="The number of currently existing sessions"/>
-    <event counter="ARM_Mali-V500_cnt7" title="Mali Video Engine" name="Processed Frames" class="absolute" description="The number of processed frames. A processed frame is one where the encode or decode is complete for that particular frame. Frames can be processed out of order so this is not the same as the number of output-buffers returned"/>
-    <event counter="ARM_Mali-V500_cnt8" title="Mali Video Engine" name="Input Flushes Requested" class="absolute" description="The number of requested flushes of the input queue"/>
-    <event counter="ARM_Mali-V500_cnt9" title="Mali Video Engine" name="Input Flushes Complete" class="absolute" description="The number of completed flushes of the input queue"/>
-    <event counter="ARM_Mali-V500_cnt10" title="Mali Video Engine" name="Output Flushes Requested" class="absolute" description="The number of requested flushes of the output queue"/>
-    <event counter="ARM_Mali-V500_cnt11" title="Mali Video Engine" name="Output Flushes Complete" class="absolute" description="The number of completed flushes of the output queue"/>
-    <event counter="ARM_Mali-V500_cnt12" title="Mali Video Engine" name="Queued Output Buffers (current)" description="The number of output-buffers that are currently queued for usage by the MVE"/>
-    <event counter="ARM_Mali-V500_cnt13" title="Mali Video Engine" name="Queued Input Buffers (current)" description="The number of input-buffers that are currently queued for consumption by the MVE"/>
-    <event counter="ARM_Mali-V500_cnt14" title="Mali Video Engine" name="Output Queue Flushes" description="The number of pending flushes for the MVE output-queue"/>
-    <event counter="ARM_Mali-V500_cnt15" title="Mali Video Engine" name="Input Queue Flushes" description="The number of pending flushes for the MVE input-queue"/>
-    <event counter="ARM_Mali-V500_cnt16" title="Mali Video Engine" name="Errors encountered" class="absolute" description="The number of errors encountered"/>
-    <event counter="ARM_Mali-V500_cnt17" title="Mali Video Engine" name="Bits consumed" class="absolute" description="The number of bits consumed during decode"/>
-    <event counter="ARM_Mali-V500_cnt18" title="Mali Video Engine" name="AFBC bandwidth" class="absolute" description="The amount of AFBC-encoded bytes read or written"/>
-    <event counter="ARM_Mali-V500_cnt19" title="Mali Video Engine" name="Bandwidth (read)" class="absolute" description="The amount of bytes read over the AXI bus"/>
-    <event counter="ARM_Mali-V500_cnt20" title="Mali Video Engine" name="Bandwidth (write)" class="absolute" description="The amount of bytes written over the AXI bus"/>
-    <event counter="ARM_Mali-V500_evn0" title="Mali Video Engine" name="Session created" description="Generated when a session has been created"/>
-    <event counter="ARM_Mali-V500_evn1" title="Mali Video Engine" name="Session destroyed" description="Generated when a session has been destroyed"/>
-    <event counter="ARM_Mali-V500_evn2" title="Mali Video Engine" name="Frame Processed" description="Generated when the MVE has finished processing a frame"/>
-    <event counter="ARM_Mali-V500_evn3" title="Mali Video Engine" name="Output buffer received" description="Generated when an an output buffer is returned to us from the MVE"/>
-    <event counter="ARM_Mali-V500_evn4" title="Mali Video Engine" name="Input buffer received" description="Generated when we an input buffer is returned to us from the MVE"/>
-    <!--event counter="ARM_Mali-V500_act" title="VPU" name="Activity" class="activity" activity1="Parsed" activity_color1="0x000000ff" activity2="Piped" activity_color2="0x0000ff00" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" cores="8" description="Mali-V500 Activity"/-->
+    <event counter="ARM_Mali-V500_cnt0" title="MVE-V500 Stats" name="Samples" class="absolute" description="The number of times we have taken a sample"/>
+    <event counter="ARM_Mali-V500_cnt1" title="MVE-V500 Input Totals" name="Queued input-buffers" class="absolute" description="The number of input-buffers that has been queued for consumption by the MVE"/>
+    <event counter="ARM_Mali-V500_cnt2" title="MVE-V500 Input Totals" name="Consumed input-buffers" class="absolute" description="The number of input-buffers that has been consumed by the MVE and returned to the application"/>
+    <event counter="ARM_Mali-V500_cnt3" title="MVE-V500 Output Totals" name="Queued output-buffers" class="absolute" description="The number of output-buffers that has been queued for usage by the MVE"/>
+    <event counter="ARM_Mali-V500_cnt4" title="MVE-V500 Output Totals" name="Consumed output-buffers" class="absolute" description="The number of output-buffers that has been consumed by the MVE and returned to the application"/>
+    <event counter="ARM_Mali-V500_cnt5" title="MVE-V500 Stats" name="Created Sessions" class="absolute" description="The number of created sessions throughout the lifetime of the process"/>
+    <event counter="ARM_Mali-V500_cnt6" title="MVE-V500 Sessions" name="Active Sessions" description="The number of currently existing sessions"/>
+    <event counter="ARM_Mali-V500_cnt7" title="MVE-V500 Stats" name="Processed Frames" class="absolute" description="The number of processed frames. A processed frame is one where the encode or decode is complete for that particular frame. Frames can be processed out of order so this is not the same as the number of output-buffers returned"/>
+    <event counter="ARM_Mali-V500_cnt8" title="MVE-V500 Input Totals" name="Input Flushes Requested" class="absolute" description="The number of requested flushes of the input queue"/>
+    <event counter="ARM_Mali-V500_cnt9" title="MVE-V500 Input Totals" name="Input Flushes Complete" class="absolute" description="The number of completed flushes of the input queue"/>
+    <event counter="ARM_Mali-V500_cnt10" title="MVE-V500 Output Totals" name="Output Flushes Requested" class="absolute" description="The number of requested flushes of the output queue"/>
+    <event counter="ARM_Mali-V500_cnt11" title="MVE-V500 Output Totals" name="Output Flushes Complete" class="absolute" description="The number of completed flushes of the output queue"/>
+    <event counter="ARM_Mali-V500_cnt12" title="MVE-V500 Output" name="Queued Output Buffers (current)" description="The number of output-buffers that are currently queued for usage by the MVE"/>
+    <event counter="ARM_Mali-V500_cnt13" title="MVE-V500 Input" name="Queued Input Buffers (current)" description="The number of input-buffers that are currently queued for consumption by the MVE"/>
+    <event counter="ARM_Mali-V500_cnt14" title="MVE-V500 Output" name="Output Queue Flushes" description="The number of pending flushes for the MVE output-queue"/>
+    <event counter="ARM_Mali-V500_cnt15" title="MVE-V500 Input" name="Input Queue Flushes" description="The number of pending flushes for the MVE input-queue"/>
+    <event counter="ARM_Mali-V500_cnt16" title="MVE-V500 Stats" name="Errors encountered" class="absolute" description="The number of errors encountered"/>
+    <event counter="ARM_Mali-V500_cnt17" title="MVE-V500 Bandwidth" name="Bits consumed" class="absolute" description="The number of bits consumed during decode"/>
+    <event counter="ARM_Mali-V500_cnt18" title="MVE-V500 Bandwidth" name="AFBC bandwidth" class="absolute" description="The amount of AFBC-encoded bytes read or written"/>
+    <event counter="ARM_Mali-V500_cnt19" title="MVE-V500 Bandwidth" name="Bandwidth (read)" class="absolute" description="The amount of bytes read over the AXI bus"/>
+    <event counter="ARM_Mali-V500_cnt20" title="MVE-V500 Bandwidth" name="Bandwidth (write)" class="absolute" description="The amount of bytes written over the AXI bus"/>
+    <event counter="ARM_Mali-V500_evn0" title="MVE-V500 Sessions" name="Session created" description="Generated when a session has been created"/>
+    <event counter="ARM_Mali-V500_evn1" title="MVE-V500 Sessions" name="Session destroyed" description="Generated when a session has been destroyed"/>
+    <event counter="ARM_Mali-V500_evn2" title="MVE-V500 Frames" name="Frame Processed" description="Generated when the MVE has finished processing a frame"/>
+    <event counter="ARM_Mali-V500_evn3" title="MVE-V500 Output" name="Output buffer received" description="Generated when an an output buffer is returned to us from the MVE"/>
+    <event counter="ARM_Mali-V500_evn4" title="MVE-V500 Input" name="Input buffer received" description="Generated when we an input buffer is returned to us from the MVE"/>
+    <event counter="ARM_Mali-V500_act0" title="MVE-V500 Parsed" name="Activity" class="activity" activity1="activity" activity_color1="0x000000ff" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" cores="8" description="Mali-V500 Activity"/>
+    <event counter="ARM_Mali-V500_act1" title="MVE-V500 Piped" name="Activity" class="activity" activity1="activity" activity_color1="0x0000ff00" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" cores="8" description="Mali-V500 Activity"/>
   </category>
diff --git a/tools/gator/daemon/events-ftrace.xml b/tools/gator/daemon/events-ftrace.xml
new file mode 100644 (file)
index 0000000..33ab7aa
--- /dev/null
@@ -0,0 +1,7 @@
+  <category name="Ftrace">
+    <!-- counter attribute must start with ftrace_ and be unique -->
+    <!-- regex item in () is the value shown -->
+    <!--
+    <event counter="ftrace_trace_marker_numbers" title="ftrace" name="trace_marker" class="absolute" regex="([0-9]+)" description="Numbers written to /sys/kernel/debug/tracing/trace_marker, ex: echo 42 > /sys/kernel/debug/tracing/trace_marker"/>
+    -->
+  </category>
index 2998c701222132bf075ea6eb7d555afc07d2bdb9..fbce1e15d0d015da52111fb80245e88f84c4ab23 100644 (file)
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include "CCNDriver.h"
 #include "Child.h"
 #include "EventsXML.h"
-#include "KMod.h"
 #include "Logging.h"
 #include "Monitor.h"
 #include "OlySocket.h"
 #include "OlyUtility.h"
 #include "SessionData.h"
-
-#define DEBUG false
+#include "Setup.h"
 
 extern Child* child;
 static int shutdownFilesystem();
@@ -40,8 +39,9 @@ static bool driverRunningAtStart = false;
 static bool driverMountedAtStart = false;
 
 struct cmdline_t {
+       char *module;
        int port;
-       char* module;
+       bool update;
 };
 
 #define DEFAULT_PORT 8080
@@ -105,7 +105,6 @@ static void child_exit(int) {
        }
 }
 
-static const int UDP_ANS_PORT = 30000;
 static const int UDP_REQ_PORT = 30001;
 
 typedef struct {
@@ -125,11 +124,10 @@ static const char DST_REQ[] = { 'D', 'S', 'T', '_', 'R', 'E', 'Q', ' ', 0, 0, 0,
 
 class UdpListener {
 public:
-       UdpListener() : mDstAns(), mReq(-1), mAns(-1) {}
+       UdpListener() : mDstAns(), mReq(-1) {}
 
        void setup(int port) {
                mReq = udpPort(UDP_REQ_PORT);
-               mAns = udpPort(UDP_ANS_PORT);
 
                // Format the answer buffer
                memset(&mDstAns, 0, sizeof(mDstAns));
@@ -161,16 +159,13 @@ public:
                        logg->logError(__FILE__, __LINE__, "recvfrom failed");
                        handleException();
                } else if ((read == 12) && (memcmp(buf, DST_REQ, sizeof(DST_REQ)) == 0)) {
-                       if (sendto(mAns, &mDstAns, sizeof(mDstAns), 0, (struct sockaddr *)&sockaddr, addrlen) != sizeof(mDstAns)) {
-                               logg->logError(__FILE__, __LINE__, "sendto failed");
-                               handleException();
-                       }
+                       // Don't care if sendto fails - gatord shouldn't exit because of it and Streamline will retry
+                       sendto(mReq, &mDstAns, sizeof(mDstAns), 0, (struct sockaddr *)&sockaddr, addrlen);
                }
        }
 
        void close() {
                ::close(mReq);
-               ::close(mAns);
        }
 
 private:
@@ -180,10 +175,10 @@ private:
                int on;
                int family = AF_INET6;
 
-               s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+               s = socket_cloexec(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
                if (s == -1) {
                        family = AF_INET;
-                       s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+                       s = socket_cloexec(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
                        if (s == -1) {
                                logg->logError(__FILE__, __LINE__, "socket failed");
                                handleException();
@@ -210,7 +205,6 @@ private:
 
        RVIConfigureInfo mDstAns;
        int mReq;
-       int mAns;
 };
 
 static UdpListener udpListener;
@@ -233,7 +227,7 @@ static int mountGatorFS() {
 
 static bool init_module (const char * const location) {
        bool ret(false);
-       const int fd = open(location, O_RDONLY);
+       const int fd = open(location, O_RDONLY | O_CLOEXEC);
        if (fd >= 0) {
                struct stat st;
                if (fstat(fd, &st) == 0) {
@@ -332,10 +326,26 @@ static int shutdownFilesystem() {
        return 0; // success
 }
 
+static const char OPTSTRING[] = "hvudap:s:c:e:m:o:";
+
+static bool hasDebugFlag(int argc, char** argv) {
+       int c;
+
+       optind = 1;
+       while ((c = getopt(argc, argv, OPTSTRING)) != -1) {
+               if (c == 'd') {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 static struct cmdline_t parseCommandLine(int argc, char** argv) {
        struct cmdline_t cmdline;
        cmdline.port = DEFAULT_PORT;
        cmdline.module = NULL;
+       cmdline.update = false;
        char version_string[256]; // arbitrary length to hold the version information
        int c;
 
@@ -346,11 +356,15 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
                snprintf(version_string, sizeof(version_string), "Streamline gatord development version %d", PROTOCOL_VERSION);
        }
 
-       while ((c = getopt(argc, argv, "hvp:s:c:e:m:o:")) != -1) {
-               switch(c) {
+       optind = 1;
+       while ((c = getopt(argc, argv, OPTSTRING)) != -1) {
+               switch (c) {
                        case 'c':
                                gSessionData->mConfigurationXMLPath = optarg;
                                break;
+                       case 'd':
+                               // Already handled
+                               break;
                        case 'e':
                                gSessionData->mEventsXMLPath = optarg;
                                break;
@@ -366,6 +380,12 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
                        case 'o':
                                gSessionData->mTargetPath = optarg;
                                break;
+                       case 'u':
+                               cmdline.update = true;
+                               break;
+                       case 'a':
+                               gSessionData->mAllowCommands = true;
+                               break;
                        case 'h':
                        case '?':
                                logg->logError(__FILE__, __LINE__,
@@ -375,9 +395,11 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
                                        "-h              this help page\n"
                                        "-m module       path and filename of gator.ko\n"
                                        "-p port_number  port upon which the server listens; default is 8080\n"
-                                       "-s session_xml  path and filename of a session xml used for local capture\n"
+                                       "-s session_xml  path and filename of a session.xml used for local capture\n"
                                        "-o apc_dir      path and name of the output for a local capture\n"
                                        "-v              version information\n"
+                                       "-d              enable debug messages\n"
+                                       "-a              allow the user user to provide a command to run at the start of a capture"
                                        , version_string);
                                handleException();
                                break;
@@ -407,7 +429,7 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
        return cmdline;
 }
 
-void handleClient() {
+static void handleClient() {
        OlySocket client(sock->acceptConnection());
 
        int pid = fork();
@@ -452,12 +474,15 @@ int main(int argc, char** argv) {
        //   e.g. it may not be the group leader when launched as 'sudo gatord'
        setsid();
 
-       logg = new Logging(DEBUG);  // Set up global thread-safe logging
-       gSessionData = new SessionData(); // Global data class
-       util = new OlyUtility();        // Set up global utility class
+  // Set up global thread-safe logging
+       logg = new Logging(hasDebugFlag(argc, argv));
+       // Global data class
+       gSessionData = new SessionData();
+       // Set up global utility class
+       util = new OlyUtility();
 
        // Initialize drivers
-       new KMod();
+       new CCNDriver();
 
        prctl(PR_SET_NAME, (unsigned long)&"gatord-main", 0, 0, 0);
        pthread_mutex_init(&numSessions_mutex, NULL);
@@ -474,6 +499,10 @@ int main(int argc, char** argv) {
        // Parse the command line parameters
        struct cmdline_t cmdline = parseCommandLine(argc, argv);
 
+       if (cmdline.update) {
+               return update(argv[0]);
+       }
+
        // Verify root permissions
        uid_t euid = geteuid();
        if (euid) {
@@ -490,17 +519,18 @@ int main(int argc, char** argv) {
                                       "  >>> gator.ko should be co-located with gatord in the same directory\n"
                                       "  >>> OR insmod gator.ko prior to launching gatord\n"
                                       "  >>> OR specify the location of gator.ko on the command line\n"
-                                      "  >>> OR run Linux 3.4 or later with perf (CONFIG_PERF_EVENTS and CONFIG_HW_PERF_EVENTS) and tracing (CONFIG_TRACING) support to collect data via userspace only");
+                                      "  >>> OR run Linux 3.4 or later with perf (CONFIG_PERF_EVENTS and CONFIG_HW_PERF_EVENTS) and tracing (CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER) support to collect data via userspace only");
                        handleException();
                }
        }
 
-       gSessionData->hwmon.setup();
        {
                EventsXML eventsXML;
                mxml_node_t *xml = eventsXML.getTree();
-               gSessionData->fsDriver.setup(xml);
-               gSessionData->maliVideo.setup(xml);
+               // Initialize all drivers
+               for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) {
+                       driver->readEvents(xml);
+               }
                mxmlDelete(xml);
        }
 
@@ -517,9 +547,14 @@ int main(int argc, char** argv) {
                child->run();
                delete child;
        } else {
+               gSessionData->annotateListener.setup();
                sock = new OlyServerSocket(cmdline.port);
                udpListener.setup(cmdline.port);
-               if (!monitor.init() || !monitor.add(sock->getFd()) || !monitor.add(udpListener.getReq())) {
+               if (!monitor.init() ||
+                               !monitor.add(sock->getFd()) ||
+                               !monitor.add(udpListener.getReq()) ||
+                               !monitor.add(gSessionData->annotateListener.getFd()) ||
+                               false) {
                        logg->logError(__FILE__, __LINE__, "Monitor setup failed");
                        handleException();
                }
@@ -537,6 +572,8 @@ int main(int argc, char** argv) {
                                        handleClient();
                                } else if (events[i].data.fd == udpListener.getReq()) {
                                        udpListener.handle();
+                               } else if (events[i].data.fd == gSessionData->annotateListener.getFd()) {
+                                       gSessionData->annotateListener.handle();
                                }
                        }
                }
index 1f59ba34a474dcfb566c4b1cd5001f9cb9ab6e4f..ad6df1d7debec4eccef162f6c9dbcbfd8a655725 100644 (file)
@@ -1,10 +1,10 @@
 /* config.h.  Generated from config.h.in by configure.  */
 /*
- * "$Id: config.h.in 408 2010-09-19 05:26:46Z mike $"
+ * "$Id: config.h.in 451 2014-01-04 21:50:06Z msweet $"
  *
  * Configuration file for Mini-XML, a small XML-like file parsing library.
  *
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Michael R Sweet and are protected by Federal copyright
@@ -12,7 +12,7 @@
  * which should have been included with this file.  If this file is
  * missing or damaged, see the license at:
  *
- *     http://www.minixml.org/
+ *     http://www.msweet.org/projects.php/Mini-XML
  */
 
 /*
@@ -30,7 +30,7 @@
  * Version number...
  */
 
-#define MXML_VERSION "Mini-XML v2.7"
+#define MXML_VERSION "Mini-XML v2.8"
 
 
 /*
@@ -92,5 +92,5 @@ extern int    _mxml_vsnprintf(char *, size_t, const char *, va_list);
 #  endif /* !HAVE_VSNPRINTF */
 
 /*
- * End of "$Id: config.h.in 408 2010-09-19 05:26:46Z mike $".
+ * End of "$Id: config.h.in 451 2014-01-04 21:50:06Z msweet $".
  */
index c9950f5fb73279c0f162b73fbff8937538ec9870..8e89cc1474f8819e27100bafa83d6ad57926236a 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $"
+ * "$Id: mxml-attr.c 451 2014-01-04 21:50:06Z msweet $"
  *
  * Attribute support code for Mini-XML, a small XML-like file parsing library.
  *
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Michael R Sweet and are protected by Federal copyright
  * which should have been included with this file.  If this file is
  * missing or damaged, see the license at:
  *
- *     http://www.minixml.org/
- *
- * Contents:
- *
- *   mxmlElementDeleteAttr() - Delete an attribute.
- *   mxmlElementGetAttr()    - Get an attribute.
- *   mxmlElementSetAttr()    - Set an attribute.
- *   mxmlElementSetAttrf()   - Set an attribute with a formatted value.
- *   mxml_set_attr()         - Set or add an attribute name/value pair.
+ *     http://www.msweet.org/projects.php/Mini-XML
  */
 
 /*
@@ -90,6 +82,9 @@ mxmlElementDeleteAttr(mxml_node_t *node,/* I - Element */
         memmove(attr, attr + 1, i * sizeof(mxml_attr_t));
 
       node->value.element.num_attrs --;
+
+      if (node->value.element.num_attrs == 0)
+        free(node->value.element.attrs);
       return;
     }
   }
@@ -315,5 +310,5 @@ mxml_set_attr(mxml_node_t *node,    /* I - Element node */
 
 
 /*
- * End of "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $".
+ * End of "$Id: mxml-attr.c 451 2014-01-04 21:50:06Z msweet $".
  */
index c5c9f61f73c24e9fe7d82c5befcaefc4900e7b71..0d11df6a70bc12d74219516bd2fb26e83b93cf5f 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * "$Id: mxml-entity.c 408 2010-09-19 05:26:46Z mike $"
+ * "$Id: mxml-entity.c 451 2014-01-04 21:50:06Z msweet $"
  *
  * Character entity support code for Mini-XML, a small XML-like
  * file parsing library.
  *
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Michael R Sweet and are protected by Federal copyright
  * which should have been included with this file.  If this file is
  * missing or damaged, see the license at:
  *
- *     http://www.minixml.org/
- *
- * Contents:
- *
- *   mxmlEntityAddCallback()    - Add a callback to convert entities to
- *                                Unicode.
- *   mxmlEntityGetName()        - Get the name that corresponds to the
- *                                character value.
- *   mxmlEntityGetValue()       - Get the character corresponding to a named
- *                                entity.
- *   mxmlEntityRemoveCallback() - Remove a callback.
- *   _mxml_entity_cb()          - Lookup standard (X)HTML entities.
+ *     http://www.msweet.org/projects.php/Mini-XML
  */
 
 /*
@@ -456,5 +445,5 @@ _mxml_entity_cb(const char *name)   /* I - Entity name */
 
 
 /*
- * End of "$Id: mxml-entity.c 408 2010-09-19 05:26:46Z mike $".
+ * End of "$Id: mxml-entity.c 451 2014-01-04 21:50:06Z msweet $".
  */
index 7860ee5f8370664eddc7b9211bec69bb359aaee0..3812c253fc3e3788b72fbf75a0e2e29f4c0f78cd 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$Id: mxml-file.c 438 2011-03-24 05:47:51Z mike $"
+ * "$Id: mxml-file.c 455 2014-01-05 03:28:03Z msweet $"
  *
  * File loading code for Mini-XML, a small XML-like file parsing library.
  *
- * Copyright 2003-2011 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Michael R Sweet and are protected by Federal copyright
  * which should have been included with this file.  If this file is
  * missing or damaged, see the license at:
  *
- *     http://www.minixml.org/
- *
- * Contents:
- *
- *   mxmlLoadFd()            - Load a file descriptor into an XML node tree.
- *   mxmlLoadFile()          - Load a file into an XML node tree.
- *   mxmlLoadString()        - Load a string into an XML node tree.
- *   mxmlSaveAllocString()   - Save an XML tree to an allocated string.
- *   mxmlSaveFd()            - Save an XML tree to a file descriptor.
- *   mxmlSaveFile()          - Save an XML tree to a file.
- *   mxmlSaveString()        - Save an XML node tree to a string.
- *   mxmlSAXLoadFd()         - Load a file descriptor into an XML node tree
- *                             using a SAX callback.
- *   mxmlSAXLoadFile()       - Load a file into an XML node tree
- *                             using a SAX callback.
- *   mxmlSAXLoadString()     - Load a string into an XML node tree
- *                             using a SAX callback.
- *   mxmlSetCustomHandlers() - Set the handling functions for custom data.
- *   mxmlSetErrorCallback()  - Set the error message callback.
- *   mxmlSetWrapMargin()     - Set the wrap margin when saving XML data.
- *   mxml_add_char()         - Add a character to a buffer, expanding as needed.
- *   mxml_fd_getc()          - Read a character from a file descriptor.
- *   mxml_fd_putc()          - Write a character to a file descriptor.
- *   mxml_fd_read()          - Read a buffer of data from a file descriptor.
- *   mxml_fd_write()         - Write a buffer of data to a file descriptor.
- *   mxml_file_getc()        - Get a character from a file.
- *   mxml_file_putc()        - Write a character to a file.
- *   mxml_get_entity()       - Get the character corresponding to an entity...
- *   mxml_load_data()        - Load data into an XML node tree.
- *   mxml_parse_element()    - Parse an element for any attributes...
- *   mxml_string_getc()      - Get a character from a string.
- *   mxml_string_putc()      - Write a character to a string.
- *   mxml_write_name()       - Write a name string.
- *   mxml_write_node()       - Save an XML node to a file.
- *   mxml_write_string()     - Write a string, escaping & and < as needed.
- *   mxml_write_ws()         - Do whitespace callback...
+ *     http://www.msweet.org/projects.php/Mini-XML
  */
 
+/*** This file modified by ARM on 25 Aug 2014 to avoid pointer overflow when checking if the write position is beyond the end of the buffer in mxmlSaveString and mxml_string_putc ***/
+
 /*
  * Include necessary headers...
  */
@@ -128,7 +95,7 @@ static int           mxml_write_node(mxml_node_t *node, void *p,
                                        _mxml_global_t *global);
 static int             mxml_write_string(const char *s, void *p,
                                          _mxml_putc_cb_t putc_cb);
-static int             mxml_write_ws(mxml_node_t *node, void *p, 
+static int             mxml_write_ws(mxml_node_t *node, void *p,
                                      mxml_save_cb_t cb, int ws,
                                      int col, _mxml_putc_cb_t putc_cb);
 
@@ -400,7 +367,7 @@ mxmlSaveString(mxml_node_t    *node,        /* I - Node to write */
                mxml_save_cb_t cb)      /* I - Whitespace callback or MXML_NO_CALLBACK */
 {
   int  col;                            /* Final column */
-  char *ptr[2];                        /* Pointers for putc_cb */
+  char *ptr[3];                        /* Pointers for putc_cb */
   _mxml_global_t *global = _mxml_global();
                                        /* Global data */
 
@@ -411,6 +378,7 @@ mxmlSaveString(mxml_node_t    *node,        /* I - Node to write */
 
   ptr[0] = buffer;
   ptr[1] = buffer + bufsize;
+  ptr[2] = 0;
 
   if ((col = mxml_write_node(node, ptr, cb, 0, mxml_string_putc, global)) < 0)
     return (-1);
@@ -422,7 +390,7 @@ mxmlSaveString(mxml_node_t    *node,        /* I - Node to write */
   * Nul-terminate the buffer...
   */
 
-  if (ptr[0] >= ptr[1])
+  if (ptr[2] != 0)
     buffer[bufsize - 1] = '\0';
   else
     ptr[0][0] = '\0';
@@ -567,7 +535,7 @@ mxmlSAXLoadString(
  *
  * The save function accepts a node pointer and must return a malloc'd
  * string on success and NULL on error.
- * 
+ *
  */
 
 void
@@ -756,7 +724,7 @@ mxml_fd_getc(void *p,                       /* I  - File descriptor buffer */
              return (EOF);
 
          ch = *(buf->current)++;
-          
+
          if (ch != 0xff)
            return (EOF);
 
@@ -775,7 +743,7 @@ mxml_fd_getc(void *p,                       /* I  - File descriptor buffer */
              return (EOF);
 
          ch = *(buf->current)++;
-          
+
          if (ch != 0xfe)
            return (EOF);
 
@@ -1287,8 +1255,8 @@ mxml_file_getc(void *p,                   /* I  - Pointer to file */
          * Multi-word UTF-16 char...
          */
 
-          int lch = (getc(fp) << 8);
-          lch |= getc(fp);
+          int lch = getc(fp);
+          lch = (lch << 8) | getc(fp);
 
           if (lch < 0xdc00 || lch >= 0xdfff)
            return (EOF);
@@ -1317,7 +1285,7 @@ mxml_file_getc(void *p,                   /* I  - Pointer to file */
          */
 
           int lch = getc(fp);
-                 lch |= (getc(fp) << 8);
+          lch |= (getc(fp) << 8);
 
           if (lch < 0xdc00 || lch >= 0xdfff)
            return (EOF);
@@ -1463,8 +1431,10 @@ mxml_load_data(
 
   if (cb && parent)
     type = (*cb)(parent);
-  else
+  else if (parent)
     type = MXML_TEXT;
+  else
+    type = MXML_IGNORE;
 
   while ((ch = (*getc_cb)(p, &encoding)) != EOF)
   {
@@ -1518,7 +1488,7 @@ mxml_load_data(
         default : /* Ignore... */
            node = NULL;
            break;
-      }          
+      }
 
       if (*bufptr)
       {
@@ -1661,9 +1631,9 @@ mxml_load_data(
          * There can only be one root element!
          */
 
-         mxml_error("<%s> cannot be a second root node after <%s>", 
+         mxml_error("<%s> cannot be a second root node after <%s>",
                     buffer, first->value.element.name);
-          goto error;               
+          goto error;
        }
 
        if ((node = mxmlNewElement(parent, buffer)) == NULL)
@@ -1729,9 +1699,9 @@ mxml_load_data(
          * There can only be one root element!
          */
 
-         mxml_error("<%s> cannot be a second root node after <%s>", 
+         mxml_error("<%s> cannot be a second root node after <%s>",
                     buffer, first->value.element.name);
-          goto error;               
+          goto error;
        }
 
        if ((node = mxmlNewElement(parent, buffer)) == NULL)
@@ -1796,9 +1766,9 @@ mxml_load_data(
          * There can only be one root element!
          */
 
-         mxml_error("<%s> cannot be a second root node after <%s>", 
+         mxml_error("<%s> cannot be a second root node after <%s>",
                     buffer, first->value.element.name);
-          goto error;               
+          goto error;
        }
 
        if ((node = mxmlNewElement(parent, buffer)) == NULL)
@@ -1882,9 +1852,9 @@ mxml_load_data(
          * There can only be one root element!
          */
 
-         mxml_error("<%s> cannot be a second root node after <%s>", 
+         mxml_error("<%s> cannot be a second root node after <%s>",
                     buffer, first->value.element.name);
-          goto error;               
+          goto error;
        }
 
        if ((node = mxmlNewElement(parent, buffer)) == NULL)
@@ -1974,9 +1944,9 @@ mxml_load_data(
          * There can only be one root element!
          */
 
-         mxml_error("<%s> cannot be a second root node after <%s>", 
+         mxml_error("<%s> cannot be a second root node after <%s>",
                     buffer, first->value.element.name);
-          goto error;               
+          goto error;
        }
 
         if ((node = mxmlNewElement(parent, buffer)) == NULL)
@@ -2076,7 +2046,7 @@ mxml_load_data(
   {
     node = parent;
 
-    while (parent->parent != top && parent->parent)
+    while (parent != top && parent->parent)
       parent = parent->parent;
 
     if (node != parent)
@@ -2286,7 +2256,7 @@ mxml_parse_element(
            if (ch == '&')
              if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
                goto error;
-             
+
            if (mxml_add_char(ch, &ptr, &value, &valsize))
              goto error;
          }
@@ -2310,7 +2280,7 @@ mxml_parse_element(
            if (ch == '&')
              if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
                goto error;
-             
+
            if (mxml_add_char(ch, &ptr, &value, &valsize))
              goto error;
          }
@@ -2643,8 +2613,12 @@ mxml_string_putc(int  ch,                /* I - Character to write */
 
   pp = (char **)p;
 
-  if (pp[0] < pp[1])
-    pp[0][0] = ch;
+  if (pp[2] == 0) {
+    if (pp[0] < pp[1])
+      pp[0][0] = ch;
+    else
+      pp[2] = (char *)1;
+  }
 
   pp[0] ++;
 
@@ -3078,5 +3052,5 @@ mxml_write_ws(mxml_node_t     *node,      /* I - Current node */
 
 
 /*
- * End of "$Id: mxml-file.c 438 2011-03-24 05:47:51Z mike $".
+ * End of "$Id: mxml-file.c 455 2014-01-05 03:28:03Z msweet $".
  */
index a5356d57e186bb127ac0c6914a77bb926948f552..40ed3d0839b4151c8b1a8f2a3b4d1c565304435e 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$Id: mxml-get.c 427 2011-01-03 02:03:29Z mike $"
+ * "$Id: mxml-get.c 451 2014-01-04 21:50:06Z msweet $"
  *
  * Node get functions for Mini-XML, a small XML-like file parsing library.
  *
- * Copyright 2011 by Michael R Sweet.
+ * Copyright 2014 by Michael R Sweet.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Michael R Sweet and are protected by Federal copyright
  * which should have been included with this file.  If this file is
  * missing or damaged, see the license at:
  *
- *     http://www.minixml.org/
- *
- * Contents:
- *
- *   mxmlGetCDATA()       - Get the value for a CDATA node.
- *   mxmlGetCustom()      - Get the value for a custom node.
- *   mxmlGetElement()     - Get the name for an element node.
- *   mxmlGetFirstChild()  - Get the first child of an element node.
- *   mxmlGetInteger()     - Get the integer value from the specified node or its
- *                          first child.
- *   mxmlGetLastChild()   - Get the last child of an element node.
- *   mxmlGetNextSibling() - Get the next node for the current parent.
- *   mxmlGetOpaque()      - Get an opaque string value for a node or its first
- *                          child.
- *   mxmlGetParent()      - Get the parent node.
- *   mxmlGetPrevSibling() - Get the previous node for the current parent.
- *   mxmlGetReal()        - Get the real value for a node or its first child.
- *   mxmlGetText()        - Get the text value for a node or its first child.
- *   mxmlGetType()        - Get the node type.
- *   mxmlGetUserData()    - Get the user data pointer for a node.
+ *     http://www.msweet.org/projects.php/Mini-XML
  */
 
 /*
@@ -467,5 +448,5 @@ mxmlGetUserData(mxml_node_t *node)  /* I - Node to get */
 
 
 /*
- * End of "$Id: mxml-get.c 427 2011-01-03 02:03:29Z mike $".
+ * End of "$Id: mxml-get.c 451 2014-01-04 21:50:06Z msweet $".
  */
index b6efc66f055cee93136d51fd2f39e49b0ba69496..10814390d3a067a0c8a46247b4bbd747ac39c86e 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$Id: mxml-index.c 426 2011-01-01 23:42:17Z mike $"
+ * "$Id: mxml-index.c 451 2014-01-04 21:50:06Z msweet $"
  *
  * Index support code for Mini-XML, a small XML-like file parsing library.
  *
- * Copyright 2003-2011 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Michael R Sweet and are protected by Federal copyright
  * which should have been included with this file.  If this file is
  * missing or damaged, see the license at:
  *
- *     http://www.minixml.org/
- *
- * Contents:
- *
+ *     http://www.msweet.org/projects.php/Mini-XML
  */
 
 /*
@@ -658,5 +655,5 @@ index_sort(mxml_index_t *ind,               /* I - Index to sort */
 
 
 /*
- * End of "$Id: mxml-index.c 426 2011-01-01 23:42:17Z mike $".
+ * End of "$Id: mxml-index.c 451 2014-01-04 21:50:06Z msweet $".
  */
index 44af759f9de3298d97697ebbbf331e9dd5a03d48..128cda1a4cf2f87f22bb7eda0a0a01a956871249 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$Id: mxml-node.c 436 2011-01-22 01:02:05Z mike $"
+ * "$Id: mxml-node.c 451 2014-01-04 21:50:06Z msweet $"
  *
  * Node support code for Mini-XML, a small XML-like file parsing library.
  *
- * Copyright 2003-2011 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Michael R Sweet and are protected by Federal copyright
  * which should have been included with this file.  If this file is
  * missing or damaged, see the license at:
  *
- *     http://www.minixml.org/
- *
- * Contents:
- *
- *   mxmlAdd()         - Add a node to a tree.
- *   mxmlDelete()      - Delete a node and all of its children.
- *   mxmlGetRefCount() - Get the current reference (use) count for a node.
- *   mxmlNewCDATA()    - Create a new CDATA node.
- *   mxmlNewCustom()   - Create a new custom data node.
- *   mxmlNewElement()  - Create a new element node.
- *   mxmlNewInteger()  - Create a new integer node.
- *   mxmlNewOpaque()   - Create a new opaque string.
- *   mxmlNewReal()     - Create a new real number node.
- *   mxmlNewText()     - Create a new text fragment node.
- *   mxmlNewTextf()    - Create a new formatted text fragment node.
- *   mxmlRemove()      - Remove a node from its parent.
- *   mxmlNewXML()      - Create a new XML document tree.
- *   mxmlRelease()     - Release a node.
- *   mxmlRetain()      - Retain a node.
- *   mxml_new()        - Create a new node.
+ *     http://www.msweet.org/projects.php/Mini-XML
  */
 
 /*
@@ -529,7 +510,7 @@ mxmlNewReal(mxml_node_t *parent,    /* I - Parent node or MXML_NO_PARENT */
  * list. The constant MXML_NO_PARENT can be used to specify that the new
  * text node has no parent. The whitespace parameter is used to specify
  * whether leading whitespace is present before the node. The text
- * string must be nul-terminated and is copied into the new node.  
+ * string must be nul-terminated and is copied into the new node.
  */
 
 mxml_node_t *                          /* O - New node */
@@ -573,7 +554,7 @@ mxmlNewText(mxml_node_t *parent,    /* I - Parent node or MXML_NO_PARENT */
  * list. The constant MXML_NO_PARENT can be used to specify that the new
  * text node has no parent. The whitespace parameter is used to specify
  * whether leading whitespace is present before the node. The format
- * string must be nul-terminated and is formatted into the new node.  
+ * string must be nul-terminated and is formatted into the new node.
  */
 
 mxml_node_t *                          /* O - New node */
@@ -803,5 +784,5 @@ mxml_new(mxml_node_t *parent,               /* I - Parent node */
 
 
 /*
- * End of "$Id: mxml-node.c 436 2011-01-22 01:02:05Z mike $".
+ * End of "$Id: mxml-node.c 451 2014-01-04 21:50:06Z msweet $".
  */
index 72f3e2320c7ca233dc4beae9ab430bbf72fc728b..bec4bbfbf37868f5bcc7c6fd307c30ff81b8c032 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$Id: mxml-private.c 422 2010-11-07 22:55:11Z mike $"
+ * "$Id: mxml-private.c 451 2014-01-04 21:50:06Z msweet $"
  *
  * Private functions for Mini-XML, a small XML-like file parsing library.
  *
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Michael R Sweet and are protected by Federal copyright
  * which should have been included with this file.  If this file is
  * missing or damaged, see the license at:
  *
- *     http://www.minixml.org/
- *
- * Contents:
- *
- *   mxml_error()      - Display an error message.
- *   mxml_integer_cb() - Default callback for integer values.
- *   mxml_opaque_cb()  - Default callback for opaque values.
- *   mxml_real_cb()    - Default callback for real number values.
- *   _mxml_global()    - Get global data.
+ *     http://www.msweet.org/projects.php/Mini-XML
  */
 
 /*
@@ -238,7 +230,7 @@ static DWORD _mxml_tls_index;               /* Index for global storage */
 /*
  * 'DllMain()' - Main entry for library.
  */
+
 BOOL WINAPI                            /* O - Success/failure */
 DllMain(HINSTANCE hinst,               /* I - DLL module handle */
         DWORD     reason,              /* I - Reason */
@@ -250,28 +242,28 @@ DllMain(HINSTANCE hinst,          /* I - DLL module handle */
   (void)hinst;
   (void)reserved;
 
-  switch (reason) 
-  { 
+  switch (reason)
+  {
     case DLL_PROCESS_ATTACH :          /* Called on library initialization */
-        if ((_mxml_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) 
-          return (FALSE); 
-        break; 
+        if ((_mxml_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+          return (FALSE);
+        break;
 
     case DLL_THREAD_DETACH :           /* Called when a thread terminates */
         if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
           free(global);
-        break; 
+        break;
 
     case DLL_PROCESS_DETACH :          /* Called when library is unloaded */
         if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
           free(global);
 
-        TlsFree(_mxml_tls_index); 
-        break; 
+        TlsFree(_mxml_tls_index);
+        break;
 
-    default: 
-        break; 
-  } 
+    default:
+        break;
+  }
 
   return (TRUE);
 }
@@ -295,7 +287,7 @@ _mxml_global(void)
     global->entity_cbs[0]  = _mxml_entity_cb;
     global->wrap           = 72;
 
-    TlsSetValue(_mxml_tls_index, (LPVOID)global); 
+    TlsSetValue(_mxml_tls_index, (LPVOID)global);
   }
 
   return (global);
@@ -327,5 +319,5 @@ _mxml_global(void)
 
 
 /*
- * End of "$Id: mxml-private.c 422 2010-11-07 22:55:11Z mike $".
+ * End of "$Id: mxml-private.c 451 2014-01-04 21:50:06Z msweet $".
  */
index 8789e6c52cbd74c4443f341a4cd9c395a9df0cf5..c5e4e6b6f27a24aa294d023ca68113a69b17bd15 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$Id: mxml-private.h 408 2010-09-19 05:26:46Z mike $"
+ * "$Id: mxml-private.h 451 2014-01-04 21:50:06Z msweet $"
  *
  * Private definitions for Mini-XML, a small XML-like file parsing library.
  *
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Michael R Sweet and are protected by Federal copyright
@@ -11,7 +11,7 @@
  * which should have been included with this file.  If this file is
  * missing or damaged, see the license at:
  *
- *     http://www.minixml.org/
+ *     http://www.msweet.org/projects.php/Mini-XML
  */
 
 /*
@@ -46,5 +46,5 @@ extern int            _mxml_entity_cb(const char *name);
 
 
 /*
- * End of "$Id: mxml-private.h 408 2010-09-19 05:26:46Z mike $".
+ * End of "$Id: mxml-private.h 451 2014-01-04 21:50:06Z msweet $".
  */
index f975af1543ca869b309eb9a6df7fc63b6b0f9266..313a52f0ce2f8cb4219e220b61c1d9f04050435c 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * "$Id: mxml-search.c 427 2011-01-03 02:03:29Z mike $"
+ * "$Id: mxml-search.c 451 2014-01-04 21:50:06Z msweet $"
  *
  * Search/navigation functions for Mini-XML, a small XML-like file
  * parsing library.
  *
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Michael R Sweet and are protected by Federal copyright
  * which should have been included with this file.  If this file is
  * missing or damaged, see the license at:
  *
- *     http://www.minixml.org/
- *
- * Contents:
- *
- *   mxmlFindElement() - Find the named element.
- *   mxmlFindValue()   - Find a value with the given path.
- *   mxmlWalkNext()    - Walk to the next logical node in the tree.
- *   mxmlWalkPrev()    - Walk to the previous logical node in the tree.
+ *     http://www.msweet.org/projects.php/Mini-XML
  */
 
 /*
@@ -126,7 +119,7 @@ mxmlFindElement(mxml_node_t *node,  /* I - Current node */
  *
  * The first child node of the found node is returned if the given node has
  * children and the first child is a value node.
- * 
+ *
  * @since Mini-XML 2.7@
  */
 
@@ -283,5 +276,5 @@ mxmlWalkPrev(mxml_node_t *node,             /* I - Current node */
 
 
 /*
- * End of "$Id: mxml-search.c 427 2011-01-03 02:03:29Z mike $".
+ * End of "$Id: mxml-search.c 451 2014-01-04 21:50:06Z msweet $".
  */
index b0bd52790b2eeecf83ddef48acd8a65322032e0c..16d4bf1050dd0b2bc2bbdbb7174f9965837949c8 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$Id: mxml-set.c 441 2011-12-09 23:49:00Z mike $"
+ * "$Id: mxml-set.c 451 2014-01-04 21:50:06Z msweet $"
  *
  * Node set functions for Mini-XML, a small XML-like file parsing library.
  *
- * Copyright 2003-2011 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Michael R Sweet and are protected by Federal copyright
  * which should have been included with this file.  If this file is
  * missing or damaged, see the license at:
  *
- *     http://www.minixml.org/
- *
- * Contents:
- *
- *   mxmlSetCDATA()    - Set the element name of a CDATA node.
- *   mxmlSetCustom()   - Set the data and destructor of a custom data node.
- *   mxmlSetElement()  - Set the name of an element node.
- *   mxmlSetInteger()  - Set the value of an integer node.
- *   mxmlSetOpaque()   - Set the value of an opaque node.
- *   mxmlSetReal()     - Set the value of a real number node.
- *   mxmlSetText()     - Set the value of a text node.
- *   mxmlSetTextf()    - Set the value of a text node to a formatted string.
- *   mxmlSetUserData() - Set the user data pointer for a node.
+ *     http://www.msweet.org/projects.php/Mini-XML
  */
 
 /*
@@ -345,5 +333,5 @@ mxmlSetUserData(mxml_node_t *node,  /* I - Node to set */
 
 
 /*
- * End of "$Id: mxml-set.c 441 2011-12-09 23:49:00Z mike $".
+ * End of "$Id: mxml-set.c 451 2014-01-04 21:50:06Z msweet $".
  */
index 6be42523f95c306e62b457a018d2c5140f78b489..9d5b58e6adb70bd73644bef31c5153e3e4a46d5c 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$Id: mxml-string.c 424 2010-12-25 16:21:50Z mike $"
+ * "$Id: mxml-string.c 454 2014-01-05 03:25:07Z msweet $"
  *
  * String functions for Mini-XML, a small XML-like file parsing library.
  *
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Michael R Sweet and are protected by Federal copyright
  * which should have been included with this file.  If this file is
  * missing or damaged, see the license at:
  *
- *     http://www.minixml.org/
- *
- * Contents:
- *
- *   _mxml_snprintf()  - Format a string.
- *   _mxml_strdup()    - Duplicate a string.
- *   _mxml_strdupf()   - Format and duplicate a string.
- *   _mxml_vsnprintf() - Format a string into a fixed size buffer.
- *   _mxml_vstrdupf()  - Format and duplicate a string.
+ *     http://www.msweet.org/projects.php/Mini-XML
  */
 
 /*
@@ -38,7 +30,7 @@
 #  ifdef __va_copy
 #    define va_copy(dst,src) __va_copy(dst,src)
 #  else
-#    define va_copy(dst,src) memcpy(&dst, &src, sizeof(va_list))
+#    define va_copy(dst,src) memcpy(&dst, src, sizeof(va_list))
 #  endif /* __va_copy */
 #endif /* va_copy */
 
@@ -157,7 +149,8 @@ _mxml_vsnprintf(char       *buffer, /* O - Output buffer */
 
       if (*format == '%')
       {
-        if (bufptr && bufptr < bufend) *bufptr++ = *format;
+        if (bufptr && bufptr < bufend)
+          *bufptr++ = *format;
         bytes ++;
         format ++;
        continue;
@@ -472,5 +465,5 @@ _mxml_vstrdupf(const char *format,  /* I - Printf-style format string */
 
 
 /*
- * End of "$Id: mxml-string.c 424 2010-12-25 16:21:50Z mike $".
+ * End of "$Id: mxml-string.c 454 2014-01-05 03:25:07Z msweet $".
  */
index 79c711f4c80fd59674e8273ea6866d37ec534476..bba5fd23a67b663fd432c683104f18909646d8e1 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$Id: mxml.h 427 2011-01-03 02:03:29Z mike $"
+ * "$Id: mxml.h 451 2014-01-04 21:50:06Z msweet $"
  *
  * Header file for Mini-XML, a small XML-like file parsing library.
  *
- * Copyright 2003-2011 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Michael R Sweet and are protected by Federal copyright
@@ -11,7 +11,7 @@
  * which should have been included with this file.  If this file is
  * missing or damaged, see the license at:
  *
- *     http://www.minixml.org/
+ *     http://www.msweet.org/projects.php/Mini-XML
  */
 
 /*
@@ -36,6 +36,9 @@
  * Constants...
  */
 
+#  define MXML_MAJOR_VERSION   2       /* Major version number */
+#  define MXML_MINOR_VERSION   8       /* Minor version number */
+
 #  define MXML_TAB             8       /* Tabs every N columns */
 
 #  define MXML_NO_CALLBACK     0       /* Don't use a type callback */
@@ -93,7 +96,7 @@ typedef enum mxml_type_e              /**** The XML node type. ****/
 typedef void (*mxml_custom_destroy_cb_t)(void *);
                                        /**** Custom data destructor ****/
 
-typedef void (*mxml_error_cb_t)(const char *);  
+typedef void (*mxml_error_cb_t)(const char *);
                                        /**** Error callback function ****/
 
 typedef struct mxml_attr_s             /**** An XML element attribute value. @private@ ****/
@@ -161,7 +164,7 @@ typedef struct mxml_index_s mxml_index_t;
 typedef int (*mxml_custom_load_cb_t)(mxml_node_t *, const char *);
                                        /**** Custom data load callback function ****/
 
-typedef char *(*mxml_custom_save_cb_t)(mxml_node_t *);  
+typedef char *(*mxml_custom_save_cb_t)(mxml_node_t *);
                                        /**** Custom data save callback function ****/
 
 typedef int (*mxml_entity_cb_t)(const char *);
@@ -173,7 +176,7 @@ typedef mxml_type_t (*mxml_load_cb_t)(mxml_node_t *);
 typedef const char *(*mxml_save_cb_t)(mxml_node_t *, int);
                                        /**** Save callback function ****/
 
-typedef void (*mxml_sax_cb_t)(mxml_node_t *, mxml_sax_event_t, void *);  
+typedef void (*mxml_sax_cb_t)(mxml_node_t *, mxml_sax_event_t, void *);
                                        /**** SAX callback function ****/
 
 
@@ -325,5 +328,5 @@ extern mxml_type_t  mxml_real_cb(mxml_node_t *node);
 
 
 /*
- * End of "$Id: mxml.h 427 2011-01-03 02:03:29Z mike $".
+ * End of "$Id: mxml.h 451 2014-01-04 21:50:06Z msweet $".
  */