summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Medhurst <tixy@linaro.org>2012-03-17 10:25:47 +0000
committerJon Medhurst <tixy@linaro.org>2012-03-19 09:06:36 +0000
commit685fec4d4f4fb6bca850be6659e795e8368ce613 (patch)
treea6000b74c677d11a1aceef60e727b623d773254e
parentc16fa4f2ad19908a47c63d8fa436a1178438c7e7 (diff)
gator/daemon: Version 5.9
Signed-off-by: Jon Medhurst <tixy@linaro.org>
-rw-r--r--drivers/gator/daemon/Android.mk34
-rw-r--r--drivers/gator/daemon/CapturedXML.cpp97
-rw-r--r--drivers/gator/daemon/CapturedXML.h23
-rw-r--r--drivers/gator/daemon/Child.cpp304
-rw-r--r--drivers/gator/daemon/Child.h35
-rw-r--r--drivers/gator/daemon/Collector.cpp266
-rw-r--r--drivers/gator/daemon/Collector.h38
-rw-r--r--drivers/gator/daemon/ConfigurationXML.cpp156
-rw-r--r--drivers/gator/daemon/ConfigurationXML.h29
-rw-r--r--drivers/gator/daemon/Fifo.cpp103
-rw-r--r--drivers/gator/daemon/Fifo.h41
-rw-r--r--drivers/gator/daemon/LocalCapture.cpp208
-rw-r--r--drivers/gator/daemon/LocalCapture.h27
-rw-r--r--drivers/gator/daemon/Logging.cpp79
-rw-r--r--drivers/gator/daemon/Logging.h45
-rw-r--r--drivers/gator/daemon/Makefile40
-rw-r--r--drivers/gator/daemon/OlySocket.cpp257
-rw-r--r--drivers/gator/daemon/OlySocket.h38
-rw-r--r--drivers/gator/daemon/OlyUtility.cpp167
-rw-r--r--drivers/gator/daemon/OlyUtility.h35
-rw-r--r--drivers/gator/daemon/RequestXML.cpp61
-rw-r--r--drivers/gator/daemon/RequestXML.h33
-rw-r--r--drivers/gator/daemon/Sender.cpp106
-rw-r--r--drivers/gator/daemon/Sender.h38
-rw-r--r--drivers/gator/daemon/SessionData.cpp103
-rw-r--r--drivers/gator/daemon/SessionData.h68
-rw-r--r--drivers/gator/daemon/SessionXML.cpp119
-rw-r--r--drivers/gator/daemon/SessionXML.h40
-rw-r--r--drivers/gator/daemon/StreamlineSetup.cpp321
-rw-r--r--drivers/gator/daemon/StreamlineSetup.h46
-rw-r--r--drivers/gator/daemon/XMLOut.cpp175
-rw-r--r--drivers/gator/daemon/XMLOut.h45
-rw-r--r--drivers/gator/daemon/XMLReader.cpp164
-rw-r--r--drivers/gator/daemon/XMLReader.h27
-rw-r--r--drivers/gator/daemon/configuration.xml39
-rw-r--r--drivers/gator/daemon/events-ARM11.xml43
-rw-r--r--drivers/gator/daemon/events-ARM11MPCore.xml30
-rw-r--r--drivers/gator/daemon/events-Cortex-A15.xml77
-rw-r--r--drivers/gator/daemon/events-Cortex-A5.xml39
-rw-r--r--drivers/gator/daemon/events-Cortex-A7.xml50
-rw-r--r--drivers/gator/daemon/events-Cortex-A8.xml58
-rw-r--r--drivers/gator/daemon/events-Cortex-A9.xml67
-rw-r--r--drivers/gator/daemon/events-Krait-architected.xml28
-rw-r--r--drivers/gator/daemon/events-L2C-310.xml21
-rw-r--r--drivers/gator/daemon/events-Linux.xml16
-rw-r--r--drivers/gator/daemon/events-Mali-400.xml395
-rw-r--r--drivers/gator/daemon/events-Scorpion.xml113
-rw-r--r--drivers/gator/daemon/events-ScorpionMP.xml96
-rw-r--r--drivers/gator/daemon/events_footer.xml1
-rw-r--r--drivers/gator/daemon/events_header.xml2
-rw-r--r--drivers/gator/daemon/main.cpp306
51 files changed, 4749 insertions, 0 deletions
diff --git a/drivers/gator/daemon/Android.mk b/drivers/gator/daemon/Android.mk
new file mode 100644
index 00000000000..14aeda2d114
--- /dev/null
+++ b/drivers/gator/daemon/Android.mk
@@ -0,0 +1,34 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+$(shell cd $(LOCAL_PATH);cat events_header.xml events-*\.xml events_footer.xml > events.xml;xxd -i events.xml > events_xml.h;xxd -i configuration.xml > configuration_xml.h)
+
+LOCAL_CFLAGS += -Wall -O3 -ftree-vectorize
+
+LOCAL_SRC_FILES:= \
+ CapturedXML.cpp \
+ Child.cpp \
+ Collector.cpp \
+ ConfigurationXML.cpp \
+ Fifo.cpp \
+ LocalCapture.cpp \
+ Logging.cpp \
+ main.cpp \
+ OlySocket.cpp \
+ OlyUtility.cpp \
+ RequestXML.cpp \
+ Sender.cpp \
+ SessionData.cpp \
+ SessionXML.cpp \
+ StreamlineSetup.cpp \
+ XMLOut.cpp \
+ XMLReader.cpp
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)
+
+LOCAL_MODULE:= gatord
+LOCAL_MODULE_TAGS:= optional
+
+LOCAL_LDLIBS := -lz -llog
+
+include $(BUILD_EXECUTABLE)
diff --git a/drivers/gator/daemon/CapturedXML.cpp b/drivers/gator/daemon/CapturedXML.cpp
new file mode 100644
index 00000000000..51076dd4871
--- /dev/null
+++ b/drivers/gator/daemon/CapturedXML.cpp
@@ -0,0 +1,97 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include "SessionData.h"
+#include "CapturedXML.h"
+#include "Logging.h"
+#include "OlyUtility.h"
+
+extern void handleException();
+
+CapturedXML::CapturedXML() {
+}
+
+CapturedXML::~CapturedXML() {
+}
+
+const char* CapturedXML::getXML() {
+ bool perfCounters = false;
+ int x;
+
+ clearXmlString();
+ xmlHeader();
+
+ for (x=0; x<MAX_PERFORMANCE_COUNTERS; x++) {
+ if (gSessionData->mPerfCounterEnabled[x]) {
+ perfCounters = true;
+ break;
+ }
+ }
+
+ startElement("captured");
+ attributeInt("version", 1);
+ attributeInt("protocol", PROTOCOL_VERSION);
+ if (gSessionData->mBytes > 0) { // Send the following only after the capture is complete
+ if (time(NULL) > 1267000000) { // If the time is reasonable (after Feb 23, 2010)
+ attributeUInt("created", time(NULL)); // Valid until the year 2038
+ }
+ attributeUInt("bytes", gSessionData->mBytes);
+ }
+ startElement("target");
+ attributeString("name", gSessionData->mCoreName);
+ attributeInt("sample_rate", gSessionData->mSampleRate);
+ attributeInt("cores", gSessionData->mCores);
+ endElement("target");
+ if (perfCounters) {
+ startElement("counters");
+ for (x = 0; x < MAX_PERFORMANCE_COUNTERS; x++) {
+ if (gSessionData->mPerfCounterEnabled[x]) {
+ startElement("counter");
+ attributeString("title", gSessionData->mPerfCounterTitle[x]);
+ attributeString("name", gSessionData->mPerfCounterName[x]);
+ attributeHex8("color", gSessionData->mPerfCounterColor[x]);
+ attributeHex8("key", gSessionData->mPerfCounterKey[x]);
+ attributeString("type", gSessionData->mPerfCounterType[x]);
+ attributeHex8("event", gSessionData->mPerfCounterEvent[x]);
+ if (gSessionData->mPerfCounterPerCPU[x]) {
+ attributeBool("per_cpu", true);
+ }
+ if (strlen(gSessionData->mPerfCounterOperation[x]) > 0) {
+ attributeString("operation", gSessionData->mPerfCounterOperation[x]);
+ }
+ if (gSessionData->mPerfCounterCount[x] > 0) {
+ attributeInt("count", gSessionData->mPerfCounterCount[x]);
+ }
+ attributeString("description", gSessionData->mPerfCounterDescription[x]);
+ endElement("counter");
+ }
+ }
+ endElement("counters");
+ }
+ endElement("captured");
+ return getXmlString();
+}
+
+void CapturedXML::write(char* path) {
+ char* file = (char*)malloc(PATH_MAX);
+
+ // Set full path
+ snprintf(file, PATH_MAX, "%s/captured.xml", path);
+
+ // Write the file
+ const char* xml = getXML();
+ if (util->writeToDisk(file, xml) < 0) {
+ logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
+ handleException();
+ }
+
+ free(file);
+}
diff --git a/drivers/gator/daemon/CapturedXML.h b/drivers/gator/daemon/CapturedXML.h
new file mode 100644
index 00000000000..d37c59e37ac
--- /dev/null
+++ b/drivers/gator/daemon/CapturedXML.h
@@ -0,0 +1,23 @@
+/**
+
+ * Copyright (C) ARM Limited 2010-2012. 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 __CAPTURED_XML_H__
+#define __CAPTURED_XML_H__
+
+#include "XMLOut.h"
+
+class CapturedXML : XMLOut {
+public:
+ CapturedXML();
+ ~CapturedXML();
+ const char* getXML();
+ void write(char* path);
+};
+
+#endif //__CAPTURED_XML_H__
diff --git a/drivers/gator/daemon/Child.cpp b/drivers/gator/daemon/Child.cpp
new file mode 100644
index 00000000000..fe5a1f061f9
--- /dev/null
+++ b/drivers/gator/daemon/Child.cpp
@@ -0,0 +1,304 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/syscall.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <sys/prctl.h>
+#include "Logging.h"
+#include "CapturedXML.h"
+#include "SessionData.h"
+#include "Child.h"
+#include "LocalCapture.h"
+#include "Collector.h"
+#include "Sender.h"
+#include "OlyUtility.h"
+#include "StreamlineSetup.h"
+#include "ConfigurationXML.h"
+
+static sem_t haltPipeline, senderThreadStarted, startProfile; // Shared by Child and spawned threads
+static Fifo* collectorFifo = NULL; // Shared by Child.cpp and spawned threads
+static Sender* sender = NULL; // Shared by Child.cpp and spawned threads
+Collector* collector = NULL;
+Child* child = NULL; // shared by Child.cpp and main.cpp
+
+extern void cleanUp();
+void handleException() {
+ if (child && child->numExceptions++ > 0) {
+ // it is possible one of the below functions itself can cause an exception, thus allow only one exception
+ logg->logMessage("Received multiple exceptions, terminating the child");
+ exit(1);
+ }
+ fprintf(stderr, "%s", logg->getLastError());
+
+ if (child && child->socket) {
+ if (sender) {
+ // send the error, regardless of the command sent by Streamline
+ sender->writeData(logg->getLastError(), strlen(logg->getLastError()), RESPONSE_ERROR);
+
+ // cannot close the socket before Streamline issues the command, so wait for the command before exiting
+ if (gSessionData->mWaitingOnCommand) {
+ char discard;
+ child->socket->receiveNBytes(&discard, 1);
+ }
+
+ // this indirectly calls close socket which will ensure the data has been sent
+ delete sender;
+ }
+ }
+
+ if (gSessionData->mLocalCapture)
+ cleanUp();
+
+ exit(1);
+}
+
+// CTRL C Signal Handler for child process
+void child_handler(int signum) {
+ static bool beenHere = false;
+ if (beenHere == true) {
+ logg->logMessage("Gator is being forced to shut down.");
+ exit(1);
+ }
+ beenHere = true;
+ logg->logMessage("Gator is shutting down.");
+ if (signum == SIGALRM || !collector) {
+ exit(1);
+ } else {
+ child->endSession();
+ alarm(5); // Safety net in case endSession does not complete within 5 seconds
+ }
+}
+
+void* durationThread(void* pVoid) {
+ prctl(PR_SET_NAME, (unsigned int)&"gatord-duration", 0, 0, 0);
+ sem_wait(&startProfile);
+ if (gSessionData->mSessionIsActive) {
+ // Time out after duration seconds
+ // Add a second for host-side filtering
+ sleep(gSessionData->mDuration + 1);
+ if (gSessionData->mSessionIsActive) {
+ logg->logMessage("Duration expired.");
+ child->endSession();
+ }
+ }
+ logg->logMessage("Exit duration thread");
+ return 0;
+}
+
+void* stopThread(void* pVoid) {
+ int length;
+ char type;
+ OlySocket* socket = child->socket;
+
+ prctl(PR_SET_NAME, (unsigned int)&"gatord-stopper", 0, 0, 0);
+ while (gSessionData->mSessionIsActive) {
+ // This thread will stall until the APC_STOP or PING command is received over the socket or the socket is disconnected
+ if (socket->receiveNBytes(&type, sizeof(type)) > 0) {
+ if ((type != COMMAND_APC_STOP) && (type != COMMAND_PING)) {
+ logg->logMessage("INVESTIGATE: Received unknown command type %d", type);
+ } else {
+ // verify a length of zero
+ if (socket->receiveNBytes((char*)&length, sizeof(length)) < 0) {
+ break;
+ }
+
+ if (length == 0) {
+ if (type == COMMAND_APC_STOP) {
+ logg->logMessage("Stop command received.");
+ child->endSession();
+ } else {
+ // Ping is used to make sure gator is alive and requires an ACK as the response
+ logg->logMessage("Ping command received.");
+ sender->writeData(NULL, 0, RESPONSE_ACK);
+ }
+ } else {
+ logg->logMessage("INVESTIGATE: Received stop command but with length = %d", length);
+ }
+ }
+ }
+ }
+
+ logg->logMessage("Exit stop thread");
+ return 0;
+}
+
+void* senderThread(void* pVoid) {
+ int length;
+ char* data;
+
+ sem_post(&senderThreadStarted);
+ prctl(PR_SET_NAME, (unsigned int)&"gatord-sender", 0, 0, 0);
+ sem_wait(&haltPipeline);
+
+ do {
+ data = collectorFifo->read(&length);
+ sender->writeData(data, length, RESPONSE_APC_DATA);
+ } while (length > 0);
+ logg->logMessage("Exit sender thread");
+ return 0;
+}
+
+Child::Child(char* path) {
+ initialization();
+ sessionXMLPath = path;
+ gSessionData->mLocalCapture = true;
+}
+
+Child::Child(OlySocket* sock, int conn) {
+ initialization();
+ socket = sock;
+ numConnections = conn;
+}
+
+Child::~Child() {
+}
+
+void Child::initialization() {
+ // Set up different handlers for signals
+ gSessionData->mSessionIsActive = true;
+ signal(SIGINT, child_handler);
+ signal(SIGTERM, child_handler);
+ signal(SIGABRT, child_handler);
+ signal(SIGALRM, child_handler);
+ socket = NULL;
+ numExceptions = 0;
+ numConnections = 0;
+ sessionXMLPath = 0;
+
+ // Initialize semaphores
+ sem_init(&senderThreadStarted, 0, 0);
+ sem_init(&startProfile, 0, 0);
+}
+
+void Child::endSession() {
+ gSessionData->mSessionIsActive = false;
+ collector->stop();
+ sem_post(&haltPipeline);
+}
+
+void Child::run() {
+ char* collectBuffer;
+ int bytesCollected = 0;
+ LocalCapture* localCapture = NULL;
+
+ prctl(PR_SET_NAME, (unsigned int)&"gatord-child", 0, 0, 0);
+
+ // Instantiate the Sender - must be done first, after which error messages can be sent
+ sender = new Sender(socket);
+
+ if (numConnections > 1) {
+ logg->logError(__FILE__, __LINE__, "Session already in progress");
+ handleException();
+ }
+
+ // Populate gSessionData with the configuration
+ new ConfigurationXML();
+
+ // Set up the driver; must be done after gSessionData->mPerfCounterType[] is populated
+ collector = new Collector();
+
+ // Start up and parse session xml
+ if (socket) {
+ // Respond to Streamline requests
+ StreamlineSetup ss(socket);
+ } else {
+ xmlString = util->readFromDisk(sessionXMLPath);
+ if (xmlString == 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to read session xml file: %s", sessionXMLPath);
+ handleException();
+ }
+ gSessionData->parseSessionXML(xmlString);
+ localCapture = new LocalCapture();
+ localCapture->createAPCDirectory(gSessionData->target_path, gSessionData->title);
+ localCapture->copyImages(gSessionData->images);
+ localCapture->write(xmlString);
+ sender->createDataFile(gSessionData->apcDir);
+ delete xmlString;
+ }
+
+ // Write configuration into the driver
+ collector->enablePerfCounters();
+
+ // Create user-space buffers
+ int fifoBufferSize = collector->getBufferSize();
+ int numCollectorBuffers = (gSessionData->mTotalBufferSize * 1024 * 1024 + fifoBufferSize - 1) / fifoBufferSize;
+ numCollectorBuffers = (numCollectorBuffers < 4) ? 4 : numCollectorBuffers;
+ logg->logMessage("Created %d %d-byte collector buffers", numCollectorBuffers, fifoBufferSize);
+ collectorFifo = new Fifo(numCollectorBuffers, fifoBufferSize);
+
+ // Get the initial pointer to the collect buffer
+ collectBuffer = collectorFifo->start();
+
+ // Sender thread shall be halted until it is signaled for one shot mode
+ sem_init(&haltPipeline, 0, gSessionData->mOneShot ? 0 : 2);
+
+ // Create the duration, stop, and sender threads
+ bool thread_creation_success = true;
+ if (gSessionData->mDuration > 0 && pthread_create(&durationThreadID, NULL, durationThread, NULL))
+ thread_creation_success = false;
+ else if (socket && pthread_create(&stopThreadID, NULL, stopThread, NULL))
+ thread_creation_success = false;
+ else if (pthread_create(&senderThreadID, NULL, senderThread, NULL))
+ thread_creation_success = false;
+ if (!thread_creation_success) {
+ logg->logError(__FILE__, __LINE__, "Failed to create gator threads");
+ handleException();
+ }
+
+ // Wait until thread has started
+ sem_wait(&senderThreadStarted);
+
+ // Start profiling
+ logg->logMessage("********** Profiling started **********");
+ collector->start();
+ sem_post(&startProfile);
+
+ // Collect Data
+ do {
+ // This command will stall until data is received from the driver
+ bytesCollected = collector->collect(collectBuffer);
+
+ // In one shot mode, stop collection once all the buffers are filled
+ if (gSessionData->mOneShot && gSessionData->mSessionIsActive) {
+ // Depth minus 1 because write() has not yet been called
+ if ((bytesCollected == -1) || (collectorFifo->numWriteToReadBuffersFilled() == collectorFifo->depth() - 1)) {
+ logg->logMessage("One shot");
+ endSession();
+ }
+ }
+ collectBuffer = collectorFifo->write(bytesCollected);
+ } while (bytesCollected > 0);
+ logg->logMessage("Exit collect data loop");
+
+ // Wait for the other threads to exit
+ pthread_join(senderThreadID, NULL);
+
+ // Shutting down the connection should break the stop thread which is stalling on the socket recv() function
+ if (socket) {
+ logg->logMessage("Waiting on stop thread");
+ socket->shutdownConnection();
+ pthread_join(stopThreadID, NULL);
+ }
+
+ // Write the captured xml file
+ if (gSessionData->mLocalCapture) {
+ CapturedXML capturedXML;
+ capturedXML.write(gSessionData->apcDir);
+ }
+
+ logg->logMessage("Profiling ended.");
+
+ delete collectorFifo;
+ delete sender;
+ delete collector;
+ delete localCapture;
+}
diff --git a/drivers/gator/daemon/Child.h b/drivers/gator/daemon/Child.h
new file mode 100644
index 00000000000..eee5ac70f9e
--- /dev/null
+++ b/drivers/gator/daemon/Child.h
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 __CHILD_H__
+#define __CHILD_H__
+
+#include <pthread.h>
+#include "Fifo.h"
+#include "OlySocket.h"
+
+class Child {
+public:
+ Child(char* sessionXMLPath);
+ Child(OlySocket* sock, int numConnections);
+ ~Child();
+ void run();
+ OlySocket *socket;
+ void endSession();
+ int numExceptions;
+private:
+ char* xmlString;
+ char* sessionXMLPath;
+ int numConnections;
+ time_t timeStart;
+ pthread_t durationThreadID, stopThreadID, senderThreadID;
+
+ void initialization();
+};
+
+#endif //__CHILD_H__
diff --git a/drivers/gator/daemon/Collector.cpp b/drivers/gator/daemon/Collector.cpp
new file mode 100644
index 00000000000..c6f837628f1
--- /dev/null
+++ b/drivers/gator/daemon/Collector.cpp
@@ -0,0 +1,266 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <fcntl.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include "Collector.h"
+#include "SessionData.h"
+#include "Logging.h"
+
+extern void handleException();
+
+// Driver initialization independent of session settings
+Collector::Collector() {
+ char text[sizeof(gSessionData->mPerfCounterType[0]) + 20]; // sufficiently large to hold all events/<types>/<file>
+
+ bufferFD = 0;
+
+ checkVersion();
+
+ int enable = -1;
+ if (readIntDriver("enable", &enable) != 0 || enable != 0) {
+ logg->logError(__FILE__, __LINE__, "Driver already enabled, possibly a session is already in progress.");
+ handleException();
+ }
+
+ readIntDriver("cpu_cores", &gSessionData->mCores);
+ if (gSessionData->mCores == 0) {
+ gSessionData->mCores = 1;
+ }
+
+ bufferSize = 512 * 1024;
+ if (writeReadDriver("buffer_size", &bufferSize) || bufferSize <= 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to set the driver buffer size");
+ handleException();
+ }
+
+ getCoreName();
+
+ // Read unchanging keys from driver which are created at insmod'ing of gator.ko
+ for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) {
+ snprintf(text, sizeof(text), "events/%s/key", gSessionData->mPerfCounterType[i]);
+ readIntDriver(text, &gSessionData->mPerfCounterKey[i]);
+ }
+}
+
+Collector::~Collector() {
+ // Write zero for safety, as a zero should have already been written
+ writeDriver("enable", "0");
+
+ // Calls event_buffer_release in the driver
+ if (bufferFD) {
+ close(bufferFD);
+ }
+}
+
+void Collector::enablePerfCounters() {
+ char base[sizeof(gSessionData->mPerfCounterType[0]) + 10]; // sufficiently large to hold all events/<types>
+ char text[sizeof(gSessionData->mPerfCounterType[0]) + 20]; // sufficiently large to hold all events/<types>/<file>
+
+ for (int i=0; i<MAX_PERFORMANCE_COUNTERS; i++) {
+ if (!gSessionData->mPerfCounterEnabled[i]) {
+ continue;
+ }
+ snprintf(base, sizeof(base), "events/%s", gSessionData->mPerfCounterType[i]);
+ snprintf(text, sizeof(text), "%s/event", base);
+ writeDriver(text, gSessionData->mPerfCounterEvent[i]);
+ if (gSessionData->mPerfCounterEBSCapable[i]) {
+ snprintf(text, sizeof(text), "%s/count", base);
+ if (access(resolvePath(text), F_OK) == 0) {
+ if (writeReadDriver(text, &gSessionData->mPerfCounterCount[i]) && gSessionData->mPerfCounterCount[i] > 0) {
+ logg->logError(__FILE__, __LINE__, "Cannot enable EBS for %s with a count of %d\n", gSessionData->mPerfCounterName[i], gSessionData->mPerfCounterCount[i]);
+ handleException();
+ }
+ } else if (gSessionData->mPerfCounterCount[i] > 0) {
+ logg->logError(__FILE__, __LINE__, "Event Based Sampling is only supported with kernel versions 3.0.0 and higher with CONFIG_PERF_EVENTS=y, and CONFIG_HW_PERF_EVENTS=y\n");
+ handleException();
+ }
+ }
+ snprintf(text, sizeof(text), "%s/enabled", base);
+ if (writeReadDriver(text, &gSessionData->mPerfCounterEnabled[i])) {
+ gSessionData->mPerfCounterEnabled[i] = 0;
+ }
+ }
+}
+
+void Collector::checkVersion() {
+ int driver_version = 0;
+
+ if (readIntDriver("version", &driver_version) == -1) {
+ logg->logError(__FILE__, __LINE__, "Error reading gator driver version");
+ handleException();
+ }
+
+ // Verify the driver version matches the daemon version
+ if (driver_version != PROTOCOL_VERSION) {
+ if ((driver_version > PROTOCOL_DEV) || (PROTOCOL_VERSION > PROTOCOL_DEV)) {
+ // One of the mismatched versions is development version
+ logg->logError(__FILE__, __LINE__,
+ "DEVELOPMENT BUILD MISMATCH: gator driver version \"%d\" is not in sync with gator daemon version \"%d\".\n"
+ ">> The following must be synchronized from engineering repository:\n"
+ ">> * gator driver\n"
+ ">> * gator daemon\n"
+ ">> * Streamline", driver_version, PROTOCOL_VERSION);
+ handleException();
+ } else {
+ // Release version mismatch
+ logg->logError(__FILE__, __LINE__,
+ "gator driver version \"%d\" is different than gator daemon version \"%d\".\n"
+ ">> Please upgrade the driver and daemon to the latest versions.", driver_version, PROTOCOL_VERSION);
+ handleException();
+ }
+ }
+}
+
+void Collector::start() {
+ // Set the maximum backtrace depth
+ if (writeReadDriver("backtrace_depth", &gSessionData->mBacktraceDepth)) {
+ logg->logError(__FILE__, __LINE__, "Unable to set the driver backtrace depth");
+ handleException();
+ }
+
+ // open the buffer which calls userspace_buffer_open() in the driver
+ bufferFD = open(resolvePath("buffer"), O_RDONLY);
+ if (bufferFD < 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();
+ }
+
+ // set the tick rate of the profiling timer
+ if (writeReadDriver("tick", &gSessionData->mSampleRate) != 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to set the driver tick");
+ handleException();
+ }
+
+ // notify the kernel of the streaming mode, currently used for network stats
+ int streaming = (int)!gSessionData->mOneShot;
+ if (writeReadDriver("streaming", &streaming) != 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to set streaming");
+ handleException();
+ }
+
+ logg->logMessage("Start the driver");
+
+ // This command makes the driver start profiling by calling gator_op_start() in the driver
+ if (writeDriver("enable", "1") != 0) {
+ logg->logError(__FILE__, __LINE__, "The gator driver did not start properly. Please view the linux console or dmesg log for more information on the failure.");
+ handleException();
+ }
+
+ lseek(bufferFD, 0, SEEK_SET);
+}
+
+// These commands should cause the read() function in collect() to return
+void Collector::stop() {
+ // This will stop the driver from profiling
+ if (writeDriver("enable", "0") != 0) {
+ logg->logMessage("Stopping kernel failed");
+ }
+}
+
+int Collector::collect(char* buffer) {
+ // Calls event_buffer_read in the driver
+ int bytesRead = read(bufferFD, buffer, bufferSize);
+
+ // If read() returned due to an interrupt signal, re-read to obtain the last bit of collected data
+ if (bytesRead == -1 && errno == EINTR) {
+ bytesRead = read(bufferFD, buffer, bufferSize);
+ }
+
+ logg->logMessage("Driver read of %d bytes", bytesRead);
+
+ return bytesRead;
+}
+
+void Collector::getCoreName() {
+ char temp[256]; // arbitrarily large amount
+ strcpy(gSessionData->mCoreName, "unknown");
+
+ 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'.");
+ return;
+ }
+
+ while (fgets(temp, sizeof(temp), f)) {
+ if (strlen(temp) > 0)
+ temp[strlen(temp) - 1] = 0; // Replace the line feed with a null
+
+ if (strstr(temp, "Hardware") != 0) {
+ char* position = strchr(temp, ':');
+ if (position == NULL || (unsigned int)(position - temp) + 2 >= strlen(temp)) {
+ logg->logMessage("Unknown format of /proc/cpuinfo\n"
+ "The core name in the captured xml file will be 'unknown'.");
+ return;
+ }
+ strncpy(gSessionData->mCoreName, (char *)((int)position + 2), sizeof(gSessionData->mCoreName));
+ gSessionData->mCoreName[sizeof(gSessionData->mCoreName) - 1] = 0; // strncpy does not guarantee a null-terminated string
+ fclose(f);
+ return;
+ }
+ }
+
+ logg->logMessage("Could not determine core name from /proc/cpuinfo\n"
+ "The core name in the captured xml file will be 'unknown'.");
+ fclose(f);
+}
+
+char* Collector::resolvePath(const char* file) {
+ static char fullpath[100]; // Sufficiently large to hold any path within /dev/gator
+ snprintf(fullpath, sizeof(fullpath), "/dev/gator/%s", file);
+ return fullpath;
+}
+
+int Collector::readIntDriver(const char* path, int* value) {
+ char* fullpath = resolvePath(path);
+ FILE* file = fopen(fullpath, "r");
+ if (file == NULL) {
+ return -1;
+ }
+ if (fscanf(file, "%u", value) != 1) {
+ fclose(file);
+ logg->logMessage("Invalid value in file %s", fullpath);
+ return -1;
+ }
+ fclose(file);
+ return 0;
+}
+
+int Collector::writeDriver(const char* path, int value) {
+ char data[40]; // Sufficiently large to hold any integer
+ snprintf(data, sizeof(data), "%d", value);
+ return writeDriver(path, data);
+}
+
+int Collector::writeDriver(const char* path, const char* data) {
+ char* fullpath = resolvePath(path);
+ int fd = open(fullpath, O_WRONLY);
+ if (fd < 0) {
+ return -1;
+ }
+ if (write(fd, data, strlen(data)) < 0) {
+ close(fd);
+ logg->logMessage("Opened but could not write to %s", fullpath);
+ return -1;
+ }
+ close(fd);
+ return 0;
+}
+
+int Collector::writeReadDriver(const char* path, int* value) {
+ if (writeDriver(path, *value) || readIntDriver(path, value)) {
+ return -1;
+ }
+ return 0;
+}
diff --git a/drivers/gator/daemon/Collector.h b/drivers/gator/daemon/Collector.h
new file mode 100644
index 00000000000..1cfe84e1b97
--- /dev/null
+++ b/drivers/gator/daemon/Collector.h
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 __COLLECTOR_H__
+#define __COLLECTOR_H__
+
+#include <stdio.h>
+
+class Collector {
+public:
+ Collector();
+ ~Collector();
+ void start();
+ void stop();
+ int collect(char* buffer);
+ void enablePerfCounters();
+ int getBufferSize() {return bufferSize;}
+private:
+ int bufferSize;
+ int bufferFD;
+ char * buffer;
+
+ void checkVersion();
+ void getCoreName();
+
+ char* resolvePath(const char* file);
+ int readIntDriver(const char* path, int* value);
+ int writeDriver(const char* path, int value);
+ int writeDriver(const char* path, const char* data);
+ int writeReadDriver(const char* path, int* value);
+};
+
+#endif //__COLLECTOR_H__
diff --git a/drivers/gator/daemon/ConfigurationXML.cpp b/drivers/gator/daemon/ConfigurationXML.cpp
new file mode 100644
index 00000000000..e1bec0fd4fa
--- /dev/null
+++ b/drivers/gator/daemon/ConfigurationXML.cpp
@@ -0,0 +1,156 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <string.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include "ConfigurationXML.h"
+#include "Logging.h"
+#include "OlyUtility.h"
+#include "SessionData.h"
+
+extern void handleException();
+
+static const char* ATTR_COUNTER = "counter";
+static const char* ATTR_VERSION = "version";
+static const char* ATTR_TITLE = "title";
+static const char* ATTR_NAME = "name";
+static const char* ATTR_EVENT = "event";
+static const char* ATTR_COLOR = "color";
+static const char* ATTR_COUNT = "count";
+static const char* ATTR_OPERATION = "operation";
+static const char* ATTR_PER_CPU = "per_cpu";
+static const char* ATTR_DESCRIPTION = "description";
+static const char* ATTR_EBS = "event_based_sampling";
+
+ConfigurationXML::ConfigurationXML() {
+#include "configuration_xml.h" // defines and initializes char configuration_xml[] and int configuration_xml_len
+ index = 0;
+ char* path = (char *)malloc(PATH_MAX);
+
+ if (gSessionData->configurationXMLPath) {
+ strncpy(path, gSessionData->configurationXMLPath, PATH_MAX);
+ } else {
+ if (util->getApplicationFullPath(path, PATH_MAX) != 0) {
+ logg->logMessage("Unable to determine the full path of gatord, the cwd will be used");
+ }
+ strncat(path, "configuration.xml", PATH_MAX - strlen(path) - 1);
+ }
+ mConfigurationXML = util->readFromDisk(path);
+
+ if (mConfigurationXML == NULL) {
+ logg->logMessage("Unable to locate configuration.xml, using default in binary");
+ // null-terminate configuration_xml
+ mConfigurationXML = (char*)malloc(configuration_xml_len + 1);
+ memcpy(mConfigurationXML, (const void*)configuration_xml, configuration_xml_len);
+ mConfigurationXML[configuration_xml_len] = 0;
+ }
+
+ // disable all counters prior to parsing the configuration xml
+ for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) {
+ gSessionData->mPerfCounterEnabled[i] = 0;
+ }
+
+ int ret = parse(mConfigurationXML);
+ if (ret == 1) {
+ // remove configuration.xml on disk to use the default
+ if (remove(path) != 0) {
+ logg->logError(__FILE__, __LINE__, "Invalid configuration.xml file detected and unable to delete it. To resolve, delete configuration.xml on disk");
+ handleException();
+ }
+ } else if (ret < 0 || isValid() == false) {
+ logg->logError(__FILE__, __LINE__, "Parsing of the configuration.xml file failed. Please verify configuration.xml on the target filesystem is valid or delete it to use the default.");
+ handleException();
+ }
+
+ free(path);
+}
+
+ConfigurationXML::~ConfigurationXML() {
+ if (mConfigurationXML) {
+ free((void*)mConfigurationXML);
+ }
+}
+
+int ConfigurationXML::parse(const char* configurationXML) {
+ int ret = 0;
+ XMLReader reader(configurationXML);
+ char * tag = reader.nextTag();
+ while(tag != 0 && ret == 0) {
+ if (strcmp(tag, "configurations") == 0) {
+ ret = configurationsTag(&reader);
+ } else if (strcmp(tag, "configuration") == 0) {
+ ret = configurationTag(&reader);
+ }
+ tag = reader.nextTag();
+ }
+
+ return ret;
+}
+
+bool ConfigurationXML::isValid(void) {
+ for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) {
+ if (gSessionData->mPerfCounterEnabled[i]) {
+ if (strcmp(gSessionData->mPerfCounterType[i], "") == 0 ||
+ strcmp(gSessionData->mPerfCounterTitle[i], "") == 0 ||
+ strcmp(gSessionData->mPerfCounterName[i], "") == 0) {
+ logg->logMessage("Invalid required attribute\n counter=\"%s\"\n title=\"%s\"\n name=\"%s\"\n event=%d\n", gSessionData->mPerfCounterType[i], gSessionData->mPerfCounterTitle[i], gSessionData->mPerfCounterName[i], gSessionData->mPerfCounterEvent[i]);
+ return false; // failure
+ }
+
+ // iterate through the remaining enabled performance counters
+ for (int j = i + 1; j < MAX_PERFORMANCE_COUNTERS; j++) {
+ if (gSessionData->mPerfCounterEnabled[j]) {
+ // check if the type or device are the same
+ if (strcmp(gSessionData->mPerfCounterType[i], gSessionData->mPerfCounterType[j]) == 0) {
+ logg->logMessage("Duplicate performance counter type: %s", gSessionData->mPerfCounterType[i]);
+ return false; // failure
+ }
+ }
+ }
+ }
+ }
+
+ return true; // success
+}
+
+#define CONFIGURATION_VERSION 1
+int ConfigurationXML::configurationsTag(XMLReader *in) {
+ int version = in->getAttributeAsInteger(ATTR_VERSION, 0);
+ if (version != CONFIGURATION_VERSION) {
+ logg->logMessage("Incompatible configuration.xml version (%d) detected. The version needs to be %d.", version, CONFIGURATION_VERSION);
+ return 1; // version issue
+ }
+ return 0;
+}
+
+int ConfigurationXML::configurationTag(XMLReader* in) {
+ // handle all other performance counters
+ if (index >= MAX_PERFORMANCE_COUNTERS) {
+ logg->logMessage("Invalid performance counter index: %d", index);
+ return -1; // failure
+ }
+
+ // read attributes
+ in->getAttribute(ATTR_COUNTER, gSessionData->mPerfCounterType[index], sizeof(gSessionData->mPerfCounterType[index]), "");
+ in->getAttribute(ATTR_TITLE, gSessionData->mPerfCounterTitle[index], sizeof(gSessionData->mPerfCounterTitle[index]), "");
+ in->getAttribute(ATTR_NAME, gSessionData->mPerfCounterName[index], sizeof(gSessionData->mPerfCounterName[index]), "");
+ in->getAttribute(ATTR_DESCRIPTION, gSessionData->mPerfCounterDescription[index], sizeof(gSessionData->mPerfCounterDescription[index]), "");
+ gSessionData->mPerfCounterEvent[index] = in->getAttributeAsInteger(ATTR_EVENT, 0);
+ gSessionData->mPerfCounterCount[index] = in->getAttributeAsInteger(ATTR_COUNT, 0);
+ gSessionData->mPerfCounterColor[index] = in->getAttributeAsInteger(ATTR_COLOR, 0);
+ gSessionData->mPerfCounterPerCPU[index] = in->getAttributeAsBoolean(ATTR_PER_CPU, false);
+ gSessionData->mPerfCounterEBSCapable[index] = in->getAttributeAsBoolean(ATTR_EBS, false);
+ in->getAttribute(ATTR_OPERATION, gSessionData->mPerfCounterOperation[index], sizeof(gSessionData->mPerfCounterOperation[index]), "");
+ gSessionData->mPerfCounterEnabled[index] = true;
+
+ // update counter index
+ index++;
+
+ return 0; // success
+}
diff --git a/drivers/gator/daemon/ConfigurationXML.h b/drivers/gator/daemon/ConfigurationXML.h
new file mode 100644
index 00000000000..047c4b07705
--- /dev/null
+++ b/drivers/gator/daemon/ConfigurationXML.h
@@ -0,0 +1,29 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 COUNTERS_H
+#define COUNTERS_H
+
+#include "XMLReader.h"
+
+class ConfigurationXML {
+public:
+ ConfigurationXML();
+ ~ConfigurationXML();
+ const char* getConfigurationXML() {return mConfigurationXML;}
+private:
+ char* mConfigurationXML;
+
+ int parse(const char* xmlFile);
+ bool isValid(void);
+ int configurationsTag(XMLReader *in);
+ int configurationTag(XMLReader* in);
+ int index;
+};
+
+#endif // COUNTERS_H
diff --git a/drivers/gator/daemon/Fifo.cpp b/drivers/gator/daemon/Fifo.cpp
new file mode 100644
index 00000000000..1456183b0f0
--- /dev/null
+++ b/drivers/gator/daemon/Fifo.cpp
@@ -0,0 +1,103 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "Fifo.h"
+#include "Logging.h"
+
+extern void handleException();
+
+Fifo::Fifo(int numBuffers, int bufferSize) {
+ int which;
+
+ if (numBuffers > FIFO_BUFFER_LIMIT) {
+ logg->logError(__FILE__, __LINE__, "Number of fifo buffers exceeds maximum");
+ handleException();
+ }
+ mNumBuffers = numBuffers;
+ mBufferSize = bufferSize;
+ mWriteCurrent = 0;
+ mReadCurrent = mNumBuffers - 1; // (n-1) pipelined
+
+ for (which=0; which<mNumBuffers; which++) {
+ // initialized read-to-write sem to 1, so that first wait goes through; write-to-read init'd to 0
+ if (sem_init(&mReadToWriteSem[which], 0, 1) ||
+ sem_init(&mWriteToReadSem[which], 0, 0)) {
+ logg->logError(__FILE__, __LINE__, "sem_init(%d) failed", which);
+ handleException();
+ }
+ // page-align allocate buffers
+ mBuffer[which] = (char*)valloc(bufferSize);
+ if (mBuffer[which] == NULL) {
+ logg->logError(__FILE__, __LINE__, "failed to allocate %d bytes", bufferSize);
+ handleException();
+ }
+ // touch each page to fault it in
+ for (int i=0; i<bufferSize; i+= getpagesize()) {
+ *mBuffer[which] = 0;
+ }
+ }
+}
+
+Fifo::~Fifo() {
+ for (int which=0; which<mNumBuffers; which++) {
+ if (mBuffer[which] != NULL) {
+ free(mBuffer[which]);
+ mBuffer[which] = NULL;
+ }
+ }
+}
+
+int Fifo::depth(void) {
+ return mNumBuffers;
+}
+
+int Fifo::numReadToWriteBuffersFilled() {
+ int value;
+ int numFilled = 0;
+ for (int which=0; which<mNumBuffers; which++) {
+ if (sem_getvalue(&mReadToWriteSem[which], &value) == 0) numFilled += value;
+ }
+ return numFilled;
+}
+
+int Fifo::numWriteToReadBuffersFilled() {
+ int value;
+ int numFilled = 0;
+ for (int which=0; which<mNumBuffers; which++) {
+ if (sem_getvalue(&mWriteToReadSem[which], &value) == 0) numFilled += value;
+ }
+ return numFilled;
+}
+
+char* Fifo::start() {
+ sem_wait(&mReadToWriteSem[mWriteCurrent]);
+ return mBuffer[mWriteCurrent];
+}
+
+char* Fifo::write(int length) {
+ mLength[mWriteCurrent] = length;
+ sem_post(&mWriteToReadSem[mWriteCurrent]);
+ mWriteCurrent = (mWriteCurrent + 1) % mNumBuffers;
+ sem_wait(&mReadToWriteSem[mWriteCurrent]);
+ return mBuffer[mWriteCurrent];
+}
+
+char* Fifo::read(int* length) {
+ static bool firstTime = true;
+ if (!firstTime) {
+ sem_post(&mReadToWriteSem[mReadCurrent]);
+ }
+ firstTime = false;
+ mReadCurrent = (mReadCurrent + 1) % mNumBuffers;
+ sem_wait(&mWriteToReadSem[mReadCurrent]);
+ *length = mLength[mReadCurrent];
+ return mBuffer[mReadCurrent];
+}
diff --git a/drivers/gator/daemon/Fifo.h b/drivers/gator/daemon/Fifo.h
new file mode 100644
index 00000000000..51e2bcd6a7f
--- /dev/null
+++ b/drivers/gator/daemon/Fifo.h
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 __FIFO_H__
+#define __FIFO_H__
+
+#include <semaphore.h>
+
+// Number of buffers allowed with large buffer mode
+#define FIFO_BUFFER_LIMIT 64
+
+class Fifo {
+public:
+ Fifo(int numBuffers, int bufferSize);
+ ~Fifo();
+ int depth(void);
+ int numReadToWriteBuffersFilled();
+ int numWriteToReadBuffersFilled();
+ int numReadToWriteBuffersEmpty() {return depth() - numReadToWriteBuffersFilled();}
+ int numWriteToReadBuffersEmpty() {return depth() - numWriteToReadBuffersFilled();}
+ char* start();
+ char* write(int length);
+ char* read(int* length);
+
+private:
+ int mNumBuffers;
+ int mBufferSize;
+ int mWriteCurrent;
+ int mReadCurrent;
+ sem_t mReadToWriteSem[FIFO_BUFFER_LIMIT];
+ sem_t mWriteToReadSem[FIFO_BUFFER_LIMIT];
+ char* mBuffer[FIFO_BUFFER_LIMIT];
+ int mLength[FIFO_BUFFER_LIMIT];
+};
+
+#endif //__FIFO_H__
diff --git a/drivers/gator/daemon/LocalCapture.cpp b/drivers/gator/daemon/LocalCapture.cpp
new file mode 100644
index 00000000000..4a2d6d755e6
--- /dev/null
+++ b/drivers/gator/daemon/LocalCapture.cpp
@@ -0,0 +1,208 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "LocalCapture.h"
+#include "SessionData.h"
+#include "Logging.h"
+#include "OlyUtility.h"
+
+extern void handleException();
+
+LocalCapture::LocalCapture() {}
+
+LocalCapture::~LocalCapture() {}
+
+void LocalCapture::createAPCDirectory(char* target_path, char* name) {
+ gSessionData->apcDir = createUniqueDirectory(target_path, ".apc", name);
+ if ((removeDirAndAllContents(gSessionData->apcDir) != 0 || mkdir(gSessionData->apcDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)) {
+ logg->logError(__FILE__, __LINE__, "Unable to create directory %s", gSessionData->apcDir);
+ handleException();
+ }
+}
+
+void LocalCapture::write(char* string) {
+ char* file = (char*)malloc(PATH_MAX);
+
+ // Set full path
+ snprintf(file, PATH_MAX, "%s/session.xml", gSessionData->apcDir);
+
+ // Write the file
+ if (util->writeToDisk(file, string) < 0) {
+ logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
+ handleException();
+ }
+
+ free(file);
+}
+
+char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* ending, char* title) {
+ int i;
+ char* output;
+ char* path = (char*)malloc(PATH_MAX);
+
+ // Ensure the path is an absolute path, i.e. starts with a slash
+ if (initialPath == 0 || strlen(initialPath) == 0) {
+ if (getcwd(path, PATH_MAX) == 0)
+ logg->logMessage("Unable to retrive the current working directory");
+ strncat(path, "/@F_@N", PATH_MAX - strlen(path) - 1);
+ } else if (initialPath[0] != '/') {
+ if (getcwd(path, PATH_MAX) == 0)
+ logg->logMessage("Unable to retrive the current working directory");
+ strncat(path, "/", PATH_MAX - strlen(path) - 1);
+ strncat(path, initialPath, PATH_MAX - strlen(path) - 1);
+ } else {
+ strncpy(path, initialPath, PATH_MAX);
+ path[PATH_MAX - 1] = 0; // strncpy does not guarantee a null-terminated string
+ }
+
+ // Convert to uppercase
+ replaceAll(path, "@f", "@F", PATH_MAX);
+ replaceAll(path, "@n", "@N", PATH_MAX);
+
+ // Replace @F with the session xml title
+ replaceAll(path, "@F", title, PATH_MAX);
+
+ // Add ending if it is not already there
+ if (strcmp(&path[strlen(path) - strlen(ending)], ending) != 0) {
+ strncat(path, ending, PATH_MAX - strlen(path) - 1);
+ }
+
+ // Replace @N with a unique integer
+ if (strstr(path, "@N")) {
+ char* tempPath = (char*)malloc(PATH_MAX);
+ for (i = 1; i < 1000; i++) {
+ char number[4];
+ snprintf(number, sizeof(number), "%03d", i);
+ strcpy(tempPath, path);
+ replaceAll(tempPath, "@N", number, PATH_MAX);
+ struct stat mFileInfo;
+ if (stat(tempPath, &mFileInfo) != 0) {
+ // if the direcotry does not exist, break
+ break;
+ }
+ }
+
+ if (i == 1000) {
+ logg->logError(__FILE__, __LINE__, "Unable to create .apc directory, please delete older directories.");
+ handleException();
+ }
+
+ output = strdup(tempPath);
+ free(tempPath);
+ } else {
+ output = strdup(path);
+ }
+
+ free(path);
+ return output;
+}
+
+//Replaces all occurrences of <find> in <target> with <replace> provided enough <size> is available
+void LocalCapture::replaceAll(char* target, const char* find, const char* replace, unsigned int size) {
+ char* nextOccurrence;
+ unsigned int count = 0;
+
+ // Duplicate the original string
+ char* original = strdup(target);
+ char* ptr = original;
+
+ // Determine number of <find>s
+ ptr = strstr(ptr, find);
+ while (ptr) {
+ count++;
+ ptr += strlen(find);
+ ptr = strstr(ptr, find);
+ }
+
+ // Is there enough space available
+ if (strlen(target) + (strlen(replace) - strlen(find)) * count > size - 1) {
+ free(original);
+ return;
+ }
+
+ // Reset
+ ptr = original;
+
+ nextOccurrence = strstr(ptr, find);
+ while (nextOccurrence) {
+ // Move pointers to location of replace
+ int length = nextOccurrence - ptr;
+ target += length;
+ ptr += length;
+
+ // Replace <find> with <replace>
+ memcpy(target, replace, strlen(replace));
+
+ // Increment over <replace>/<find>
+ target += strlen(replace);
+ ptr += strlen(find);
+
+ // Copy remainder of ptr
+ strcpy(target, ptr);
+
+ // Get next occurrence
+ nextOccurrence = strstr(ptr, find);
+ }
+
+ free(original);
+}
+
+int LocalCapture::removeDirAndAllContents(char *path) {
+ int error = 0;
+ struct stat mFileInfo;
+ // Does the path exist?
+ if (stat(path, &mFileInfo) == 0) {
+ // Is it a directory?
+ if (mFileInfo.st_mode & S_IFDIR) {
+ DIR * dir = opendir(path);
+ dirent* entry = readdir(dir);
+ while (entry) {
+ if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
+ char* newpath = (char*)malloc(strlen(path) + strlen(entry->d_name) + 2);
+ sprintf(newpath, "%s/%s", path, entry->d_name);
+ error = removeDirAndAllContents(newpath);
+ free(newpath);
+ if (error) break;
+ }
+ entry = readdir(dir);
+ }
+ closedir(dir);
+ if (error == 0) {
+ error = rmdir(path);
+ }
+ } else {
+ error = remove(path);
+ }
+ }
+ return error;
+}
+
+void LocalCapture::copyImages(ImageLinkList* ptr) {
+ char* dstfilename = (char*)malloc(PATH_MAX);
+
+ while (ptr) {
+ strncpy(dstfilename, gSessionData->apcDir, PATH_MAX);
+ dstfilename[PATH_MAX - 1] = 0; // strncpy does not guarantee a null-terminated string
+ if (gSessionData->apcDir[strlen(gSessionData->apcDir) - 1] != '/')
+ strncat(dstfilename, "/", PATH_MAX - strlen(dstfilename) - 1);
+ strncat(dstfilename, util->getFilePart(ptr->path), PATH_MAX - strlen(dstfilename) - 1);
+ if (util->copyFile(ptr->path, dstfilename))
+ logg->logMessage("copied file %s to %s", ptr->path, dstfilename);
+ else
+ logg->logMessage("copy of file %s to %s failed", ptr->path, dstfilename);
+
+ ptr = ptr->next;
+ }
+ free(dstfilename);
+}
diff --git a/drivers/gator/daemon/LocalCapture.h b/drivers/gator/daemon/LocalCapture.h
new file mode 100644
index 00000000000..4f5f8186e09
--- /dev/null
+++ b/drivers/gator/daemon/LocalCapture.h
@@ -0,0 +1,27 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 __LOCAL_CAPTURE_H__
+#define __LOCAL_CAPTURE_H__
+
+#include "SessionXML.h"
+
+class LocalCapture {
+public:
+ LocalCapture();
+ ~LocalCapture();
+ void write(char *string);
+ void copyImages(ImageLinkList* ptr);
+ void createAPCDirectory(char* target_path, char* name);
+private:
+ char* createUniqueDirectory(const char* path, const char* ending, char* title);
+ void replaceAll(char* target, const char* find, const char* replace, unsigned int size);
+ int removeDirAndAllContents(char *path);
+};
+
+#endif //__LOCAL_CAPTURE_H__
diff --git a/drivers/gator/daemon/Logging.cpp b/drivers/gator/daemon/Logging.cpp
new file mode 100644
index 00000000000..3e6f8a388a4
--- /dev/null
+++ b/drivers/gator/daemon/Logging.cpp
@@ -0,0 +1,79 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include "OlyUtility.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
+#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)
+#endif
+
+#include "Logging.h"
+
+// Global thread-safe logging
+Logging* logg = NULL;
+
+Logging::Logging(bool debug) {
+ mDebug = debug;
+ MUTEX_INIT();
+
+ strcpy(mErrBuf, "Unknown Error");
+ strcpy(mLogBuf, "Unknown Message");
+}
+
+Logging::~Logging() {
+}
+
+void Logging::logError(const char* file, int line, const char* fmt, ...) {
+ va_list args;
+
+ MUTEX_LOCK();
+ if (mDebug) {
+ snprintf(mErrBuf, sizeof(mErrBuf), "ERROR[%s:%d]: ", file, line);
+ } else {
+ mErrBuf[0] = 0;
+ }
+
+ va_start(args, fmt);
+ vsnprintf(mErrBuf + strlen(mErrBuf), sizeof(mErrBuf) - 2 - strlen(mErrBuf), fmt, args); // subtract 2 for \n and \0
+ va_end(args);
+
+ if (strlen(mErrBuf) > 0) {
+ strcat(mErrBuf, "\n");
+ }
+ MUTEX_UNLOCK();
+}
+
+void Logging::logMessage(const char* fmt, ...) {
+ if (mDebug) {
+ va_list args;
+
+ MUTEX_LOCK();
+ strcpy(mLogBuf, "INFO: ");
+
+ va_start(args, fmt);
+ vsnprintf(mLogBuf + strlen(mLogBuf), sizeof(mLogBuf) - 2 - strlen(mLogBuf), fmt, args); // subtract 2 for \n and \0
+ va_end(args);
+ strcat(mLogBuf, "\n");
+
+ fprintf(stdout, "%s", mLogBuf);
+ fflush(stdout);
+ MUTEX_UNLOCK();
+ }
+}
diff --git a/drivers/gator/daemon/Logging.h b/drivers/gator/daemon/Logging.h
new file mode 100644
index 00000000000..424796658f7
--- /dev/null
+++ b/drivers/gator/daemon/Logging.h
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 __LOGGING_H__
+#define __LOGGING_H__
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#endif
+
+#define DRIVER_ERROR "\n Driver issue:\n >> gator.ko must be built against the current kernel version & configuration\n >> gator.ko should be co-located with gatord in the same directory\n >> OR insmod gator.ko prior to launching gatord"
+
+class Logging {
+public:
+ Logging(bool debug);
+ ~Logging();
+ void logError(const char* file, int line, const char* fmt, ...);
+ void logMessage(const char* fmt, ...);
+ char* getLastError() {return mErrBuf;}
+ 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;
+#ifdef WIN32
+ HANDLE mLoggingMutex;
+#else
+ pthread_mutex_t mLoggingMutex;
+#endif
+};
+
+extern Logging* logg;
+
+#endif //__LOGGING_H__
diff --git a/drivers/gator/daemon/Makefile b/drivers/gator/daemon/Makefile
new file mode 100644
index 00000000000..4aaf219d784
--- /dev/null
+++ b/drivers/gator/daemon/Makefile
@@ -0,0 +1,40 @@
+#
+# Makefile for ARM Streamline - Gator Daemon
+#
+
+# Uncomment and define CROSS_COMPILE if it is not already defined
+# CROSS_COMPILE=/path/to/cross-compiler/arm-none-linux-gnueabi-
+ARCH=arm
+
+CPP=$(CROSS_COMPILE)g++
+
+# -g produces debugging information
+# -O3 maximum optimization
+# -O0 no optimization, used for debugging
+# -Wall enables most warnings
+# -Werror treats warnings as errors
+# -std=c++0x is the planned new c++ standard
+# -std=c++98 is the 1998 c++ standard
+# -march=armv5t is required to set the minimum architecture
+# -mthumb-interwork is required for interworking to ARM or Thumb stdlibc
+CFLAGS=-O3 -Wall -Werror -march=armv5t -mthumb-interwork
+TARGET=gatord
+CPP_SRC = $(wildcard *.cpp)
+TGT_OBJS = $(CPP_SRC:%.cpp=%.o)
+
+all: $(TARGET)
+
+%.o: %.cpp *.h
+ $(CPP) -c $(CFLAGS) -o $@ $<
+
+$(TARGET): convert $(TGT_OBJS)
+ $(CPP) -s -o $@ $(TGT_OBJS) -lc -lrt -lpthread
+ rm events_xml.h configuration_xml.h
+
+convert:
+ cat events_header.xml events-*\.xml events_footer.xml > events.xml
+ xxd -i events.xml > events_xml.h
+ xxd -i configuration.xml > configuration_xml.h
+
+clean:
+ rm -f *.o $(TARGET) events.xml events_xml.h configuration_xml.h
diff --git a/drivers/gator/daemon/OlySocket.cpp b/drivers/gator/daemon/OlySocket.cpp
new file mode 100644
index 00000000000..8a9ca970b94
--- /dev/null
+++ b/drivers/gator/daemon/OlySocket.cpp
@@ -0,0 +1,257 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <stdio.h>
+#ifdef WIN32
+#include <Winsock2.h>
+#else
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <netdb.h>
+#endif
+#include "OlySocket.h"
+#include "Logging.h"
+
+#ifdef WIN32
+#define CLOSE_SOCKET(x) closesocket(x)
+#define SHUTDOWN_RX_TX SD_BOTH
+#define snprintf _snprintf
+#else
+#define CLOSE_SOCKET(x) close(x)
+#define SHUTDOWN_RX_TX SHUT_RDWR
+#endif
+
+extern void handleException();
+
+OlySocket::OlySocket(int port, bool multiple) {
+#ifdef WIN32
+ WSADATA wsaData;
+ if (WSAStartup(0x0202, &wsaData) != 0) {
+ logg->logError(__FILE__, __LINE__, "Windows socket initialization failed");
+ handleException();
+ }
+#endif
+
+ if (multiple) {
+ createServerSocket(port);
+ } else {
+ createSingleServerConnection(port);
+ }
+}
+
+OlySocket::OlySocket(int port, char* host) {
+ fdServer = 0;
+ createClientSocket(host, port);
+}
+
+OlySocket::~OlySocket() {
+ if (mSocketID > 0) {
+ CLOSE_SOCKET(mSocketID);
+ }
+}
+
+void OlySocket::shutdownConnection() {
+ // Shutdown is primarily used to unblock other threads that are blocking on send/receive functions
+ shutdown(mSocketID, SHUTDOWN_RX_TX);
+}
+
+void OlySocket::closeSocket() {
+ // Used for closing an accepted socket but keeping the server socket active
+ if (mSocketID > 0) {
+ CLOSE_SOCKET(mSocketID);
+ mSocketID = -1;
+ }
+}
+
+void OlySocket::closeServerSocket() {
+ if (CLOSE_SOCKET(fdServer) != 0) {
+ logg->logError(__FILE__, __LINE__, "Failed to close server socket.");
+ handleException();
+ }
+ fdServer = 0;
+}
+
+void OlySocket::createClientSocket(char* hostname, int portno) {
+#ifdef WIN32
+ // TODO: Implement for Windows
+#else
+ char buf[32];
+ struct addrinfo hints, *res, *res0;
+
+ snprintf(buf, sizeof(buf), "%d", portno);
+ mSocketID = -1;
+ memset((void*)&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if (getaddrinfo(hostname, buf, &hints, &res0)) {
+ logg->logError(__FILE__, __LINE__, "Client socket failed to get address info for %s", hostname);
+ handleException();
+ }
+ for (res=res0; res!=NULL; res = res->ai_next) {
+ if ( res->ai_family != PF_INET || res->ai_socktype != SOCK_STREAM )
+ continue;
+ mSocketID = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (mSocketID < 0) {
+ continue;
+ }
+ if (connect(mSocketID, res->ai_addr, res->ai_addrlen) < 0) {
+ close(mSocketID);
+ mSocketID = -1;
+ }
+ if (mSocketID > 0) break;
+ }
+ freeaddrinfo(res0);
+ if (mSocketID <= 0) {
+ logg->logError(__FILE__, __LINE__, "Could not connect to client socket. Ensure ARM Streamline is running.");
+ handleException();
+ }
+#endif
+}
+
+void OlySocket::createSingleServerConnection(int port) {
+ createServerSocket(port);
+
+ mSocketID = acceptConnection();
+ closeServerSocket();
+}
+
+void OlySocket::createServerSocket(int port) {
+ // Create socket
+ fdServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (fdServer < 0) {
+ logg->logError(__FILE__, __LINE__, "Error creating server socket");
+ handleException();
+ }
+
+ // Enable address reuse, another solution would be to create the server socket once and only close it when the object exits
+ int on = 1;
+ if (setsockopt(fdServer, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on)) != 0) {
+ logg->logError(__FILE__, __LINE__, "Setting server socket options failed");
+ handleException();
+ }
+
+ // Create sockaddr_in structure, ensuring non-populated fields are zero
+ struct sockaddr_in sockaddr;
+ memset((void*)&sockaddr, 0, sizeof(struct sockaddr_in));
+ sockaddr.sin_family = AF_INET;
+ sockaddr.sin_port = htons(port);
+ sockaddr.sin_addr.s_addr = INADDR_ANY;
+
+ // Bind the socket to an address
+ if (bind(fdServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
+ logg->logError(__FILE__, __LINE__, "Binding of server socket failed.\nIs an instance already running?");
+ handleException();
+ }
+
+ // Listen for connections on this socket
+ if (listen(fdServer, 1) < 0) {
+ logg->logError(__FILE__, __LINE__, "Listening of server socket failed");
+ handleException();
+ }
+}
+
+// mSocketID is always set to the most recently accepted connection
+// The user of this class should maintain the different socket connections, e.g. by forking the process
+int OlySocket::acceptConnection() {
+ if (fdServer <= 0) {
+ logg->logError(__FILE__, __LINE__, "Attempting multiple connections on a single connection server socket or attempting to accept on a client socket");
+ handleException();
+ }
+
+ // Accept a connection, note that this call blocks until a client connects
+ mSocketID = accept(fdServer, NULL, NULL);
+ if (mSocketID < 0) {
+ logg->logError(__FILE__, __LINE__, "Socket acceptance failed");
+ handleException();
+ }
+ return mSocketID;
+}
+
+void OlySocket::send(char* buffer, int size) {
+ if (size <= 0 || buffer == NULL) {
+ return;
+ }
+
+ while (size > 0) {
+ int n = ::send(mSocketID, buffer, size, 0);
+ if (n < 0) {
+ logg->logError(__FILE__, __LINE__, "Socket send error");
+ handleException();
+ }
+ size -= n;
+ buffer += n;
+ }
+}
+
+// Returns the number of bytes received
+int OlySocket::receive(char* buffer, int size) {
+ if (size <= 0 || buffer == NULL) {
+ return 0;
+ }
+
+ int bytes = recv(mSocketID, buffer, size, 0);
+ if (bytes < 0) {
+ logg->logError(__FILE__, __LINE__, "Socket receive error");
+ handleException();
+ } else if (bytes == 0) {
+ logg->logMessage("Socket disconnected");
+ return -1;
+ }
+ return bytes;
+}
+
+// Receive exactly size bytes of data. Note, this function will block until all bytes are received
+int OlySocket::receiveNBytes(char* buffer, int size) {
+ int bytes = 0;
+ while (size > 0 && buffer != NULL) {
+ bytes = recv(mSocketID, buffer, size, 0);
+ if (bytes < 0) {
+ logg->logError(__FILE__, __LINE__, "Socket receive error");
+ handleException();
+ } else if (bytes == 0) {
+ logg->logMessage("Socket disconnected");
+ return -1;
+ }
+ buffer += bytes;
+ size -= bytes;
+ }
+ return bytes;
+}
+
+// Receive data until a carriage return, line feed, or null is encountered, or the buffer fills
+int OlySocket::receiveString(char* buffer, int size) {
+ int bytes_received = 0;
+ bool found = false;
+
+ if (buffer == 0)
+ return 0;
+
+ while (!found && bytes_received < size) {
+ // Receive a single character
+ int bytes = recv(mSocketID, &buffer[bytes_received], 1, 0);
+ if (bytes < 0) {
+ logg->logError(__FILE__, __LINE__, "Socket receive error");
+ handleException();
+ } else if (bytes == 0) {
+ logg->logMessage("Socket disconnected");
+ return -1;
+ }
+
+ // Replace carriage returns and line feeds with zero
+ if (buffer[bytes_received] == '\n' || buffer[bytes_received] == '\r' || buffer[bytes_received] == '\0') {
+ buffer[bytes_received] = '\0';
+ found = true;
+ }
+
+ bytes_received++;
+ }
+
+ return bytes_received;
+}
diff --git a/drivers/gator/daemon/OlySocket.h b/drivers/gator/daemon/OlySocket.h
new file mode 100644
index 00000000000..2fe6e59516f
--- /dev/null
+++ b/drivers/gator/daemon/OlySocket.h
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 __OLY_SOCKET_H__
+#define __OLY_SOCKET_H__
+
+#include <string.h>
+
+class OlySocket {
+public:
+ OlySocket(int port, bool multipleConnections = false);
+ OlySocket(int port, char* hostname);
+ ~OlySocket();
+ int acceptConnection();
+ void closeSocket();
+ void closeServerSocket();
+ void shutdownConnection();
+ void send(char* buffer, int size);
+ void sendString(const char* string) {send((char*)string, strlen(string));}
+ int receive(char* buffer, int size);
+ int receiveNBytes(char* buffer, int size);
+ int receiveString(char* buffer, int size);
+ char* getLastError() {return strError;}
+ int getSocketID() {return mSocketID;}
+private:
+ char* strError;
+ int mSocketID, fdServer;
+ void createClientSocket(char* hostname, int port);
+ void createSingleServerConnection(int port);
+ void createServerSocket(int port);
+};
+
+#endif //__OLY_SOCKET_H__
diff --git a/drivers/gator/daemon/OlyUtility.cpp b/drivers/gator/daemon/OlyUtility.cpp
new file mode 100644
index 00000000000..1b15d33d0e5
--- /dev/null
+++ b/drivers/gator/daemon/OlyUtility.cpp
@@ -0,0 +1,167 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <Windows.h>
+#endif
+
+#include "OlyUtility.h"
+
+OlyUtility* util = NULL;
+
+void OlyUtility::stringToLower(char* string) {
+ if (string == NULL)
+ return;
+
+ while (*string) {
+ *string = tolower(*string);
+ string++;
+ }
+}
+
+// Modifies fullpath with the path part including the trailing path separator
+int OlyUtility::getApplicationFullPath(char* fullpath, int sizeOfPath) {
+ memset(fullpath, 0, sizeOfPath);
+#ifdef WIN32
+ int length = GetModuleFileName(NULL, fullpath, sizeOfPath);
+#else
+ int length = readlink("/proc/self/exe", fullpath, sizeOfPath);
+#endif
+
+ if (length == sizeOfPath)
+ return -1;
+
+ fullpath[length] = 0;
+ fullpath = getPathPart(fullpath);
+
+ return 0;
+}
+
+char* OlyUtility::readFromDisk(const char* file, unsigned int *size, bool appendNull) {
+ // Open the file
+ FILE* pFile = fopen(file, "rb");
+ if (pFile==NULL) return NULL;
+
+ // Obtain file size
+ fseek(pFile , 0 , SEEK_END);
+ unsigned int lSize = ftell(pFile);
+ rewind(pFile);
+
+ // Allocate memory to contain the whole file
+ char* buffer = (char*)malloc(lSize + (int)appendNull);
+ if (buffer == NULL) return NULL;
+
+ // Copy the file into the buffer
+ if (fread(buffer, 1, lSize, pFile) != lSize) return NULL;
+
+ // Terminate
+ fclose(pFile);
+
+ if (appendNull)
+ buffer[lSize] = 0;
+
+ if (size)
+ *size = lSize;
+
+ return buffer;
+}
+
+int OlyUtility::writeToDisk(const char* path, const char* data) {
+ // Open the file
+ FILE* pFile = fopen(path, "wb");
+ if (pFile == NULL) return -1;
+
+ // Write the data to disk
+ if (fwrite(data, 1, strlen(data), pFile) != strlen(data)) return -1;
+
+ // Terminate
+ fclose(pFile);
+ return 0;
+}
+
+int OlyUtility::appendToDisk(const char* path, const char* data) {
+ // Open the file
+ FILE* pFile = fopen(path, "a");
+ if (pFile == NULL) return -1;
+
+ // Write the data to disk
+ if (fwrite(data, 1, strlen(data), pFile) != strlen(data)) return -1;
+
+ // Terminate
+ fclose(pFile);
+ return 0;
+}
+
+/**
+ * Copies the srcFile into dstFile in 1kB chunks.
+ * The dstFile will be overwritten if it exists.
+ * 0 is returned on an error; otherwise 1.
+ */
+#define TRANSFER_SIZE 1024
+int OlyUtility::copyFile(const char * srcFile, const char * dstFile) {
+ char* buffer = (char*)malloc(TRANSFER_SIZE);
+ FILE * f_src = fopen(srcFile,"rb");
+ if (!f_src) {
+ return 0;
+ }
+ FILE * f_dst = fopen(dstFile,"wb");
+ if (!f_dst) {
+ fclose(f_src);
+ return 0;
+ }
+ while (!feof(f_src)) {
+ int num_bytes_read = fread(buffer, 1, TRANSFER_SIZE, f_src);
+ if (num_bytes_read < TRANSFER_SIZE && !feof(f_src)) {
+ fclose(f_src);
+ fclose(f_dst);
+ return 0;
+ }
+ int num_bytes_written = fwrite(buffer, 1, num_bytes_read, f_dst);
+ if (num_bytes_written != num_bytes_read) {
+ fclose(f_src);
+ fclose(f_dst);
+ return 0;
+ }
+ }
+ fclose(f_src);
+ fclose(f_dst);
+ free(buffer);
+ return 1;
+}
+
+const char* OlyUtility::getFilePart(const char* path) {
+ const char* last_sep = strrchr(path, PATH_SEPARATOR);
+
+ // in case path is not a full path
+ if (last_sep == NULL) {
+ return path;
+ }
+
+ return (const char*)((int)last_sep + 1);
+}
+
+// getPathPart may modify the contents of path
+// returns the path including the trailing path separator
+char* OlyUtility::getPathPart(char* path) {
+ char* last_sep = strrchr(path, PATH_SEPARATOR);
+
+ // in case path is not a full path
+ if (last_sep == NULL) {
+ return 0;
+ }
+ *(char*)((int)last_sep + 1) = 0;
+
+ return (path);
+}
diff --git a/drivers/gator/daemon/OlyUtility.h b/drivers/gator/daemon/OlyUtility.h
new file mode 100644
index 00000000000..0fa021dc364
--- /dev/null
+++ b/drivers/gator/daemon/OlyUtility.h
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 OLY_UTILITY_H
+#define OLY_UTILITY_H
+
+#ifdef WIN32
+#define PATH_SEPARATOR '\\'
+#else
+#define PATH_SEPARATOR '/'
+#endif
+
+class OlyUtility {
+public:
+ OlyUtility() {};
+ ~OlyUtility() {};
+ void stringToLower(char* string);
+ int getApplicationFullPath(char* path, int sizeOfPath);
+ char* readFromDisk(const char* file, unsigned int *size = NULL, bool appendNull = true);
+ int writeToDisk(const char* path, const char* file);
+ int appendToDisk(const char* path, const char* file);
+ int copyFile(const char * srcFile, const char * dstFile);
+ const char* getFilePart(const char* path);
+ char* getPathPart(char* path);
+private:
+};
+
+extern OlyUtility* util;
+
+#endif // OLY_UTILITY_H
diff --git a/drivers/gator/daemon/RequestXML.cpp b/drivers/gator/daemon/RequestXML.cpp
new file mode 100644
index 00000000000..e8f24d2d25d
--- /dev/null
+++ b/drivers/gator/daemon/RequestXML.cpp
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) ARM Limited 2011-2012. 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 <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "RequestXML.h"
+#include "Logging.h"
+
+extern void handleException();
+
+static const char* TAG_REQUEST = "request";
+
+static const char* ATTR_PROTOCOL = "protocol";
+static const char* ATTR_EVENTS = "events";
+static const char* ATTR_CONFIGURATION = "configuration";
+static const char* ATTR_COUNTERS = "counters";
+static const char* ATTR_SESSION = "session";
+static const char* ATTR_CAPTURED = "captured";
+static const char* ATTR_DEFAULTS = "defaults";
+
+RequestXML::RequestXML(const char * str) {
+ parameters.protocol = false;
+ parameters.events = false;
+ parameters.configuration = false;
+ parameters.counters = false;
+ parameters.session = false;
+ parameters.captured = false;
+ parameters.defaults = false;
+
+ XMLReader reader(str);
+ char * tag = reader.nextTag();
+ while(tag != 0) {
+ if (strcmp(tag, TAG_REQUEST) == 0) {
+ requestTag(&reader);
+ return;
+ }
+ tag = reader.nextTag();
+ }
+
+ logg->logError(__FILE__, __LINE__, "No request tag found in the request.xml file");
+ handleException();
+}
+
+RequestXML::~RequestXML() {
+}
+
+void RequestXML::requestTag(XMLReader* in) {
+ parameters.protocol = in->getAttributeAsBoolean(ATTR_PROTOCOL, false);
+ parameters.events = in->getAttributeAsBoolean(ATTR_EVENTS, false);
+ parameters.configuration = in->getAttributeAsBoolean(ATTR_CONFIGURATION, false);
+ parameters.counters = in->getAttributeAsBoolean(ATTR_COUNTERS, false);
+ parameters.session = in->getAttributeAsBoolean(ATTR_SESSION, false);
+ parameters.captured = in->getAttributeAsBoolean(ATTR_CAPTURED, false);
+ parameters.defaults = in->getAttributeAsBoolean(ATTR_DEFAULTS, false);
+}
diff --git a/drivers/gator/daemon/RequestXML.h b/drivers/gator/daemon/RequestXML.h
new file mode 100644
index 00000000000..bebd04809ae
--- /dev/null
+++ b/drivers/gator/daemon/RequestXML.h
@@ -0,0 +1,33 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 REQUEST_XML_H
+#define REQUEST_XML_H
+
+#include "XMLReader.h"
+
+struct ConfigParameters {
+ bool protocol;
+ bool events;
+ bool configuration;
+ bool counters;
+ bool session;
+ bool captured;
+ bool defaults;
+};
+
+class RequestXML {
+public:
+ RequestXML(const char * str);
+ ~RequestXML();
+ ConfigParameters parameters;
+private:
+ void requestTag(XMLReader* in);
+};
+
+#endif // REQUEST_XML_H
diff --git a/drivers/gator/daemon/Sender.cpp b/drivers/gator/daemon/Sender.cpp
new file mode 100644
index 00000000000..9792c3677a3
--- /dev/null
+++ b/drivers/gator/daemon/Sender.cpp
@@ -0,0 +1,106 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "Sender.h"
+#include "Logging.h"
+#include "SessionData.h"
+
+extern void handleException();
+
+Sender::Sender(OlySocket* socket) {
+ dataFile = NULL;
+ dataSocket = NULL;
+
+ // Set up the socket connection
+ if (socket) {
+ char streamline[64] = {0};
+ dataSocket = socket;
+
+ // Receive magic sequence - can wait forever
+ // Streamline will send data prior to the magic sequence for legacy support, which should be ignored for v4+
+ while (strcmp("STREAMLINE", streamline) != 0) {
+ if (dataSocket->receiveString(streamline, sizeof(streamline)) == -1) {
+ logg->logError(__FILE__, __LINE__, "Socket disconnected");
+ handleException();
+ }
+ }
+
+ // Send magic sequence - must be done first, afterwhich error messages can be sent
+ char magic[] = {'G', 'A', 'T', 'O', 'R', '\n'};
+ dataSocket->send(magic, sizeof(magic));
+
+ gSessionData->mWaitingOnCommand = true;
+ logg->logMessage("Completed magic sequence");
+ }
+
+ pthread_mutex_init(&sendMutex, NULL);
+}
+
+Sender::~Sender() {
+ delete dataSocket;
+ dataSocket = NULL;
+ if (dataFile) {
+ fclose(dataFile);
+ }
+}
+
+void Sender::createDataFile(char* apcDir) {
+ if (apcDir == NULL)
+ return;
+
+ dataFileName = (char*)malloc(strlen(apcDir) + 12);
+ sprintf(dataFileName, "%s/0000000000", apcDir);
+ dataFile = fopen(dataFileName, "wb");
+ if (!dataFile) {
+ logg->logError(__FILE__, __LINE__, "Failed to open binary file: %s", dataFileName);
+ handleException();
+ }
+}
+
+void Sender::writeData(const char* data, int length, int type) {
+ if (length < 0 || (data == NULL && length > 0)) {
+ return;
+ }
+
+ // Multiple threads call writeData()
+ pthread_mutex_lock(&sendMutex);
+
+ // Send data over the socket connection
+ if (dataSocket) {
+ // Start alarm
+ alarm(8);
+
+ // Send data over the socket, sending the type and size first
+ logg->logMessage("Sending data with length %d", length);
+ dataSocket->send((char*)&type, 1);
+ dataSocket->send((char*)&length, sizeof(length));
+ dataSocket->send((char*)data, length);
+
+ // Stop alarm
+ alarm(0);
+ }
+
+ // Write data to disk as long as it is not meta data
+ if (dataFile && type == RESPONSE_APC_DATA) {
+ logg->logMessage("Writing data with length %d", length);
+ // Send data to the data file, storing the size first
+ if ((fwrite((char*)&length, 1, sizeof(length), dataFile) != sizeof(length)) || (fwrite(data, 1, length, dataFile) != (unsigned int)length)) {
+ logg->logError(__FILE__, __LINE__, "Failed writing binary file %s", dataFileName);
+ handleException();
+ }
+ }
+
+ pthread_mutex_unlock(&sendMutex);
+}
diff --git a/drivers/gator/daemon/Sender.h b/drivers/gator/daemon/Sender.h
new file mode 100644
index 00000000000..3444b852b01
--- /dev/null
+++ b/drivers/gator/daemon/Sender.h
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 __SENDER_H__
+#define __SENDER_H__
+
+#include <stdio.h>
+#include <pthread.h>
+#include "OlySocket.h"
+
+enum {
+ RESPONSE_END = 0, // unused
+ RESPONSE_XML = 1,
+ RESPONSE_APC_DATA = 3,
+ RESPONSE_ACK = 4,
+ RESPONSE_NAK = 5,
+ RESPONSE_ERROR = 0xFF
+};
+
+class Sender {
+public:
+ Sender(OlySocket* socket);
+ ~Sender();
+ void writeData(const char* data, int length, int type);
+ void createDataFile(char* apcDir);
+private:
+ OlySocket* dataSocket;
+ FILE* dataFile;
+ char* dataFileName;
+ pthread_mutex_t sendMutex;
+};
+
+#endif //__SENDER_H__
diff --git a/drivers/gator/daemon/SessionData.cpp b/drivers/gator/daemon/SessionData.cpp
new file mode 100644
index 00000000000..4adcfcd6c20
--- /dev/null
+++ b/drivers/gator/daemon/SessionData.cpp
@@ -0,0 +1,103 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <string.h>
+#include "SessionData.h"
+#include "SessionXML.h"
+#include "Logging.h"
+extern void handleException();
+
+SessionData* gSessionData = NULL;
+
+SessionData::SessionData() {
+ initialize();
+}
+
+SessionData::~SessionData() {
+}
+
+void SessionData::initialize() {
+ mWaitingOnCommand = false;
+ mSessionIsActive = false;
+ mLocalCapture = false;
+ mOneShot = false;
+ strcpy(mCoreName, "unknown");
+ configurationXMLPath = NULL;
+ apcDir = NULL;
+ mSampleRate = 0;
+ mDuration = 0;
+ mBytes = 0;
+ mBacktraceDepth = 0;
+ mTotalBufferSize = 0;
+ mCores = 1;
+
+ initializeCounters();
+}
+
+void SessionData::initializeCounters() {
+ // PMU Counters
+ for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) {
+ mPerfCounterType[i][0] = 0;
+ mPerfCounterTitle[i][0] = 0;
+ mPerfCounterName[i][0] = 0;
+ mPerfCounterDescription[i][0] = 0;
+ mPerfCounterEnabled[i] = 0;
+ mPerfCounterEvent[i] = 0;
+ mPerfCounterColor[i] = 0;
+ mPerfCounterKey[i] = 0;
+ mPerfCounterCount[i] = 0;
+ mPerfCounterOperation[i][0] = 0;
+ mPerfCounterPerCPU[i] = false;
+ mPerfCounterEBSCapable[i] = false;
+ }
+}
+
+void SessionData::parseSessionXML(char* xmlString) {
+ SessionXML session(xmlString);
+ session.parse();
+
+ // Parameter error checking
+ if (session.parameters.output_path == 0 && session.parameters.target_path == 0) {
+ logg->logError(__FILE__, __LINE__, "No capture path (target or host) was provided.");
+ handleException();
+ } else if (gSessionData->mLocalCapture && session.parameters.target_path == 0) {
+ logg->logError(__FILE__, __LINE__, "Missing target_path tag in session xml required for a local capture.");
+ handleException();
+ }
+
+ // Set session data values
+ if (strcmp(session.parameters.sample_rate, "high") == 0) {
+ gSessionData->mSampleRate = 10000;
+ } else if (strcmp(session.parameters.sample_rate, "normal") == 0) {
+ gSessionData->mSampleRate = 1000;
+ } else { // "low"
+ gSessionData->mSampleRate = 100;
+ }
+ gSessionData->mBacktraceDepth = session.parameters.call_stack_unwinding == true ? 128 : 0;
+ gSessionData->mDuration = session.parameters.duration;
+
+ // Determine buffer size (in MB) based on buffer mode
+ gSessionData->mOneShot = true;
+ if (strcmp(session.parameters.buffer_mode, "streaming") == 0) {
+ gSessionData->mOneShot = false;
+ gSessionData->mTotalBufferSize = 1;
+ } else if (strcmp(session.parameters.buffer_mode, "small") == 0) {
+ gSessionData->mTotalBufferSize = 1;
+ } else if (strcmp(session.parameters.buffer_mode, "normal") == 0) {
+ gSessionData->mTotalBufferSize = 4;
+ } else if (strcmp(session.parameters.buffer_mode, "large") == 0) {
+ gSessionData->mTotalBufferSize = 16;
+ } else {
+ logg->logError(__FILE__, __LINE__, "Invalid value for buffer mode in session xml.");
+ handleException();
+ }
+
+ gSessionData->images = session.parameters.images;
+ gSessionData->target_path = session.parameters.target_path;
+ gSessionData->title = session.parameters.title;
+}
diff --git a/drivers/gator/daemon/SessionData.h b/drivers/gator/daemon/SessionData.h
new file mode 100644
index 00000000000..cc188f8e694
--- /dev/null
+++ b/drivers/gator/daemon/SessionData.h
@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 SESSION_DATA_H
+#define SESSION_DATA_H
+
+#define MAX_PERFORMANCE_COUNTERS 50
+#define MAX_STRING_LEN 80
+#define MAX_DESCRIPTION_LEN 400
+
+#define PROTOCOL_VERSION 8
+#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions
+
+struct ImageLinkList {
+ char *path;
+ struct ImageLinkList *next;
+};
+
+class SessionData {
+public:
+ SessionData();
+ ~SessionData();
+ void initialize();
+ void initializeCounters();
+ void parseSessionXML(char* xmlString);
+
+ char mCoreName[MAX_STRING_LEN];
+ struct ImageLinkList *images;
+ char* configurationXMLPath;
+ char* target_path;
+ char* apcDir;
+ char* title;
+
+ bool mWaitingOnCommand;
+ bool mSessionIsActive;
+ bool mLocalCapture;
+ bool mOneShot; // halt processing of the driver data until profiling is complete or the buffer is filled
+
+ int mBacktraceDepth;
+ int mTotalBufferSize; // approximate number of MB to use for the entire collection buffer, the actual amount is a multiple based on a buffer size retrieved from the driver
+ int mSampleRate;
+ int mDuration;
+ int mCores;
+ int mBytes;
+
+ // PMU Counters
+ char mPerfCounterType[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
+ char mPerfCounterTitle[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
+ char mPerfCounterName[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
+ char mPerfCounterDescription[MAX_PERFORMANCE_COUNTERS][MAX_DESCRIPTION_LEN];
+ int mPerfCounterEnabled[MAX_PERFORMANCE_COUNTERS];
+ int mPerfCounterEvent[MAX_PERFORMANCE_COUNTERS];
+ int mPerfCounterColor[MAX_PERFORMANCE_COUNTERS];
+ int mPerfCounterCount[MAX_PERFORMANCE_COUNTERS];
+ int mPerfCounterKey[MAX_PERFORMANCE_COUNTERS];
+ bool mPerfCounterPerCPU[MAX_PERFORMANCE_COUNTERS];
+ bool mPerfCounterEBSCapable[MAX_PERFORMANCE_COUNTERS];
+ char mPerfCounterOperation[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
+};
+
+extern SessionData* gSessionData;
+
+#endif // SESSION_DATA_H
diff --git a/drivers/gator/daemon/SessionXML.cpp b/drivers/gator/daemon/SessionXML.cpp
new file mode 100644
index 00000000000..4604d7cf193
--- /dev/null
+++ b/drivers/gator/daemon/SessionXML.cpp
@@ -0,0 +1,119 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "SessionXML.h"
+#include "Logging.h"
+
+extern void handleException();
+
+static const char* TAG_SESSION = "session";
+static const char* TAG_IMAGE = "image";
+
+static const char* ATTR_VERSION = "version";
+static const char* ATTR_TITLE = "title";
+static const char* ATTR_UUID = "uuid";
+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_TARGET_PATH = "target_path";
+static const char* ATTR_OUTPUT_PATH = "output_path";
+static const char* ATTR_DURATION = "duration";
+static const char* ATTR_PATH = "path";
+
+SessionXML::SessionXML(const char * str) {
+ parameters.title = 0;
+ parameters.uuid[0] = 0;
+ parameters.target_path = 0;
+ parameters.output_path = 0;
+ parameters.buffer_mode[0] = 0;
+ parameters.sample_rate[0] = 0;
+ parameters.duration = 0;
+ parameters.call_stack_unwinding = false;
+ parameters.images = NULL;
+ mPath = 0;
+ mSessionXML = (char*)str;
+ logg->logMessage(mSessionXML);
+}
+
+SessionXML::~SessionXML() {
+ if (mPath != 0) {
+ free(mSessionXML);
+ }
+}
+
+void SessionXML::parse() {
+ XMLReader reader(mSessionXML);
+ char * tag = reader.nextTag();
+ while(tag != 0) {
+ if (strcmp(tag, TAG_SESSION) == 0) {
+ sessionTag(&reader);
+ return;
+ }
+ tag = reader.nextTag();
+ }
+
+ logg->logError(__FILE__, __LINE__, "No session tag found in the session.xml file");
+ handleException();
+}
+
+void SessionXML::sessionTag(XMLReader* in) {
+ char* tempBuffer = (char*)malloc(PATH_MAX);
+ int version = in->getAttributeAsInteger(ATTR_VERSION, 0);
+ if (version != 1) {
+ logg->logError(__FILE__, __LINE__, "Invalid session.xml version: %d", version);
+ handleException();
+ }
+
+ in->getAttribute(ATTR_TITLE, tempBuffer, PATH_MAX, "unnamed");
+ parameters.title = strdup(tempBuffer); // freed when the child process exits
+ if (parameters.title == NULL) {
+ logg->logError(__FILE__, __LINE__, "failed to allocate parameters.title (%d bytes)", strlen(tempBuffer));
+ handleException();
+ }
+ in->getAttribute(ATTR_UUID, parameters.uuid, sizeof(parameters.uuid), "");
+ parameters.duration = in->getAttributeAsInteger(ATTR_DURATION, 0);
+ parameters.call_stack_unwinding = in->getAttributeAsBoolean(ATTR_CALL_STACK_UNWINDING, true);
+ in->getAttribute(ATTR_BUFFER_MODE, parameters.buffer_mode, sizeof(parameters.buffer_mode), "normal");
+ in->getAttribute(ATTR_SAMPLE_RATE, parameters.sample_rate, sizeof(parameters.sample_rate), "");
+ in->getAttribute(ATTR_TARGET_PATH, tempBuffer, PATH_MAX, "");
+ parameters.target_path = strdup(tempBuffer); // freed when the child process exits
+ if (parameters.target_path == NULL) {
+ logg->logError(__FILE__, __LINE__, "failed to allocate parameters.target_path (%d bytes)", strlen(tempBuffer));
+ handleException();
+ }
+ in->getAttribute(ATTR_OUTPUT_PATH, tempBuffer, PATH_MAX, "");
+ parameters.output_path = strdup(tempBuffer); // freed when the child process exits
+ if (parameters.output_path == NULL) {
+ logg->logError(__FILE__, __LINE__, "failed to allocate parameters.output_path (%d bytes)", strlen(tempBuffer));
+ handleException();
+ }
+
+ free(tempBuffer);
+
+ char * tag = in->nextTag();
+ while(tag != 0) {
+ if (strcmp(tag, TAG_IMAGE) == 0) {
+ sessionImage(in);
+ }
+ tag = in->nextTag();
+ }
+}
+
+void SessionXML::sessionImage(XMLReader* in) {
+ int length = in->getAttributeLength(ATTR_PATH);
+ struct ImageLinkList *image;
+
+ image = (struct ImageLinkList *)malloc(sizeof(struct ImageLinkList));
+ image->path = (char *)malloc(length + 1);
+ in->getAttribute(ATTR_PATH, image->path, length + 1, "");
+ image->next = parameters.images;
+ parameters.images = image;
+}
diff --git a/drivers/gator/daemon/SessionXML.h b/drivers/gator/daemon/SessionXML.h
new file mode 100644
index 00000000000..4649685bc9e
--- /dev/null
+++ b/drivers/gator/daemon/SessionXML.h
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 SESSION_XML_H
+#define SESSION_XML_H
+
+#include "XMLReader.h"
+#include "SessionData.h"
+
+struct ConfigParameters {
+ char* title; // status title
+ char uuid[64]; // universal unique identifier
+ char* target_path; // target path of where to write to disk
+ char* output_path; // host path of where to write to disk
+ 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
+ struct ImageLinkList *images; // linked list of image strings
+};
+
+class SessionXML {
+public:
+ SessionXML(const char * str);
+ ~SessionXML();
+ void parse();
+ ConfigParameters parameters;
+private:
+ char* mSessionXML;
+ char* mPath;
+ void sessionTag(XMLReader* in);
+ void sessionImage(XMLReader* in);
+};
+
+#endif // SESSION_XML_H
diff --git a/drivers/gator/daemon/StreamlineSetup.cpp b/drivers/gator/daemon/StreamlineSetup.cpp
new file mode 100644
index 00000000000..5662ee8c76f
--- /dev/null
+++ b/drivers/gator/daemon/StreamlineSetup.cpp
@@ -0,0 +1,321 @@
+/**
+ * Copyright (C) ARM Limited 2011-2012. 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 <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "XMLOut.h"
+#include "Sender.h"
+#include "Logging.h"
+#include "XMLReader.h"
+#include "RequestXML.h"
+#include "OlyUtility.h"
+#include "SessionData.h"
+#include "CapturedXML.h"
+#include "StreamlineSetup.h"
+#include "ConfigurationXML.h"
+
+extern void handleException();
+
+static const char* TAG_SESSION = "session";
+static const char* TAG_CONFIGURATIONS = "configurations";
+
+StreamlineSetup::StreamlineSetup(OlySocket* s) {
+ bool ready = false;
+ char *data = NULL;
+ int type;
+
+ socket = s;
+ mSessionXML = NULL;
+
+ // Receive commands from Streamline (master)
+ while (!ready) {
+ // receive command over socket
+ gSessionData->mWaitingOnCommand = true;
+ data = readCommand(&type);
+
+ // parse and handle data
+ switch (type) {
+ case COMMAND_REQUEST_XML:
+ handleRequest(data);
+ break;
+ case COMMAND_DELIVER_XML:
+ handleDeliver(data);
+ break;
+ case COMMAND_APC_START:
+ logg->logMessage("Received apc start request");
+ ready = true;
+ break;
+ case COMMAND_APC_STOP:
+ logg->logMessage("Received apc stop request before apc start request");
+ exit(0);
+ break;
+ case COMMAND_DISCONNECT:
+ logg->logMessage("Received disconnect command");
+ exit(0);
+ break;
+ case COMMAND_PING:
+ logg->logMessage("Received ping command");
+ sendData(NULL, 0, RESPONSE_ACK);
+ break;
+ default:
+ logg->logError(__FILE__, __LINE__, "Target error: Unknown command type, %d", type);
+ handleException();
+ }
+
+ delete(data);
+ }
+}
+
+StreamlineSetup::~StreamlineSetup() {
+ if (mSessionXML)
+ free(mSessionXML);
+}
+
+char* StreamlineSetup::readCommand(int* command) {
+ char type;
+ char* data;
+ int response, length;
+
+ // receive type
+ response = socket->receiveNBytes(&type, sizeof(type));
+
+ // After receiving a single byte, we are no longer waiting on a command
+ gSessionData->mWaitingOnCommand = false;
+
+ if (response < 0) {
+ logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect");
+ handleException();
+ }
+
+ // receive length
+ response = socket->receiveNBytes((char*)&length, sizeof(length));
+ if (response < 0) {
+ logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect");
+ handleException();
+ }
+
+ // add artificial limit
+ if ((length < 0) || length > 1024 * 1024) {
+ logg->logError(__FILE__, __LINE__, "Target error: Invalid length received, %d", length);
+ handleException();
+ }
+
+ // allocate memory to contain the xml file, size of zero returns a zero size object
+ data = (char*)calloc(length + 1, 1);
+ if (data == NULL) {
+ logg->logError(__FILE__, __LINE__, "Unable to allocate memory for xml");
+ handleException();
+ }
+
+ // receive data
+ response = socket->receiveNBytes(data, length);
+ if (response < 0) {
+ logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect");
+ handleException();
+ }
+
+ // null terminate the data for string parsing
+ if (length > 0) {
+ data[length] = 0;
+ }
+
+ *command = type;
+ return data;
+}
+
+void StreamlineSetup::handleRequest(char* xml) {
+ RequestXML request(xml);
+
+ if (request.parameters.protocol) {
+ sendProtocol();
+ logg->logMessage("Sent protocol xml response");
+ } else if (request.parameters.events) {
+ sendEvents();
+ logg->logMessage("Sent events xml response");
+ } else if (request.parameters.configuration) {
+ sendConfiguration();
+ logg->logMessage("Sent configuration xml response");
+ } else if (request.parameters.counters) {
+ sendCounters();
+ logg->logMessage("Sent counters xml response");
+ } else if (request.parameters.session) {
+ sendData(mSessionXML, strlen(mSessionXML), RESPONSE_XML);
+ logg->logMessage("Sent session xml response");
+ } else if (request.parameters.captured) {
+ CapturedXML capturedXML;
+ const char* capturedText = capturedXML.getXML();
+ sendData(capturedText, strlen(capturedText), RESPONSE_XML);
+ logg->logMessage("Sent captured xml response");
+ } else if (request.parameters.defaults) {
+ sendDefaults();
+ logg->logMessage("Sent default configuration xml response");
+ } else {
+ char error[] = "Unknown request";
+ sendData(error, strlen(error), RESPONSE_NAK);
+ logg->logMessage("Received unknown request:\n%s", xml);
+ }
+}
+
+typedef enum {UNKNOWN, SESSION_XML, CONFIGURATION_XML} delivery_type_t;
+void StreamlineSetup::handleDeliver(char* xml) {
+ delivery_type_t type = UNKNOWN;
+
+ // Determine xml type
+ XMLReader reader(xml);
+ char * tag = reader.nextTag();
+ while(tag != 0) {
+ if (strcmp(tag, TAG_SESSION) == 0) {
+ type = SESSION_XML;
+ break;
+ } else if (strcmp(tag, TAG_CONFIGURATIONS) == 0) {
+ type = CONFIGURATION_XML;
+ break;
+ }
+ tag = reader.nextTag();
+ }
+
+ switch (type) {
+ case UNKNOWN:
+ logg->logMessage("Received unknown delivery type: %d", type);
+ sendData(NULL, 0, RESPONSE_NAK);
+ break;
+ case SESSION_XML:
+ // Parse the session xml
+ gSessionData->parseSessionXML(xml);
+
+ // Save xml
+ mSessionXML = strdup(xml);
+ if (mSessionXML == NULL) {
+ logg->logError(__FILE__, __LINE__, "malloc failed for size %d", strlen(xml) + 1);
+ handleException();
+ }
+ sendData(NULL, 0, RESPONSE_ACK);
+ logg->logMessage("Received session xml");
+ break;
+ case CONFIGURATION_XML:
+ writeConfiguration(xml);
+ sendData(NULL, 0, RESPONSE_ACK);
+ logg->logMessage("Received configuration xml");
+ break;
+ }
+}
+
+void StreamlineSetup::sendData(const char* data, int length, int type) {
+ socket->send((char*)&type, 1);
+ socket->send((char*)&length, sizeof(length));
+ socket->send((char*)data, length);
+}
+
+void StreamlineSetup::sendProtocol() {
+ XMLOut out;
+ out.xmlHeader();
+
+ out.startElement("protocol");
+ out.attributeInt("version", PROTOCOL_VERSION);
+ out.endElement("protocol");
+
+ sendString(out.getXmlString(), RESPONSE_XML);
+}
+
+void StreamlineSetup::sendEvents() {
+#include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len
+ char* path = (char*)malloc(PATH_MAX);;
+ char* buffer;
+ unsigned int size = 0;
+
+ util->getApplicationFullPath(path, PATH_MAX);
+ strncat(path, "events.xml", PATH_MAX - strlen(path) - 1);
+ buffer = util->readFromDisk(path, &size);
+ if (buffer == NULL) {
+ logg->logMessage("Unable to locate events.xml, using default");
+ buffer = (char*)events_xml;
+ size = events_xml_len;
+ }
+
+ sendData(buffer, size, RESPONSE_XML);
+ if (buffer != (char*)events_xml) {
+ free(buffer);
+ }
+ free(path);
+}
+
+void StreamlineSetup::sendConfiguration() {
+ ConfigurationXML xml;
+
+ const char* string = xml.getConfigurationXML();
+ sendData(string, strlen(string), RESPONSE_XML);
+}
+
+void StreamlineSetup::sendDefaults() {
+#include "configuration_xml.h" // defines and initializes char configuration_xml[] and int configuration_xml_len
+ // Send the config built into the binary
+ char* xml = (char*)configuration_xml;
+ unsigned int size = configuration_xml_len;
+
+ // Artificial size restriction
+ if (size > 1024*1024) {
+ logg->logError(__FILE__, __LINE__, "Corrupt default configuration file");
+ handleException();
+ }
+
+ sendData(xml, size, RESPONSE_XML);
+}
+
+#include <dirent.h>
+void StreamlineSetup::sendCounters() {
+ XMLOut out;
+ struct dirent *ent;
+
+ // counters.xml is simply a file listing of /dev/gator/events
+ DIR* dir = opendir("/dev/gator/events");
+ if (dir == NULL) {
+ logg->logError(__FILE__, __LINE__, "Cannot create counters.xml since unable to read /dev/gator/events");
+ handleException();
+ }
+
+ out.xmlHeader();
+ out.startElement("counters");
+ while ((ent = readdir(dir)) != NULL) {
+ // skip hidden files, current dir, and parent dir
+ if (ent->d_name[0] == '.')
+ continue;
+ out.startElement("counter");
+ out.attributeString("name", ent->d_name);
+ out.endElement("counter");
+ }
+ out.endElement("counters");
+ closedir (dir);
+
+ sendString(out.getXmlString(), RESPONSE_XML);
+}
+
+void StreamlineSetup::writeConfiguration(char* xml) {
+ char* path = (char*)malloc(PATH_MAX);
+
+ if (gSessionData->configurationXMLPath) {
+ strncpy(path, gSessionData->configurationXMLPath, PATH_MAX);
+ } else {
+ util->getApplicationFullPath(path, PATH_MAX);
+ strncat(path, "configuration.xml", PATH_MAX - strlen(path) - 1);
+ }
+
+ if (util->writeToDisk(path, xml) < 0) {
+ logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify write permissions to this path.", path);
+ handleException();
+ }
+
+ // Re-populate gSessionData with the configuration, as it has now changed
+ new ConfigurationXML();
+ free(path);
+}
diff --git a/drivers/gator/daemon/StreamlineSetup.h b/drivers/gator/daemon/StreamlineSetup.h
new file mode 100644
index 00000000000..10327e00bc7
--- /dev/null
+++ b/drivers/gator/daemon/StreamlineSetup.h
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 __STREAMLINE_SETUP_H__
+#define __STREAMLINE_SETUP_H__
+
+#include "OlySocket.h"
+
+// Commands from Streamline
+enum {
+ COMMAND_REQUEST_XML = 0,
+ COMMAND_DELIVER_XML = 1,
+ COMMAND_APC_START = 2,
+ COMMAND_APC_STOP = 3,
+ COMMAND_DISCONNECT = 4,
+ COMMAND_PING = 5
+};
+
+class StreamlineSetup {
+public:
+ StreamlineSetup(OlySocket *socket);
+ ~StreamlineSetup();
+private:
+ int numConnections;
+ OlySocket* socket;
+ char* mSessionXML;
+
+ char* readCommand(int*);
+ void handleRequest(char* xml);
+ void handleDeliver(char* xml);
+ void sendData(const char* data, int length, int type);
+ void sendString(const char* string, int type) {sendData(string, strlen(string), type);}
+ void sendProtocol();
+ void sendEvents();
+ void sendConfiguration();
+ void sendDefaults();
+ void sendCounters();
+ void writeConfiguration(char* xml);
+};
+
+#endif //__STREAMLINE_SETUP_H__
diff --git a/drivers/gator/daemon/XMLOut.cpp b/drivers/gator/daemon/XMLOut.cpp
new file mode 100644
index 00000000000..c194fc0042d
--- /dev/null
+++ b/drivers/gator/daemon/XMLOut.cpp
@@ -0,0 +1,175 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include "XMLOut.h"
+
+XMLOut::XMLOut() {
+ indent = 0;
+ incomplete = false;
+ xml_string[0] = 0;
+}
+
+XMLOut::~XMLOut() {
+}
+
+void XMLOut::writeTabs() {
+ for (int i = 0; i < indent; i++) {
+ writeData(" ");
+ }
+}
+
+void XMLOut::encodeAttributeData(const char* data) {
+ if (data) {
+ while (*data) {
+ char ch = *data++;
+
+ if (ch == '<') {
+ writeData("&lt;");
+ } else if (ch == '>') {
+ writeData("&gt;");
+ } else if (ch == '&') {
+ writeData("&amp;");
+ } else if (ch == '"') {
+ writeData("&quot;");
+ } else if (ch == '\'') {
+ writeData("&apos;");
+ } else if (ch >= ' ' && ch <= '~') {
+ writeData("%c",ch);
+ } else {
+ writeData("&#%u;",(unsigned int)ch);
+ }
+ }
+ }
+}
+
+void XMLOut::writeData(const char *format, ...) {
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(temp_buffer, sizeof(temp_buffer), format, ap);
+ va_end(ap);
+
+ strncat(xml_string, temp_buffer, sizeof(xml_string) - strlen(xml_string) - 1);
+}
+
+const XMLOut & XMLOut::xmlHeader(void) {
+ writeData("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ incomplete = false;
+ return *this;
+}
+
+const XMLOut & XMLOut::comment(const char* text, const bool newline) {
+ if (incomplete) {
+ writeData(">\n");
+ }
+ writeTabs();
+ writeData("<!-- %s -->", text);
+ if (newline) {
+ writeData("\n");
+ }
+ incomplete = false;
+ return *this;
+}
+
+const XMLOut & XMLOut::startElement(const char* tag) {
+ if (incomplete) {
+ writeData(">\n");
+ }
+ writeTabs();
+ writeData("<%s", tag);
+ incomplete = true;
+ indent++;
+ return *this;
+}
+
+const XMLOut & XMLOut::startElement(const char* tag, int index) {
+ if (incomplete) {
+ writeData(">\n");
+ }
+ writeTabs();
+ writeData("<!-- %d -->", index);
+ writeData("<%s", tag);
+ incomplete = true;
+ indent++;
+ return *this;
+}
+
+const XMLOut & XMLOut::endElement(const char* tag) {
+ indent--;
+ if (indent < 0) {
+ indent = 0;
+ }
+ if (incomplete) {
+ writeData("/>\n");
+ incomplete = false;
+ } else {
+ writeTabs();
+ writeData("</%s>\n", tag);
+ }
+ return *this;
+}
+
+const XMLOut & XMLOut::attributeString(const char* name, const char* value) {
+ writeData(" %s=\"", name);
+ encodeAttributeData(value);
+ writeData("\"");
+ return *this;
+}
+
+const XMLOut & XMLOut::attributeInt(const char* name, int value) {
+ writeData(" %s=\"%d\"", name, value);
+ return *this;
+}
+
+const XMLOut & XMLOut::attributeUInt(const char* name, unsigned int value) {
+ writeData(" %s=\"%u\"", name, value);
+ return *this;
+}
+
+const XMLOut & XMLOut::attributeLong(const char* name, long value) {
+ writeData(" %s=\"%ld\"", name, value);
+ return *this;
+}
+
+const XMLOut & XMLOut::attributeULong(const char* name, unsigned long value) {
+ writeData(" %s=\"%lu\"", name, value);
+ return *this;
+}
+
+const XMLOut & XMLOut::attributeLongLong(const char* name, long long value) {
+ writeData(" %s=\"%lld\"", name, value);
+ return *this;
+}
+
+const XMLOut & XMLOut::attributeULongLong(const char* name, unsigned long long value) {
+ writeData(" %s=\"%llu\"", name, value);
+ return *this;
+}
+
+const XMLOut & XMLOut::attributeDouble(const char* name, double value) {
+ writeData(" %s=\"%f\"", name, value);
+ return *this;
+}
+
+const XMLOut & XMLOut::attributeBool(const char* name, bool value) {
+ writeData(" %s=\"%s\"", name, value ? "yes" : "no");
+ return *this;
+}
+
+const XMLOut & XMLOut::attributeHex4(const char* name, int value) {
+ writeData(" %s=\"0x%04x\"", name, value);
+ return *this;
+}
+
+const XMLOut & XMLOut::attributeHex8(const char* name, int value) {
+ writeData(" %s=\"0x%08x\"", name, value);
+ return *this;
+}
diff --git a/drivers/gator/daemon/XMLOut.h b/drivers/gator/daemon/XMLOut.h
new file mode 100644
index 00000000000..3af253dbe83
--- /dev/null
+++ b/drivers/gator/daemon/XMLOut.h
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 __XMLOUT_H
+#define __XMLOUT_H
+
+class XMLOut {
+ int indent;
+ bool incomplete;
+ char temp_buffer[4096]; // arbitrarilly large buffer to hold variable arguments
+ char xml_string[64*1024]; // arbitrarilly large buffer to hold an xml file output by the daemon
+
+ void writeTabs();
+ void encodeAttributeData(const char* data);
+ void writeData(const char *format, ...);
+
+public:
+ XMLOut();
+ ~XMLOut();
+ char* getXmlString() {return xml_string;}
+ void clearXmlString() {xml_string[0]=0;}
+ const XMLOut & xmlHeader(void);
+ const XMLOut & comment(const char* text, const bool newline);
+ const XMLOut & startElement(const char* tag);
+ const XMLOut & startElement(const char* tag, int index);
+ const XMLOut & endElement(const char* tag);
+ const XMLOut & attributeString(const char* name, const char* value);
+ const XMLOut & attributeInt(const char* name, int value);
+ const XMLOut & attributeUInt(const char* name, unsigned int value);
+ const XMLOut & attributeLong(const char* name, long value);
+ const XMLOut & attributeULong(const char* name, unsigned long value);
+ const XMLOut & attributeLongLong(const char* name, long long value);
+ const XMLOut & attributeULongLong(const char* name, unsigned long long value);
+ const XMLOut & attributeDouble(const char* name, double value);
+ const XMLOut & attributeBool(const char* name, bool value);
+ const XMLOut & attributeHex4(const char* name, int value);
+ const XMLOut & attributeHex8(const char* name, int value);
+};
+
+#endif // __XMLOUT_H
diff --git a/drivers/gator/daemon/XMLReader.cpp b/drivers/gator/daemon/XMLReader.cpp
new file mode 100644
index 00000000000..77c76e29d73
--- /dev/null
+++ b/drivers/gator/daemon/XMLReader.cpp
@@ -0,0 +1,164 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "XMLReader.h"
+extern void handleException();
+
+XMLReader::XMLReader(const char* xmlstring) {
+ mPtr = (char*)xmlstring;
+ mNoMore = false;
+ mFirstTime = true;
+}
+
+XMLReader::~XMLReader() {
+}
+
+char* XMLReader::nextTag() {
+ static char tag[128]; // arbitrarily set max tag size to 127 characters + nul
+
+ // Check if past the end of the root tag
+ if (mNoMore) return NULL;
+
+ // Find start character
+ mPtr = strchr(mPtr, '<');
+
+ if (mPtr == NULL) return mPtr;
+
+ // Skip tag if it begins with <?
+ if (mPtr[1] == '?') {
+ mPtr++;
+ return nextTag();
+ }
+
+ // Find end of tag name
+ mPtr++;
+ char* end = strchr(mPtr, ' ');
+ if (end == NULL)
+ end = strchr(mPtr, '>');
+ if (end == NULL)
+ return 0;
+
+ // Check if tag has no attributes
+ char* tagend = strchr(mPtr, '>');
+ if (tagend < end) end = tagend;
+
+ // Check the tag name length
+ unsigned int length = (int)end - (int)mPtr;
+ if (length > sizeof(tag) - 1) {
+ // tag name too long, skip it
+ return nextTag();
+ }
+
+ // Return the tag name
+ strncpy(tag, mPtr, length);
+ tag[length] = 0;
+
+ // Mark the root tag
+ if (mFirstTime) {
+ mEndXML[0] = '/';
+ strcpy(&mEndXML[1], tag);
+ mFirstTime = false;
+ } else if (strcmp(tag, mEndXML) == 0) {
+ // End of root tag found
+ mNoMore = true;
+ }
+
+ return tag;
+}
+
+void XMLReader::getAttribute(const char* name, char* value, int maxSize, const char* defValue) {
+ char searchString[128];
+
+ // Set up default
+ strncpy(value, defValue, maxSize - 1);
+ value[maxSize - 1] = 0;
+
+ // Determine search string by ending the name with ="
+ if (strlen(name) > sizeof(searchString) - 3) return;
+ strcpy(searchString, name);
+ strcat(searchString, "=\"");
+
+ // Find the beginning of the attribute's search string
+ char* begin = strstr(mPtr, searchString);
+ if (begin == NULL) return;
+
+ // Find the beginning of the attribute's value
+ begin += strlen(searchString);
+
+ // Find the end of the current tag to make sure the attribute exists within the tag
+ char* endtag = strchr(mPtr, '>');
+ if (endtag < begin) return;
+
+ // Find the end of the attribute's value
+ char* end = strchr(begin, '"');
+ if (end == NULL) return;
+
+ // Determine length
+ int length = (int)end - (int)begin;
+ if (length > maxSize - 1) return;
+
+ strncpy(value, begin, length);
+ value[length] = 0;
+}
+
+int XMLReader::getAttributeAsInteger(const char* name, int defValue) {
+ char value[32];
+ getAttribute(name, value, sizeof(value), "");
+ if (value[0] == 0) return defValue;
+ if (value[0] == '0' && value[1] == 'x') {
+ return (int) strtoul(&value[2], (char**)NULL, 16);
+ }
+ return strtol(value, NULL, 10);
+}
+
+bool XMLReader::getAttributeAsBoolean(const char* name, bool defValue) {
+ char value[32];
+ getAttribute(name, value, sizeof(value), "");
+ if (value[0] == 0) return defValue;
+
+ // Convert to lowercase
+ int i = 0;
+ while (value[i]) {
+ value[i] = tolower(value[i]);
+ i++;
+ }
+
+ if (strcmp(value, "true") == 0 || strcmp(value, "yes") == 0 || strcmp(value, "1") == 0 || strcmp(value, "on") == 0) return true;
+ else if (strcmp(value, "false") == 0 || strcmp(value, "no") == 0 || strcmp(value, "0") == 0 || strcmp(value, "off") == 0) return false;
+ else return defValue;
+}
+
+int XMLReader::getAttributeLength(const char* name) {
+ char searchString[128]; // arbitrarily large amount
+
+ // Determine search string by ending the name with ="
+ if (strlen(name) > sizeof(searchString) - 3) return 0;
+ strcpy(searchString, name);
+ strcat(searchString, "=\"");
+
+ // Find the beginning of the attribute's search string
+ char* begin = strstr(mPtr, searchString);
+ if (begin == NULL) return 0;
+
+ // Find the beginning of the attribute's value
+ begin += strlen(searchString);
+
+ // Find the end of the current tag to make sure the attribute exists within the tag
+ char* endtag = strchr(mPtr, '>');
+ if (endtag < begin) return 0;
+
+ // Find the end of the attribute's value
+ char* end = strchr(begin, '"');
+ if (end == NULL) return 0;
+
+ // Determine length
+ return (int)end - (int)begin;
+}
diff --git a/drivers/gator/daemon/XMLReader.h b/drivers/gator/daemon/XMLReader.h
new file mode 100644
index 00000000000..ac0098add0a
--- /dev/null
+++ b/drivers/gator/daemon/XMLReader.h
@@ -0,0 +1,27 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 _XMLREADER_H
+#define _XMLREADER_H
+
+class XMLReader {
+public:
+ XMLReader(const char* xmlstring);
+ ~XMLReader();
+ char* nextTag();
+ void getAttribute(const char* name, char* value, int maxSize, const char* defValue);
+ int getAttributeAsInteger(const char* name, int defValue);
+ bool getAttributeAsBoolean(const char* name, bool defValue);
+ int getAttributeLength(const char* name);
+private:
+ char* mPtr;
+ bool mFirstTime, mNoMore;
+ char mEndXML[128];
+};
+
+#endif // _XMLREADER_H
diff --git a/drivers/gator/daemon/configuration.xml b/drivers/gator/daemon/configuration.xml
new file mode 100644
index 00000000000..0f910651950
--- /dev/null
+++ b/drivers/gator/daemon/configuration.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<configurations version="1">
+ <configuration counter="ARM_ARM11_ccnt" title="Clock" name="Cycles" color="0x800084AB" per_cpu="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_ARM11_cnt0" event="0x7" title="Instruction" name="Executed" color="0x80008000" per_cpu="yes" description="Instructions executed"/>
+ <configuration counter="ARM_ARM11_cnt1" event="0xa" title="Cache" name="Data miss" color="0x80C92211" per_cpu="yes" description="Data cache miss, not including Cache Operations"/>
+ <configuration counter="ARM_ARM11MPCore_ccnt" title="Clock" name="Cycles" color="0x800084AB" per_cpu="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_ARM11MPCore_cnt0" event="0x08" title="Core" name="Instructions" color="0x80008000" per_cpu="yes" description="Instructions executed"/>
+ <configuration counter="ARM_ARM11MPCore_cnt1" event="0x0b" title="Cache" name="Data read miss" color="0x000080FF" per_cpu="yes" description="Data cache miss, not including Cache Operations"/>
+ <configuration counter="ARM_Cortex-A5_ccnt" title="Clock" name="Cycles" color="0x800084AB" per_cpu="yes" event_based_sampling="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A5_cnt0" event="0x8" title="Instruction" name="Executed" color="0x80008000" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A5_cnt1" event="0x1" title="Cache" name="Instruction refill" color="0x80C92211" per_cpu="yes" event_based_sampling="yes" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
+ <configuration counter="ARM_Cortex-A8_ccnt" title="Clock" name="Cycles" color="0x800084AB" per_cpu="yes" event_based_sampling="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A8_cnt0" event="0x8" title="Instruction" name="Executed" color="0x80008000" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A8_cnt1" event="0x44" title="Cache" name="L2 miss" color="0x80C92211" per_cpu="yes" event_based_sampling="yes" description="Any cacheable miss in the L2 cache"/>
+ <configuration counter="ARM_Cortex-A8_cnt2" event="0x43" title="Cache" name="L1 miss" color="0x80FFC000" per_cpu="yes" event_based_sampling="yes" description="Any accesses to the L2 cache"/>
+ <configuration counter="ARM_Cortex-A8_cnt3" event="0x10" title="Branch" name="Mispredicted" color="0x80FFFF33" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="ARM_Cortex-A9_ccnt" title="Clock" name="Cycles" color="0x800084AB" per_cpu="yes" event_based_sampling="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A9_cnt0" event="0x68" title="Instruction" name="Executed" color="0x80008000" per_cpu="yes" event_based_sampling="yes" description="Counts the number of instructions going through the Register Renaming stage. This number is an approximate number of the total number of instructions speculatively executed, and even more approximate of the total number of instructions architecturally executed"/>
+ <configuration counter="ARM_Cortex-A9_cnt1" event="0x50" title="Cache" name="Coherency miss" color="0x80C92211" per_cpu="yes" event_based_sampling="yes" description="Counts the number of coherent linefill requests performed by the Cortex-A9 processor which also miss in all the other Cortex-A9 processors, meaning that the request is sent to the external memory"/>
+ <configuration counter="ARM_Cortex-A9_cnt2" event="0x51" title="Cache" name="Coherency hit" color="0x80FFC000" per_cpu="yes" event_based_sampling="yes" description="Counts the number of coherent linefill requests performed by the Cortex-A9 processor which hit in another Cortex-A9 processor, meaning that the linefill data is fetched directly from the relevant Cortex-A9 cache"/>
+ <configuration counter="ARM_Cortex-A9_cnt3" event="0x0c" title="Branch" name="PC change" color="0x809900FF" per_cpu="yes" event_based_sampling="yes" description="Software change of Program Counter, except by an exception, architecturally executed"/>
+ <configuration counter="ARM_Cortex-A9_cnt4" event="0x10" title="Branch" name="Mispredicted" color="0x80FFFF33" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="ARM_Cortex-A9_cnt5" event="0x0f" title="Fault" name="Unaligned access" color="0x666666" per_cpu="yes" event_based_sampling="yes" description="Unaligned access architecturally executed"/>
+ <configuration counter="ARM_Cortex-A15_ccnt" title="Clock" name="Cycles" color="0x800084AB" per_cpu="yes" event_based_sampling="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A15_cnt0" event="0x8" title="Instruction" name="Executed" color="0x80008000" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A15_cnt1" event="0x16" title="Cache" name="L2 data access" color="0x80C92211" per_cpu="yes" event_based_sampling="yes" description="Level 2 data cache access"/>
+ <configuration counter="ARM_Cortex-A15_cnt2" event="0x10" title="Branch" name="Mispredicted" color="0x80FFFF33" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="ARM_Cortex-A15_cnt3" event="0x19" title="Bus" name="Access" color="0x809900FF" per_cpu="yes" event_based_sampling="yes" description=""/>
+ <configuration counter="Linux_irq_irq" title="Interrupts" name="IRQ" color="0x805050F4" per_cpu="yes" description="Linux IRQ taken"/>
+ <configuration counter="Linux_irq_softirq" title="Interrupts" name="SoftIRQ" color="0x80FF9000" per_cpu="yes" description="Linux SoftIRQ taken"/>
+ <configuration counter="Linux_block_rq_wr" title="Disk IO" name="Write" color="0x80FF4020" description="Disk IO Bytes Written"/>
+ <configuration counter="Linux_block_rq_rd" title="Disk IO" name="Read" color="0x800090FF" description="Disk IO Bytes Read"/>
+ <configuration counter="Linux_meminfo_memused" title="Memory" name="Used" color="0x800084ab" operation="maximum" description="Total used memory size"/>
+ <configuration counter="Linux_meminfo_memfree" title="Memory" name="Free" color="0x80e9e9e9" operation="maximum" description="Available memory size"/>
+ <configuration counter="Linux_net_rx" title="Network" name="Receive" color="0x805050F4" description="Receive network traffic, excluding effect from Streamline"/>
+ <configuration counter="Linux_net_tx" title="Network" name="Transmit" color="0x80FF9000" description="Transmit network traffic, excluding effect from Streamline"/>
+ <configuration counter="Linux_cpuload_system" title="CPU Load" name="System" color="0x80FF0000" description="Scheduler CPU Load of System Behavior"/>
+ <configuration counter="Linux_cpuload_user" title="CPU Load" name="User" color="0x8000FF00" description="Scheduler CPU Load of User Application"/>
+</configurations>
diff --git a/drivers/gator/daemon/events-ARM11.xml b/drivers/gator/daemon/events-ARM11.xml
new file mode 100644
index 00000000000..5742271c29b
--- /dev/null
+++ b/drivers/gator/daemon/events-ARM11.xml
@@ -0,0 +1,43 @@
+ <counter_set name="ARM_ARM11_cntX">
+ <counter name="ARM_ARM11_cnt0"/>
+ <counter name="ARM_ARM11_cnt1"/>
+ <counter name="ARM_ARM11_cnt2"/>
+ </counter_set>
+ <category name="ARM11" counter_set="ARM_ARM11_cntX" per_cpu="yes">
+ <event counter="ARM_ARM11_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/>
+ <event event="0x00" title="Cache" name="Inst miss" description="Instruction cache miss to a cacheable location, which requires a fetch from external memory"/>
+ <event event="0x01" title="Pipeline" name="Instruction stall" description="Stall because instruction buffer cannot deliver an instruction"/>
+ <event event="0x02" title="Pipeline" name="Data stall" description="Stall because of a data dependency"/>
+ <event event="0x03" title="Cache" name="Inst micro TLB miss" description="Instruction MicroTLB miss (unused on ARM1156)"/>
+ <event event="0x04" title="Cache" name="Data micro TLB miss" description="Data MicroTLB miss (unused on ARM1156)"/>
+ <event event="0x05" title="Branch" name="Instruction executed" description="Branch instruction executed, branch might or might not have changed program flow"/>
+ <event event="0x06" title="Branch" name="Mispredicted" description="Branch mis-predicted"/>
+ <event event="0x07" title="Instruction" name="Executed" description="Instructions executed"/>
+ <event event="0x09" title="Cache" name="Data access" description="Data cache access, not including Cache operations"/>
+ <event event="0x0a" title="Cache" name="Data all access" description="Data cache access, not including Cache Operations regardless of whether or not the location is cacheable"/>
+ <event event="0x0b" title="Cache" name="Data miss" description="Data cache miss, not including Cache Operations"/>
+ <event event="0x0c" title="Cache" name="Write-back" description="Data cache write-back"/>
+ <event event="0x0d" title="Program Counter" name="SW change" description="Software changed the PC"/>
+ <event event="0x0f" title="Cache " name="TLB miss" description="Main TLB miss (unused on ARM1156)"/>
+ <event event="0x10" title="External" name="Access" description="Explicit external data or peripheral access"/>
+ <event event="0x11" title="Cache" name="Data miss" description="Stall because of Load Store Unit request queue being full"/>
+ <event event="0x12" title="Write Buffer" name="Drains" description="The number of times the Write Buffer was drained because of a Data Synchronization Barrier command or Strongly Ordered operation"/>
+ <event event="0x13" title="Disable Interrupts" name="FIQ" description="The number of cycles which FIQ interrupts are disabled (ARM1156 only)"/>
+ <event event="0x14" title="Disable Interrupts" name="IRQ" description="The number of cycles which IRQ interrupts are disabled (ARM1156 only)"/>
+ <event event="0x20" title="ETM" name="ETMEXTOUT[0]" description="ETMEXTOUT[0] signal was asserted for a cycle"/>
+ <event event="0x21" title="ETM" name="ETMEXTOUT[1]" description="ETMEXTOUT[1] signal was asserted for a cycle"/>
+ <event event="0x22" title="ETM" name="ETMEXTOUT[0,1]" description="ETMEXTOUT[0] or ETMEXTOUT[1] was asserted"/>
+ <event event="0x23" title="Procedure" name="Calls" description="Procedure call instruction executed"/>
+ <event event="0x24" title="Procedure" name="Returns" description="Procedure return instruction executed"/>
+ <event event="0x25" title="Procedure" name="Return and predicted" description="Procedure return instruction executed and return address predicted"/>
+ <event event="0x26" title="Procedure" name="Return and mispredicted" description="Procedure return instruction executed and return address predicted incorrectly"/>
+ <event event="0x30" title="Cache" name="Inst tag or parity error" description="Instruction cache Tag or Valid RAM parity error (ARM1156 only)"/>
+ <event event="0x31" title="Cache" name="Inst parity error" description="Instruction cache RAM parity error (ARM1156 only)"/>
+ <event event="0x32" title="Cache" name="Data tag or parity error" description="Data cache Tag or Valid RAM parity error (ARM1156 only)"/>
+ <event event="0x33" title="Cache" name="Data parity error" description="Data cache RAM parity error (ARM1156 only)"/>
+ <event event="0x34" title="ITCM" name="Error" description="ITCM error (ARM1156 only)"/>
+ <event event="0x35" title="DTCM" name="Error" description="DTCM error (ARM1156 only)"/>
+ <event event="0x36" title="Procedure" name="Return address pop" description="Procedure return address popped off the return stack (ARM1156 only)"/>
+ <event event="0x37" title="Procedure" name="Return address misprediction" description="Procedure return address popped off the return stack has been incorrectly predicted by the PFU (ARM1156 only)"/>
+ <event event="0x38" title="Cache" name="Data dirty parity error" description="Data cache Dirty RAM parity error (ARM1156 only)"/>
+ </category>
diff --git a/drivers/gator/daemon/events-ARM11MPCore.xml b/drivers/gator/daemon/events-ARM11MPCore.xml
new file mode 100644
index 00000000000..6da9ecb49dd
--- /dev/null
+++ b/drivers/gator/daemon/events-ARM11MPCore.xml
@@ -0,0 +1,30 @@
+ <counter_set name="ARM_ARM11MPCore_cntX">
+ <counter name="ARM_ARM11MPCore_cnt0"/>
+ <counter name="ARM_ARM11MPCore_cnt1"/>
+ <counter name="ARM_ARM11MPCore_cnt2"/>
+ </counter_set>
+ <category name="ARM11MPCore" counter_set="ARM_ARM11MPCore_cntX" per_cpu="yes">
+ <event counter="ARM_ARM11MPCore_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/>
+ <event event="0x00" title="Cache" name="Inst miss" description="Instruction cache miss to a cacheable location, which requires a fetch from external memory"/>
+ <event event="0x01" title="Pipeline" name="Instruction stall" description="Stall because instruction buffer cannot deliver an instruction"/>
+ <event event="0x02" title="Pipeline" name="Data stall" description="Stall because of a data dependency"/>
+ <event event="0x03" title="Cache" name="Inst micro TLB miss" description="Instruction MicroTLB miss (unused on ARM1156)"/>
+ <event event="0x04" title="Cache" name="Data micro TLB miss" description="Data MicroTLB miss (unused on ARM1156)"/>
+ <event event="0x05" title="Branch" name="Instruction executed" description="Branch instructions executed, branch might or might not have changed program flow"/>
+ <event event="0x06" title="Branch" name="Not predicted" description="Branch not predicted"/>
+ <event event="0x07" title="Branch" name="Mispredicted" description="Branch mispredicted"/>
+ <event event="0x08" title="Core" name="Instructions" description="Instructions executed"/>
+ <event event="0x09" title="Core" name="Folded Instructions" description="Folded instructions executed"/>
+ <event event="0x0a" title="Cache" name="Data read access" description="Data cache read access, not including cache operations"/>
+ <event event="0x0b" title="Cache" name="Data read miss" description="Data cache miss, not including Cache Operations"/>
+ <event event="0x0c" title="Cache" name="Data write access" description="Data cache write access"/>
+ <event event="0x0d" title="Cache" name="Data write miss" description="Data cache write miss"/>
+ <event event="0x0e" title="Cache" name="Data line eviction" description="Data cache line eviction, not including cache operations"/>
+ <event event="0x0f" title="Branch" name="PC change w/o mode change" description="Software changed the PC and there is not a mode change"/>
+ <event event="0x10" title="Cache " name="TLB miss" description="Main TLB miss"/>
+ <event event="0x11" title="External" name="External Memory request" description="External memory request (cache refill, noncachable, write-back)"/>
+ <event event="0x12" title="Cache" name="Stall" description="Stall because of Load Store Unit request queue being full"/>
+ <event event="0x13" title="Write Buffer" name="Drains" description="The number of times the Write Buffer was drained because of LSU ordering constraints or CP15 operations (Data Synchronization Barrier command) or Strongly Ordered operation"/>
+ <event event="0x14" title="Write Buffer" name="Write Merges" description="Buffered write merged in a store buffer slot"/>
+ <event event="0xFF" title="Core" name="Cycle counter" description="An increment each cycle"/>
+ </category> \ No newline at end of file
diff --git a/drivers/gator/daemon/events-Cortex-A15.xml b/drivers/gator/daemon/events-Cortex-A15.xml
new file mode 100644
index 00000000000..86a3d17e9d8
--- /dev/null
+++ b/drivers/gator/daemon/events-Cortex-A15.xml
@@ -0,0 +1,77 @@
+ <counter_set name="ARM_Cortex-A15_cntX">
+ <counter name="ARM_Cortex-A15_cnt0"/>
+ <counter name="ARM_Cortex-A15_cnt1"/>
+ <counter name="ARM_Cortex-A15_cnt2"/>
+ <counter name="ARM_Cortex-A15_cnt3"/>
+ <counter name="ARM_Cortex-A15_cnt4"/>
+ <counter name="ARM_Cortex-A15_cnt5"/>
+ </counter_set>
+ <category name="Cortex-A15" counter_set="ARM_Cortex-A15_cntX" per_cpu="yes" event_based_sampling="yes">
+ <event counter="ARM_Cortex-A15_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/>
+ <event event="0x00" title="Software" name="Increment" description="Software increment architecturally executed"/>
+ <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="0x11" title="Cycle" name="Cycle" description=""/>
+ <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=""/>
+ <event event="0x1a" title="Memory" name="Error" description="Local memory error"/>
+ <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=""/>
+ <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
+ <event event="0x41" title="Cache" name="L1 data write" description="Level 1 data cache access - Write"/>
+ <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/>
+ <event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill - Write"/>
+ <event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-Back - Victim"/>
+ <event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-Back - Cleaning and coherency"/>
+ <event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/>
+ <event event="0x4c" title="TLB" name="L1 data refill read" description="Level 1 data TLB refill - Read"/>
+ <event event="0x4d" title="TLB" name="L1 data refill write" description="Level 1 data TLB refill - 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 write" description="Level 2 data cache access - Write"/>
+ <event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/>
+ <event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill - 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="0x61" title="Bus" name="Write" description="Bus access - Write"/>
+ <event event="0x64" title="Bus" name="Access" 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="0x6d" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/>
+ <event event="0x6e" title="Intrinsic" name="STREX fail" description="Exclusive instruction speculatively executed - STREX fail"/>
+ <event event="0x70" title="Instructions" name="Load" description="Instruction speculatively executed - Load"/>
+ <event event="0x71" title="Instructions" name="Store" description="Instruction speculatively executed - Store"/>
+ <event event="0x72" title="Instructions" name="Load/Store" description="Instruction speculatively executed - Load or store"/>
+ <event event="0x73" title="Instructions" name="Integer" description="Instruction speculatively executed - Integer data processing"/>
+ <event event="0x74" title="Instructions" name="Advanced SIMD" description="Instruction speculatively executed - Advanced SIMD"/>
+ <event event="0x75" title="Instructions" name="VFP" description="Instruction speculatively executed - VFP"/>
+ <event event="0x76" title="Instructions" name="Software change" description="Instruction speculatively executed - Software change of the PC"/>
+ <event event="0x78" title="Instructions" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
+ <event event="0x79" title="Instructions" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
+ <event event="0x7a" title="Instructions" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
+ <event event="0x7c" title="Instructions" name="ISB" description="Barrier speculatively executed - ISB"/>
+ <event event="0x7d" title="Instructions" name="DSB" description="Barrier speculatively executed - DSB"/>
+ <event event="0x7e" title="Instructions" name="DMB" description="Barrier speculatively executed - DMB"/>
+ </category>
+ \ No newline at end of file
diff --git a/drivers/gator/daemon/events-Cortex-A5.xml b/drivers/gator/daemon/events-Cortex-A5.xml
new file mode 100644
index 00000000000..3683947cbe5
--- /dev/null
+++ b/drivers/gator/daemon/events-Cortex-A5.xml
@@ -0,0 +1,39 @@
+ <counter_set name="ARM_Cortex-A5_cntX">
+ <counter name="ARM_Cortex-A5_cnt0"/>
+ <counter name="ARM_Cortex-A5_cnt1"/>
+ </counter_set>
+ <category name="Cortex-A5" counter_set="ARM_Cortex-A5_cntX" per_cpu="yes" event_based_sampling="yes">
+ <event counter="ARM_Cortex-A5_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/>
+ <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
+ <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="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
+ <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
+ <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="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
+ <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
+ <event event="0x0e" title="Procedure" name="Return" description="Procedure return, other than exception return, architecturally executed"/>
+ <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access 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="Instruction access" description="Instruction cache access"/>
+ <event event="0x15" title="Cache" name="Data eviction" description="Data cache eviction"/>
+ <event event="0x86" title="Interrupts" name="IRQ" description="IRQ exception taken"/>
+ <event event="0x87" title="Interrupts" name="FIQ" description="FIQ exception taken"/>
+ <event event="0xC0" title="Memory" name="External request" description="External memory request"/>
+ <event event="0xC1" title="Memory" name="Non-cacheable ext req" description="Non-cacheable external memory request"/>
+ <event event="0xC2" title="Cache" name="Linefill" description="Linefill because of prefetch"/>
+ <event event="0xC3" title="Cache" name="Linefill dropped" description="Prefetch linefill dropped"/>
+ <event event="0xC4" title="Cache" name="Allocate mode enter" description="Entering read allocate mode"/>
+ <event event="0xC5" title="Cache" name="Allocate mode" description="Read allocate mode"/>
+ <event event="0xC7" title="ETM" name="ETM Ext Out[0]" description=""/>
+ <event event="0xC8" title="ETM" name="ETM Ext Out[1]" description=""/>
+ <event event="0xC9" title="Instruction" name="Pipeline stall" description="Data Write operation that stalls the pipeline because the store buffer is full"/>
+ </category>
diff --git a/drivers/gator/daemon/events-Cortex-A7.xml b/drivers/gator/daemon/events-Cortex-A7.xml
new file mode 100644
index 00000000000..db9f180ca10
--- /dev/null
+++ b/drivers/gator/daemon/events-Cortex-A7.xml
@@ -0,0 +1,50 @@
+ <counter_set name="ARM_Cortex-A7_cntX">
+ <counter name="ARM_Cortex-A7_cnt0"/>
+ <counter name="ARM_Cortex-A7_cnt1"/>
+ <counter name="ARM_Cortex-A7_cnt2"/>
+ <counter name="ARM_Cortex-A7_cnt3"/>
+ </counter_set>
+ <category name="Cortex-A7" counter_set="ARM_Cortex-A7_cntX" per_cpu="yes" event_based_sampling="yes">
+ <event counter="ARM_Cortex-A7_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/>
+ <event event="0x00" title="Software" name="Increment" description="Software increment architecturally executed"/>
+ <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="0x06" title="Memory" name="Data Read" description="Data read architecturally executed"/>
+ <event event="0x07" title="Memory" name="Data Write" description="Data write architecturally executed"/>
+ <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="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
+ <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
+ <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed"/>
+ <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
+ <event event="0x11" title="Cycle" name="Counter" description=""/>
+ <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 eviction" description="Level 1 data cache eviction"/>
+ <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=""/>
+ <event event="0x1d" title="Bus" name="Cycle" description=""/>
+ <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
+ <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/>
+ <event event="0x86" title="Exception" name="IRQ" description="IRQ exception taken"/>
+ <event event="0x87" title="Exception" name="FIQ" description="FIQ exception taken"/>
+ <event event="0xC0" title="Memory" name="External request" description="External memory request"/>
+ <event event="0xC1" title="Memory" name="Non-cacheable ext req" description="Non-cacheable external memory request"/>
+ <event event="0xC2" title="Cache" name="Linefill" description="Linefill because of prefetch"/>
+ <event event="0xC3" title="Cache" name="Linefill dropped" description="Prefetch linefill dropped"/>
+ <event event="0xC4" title="Cache" name="Allocate mode enter" description="Entering read allocate mode"/>
+ <event event="0xC5" title="Cache" name="Allocate mode" description="Read allocate mode"/>
+ <event event="0xC7" title="ETM" name="ETM Ext Out[0]" description=""/>
+ <event event="0xC8" title="ETM" name="ETM Ext Out[1]" description=""/>
+ <event event="0xC9" title="Instruction" name="Pipeline stall" description="Data Write operation that stalls the pipeline because the store buffer is full"/>
+ <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 cluster, rather than accessing the L2 cache or issuing an external read."/>
+ </category>
+ \ No newline at end of file
diff --git a/drivers/gator/daemon/events-Cortex-A8.xml b/drivers/gator/daemon/events-Cortex-A8.xml
new file mode 100644
index 00000000000..f3396b71144
--- /dev/null
+++ b/drivers/gator/daemon/events-Cortex-A8.xml
@@ -0,0 +1,58 @@
+ <counter_set name="ARM_Cortex-A8_cntX">
+ <counter name="ARM_Cortex-A8_cnt0"/>
+ <counter name="ARM_Cortex-A8_cnt1"/>
+ <counter name="ARM_Cortex-A8_cnt2"/>
+ <counter name="ARM_Cortex-A8_cnt3"/>
+ </counter_set>
+ <category name="Cortex-A8" counter_set="ARM_Cortex-A8_cntX" per_cpu="yes" event_based_sampling="yes">
+ <event counter="ARM_Cortex-A8_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/>
+ <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
+ <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="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
+ <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
+ <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="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
+ <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
+ <event event="0x0e" title="Procedure" name="Return" description="Procedure return, other than exception return, architecturally executed"/>
+ <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access 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="0x40" title="Cache" name="Write buffer full" description="Any write buffer full cycle"/>
+ <event event="0x41" title="Cache" name="L2 store" description="Any store that is merged in the L2 memory system"/>
+ <event event="0x42" title="Cache" name="Bufferable transaction" description="Any bufferable store transaction from load/store to L2 cache, excluding eviction or cast out data"/>
+ <event event="0x43" title="Cache" name="L1 miss" description="Any accesses to the L2 cache"/>
+ <event event="0x44" title="Cache" name="L2 miss" description="Any cacheable miss in the L2 cache"/>
+ <event event="0x45" title="AXI" name="Read" description="The number of AXI read data transfers"/>
+ <event event="0x46" title="AXI" name="Write" description="The number of AXI write data transfers"/>
+ <event event="0x47" title="Memory" name="Replay event" description="Any replay event in the memory system"/>
+ <event event="0x48" title="Memory" name="Unaligned access" description="Any unaligned memory access that results in a replay"/>
+ <event event="0x49" title="Cache" name="L1 data hash miss" description="Any L1 data memory access that misses in the cache as a result of the hashing algorithm"/>
+ <event event="0x4a" title="Cache" name="L1 inst hash miss" description="Any L1 instruction memory access that misses in the cache as a result of the hashing algorithm"/>
+ <event event="0x4b" title="Cache" name="L1 page coloring" description="Any L1 data memory access in which a page coloring alias occurs"/>
+ <event event="0x4c" title="NEON" name="L1 cache hit" description="Any NEON access that hits in the L1 data cache"/>
+ <event event="0x4d" title="NEON" name="L1 cache access" description="Any NEON cacheable data accesses for L1 data cache"/>
+ <event event="0x4e" title="NEON" name="L2 cache access" description="Any L2 cache accesses as a result of a NEON memory access"/>
+ <event event="0x4f" title="NEON" name="L2 cache hit" description="Any NEON hit in the L2 cache"/>
+ <event event="0x50" title="Cache" name="L1 inst access" description="Any L1 instruction cache access, excluding CP15 cache accesses"/>
+ <event event="0x51" title="Branch" name="Return stack misprediction" description="Any return stack misprediction because of incorrect target address for a taken return stack pop"/>
+ <event event="0x52" title="Branch" name="Direction misprediction" description="Branch direction misprediction"/>
+ <event event="0x53" title="Branch" name="Taken prediction" description="Any predictable branch that is predicted to be taken"/>
+ <event event="0x54" title="Branch" name="Executed and taken prediction" description="Any predictable branch that is executed and taken"/>
+ <event event="0x55" title="Core" name="Operations issued" description="Number of operations issued, where an operation is either: an instruction or one operation in a sequence of operations that make up a multi-cycle instruction"/>
+ <event event="0x56" title="Core" name="No issue cycles" description="Increment for every cycle that no instructions are available for issue"/>
+ <event event="0x57" title="Core" name="Issue cycles" description="For every cycle, this event counts the number of instructions issued in that cycle. Multi-cycle instructions are only counted once"/>
+ <event event="0x58" title="NEON" name="MRC data wait" description="Number of cycles the processor stalls waiting on MRC data from NEON"/>
+ <event event="0x59" title="NEON" name="Full queue" description="Number of cycles that the processor stalls as a result of a full NEON instruction queue or NEON load queue"/>
+ <event event="0x5a" title="NEON" name="Idle" description="Number of cycles that NEON and integer processors are both not idle"/>
+ <event event="0x70" title="External" name="PMUEXTIN[0]" description="Counts any event from external input source PMUEXTIN[0]"/>
+ <event event="0x71" title="External" name="PMUEXTIN[1]" description="Counts any event from external input source PMUEXTIN[1]"/>
+ <event event="0x72" title="External" name="PMUEXTIN[0,1]" description="Counts any event from both external input sources PMUEXTIN[0] and PMUEXTIN[1]"/>
+ </category>
+ \ No newline at end of file
diff --git a/drivers/gator/daemon/events-Cortex-A9.xml b/drivers/gator/daemon/events-Cortex-A9.xml
new file mode 100644
index 00000000000..1edb54a9359
--- /dev/null
+++ b/drivers/gator/daemon/events-Cortex-A9.xml
@@ -0,0 +1,67 @@
+ <counter_set name="ARM_Cortex-A9_cntX">
+ <counter name="ARM_Cortex-A9_cnt0"/>
+ <counter name="ARM_Cortex-A9_cnt1"/>
+ <counter name="ARM_Cortex-A9_cnt2"/>
+ <counter name="ARM_Cortex-A9_cnt3"/>
+ <counter name="ARM_Cortex-A9_cnt4"/>
+ <counter name="ARM_Cortex-A9_cnt5"/>
+ </counter_set>
+ <category name="Cortex-A9" counter_set="ARM_Cortex-A9_cntX" per_cpu="yes" event_based_sampling="yes">
+ <event counter="ARM_Cortex-A9_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/>
+ <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
+ <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="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
+ <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing 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="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
+ <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
+ <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access 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="0x40" title="Java" name="Bytecode execute" description="Counts the number of Java bytecodes being decoded, including speculative ones"/>
+ <event event="0x41" title="Java" name="SW bytecode execute" description="Counts the number of software java bytecodes being decoded, including speculative ones"/>
+ <event event="0x42" title="Jazelle" name="Backward branch execute" description="Counts the number of Jazelle taken branches being executed"/>
+ <event event="0x50" title="Cache" name="Coherency miss" description="Counts the number of coherent linefill requests performed by the Cortex-A9 processor which also miss in all the other Cortex-A9 processors, meaning that the request is sent to the external memory"/>
+ <event event="0x51" title="Cache" name="Coherency hit" description="Counts the number of coherent linefill requests performed by the Cortex-A9 processor which hit in another Cortex-A9 processor, meaning that the linefill data is fetched directly from the relevant Cortex-A9 cache"/>
+ <event event="0x60" title="Cache" name="Inst dependent stall" description="Counts the number of cycles where the processor is ready to accept new instructions, but does not receive any because of the instruction side not being able to provide any and the instruction cache is currently performing at least one linefill"/>
+ <event event="0x61" title="Cache" name="Data dependent stall" description="Counts the number of cycles where the core has some instructions that it cannot issue to any pipeline, and the Load Store unit has at least one pending linefill request, and no pending TLB requests"/>
+ <event event="0x62" title="Cache" name="TLB stall" description="Counts the number of cycles where the processor is stalled waiting for the completion of translation table walks from the main TLB"/>
+ <event event="0x63" title="Intrinsic" name="STREX pass" description="Counts the number of STREX instructions architecturally executed and passed"/>
+ <event event="0x64" title="Intrinsic" name="STREX fail" description="Counts the number of STREX instructions architecturally executed and failed"/>
+ <event event="0x65" title="Cache" name="Data eviction" description="Counts the number of eviction requests because of a linefill in the data cache"/>
+ <event event="0x66" title="Pipeline" name="Issue stage no dispatch" description="Counts the number of cycles where the issue stage does not dispatch any instruction because it is empty or cannot dispatch any instructions"/>
+ <event event="0x67" title="Pipeline" name="Issue stage empty" description="Counts the number of cycles where the issue stage is empty"/>
+ <event event="0x68" title="Instruction" name="Executed" description="Counts the number of instructions going through the Register Renaming stage. This number is an approximate number of the total number of instructions speculatively executed, and even more approximate of the total number of instructions architecturally executed"/>
+ <event event="0x6E" title="Core" name="Functions" description="Counts the number of procedure returns whose condition codes do not fail, excluding all returns from exception"/>
+ <event event="0x70" title="Instructions" name="Main execution unit" description="Counts the number of instructions being executed in the main execution pipeline of the processor, the multiply pipeline and arithmetic logic unit pipeline"/>
+ <event event="0x71" title="Instructions" name="Second execution unit" description="Counts the number of instructions being executed in the processor second execution pipeline (ALU)"/>
+ <event event="0x72" title="Instructions" name="Load/Store" description="Counts the number of instructions being executed in the Load/Store unit"/>
+ <event event="0x73" title="Instructions" name="Floating point" description="Counts the number of Floating-point instructions going through the Register Rename stage"/>
+ <event event="0x74" title="Instructions" name="NEON" description="Counts the number of NEON instructions going through the Register Rename stage"/>
+ <event event="0x80" title="Stalls" name="PLD" description="Counts the number of cycles where the processor is stalled because PLD slots are all full"/>
+ <event event="0x81" title="Stalls" name="Memory write" description="Counts the number of cycles when the processor is stalled and the data side is stalled too because it is full and executing writes to the external memory"/>
+ <event event="0x82" title="Stalls" name="Inst main TLB miss" description="Counts the number of stall cycles because of main TLB misses on requests issued by the instruction side"/>
+ <event event="0x83" title="Stalls" name="Data main TLB miss" description="Counts the number of stall cycles because of main TLB misses on requests issued by the data side"/>
+ <event event="0x84" title="Stalls" name="Inst micro TLB miss" description="Counts the number of stall cycles because of micro TLB misses on the instruction side"/>
+ <event event="0x85" title="Stalls" name="Data micro TLB miss" description="Counts the number of stall cycles because of micro TLB misses on the data side"/>
+ <event event="0x86" title="Stalls" name="DMB" description="Counts the number of stall cycles because of the execution of a DMB memory barrier"/>
+ <event event="0x8A" title="Clock" name="Integer core" description="Counts the number of cycles during which the integer core clock is enabled"/>
+ <event event="0x8B" title="Clock" name="Data engine" description="Counts the number of cycles during which the Data Engine clock is enabled"/>
+ <event event="0x90" title="Instructions" name="ISB" description="Counts the number of ISB instructions architecturally executed"/>
+ <event event="0x91" title="Instructions" name="DSB" description="Counts the number of DSB instructions architecturally executed"/>
+ <event event="0x92" title="Instructions" name="DMB" description="Counts the number of DMB instructions speculatively executed"/>
+ <event event="0x93" title="External" name="Interrupts" description="Counts the number of external interrupts executed by the processor"/>
+ <event event="0xA0" title="PLE" name="Cache line rq completed" description="Counts the number of PLE cache line requests completed"/>
+ <event event="0xA1" title="PLE" name="Cache line rq skipped" description="Counts the number of PLE cache line requests skipped"/>
+ <event event="0xA2" title="PLE" name="FIFO flush" description="Counts the number of PLE FIFO flush requests"/>
+ <event event="0xA3" title="PLE" name="Request completed" description="Counts the number of PLE FIFO flush completed"/>
+ <event event="0xA4" title="PLE" name="FIFO overflow" description="Counts the number of PLE FIFO flush overflowed"/>
+ <event event="0xA5" title="PLE" name="Request programmed" description="Counts the number of PLE FIFO flush program requests"/>
+ </category>
+ \ No newline at end of file
diff --git a/drivers/gator/daemon/events-Krait-architected.xml b/drivers/gator/daemon/events-Krait-architected.xml
new file mode 100644
index 00000000000..46d6a616b05
--- /dev/null
+++ b/drivers/gator/daemon/events-Krait-architected.xml
@@ -0,0 +1,28 @@
+ <counter_set name="Krait_cntX">
+ <counter name="Krait_cnt0"/>
+ <counter name="Krait_cnt1"/>
+ <counter name="Krait_cnt2"/>
+ <counter name="Krait_cnt3"/>
+ </counter_set>
+ <category name="Krait" counter_set="Krait_cntX" per_cpu="yes">
+ <event counter="Krait_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/>
+ <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
+ <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="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
+ <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
+ <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="0x0c" title="Program Counter" name="SW change" description="Software change of PC, except by an exception, architecturally executed"/>
+ <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
+ <event event="0x0e" title="Branch" name="Procedure Return" description="Procedure return architecturally executed (not by exceptions)"/>
+ <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access 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"/>
+ </category>
+ \ No newline at end of file
diff --git a/drivers/gator/daemon/events-L2C-310.xml b/drivers/gator/daemon/events-L2C-310.xml
new file mode 100644
index 00000000000..b1cd8dff5b5
--- /dev/null
+++ b/drivers/gator/daemon/events-L2C-310.xml
@@ -0,0 +1,21 @@
+ <counter_set name="L2C-310_cntX">
+ <counter name="L2C-310_cnt0"/>
+ <counter name="L2C-310_cnt1"/>
+ </counter_set>
+ <category name="L2C-310" counter_set="L2C-310_cntX" per_cpu="no">
+ <event event="0x1" title="L2Cache" name="CO" description="Eviction, CastOut, of a line from the L2 cache"/>
+ <event event="0x2" title="L2Cache" name="DRH" description="Data read hit"/>
+ <event event="0x3" title="L2Cache" name="DRREQ" description="Data read request"/>
+ <event event="0x4" title="L2Cache" name="DWHIT" description="Data write hit"/>
+ <event event="0x5" title="L2Cache" name="DWREQ" description="Data write request"/>
+ <event event="0x6" title="L2Cache" name="DWTREQ" description="Data write request with write-through attribute"/>
+ <event event="0x7" title="L2Cache" name="IRHIT" description="Instruction read hit"/>
+ <event event="0x8" title="L2Cache" name="IRREQ" description="Instruction read request"/>
+ <event event="0x9" title="L2Cache" name="WA" description="Write allocate"/>
+ <event event="0xa" title="L2Cache" name="IPFALLOC" description="Allocation of a prefetch generated by L2C-310 into the L2 cache"/>
+ <event event="0xb" title="L2Cache" name="EPFHIT" description="Prefetch hint hits in the L2 cache"/>
+ <event event="0xc" title="L2Cache" name="EPFALLOC" description="Prefetch hint allocated into the L2 cache"/>
+ <event event="0xd" title="L2Cache" name="SRRCVD" description="Speculative read received"/>
+ <event event="0xe" title="L2Cache" name="SRCONF" description="Speculative read confirmed"/>
+ <event event="0xf" title="L2Cache" name="EPFRCVD" description="Prefetch hint received"/>
+ </category>
diff --git a/drivers/gator/daemon/events-Linux.xml b/drivers/gator/daemon/events-Linux.xml
new file mode 100644
index 00000000000..338e1605506
--- /dev/null
+++ b/drivers/gator/daemon/events-Linux.xml
@@ -0,0 +1,16 @@
+ <category name="Linux">
+ <event counter="Linux_cpuload_user" title="CPU Load" name="User" per_cpu="yes" description="Scheduler CPU Load of User Application" operation="percentage"/>
+ <event counter="Linux_cpuload_system" title="CPU Load" name="System" per_cpu="yes" description="Scheduler CPU Load of System Behavior" operation="percentage"/>
+ <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" description="Disk IO Bytes Written"/>
+ <event counter="Linux_block_rq_rd" title="Disk IO" name="Read" description="Disk IO Bytes Read"/>
+ <event counter="Linux_meminfo_memused" title="Memory" name="Used" description="Total used memory size" operation="maximum"/>
+ <event counter="Linux_meminfo_memfree" title="Memory" name="Free" description="Available memory size" operation="maximum"/>
+ <event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" description="Memory used by buffers" operation="maximum"/>
+ <event counter="Linux_net_rx" title="Network" name="Receive" description="Receive network traffic, excluding effect from Streamline"/>
+ <event counter="Linux_net_tx" title="Network" name="Transmit" description="Transmit network traffic, excluding effect from Streamline"/>
+ <event counter="Linux_sched_switch" title="Scheduler" name="Switch" description="Context switch events"/>
+ <event counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" description="Target frequency of the CPU" operation="frequency"/>
+ </category>
+
diff --git a/drivers/gator/daemon/events-Mali-400.xml b/drivers/gator/daemon/events-Mali-400.xml
new file mode 100644
index 00000000000..f64fec8aaac
--- /dev/null
+++ b/drivers/gator/daemon/events-Mali-400.xml
@@ -0,0 +1,395 @@
+ <counter_set name="ARM_Mali-400_VP_cntX">
+ <counter name="ARM_Mali-400_VP_cnt0"/>
+ <counter name="ARM_Mali-400_VP_cnt1"/>
+ </counter_set>
+ <counter_set name="ARM_Mali-400_FP0_cntX">
+ <counter name="ARM_Mali-400_FP0_cnt0"/>
+ <counter name="ARM_Mali-400_FP0_cnt1"/>
+ </counter_set>
+ <counter_set name="ARM_Mali-400_FP1_cntX">
+ <counter name="ARM_Mali-400_FP1_cnt0"/>
+ <counter name="ARM_Mali-400_FP1_cnt1"/>
+ </counter_set>
+ <counter_set name="ARM_Mali-400_FP2_cntX">
+ <counter name="ARM_Mali-400_FP2_cnt0"/>
+ <counter name="ARM_Mali-400_FP2_cnt1"/>
+ </counter_set>
+ <counter_set name="ARM_Mali-400_FP3_cntX">
+ <counter name="ARM_Mali-400_FP3_cnt0"/>
+ <counter name="ARM_Mali-400_FP3_cnt1"/>
+ </counter_set>
+ <counter_set name="ARM_Mali-400_L2_cntX">
+ <counter name="ARM_Mali-400_L2_cnt0"/>
+ <counter name="ARM_Mali-400_L2_cnt1"/>
+ </counter_set>
+ <counter_set name="ARM_Mali-400_SW_cntX">
+ </counter_set>
+ <counter_set name="ARM_Mali-400_Filmstrip_cntX">
+ <counter name="ARM_Mali-400_Filmstrip"/>
+ </counter_set>
+ <category name="Mali-400-VP" counter_set="ARM_Mali-400_VP_cntX" per_cpu="no">
+ <event event="0x01" title="Mali GPU Vertex Processor" name="Active cycles" description="Number of cycles per frame the MaliGP2 was active"/>
+ <event event="0x02" title="Mali GPU Vertex Processor" name="Active cycles, vertex shader" description="Number of cycles per frame the vertex shader unit was active"/>
+ <event event="0x03" title="Mali GPU Vertex Processor" name="Active cycles, vertex storer" description="Number of cycles per frame the vertex storer unit was active"/>
+ <event event="0x04" title="Mali GPU Vertex Processor" name="Active cycles, vertex loader" description="Number of cycles per frame the vertex loader unit was active"/>
+ <event event="0x05" title="Mali GPU Vertex Processor" name="Cycles vertex loader waiting for vertex shader" description="Number of cycles per frame the vertex loader was idle while waiting on the vertex shader"/>
+ <event event="0x06" title="Mali GPU Vertex Processor" name="Words read, system bus" description="Total number of 64 bit words read by the GP2 from the system bus per frame"/>
+ <event event="0x07" title="Mali GPU Vertex Processor" name="Words written, system bus" description="Total number of 64 bit words written by the GP2 to the system bus per frame"/>
+ <event event="0x08" title="Mali GPU Vertex Processor" name="Read bursts, system bus" description="Number of read bursts by the GP2 from the system bus per frame"/>
+ <event event="0x09" title="Mali GPU Vertex Processor" name="Write bursts, system bus" description="Number of write bursts from the MaliGP2 to the system bus per frame"/>
+ <event event="0x0a" title="Mali GPU Vertex Processor" name="Vertices processed" description="Number of vertices processed by the MaliGP2 per frame"/>
+ <event event="0x0b" title="Mali GPU Vertex Processor" name="Vertices fetched" description="Number of vertices fetched by the MaliGP2 per frame"/>
+ <event event="0x0c" title="Mali GPU Vertex Processor" name="Primitives fetched" description="Number of graphics primitives fetched by the MaliGP2 per frame"/>
+ <event event="0x0e" title="Mali GPU Vertex Processor" name="Primitives culled" description="Number of graphics primitives discarded per frame, because they were seen from the back or were offscreen"/>
+ <event event="0x0f" title="Mali GPU Vertex Processor" name="Commands written to tiles" description="Number of commands (8 Bytes, mainly primitives) written by GP2 to the PP input data structure per frame"/>
+ <event event="0x10" title="Mali GPU Vertex Processor" name="Memory blocks allocated" description="Number of overflow data blocks needed for outputting the PP input data structure per frame "/>
+ <event event="0x13" title="Mali GPU Vertex Processor" name="Vertex loader cache misses" description="Number of cache misses for the vertex shader's vertex input unit per frame"/>
+ <event event="0x16" title="Mali GPU Vertex Processor" name="Active cycles, vertex shader command processor" description="Number of cycles per frame the GP2 vertex shader command processor was active. This includes time waiting for semaphores."/>
+ <event event="0x17" title="Mali GPU Vertex Processor" name="Active cycles, PLBU command processor" description="Number of cycles per frame the MaliGP2 PLBU command processor was active. This includes time waiting for semaphores"/>
+ <event event="0x18" title="Mali GPU Vertex Processor" name="Number of cycles per frame the MaliGP2 PLBU output unit was active (Writing the Mali200 input data structure). This includes time spent waiting on the bus" description="MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_LIST_WRITER"/>
+ <event event="0x19" title="Mali GPU Vertex Processor" name="Active cycles, PLBU geometry processing" description="Number of cycles per frame the MaliGP2 PLBU was active, excepting final data output. In other words: active cycles through the prepare list commands. This includes time spent waiting on the bus"/>
+ <event event="0x1b" title="Mali GPU Vertex Processor" name="Active cycles, PLBU primitive assembly" description="Number of active cycles per frame spent by the MaliGP2 PLBU doing primitive assembly. This does not include scissoring or final output. This includes time spent waiting on the bus"/>
+ <event event="0x1c" title="Mali GPU Vertex Processor" name="Active cycles, PLBU vertex fetcher" description="Number of active cycles per frame spent by the MaliGP2 PLBU fetching vertex data. This includes time spent waiting on the bus"/>
+ <event event="0x1e" title="Mali GPU Vertex Processor" name="Active cycles, Bounding-box and command generator" description="Number of active cycles per frame spent by the MaliGP2 PLBU setting up bounding boxes and commands (mainly graphics primitives). This includes time spent waiting on the bus"/>
+ <event event="0x20" title="Mali GPU Vertex Processor" name="Active cycles, Scissor tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over tiles to perform scissoringi. This includes time spent waiting on the bus"/>
+ <event event="0x21" title="Mali GPU Vertex Processor" name="Active cycles, PLBU tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over the tiles in the bounding box generating commands (mainly graphics primitives). This includes time spent waiting on the bus"/>
+ </category>
+ <category name="Mali-400-FP0" counter_set="ARM_Mali-400_FP0_cntX" per_cpu="no">
+ <event event="0x00" title="Mali GPU Fragment Processor 0" name="Active clock cycles" description="Active clock cycles, between polygon start and IRQ"/>
+ <event event="0x02" title="Mali GPU Fragment Processor 0" name="Total bus reads" description="Total number of 64-bit words read from the bus"/>
+ <event event="0x03" title="Mali GPU Fragment Processor 0" name="Total bus writes" description="Total number of 64-bit words written to the bus"/>
+ <event event="0x04" title="Mali GPU Fragment Processor 0" name="Bus read request cycles" description="MALI_CINSTR_PP_BUS_READ_REQUEST_CYCLES_COUNT"/>
+ <event event="0x05" title="Mali GPU Fragment Processor 0" name="Bus write request cycles" description="MALI_CINSTR_PP_BUS_WRITE_REQUEST_CYCLES_COUNT"/>
+ <event event="0x06" title="Mali GPU Fragment Processor 0" name="Bus read transactions count" description="Number of read requests accepted by the bus"/>
+ <event event="0x07" title="Mali GPU Fragment Processor 0" name="Bus write transactions" description="Number of write requests accepted by the bus"/>
+ <event event="0x09" title="Mali GPU Fragment Processor 0" name="Tile writeback writes" description="64-bit words written to the bus by the writeback unit"/>
+ <event event="0x0a" title="Mali GPU Fragment Processor 0" name="Store unit writes" description="64-bit words written to the bus by the store unit"/>
+ <event event="0x0d" title="Mali GPU Fragment Processor 0" name="Texture cache uncompressed reads" description="Number of 64-bit words read from the bus into the uncompressed textures cache"/>
+ <event event="0x0e" title="Mali GPU Fragment Processor 0" name="Polygon list reads" description="Number of 64-bit words read from the bus by the polygon list reader"/>
+ <event event="0x0f" title="Mali GPU Fragment Processor 0" name="RSW reads" description="Number of 64-bit words read from the bus into the Render State Word register"/>
+ <event event="0x10" title="Mali GPU Fragment Processor 0" name="Vertex cache reads" description="Number of 64-bit words read from the bus into the vertex cache"/>
+ <event event="0x11" title="Mali GPU Fragment Processor 0" name="Uniform remapping reads" description="Number of 64-bit words read from the bus when reading from the uniform remapping table"/>
+ <event event="0x12" title="Mali GPU Fragment Processor 0" name="Program cache reads" description="Number of 64-bit words read from the bus into the fragment shader program cache"/>
+ <event event="0x13" title="Mali GPU Fragment Processor 0" name="Varying reads" description="Number of 64-bit words containing varyings generated by the vertex processing read from the bus"/>
+ <event event="0x14" title="Mali GPU Fragment Processor 0" name="Texture descriptors reads" description="Number of 64-bit words containing texture descriptors read from the bus"/>
+ <event event="0x15" title="Mali GPU Fragment Processor 0" name="Texture descriptor remapping reads" description="Number of 64-bit words read from the bus when reading from the texture descriptor remapping table"/>
+ <event event="0x17" title="Mali GPU Fragment Processor 0" name="Load unit reads" description="Number of 64-bit words read from the bus by the LOAD sub-instruction"/>
+ <event event="0x18" title="Mali GPU Fragment Processor 0" name="Polygon count" description="Number of triangles read from the polygon list"/>
+ <event event="0x19" title="Mali GPU Fragment Processor 0" name="Pixel rectangle count" description="Number of pixel rectangles read from the polygon list"/>
+ <event event="0x1a" title="Mali GPU Fragment Processor 0" name="Lines count" description="Number of lines read from the polygon list"/>
+ <event event="0x1b" title="Mali GPU Fragment Processor 0" name="Points count" description="Number of points read from the polygon list"/>
+ <event event="0x1c" title="Mali GPU Fragment Processor 0" name="Stall cycles PolygonListReader" description="Number of clock cycles the Polygon List Reader waited for output being collected"/>
+ <event event="0x1d" title="Mali GPU Fragment Processor 0" name="Stall cycles triangle setup" description="Number of clock cycles the TSC waited for input"/>
+ <event event="0x1e" title="Mali GPU Fragment Processor 0" name="Quad rasterized count" description="Number of 2x?2 quads output from rasterizer"/>
+ <event event="0x1f" title="Mali GPU Fragment Processor 0" name="Fragment rasterized count" description="Number of fragment rasterized. Fragments/(Quads*4) gives average actual fragments per quad"/>
+ <event event="0x20" title="Mali GPU Fragment Processor 0" name="Fragment rejected fragment-kill count" description="Number of fragments exiting the fragment shader as killed"/>
+ <event event="0x21" title="Mali GPU Fragment Processor 0" name="Fragment rejected fwd-fragment-kill count" description="Number of fragments killed by forward fragment kill"/>
+ <event event="0x22" title="Mali GPU Fragment Processor 0" name="Fragment passed z/stencil count" description="Number of fragments passing Z and stencil test"/>
+ <event event="0x23" title="Mali GPU Fragment Processor 0" name="Patches rejected early z/stencil count" description="Number of patches rejected by EarlyZ. A patch can be 8x8, 4x4 or 2x2 pixels"/>
+ <event event="0x24" title="Mali GPU Fragment Processor 0" name="Patches evaluated" description="Number of patches evaluated for EarlyZ rejection"/>
+ <event event="0x25" title="Mali GPU Fragment Processor 0" name="Instruction completed count" description="Number of fragment shader instruction words completed. It is a function of pixels processed and the length of the shader programs"/>
+ <event event="0x26" title="Mali GPU Fragment Processor 0" name="Instruction failed rendezvous count" description="Number of fragment shader instructions not completed because of failed Rendezvous"/>
+ <event event="0x27" title="Mali GPU Fragment Processor 0" name="Instruction failed varying-miss count" description="Number of fragment shader instructions not completed because of failed varying operation"/>
+ <event event="0x28" title="Mali GPU Fragment Processor 0" name="Instruction failed texture-miss count" description="Number of fragment shader instructions not completed because of failed texture operation"/>
+ <event event="0x29" title="Mali GPU Fragment Processor 0" name="Instruction failed load-miss count" description="Number of fragment shader instructions not completed because of failed load operation"/>
+ <event event="0x2a" title="Mali GPU Fragment Processor 0" name="Instruction failed tile read-miss count" description="Number of fragment shader instructions not completed because of failed read from the tilebuffer"/>
+ <event event="0x2b" title="Mali GPU Fragment Processor 0" name="Instruction failed store-miss count" description="Number of fragment shader instructions not completed because of failed store operation"/>
+ <event event="0x2c" title="Mali GPU Fragment Processor 0" name="Rendezvous breakage count" description="Number of Rendezvous breakages reported"/>
+ <event event="0x2d" title="Mali GPU Fragment Processor 0" name="Pipeline bubbles cycle count" description="Number of unused cycles in the fragment shader while rendering is active"/>
+ <event event="0x2e" title="Mali GPU Fragment Processor 0" name="Texture mapper multipass count" description="Number of texture operations looped because of more texture passes needed"/>
+ <event event="0x2f" title="Mali GPU Fragment Processor 0" name="Texture mapper cycle count" description="Number of texture operation cycles"/>
+ <event event="0x30" title="Mali GPU Fragment Processor 0" name="Vertex cache hit count" description="Number of times a requested vertex was found in the cache (Number of vertex cache hits)"/>
+ <event event="0x31" title="Mali GPU Fragment Processor 0" name="Vertex cache miss count" description="Number of times a requested vertex was not found in the cache (Number of vertex cache misses)"/>
+ <event event="0x32" title="Mali GPU Fragment Processor 0" name="Varying cache hit count" description="Number of times a requested varying was found in the cache (Number of varying cache hits)"/>
+ <event event="0x33" title="Mali GPU Fragment Processor 0" name="Varying cache miss count" description="Number of times a requested varying was not found in the cache (Number of varying cache misses)"/>
+ <event event="0x34" title="Mali GPU Fragment Processor 0" name="Varying cache conflict miss count" description="Number of times a requested varying was not in the cache and its value, retrieved from memory, must overwrite an older cache entry. This happens when an access pattern cannot be serviced by the cache"/>
+ <event event="0x35" title="Mali GPU Fragment Processor 0" name="Texture cache hit count" description="Number of times a requested texel was found in the texture cache (Number of texture cache hits)"/>
+ <event event="0x36" title="Mali GPU Fragment Processor 0" name="Texture cache miss count" description="Number of times a requested texel was not found in the texture cache (Number of texture cache misses)"/>
+ <event event="0x37" title="Mali GPU Fragment Processor 0" name="Texture cache conflict miss count" description="Number of times a requested texel was not in the cache and its value, retrieved from memory, must overwrite an older cache entry. This happens when an access pattern cannot be serviced by the cache"/>
+ <event event="0x38" title="Mali GPU Fragment Processor 0" name="(Mali200)Palette cache hit count; (Mali400)Compressed texture cache hit count" description="Number of times a requested item was found in the cache."/>
+ <event event="0x39" title="Mali GPU Fragment Processor 0" name="(Mali200)Palette cache miss count; (Mali400)Compressed texture cache miss count" description="Number of times a requested item was not found in the cache."/>
+ <event event="0x3a" title="Mali GPU Fragment Processor 0" name="Load/Store cache hit count" description="Number of hits in the load/store cache"/>
+ <event event="0x3b" title="Mali GPU Fragment Processor 0" name="Load/Store cache miss count" description="Number of misses in the load/store cache"/>
+ <event event="0x3c" title="Mali GPU Fragment Processor 0" name="Program cache hit count" description="Number of hits in the program cache"/>
+ <event event="0x3d" title="Mali GPU Fragment Processor 0" name="Program cache miss count" description="Number of misses in the program cache"/>
+ </category>
+ <category name="Mali-400-FP1" counter_set="ARM_Mali-400_FP1_cntX" per_cpu="no">
+ <event event="0x00" title="Mali GPU Fragment Processor 1" name="Active clock cycles" description="Active clock cycles, between polygon start and IRQ"/>
+ <event event="0x02" title="Mali GPU Fragment Processor 1" name="Total bus reads" description="Total number of 64-bit words read from the bus"/>
+ <event event="0x03" title="Mali GPU Fragment Processor 1" name="Total bus writes" description="Total number of 64-bit words written to the bus"/>
+ <event event="0x04" title="Mali GPU Fragment Processor 1" name="Bus read request cycles" description="MALI_CINSTR_PP_BUS_READ_REQUEST_CYCLES_COUNT"/>
+ <event event="0x05" title="Mali GPU Fragment Processor 1" name="Bus write request cycles" description="MALI_CINSTR_PP_BUS_WRITE_REQUEST_CYCLES_COUNT"/>
+ <event event="0x06" title="Mali GPU Fragment Processor 1" name="Bus read transactions count" description="Number of read requests accepted by the bus"/>
+ <event event="0x07" title="Mali GPU Fragment Processor 1" name="Bus write transactions" description="Number of write requests accepted by the bus"/>
+ <event event="0x09" title="Mali GPU Fragment Processor 1" name="Tile writeback writes" description="64-bit words written to the bus by the writeback unit"/>
+ <event event="0x0a" title="Mali GPU Fragment Processor 1" name="Store unit writes" description="64-bit words written to the bus by the store unit"/>
+ <event event="0x0d" title="Mali GPU Fragment Processor 1" name="Texture cache uncompressed reads" description="Number of 64-bit words read from the bus into the uncompressed textures cache"/>
+ <event event="0x0e" title="Mali GPU Fragment Processor 1" name="Polygon list reads" description="Number of 64-bit words read from the bus by the polygon list reader"/>
+ <event event="0x0f" title="Mali GPU Fragment Processor 1" name="RSW reads" description="Number of 64-bit words read from the bus into the Render State Word register"/>
+ <event event="0x10" title="Mali GPU Fragment Processor 1" name="Vertex cache reads" description="Number of 64-bit words read from the bus into the vertex cache"/>
+ <event event="0x11" title="Mali GPU Fragment Processor 1" name="Uniform remapping reads" description="Number of 64-bit words read from the bus when reading from the uniform remapping table"/>
+ <event event="0x12" title="Mali GPU Fragment Processor 1" name="Program cache reads" description="Number of 64-bit words read from the bus into the fragment shader program cache"/>
+ <event event="0x13" title="Mali GPU Fragment Processor 1" name="Varying reads" description="Number of 64-bit words containing varyings generated by the vertex processing read from the bus"/>
+ <event event="0x14" title="Mali GPU Fragment Processor 1" name="Texture descriptors reads" description="Number of 64-bit words containing texture descriptors read from the bus"/>
+ <event event="0x15" title="Mali GPU Fragment Processor 1" name="Texture descriptor remapping reads" description="Number of 64-bit words read from the bus when reading from the texture descriptor remapping table"/>
+ <event event="0x17" title="Mali GPU Fragment Processor 1" name="Load unit reads" description="Number of 64-bit words read from the bus by the LOAD sub-instruction"/>
+ <event event="0x18" title="Mali GPU Fragment Processor 1" name="Polygon count" description="Number of triangles read from the polygon list"/>
+ <event event="0x19" title="Mali GPU Fragment Processor 1" name="Pixel rectangle count" description="Number of pixel rectangles read from the polygon list"/>
+ <event event="0x1a" title="Mali GPU Fragment Processor 1" name="Lines count" description="Number of lines read from the polygon list"/>
+ <event event="0x1b" title="Mali GPU Fragment Processor 1" name="Points count" description="Number of points read from the polygon list"/>
+ <event event="0x1c" title="Mali GPU Fragment Processor 1" name="Stall cycles PolygonListReader" description="Number of clock cycles the Polygon List Reader waited for output being collected"/>
+ <event event="0x1d" title="Mali GPU Fragment Processor 1" name="Stall cycles triangle setup" description="Number of clock cycles the TSC waited for input"/>
+ <event event="0x1e" title="Mali GPU Fragment Processor 1" name="Quad rasterized count" description="Number of 2x?2 quads output from rasterizer"/>
+ <event event="0x1f" title="Mali GPU Fragment Processor 1" name="Fragment rasterized count" description="Number of fragment rasterized. Fragments/(Quads*4) gives average actual fragments per quad"/>
+ <event event="0x20" title="Mali GPU Fragment Processor 1" name="Fragment rejected fragment-kill count" description="Number of fragments exiting the fragment shader as killed"/>
+ <event event="0x21" title="Mali GPU Fragment Processor 1" name="Fragment rejected fwd-fragment-kill count" description="Number of fragments killed by forward fragment kill"/>
+ <event event="0x22" title="Mali GPU Fragment Processor 1" name="Fragment passed z/stencil count" description="Number of fragments passing Z and stencil test"/>
+ <event event="0x23" title="Mali GPU Fragment Processor 1" name="Patches rejected early z/stencil count" description="Number of patches rejected by EarlyZ. A patch can be 8x8, 4x4 or 2x2 pixels"/>
+ <event event="0x24" title="Mali GPU Fragment Processor 1" name="Patches evaluated" description="Number of patches evaluated for EarlyZ rejection"/>
+ <event event="0x25" title="Mali GPU Fragment Processor 1" name="Instruction completed count" description="Number of fragment shader instruction words completed. It is a function of pixels processed and the length of the shader programs"/>
+ <event event="0x26" title="Mali GPU Fragment Processor 1" name="Instruction failed rendezvous count" description="Number of fragment shader instructions not completed because of failed Rendezvous"/>
+ <event event="0x27" title="Mali GPU Fragment Processor 1" name="Instruction failed varying-miss count" description="Number of fragment shader instructions not completed because of failed varying operation"/>
+ <event event="0x28" title="Mali GPU Fragment Processor 1" name="Instruction failed texture-miss count" description="Number of fragment shader instructions not completed because of failed texture operation"/>
+ <event event="0x29" title="Mali GPU Fragment Processor 1" name="Instruction failed load-miss count" description="Number of fragment shader instructions not completed because of failed load operation"/>
+ <event event="0x2a" title="Mali GPU Fragment Processor 1" name="Instruction failed tile read-miss count" description="Number of fragment shader instructions not completed because of failed read from the tilebuffer"/>
+ <event event="0x2b" title="Mali GPU Fragment Processor 1" name="Instruction failed store-miss count" description="Number of fragment shader instructions not completed because of failed store operation"/>
+ <event event="0x2c" title="Mali GPU Fragment Processor 1" name="Rendezvous breakage count" description="Number of Rendezvous breakages reported"/>
+ <event event="0x2d" title="Mali GPU Fragment Processor 1" name="Pipeline bubbles cycle count" description="Number of unused cycles in the fragment shader while rendering is active"/>
+ <event event="0x2e" title="Mali GPU Fragment Processor 1" name="Texture mapper multipass count" description="Number of texture operations looped because of more texture passes needed"/>
+ <event event="0x2f" title="Mali GPU Fragment Processor 1" name="Texture mapper cycle count" description="Number of texture operation cycles"/>
+ <event event="0x30" title="Mali GPU Fragment Processor 1" name="Vertex cache hit count" description="Number of times a requested vertex was found in the cache (Number of vertex cache hits)"/>
+ <event event="0x31" title="Mali GPU Fragment Processor 1" name="Vertex cache miss count" description="Number of times a requested vertex was not found in the cache (Number of vertex cache misses)"/>
+ <event event="0x32" title="Mali GPU Fragment Processor 1" name="Varying cache hit count" description="Number of times a requested varying was found in the cache (Number of varying cache hits)"/>
+ <event event="0x33" title="Mali GPU Fragment Processor 1" name="Varying cache miss count" description="Number of times a requested varying was not found in the cache (Number of varying cache misses)"/>
+ <event event="0x34" title="Mali GPU Fragment Processor 1" name="Varying cache conflict miss count" description="Number of times a requested varying was not in the cache and its value, retrieved from memory, must overwrite an older cache entry. This happens when an access pattern cannot be serviced by the cache"/>
+ <event event="0x35" title="Mali GPU Fragment Processor 1" name="Texture cache hit count" description="Number of times a requested texel was found in the texture cache (Number of texture cache hits)"/>
+ <event event="0x36" title="Mali GPU Fragment Processor 1" name="Texture cache miss count" description="Number of times a requested texel was not found in the texture cache (Number of texture cache misses)"/>
+ <event event="0x37" title="Mali GPU Fragment Processor 1" name="Texture cache conflict miss count" description="Number of times a requested texel was not in the cache and its value, retrieved from memory, must overwrite an older cache entry. This happens when an access pattern cannot be serviced by the cache"/>
+ <event event="0x38" title="Mali GPU Fragment Processor 1" name="(Mali200)Palette cache hit count; (Mali400)Compressed texture cache hit count" description="Number of times a requested item was found in the cache."/>
+ <event event="0x39" title="Mali GPU Fragment Processor 1" name="(Mali200)Palette cache miss count; (Mali400)Compressed texture cache miss count" description="Number of times a requested item was not found in the cache."/>
+ <event event="0x3a" title="Mali GPU Fragment Processor 1" name="Load/Store cache hit count" description="Number of hits in the load/store cache"/>
+ <event event="0x3b" title="Mali GPU Fragment Processor 1" name="Load/Store cache miss count" description="Number of misses in the load/store cache"/>
+ <event event="0x3c" title="Mali GPU Fragment Processor 1" name="Program cache hit count" description="Number of hits in the program cache"/>
+ <event event="0x3d" title="Mali GPU Fragment Processor 1" name="Program cache miss count" description="Number of misses in the program cache"/>
+ </category>
+ <category name="Mali-400-FP2" counter_set="ARM_Mali-400_FP2_cntX" per_cpu="no">
+ <event event="0x00" title="Mali GPU Fragment Processor 2" name="Active clock cycles" description="Active clock cycles, between polygon start and IRQ"/>
+ <event event="0x02" title="Mali GPU Fragment Processor 2" name="Total bus reads" description="Total number of 64-bit words read from the bus"/>
+ <event event="0x03" title="Mali GPU Fragment Processor 2" name="Total bus writes" description="Total number of 64-bit words written to the bus"/>
+ <event event="0x04" title="Mali GPU Fragment Processor 2" name="Bus read request cycles" description="MALI_CINSTR_PP_BUS_READ_REQUEST_CYCLES_COUNT"/>
+ <event event="0x05" title="Mali GPU Fragment Processor 2" name="Bus write request cycles" description="MALI_CINSTR_PP_BUS_WRITE_REQUEST_CYCLES_COUNT"/>
+ <event event="0x06" title="Mali GPU Fragment Processor 2" name="Bus read transactions count" description="Number of read requests accepted by the bus"/>
+ <event event="0x07" title="Mali GPU Fragment Processor 2" name="Bus write transactions" description="Number of write requests accepted by the bus"/>
+ <event event="0x09" title="Mali GPU Fragment Processor 2" name="Tile writeback writes" description="64-bit words written to the bus by the writeback unit"/>
+ <event event="0x0a" title="Mali GPU Fragment Processor 2" name="Store unit writes" description="64-bit words written to the bus by the store unit"/>
+ <event event="0x0d" title="Mali GPU Fragment Processor 2" name="Texture cache uncompressed reads" description="Number of 64-bit words read from the bus into the uncompressed textures cache"/>
+ <event event="0x0e" title="Mali GPU Fragment Processor 2" name="Polygon list reads" description="Number of 64-bit words read from the bus by the polygon list reader"/>
+ <event event="0x0f" title="Mali GPU Fragment Processor 2" name="RSW reads" description="Number of 64-bit words read from the bus into the Render State Word register"/>
+ <event event="0x10" title="Mali GPU Fragment Processor 2" name="Vertex cache reads" description="Number of 64-bit words read from the bus into the vertex cache"/>
+ <event event="0x11" title="Mali GPU Fragment Processor 2" name="Uniform remapping reads" description="Number of 64-bit words read from the bus when reading from the uniform remapping table"/>
+ <event event="0x12" title="Mali GPU Fragment Processor 2" name="Program cache reads" description="Number of 64-bit words read from the bus into the fragment shader program cache"/>
+ <event event="0x13" title="Mali GPU Fragment Processor 2" name="Varying reads" description="Number of 64-bit words containing varyings generated by the vertex processing read from the bus"/>
+ <event event="0x14" title="Mali GPU Fragment Processor 2" name="Texture descriptors reads" description="Number of 64-bit words containing texture descriptors read from the bus"/>
+ <event event="0x15" title="Mali GPU Fragment Processor 2" name="Texture descriptor remapping reads" description="Number of 64-bit words read from the bus when reading from the texture descriptor remapping table"/>
+ <event event="0x17" title="Mali GPU Fragment Processor 2" name="Load unit reads" description="Number of 64-bit words read from the bus by the LOAD sub-instruction"/>
+ <event event="0x18" title="Mali GPU Fragment Processor 2" name="Polygon count" description="Number of triangles read from the polygon list"/>
+ <event event="0x19" title="Mali GPU Fragment Processor 2" name="Pixel rectangle count" description="Number of pixel rectangles read from the polygon list"/>
+ <event event="0x1a" title="Mali GPU Fragment Processor 2" name="Lines count" description="Number of lines read from the polygon list"/>
+ <event event="0x1b" title="Mali GPU Fragment Processor 2" name="Points count" description="Number of points read from the polygon list"/>
+ <event event="0x1c" title="Mali GPU Fragment Processor 2" name="Stall cycles PolygonListReader" description="Number of clock cycles the Polygon List Reader waited for output being collected"/>
+ <event event="0x1d" title="Mali GPU Fragment Processor 2" name="Stall cycles triangle setup" description="Number of clock cycles the TSC waited for input"/>
+ <event event="0x1e" title="Mali GPU Fragment Processor 2" name="Quad rasterized count" description="Number of 2x?2 quads output from rasterizer"/>
+ <event event="0x1f" title="Mali GPU Fragment Processor 2" name="Fragment rasterized count" description="Number of fragment rasterized. Fragments/(Quads*4) gives average actual fragments per quad"/>
+ <event event="0x20" title="Mali GPU Fragment Processor 2" name="Fragment rejected fragment-kill count" description="Number of fragments exiting the fragment shader as killed"/>
+ <event event="0x21" title="Mali GPU Fragment Processor 2" name="Fragment rejected fwd-fragment-kill count" description="Number of fragments killed by forward fragment kill"/>
+ <event event="0x22" title="Mali GPU Fragment Processor 2" name="Fragment passed z/stencil count" description="Number of fragments passing Z and stencil test"/>
+ <event event="0x23" title="Mali GPU Fragment Processor 2" name="Patches rejected early z/stencil count" description="Number of patches rejected by EarlyZ. A patch can be 8x8, 4x4 or 2x2 pixels"/>
+ <event event="0x24" title="Mali GPU Fragment Processor 2" name="Patches evaluated" description="Number of patches evaluated for EarlyZ rejection"/>
+ <event event="0x25" title="Mali GPU Fragment Processor 2" name="Instruction completed count" description="Number of fragment shader instruction words completed. It is a function of pixels processed and the length of the shader programs"/>
+ <event event="0x26" title="Mali GPU Fragment Processor 2" name="Instruction failed rendezvous count" description="Number of fragment shader instructions not completed because of failed Rendezvous"/>
+ <event event="0x27" title="Mali GPU Fragment Processor 2" name="Instruction failed varying-miss count" description="Number of fragment shader instructions not completed because of failed varying operation"/>
+ <event event="0x28" title="Mali GPU Fragment Processor 2" name="Instruction failed texture-miss count" description="Number of fragment shader instructions not completed because of failed texture operation"/>
+ <event event="0x29" title="Mali GPU Fragment Processor 2" name="Instruction failed load-miss count" description="Number of fragment shader instructions not completed because of failed load operation"/>
+ <event event="0x2a" title="Mali GPU Fragment Processor 2" name="Instruction failed tile read-miss count" description="Number of fragment shader instructions not completed because of failed read from the tilebuffer"/>
+ <event event="0x2b" title="Mali GPU Fragment Processor 2" name="Instruction failed store-miss count" description="Number of fragment shader instructions not completed because of failed store operation"/>
+ <event event="0x2c" title="Mali GPU Fragment Processor 2" name="Rendezvous breakage count" description="Number of Rendezvous breakages reported"/>
+ <event event="0x2d" title="Mali GPU Fragment Processor 2" name="Pipeline bubbles cycle count" description="Number of unused cycles in the fragment shader while rendering is active"/>
+ <event event="0x2e" title="Mali GPU Fragment Processor 2" name="Texture mapper multipass count" description="Number of texture operations looped because of more texture passes needed"/>
+ <event event="0x2f" title="Mali GPU Fragment Processor 2" name="Texture mapper cycle count" description="Number of texture operation cycles"/>
+ <event event="0x30" title="Mali GPU Fragment Processor 2" name="Vertex cache hit count" description="Number of times a requested vertex was found in the cache (Number of vertex cache hits)"/>
+ <event event="0x31" title="Mali GPU Fragment Processor 2" name="Vertex cache miss count" description="Number of times a requested vertex was not found in the cache (Number of vertex cache misses)"/>
+ <event event="0x32" title="Mali GPU Fragment Processor 2" name="Varying cache hit count" description="Number of times a requested varying was found in the cache (Number of varying cache hits)"/>
+ <event event="0x33" title="Mali GPU Fragment Processor 2" name="Varying cache miss count" description="Number of times a requested varying was not found in the cache (Number of varying cache misses)"/>
+ <event event="0x34" title="Mali GPU Fragment Processor 2" name="Varying cache conflict miss count" description="Number of times a requested varying was not in the cache and its value, retrieved from memory, must overwrite an older cache entry. This happens when an access pattern cannot be serviced by the cache"/>
+ <event event="0x35" title="Mali GPU Fragment Processor 2" name="Texture cache hit count" description="Number of times a requested texel was found in the texture cache (Number of texture cache hits)"/>
+ <event event="0x36" title="Mali GPU Fragment Processor 2" name="Texture cache miss count" description="Number of times a requested texel was not found in the texture cache (Number of texture cache misses)"/>
+ <event event="0x37" title="Mali GPU Fragment Processor 2" name="Texture cache conflict miss count" description="Number of times a requested texel was not in the cache and its value, retrieved from memory, must overwrite an older cache entry. This happens when an access pattern cannot be serviced by the cache"/>
+ <event event="0x38" title="Mali GPU Fragment Processor 2" name="(Mali200)Palette cache hit count; (Mali400)Compressed texture cache hit count" description="Number of times a requested item was found in the cache."/>
+ <event event="0x39" title="Mali GPU Fragment Processor 2" name="(Mali200)Palette cache miss count; (Mali400)Compressed texture cache miss count" description="Number of times a requested item was not found in the cache."/>
+ <event event="0x3a" title="Mali GPU Fragment Processor 2" name="Load/Store cache hit count" description="Number of hits in the load/store cache"/>
+ <event event="0x3b" title="Mali GPU Fragment Processor 2" name="Load/Store cache miss count" description="Number of misses in the load/store cache"/>
+ <event event="0x3c" title="Mali GPU Fragment Processor 2" name="Program cache hit count" description="Number of hits in the program cache"/>
+ <event event="0x3d" title="Mali GPU Fragment Processor 2" name="Program cache miss count" description="Number of misses in the program cache"/>
+ </category>
+ <category name="Mali-400-FP3" counter_set="ARM_Mali-400_FP3_cntX" per_cpu="no">
+ <event event="0x00" title="Mali GPU Fragment Processor 3" name="Active clock cycles" description="Active clock cycles, between polygon start and IRQ"/>
+ <event event="0x02" title="Mali GPU Fragment Processor 3" name="Total bus reads" description="Total number of 64-bit words read from the bus"/>
+ <event event="0x03" title="Mali GPU Fragment Processor 3" name="Total bus writes" description="Total number of 64-bit words written to the bus"/>
+ <event event="0x04" title="Mali GPU Fragment Processor 3" name="Bus read request cycles" description="MALI_CINSTR_PP_BUS_READ_REQUEST_CYCLES_COUNT"/>
+ <event event="0x05" title="Mali GPU Fragment Processor 3" name="Bus write request cycles" description="MALI_CINSTR_PP_BUS_WRITE_REQUEST_CYCLES_COUNT"/>
+ <event event="0x06" title="Mali GPU Fragment Processor 3" name="Bus read transactions count" description="Number of read requests accepted by the bus"/>
+ <event event="0x07" title="Mali GPU Fragment Processor 3" name="Bus write transactions" description="Number of write requests accepted by the bus"/>
+ <event event="0x09" title="Mali GPU Fragment Processor 3" name="Tile writeback writes" description="64-bit words written to the bus by the writeback unit"/>
+ <event event="0x0a" title="Mali GPU Fragment Processor 3" name="Store unit writes" description="64-bit words written to the bus by the store unit"/>
+ <event event="0x0d" title="Mali GPU Fragment Processor 3" name="Texture cache uncompressed reads" description="Number of 64-bit words read from the bus into the uncompressed textures cache"/>
+ <event event="0x0e" title="Mali GPU Fragment Processor 3" name="Polygon list reads" description="Number of 64-bit words read from the bus by the polygon list reader"/>
+ <event event="0x0f" title="Mali GPU Fragment Processor 3" name="RSW reads" description="Number of 64-bit words read from the bus into the Render State Word register"/>
+ <event event="0x10" title="Mali GPU Fragment Processor 3" name="Vertex cache reads" description="Number of 64-bit words read from the bus into the vertex cache"/>
+ <event event="0x11" title="Mali GPU Fragment Processor 3" name="Uniform remapping reads" description="Number of 64-bit words read from the bus when reading from the uniform remapping table"/>
+ <event event="0x12" title="Mali GPU Fragment Processor 3" name="Program cache reads" description="Number of 64-bit words read from the bus into the fragment shader program cache"/>
+ <event event="0x13" title="Mali GPU Fragment Processor 3" name="Varying reads" description="Number of 64-bit words containing varyings generated by the vertex processing read from the bus"/>
+ <event event="0x14" title="Mali GPU Fragment Processor 3" name="Texture descriptors reads" description="Number of 64-bit words containing texture descriptors read from the bus"/>
+ <event event="0x15" title="Mali GPU Fragment Processor 3" name="Texture descriptor remapping reads" description="Number of 64-bit words read from the bus when reading from the texture descriptor remapping table"/>
+ <event event="0x17" title="Mali GPU Fragment Processor 3" name="Load unit reads" description="Number of 64-bit words read from the bus by the LOAD sub-instruction"/>
+ <event event="0x18" title="Mali GPU Fragment Processor 3" name="Polygon count" description="Number of triangles read from the polygon list"/>
+ <event event="0x19" title="Mali GPU Fragment Processor 3" name="Pixel rectangle count" description="Number of pixel rectangles read from the polygon list"/>
+ <event event="0x1a" title="Mali GPU Fragment Processor 3" name="Lines count" description="Number of lines read from the polygon list"/>
+ <event event="0x1b" title="Mali GPU Fragment Processor 3" name="Points count" description="Number of points read from the polygon list"/>
+ <event event="0x1c" title="Mali GPU Fragment Processor 3" name="Stall cycles PolygonListReader" description="Number of clock cycles the Polygon List Reader waited for output being collected"/>
+ <event event="0x1d" title="Mali GPU Fragment Processor 3" name="Stall cycles triangle setup" description="Number of clock cycles the TSC waited for input"/>
+ <event event="0x1e" title="Mali GPU Fragment Processor 3" name="Quad rasterized count" description="Number of 2x?2 quads output from rasterizer"/>
+ <event event="0x1f" title="Mali GPU Fragment Processor 3" name="Fragment rasterized count" description="Number of fragment rasterized. Fragments/(Quads*4) gives average actual fragments per quad"/>
+ <event event="0x20" title="Mali GPU Fragment Processor 3" name="Fragment rejected fragment-kill count" description="Number of fragments exiting the fragment shader as killed"/>
+ <event event="0x21" title="Mali GPU Fragment Processor 3" name="Fragment rejected fwd-fragment-kill count" description="Number of fragments killed by forward fragment kill"/>
+ <event event="0x22" title="Mali GPU Fragment Processor 3" name="Fragment passed z/stencil count" description="Number of fragments passing Z and stencil test"/>
+ <event event="0x23" title="Mali GPU Fragment Processor 3" name="Patches rejected early z/stencil count" description="Number of patches rejected by EarlyZ. A patch can be 8x8, 4x4 or 2x2 pixels"/>
+ <event event="0x24" title="Mali GPU Fragment Processor 3" name="Patches evaluated" description="Number of patches evaluated for EarlyZ rejection"/>
+ <event event="0x25" title="Mali GPU Fragment Processor 3" name="Instruction completed count" description="Number of fragment shader instruction words completed. It is a function of pixels processed and the length of the shader programs"/>
+ <event event="0x26" title="Mali GPU Fragment Processor 3" name="Instruction failed rendezvous count" description="Number of fragment shader instructions not completed because of failed Rendezvous"/>
+ <event event="0x27" title="Mali GPU Fragment Processor 3" name="Instruction failed varying-miss count" description="Number of fragment shader instructions not completed because of failed varying operation"/>
+ <event event="0x28" title="Mali GPU Fragment Processor 3" name="Instruction failed texture-miss count" description="Number of fragment shader instructions not completed because of failed texture operation"/>
+ <event event="0x29" title="Mali GPU Fragment Processor 3" name="Instruction failed load-miss count" description="Number of fragment shader instructions not completed because of failed load operation"/>
+ <event event="0x2a" title="Mali GPU Fragment Processor 3" name="Instruction failed tile read-miss count" description="Number of fragment shader instructions not completed because of failed read from the tilebuffer"/>
+ <event event="0x2b" title="Mali GPU Fragment Processor 3" name="Instruction failed store-miss count" description="Number of fragment shader instructions not completed because of failed store operation"/>
+ <event event="0x2c" title="Mali GPU Fragment Processor 3" name="Rendezvous breakage count" description="Number of Rendezvous breakages reported"/>
+ <event event="0x2d" title="Mali GPU Fragment Processor 3" name="Pipeline bubbles cycle count" description="Number of unused cycles in the fragment shader while rendering is active"/>
+ <event event="0x2e" title="Mali GPU Fragment Processor 3" name="Texture mapper multipass count" description="Number of texture operations looped because of more texture passes needed"/>
+ <event event="0x2f" title="Mali GPU Fragment Processor 3" name="Texture mapper cycle count" description="Number of texture operation cycles"/>
+ <event event="0x30" title="Mali GPU Fragment Processor 3" name="Vertex cache hit count" description="Number of times a requested vertex was found in the cache (Number of vertex cache hits)"/>
+ <event event="0x31" title="Mali GPU Fragment Processor 3" name="Vertex cache miss count" description="Number of times a requested vertex was not found in the cache (Number of vertex cache misses)"/>
+ <event event="0x32" title="Mali GPU Fragment Processor 3" name="Varying cache hit count" description="Number of times a requested varying was found in the cache (Number of varying cache hits)"/>
+ <event event="0x33" title="Mali GPU Fragment Processor 3" name="Varying cache miss count" description="Number of times a requested varying was not found in the cache (Number of varying cache misses)"/>
+ <event event="0x34" title="Mali GPU Fragment Processor 3" name="Varying cache conflict miss count" description="Number of times a requested varying was not in the cache and its value, retrieved from memory, must overwrite an older cache entry. This happens when an access pattern cannot be serviced by the cache"/>
+ <event event="0x35" title="Mali GPU Fragment Processor 3" name="Texture cache hit count" description="Number of times a requested texel was found in the texture cache (Number of texture cache hits)"/>
+ <event event="0x36" title="Mali GPU Fragment Processor 3" name="Texture cache miss count" description="Number of times a requested texel was not found in the texture cache (Number of texture cache misses)"/>
+ <event event="0x37" title="Mali GPU Fragment Processor 3" name="Texture cache conflict miss count" description="Number of times a requested texel was not in the cache and its value, retrieved from memory, must overwrite an older cache entry. This happens when an access pattern cannot be serviced by the cache"/>
+ <event event="0x38" title="Mali GPU Fragment Processor 3" name="(Mali200)Palette cache hit count; (Mali400)Compressed texture cache hit count" description="Number of times a requested item was found in the cache."/>
+ <event event="0x39" title="Mali GPU Fragment Processor 3" name="(Mali200)Palette cache miss count; (Mali400)Compressed texture cache miss count" description="Number of times a requested item was not found in the cache."/>
+ <event event="0x3a" title="Mali GPU Fragment Processor 3" name="Load/Store cache hit count" description="Number of hits in the load/store cache"/>
+ <event event="0x3b" title="Mali GPU Fragment Processor 3" name="Load/Store cache miss count" description="Number of misses in the load/store cache"/>
+ <event event="0x3c" title="Mali GPU Fragment Processor 3" name="Program cache hit count" description="Number of hits in the program cache"/>
+ <event event="0x3d" title="Mali GPU Fragment Processor 3" name="Program cache miss count" description="Number of misses in the program cache"/>
+ </category>
+ <category name="Mali-400-L2" counter_set="ARM_Mali-400_L2_cntX" per_cpu="no">
+ <event event="0x01" title="Mali L2 Cache" name="Total clock cycles" description="Total clock cycles"/>
+ <event event="0x02" title="Mali L2 Cache" name="Active clock cycles" description="Active clock cycles" />
+ <event event="0x08" title="Mali L2 Cache" name="Read transactions, master" description="Read transactions, master" />
+ <event event="0x09" title="Mali L2 Cache" name="Write transactions, master" description="Write transactions, master" />
+ <event event="0x0a" title="Mali L2 Cache" name="Words read, master" description="Words read, master" />
+ <event event="0x0b" title="Mali L2 Cache" name="Words written, master" description="Words written, master" />
+ <event event="0x10" title="Mali L2 Cache" name="Read transactions, all slaves" description="Read transactions, all slaves" />
+ <event event="0x11" title="Mali L2 Cache" name="Write transactions, all slaves" description="Write transactions, all slaves" />
+ <event event="0x12" title="Mali L2 Cache" name="Words read, all slaves" description="Words read, all slaves" />
+ <event event="0x13" title="Mali L2 Cache" name="Words written, all slaves" description="Words written, all slaves" />
+ <event event="0x14" title="Mali L2 Cache" name="Read hits, all slaves" description="Read hits, all slaves" />
+ <event event="0x15" title="Mali L2 Cache" name="Read misses, all slaves" description="Read misses, all slaves" />
+ <event event="0x16" title="Mali L2 Cache" name="Write invalidates, all slaves" description="Write invalidates, all slaves" />
+ <event event="0x17" title="Mali L2 Cache" name="Read invalidates, all slaves" description="Read invalidates, all slaves" />
+ <event event="0x18" title="Mali L2 Cache" name="Cacheable read transactions, all slaves" description="Cacheable read transactions, all slaves" />
+ <event event="0x20" title="Mali L2 Cache" name="Read transactions, slave 0" description="Read transactions, slave 0" />
+ <event event="0x21" title="Mali L2 Cache" name="Write transactions, slave 0" description="Write transactions, slave 0" />
+ <event event="0x22" title="Mali L2 Cache" name="Words read, slave 0" description="Words read, slave 0" />
+ <event event="0x23" title="Mali L2 Cache" name="Words written, slave 0" description="Words written, slave 0" />
+ <event event="0x24" title="Mali L2 Cache" name="Read hits, slave 0" description="Read hits, slave 0" />
+ <event event="0x25" title="Mali L2 Cache" name="Read misses, slave 0" description="Read misses, slave 0" />
+ <event event="0x26" title="Mali L2 Cache" name="Write invalidates, slave 0" description="Write invalidates, slave 0" />
+ <event event="0x27" title="Mali L2 Cache" name="Read invalidates, slave 0" description="Read invalidates, slave 0" />
+ <event event="0x28" title="Mali L2 Cache" name="Cacheable read transactions, slave 0" description="Cacheable read transactions, slave 0" />
+ <event event="0x30" title="Mali L2 Cache" name="Read transactions, slave 1" description="Read transactions, slave 1" />
+ <event event="0x31" title="Mali L2 Cache" name="Write transactions, slave 1" description="Write transactions, slave 1" />
+ <event event="0x32" title="Mali L2 Cache" name="Words read, slave 1" description="Words read, slave 1" />
+ <event event="0x33" title="Mali L2 Cache" name="Words written, slave 1" description="Words written, slave 1" />
+ <event event="0x34" title="Mali L2 Cache" name="Read hits, slave 1" description="Read hits, slave 1" />
+ <event event="0x35" title="Mali L2 Cache" name="Read misses, slave 1" description="Read misses, slave 1" />
+ <event event="0x36" title="Mali L2 Cache" name="Write invalidates, slave 1" description="Write invalidates, slave 1" />
+ <event event="0x37" title="Mali L2 Cache" name="Read invalidates, slave 1" description="Read invalidates, slave 1" />
+ <event event="0x38" title="Mali L2 Cache" name="Cacheable read transactions, slave 1" description="Cacheable read transactions, slave 1" />
+ <event event="0x40" title="Mali L2 Cache" name="Read transactions, slave 2" description="Read transactions, slave 2" />
+ <event event="0x41" title="Mali L2 Cache" name="Write transactions, slave 2" description="Write transactions, slave 2" />
+ <event event="0x42" title="Mali L2 Cache" name="Words read, slave 2" description="Words read, slave 2" />
+ <event event="0x43" title="Mali L2 Cache" name="Words written, slave 2" description="Words written, slave 2" />
+ <event event="0x44" title="Mali L2 Cache" name="Read hits, slave 2" description="Read hits, slave 2" />
+ <event event="0x45" title="Mali L2 Cache" name="Read misses, slave 2" description="Read misses, slave 2" />
+ <event event="0x46" title="Mali L2 Cache" name="Write invalidates, slave 2" description="Write invalidates, slave 2" />
+ <event event="0x47" title="Mali L2 Cache" name="Read invalidates, slave 2" description="Read invalidates, slave 2" />
+ <event event="0x48" title="Mali L2 Cache" name="Cacheable read transactions, slave 2" description="Cacheable read transactions, slave 2" />
+ <event event="0x50" title="Mali L2 Cache" name="Read transactions, slave 3" description="Read transactions, slave 3" />
+ <event event="0x51" title="Mali L2 Cache" name="Write transactions, slave 3" description="Write transactions, slave 3" />
+ <event event="0x52" title="Mali L2 Cache" name="Words read, slave 3" description="Words read, slave 3" />
+ <event event="0x53" title="Mali L2 Cache" name="Words written, slave 3" description="Words written, slave 3" />
+ <event event="0x54" title="Mali L2 Cache" name="Read hits, slave 3" description="Read hits, slave 3" />
+ <event event="0x55" title="Mali L2 Cache" name="Read misses, slave 3" description="Read misses, slave 3" />
+ <event event="0x56" title="Mali L2 Cache" name="Write invalidates, slave 3" description="Write invalidates, slave 3" />
+ <event event="0x57" title="Mali L2 Cache" name="Read invalidates, slave 3" description="Read invalidates, slave 3" />
+ <event event="0x58" title="Mali L2 Cache" name="Cacheable read transactions, slave 3" description="Cacheable read transactions, slave 3" />
+ <event event="0x60" title="Mali L2 Cache" name="Read transactions, slave 4" description="Read transactions, slave 4" />
+ <event event="0x61" title="Mali L2 Cache" name="Write transactions, slave 4" description="Write transactions, slave 4" />
+ <event event="0x62" title="Mali L2 Cache" name="Words read, slave 4" description="Words read, slave 4" />
+ <event event="0x63" title="Mali L2 Cache" name="Words written, slave 4" description="Words written, slave 4" />
+ <event event="0x64" title="Mali L2 Cache" name="Read hits, slave 4" description="Read hits, slave 4" />
+ <event event="0x65" title="Mali L2 Cache" name="Read misses, slave 4" description="Read misses, slave 4" />
+ <event event="0x66" title="Mali L2 Cache" name="Write invalidates, slave 4" description="Write invalidates, slave 4" />
+ <event event="0x67" title="Mali L2 Cache" name="Read invalidates, slave 4" description="Read invalidates, slave 4" />
+ <event event="0x68" title="Mali L2 Cache" name="Cacheable read transactions, slave 4" description="Cacheable read transactions, slave 4" />
+ </category>
+ <category name="ARM_Mali-400_Filmstrip" counter_set="ARM_Mali-400_Filmstrip_cntX" per_cpu="no">
+ <event event="0x040a" title="ARM_Mali-400_Filmstrip" name="Size 1:4, freq 1:10" description="Scaled framebuffer captures every 10th frame" />
+ </category>
+ <category name="Mali-400-SW" counter_set="ARM_Mali-400_SW_cntX" per_cpu="no">
+ <!-- EGL Counters -->
+ <event counter="ARM_Mali-400_SW_17" title="Mali EGL Software Counters" name="Blit Time" description="Time spent blitting the the framebuffer from video memory to framebuffer"/>
+ <!-- glDrawElements Counters -->
+ <event counter="ARM_Mali-400_SW_18" title="glDrawElements Statistics" name="Calls to glDrawElements" description="Number of calls to glDrawElements"/>
+ <event counter="ARM_Mali-400_SW_19" title="glDrawElements Statistics" name="Indices to glDrawElements" description="Number of indicies to glDrawElements"/>
+ <event counter="ARM_Mali-400_SW_20" title="glDrawElements Statistics" name="Transformed by glDrawElements" description="Number of vertices transformed by glDrawElements"/>
+ <!-- glDrawArrays Counters -->
+ <event counter="ARM_Mali-400_SW_21" title="glDrawArrays Statistics" name="Calls to glDrawArrays" description="Number of calls to glDrawArrays"/>
+ <event counter="ARM_Mali-400_SW_22" title="glDrawArrays Statistics" name="Transformed by glDrawArrays" description="Number of vertices transformed by glDrawArrays"/>
+ <!-- Draw Call Counters -->
+ <event counter="ARM_Mali-400_SW_23" title="Drawcall Statistics" name="Points" description="Number of calls to glDraw* with parameter GL_POINTS"/>
+ <event counter="ARM_Mali-400_SW_24" title="Drawcall Statistics" name="Lines" description="Number of calls to glDraw* with parameter GL_LINES"/>
+ <event counter="ARM_Mali-400_SW_25" title="Drawcall Statistics" name="Lineloop" description="Number of calls to glDraw* with parameter GL_LINE_LOOP"/>
+ <event counter="ARM_Mali-400_SW_26" title="Drawcall Statistics" name="Linestrip" description="Number of calls to glDraw* with parameter GL_LINE_STRIP"/>
+ <event counter="ARM_Mali-400_SW_27" title="Drawcall Statistics" name="Triangles" description="Number of calls to glDraw* with parameter GL_TRIANGLES"/>
+ <event counter="ARM_Mali-400_SW_28" title="Drawcall Statistics" name="Trianglestrip" description="Number of calls to glDraw* with parameter GL_TRIANGLE_STRIP"/>
+ <event counter="ARM_Mali-400_SW_29" title="Drawcall Statistics" name="Trianglefan" description="Number of calls to glDraw* with parameter GL_TRIANGLE_FAN"/>
+ <event counter="ARM_Mali-400_SW_30" title="Drawcall Statistics" name="Vertex Upload Time (us)" description="Time spent uploading vertex attributes and faceindex data not present in a VBO"/>
+ <event counter="ARM_Mali-400_SW_31" title="Drawcall Statistics" name="Uniform Bytes Copied (bytes)" description="Number of bytes copied to Mali memory as a result of uniforms update"/>
+ <!-- Buffer Profiling Counters -->
+ <event counter="ARM_Mali-400_SW_32" title="Buffer Profiling" name="Texture Upload Time (ms)" description="Time spent uploading textures"/>
+ <event counter="ARM_Mali-400_SW_33" title="Buffer Profiling" name="VBO Upload Time (ms)" description="Time spent uploading vertex buffer objects"/>
+ <event counter="ARM_Mali-400_SW_34" title="Buffer Profiling" name="FBO Flushes" description="Number of flushed on framebuffer attachement"/>
+ <!-- OpenGL ES 1.1 Emulation -->
+ <event counter="ARM_Mali-400_SW_35" title="Fixed-function Emulation" name="# Vertex Shaders Generated" description="Number of vertex shaders generated"/>
+ <event counter="ARM_Mali-400_SW_36" title="Fixed-function Emulation" name="# Fragment Shaders Generated" description="Number of fragment shaders generated"/>
+ <!-- Geometry Statistics -->
+ <event counter="ARM_Mali-400_SW_50" title="Geometry Statistics" name="Triangles" description="The total number of triangles passed to GLES per-frame"/>
+ <event counter="ARM_Mali-400_SW_51" title="Geometry Statistics" name="Independent Triangles" description="Number of triangles passed to GLES using the mode GL_TRIANGLES"/>
+ <event counter="ARM_Mali-400_SW_52" title="Geometry Statistics" name="Strip Triangles" description="Number of triangles passed to GLES using the mode GL_TRIANGLE_STRIP"/>
+ <event counter="ARM_Mali-400_SW_53" title="Geometry Statistics" name="Fan Triangles" description="Number of triangles passed to GLES using the mode GL_TRIANGLE_FAN"/>
+ <event counter="ARM_Mali-400_SW_54" title="Geometry Statistics" name="Lines" description="Number of lines passed to GLES per-frame"/>
+ <event counter="ARM_Mali-400_SW_55" title="Geometry Statistics" name="Independent Lines" description="Number of lines passed to GLES using the mode GL_LINES"/>
+ <event counter="ARM_Mali-400_SW_56" title="Geometry Statistics" name="Strip Lines" description="Number of lines passed to GLES using the mode GL_LINE_STRIP"/>
+ <event counter="ARM_Mali-400_SW_57" title="Geometry Statistics" name="Loop Lines" description="Number of lines passed to GLES using the mode GL_LINE_LOOP"/>
+ </category>
+
diff --git a/drivers/gator/daemon/events-Scorpion.xml b/drivers/gator/daemon/events-Scorpion.xml
new file mode 100644
index 00000000000..8ad196a2dbf
--- /dev/null
+++ b/drivers/gator/daemon/events-Scorpion.xml
@@ -0,0 +1,113 @@
+ <counter_set name="Scorpion_cntX">
+ <counter name="Scorpion_cnt0"/>
+ <counter name="Scorpion_cnt1"/>
+ <counter name="Scorpion_cnt2"/>
+ <counter name="Scorpion_cnt3"/>
+ </counter_set>
+ <category name="Scorpion" counter_set="Scorpion_cntX" per_cpu="yes">
+ <event counter="Scorpion_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/>
+ <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
+ <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="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
+ <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
+ <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="0x0c" title="Program Counter" name="SW change" description="Software change of PC, except by an exception, architecturally executed"/>
+ <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
+ <event event="0x0e" title="Branch" name="Procedure Return" description="Procedure return architecturally executed (not by exceptions)"/>
+ <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access 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="0x4c" title="Scorpion" name="ICACHE_EXPL_INV" description="I-cache explicit invalidates"/>
+ <event event="0x4d" title="Scorpion" name="ICACHE_MISS" description="I-cache misses"/>
+ <event event="0x4e" title="Scorpion" name="ICACHE_ACCESS" description="I-cache accesses"/>
+ <event event="0x4f" title="Scorpion" name="ICACHE_CACHEREQ_L2" description="I-cache cacheable requests to L2"/>
+ <event event="0x50" title="Scorpion" name="ICACHE_NOCACHE_L2" description="I-cache non-cacheable requests to L2"/>
+ <event event="0x51" title="Scorpion" name="HIQUP_NOPED" description="Conditional instructions HIQUPs NOPed"/>
+ <event event="0x52" title="Scorpion" name="DATA_ABORT" description="Interrupts and Exceptions Data Abort"/>
+ <event event="0x53" title="Scorpion" name="IRQ" description="Interrupts and Exceptions IRQ"/>
+ <event event="0x54" title="Scorpion" name="FIQ" description="Interrupts and Exceptions FIQ"/>
+ <event event="0x55" title="Scorpion" name="ALL_EXCPT" description="Interrupts and Exceptions All interrupts"/>
+ <event event="0x56" title="Scorpion" name="UNDEF" description="Interrupts and Exceptions Undefined"/>
+ <event event="0x57" title="Scorpion" name="SVC" description="Interrupts and Exceptions SVC"/>
+ <event event="0x58" title="Scorpion" name="SMC" description="Interrupts and Exceptions SMC"/>
+ <event event="0x59" title="Scorpion" name="PREFETCH_ABORT" description="Interrupts and Exceptions Prefetch Abort"/>
+ <event event="0x5a" title="Scorpion" name="INDEX_CHECK" description="Interrupts and Exceptions Index Check"/>
+ <event event="0x5b" title="Scorpion" name="NULL_CHECK" description="Interrupts and Exceptions Null Check"/>
+ <event event="0x5c" title="Scorpion" name="EXPL_ICIALLU" description="I-cache and BTAC Invalidates Explicit ICIALLU"/>
+ <event event="0x5d" title="Scorpion" name="IMPL_ICIALLU" description="I-cache and BTAC Invalidates Implicit ICIALLU"/>
+ <event event="0x5e" title="Scorpion" name="NONICIALLU_BTAC_INV" description="I-cache and BTAC Invalidates Non-ICIALLU BTAC Invalidate"/>
+ <event event="0x5f" title="Scorpion" name="ICIMVAU_IMPL_ICIALLU" description="I-cache and BTAC Invalidates ICIMVAU-implied ICIALLU"/>
+ <event event="0x60" title="Scorpion" name="SPIPE_ONLY_CYCLES" description="Issue S-pipe only issue cycles"/>
+ <event event="0x61" title="Scorpion" name="XPIPE_ONLY_CYCLES" description="Issue X-pipe only issue cycles"/>
+ <event event="0x62" title="Scorpion" name="DUAL_CYCLES" description="Issue dual issue cycles"/>
+ <event event="0x63" title="Scorpion" name="DISPATCH_ANY_CYCLES" description="Dispatch any dispatch cycles"/>
+ <event event="0x64" title="Scorpion" name="FIFO_FULLBLK_CMT" description="Commits Trace FIFO full Blk CMT"/>
+ <event event="0x65" title="Scorpion" name="FAIL_COND_INST" description="Conditional instructions failing conditional instrs (excluding branches)"/>
+ <event event="0x66" title="Scorpion" name="PASS_COND_INST" description="Conditional instructions passing conditional instrs (excluding branches)"/>
+ <event event="0x67" title="Scorpion" name="ALLOW_VU_CLK" description="Unit Clock Gating Allow VU Clks"/>
+ <event event="0x68" title="Scorpion" name="VU_IDLE" description="Unit Clock Gating VU Idle"/>
+ <event event="0x69" title="Scorpion" name="ALLOW_L2_CLK" description="Unit Clock Gating Allow L2 Clks"/>
+ <event event="0x6a" title="Scorpion" name="L2_IDLE" description="Unit Clock Gating L2 Idle"/>
+ <event event="0x6b" title="Scorpion" name="DTLB_IMPL_INV_SCTLR_DACR" description="DTLB implicit invalidates writes to SCTLR and DACR"/>
+ <event event="0x6c" title="Scorpion" name="DTLB_EXPL_INV" description="DTLB explicit invalidates"/>
+ <event event="0x6d" title="Scorpion" name="DTLB_MISS" description="DTLB misses"/>
+ <event event="0x6e" title="Scorpion" name="DTLB_ACCESS" description="DTLB accesses"/>
+ <event event="0x6f" title="Scorpion" name="ITLB_MISS" description="ITLB misses"/>
+ <event event="0x70" title="Scorpion" name="ITLB_IMPL_INV" description="ITLB implicit ITLB invalidates"/>
+ <event event="0x71" title="Scorpion" name="ITLB_EXPL_INV" description="ITLB explicit ITLB invalidates"/>
+ <event event="0x72" title="Scorpion" name="UTLB_D_MISS" description="UTLB d-side misses"/>
+ <event event="0x73" title="Scorpion" name="UTLB_D_ACCESS" description="UTLB d-side accesses"/>
+ <event event="0x74" title="Scorpion" name="UTLB_I_MISS" description="UTLB i-side misses"/>
+ <event event="0x75" title="Scorpion" name="UTLB_I_ACCESS" description="UTLB i-side accesses"/>
+ <event event="0x76" title="Scorpion" name="UTLB_INV_ASID" description="UTLB invalidate by ASID"/>
+ <event event="0x77" title="Scorpion" name="UTLB_INV_MVA" description="UTLB invalidate by MVA"/>
+ <event event="0x78" title="Scorpion" name="UTLB_INV_ALL" description="UTLB invalidate all"/>
+ <event event="0x79" title="Scorpion" name="S2_HOLD_RDQ_UNAVAIL" description="S2 hold RDQ unavail"/>
+ <event event="0x7a" title="Scorpion" name="S2_HOLD" description="S2 hold"/>
+ <event event="0x7b" title="Scorpion" name="S2_HOLD_DEV_OP" description="S2 hold device op"/>
+ <event event="0x7c" title="Scorpion" name="S2_HOLD_ORDER" description="S2 hold strongly ordered op"/>
+ <event event="0x7d" title="Scorpion" name="S2_HOLD_BARRIER" description="S2 hold barrier"/>
+ <event event="0x7e" title="Scorpion" name="VIU_DUAL_CYCLE" description="Scorpion VIU dual cycle"/>
+ <event event="0x7f" title="Scorpion" name="VIU_SINGLE_CYCLE" description="Scorpion VIU single cycle"/>
+ <event event="0x80" title="Scorpion" name="VX_PIPE_WAR_STALL_CYCLES" description="Scorpion VX pipe WAR cycles"/>
+ <event event="0x81" title="Scorpion" name="VX_PIPE_WAW_STALL_CYCLES" description="Scorpion VX pipe WAW cycles"/>
+ <event event="0x82" title="Scorpion" name="VX_PIPE_RAW_STALL_CYCLES" description="Scorpion VX pipe RAW cycles"/>
+ <event event="0x83" title="Scorpion" name="VX_PIPE_LOAD_USE_STALL" description="Scorpion VX pipe load use stall"/>
+ <event event="0x84" title="Scorpion" name="VS_PIPE_WAR_STALL_CYCLES" description="Scorpion VS pipe WAR stall cycles"/>
+ <event event="0x85" title="Scorpion" name="VS_PIPE_WAW_STALL_CYCLES" description="Scorpion VS pipe WAW stall cycles"/>
+ <event event="0x86" title="Scorpion" name="VS_PIPE_RAW_STALL_CYCLES" description="Scorpion VS pipe RAW stall cycles"/>
+ <event event="0x87" title="Scorpion" name="EXCEPTIONS_INV_OPERATION" description="Scorpion invalid operation exceptions"/>
+ <event event="0x88" title="Scorpion" name="EXCEPTIONS_DIV_BY_ZERO" description="Scorpion divide by zero exceptions"/>
+ <event event="0x89" title="Scorpion" name="COND_INST_FAIL_VX_PIPE" description="Scorpion conditional instruction fail VX pipe"/>
+ <event event="0x8a" title="Scorpion" name="COND_INST_FAIL_VS_PIPE" description="Scorpion conditional instruction fail VS pipe"/>
+ <event event="0x8b" title="Scorpion" name="EXCEPTIONS_OVERFLOW" description="Scorpion overflow exceptions"/>
+ <event event="0x8c" title="Scorpion" name="EXCEPTIONS_UNDERFLOW" description="Scorpion underflow exceptions"/>
+ <event event="0x8d" title="Scorpion" name="EXCEPTIONS_DENORM" description="Scorpion denorm exceptions"/>
+ <event event="0x8e" title="Scorpion" name="BANK_AB_HIT" description="L2 hit rates bank A/B hits"/>
+ <event event="0x8f" title="Scorpion" name="BANK_AB_ACCESS" description="L2 hit rates bank A/B accesses"/>
+ <event event="0x90" title="Scorpion" name="BANK_CD_HIT" description="L2 hit rates bank C/D hits"/>
+ <event event="0x91" title="Scorpion" name="BANK_CD_ACCESS" description="L2 hit rates bank C/D accesses"/>
+ <event event="0x92" title="Scorpion" name="BANK_AB_DSIDE_HIT" description="L2 hit rates bank A/B d-side hits"/>
+ <event event="0x93" title="Scorpion" name="BANK_AB_DSIDE_ACCESS" description="L2 hit rates bank A/B d-side accesses"/>
+ <event event="0x94" title="Scorpion" name="BANK_CD_DSIDE_HIT" description="L2 hit rates bank C/D d-side hits"/>
+ <event event="0x95" title="Scorpion" name="BANK_CD_DSIDE_ACCESS" description="L2 hit rates bank C/D d-side accesses"/>
+ <event event="0x96" title="Scorpion" name="BANK_AB_ISIDE_HIT" description="L2 hit rates bank A/B i-side hits"/>
+ <event event="0x97" title="Scorpion" name="BANK_AB_ISIDE_ACCESS" description="L2 hit rates bank A/B i-side accesses"/>
+ <event event="0x98" title="Scorpion" name="BANK_CD_ISIDE_HIT" description="L2 hit rates bank C/D i-side hits"/>
+ <event event="0x99" title="Scorpion" name="BANK_CD_ISIDE_ACCESS" description="L2 hit rates bank C/D i-side accesses"/>
+ <event event="0x9a" title="Scorpion" name="ISIDE_RD_WAIT" description="fills and castouts cycles that i-side RD requests wait on data from bus"/>
+ <event event="0x9b" title="Scorpion" name="DSIDE_RD_WAIT" description="fills and castouts cycles that d-side RD requests wait on data from bus"/>
+ <event event="0x9c" title="Scorpion" name="BANK_BYPASS_WRITE" description="fills and castouts bank bypass writes"/>
+ <event event="0x9d" title="Scorpion" name="BANK_AB_NON_CASTOUT" description="fills and castouts bank A/B non-castout writes to bus"/>
+ <event event="0x9e" title="Scorpion" name="BANK_AB_L2_CASTOUT" description="fills and castouts bank A/B L2 castouts (granules)"/>
+ <event event="0x9f" title="Scorpion" name="BANK_CD_NON_CASTOUT" description="fills and castouts bank C/D non-castout writes to bus"/>
+ <event event="0xa0" title="Scorpion" name="BANK_CD_L2_CASTOUT" description="fills and castouts bank C/D L2 castouts (granules)"/>
+ </category>
+ \ No newline at end of file
diff --git a/drivers/gator/daemon/events-ScorpionMP.xml b/drivers/gator/daemon/events-ScorpionMP.xml
new file mode 100644
index 00000000000..bd13b8a9b3a
--- /dev/null
+++ b/drivers/gator/daemon/events-ScorpionMP.xml
@@ -0,0 +1,96 @@
+ <counter_set name="ScorpionMP_cntX">
+ <counter name="ScorpionMP_cnt0"/>
+ <counter name="ScorpionMP_cnt1"/>
+ <counter name="ScorpionMP_cnt2"/>
+ <counter name="ScorpionMP_cnt3"/>
+ </counter_set>
+ <category name="ScorpionMP" counter_set="ScorpionMP_cntX" per_cpu="yes">
+ <event counter="ScorpionMP_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/>
+ <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
+ <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="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
+ <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
+ <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="0x0c" title="Program Counter" name="SW change" description="Software change of PC, except by an exception, architecturally executed"/>
+ <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
+ <event event="0x0e" title="Branch" name="Procedure Return" description="Procedure return architecturally executed (not by exceptions)"/>
+ <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access 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="0x4c" title="Scorpion" name="ICACHE_EXPL_INV" description="I-cache explicit invalidates"/>
+ <event event="0x4d" title="Scorpion" name="ICACHE_MISS" description="I-cache misses"/>
+ <event event="0x4e" title="Scorpion" name="ICACHE_ACCESS" description="I-cache accesses"/>
+ <event event="0x4f" title="Scorpion" name="ICACHE_CACHEREQ_L2" description="I-cache cacheable requests to L2"/>
+ <event event="0x50" title="Scorpion" name="ICACHE_NOCACHE_L2" description="I-cache non-cacheable requests to L2"/>
+ <event event="0x51" title="Scorpion" name="HIQUP_NOPED" description="Conditional instructions HIQUPs NOPed"/>
+ <event event="0x52" title="Scorpion" name="DATA_ABORT" description="Interrupts and Exceptions Data Abort"/>
+ <event event="0x53" title="Scorpion" name="IRQ" description="Interrupts and Exceptions IRQ"/>
+ <event event="0x54" title="Scorpion" name="FIQ" description="Interrupts and Exceptions FIQ"/>
+ <event event="0x55" title="Scorpion" name="ALL_EXCPT" description="Interrupts and Exceptions All interrupts"/>
+ <event event="0x56" title="Scorpion" name="UNDEF" description="Interrupts and Exceptions Undefined"/>
+ <event event="0x57" title="Scorpion" name="SVC" description="Interrupts and Exceptions SVC"/>
+ <event event="0x58" title="Scorpion" name="SMC" description="Interrupts and Exceptions SMC"/>
+ <event event="0x59" title="Scorpion" name="PREFETCH_ABORT" description="Interrupts and Exceptions Prefetch Abort"/>
+ <event event="0x5a" title="Scorpion" name="INDEX_CHECK" description="Interrupts and Exceptions Index Check"/>
+ <event event="0x5b" title="Scorpion" name="NULL_CHECK" description="Interrupts and Exceptions Null Check"/>
+ <event event="0x5c" title="Scorpion" name="EXPL_ICIALLU" description="I-cache and BTAC Invalidates Explicit ICIALLU"/>
+ <event event="0x5d" title="Scorpion" name="IMPL_ICIALLU" description="I-cache and BTAC Invalidates Implicit ICIALLU"/>
+ <event event="0x5e" title="Scorpion" name="NONICIALLU_BTAC_INV" description="I-cache and BTAC Invalidates Non-ICIALLU BTAC Invalidate"/>
+ <event event="0x5f" title="Scorpion" name="ICIMVAU_IMPL_ICIALLU" description="I-cache and BTAC Invalidates ICIMVAU-implied ICIALLU"/>
+ <event event="0x60" title="Scorpion" name="SPIPE_ONLY_CYCLES" description="Issue S-pipe only issue cycles"/>
+ <event event="0x61" title="Scorpion" name="XPIPE_ONLY_CYCLES" description="Issue X-pipe only issue cycles"/>
+ <event event="0x62" title="Scorpion" name="DUAL_CYCLES" description="Issue dual issue cycles"/>
+ <event event="0x63" title="Scorpion" name="DISPATCH_ANY_CYCLES" description="Dispatch any dispatch cycles"/>
+ <event event="0x64" title="Scorpion" name="FIFO_FULLBLK_CMT" description="Commits Trace FIFO full Blk CMT"/>
+ <event event="0x65" title="Scorpion" name="FAIL_COND_INST" description="Conditional instructions failing conditional instrs (excluding branches)"/>
+ <event event="0x66" title="Scorpion" name="PASS_COND_INST" description="Conditional instructions passing conditional instrs (excluding branches)"/>
+ <event event="0x67" title="Scorpion" name="ALLOW_VU_CLK" description="Unit Clock Gating Allow VU Clks"/>
+ <event event="0x68" title="Scorpion" name="VU_IDLE" description="Unit Clock Gating VU Idle"/>
+ <event event="0x69" title="Scorpion" name="ALLOW_L2_CLK" description="Unit Clock Gating Allow L2 Clks"/>
+ <event event="0x6a" title="Scorpion" name="L2_IDLE" description="Unit Clock Gating L2 Idle"/>
+ <event event="0x6b" title="Scorpion" name="DTLB_IMPL_INV_SCTLR_DACR" description="DTLB implicit invalidates writes to SCTLR and DACR"/>
+ <event event="0x6c" title="Scorpion" name="DTLB_EXPL_INV" description="DTLB explicit invalidates"/>
+ <event event="0x6d" title="Scorpion" name="DTLB_MISS" description="DTLB misses"/>
+ <event event="0x6e" title="Scorpion" name="DTLB_ACCESS" description="DTLB accesses"/>
+ <event event="0x6f" title="Scorpion" name="ITLB_MISS" description="ITLB misses"/>
+ <event event="0x70" title="Scorpion" name="ITLB_IMPL_INV" description="ITLB implicit ITLB invalidates"/>
+ <event event="0x71" title="Scorpion" name="ITLB_EXPL_INV" description="ITLB explicit ITLB invalidates"/>
+ <event event="0x72" title="Scorpion" name="UTLB_D_MISS" description="UTLB d-side misses"/>
+ <event event="0x73" title="Scorpion" name="UTLB_D_ACCESS" description="UTLB d-side accesses"/>
+ <event event="0x74" title="Scorpion" name="UTLB_I_MISS" description="UTLB i-side misses"/>
+ <event event="0x75" title="Scorpion" name="UTLB_I_ACCESS" description="UTLB i-side accesses"/>
+ <event event="0x76" title="Scorpion" name="UTLB_INV_ASID" description="UTLB invalidate by ASID"/>
+ <event event="0x77" title="Scorpion" name="UTLB_INV_MVA" description="UTLB invalidate by MVA"/>
+ <event event="0x78" title="Scorpion" name="UTLB_INV_ALL" description="UTLB invalidate all"/>
+ <event event="0x79" title="Scorpion" name="S2_HOLD_RDQ_UNAVAIL" description="S2 hold RDQ unavail"/>
+ <event event="0x7a" title="Scorpion" name="S2_HOLD" description="S2 hold"/>
+ <event event="0x7b" title="Scorpion" name="S2_HOLD_DEV_OP" description="S2 hold device op"/>
+ <event event="0x7c" title="Scorpion" name="S2_HOLD_ORDER" description="S2 hold strongly ordered op"/>
+ <event event="0x7d" title="Scorpion" name="S2_HOLD_BARRIER" description="S2 hold barrier"/>
+ <event event="0x7e" title="Scorpion" name="VIU_DUAL_CYCLE" description="Scorpion VIU dual cycle"/>
+ <event event="0x7f" title="Scorpion" name="VIU_SINGLE_CYCLE" description="Scorpion VIU single cycle"/>
+ <event event="0x80" title="Scorpion" name="VX_PIPE_WAR_STALL_CYCLES" description="Scorpion VX pipe WAR cycles"/>
+ <event event="0x81" title="Scorpion" name="VX_PIPE_WAW_STALL_CYCLES" description="Scorpion VX pipe WAW cycles"/>
+ <event event="0x82" title="Scorpion" name="VX_PIPE_RAW_STALL_CYCLES" description="Scorpion VX pipe RAW cycles"/>
+ <event event="0x83" title="Scorpion" name="VX_PIPE_LOAD_USE_STALL" description="Scorpion VX pipe load use stall"/>
+ <event event="0x84" title="Scorpion" name="VS_PIPE_WAR_STALL_CYCLES" description="Scorpion VS pipe WAR stall cycles"/>
+ <event event="0x85" title="Scorpion" name="VS_PIPE_WAW_STALL_CYCLES" description="Scorpion VS pipe WAW stall cycles"/>
+ <event event="0x86" title="Scorpion" name="VS_PIPE_RAW_STALL_CYCLES" description="Scorpion VS pipe RAW stall cycles"/>
+ <event event="0x87" title="Scorpion" name="EXCEPTIONS_INV_OPERATION" description="Scorpion invalid operation exceptions"/>
+ <event event="0x88" title="Scorpion" name="EXCEPTIONS_DIV_BY_ZERO" description="Scorpion divide by zero exceptions"/>
+ <event event="0x89" title="Scorpion" name="COND_INST_FAIL_VX_PIPE" description="Scorpion conditional instruction fail VX pipe"/>
+ <event event="0x8a" title="Scorpion" name="COND_INST_FAIL_VS_PIPE" description="Scorpion conditional instruction fail VS pipe"/>
+ <event event="0x8b" title="Scorpion" name="EXCEPTIONS_OVERFLOW" description="Scorpion overflow exceptions"/>
+ <event event="0x8c" title="Scorpion" name="EXCEPTIONS_UNDERFLOW" description="Scorpion underflow exceptions"/>
+ <event event="0x8d" title="Scorpion" name="EXCEPTIONS_DENORM" description="Scorpion denorm exceptions"/>
+ <event event="0x8e" title="ScorpionMP" name="NUM_BARRIERS" description="Barriers"/>
+ <event event="0x8f" title="ScorpionMP" name="BARRIER_CYCLES" description="Barrier cycles"/>
+ </category>
+ \ No newline at end of file
diff --git a/drivers/gator/daemon/events_footer.xml b/drivers/gator/daemon/events_footer.xml
new file mode 100644
index 00000000000..cd2b44665ba
--- /dev/null
+++ b/drivers/gator/daemon/events_footer.xml
@@ -0,0 +1 @@
+</events>
diff --git a/drivers/gator/daemon/events_header.xml b/drivers/gator/daemon/events_header.xml
new file mode 100644
index 00000000000..38ec4c03246
--- /dev/null
+++ b/drivers/gator/daemon/events_header.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<events>
diff --git a/drivers/gator/daemon/main.cpp b/drivers/gator/daemon/main.cpp
new file mode 100644
index 00000000000..51237cbcf75
--- /dev/null
+++ b/drivers/gator/daemon/main.cpp
@@ -0,0 +1,306 @@
+/**
+ * Copyright (C) ARM Limited 2010-2012. 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 <stdint.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <ctype.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include "Child.h"
+#include "SessionData.h"
+#include "OlySocket.h"
+#include "Logging.h"
+#include "OlyUtility.h"
+
+#define DEBUG false
+
+extern Child* child;
+extern void handleException();
+int shutdownFilesystem();
+static pthread_mutex_t numSessions_mutex;
+static int numSessions = 0;
+static OlySocket* socket = NULL;
+static bool driverRunningAtStart = false;
+static bool driverMountedAtStart = false;
+
+struct cmdline_t {
+ int port;
+ char* sessionXML;
+};
+
+void cleanUp() {
+ if (shutdownFilesystem() == -1) {
+ logg->logMessage("Error shutting down gator filesystem");
+ }
+ delete socket;
+ delete util;
+ delete logg;
+}
+
+// CTRL C Signal Handler
+void handler(int signum) {
+ logg->logMessage("Received signal %d, gator daemon exiting", signum);
+
+ // Case 1: both child and parent receive the signal
+ if (numSessions > 0) {
+ // Arbitrary sleep of 1 second to give time for the child to exit;
+ // if something bad happens, continue the shutdown process regardless
+ sleep(1);
+ }
+
+ // Case 2: only the parent received the signal
+ if (numSessions > 0) {
+ // Kill child threads - the first signal exits gracefully
+ logg->logMessage("Killing process group as %d child was running when signal was received", numSessions);
+ kill(0, SIGINT);
+
+ // Give time for the child to exit
+ sleep(1);
+
+ if (numSessions > 0) {
+ // The second signal force kills the child
+ logg->logMessage("Force kill the child");
+ kill(0, SIGINT);
+ // Again, sleep for 1 second
+ sleep(1);
+
+ if (numSessions > 0) {
+ // Something bad has really happened; the child is not exiting and therefore may hold the /dev/gator resource open
+ printf("Unable to kill the gatord child process, thus gator.ko may still be loaded.\n");
+ }
+ }
+ }
+
+ cleanUp();
+ exit(0);
+}
+
+// Child exit Signal Handler
+void child_exit(int signum) {
+ int status;
+ int pid = wait(&status);
+ if (pid != -1) {
+ pthread_mutex_lock(&numSessions_mutex);
+ numSessions--;
+ pthread_mutex_unlock(&numSessions_mutex);
+ logg->logMessage("Child process %d exited with status %d", pid, status);
+ }
+}
+
+// retval: -1 = failure; 0 = was already mounted; 1 = successfully mounted
+int mountGatorFS() {
+ // If already mounted,
+ if (access("/dev/gator/buffer", F_OK) == 0)
+ return 0;
+
+ // else, mount the filesystem
+ mkdir("/dev/gator", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+ if (mount("nodev", "/dev/gator", "gatorfs", 0, NULL) != 0)
+ return -1;
+ else
+ return 1;
+}
+
+int setupFilesystem() {
+ int retval;
+
+ // Verify root permissions
+ uid_t euid = geteuid();
+ if (euid) {
+ logg->logError(__FILE__, __LINE__, "gatord must be launched with root privileges");
+ handleException();
+ }
+
+ retval = mountGatorFS();
+ if (retval == 1) {
+ logg->logMessage("Driver already running at startup");
+ driverRunningAtStart = true;
+ } else if (retval == 0) {
+ logg->logMessage("Driver already mounted at startup");
+ driverRunningAtStart = driverMountedAtStart = true;
+ } else {
+ char command[256]; // arbitrarily large amount
+
+ // Is the driver co-located in the same directory?
+ if (util->getApplicationFullPath(command, sizeof(command)) != 0) { // allow some buffer space
+ logg->logMessage("Unable to determine the full path of gatord, the cwd will be used");
+ }
+ strcat(command, "gator.ko");
+ if (access(command, F_OK) == -1) {
+ logg->logError(__FILE__, __LINE__, "Unable to locate gator.ko driver:\n >>> gator.ko should be co-located with gatord in the same directory\n >>> OR insmod gator.ko prior to launching gatord");
+ handleException();
+ }
+
+ // Load driver
+ strcpy(command, "insmod ");
+ util->getApplicationFullPath(&command[7], sizeof(command) - 64); // allow some buffer space
+ strcat(command, "gator.ko >/dev/null 2>&1");
+
+ if (system(command) != 0) {
+ logg->logMessage("Unable to load gator.ko driver with command: %s", command);
+ logg->logError(__FILE__, __LINE__, "Unable to load (insmod) gator.ko driver:\n >>> gator.ko must be built against the current kernel version & configuration\n >>> See dmesg for more details");
+ handleException();
+ }
+
+ if (mountGatorFS() == -1) {
+ logg->logError(__FILE__, __LINE__, "Unable to mount the gator filesystem needed for profiling.");
+ handleException();
+ }
+ }
+
+ return 0;
+}
+
+int shutdownFilesystem() {
+ if (driverMountedAtStart == false)
+ umount("/dev/gator");
+ if (driverRunningAtStart == false)
+ if (system("rmmod gator >/dev/null 2>&1") != 0)
+ return -1;
+
+ return 0; // success
+}
+
+struct cmdline_t parseCommandLine(int argc, char** argv) {
+ struct cmdline_t cmdline;
+ cmdline.port = 8080;
+ cmdline.sessionXML = NULL;
+ int c;
+
+ while ((c = getopt (argc, argv, "hvp:s:c:")) != -1) {
+ switch(c) {
+ case 'p':
+ cmdline.port = strtol(optarg, NULL, 10);
+ break;
+ case 's':
+ cmdline.sessionXML = optarg;
+ break;
+ case 'c':
+ gSessionData->configurationXMLPath = optarg;
+ break;
+ case 'h':
+ case '?':
+ logg->logError(__FILE__, __LINE__,
+ "Streamline gatord version %d. All parameters are optional:\n"
+ "-p port_number\tport upon which the server listens; default is 8080\n"
+ "-s session_xml\tpath and filename of a session xml used for local capture\n"
+ "-c config_xml\tpath and filename of the configuration.xml to use\n"
+ "-v\t\tversion information\n"
+ "-h\t\tthis help page\n", PROTOCOL_VERSION);
+ handleException();
+ break;
+ case 'v':
+ logg->logError(__FILE__, __LINE__, "Streamline gatord version %d", PROTOCOL_VERSION);
+ handleException();
+ break;
+ }
+ }
+
+ // Error checking
+ if (cmdline.port != 8080 && cmdline.sessionXML != NULL) {
+ logg->logError(__FILE__, __LINE__, "Only a port or a session xml can be specified, not both");
+ handleException();
+ }
+
+ if (optind < argc) {
+ logg->logError(__FILE__, __LINE__, "Unknown argument: %s. Use '-h' for help.", argv[optind]);
+ handleException();
+ }
+
+ return cmdline;
+}
+
+// Gator data flow: collector -> collector fifo -> sender
+int main(int argc, char** argv, char *envp[]) {
+ gSessionData = new SessionData(); // Global data class
+ logg = new Logging(DEBUG); // Set up global thread-safe logging
+ util = new OlyUtility(); // Set up global utility class
+
+ prctl(PR_SET_NAME, (unsigned int)&"gatord-main", 0, 0, 0);
+ pthread_mutex_init(&numSessions_mutex, NULL);
+
+ signal(SIGINT, handler);
+ signal(SIGTERM, handler);
+ signal(SIGABRT, handler);
+
+ // Set to high priority
+ if (setpriority(PRIO_PROCESS, syscall(__NR_gettid), -19) == -1)
+ logg->logMessage("setpriority() failed");
+
+ // Initialize session data
+ gSessionData->initialize();
+
+ // Parse the command line parameters
+ struct cmdline_t cmdline = parseCommandLine(argc, argv);
+
+ // Call before setting up the SIGCHLD handler, as system() spawns child processes
+ setupFilesystem();
+
+ // Handle child exit codes
+ signal(SIGCHLD, child_exit);
+
+ // Ignore the SIGPIPE signal so that any send to a broken socket will return an error code instead of asserting a signal
+ // Handling the error at the send function call is much easier than trying to do anything intelligent in the sig handler
+ signal(SIGPIPE, SIG_IGN);
+
+ // If the command line argument is a session xml file, no need to open a socket
+ if (cmdline.sessionXML) {
+ child = new Child(cmdline.sessionXML);
+ child->run();
+ delete child;
+ } else {
+ socket = new OlySocket(cmdline.port, true);
+ // Forever loop, can be exited via a signal or exception
+ while (1) {
+ logg->logMessage("Waiting on connection...");
+ socket->acceptConnection();
+
+ int pid = fork();
+ if (pid < 0) {
+ // Error
+ logg->logError(__FILE__, __LINE__, "Fork process failed. Please power cycle the target device if this error persists.");
+ } else if (pid == 0) {
+ // Child
+ socket->closeServerSocket();
+ child = new Child(socket, numSessions + 1);
+ child->run();
+ delete child;
+ exit(0);
+ } else {
+ // Parent
+ socket->closeSocket();
+
+ pthread_mutex_lock(&numSessions_mutex);
+ numSessions++;
+ pthread_mutex_unlock(&numSessions_mutex);
+
+ // Maximum number of connections is 2
+ int wait = 0;
+ while (numSessions > 1) {
+ // Throttle until one of the children exits before continuing to accept another socket connection
+ logg->logMessage("%d sessions active!", numSessions);
+ if (wait++ >= 10) { // Wait no more than 10 seconds
+ // Kill last created child
+ kill(pid, SIGALRM);
+ break;
+ }
+ sleep(1);
+ }
+ }
+ }
+ }
+
+ cleanUp();
+ return 0;
+}