aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew Richardson <drew.richardson@arm.com>2012-03-01 12:00:00 -0800
committerDrew Richardson <drew.richardson@arm.com>2014-12-19 15:24:06 -0800
commit3de04f9cecf0d50e895f9fe0164ecbbbae997319 (patch)
tree9bc04b0b4ad5b313559479d6bd12942961017b7d
parent689b7539711ab098911503808cc3e24307d9bcf7 (diff)
gator: Version 5.95.9
Signed-off-by: Drew Richardson <drew.richardson@arm.com>
-rw-r--r--README_Streamline.txt14
-rw-r--r--daemon/CapturedXML.cpp40
-rw-r--r--daemon/CapturedXML.h3
-rw-r--r--daemon/Child.cpp51
-rw-r--r--daemon/Child.h2
-rw-r--r--daemon/Collector.cpp83
-rw-r--r--daemon/Collector.h3
-rw-r--r--daemon/ConfigurationXML.cpp58
-rw-r--r--daemon/ConfigurationXML.h2
-rw-r--r--daemon/Fifo.cpp2
-rw-r--r--daemon/Fifo.h2
-rw-r--r--daemon/LocalCapture.cpp14
-rw-r--r--daemon/LocalCapture.h2
-rw-r--r--daemon/Logging.cpp19
-rw-r--r--daemon/Logging.h7
-rw-r--r--daemon/Makefile7
-rw-r--r--daemon/OlySocket.cpp2
-rw-r--r--daemon/OlySocket.h2
-rw-r--r--daemon/OlyUtility.cpp2
-rw-r--r--daemon/OlyUtility.h2
-rw-r--r--daemon/RequestXML.cpp2
-rw-r--r--daemon/RequestXML.h2
-rw-r--r--daemon/Sender.cpp4
-rw-r--r--daemon/Sender.h2
-rw-r--r--daemon/SessionData.cpp37
-rw-r--r--daemon/SessionData.h7
-rw-r--r--daemon/SessionXML.cpp2
-rw-r--r--daemon/SessionXML.h2
-rw-r--r--daemon/StreamlineSetup.cpp26
-rw-r--r--daemon/StreamlineSetup.h2
-rw-r--r--daemon/XMLOut.cpp2
-rw-r--r--daemon/XMLOut.h2
-rw-r--r--daemon/XMLReader.cpp2
-rw-r--r--daemon/XMLReader.h2
-rw-r--r--daemon/events-Cortex-A5.xml2
-rw-r--r--daemon/events-Cortex-A7.xml50
-rw-r--r--daemon/events-Cortex-A8.xml6
-rw-r--r--daemon/events-Cortex-A9.xml2
-rw-r--r--daemon/events-Krait-architected.xml28
-rw-r--r--daemon/events-Linux.xml4
-rw-r--r--daemon/events-Mali-400.xml395
-rw-r--r--daemon/events-Scorpion.xml174
-rw-r--r--daemon/events-ScorpionMP.xml140
-rw-r--r--daemon/main.cpp65
-rw-r--r--driver/Makefile4
-rw-r--r--driver/gator.h20
-rw-r--r--driver/gator_annotate.c2
-rw-r--r--driver/gator_annotate_kernel.c3
-rw-r--r--driver/gator_backtrace.c2
-rw-r--r--driver/gator_cookies.c15
-rw-r--r--driver/gator_ebs.c255
-rw-r--r--driver/gator_events_armv6.c52
-rw-r--r--driver/gator_events_armv7.c89
-rw-r--r--driver/gator_events_armv7.h38
-rw-r--r--driver/gator_events_block.c2
-rw-r--r--driver/gator_events_irq.c38
-rw-r--r--driver/gator_events_l2c-310.c7
-rw-r--r--driver/gator_events_mali.c611
-rw-r--r--driver/gator_events_meminfo.c2
-rw-r--r--driver/gator_events_mmaped.c6
-rw-r--r--driver/gator_events_net.c47
-rw-r--r--driver/gator_events_perf_pmu.c296
-rw-r--r--driver/gator_events_power.c178
-rw-r--r--driver/gator_events_sched.c2
-rw-r--r--driver/gator_events_scorpion.c79
-rw-r--r--driver/gator_hrtimer_gator.c76
-rw-r--r--driver/gator_hrtimer_perf.c113
-rw-r--r--driver/gator_main.c492
-rw-r--r--driver/gator_pack.c2
-rw-r--r--driver/gator_trace_gpu.c250
-rw-r--r--driver/gator_trace_gpu.h79
-rw-r--r--driver/gator_trace_sched.c19
72 files changed, 3126 insertions, 930 deletions
diff --git a/README_Streamline.txt b/README_Streamline.txt
index f9edf11..963277e 100644
--- a/README_Streamline.txt
+++ b/README_Streamline.txt
@@ -59,13 +59,15 @@ If successful, a gator.ko module should be generated
*** Building the gator daemon ***
cd /path/to/gator/daemon-src
-tar -xzf gator-daemon.tar.gz
-For Linux,
- build with 'make'
-For Android,
+tar -xzf gator-daemon.tar.gz (may need to issue with 'sudo')
+For Linux targets,
+ cd gator-daemon
+ make
+ gatord should now be created
+For Android targets (install the android ndk, see developer.android.com)
mv gator-daemon jni
- install the android ndk, see developer.android.com
- /path/to/ndk/ndk-build
+ ndk-build
+ or execute /path/to/ndk/ndk-build if the ndk is not on your path
gatord should now be created and located in libs/armeabi
*** Running gator ***
diff --git a/daemon/CapturedXML.cpp b/daemon/CapturedXML.cpp
index 5d1f295..51076dd 100644
--- a/daemon/CapturedXML.cpp
+++ b/daemon/CapturedXML.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -30,7 +30,7 @@ const char* CapturedXML::getXML() {
xmlHeader();
for (x=0; x<MAX_PERFORMANCE_COUNTERS; x++) {
- if (gSessionData.mPerfCounterEnabled[x]) {
+ if (gSessionData->mPerfCounterEnabled[x]) {
perfCounters = true;
break;
}
@@ -39,38 +39,38 @@ const char* CapturedXML::getXML() {
startElement("captured");
attributeInt("version", 1);
attributeInt("protocol", PROTOCOL_VERSION);
- if (gSessionData.mBytes > 0) { // Send the following only after the capture is complete
+ 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);
+ attributeUInt("bytes", gSessionData->mBytes);
}
startElement("target");
- attributeString("name", gSessionData.mCoreName);
- attributeInt("sample_rate", gSessionData.mSampleRate);
- attributeInt("cores", gSessionData.mCores);
+ 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]) {
+ 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]) {
+ 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 (strlen(gSessionData->mPerfCounterOperation[x]) > 0) {
+ attributeString("operation", gSessionData->mPerfCounterOperation[x]);
}
- if (gSessionData.mPerfCounterCount[x] > 0) {
- attributeInt("count", gSessionData.mPerfCounterCount[x]);
+ if (gSessionData->mPerfCounterCount[x] > 0) {
+ attributeInt("count", gSessionData->mPerfCounterCount[x]);
}
- attributeString("description", gSessionData.mPerfCounterDescription[x]);
+ attributeString("description", gSessionData->mPerfCounterDescription[x]);
endElement("counter");
}
}
diff --git a/daemon/CapturedXML.h b/daemon/CapturedXML.h
index aafeefe..d37c59e 100644
--- a/daemon/CapturedXML.h
+++ b/daemon/CapturedXML.h
@@ -1,5 +1,6 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+
+ * 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
diff --git a/daemon/Child.cpp b/daemon/Child.cpp
index 6cfbe60..ddf105b 100644
--- a/daemon/Child.cpp
+++ b/daemon/Child.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -22,11 +22,12 @@
#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; // shared by Child.cpp and ConfigurationXML.cpp
+Collector* collector = NULL;
Child* child = NULL; // shared by Child.cpp and main.cpp
extern void cleanUp();
@@ -44,7 +45,7 @@ void handleException() {
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) {
+ if (gSessionData->mWaitingOnCommand) {
char discard;
child->socket->receiveNBytes(&discard, 1);
}
@@ -54,7 +55,7 @@ void handleException() {
}
}
- if (gSessionData.mLocalCapture)
+ if (gSessionData->mLocalCapture)
cleanUp();
exit(1);
@@ -80,11 +81,11 @@ void child_handler(int signum) {
void* durationThread(void* pVoid) {
prctl(PR_SET_NAME, (unsigned int)&"gatord-duration", 0, 0, 0);
sem_wait(&startProfile);
- if (gSessionData.mSessionIsActive) {
+ if (gSessionData->mSessionIsActive) {
// Time out after duration seconds
// Add a second for host-side filtering
- sleep(gSessionData.mDuration + 1);
- if (gSessionData.mSessionIsActive) {
+ sleep(gSessionData->mDuration + 1);
+ if (gSessionData->mSessionIsActive) {
logg->logMessage("Duration expired.");
child->endSession();
}
@@ -99,7 +100,7 @@ void* stopThread(void* pVoid) {
OlySocket* socket = child->socket;
prctl(PR_SET_NAME, (unsigned int)&"gatord-stopper", 0, 0, 0);
- while (gSessionData.mSessionIsActive) {
+ 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)) {
@@ -149,6 +150,7 @@ void* senderThread(void* pVoid) {
Child::Child(char* path) {
initialization();
sessionXMLPath = path;
+ gSessionData->mLocalCapture = true;
}
Child::Child(OlySocket* sock, int conn) {
@@ -162,7 +164,7 @@ Child::~Child() {
void Child::initialization() {
// Set up different handlers for signals
- gSessionData.mSessionIsActive = true;
+ gSessionData->mSessionIsActive = true;
signal(SIGINT, child_handler);
signal(SIGTERM, child_handler);
signal(SIGABRT, child_handler);
@@ -178,7 +180,7 @@ void Child::initialization() {
}
void Child::endSession() {
- gSessionData.mSessionIsActive = false;
+ gSessionData->mSessionIsActive = false;
collector->stop();
sem_post(&haltPipeline);
}
@@ -198,7 +200,10 @@ void Child::run() {
handleException();
}
- // Set up the driver
+ // 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
@@ -207,23 +212,25 @@ void Child::run() {
StreamlineSetup ss(socket);
} else {
xmlString = util->readFromDisk(sessionXMLPath);
- gSessionData.mLocalCapture = true;
if (xmlString == 0) {
logg->logError(__FILE__, __LINE__, "Unable to read session xml file: %s", sessionXMLPath);
handleException();
}
- gSessionData.parseSessionXML(xmlString);
+ gSessionData->parseSessionXML(xmlString);
localCapture = new LocalCapture();
- localCapture->createAPCDirectory(gSessionData.target_path, gSessionData.title);
- localCapture->copyImages(gSessionData.images);
+ localCapture->createAPCDirectory(gSessionData->target_path, gSessionData->title);
+ localCapture->copyImages(gSessionData->images);
localCapture->write(xmlString);
- sender->createDataFile(gSessionData.apcDir);
+ sender->createDataFile(gSessionData->apcDir);
delete xmlString;
}
+ // Write configuration into the driver
+ collector->setupPerfCounters();
+
// Create user-space buffers
int fifoBufferSize = collector->getBufferSize();
- int numCollectorBuffers = (gSessionData.mTotalBufferSize * 1024 * 1024 + fifoBufferSize - 1) / fifoBufferSize;
+ 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);
@@ -232,11 +239,11 @@ void Child::run() {
collectBuffer = collectorFifo->start();
// Sender thread shall be halted until it is signaled for one shot mode
- sem_init(&haltPipeline, 0, gSessionData.mOneShot ? 0 : 2);
+ 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))
+ 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;
@@ -261,7 +268,7 @@ void Child::run() {
bytesCollected = collector->collect(collectBuffer);
// In one shot mode, stop collection once all the buffers are filled
- if (gSessionData.mOneShot && gSessionData.mSessionIsActive) {
+ 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");
@@ -283,9 +290,9 @@ void Child::run() {
}
// Write the captured xml file
- if (gSessionData.mLocalCapture) {
+ if (gSessionData->mLocalCapture) {
CapturedXML capturedXML;
- capturedXML.write(gSessionData.apcDir);
+ capturedXML.write(gSessionData->apcDir);
}
logg->logMessage("Profiling ended.");
diff --git a/daemon/Child.h b/daemon/Child.h
index 950eb94..eee5ac7 100644
--- a/daemon/Child.h
+++ b/daemon/Child.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/Collector.cpp b/daemon/Collector.cpp
index 18f6dee..7a41198 100644
--- a/daemon/Collector.cpp
+++ b/daemon/Collector.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -16,12 +16,13 @@
#include "Collector.h"
#include "SessionData.h"
#include "Logging.h"
-#include "ConfigurationXML.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();
@@ -32,9 +33,9 @@ Collector::Collector() {
handleException();
}
- readIntDriver("cpu_cores", &gSessionData.mCores);
- if (gSessionData.mCores == 0) {
- gSessionData.mCores = 1;
+ readIntDriver("cpu_cores", &gSessionData->mCores);
+ if (gSessionData->mCores == 0) {
+ gSessionData->mCores = 1;
}
bufferSize = 512 * 1024;
@@ -45,8 +46,15 @@ Collector::Collector() {
getCoreName();
- // populate performance counter session data
- new ConfigurationXML();
+ enablePerfCounters();
+
+ // Read unchanging keys from driver which are created at insmod'ing of gator.ko
+ for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) {
+ if (gSessionData->mPerfCounterEnabled[i]) {
+ snprintf(text, sizeof(text), "events/%s/key", gSessionData->mPerfCounterType[i]);
+ readIntDriver(text, &gSessionData->mPerfCounterKey[i]);
+ }
+ }
}
Collector::~Collector() {
@@ -60,28 +68,42 @@ Collector::~Collector() {
}
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>
+ char text[sizeof(gSessionData->mPerfCounterType[0]) + 30]; // sufficiently large to hold all /dev/gator/events/<types>/enabled
+ for (int i=0; i<MAX_PERFORMANCE_COUNTERS; i++) {
+ if (!gSessionData->mPerfCounterEnabled[i]) {
+ continue;
+ }
+ snprintf(text, sizeof(text), "events/%s/enabled", gSessionData->mPerfCounterType[i]);
+ if (writeReadDriver(text, &gSessionData->mPerfCounterEnabled[i])) {
+ // Disable those events that don't exist on this hardware platform even though they exist in configuration.xml
+ gSessionData->mPerfCounterEnabled[i] = 0;
+ continue;
+ }
+ }
+}
+
+void Collector::setupPerfCounters() {
+ 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]) {
+ if (!gSessionData->mPerfCounterEnabled[i]) {
continue;
}
- snprintf(base, sizeof(base), "events/%s", gSessionData.mPerfCounterType[i]);
+ snprintf(base, sizeof(base), "events/%s", gSessionData->mPerfCounterType[i]);
snprintf(text, sizeof(text), "%s/event", base);
- writeDriver(text, gSessionData.mPerfCounterEvent[i]);
- snprintf(text, sizeof(text), "%s/key", base);
- readIntDriver(text, &gSessionData.mPerfCounterKey[i]);
- if (gSessionData.mPerfCounterEBSCapable[i]) {
+ writeDriver(text, gSessionData->mPerfCounterEvent[i]);
+ if (gSessionData->mPerfCounterEBSCapable[i]) {
snprintf(text, sizeof(text), "%s/count", base);
- if (writeReadDriver(text, &gSessionData.mPerfCounterCount[i]))
- gSessionData.mPerfCounterCount[i] = 0;
- if (gSessionData.mPerfCounterCount[i] > 0)
- logg->logMessage("EBS enabled for %s with a count of %d", gSessionData.mPerfCounterName[i], gSessionData.mPerfCounterCount[i]);
- }
- snprintf(text, sizeof(text), "%s/enabled", base);
- if (writeReadDriver(text, &gSessionData.mPerfCounterEnabled[i])) {
- gSessionData.mPerfCounterEnabled[i] = 0;
+ 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();
+ }
}
}
}
@@ -117,27 +139,26 @@ void Collector::checkVersion() {
void Collector::start() {
// Set the maximum backtrace depth
- if (writeReadDriver("backtrace_depth", &gSessionData.mBacktraceDepth)) {
+ 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
- char* fullpath = resolvePath("buffer");
- bufferFD = open(fullpath, O_RDONLY);
+ 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) {
+ 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;
+ int streaming = (int)!gSessionData->mOneShot;
if (writeReadDriver("streaming", &streaming) != 0) {
logg->logError(__FILE__, __LINE__, "Unable to set streaming");
handleException();
@@ -178,7 +199,7 @@ int Collector::collect(char* buffer) {
void Collector::getCoreName() {
char temp[256]; // arbitrarily large amount
- strcpy(gSessionData.mCoreName, "unknown");
+ strcpy(gSessionData->mCoreName, "unknown");
FILE* f = fopen("/proc/cpuinfo", "r");
if (f == NULL) {
@@ -198,8 +219,8 @@ void Collector::getCoreName() {
"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
+ 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;
}
diff --git a/daemon/Collector.h b/daemon/Collector.h
index bcdfc23..6c80725 100644
--- a/daemon/Collector.h
+++ b/daemon/Collector.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -19,6 +19,7 @@ public:
void stop();
int collect(char* buffer);
void enablePerfCounters();
+ void setupPerfCounters();
int getBufferSize() {return bufferSize;}
private:
int bufferSize;
diff --git a/daemon/ConfigurationXML.cpp b/daemon/ConfigurationXML.cpp
index 6348818..e1bec0f 100644
--- a/daemon/ConfigurationXML.cpp
+++ b/daemon/ConfigurationXML.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -11,12 +11,10 @@
#include <dirent.h>
#include "ConfigurationXML.h"
#include "Logging.h"
-#include "Collector.h"
#include "OlyUtility.h"
#include "SessionData.h"
extern void handleException();
-extern Collector* collector;
static const char* ATTR_COUNTER = "counter";
static const char* ATTR_VERSION = "version";
@@ -35,10 +33,14 @@ ConfigurationXML::ConfigurationXML() {
index = 0;
char* path = (char *)malloc(PATH_MAX);
- if (util->getApplicationFullPath(path, PATH_MAX) != 0) {
- logg->logMessage("Unable to determine the full path of gatord, the cwd will be used");
+ 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);
}
- strncat(path, "configuration.xml", PATH_MAX - strlen(path) - 1);
mConfigurationXML = util->readFromDisk(path);
if (mConfigurationXML == NULL) {
@@ -49,7 +51,10 @@ ConfigurationXML::ConfigurationXML() {
mConfigurationXML[configuration_xml_len] = 0;
}
- gSessionData.initializeCounters();
+ // 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) {
@@ -63,7 +68,6 @@ ConfigurationXML::ConfigurationXML() {
handleException();
}
- collector->enablePerfCounters();
free(path);
}
@@ -91,20 +95,20 @@ int ConfigurationXML::parse(const char* configurationXML) {
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]);
+ 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]) {
+ 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]);
+ if (strcmp(gSessionData->mPerfCounterType[i], gSessionData->mPerfCounterType[j]) == 0) {
+ logg->logMessage("Duplicate performance counter type: %s", gSessionData->mPerfCounterType[i]);
return false; // failure
}
}
@@ -133,17 +137,17 @@ int ConfigurationXML::configurationTag(XMLReader* in) {
}
// 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;
+ 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++;
diff --git a/daemon/ConfigurationXML.h b/daemon/ConfigurationXML.h
index 57a426e..047c4b0 100644
--- a/daemon/ConfigurationXML.h
+++ b/daemon/ConfigurationXML.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/Fifo.cpp b/daemon/Fifo.cpp
index 6ffebba..1456183 100644
--- a/daemon/Fifo.cpp
+++ b/daemon/Fifo.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/Fifo.h b/daemon/Fifo.h
index 14688a9..51e2bcd 100644
--- a/daemon/Fifo.h
+++ b/daemon/Fifo.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/LocalCapture.cpp b/daemon/LocalCapture.cpp
index 510a6c3..4a2d6d7 100644
--- a/daemon/LocalCapture.cpp
+++ b/daemon/LocalCapture.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -24,9 +24,9 @@ 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);
+ 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();
}
}
@@ -35,7 +35,7 @@ void LocalCapture::write(char* string) {
char* file = (char*)malloc(PATH_MAX);
// Set full path
- snprintf(file, PATH_MAX, "%s/session.xml", gSessionData.apcDir);
+ snprintf(file, PATH_MAX, "%s/session.xml", gSessionData->apcDir);
// Write the file
if (util->writeToDisk(file, string) < 0) {
@@ -192,9 +192,9 @@ void LocalCapture::copyImages(ImageLinkList* ptr) {
char* dstfilename = (char*)malloc(PATH_MAX);
while (ptr) {
- strncpy(dstfilename, gSessionData.apcDir, PATH_MAX);
+ 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] != '/')
+ 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))
diff --git a/daemon/LocalCapture.h b/daemon/LocalCapture.h
index 0bb6f94..4f5f818 100644
--- a/daemon/LocalCapture.h
+++ b/daemon/LocalCapture.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/Logging.cpp b/daemon/Logging.cpp
index d34209c..3e6f8a3 100644
--- a/daemon/Logging.cpp
+++ b/daemon/Logging.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -30,8 +30,6 @@
Logging* logg = NULL;
Logging::Logging(bool debug) {
- mFileCreated = false;
- mWarningXMLPath[0] = 0;
mDebug = debug;
MUTEX_INIT();
@@ -40,9 +38,6 @@ Logging::Logging(bool debug) {
}
Logging::~Logging() {
- if (mFileCreated) {
- util->appendToDisk(mWarningXMLPath, "</warnings>");
- }
}
void Logging::logError(const char* file, int line, const char* fmt, ...) {
@@ -59,18 +54,6 @@ void Logging::logError(const char* file, int line, const char* fmt, ...) {
vsnprintf(mErrBuf + strlen(mErrBuf), sizeof(mErrBuf) - 2 - strlen(mErrBuf), fmt, args); // subtract 2 for \n and \0
va_end(args);
- // Add the message to the warning file if the warning file was created
- if (mWarningXMLPath[0] != 0) {
- if (!mFileCreated) {
- if (util->writeToDisk(mWarningXMLPath, "<?xml version=\"1.0\" encoding='UTF-8'?>\n<warnings version=\"1\">\n") < 0) {
- return;
- }
- mFileCreated = true;
- }
- util->appendToDisk(mWarningXMLPath, " <warning text=\"");
- util->appendToDisk(mWarningXMLPath, mErrBuf);
- util->appendToDisk(mWarningXMLPath, "\"/>\n");
- }
if (strlen(mErrBuf) > 0) {
strcat(mErrBuf, "\n");
}
diff --git a/daemon/Logging.h b/daemon/Logging.h
index cd8d7cd..4247966 100644
--- a/daemon/Logging.h
+++ b/daemon/Logging.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -14,10 +14,8 @@
#include <limits.h>
#ifdef WIN32
#include <windows.h>
-#define GATOR_PATH_MAX MAX_PATH
#else
#include <pthread.h>
-#define GATOR_PATH_MAX PATH_MAX
#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"
@@ -28,16 +26,13 @@ public:
~Logging();
void logError(const char* file, int line, const char* fmt, ...);
void logMessage(const char* fmt, ...);
- void SetWarningFile(char* path) {strncpy(mWarningXMLPath, path, GATOR_PATH_MAX); mWarningXMLPath[GATOR_PATH_MAX - 1] = 0;}
char* getLastError() {return mErrBuf;}
char* getLastMessage() {return mLogBuf;}
private:
- char mWarningXMLPath[GATOR_PATH_MAX];
char mErrBuf[4096]; // Arbitrarily large buffer to hold a string
char mLogBuf[4096]; // Arbitrarily large buffer to hold a string
bool mDebug;
- bool mFileCreated;
#ifdef WIN32
HANDLE mLoggingMutex;
#else
diff --git a/daemon/Makefile b/daemon/Makefile
index 2a41e31..4aaf219 100644
--- a/daemon/Makefile
+++ b/daemon/Makefile
@@ -19,14 +19,13 @@ CPP=$(CROSS_COMPILE)g++
# -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) $(wildcard ../../reptilia/*.cpp)
+CPP_SRC = $(wildcard *.cpp)
TGT_OBJS = $(CPP_SRC:%.cpp=%.o)
-INCLUDES = -I../../reptilia
all: $(TARGET)
%.o: %.cpp *.h
- $(CPP) $(INCLUDES) -c $(CFLAGS) -o $@ $<
+ $(CPP) -c $(CFLAGS) -o $@ $<
$(TARGET): convert $(TGT_OBJS)
$(CPP) -s -o $@ $(TGT_OBJS) -lc -lrt -lpthread
@@ -38,4 +37,4 @@ convert:
xxd -i configuration.xml > configuration_xml.h
clean:
- rm -f *.o $(TARGET) events.xml events_xml.h configuration_xml.h ../../reptilia/*.o
+ rm -f *.o $(TARGET) events.xml events_xml.h configuration_xml.h
diff --git a/daemon/OlySocket.cpp b/daemon/OlySocket.cpp
index 9b031dc..8a9ca97 100644
--- a/daemon/OlySocket.cpp
+++ b/daemon/OlySocket.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/OlySocket.h b/daemon/OlySocket.h
index 9ba6ee8..2fe6e59 100644
--- a/daemon/OlySocket.h
+++ b/daemon/OlySocket.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/OlyUtility.cpp b/daemon/OlyUtility.cpp
index 6216726..1b15d33 100644
--- a/daemon/OlyUtility.cpp
+++ b/daemon/OlyUtility.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/OlyUtility.h b/daemon/OlyUtility.h
index e516c01..0fa021d 100644
--- a/daemon/OlyUtility.h
+++ b/daemon/OlyUtility.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/RequestXML.cpp b/daemon/RequestXML.cpp
index 3dd7a43..e8f24d2 100644
--- a/daemon/RequestXML.cpp
+++ b/daemon/RequestXML.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2011. All rights reserved.
+ * 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
diff --git a/daemon/RequestXML.h b/daemon/RequestXML.h
index eff242e..bebd048 100644
--- a/daemon/RequestXML.h
+++ b/daemon/RequestXML.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/Sender.cpp b/daemon/Sender.cpp
index c547d67..9792c36 100644
--- a/daemon/Sender.cpp
+++ b/daemon/Sender.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -41,7 +41,7 @@ Sender::Sender(OlySocket* socket) {
char magic[] = {'G', 'A', 'T', 'O', 'R', '\n'};
dataSocket->send(magic, sizeof(magic));
- gSessionData.mWaitingOnCommand = true;
+ gSessionData->mWaitingOnCommand = true;
logg->logMessage("Completed magic sequence");
}
diff --git a/daemon/Sender.h b/daemon/Sender.h
index 147f190..3444b85 100644
--- a/daemon/Sender.h
+++ b/daemon/Sender.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/SessionData.cpp b/daemon/SessionData.cpp
index f84253a..4adcfcd 100644
--- a/daemon/SessionData.cpp
+++ b/daemon/SessionData.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -12,7 +12,7 @@
#include "Logging.h"
extern void handleException();
-SessionData gSessionData;
+SessionData* gSessionData = NULL;
SessionData::SessionData() {
initialize();
@@ -27,6 +27,7 @@ void SessionData::initialize() {
mLocalCapture = false;
mOneShot = false;
strcpy(mCoreName, "unknown");
+ configurationXMLPath = NULL;
apcDir = NULL;
mSampleRate = 0;
mDuration = 0;
@@ -34,6 +35,8 @@ void SessionData::initialize() {
mBacktraceDepth = 0;
mTotalBufferSize = 0;
mCores = 1;
+
+ initializeCounters();
}
void SessionData::initializeCounters() {
@@ -62,39 +65,39 @@ void SessionData::parseSessionXML(char* xmlString) {
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) {
+ } 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;
+ gSessionData->mSampleRate = 10000;
} else if (strcmp(session.parameters.sample_rate, "normal") == 0) {
- gSessionData.mSampleRate = 1000;
+ gSessionData->mSampleRate = 1000;
} else { // "low"
- gSessionData.mSampleRate = 100;
+ gSessionData->mSampleRate = 100;
}
- gSessionData.mBacktraceDepth = session.parameters.call_stack_unwinding == true ? 128 : 0;
- gSessionData.mDuration = session.parameters.duration;
+ 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;
+ gSessionData->mOneShot = true;
if (strcmp(session.parameters.buffer_mode, "streaming") == 0) {
- gSessionData.mOneShot = false;
- gSessionData.mTotalBufferSize = 1;
+ gSessionData->mOneShot = false;
+ gSessionData->mTotalBufferSize = 1;
} else if (strcmp(session.parameters.buffer_mode, "small") == 0) {
- gSessionData.mTotalBufferSize = 1;
+ gSessionData->mTotalBufferSize = 1;
} else if (strcmp(session.parameters.buffer_mode, "normal") == 0) {
- gSessionData.mTotalBufferSize = 4;
+ gSessionData->mTotalBufferSize = 4;
} else if (strcmp(session.parameters.buffer_mode, "large") == 0) {
- gSessionData.mTotalBufferSize = 16;
+ 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;
+ gSessionData->images = session.parameters.images;
+ gSessionData->target_path = session.parameters.target_path;
+ gSessionData->title = session.parameters.title;
}
diff --git a/daemon/SessionData.h b/daemon/SessionData.h
index f3ae4a3..cc188f8 100644
--- a/daemon/SessionData.h
+++ b/daemon/SessionData.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -13,7 +13,7 @@
#define MAX_STRING_LEN 80
#define MAX_DESCRIPTION_LEN 400
-#define PROTOCOL_VERSION 7
+#define PROTOCOL_VERSION 8
#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions
struct ImageLinkList {
@@ -31,6 +31,7 @@ public:
char mCoreName[MAX_STRING_LEN];
struct ImageLinkList *images;
+ char* configurationXMLPath;
char* target_path;
char* apcDir;
char* title;
@@ -62,6 +63,6 @@ public:
char mPerfCounterOperation[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
};
-extern SessionData gSessionData;
+extern SessionData* gSessionData;
#endif // SESSION_DATA_H
diff --git a/daemon/SessionXML.cpp b/daemon/SessionXML.cpp
index 5034e48..4604d7c 100644
--- a/daemon/SessionXML.cpp
+++ b/daemon/SessionXML.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/SessionXML.h b/daemon/SessionXML.h
index b52b57f..4649685 100644
--- a/daemon/SessionXML.h
+++ b/daemon/SessionXML.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/StreamlineSetup.cpp b/daemon/StreamlineSetup.cpp
index 80a4ebb..5662ee8 100644
--- a/daemon/StreamlineSetup.cpp
+++ b/daemon/StreamlineSetup.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2011. All rights reserved.
+ * 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
@@ -41,7 +41,7 @@ StreamlineSetup::StreamlineSetup(OlySocket* s) {
// Receive commands from Streamline (master)
while (!ready) {
// receive command over socket
- gSessionData.mWaitingOnCommand = true;
+ gSessionData->mWaitingOnCommand = true;
data = readCommand(&type);
// parse and handle data
@@ -57,16 +57,12 @@ StreamlineSetup::StreamlineSetup(OlySocket* s) {
ready = true;
break;
case COMMAND_APC_STOP:
- // Clear error log so no text appears on console and exit
logg->logMessage("Received apc stop request before apc start request");
- logg->logError(__FILE__, __LINE__, "");
- handleException();
+ exit(0);
break;
case COMMAND_DISCONNECT:
- // Clear error log so no text appears on console and exit
logg->logMessage("Received disconnect command");
- logg->logError(__FILE__, __LINE__, "");
- handleException();
+ exit(0);
break;
case COMMAND_PING:
logg->logMessage("Received ping command");
@@ -95,7 +91,7 @@ char* StreamlineSetup::readCommand(int* command) {
response = socket->receiveNBytes(&type, sizeof(type));
// After receiving a single byte, we are no longer waiting on a command
- gSessionData.mWaitingOnCommand = false;
+ gSessionData->mWaitingOnCommand = false;
if (response < 0) {
logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect");
@@ -196,7 +192,7 @@ void StreamlineSetup::handleDeliver(char* xml) {
break;
case SESSION_XML:
// Parse the session xml
- gSessionData.parseSessionXML(xml);
+ gSessionData->parseSessionXML(xml);
// Save xml
mSessionXML = strdup(xml);
@@ -307,13 +303,19 @@ void StreamlineSetup::sendCounters() {
void StreamlineSetup::writeConfiguration(char* xml) {
char* path = (char*)malloc(PATH_MAX);
- util->getApplicationFullPath(path, PATH_MAX);
- strncat(path, "configuration.xml", PATH_MAX - strlen(path) - 1);
+ 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/daemon/StreamlineSetup.h b/daemon/StreamlineSetup.h
index c090afb..10327e0 100644
--- a/daemon/StreamlineSetup.h
+++ b/daemon/StreamlineSetup.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/XMLOut.cpp b/daemon/XMLOut.cpp
index 647e799..c194fc0 100644
--- a/daemon/XMLOut.cpp
+++ b/daemon/XMLOut.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/XMLOut.h b/daemon/XMLOut.h
index 479cfa9..3af253d 100644
--- a/daemon/XMLOut.h
+++ b/daemon/XMLOut.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/XMLReader.cpp b/daemon/XMLReader.cpp
index 45231ed..77c76e2 100644
--- a/daemon/XMLReader.cpp
+++ b/daemon/XMLReader.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/XMLReader.h b/daemon/XMLReader.h
index 55f655b..ac0098a 100644
--- a/daemon/XMLReader.h
+++ b/daemon/XMLReader.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/daemon/events-Cortex-A5.xml b/daemon/events-Cortex-A5.xml
index 3e2f5b2..fb671b1 100644
--- a/daemon/events-Cortex-A5.xml
+++ b/daemon/events-Cortex-A5.xml
@@ -19,7 +19,7 @@
<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="Fault" name="Unaligned access" description="Unaligned access 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"/>
diff --git a/daemon/events-Cortex-A7.xml b/daemon/events-Cortex-A7.xml
new file mode 100644
index 0000000..6b3db1b
--- /dev/null
+++ b/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/daemon/events-Cortex-A8.xml b/daemon/events-Cortex-A8.xml
index 1f78b0c..1a59d4c 100644
--- a/daemon/events-Cortex-A8.xml
+++ b/daemon/events-Cortex-A8.xml
@@ -21,7 +21,7 @@
<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="Fault" name="Unaligned access" description="Unaligned access 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"/>
@@ -33,8 +33,8 @@
<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 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 miss" description="Any L1 instruction memory access that misses in the cache as a result of the hashing algorithm"/>
+ <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"/>
diff --git a/daemon/events-Cortex-A9.xml b/daemon/events-Cortex-A9.xml
index 7bc2f21..7a27ed8 100644
--- a/daemon/events-Cortex-A9.xml
+++ b/daemon/events-Cortex-A9.xml
@@ -21,7 +21,7 @@
<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="Fault" name="Unaligned access" description="Unaligned access 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"/>
diff --git a/daemon/events-Krait-architected.xml b/daemon/events-Krait-architected.xml
new file mode 100644
index 0000000..1745cdb
--- /dev/null
+++ b/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/daemon/events-Linux.xml b/daemon/events-Linux.xml
index ed50429..333e7e2 100644
--- a/daemon/events-Linux.xml
+++ b/daemon/events-Linux.xml
@@ -8,9 +8,9 @@
<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_drv" title="Network" name="Gator" description="Network traffic from Gator driver"/>
<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>
- \ No newline at end of file
+
diff --git a/daemon/events-Mali-400.xml b/daemon/events-Mali-400.xml
new file mode 100644
index 0000000..cbe0cf2
--- /dev/null
+++ b/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/daemon/events-Scorpion.xml b/daemon/events-Scorpion.xml
index 212bfed..e7a74b0 100644
--- a/daemon/events-Scorpion.xml
+++ b/daemon/events-Scorpion.xml
@@ -20,94 +20,94 @@
<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="0x0f" title="Fault" name="Unaligned access" description="Unaligned access 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="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="0x4c" title="Scorpion" name="ICACHE_EXPL_INV" description=""/>
- <event event="0x4d" title="Scorpion" name="ICACHE_MISS" description=""/>
- <event event="0x4e" title="Scorpion" name="ICACHE_ACCESS" description=""/>
- <event event="0x4f" title="Scorpion" name="ICACHE_CACHEREQ_L2" description=""/>
- <event event="0x50" title="Scorpion" name="ICACHE_NOCACHE_L2" description=""/>
- <event event="0x51" title="Scorpion" name="HIQUP_NOPED" description=""/>
- <event event="0x52" title="Scorpion" name="DATA_ABORT" description=""/>
- <event event="0x53" title="Scorpion" name="IRQ" description=""/>
- <event event="0x54" title="Scorpion" name="FIQ" description=""/>
- <event event="0x55" title="Scorpion" name="ALL_EXCPT" description=""/>
- <event event="0x56" title="Scorpion" name="UNDEF" description=""/>
- <event event="0x57" title="Scorpion" name="SVC" description=""/>
- <event event="0x58" title="Scorpion" name="SMC" description=""/>
- <event event="0x59" title="Scorpion" name="PREFETCH_ABORT" description=""/>
- <event event="0x5a" title="Scorpion" name="INDEX_CHECK" description=""/>
- <event event="0x5b" title="Scorpion" name="NULL_CHECK" description=""/>
- <event event="0x5c" title="Scorpion" name="EXPL_ICIALLU" description=""/>
- <event event="0x5d" title="Scorpion" name="IMPL_ICIALLU" description=""/>
- <event event="0x5e" title="Scorpion" name="NONICIALLU_BTAC_INV" description=""/>
- <event event="0x5f" title="Scorpion" name="ICIMVAU_IMPL_ICIALLU" description=""/>
- <event event="0x60" title="Scorpion" name="SPIPE_ONLY_CYCLES" description=""/>
- <event event="0x61" title="Scorpion" name="XPIPE_ONLY_CYCLES" description=""/>
- <event event="0x62" title="Scorpion" name="DUAL_CYCLES" description=""/>
- <event event="0x63" title="Scorpion" name="DISPATCH_ANY_CYCLES" description=""/>
- <event event="0x64" title="Scorpion" name="FIFO_FULLBLK_CMT" description=""/>
- <event event="0x65" title="Scorpion" name="FAIL_COND_INST" description=""/>
- <event event="0x66" title="Scorpion" name="PASS_COND_INST" description=""/>
- <event event="0x67" title="Scorpion" name="ALLOW_VU_CLK" description=""/>
- <event event="0x68" title="Scorpion" name="VU_IDLE" description=""/>
- <event event="0x69" title="Scorpion" name="ALLOW_L2_CLK" description=""/>
- <event event="0x6a" title="Scorpion" name="L2_IDLE" description=""/>
- <event event="0x6b" title="Scorpion" name="DTLB_IMPL_INV_SCTLR_DACR" description=""/>
- <event event="0x6c" title="Scorpion" name="DTLB_EXPL_INV" description=""/>
- <event event="0x6d" title="Scorpion" name="DTLB_MISS" description=""/>
- <event event="0x6e" title="Scorpion" name="DTLB_ACCESS" description=""/>
- <event event="0x6f" title="Scorpion" name="ITLB_MISS" description=""/>
- <event event="0x70" title="Scorpion" name="ITLB_IMPL_INV" description=""/>
- <event event="0x71" title="Scorpion" name="ITLB_EXPL_INV" description=""/>
- <event event="0x72" title="Scorpion" name="UTLB_D_MISS" description=""/>
- <event event="0x73" title="Scorpion" name="UTLB_D_ACCESS" description=""/>
- <event event="0x74" title="Scorpion" name="UTLB_I_MISS" description=""/>
- <event event="0x75" title="Scorpion" name="UTLB_I_ACCESS" description=""/>
- <event event="0x76" title="Scorpion" name="UTLB_INV_ASID" description=""/>
- <event event="0x77" title="Scorpion" name="UTLB_INV_MVA" description=""/>
- <event event="0x78" title="Scorpion" name="UTLB_INV_ALL" description=""/>
- <event event="0x79" title="Scorpion" name="S2_HOLD_RDQ_UNAVAIL" description=""/>
- <event event="0x7a" title="Scorpion" name="S2_HOLD" description=""/>
- <event event="0x7b" title="Scorpion" name="S2_HOLD_DEV_OP" description=""/>
- <event event="0x7c" title="Scorpion" name="S2_HOLD_ORDER" description=""/>
- <event event="0x7d" title="Scorpion" name="S2_HOLD_BARRIER" description=""/>
- <event event="0x7e" title="Scorpion" name="VIU_DUAL_CYCLE" description=""/>
- <event event="0x7f" title="Scorpion" name="VIU_SINGLE_CYCLE" description=""/>
- <event event="0x80" title="Scorpion" name="VX_PIPE_WAR_STALL_CYCLES" description=""/>
- <event event="0x81" title="Scorpion" name="VX_PIPE_WAW_STALL_CYCLES" description=""/>
- <event event="0x82" title="Scorpion" name="VX_PIPE_RAW_STALL_CYCLES" description=""/>
- <event event="0x83" title="Scorpion" name="VX_PIPE_LOAD_USE_STALL" description=""/>
- <event event="0x84" title="Scorpion" name="VS_PIPE_WAR_STALL_CYCLES" description=""/>
- <event event="0x85" title="Scorpion" name="VS_PIPE_WAW_STALL_CYCLES" description=""/>
- <event event="0x86" title="Scorpion" name="VS_PIPE_RAW_STALL_CYCLES" description=""/>
- <event event="0x87" title="Scorpion" name="EXCEPTIONS_INV_OPERATION" description=""/>
- <event event="0x88" title="Scorpion" name="EXCEPTIONS_DIV_BY_ZERO" description=""/>
- <event event="0x89" title="Scorpion" name="COND_INST_FAIL_VX_PIPE" description=""/>
- <event event="0x8a" title="Scorpion" name="COND_INST_FAIL_VS_PIPE" description=""/>
- <event event="0x8b" title="Scorpion" name="EXCEPTIONS_OVERFLOW" description=""/>
- <event event="0x8c" title="Scorpion" name="EXCEPTIONS_UNDERFLOW" description=""/>
- <event event="0x8d" title="Scorpion" name="EXCEPTIONS_DENORM" description=""/>
- <event event="0x8e" title="Scorpion" name="BANK_AB_HIT" description=""/>
- <event event="0x8f" title="Scorpion" name="BANK_AB_ACCESS" description=""/>
- <event event="0x90" title="Scorpion" name="BANK_CD_HIT" description=""/>
- <event event="0x91" title="Scorpion" name="BANK_CD_ACCESS" description=""/>
- <event event="0x92" title="Scorpion" name="BANK_AB_DSIDE_HIT" description=""/>
- <event event="0x93" title="Scorpion" name="BANK_AB_DSIDE_ACCESS" description=""/>
- <event event="0x94" title="Scorpion" name="BANK_CD_DSIDE_HIT" description=""/>
- <event event="0x95" title="Scorpion" name="BANK_CD_DSIDE_ACCESS" description=""/>
- <event event="0x96" title="Scorpion" name="BANK_AB_ISIDE_HIT" description=""/>
- <event event="0x97" title="Scorpion" name="BANK_AB_ISIDE_ACCESS" description=""/>
- <event event="0x98" title="Scorpion" name="BANK_CD_ISIDE_HIT" description=""/>
- <event event="0x99" title="Scorpion" name="BANK_CD_ISIDE_ACCESS" description=""/>
- <event event="0x9a" title="Scorpion" name="ISIDE_RD_WAIT" description=""/>
- <event event="0x9b" title="Scorpion" name="DSIDE_RD_WAIT" description=""/>
- <event event="0x9c" title="Scorpion" name="BANK_BYPASS_WRITE" description=""/>
- <event event="0x9d" title="Scorpion" name="BANK_AB_NON_CASTOUT" description=""/>
- <event event="0x9e" title="Scorpion" name="BANK_AB_L2_CASTOUT" description=""/>
- <event event="0x9f" title="Scorpion" name="BANK_CD_NON_CASTOUT" description=""/>
- <event event="0xa0" title="Scorpion" name="BANK_CD_L2_CASTOUT" description=""/>
+ <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/daemon/events-ScorpionMP.xml b/daemon/events-ScorpionMP.xml
index 22c93a0..ef920b3 100644
--- a/daemon/events-ScorpionMP.xml
+++ b/daemon/events-ScorpionMP.xml
@@ -20,77 +20,77 @@
<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="0x0f" title="Fault" name="Unaligned access" description="Unaligned access 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="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="0x4c" title="Scorpion" name="ICACHE_EXPL_INV" description=""/>
- <event event="0x4d" title="Scorpion" name="ICACHE_MISS" description=""/>
- <event event="0x4e" title="Scorpion" name="ICACHE_ACCESS" description=""/>
- <event event="0x4f" title="Scorpion" name="ICACHE_CACHEREQ_L2" description=""/>
- <event event="0x50" title="Scorpion" name="ICACHE_NOCACHE_L2" description=""/>
- <event event="0x51" title="Scorpion" name="HIQUP_NOPED" description=""/>
- <event event="0x52" title="Scorpion" name="DATA_ABORT" description=""/>
- <event event="0x53" title="Scorpion" name="IRQ" description=""/>
- <event event="0x54" title="Scorpion" name="FIQ" description=""/>
- <event event="0x55" title="Scorpion" name="ALL_EXCPT" description=""/>
- <event event="0x56" title="Scorpion" name="UNDEF" description=""/>
- <event event="0x57" title="Scorpion" name="SVC" description=""/>
- <event event="0x58" title="Scorpion" name="SMC" description=""/>
- <event event="0x59" title="Scorpion" name="PREFETCH_ABORT" description=""/>
- <event event="0x5a" title="Scorpion" name="INDEX_CHECK" description=""/>
- <event event="0x5b" title="Scorpion" name="NULL_CHECK" description=""/>
- <event event="0x5c" title="Scorpion" name="EXPL_ICIALLU" description=""/>
- <event event="0x5d" title="Scorpion" name="IMPL_ICIALLU" description=""/>
- <event event="0x5e" title="Scorpion" name="NONICIALLU_BTAC_INV" description=""/>
- <event event="0x5f" title="Scorpion" name="ICIMVAU_IMPL_ICIALLU" description=""/>
- <event event="0x60" title="Scorpion" name="SPIPE_ONLY_CYCLES" description=""/>
- <event event="0x61" title="Scorpion" name="XPIPE_ONLY_CYCLES" description=""/>
- <event event="0x62" title="Scorpion" name="DUAL_CYCLES" description=""/>
- <event event="0x63" title="Scorpion" name="DISPATCH_ANY_CYCLES" description=""/>
- <event event="0x64" title="Scorpion" name="FIFO_FULLBLK_CMT" description=""/>
- <event event="0x65" title="Scorpion" name="FAIL_COND_INST" description=""/>
- <event event="0x66" title="Scorpion" name="PASS_COND_INST" description=""/>
- <event event="0x67" title="Scorpion" name="ALLOW_VU_CLK" description=""/>
- <event event="0x68" title="Scorpion" name="VU_IDLE" description=""/>
- <event event="0x69" title="Scorpion" name="ALLOW_L2_CLK" description=""/>
- <event event="0x6a" title="Scorpion" name="L2_IDLE" description=""/>
- <event event="0x6b" title="Scorpion" name="DTLB_IMPL_INV_SCTLR_DACR" description=""/>
- <event event="0x6c" title="Scorpion" name="DTLB_EXPL_INV" description=""/>
- <event event="0x6d" title="Scorpion" name="DTLB_MISS" description=""/>
- <event event="0x6e" title="Scorpion" name="DTLB_ACCESS" description=""/>
- <event event="0x6f" title="Scorpion" name="ITLB_MISS" description=""/>
- <event event="0x70" title="Scorpion" name="ITLB_IMPL_INV" description=""/>
- <event event="0x71" title="Scorpion" name="ITLB_EXPL_INV" description=""/>
- <event event="0x72" title="Scorpion" name="UTLB_D_MISS" description=""/>
- <event event="0x73" title="Scorpion" name="UTLB_D_ACCESS" description=""/>
- <event event="0x74" title="Scorpion" name="UTLB_I_MISS" description=""/>
- <event event="0x75" title="Scorpion" name="UTLB_I_ACCESS" description=""/>
- <event event="0x76" title="Scorpion" name="UTLB_INV_ASID" description=""/>
- <event event="0x77" title="Scorpion" name="UTLB_INV_MVA" description=""/>
- <event event="0x78" title="Scorpion" name="UTLB_INV_ALL" description=""/>
- <event event="0x79" title="Scorpion" name="S2_HOLD_RDQ_UNAVAIL" description=""/>
- <event event="0x7a" title="Scorpion" name="S2_HOLD" description=""/>
- <event event="0x7b" title="Scorpion" name="S2_HOLD_DEV_OP" description=""/>
- <event event="0x7c" title="Scorpion" name="S2_HOLD_ORDER" description=""/>
- <event event="0x7d" title="Scorpion" name="S2_HOLD_BARRIER" description=""/>
- <event event="0x7e" title="Scorpion" name="VIU_DUAL_CYCLE" description=""/>
- <event event="0x7f" title="Scorpion" name="VIU_SINGLE_CYCLE" description=""/>
- <event event="0x80" title="Scorpion" name="VX_PIPE_WAR_STALL_CYCLES" description=""/>
- <event event="0x81" title="Scorpion" name="VX_PIPE_WAW_STALL_CYCLES" description=""/>
- <event event="0x82" title="Scorpion" name="VX_PIPE_RAW_STALL_CYCLES" description=""/>
- <event event="0x83" title="Scorpion" name="VX_PIPE_LOAD_USE_STALL" description=""/>
- <event event="0x84" title="Scorpion" name="VS_PIPE_WAR_STALL_CYCLES" description=""/>
- <event event="0x85" title="Scorpion" name="VS_PIPE_WAW_STALL_CYCLES" description=""/>
- <event event="0x86" title="Scorpion" name="VS_PIPE_RAW_STALL_CYCLES" description=""/>
- <event event="0x87" title="Scorpion" name="EXCEPTIONS_INV_OPERATION" description=""/>
- <event event="0x88" title="Scorpion" name="EXCEPTIONS_DIV_BY_ZERO" description=""/>
- <event event="0x89" title="Scorpion" name="COND_INST_FAIL_VX_PIPE" description=""/>
- <event event="0x8a" title="Scorpion" name="COND_INST_FAIL_VS_PIPE" description=""/>
- <event event="0x8b" title="Scorpion" name="EXCEPTIONS_OVERFLOW" description=""/>
- <event event="0x8c" title="Scorpion" name="EXCEPTIONS_UNDERFLOW" description=""/>
- <event event="0x8d" title="Scorpion" name="EXCEPTIONS_DENORM" description=""/>
- <event event="0x8e" title="ScorpionMP" name="NUM_BARRIERS" description=""/>
- <event event="0x8f" title="ScorpionMP" name="BARRIER_CYCLES" description=""/>
+ <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/daemon/main.cpp b/daemon/main.cpp
index cf28bfc..51237cb 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -101,7 +101,7 @@ void child_exit(int signum) {
// retval: -1 = failure; 0 = was already mounted; 1 = successfully mounted
int mountGatorFS() {
// If already mounted,
- if (access("/dev/gator/buffer", F_OK) != -1)
+ if (access("/dev/gator/buffer", F_OK) == 0)
return 0;
// else, mount the filesystem
@@ -176,28 +176,34 @@ struct cmdline_t parseCommandLine(int argc, char** argv) {
struct cmdline_t cmdline;
cmdline.port = 8080;
cmdline.sessionXML = NULL;
-
- for (int i = 1; i < argc; i++) {
- // Is the argument a number?
- if (strtol(argv[i], NULL, 10) > 0) {
- cmdline.port = strtol(argv[i], NULL, 10);
- continue;
- }
-
- if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0 || strcmp(argv[i], "--help") == 0) {
- logg->logError(__FILE__, __LINE__,
- "Streamline gatord version %d. All parameters are optional:\n"
- "port_number\tport upon which the server listens; default is 8080\n"
- "session_xml\tfilename of a session xml used for local capture\n"
- "-v/--version\tversion information\n"
- "-h/--help\tthis help page\n", PROTOCOL_VERSION);
- handleException();
- } else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
- logg->logError(__FILE__, __LINE__, "Streamline gatord version %d", PROTOCOL_VERSION);
- handleException();
- } else {
- // Assume it is an .xml file
- cmdline.sessionXML = argv[i];
+ 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;
}
}
@@ -207,11 +213,17 @@ struct cmdline_t parseCommandLine(int argc, char** argv) {
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
@@ -223,10 +235,11 @@ int main(int argc, char** argv, char *envp[]) {
signal(SIGABRT, handler);
// Set to high priority
- setpriority(PRIO_PROCESS, syscall(__NR_gettid), -19);
+ if (setpriority(PRIO_PROCESS, syscall(__NR_gettid), -19) == -1)
+ logg->logMessage("setpriority() failed");
// Initialize session data
- gSessionData.initialize();
+ gSessionData->initialize();
// Parse the command line parameters
struct cmdline_t cmdline = parseCommandLine(argc, argv);
diff --git a/driver/Makefile b/driver/Makefile
index b3981ff..e521b99 100644
--- a/driver/Makefile
+++ b/driver/Makefile
@@ -10,7 +10,9 @@ gator-y := gator_main.o \
gator_events_sched.o \
gator_events_net.o \
gator_events_block.o \
- gator_events_meminfo.o
+ gator_events_meminfo.o \
+ gator_events_power.o \
+ gator_events_perf_pmu.o
gator-y += gator_events_mmaped.o
diff --git a/driver/gator.h b/driver/gator.h
index 724ae19..a7a323c 100644
--- a/driver/gator.h
+++ b/driver/gator.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -14,15 +14,25 @@
#include <linux/mm.h>
#include <linux/list.h>
+#define GATOR_PERF_SUPPORT LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+#define GATOR_PERF_PMU_SUPPORT GATOR_PERF_SUPPORT && defined(CONFIG_PERF_EVENTS) && defined(CONFIG_HW_PERF_EVENTS)
+#define GATOR_NO_PERF_SUPPORT (!(GATOR_PERF_SUPPORT))
+#define GATOR_CPU_FREQ_SUPPORT (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) && defined(CONFIG_CPU_FREQ)
+
// cpu ids
#define ARM1136 0xb36
#define ARM1156 0xb56
#define ARM1176 0xb76
#define ARM11MPCORE 0xb02
#define CORTEX_A5 0xc05
+#define CORTEX_A7 0xc07
#define CORTEX_A8 0xc08
#define CORTEX_A9 0xc09
#define CORTEX_A15 0xc0f
+#define SCORPION 0x00f
+#define SCORPIONMP 0x02d
+#define KRAITSIM 0x049
+#define KRAIT 0x04d
/******************************************************************************
* Filesystem
@@ -69,8 +79,10 @@ struct gator_interface {
int (*create_files)(struct super_block *sb, struct dentry *root);
int (*start)(void);
void (*stop)(void);
- void (*online)(void);
- void (*offline)(void);
+ int (*online)(int** buffer);
+ int (*offline)(int** buffer);
+ void (*online_dispatch)(int cpu); // called in process context but may not be running on core 'cpu'
+ void (*offline_dispatch)(int cpu); // called in process context but may not be running on core 'cpu'
int (*read)(int **buffer);
int (*read64)(long long **buffer);
struct list_head list;
@@ -84,6 +96,4 @@ int gator_events_install(struct gator_interface *interface);
int gator_events_get_key(void);
extern u32 gator_cpuid(void);
-extern unsigned long gator_net_traffic;
-
#endif // GATOR_H_
diff --git a/driver/gator_annotate.c b/driver/gator_annotate.c
index ee5a160..36a921c 100644
--- a/driver/gator_annotate.c
+++ b/driver/gator_annotate.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/driver/gator_annotate_kernel.c b/driver/gator_annotate_kernel.c
index 4f690e8..ffab087 100644
--- a/driver/gator_annotate_kernel.c
+++ b/driver/gator_annotate_kernel.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2011. All rights reserved.
+ * Copyright (C) ARM Limited 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
@@ -25,7 +25,6 @@ static void kannotate_write(char* ptr, unsigned int size)
// String annotation
void gator_annotate(char* string)
{
- printk(KERN_ERR "module: %s\n", string);
kannotate_write(string, strlen(string) + 1);
}
EXPORT_SYMBOL(gator_annotate);
diff --git a/driver/gator_backtrace.c b/driver/gator_backtrace.c
index fc81233..26503ef 100644
--- a/driver/gator_backtrace.c
+++ b/driver/gator_backtrace.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c
index c0c4b9c..1beb34f 100644
--- a/driver/gator_cookies.c
+++ b/driver/gator_cookies.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -250,12 +250,15 @@ static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task
// Can be called from interrupt handler or from work queue or from scheduler trace
local_irq_save(flags);
- cookie = per_cpu(cookie_next_key, cpu)+=nr_cpu_ids;
- cookiemap_add(key, cookie);
+ cookie = INVALID_COOKIE;
+ if (buffer_check_space(cpu, buftype, strlen(text) + 2 * MAXSIZE_PACK32)) {
+ cookie = per_cpu(cookie_next_key, cpu) += nr_cpu_ids;
+ cookiemap_add(key, cookie);
- gator_buffer_write_packed_int(cpu, buftype, MESSAGE_COOKIE);
- gator_buffer_write_packed_int(cpu, buftype, cookie);
- gator_buffer_write_string(cpu, buftype, text);
+ gator_buffer_write_packed_int(cpu, buftype, MESSAGE_COOKIE);
+ gator_buffer_write_packed_int(cpu, buftype, cookie);
+ gator_buffer_write_string(cpu, buftype, text);
+ }
local_irq_restore(flags);
diff --git a/driver/gator_ebs.c b/driver/gator_ebs.c
index 8b4b5ff..8c2997c 100644
--- a/driver/gator_ebs.c
+++ b/driver/gator_ebs.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2011. All rights reserved.
+ * Copyright (C) ARM Limited 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
@@ -7,171 +7,186 @@
*
*/
-/******************************************************************************
- * event based sampling handling
- ******************************************************************************/
-
-#if defined (__arm__)
-#include "gator_events_armv7.h"
+#if defined(__arm__) && (GATOR_PERF_PMU_SUPPORT)
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#if LINUX_PMU_SUPPORT
#include <asm/pmu.h>
-static struct platform_device *pmu_device;
+extern int pmnc_counters;
+extern int ccnt;
+extern unsigned long pmnc_enabled[];
+extern unsigned long pmnc_event[];
+extern unsigned long pmnc_count[];
+extern unsigned long pmnc_key[];
+
+static DEFINE_PER_CPU(struct perf_event *, pevent);
+static DEFINE_PER_CPU(struct perf_event_attr *, pevent_attr);
+static DEFINE_PER_CPU(int, key);
+static DEFINE_PER_CPU(unsigned int, prev_value);
-static irqreturn_t armv7_pmnc_interrupt(int irq, void *arg)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
+static void ebs_overflow_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs)
+#else
+static void ebs_overflow_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
+#endif
{
- unsigned int cnt, cpu = smp_processor_id(), buftype = EVENT_BUF;
- struct pt_regs * const regs = get_irq_regs();
- u32 flags;
-
- // Stop irq generation
- armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E);
-
- // Get and reset overflow status flags
- flags = armv7_pmnc_reset_interrupt();
-
- // Counters header
- gator_buffer_write_packed_int(cpu, buftype, MESSAGE_COUNTERS); // type
- gator_buffer_write_packed_int64(cpu, buftype, gator_get_time()); // time
-
- // Cycle counter
- if (flags & (1 << 31)) {
- int value = armv7_ccnt_read(pmnc_count[CCNT]); // overrun
- gator_buffer_write_packed_int(cpu, buftype, 2); // length
- gator_buffer_write_packed_int(cpu, buftype, pmnc_key[CCNT]); // key
- gator_buffer_write_packed_int(cpu, buftype, value); // value
- }
+ unsigned int value, delta, cpu = smp_processor_id(), buftype = EVENT_BUF;
- // PMNC counters
- for (cnt = CNT0; cnt < CNTMAX; cnt++) {
- if (flags & (1 << (cnt - CNT0))) {
- int value = armv7_cntn_read(cnt, pmnc_count[cnt]); // overrun
- gator_buffer_write_packed_int(cpu, buftype, 2); // length
- gator_buffer_write_packed_int(cpu, buftype, pmnc_key[cnt]); // key
- gator_buffer_write_packed_int(cpu, buftype, value); // value
- }
- }
+ if (event != per_cpu(pevent, cpu))
+ return;
- // End Counters, length of zero
- gator_buffer_write_packed_int(cpu, buftype, 0);
+ if (buffer_check_space(cpu, buftype, 5 * MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
+ value = local64_read(&event->count);
+ delta = value - per_cpu(prev_value, cpu);
+ per_cpu(prev_value, cpu) = value;
+
+ // Counters header
+ gator_buffer_write_packed_int(cpu, buftype, MESSAGE_COUNTERS); // type
+ gator_buffer_write_packed_int64(cpu, buftype, gator_get_time()); // time
+
+ // Output counter
+ gator_buffer_write_packed_int(cpu, buftype, 2); // length
+ gator_buffer_write_packed_int(cpu, buftype, per_cpu(key, cpu)); // key
+ gator_buffer_write_packed_int(cpu, buftype, delta); // delta
+
+ // End Counters, length of zero
+ gator_buffer_write_packed_int(cpu, buftype, 0);
+ }
// Output backtrace
- gator_add_sample(cpu, buftype, regs);
+ if (buffer_check_space(cpu, buftype, gator_backtrace_depth * 2 * MAXSIZE_PACK32))
+ gator_add_sample(cpu, buftype, regs);
// Check and commit; commit is set to occur once buffer is 3/4 full
- event_buffer_check(cpu);
+ buffer_check(cpu, buftype);
+}
+
+static void gator_event_sampling_online(void)
+{
+ int cpu = smp_processor_id(), buftype = EVENT_BUF;
- // Allow irq generation
- armv7_pmnc_write(armv7_pmnc_read() | PMNC_E);
+ // read the counter and toss the invalid data, return zero instead
+ struct perf_event * ev = per_cpu(pevent, cpu);
+ if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
+ ev->pmu->read(ev);
+ per_cpu(prev_value, cpu) = local64_read(&ev->count);
- return IRQ_HANDLED;
+ // Counters header
+ gator_buffer_write_packed_int(cpu, buftype, MESSAGE_COUNTERS); // type
+ gator_buffer_write_packed_int64(cpu, buftype, gator_get_time()); // time
+
+ // Output counter
+ gator_buffer_write_packed_int(cpu, buftype, 2); // length
+ gator_buffer_write_packed_int(cpu, buftype, per_cpu(key, cpu)); // key
+ gator_buffer_write_packed_int(cpu, buftype, 0); // delta - zero for initialization
+
+ // End Counters, length of zero
+ gator_buffer_write_packed_int(cpu, buftype, 0);
+ }
}
+
+static void gator_event_sampling_online_dispatch(int cpu)
+{
+ struct perf_event * ev;
+
+ if (!event_based_sampling)
+ return;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
+ ev = per_cpu(pevent, cpu) = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu), cpu, 0, ebs_overflow_handler);
+#else
+ ev = per_cpu(pevent, cpu) = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu), cpu, 0, ebs_overflow_handler, 0);
#endif
+ if (IS_ERR(ev)) {
+ pr_err("gator: unable to start event-based-sampling");
+ return;
+ }
+
+ if (ev->state != PERF_EVENT_STATE_ACTIVE) {
+ pr_err("gator: unable to start event-based-sampling");
+ perf_event_release_kernel(ev);
+ return;
+ }
+
+ ev->pmu->read(ev);
+ per_cpu(prev_value, cpu) = local64_read(&ev->count);
+}
+
+static void gator_event_sampling_offline_dispatch(int cpu)
+{
+ if (per_cpu(pevent, cpu)) {
+ perf_event_release_kernel(per_cpu(pevent, cpu));
+ per_cpu(pevent, cpu) = NULL;
+ }
+}
+
static int gator_event_sampling_start(void)
{
- int cnt;
+ int cnt, event = 0, count = 0, ebs_key = 0, cpu;
+
+ for_each_present_cpu(cpu) {
+ per_cpu(pevent, cpu) = NULL;
+ per_cpu(pevent_attr, cpu) = NULL;
+ }
event_based_sampling = false;
- for (cnt = CCNT; cnt < CNTMAX; cnt++) {
+ for (cnt = 0; cnt < pmnc_counters; cnt++) {
if (pmnc_count[cnt] > 0) {
event_based_sampling = true;
+ event = pmnc_event[cnt];
+ count = pmnc_count[cnt];
+ ebs_key = pmnc_key[cnt];
break;
}
}
-#if LINUX_PMU_SUPPORT
- pmu_device = reserve_pmu(ARM_PMU_DEVICE_CPU);
- if (IS_ERR(pmu_device) && (unsigned int)pmu_device != -ENODEV) {
- pr_err("gator: unable to reserve the pmu\n");
- return -1;
- }
-
- if (event_based_sampling) {
- int irq, i;
+ if (!event_based_sampling)
+ return 0;
- if (IS_ERR(pmu_device)) {
- pr_err("gator: event based sampling is not supported as the kernel function reserve_pmu() failed\n");
+ for_each_present_cpu(cpu) {
+ u32 size = sizeof(struct perf_event_attr);
+ per_cpu(pevent_attr, cpu) = kmalloc(size, GFP_KERNEL);
+ if (!per_cpu(pevent_attr, cpu))
return -1;
- }
- // init_pmu sets the irq affinity, therefore we do not care if it fails for single core
- if (init_pmu(ARM_PMU_DEVICE_CPU) != 0 && gator_cpu_cores > 1) {
- pr_err("gator: unable to initialize the pmu\n");
- goto out_ebs_start;
+ memset(per_cpu(pevent_attr, cpu), 0, size);
+ per_cpu(pevent_attr, cpu)->type = PERF_TYPE_RAW;
+ per_cpu(pevent_attr, cpu)->size = size;
+ per_cpu(pevent_attr, cpu)->config = event;
+ per_cpu(pevent_attr, cpu)->sample_period = count;
+ per_cpu(pevent_attr, cpu)->pinned = 1;
+
+ // handle special case for ccnt
+ if (cnt == ccnt) {
+ per_cpu(pevent_attr, cpu)->type = PERF_TYPE_HARDWARE;
+ per_cpu(pevent_attr, cpu)->config = PERF_COUNT_HW_CPU_CYCLES;
}
- if (pmu_device->num_resources == 0) {
- pr_err("gator: no irqs for PMUs defined\n");
- goto out_ebs_start;
- }
-
- for (i = 0; i < pmu_device->num_resources; ++i) {
- irq = platform_get_irq(pmu_device, i);
- if (irq < 0)
- continue;
-
- if (request_irq(irq, armv7_pmnc_interrupt, IRQF_DISABLED | IRQF_NOBALANCING, "armpmu", NULL)) {
- pr_err("gator: unable to request IRQ%d for ARM perf counters\n", irq);
-
- // clean up and exit
- for (i = i - 1; i >= 0; --i) {
- irq = platform_get_irq(pmu_device, i);
- if (irq >= 0)
- free_irq(irq, NULL);
- }
- goto out_ebs_start;
- }
- }
+ per_cpu(key, cpu) = ebs_key;
}
-#else
- if (event_based_sampling) {
- pr_err("gator: event based sampling only supported in kernel versions 2.6.35 and higher and CONFIG_CPU_HAS_PMU=y\n");
- return -1;
- }
-#endif
return 0;
-
-#if LINUX_PMU_SUPPORT
-out_ebs_start:
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
- release_pmu(pmu_device);
-#else
- release_pmu(ARM_PMU_DEVICE_CPU);
-#endif
- pmu_device = NULL;
- return -1;
-#endif
}
static void gator_event_sampling_stop(void)
{
-#if LINUX_PMU_SUPPORT
- if (event_based_sampling) {
- int i, irq;
- for (i = pmu_device->num_resources - 1; i >= 0; --i) {
- irq = platform_get_irq(pmu_device, i);
- if (irq >= 0)
- free_irq(irq, NULL);
+ int cpu;
+
+ for_each_present_cpu(cpu) {
+ if (per_cpu(pevent_attr, cpu)) {
+ kfree(per_cpu(pevent_attr, cpu));
+ per_cpu(pevent_attr, cpu) = NULL;
}
}
- if (!IS_ERR(pmu_device)) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
- release_pmu(pmu_device);
-#else
- release_pmu(ARM_PMU_DEVICE_CPU);
-#endif
- }
- pmu_device = NULL;
-#endif
}
#else
+static void gator_event_sampling_online(void) {}
+static void gator_event_sampling_online_dispatch(int cpu) {}
+static void gator_event_sampling_offline_dispatch(int cpu) {}
static int gator_event_sampling_start(void) {return 0;}
static void gator_event_sampling_stop(void) {}
#endif
diff --git a/driver/gator_events_armv6.c b/driver/gator_events_armv6.c
index 170f066..ef51898 100644
--- a/driver/gator_events_armv6.c
+++ b/driver/gator_events_armv6.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -8,6 +8,9 @@
#include "gator.h"
+// gator_events_perf_pmu.c is used if perf is supported
+#if GATOR_NO_PERF_SUPPORT
+
static const char *pmnc_name;
/*
@@ -28,7 +31,6 @@ static const char *pmnc_name;
static int pmnc_counters = 0;
static unsigned long pmnc_enabled[CNTMAX];
static unsigned long pmnc_event[CNTMAX];
-static unsigned long pmnc_count[CNTMAX];
static unsigned long pmnc_key[CNTMAX];
static DEFINE_PER_CPU(int[CNTMAX], perfPrev);
@@ -83,7 +85,6 @@ int gator_events_armv6_create_files(struct super_block *sb, struct dentry *root)
return -1;
}
gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]);
- gatorfs_create_ulong(sb, dir, "count", &pmnc_count[i]);
gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]);
if (i != CCNT) {
gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]);
@@ -93,9 +94,9 @@ int gator_events_armv6_create_files(struct super_block *sb, struct dentry *root)
return 0;
}
-static void gator_events_armv6_online(void)
+static int gator_events_armv6_online(int** buffer)
{
- unsigned int cnt;
+ unsigned int cnt, len = 0, cpu = smp_processor_id();
u32 pmnc;
if (armv6_pmnc_read() & PMCR_E) {
@@ -110,7 +111,7 @@ static void gator_events_armv6_online(void)
for (pmnc = 0, cnt = PMN0; cnt <= CCNT; cnt++) {
unsigned long event;
- per_cpu(perfPrev, smp_processor_id())[cnt] = 0;
+ per_cpu(perfPrev, cpu)[cnt] = 0;
if (!pmnc_enabled[cnt])
continue;
@@ -128,9 +129,22 @@ static void gator_events_armv6_online(void)
armv6_pmnc_reset_counter(cnt);
}
armv6_pmnc_write(pmnc | PMCR_E);
+
+ // return zero values, no need to read as the counters were just reset
+ for (cnt = PMN0; cnt <= CCNT; cnt++) {
+ if (pmnc_enabled[cnt]) {
+ per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt];
+ per_cpu(perfCnt, cpu)[len++] = 0;
+ }
+ }
+
+ if (buffer)
+ *buffer = per_cpu(perfCnt, cpu);
+
+ return len;
}
-static void gator_events_armv6_offline(void)
+static int gator_events_armv6_offline(int** buffer)
{
unsigned int cnt;
@@ -138,18 +152,6 @@ static void gator_events_armv6_offline(void)
for (cnt = PMN0; cnt <= CCNT; cnt++) {
armv6_pmnc_reset_counter(cnt);
}
-}
-
-static int gator_events_armv6_start(void)
-{
- int cnt;
-
- for (cnt = CCNT; cnt < CNTMAX; cnt++) {
- if (pmnc_count[cnt] > 0) {
- pr_err("gator: event based sampling not supported on ARM v6 architectures\n");
- return -1;
- }
- }
return 0;
}
@@ -161,7 +163,6 @@ static void gator_events_armv6_stop(void)
for (cnt = PMN0; cnt <= CCNT; cnt++) {
pmnc_enabled[cnt] = 0;
pmnc_event[cnt] = 0;
- pmnc_count[cnt] = 0;
}
}
@@ -193,7 +194,6 @@ static int gator_events_armv6_read(int **buffer)
}
}
- // update or discard
if (buffer)
*buffer = per_cpu(perfCnt, cpu);
@@ -202,7 +202,6 @@ static int gator_events_armv6_read(int **buffer)
static struct gator_interface gator_events_armv6_interface = {
.create_files = gator_events_armv6_create_files,
- .start = gator_events_armv6_start,
.stop = gator_events_armv6_stop,
.online = gator_events_armv6_online,
.offline = gator_events_armv6_offline,
@@ -229,10 +228,17 @@ int gator_events_armv6_init(void)
for (cnt = PMN0; cnt <= CCNT; cnt++) {
pmnc_enabled[cnt] = 0;
pmnc_event[cnt] = 0;
- pmnc_count[cnt] = 0;
pmnc_key[cnt] = gator_events_get_key();
}
return gator_events_install(&gator_events_armv6_interface);
}
+
gator_events_init(gator_events_armv6_init);
+
+#else
+int gator_events_armv6_init(void)
+{
+ return -1;
+}
+#endif
diff --git a/driver/gator_events_armv7.c b/driver/gator_events_armv7.c
index e1434e2..cdf450f 100644
--- a/driver/gator_events_armv7.c
+++ b/driver/gator_events_armv7.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -14,15 +14,29 @@
*/
#include "gator.h"
-#include "gator_events_armv7.h"
-const char *pmnc_name;
-int pmnc_counters;
+// gator_events_perf_pmu.c is used if perf is supported
+#if GATOR_NO_PERF_SUPPORT
-unsigned long pmnc_enabled[CNTMAX];
-unsigned long pmnc_event[CNTMAX];
-unsigned long pmnc_count[CNTMAX];
-unsigned long pmnc_key[CNTMAX];
+// Per-CPU PMNC: config reg
+#define PMNC_E (1 << 0) /* Enable all counters */
+#define PMNC_P (1 << 1) /* Reset all counters */
+#define PMNC_C (1 << 2) /* Cycle counter reset */
+#define PMNC_MASK 0x3f /* Mask for writable bits */
+
+// ccnt reg
+#define CCNT_REG (1 << 31)
+
+#define CCNT 0
+#define CNT0 1
+#define CNTMAX (6+1)
+
+static const char *pmnc_name;
+static int pmnc_counters;
+
+static unsigned long pmnc_enabled[CNTMAX];
+static unsigned long pmnc_event[CNTMAX];
+static unsigned long pmnc_key[CNTMAX];
static DEFINE_PER_CPU(int[CNTMAX], perfPrev);
static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt);
@@ -76,19 +90,13 @@ inline u32 armv7_cntn_read(unsigned int cnt, u32 reset_value)
return oldval;
}
-static inline void armv7_pmnc_enable_interrupt(unsigned int cnt)
-{
- u32 val = cnt ? (1 << (cnt - CNT0)) : (1 << 31);
- asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val));
-}
-
static inline void armv7_pmnc_disable_interrupt(unsigned int cnt)
{
u32 val = cnt ? (1 << (cnt - CNT0)) : (1 << 31);
asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val));
}
-inline u32 armv7_pmnc_reset_interrupt()
+inline u32 armv7_pmnc_reset_interrupt(void)
{
// Get and reset overflow status flags
u32 flags;
@@ -143,7 +151,6 @@ static int gator_events_armv7_create_files(struct super_block *sb, struct dentry
return -1;
}
gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]);
- gatorfs_create_ulong(sb, dir, "count", &pmnc_count[i]);
gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]);
if (i > 0) {
gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]);
@@ -153,10 +160,9 @@ static int gator_events_armv7_create_files(struct super_block *sb, struct dentry
return 0;
}
-static void gator_events_armv7_online(void)
+static int gator_events_armv7_online(int** buffer)
{
- unsigned int cnt;
- int cpu = smp_processor_id();
+ unsigned int cnt, len = 0, cpu = smp_processor_id();
if (armv7_pmnc_read() & PMNC_E) {
armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E);
@@ -185,14 +191,10 @@ static void gator_events_armv7_online(void)
if (cnt != CCNT)
armv7_pmnc_write_evtsel(cnt, event);
- // Enable/disable interrupt
- if (pmnc_count[cnt] > 0)
- armv7_pmnc_enable_interrupt(cnt);
- else
- armv7_pmnc_disable_interrupt(cnt);
+ armv7_pmnc_disable_interrupt(cnt);
// Reset counter
- cnt ? armv7_cntn_read(cnt, pmnc_count[cnt]) : armv7_ccnt_read(pmnc_count[cnt]);
+ cnt ? armv7_cntn_read(cnt, 0) : armv7_ccnt_read(0);
// Enable counter
armv7_pmnc_enable_counter(cnt);
@@ -200,12 +202,27 @@ static void gator_events_armv7_online(void)
// enable
armv7_pmnc_write(armv7_pmnc_read() | PMNC_E);
+
+ // return zero values, no need to read as the counters were just reset
+ for (cnt = 0; cnt < pmnc_counters; cnt++) {
+ if (pmnc_enabled[cnt]) {
+ per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt];
+ per_cpu(perfCnt, cpu)[len++] = 0;
+ }
+ }
+
+ if (buffer)
+ *buffer = per_cpu(perfCnt, cpu);
+
+ return len;
}
-static void gator_events_armv7_offline(void)
+static int gator_events_armv7_offline(int** buffer)
{
// disbale all counters, including PMCCNTR; overflow IRQs will not be signaled
armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E);
+
+ return 0;
}
static void gator_events_armv7_stop(void)
@@ -215,7 +232,6 @@ static void gator_events_armv7_stop(void)
for (cnt = CCNT; cnt < CNTMAX; cnt++) {
pmnc_enabled[cnt] = 0;
pmnc_event[cnt] = 0;
- pmnc_count[cnt] = 0;
}
}
@@ -224,11 +240,8 @@ static int gator_events_armv7_read(int **buffer)
int cnt, len = 0;
int cpu = smp_processor_id();
- if (!pmnc_counters)
- return 0;
-
for (cnt = 0; cnt < pmnc_counters; cnt++) {
- if (pmnc_enabled[cnt] && pmnc_count[cnt] == 0) {
+ if (pmnc_enabled[cnt]) {
int value;
if (cnt == CCNT) {
value = armv7_ccnt_read(0);
@@ -243,7 +256,6 @@ static int gator_events_armv7_read(int **buffer)
}
}
- // update or discard
if (buffer)
*buffer = per_cpu(perfCnt, cpu);
@@ -267,6 +279,10 @@ int gator_events_armv7_init(void)
pmnc_name = "Cortex-A5";
pmnc_counters = 2;
break;
+ case CORTEX_A7:
+ pmnc_name = "Cortex-A7";
+ pmnc_counters = 4;
+ break;
case CORTEX_A8:
pmnc_name = "Cortex-A8";
pmnc_counters = 4;
@@ -288,10 +304,17 @@ int gator_events_armv7_init(void)
for (cnt = CCNT; cnt < CNTMAX; cnt++) {
pmnc_enabled[cnt] = 0;
pmnc_event[cnt] = 0;
- pmnc_count[cnt] = 0;
pmnc_key[cnt] = gator_events_get_key();
}
return gator_events_install(&gator_events_armv7_interface);
}
+
gator_events_init(gator_events_armv7_init);
+
+#else
+int gator_events_armv7_init(void)
+{
+ return -1;
+}
+#endif
diff --git a/driver/gator_events_armv7.h b/driver/gator_events_armv7.h
deleted file mode 100644
index d5e8d6e..0000000
--- a/driver/gator_events_armv7.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2011. 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 GATOR_EVENTS_ARMV7_H_
-#define GATOR_EVENTS_ARMV7_H_
-
-// Per-CPU PMNC: config reg
-#define PMNC_E (1 << 0) /* Enable all counters */
-#define PMNC_P (1 << 1) /* Reset all counters */
-#define PMNC_C (1 << 2) /* Cycle counter reset */
-#define PMNC_MASK 0x3f /* Mask for writable bits */
-
-// ccnt reg
-#define CCNT_REG (1 << 31)
-
-#define CCNT 0
-#define CNT0 1
-#define CNTMAX (6+1)
-
-// Function prototypes
-extern void armv7_pmnc_write(u32 val);
-extern u32 armv7_pmnc_read(void);
-extern u32 armv7_ccnt_read(u32 reset_value);
-extern u32 armv7_cntn_read(unsigned int cnt, u32 reset_value);
-extern u32 armv7_pmnc_reset_interrupt(void);
-
-// Externed variables
-extern unsigned long pmnc_enabled[CNTMAX];
-extern unsigned long pmnc_event[CNTMAX];
-extern unsigned long pmnc_count[CNTMAX];
-extern unsigned long pmnc_key[CNTMAX];
-
-#endif // GATOR_EVENTS_ARMV7_H_
diff --git a/driver/gator_events_block.c b/driver/gator_events_block.c
index cbfed86..f1bbbc8 100644
--- a/driver/gator_events_block.c
+++ b/driver/gator_events_block.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/driver/gator_events_irq.c b/driver/gator_events_irq.c
index 36a6589..59461b9 100644
--- a/driver/gator_events_irq.c
+++ b/driver/gator_events_irq.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -72,15 +72,38 @@ static int gator_events_irq_create_files(struct super_block *sb, struct dentry *
return 0;
}
-static int gator_events_irq_start(void)
+static int gator_events_irq_online(int** buffer)
{
- int cpu, i;
+ int len = 0, cpu = smp_processor_id();
+ unsigned long flags; // not necessary as we are in interrupt context anyway, but doesn't hurt
+
+ // synchronization with the irq_exit functions is not necessary as the values are being reset
+ if (hardirq_enabled) {
+ local_irq_save(flags);
+ per_cpu(irqCnt, cpu)[HARDIRQ] = 0;
+ local_irq_restore(flags);
+ per_cpu(irqPrev, cpu)[HARDIRQ] = 0;
+ per_cpu(irqGet, cpu)[len++] = hardirq_key;
+ per_cpu(irqGet, cpu)[len++] = 0;
+ }
- for_each_present_cpu(cpu) {
- for (i = 0; i < TOTALIRQ; i++)
- per_cpu(irqPrev, cpu)[i] = 0;
+ if (softirq_enabled) {
+ local_irq_save(flags);
+ per_cpu(irqCnt, cpu)[SOFTIRQ] = 0;
+ local_irq_restore(flags);
+ per_cpu(irqPrev, cpu)[SOFTIRQ] = 0;
+ per_cpu(irqGet, cpu)[len++] = softirq_key;
+ per_cpu(irqGet, cpu)[len++] = 0;
}
+ if (buffer)
+ *buffer = per_cpu(irqGet, cpu);
+
+ return len;
+}
+
+static int gator_events_irq_start(void)
+{
// register tracepoints
if (hardirq_enabled)
if (GATOR_REGISTER_TRACE(irq_handler_exit))
@@ -116,7 +139,7 @@ static void gator_events_irq_stop(void)
static int gator_events_irq_read(int **buffer)
{
- unsigned long flags;
+ unsigned long flags; // not necessary as we are in interrupt context anyway, but doesn't hurt
int len, value;
int cpu = smp_processor_id();
@@ -153,6 +176,7 @@ static int gator_events_irq_read(int **buffer)
static struct gator_interface gator_events_irq_interface = {
.create_files = gator_events_irq_create_files,
+ .online = gator_events_irq_online,
.start = gator_events_irq_start,
.stop = gator_events_irq_stop,
.read = gator_events_irq_read,
diff --git a/driver/gator_events_l2c-310.c b/driver/gator_events_l2c-310.c
index 96683b3..bd1c48a 100644
--- a/driver/gator_events_l2c-310.c
+++ b/driver/gator_events_l2c-310.c
@@ -1,7 +1,7 @@
/**
* l2c310 (L2 Cache Controller) event counters for gator
*
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -148,10 +148,7 @@ int gator_events_l2c310_init(void)
if (gator_cpuid() != CORTEX_A5 && gator_cpuid() != CORTEX_A9)
return -1;
-#if defined(CONFIG_ARCH_EXYNOS4)
- gator_events_l2c310_probe(0xfe600000);
-#endif
-#if defined(CONFIG_ARCH_S5PV310)
+#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_S5PV310)
gator_events_l2c310_probe(0x10502000);
#endif
#if defined(CONFIG_ARCH_OMAP4)
diff --git a/driver/gator_events_mali.c b/driver/gator_events_mali.c
new file mode 100644
index 0000000..31e8f0d
--- /dev/null
+++ b/driver/gator_events_mali.c
@@ -0,0 +1,611 @@
+/**
+ * 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 "gator.h"
+
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/math64.h>
+
+#include "linux/mali_linux_trace.h"
+
+#define ACTIVITY_START 1
+#define ACTIVITY_STOP 2
+
+#ifndef MALI_SUPPORT
+#error MALI_SUPPORT not defined!
+#endif
+
+#define MALI_200 0x0a07
+#define MALI_300 0x0b06 //This is not actually true; Mali-300 is also 0x0b07
+#define MALI_400 0x0b07
+#define MALI_T6xx 0x0056
+
+static const char *mali_name;
+
+enum counters {
+ /* Timeline activity */
+ ACTIVITY_VP = 0,
+ ACTIVITY_FP0,
+ ACTIVITY_FP1,
+ ACTIVITY_FP2,
+ ACTIVITY_FP3,
+
+ /* L2 cache counters */
+ COUNTER_L2_C0,
+ COUNTER_L2_C1,
+
+ /* Vertex processor counters */
+ COUNTER_VP_C0,
+ COUNTER_VP_C1,
+
+ /* Fragment processor counters */
+ COUNTER_FP0_C0,
+ COUNTER_FP0_C1,
+ COUNTER_FP1_C0,
+ COUNTER_FP1_C1,
+ COUNTER_FP2_C0,
+ COUNTER_FP2_C1,
+ COUNTER_FP3_C0,
+ COUNTER_FP3_C1,
+
+ /* EGL Software Counters */
+ COUNTER_EGL_BLIT_TIME,
+
+ /* GLES Software Counters */
+ COUNTER_GLES_DRAW_ELEMENTS_CALLS,
+ COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES,
+ COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED,
+ COUNTER_GLES_DRAW_ARRAYS_CALLS,
+ COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED,
+ COUNTER_GLES_DRAW_POINTS,
+ COUNTER_GLES_DRAW_LINES,
+ COUNTER_GLES_DRAW_LINE_LOOP,
+ COUNTER_GLES_DRAW_LINE_STRIP,
+ COUNTER_GLES_DRAW_TRIANGLES,
+ COUNTER_GLES_DRAW_TRIANGLE_STRIP,
+ COUNTER_GLES_DRAW_TRIANGLE_FAN,
+ COUNTER_GLES_NON_VBO_DATA_COPY_TIME,
+ COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI,
+ COUNTER_GLES_UPLOAD_TEXTURE_TIME,
+ COUNTER_GLES_UPLOAD_VBO_TIME,
+ COUNTER_GLES_NUM_FLUSHES,
+ COUNTER_GLES_NUM_VSHADERS_GENERATED,
+ COUNTER_GLES_NUM_FSHADERS_GENERATED,
+ COUNTER_GLES_VSHADER_GEN_TIME,
+ COUNTER_GLES_FSHADER_GEN_TIME,
+ COUNTER_GLES_INPUT_TRIANGLES,
+ COUNTER_GLES_VXCACHE_HIT,
+ COUNTER_GLES_VXCACHE_MISS,
+ COUNTER_GLES_VXCACHE_COLLISION,
+ COUNTER_GLES_CULLED_TRIANGLES,
+ COUNTER_GLES_CULLED_LINES,
+ COUNTER_GLES_BACKFACE_TRIANGLES,
+ COUNTER_GLES_GBCLIP_TRIANGLES,
+ COUNTER_GLES_GBCLIP_LINES,
+ COUNTER_GLES_TRIANGLES_DRAWN,
+ COUNTER_GLES_DRAWCALL_TIME,
+ COUNTER_GLES_TRIANGLES_COUNT,
+ COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT,
+ COUNTER_GLES_STRIP_TRIANGLES_COUNT,
+ COUNTER_GLES_FAN_TRIANGLES_COUNT,
+ COUNTER_GLES_LINES_COUNT,
+ COUNTER_GLES_INDEPENDENT_LINES_COUNT,
+ COUNTER_GLES_STRIP_LINES_COUNT,
+ COUNTER_GLES_LOOP_LINES_COUNT,
+
+ COUNTER_FILMSTRIP,
+
+ NUMBER_OF_EVENTS
+};
+
+#define FIRST_ACTIVITY_EVENT ACTIVITY_VP
+#define LAST_ACTIVITY_EVENT ACTIVITY_FP3
+
+#define FIRST_HW_COUNTER COUNTER_L2_C0
+#define LAST_HW_COUNTER COUNTER_FP3_C1
+
+#define FIRST_SW_COUNTER COUNTER_EGL_BLIT_TIME
+#define LAST_SW_COUNTER COUNTER_GLES_LOOP_LINES_COUNT
+
+#define FIRST_SPECIAL_COUNTER COUNTER_FILMSTRIP
+#define LAST_SPECIAL_COUNTER COUNTER_FILMSTRIP
+
+/* gatorfs variables for counter enable state,
+ * the event the counter should count and the
+ * 'key' (a unique id set by gatord and returned
+ * by gator.ko)
+ */
+static unsigned long counter_enabled[NUMBER_OF_EVENTS];
+static unsigned long counter_event[NUMBER_OF_EVENTS];
+static unsigned long counter_key[NUMBER_OF_EVENTS];
+
+/* The data we have recorded */
+static u32 counter_data[NUMBER_OF_EVENTS];
+/* The address to sample (or 0 if samples are sent to us) */
+static u32* counter_address[NUMBER_OF_EVENTS];
+
+/* An array used to return the data we recorded
+ * as key,value pairs hence the *2
+ */
+static unsigned long counter_dump[NUMBER_OF_EVENTS * 2];
+static unsigned long counter_prev[NUMBER_OF_EVENTS];
+
+/* Note whether tracepoints have been registered */
+static int trace_registered;
+
+/**
+ * Calculate the difference and handle the overflow.
+ */
+static u32 get_difference(u32 start, u32 end)
+{
+ if (start - end >= 0)
+ {
+ return start - end;
+ }
+
+ // Mali counters are unsigned 32 bit values that wrap.
+ return (4294967295u - end) + start;
+}
+
+/**
+ * Returns non-zero if the given counter ID is an activity counter.
+ */
+static inline int is_activity_counter(unsigned int event_id)
+{
+ return (event_id >= FIRST_ACTIVITY_EVENT &&
+ event_id <= LAST_ACTIVITY_EVENT);
+}
+
+/**
+ * Returns non-zero if the given counter ID is a hardware counter.
+ */
+static inline int is_hw_counter(unsigned int event_id)
+{
+ return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER);
+}
+
+/**
+ * Returns non-zero if the given counter ID is a software counter.
+ */
+static inline int is_sw_counter(unsigned int event_id)
+{
+ return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER);
+}
+
+/*
+ * The Mali DDK uses s64 types to contain software counter values, but gator
+ * can only use a maximum of 32 bits. This function scales a software counter
+ * to an appopriate range.
+ */
+static u32 scale_sw_counter_value(unsigned int event_id, signed long long value)
+{
+ u32 scaled_value;
+
+ switch (event_id) {
+ case COUNTER_GLES_UPLOAD_TEXTURE_TIME:
+ case COUNTER_GLES_UPLOAD_VBO_TIME:
+ scaled_value = (u32)div_s64(value, 1000000);
+ break;
+ default:
+ scaled_value = (u32)value;
+ break;
+ }
+
+ return scaled_value;
+}
+
+/* Probe for continuously sampled counter */
+#if 0 //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING
+GATOR_DEFINE_PROBE(mali_sample_address, TP_PROTO(unsigned int event_id, u32* addr))
+{
+ /* Turning on too many pr_debug statements in frequently called functions
+ * can cause stability and/or performance problems
+ */
+ //pr_debug("gator: mali_sample_address %d %d\n", event_id, addr);
+ if (event_id >= ACTIVITY_VP && event_id <= COUNTER_FP3_C1) {
+ counter_address[event_id] = addr;
+ }
+}
+#endif
+
+/* Probe for hardware counter events */
+GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int value))
+{
+ /* Turning on too many pr_debug statements in frequently called functions
+ * can cause stability and/or performance problems
+ */
+ //pr_debug("gator: mali_hw_counter %d %d\n", event_id, value);
+ if (is_hw_counter(event_id)) {
+ counter_data[event_id] = value;
+ }
+}
+
+GATOR_DEFINE_PROBE(mali_sw_counter, TP_PROTO(unsigned int event_id, signed long long value))
+{
+ if (is_sw_counter(event_id)) {
+ counter_data[event_id] = scale_sw_counter_value(event_id, value);
+ }
+}
+
+//TODO need to work out how many fp units we have
+u32 gator_mali_get_n_fp(void) {
+ return 4;
+}
+
+//TODO need to work out what kind of Mali we are looking at
+u32 gator_mali_get_id(void) {
+ return MALI_SUPPORT;
+}
+
+int gator_events_mali_create_files(struct super_block *sb, struct dentry *root) {
+ struct dentry *dir;
+ int event;
+ int n_fp = gator_mali_get_n_fp();
+
+ /*
+ * Create the filesystem entries for vertex processor, fragement processor
+ * and L2 cache timeline and hardware counters. Software counters get
+ * special handling after this block.
+ */
+ for (event = FIRST_ACTIVITY_EVENT; event <= LAST_HW_COUNTER; event++)
+ {
+ char buf[40];
+
+ /*
+ * We can skip this event if it's for a non-existent fragment
+ * processor.
+ */
+ if (((event - ACTIVITY_FP0 >= n_fp) && (event < COUNTER_L2_C0)) ||
+ (((event - COUNTER_FP0_C0)/2 >= n_fp)))
+ {
+ continue;
+ }
+
+ /* Otherwise, set up the filesystem entry for this event. */
+ switch (event) {
+ case ACTIVITY_VP:
+ snprintf(buf, sizeof buf, "ARM_%s_VP_active", mali_name);
+ break;
+ case ACTIVITY_FP0:
+ case ACTIVITY_FP1:
+ case ACTIVITY_FP2:
+ case ACTIVITY_FP3:
+ snprintf(buf, sizeof buf, "ARM_%s_FP%d_active",
+ mali_name, event - ACTIVITY_FP0);
+ break;
+ case COUNTER_L2_C0:
+ case COUNTER_L2_C1:
+ snprintf(buf, sizeof buf, "ARM_%s_L2_cnt%d",
+ mali_name, event - COUNTER_L2_C0);
+ break;
+ case COUNTER_VP_C0:
+ case COUNTER_VP_C1:
+ snprintf(buf, sizeof buf, "ARM_%s_VP_cnt%d",
+ mali_name, event - COUNTER_VP_C0);
+ break;
+ case COUNTER_FP0_C0:
+ case COUNTER_FP0_C1:
+ case COUNTER_FP1_C0:
+ case COUNTER_FP1_C1:
+ case COUNTER_FP2_C0:
+ case COUNTER_FP2_C1:
+ case COUNTER_FP3_C0:
+ case COUNTER_FP3_C1:
+ snprintf(buf, sizeof buf, "ARM_%s_FP%d_cnt%d", mali_name,
+ (event - COUNTER_FP0_C0) / 2, (event - COUNTER_FP0_C0) % 2);
+ break;
+ default:
+ printk("gator: trying to create file for non-existent counter (%d)\n", event);
+ continue;
+ }
+
+ dir = gatorfs_mkdir(sb, root, buf);
+
+ if (!dir) {
+ return -1;
+ }
+
+ gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
+
+ /* Only create an event node for counters that can change what they count */
+ if (event >= COUNTER_L2_C0) {
+ gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
+ }
+
+ gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
+ }
+
+ /* Now set up the software counter entries */
+ for (event = FIRST_SW_COUNTER; event <= LAST_SW_COUNTER; event++)
+ {
+ char buf[40];
+
+ snprintf(buf, sizeof(buf), "ARM_%s_SW_%d", mali_name, event);
+
+ dir = gatorfs_mkdir(sb, root, buf);
+
+ if (!dir) {
+ return -1;
+ }
+
+ gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
+ gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
+ }
+
+ /* Now set up the special counter entries */
+ for (event = FIRST_SPECIAL_COUNTER; event <= LAST_SPECIAL_COUNTER; event++)
+ {
+ char buf[40];
+
+ snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip", mali_name);
+
+ dir = gatorfs_mkdir(sb, root, buf);
+
+ if (!dir) {
+ return -1;
+ }
+
+ gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
+ gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
+ gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
+ }
+
+
+ return 0;
+}
+
+//TODO
+void _mali_profiling_set_event(unsigned int, unsigned int);
+void _mali_osk_fb_control_set(unsigned int, unsigned int);
+
+void _mali_profiling_get_counters(unsigned int*, unsigned int*, unsigned int*, unsigned int*);
+void (*_mali_profiling_get_counters_function_pointer)(unsigned int*, unsigned int*, unsigned int*, unsigned int*);
+
+static void mali_counter_initialize(void)
+{
+ /* If a Mali driver is present and exporting the appropriate symbol
+ * then we can request the HW counters (of which there are only 2)
+ * be configured to count the desired events
+ */
+ void (*set_hw_event)(unsigned int, unsigned int);
+ void (*set_fb_event)(unsigned int, unsigned int);
+
+ set_hw_event = symbol_get(_mali_profiling_set_event);
+
+ if (set_hw_event) {
+ int i;
+
+ pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n",set_hw_event);
+
+ for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
+ if (counter_enabled[i]) {
+ set_hw_event(i, counter_event[i]);
+ } else {
+ set_hw_event(i, 0xFFFFFFFF);
+ }
+ }
+
+ symbol_put(_mali_profiling_set_event);
+ } else {
+ printk("gator: mali online _mali_profiling_set_event symbol not found\n");
+ }
+
+ set_fb_event = symbol_get(_mali_osk_fb_control_set);
+
+ if (set_fb_event) {
+ pr_debug("gator: mali online _mali_osk_fb_control_set symbol @ %p\n", set_fb_event);
+
+ set_fb_event(0,(counter_enabled[COUNTER_FILMSTRIP]?1:0));
+
+ symbol_put(_mali_osk_fb_control_set);
+ } else {
+ printk("gator: mali online _mali_osk_fb_control_set symbol not found\n");
+ }
+
+ _mali_profiling_get_counters_function_pointer = symbol_get(_mali_profiling_get_counters);
+ if (_mali_profiling_get_counters_function_pointer){
+ pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", _mali_profiling_get_counters_function_pointer);
+ counter_prev[COUNTER_L2_C0] = 0;
+ counter_prev[COUNTER_L2_C1] = 0;
+ }
+ else{
+ pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined");
+ }
+
+}
+
+static void mali_counter_deinitialize(void)
+{
+ void (*set_hw_event)(unsigned int, unsigned int);
+ void (*set_fb_event)(unsigned int, unsigned int);
+
+ set_hw_event = symbol_get(_mali_profiling_set_event);
+
+ if (set_hw_event) {
+ int i;
+
+ pr_debug("gator: mali offline _mali_profiling_set_event symbol @ %p\n",set_hw_event);
+ for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
+ set_hw_event(i, 0xFFFFFFFF);
+ }
+
+ symbol_put(_mali_profiling_set_event);
+ } else {
+ printk("gator: mali offline _mali_profiling_set_event symbol not found\n");
+ }
+
+ set_fb_event = symbol_get(_mali_osk_fb_control_set);
+
+ if (set_fb_event) {
+ pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", set_fb_event);
+
+ set_fb_event(0,0);
+
+ symbol_put(_mali_osk_fb_control_set);
+ } else {
+ printk("gator: mali offline _mali_osk_fb_control_set symbol not found\n");
+ }
+
+ if (_mali_profiling_get_counters_function_pointer){
+ symbol_put(_mali_profiling_get_counters);
+ }
+
+}
+
+static int gator_events_mali_start(void) {
+ // register tracepoints
+ if (GATOR_REGISTER_TRACE(mali_hw_counter)) {
+ printk("gator: mali_hw_counter tracepoint failed to activate\n");
+ return -1;
+ }
+
+ if (GATOR_REGISTER_TRACE(mali_sw_counter)) {
+ printk("gator: mali_sw_counter tracepoint failed to activate\n");
+ return -1;
+ }
+
+ trace_registered = 1;
+
+ mali_counter_initialize();
+ return 0;
+}
+
+static void gator_events_mali_stop(void) {
+ unsigned int cnt;
+
+ pr_debug("gator: mali stop\n");
+
+ if (trace_registered) {
+ GATOR_UNREGISTER_TRACE(mali_hw_counter);
+ GATOR_UNREGISTER_TRACE(mali_sw_counter);
+
+ pr_debug("gator: mali timeline tracepoint deactivated\n");
+
+ trace_registered = 0;
+ }
+
+ for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) {
+ counter_enabled[cnt] = 0;
+ counter_event[cnt] = 0;
+ counter_address[cnt] = NULL;
+ }
+
+ mali_counter_deinitialize();
+}
+
+static int gator_events_mali_read(int **buffer) {
+ int cnt, len = 0;
+
+ if (smp_processor_id()) return 0;
+
+ // Read the L2 C0 and C1 here.
+ if (counter_enabled[COUNTER_L2_C0] || counter_enabled[COUNTER_L2_C1] ) {
+ u32 src0 = 0;
+ u32 val0 = 0;
+ u32 src1 = 0;
+ u32 val1 = 0;
+
+ // Poke the driver to get the counter values
+ if (_mali_profiling_get_counters_function_pointer){
+ _mali_profiling_get_counters_function_pointer(&src0, &val0, &src1, &val1);
+ }
+
+ if (counter_enabled[COUNTER_L2_C0])
+ {
+ // Calculate and save src0's counter val0
+ counter_dump[len++] = counter_key[COUNTER_L2_C0];
+ counter_dump[len++] = get_difference(val0, counter_prev[COUNTER_L2_C0]);
+ }
+
+ if (counter_enabled[COUNTER_L2_C1])
+ {
+ // Calculate and save src1's counter val1
+ counter_dump[len++] = counter_key[COUNTER_L2_C1];
+ counter_dump[len++] = get_difference(val1, counter_prev[COUNTER_L2_C1]);
+ }
+
+ // Save the previous values for the counters.
+ counter_prev[COUNTER_L2_C0] = val0;
+ counter_prev[COUNTER_L2_C1] = val1;
+ }
+
+ // Process other (non-timeline) counters.
+ for (cnt = COUNTER_VP_C0; cnt <= LAST_SW_COUNTER; cnt++) {
+ if (counter_enabled[cnt]) {
+ u32 value = 0;
+
+ // Determine the current value of the counter.
+ if( counter_address[cnt] != NULL && 0 ) { // Never true!
+ value = *counter_address[cnt];
+ } else if (counter_data[cnt]!=0) {
+ value = counter_data[cnt];
+ counter_data[cnt] = 0;
+ }
+
+ // Send the counter value only if it differs from last time.
+ if (value != counter_prev[cnt]) {
+ counter_prev[cnt] = value;
+ counter_dump[len++] = counter_key[cnt];
+ counter_dump[len++] = value;
+ }
+ }
+ }
+
+ if (buffer) {
+ *buffer = (int*) counter_dump;
+ }
+
+ return len;
+}
+
+static struct gator_interface gator_events_mali_interface = {
+ .create_files = gator_events_mali_create_files,
+ .start = gator_events_mali_start,
+ .stop = gator_events_mali_stop,
+ .read = gator_events_mali_read,
+};
+
+int gator_events_mali_init(void)
+{
+ unsigned int cnt;
+ u32 id = gator_mali_get_id();
+
+ switch (id) {
+ case MALI_T6xx:
+ mali_name = "Mali-T6xx";
+ break;
+ case MALI_400:
+ mali_name = "Mali-400";
+ break;
+ case MALI_300:
+ mali_name = "Mali-300";
+ break;
+ case MALI_200:
+ mali_name = "Mali-200";
+ break;
+ default:
+ printk("Unknown Mali ID (%d)\n", id);
+ return -1;
+ }
+
+ pr_debug("gator: mali init\n");
+
+ for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) {
+ counter_enabled[cnt] = 0;
+ counter_event[cnt] = 0;
+ counter_key[cnt] = gator_events_get_key();
+ counter_address[cnt] = NULL;
+ counter_data[cnt] = 0;
+ }
+
+ trace_registered = 0;
+
+ return gator_events_install(&gator_events_mali_interface);
+}
+gator_events_init(gator_events_mali_init);
diff --git a/driver/gator_events_meminfo.c b/driver/gator_events_meminfo.c
index a1a2031..8af9cfc 100644
--- a/driver/gator_events_meminfo.c
+++ b/driver/gator_events_meminfo.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/driver/gator_events_mmaped.c b/driver/gator_events_mmaped.c
index 6884684..cbb22b1 100644
--- a/driver/gator_events_mmaped.c
+++ b/driver/gator_events_mmaped.c
@@ -1,13 +1,15 @@
/*
* Example events provider
*
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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.
*
- * Similar entires must be present in events.xml file:
+ * Similar entries to those below must be present in the events.xml file.
+ * To add them to the events.xml, create an events-mmap.xml with the
+ * following contents and rebuild gatord:
*
* <counter_set name="mmaped_cntX">
* <counter name="mmaped_cnt0"/>
diff --git a/driver/gator_events_net.c b/driver/gator_events_net.c
index a921586..ef1623b 100644
--- a/driver/gator_events_net.c
+++ b/driver/gator_events_net.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -12,13 +12,10 @@
#define NETRX 0
#define NETTX 1
-#define NETDRV 2
-#define TOTALNET (NETDRV+1)
+#define TOTALNET 2
-static ulong netdrv_enabled;
static ulong netrx_enabled;
static ulong nettx_enabled;
-static ulong netdrv_key;
static ulong netrx_key;
static ulong nettx_key;
static int rx_total, tx_total;
@@ -44,19 +41,9 @@ static void get_network_stats(struct work_struct *wsptr) {
}
DECLARE_WORK(wq_get_stats, get_network_stats);
-static void calculate_delta(int *drv, int *rx, int *tx)
+static void calculate_delta(int *rx, int *tx)
{
- int drv_calc, rx_calc, tx_calc;
-
- drv_calc = gator_net_traffic - netPrev[NETDRV];
- if (drv_calc > 0) {
- netPrev[NETDRV] += drv_calc;
- netPrev[NETTX] += drv_calc;
- // remove tcp/ip header overhead
- // approximation based on empirical measurement
- netPrev[NETRX] += drv_calc / 42;
- netPrev[NETTX] += drv_calc / 18;
- }
+ int rx_calc, tx_calc;
rx_calc = (int)(rx_total - netPrev[NETRX]);
if (rx_calc < 0)
@@ -68,7 +55,6 @@ static void calculate_delta(int *drv, int *rx, int *tx)
tx_calc = 0;
netPrev[NETTX] += tx_calc;
- *drv = drv_calc;
*rx = rx_calc;
*tx = tx_calc;
}
@@ -77,13 +63,6 @@ static int gator_events_net_create_files(struct super_block *sb, struct dentry *
{
struct dentry *dir;
- dir = gatorfs_mkdir(sb, root, "Linux_net_drv");
- if (!dir) {
- return -1;
- }
- gatorfs_create_ulong(sb, dir, "enabled", &netdrv_enabled);
- gatorfs_create_ro_ulong(sb, dir, "key", &netdrv_key);
-
dir = gatorfs_mkdir(sb, root, "Linux_net_rx");
if (!dir) {
return -1;
@@ -104,7 +83,6 @@ static int gator_events_net_create_files(struct super_block *sb, struct dentry *
static int gator_events_net_start(void)
{
get_network_stats(NULL);
- netPrev[NETDRV] = 0;
netPrev[NETRX] = rx_total;
netPrev[NETTX] = tx_total;
return 0;
@@ -112,29 +90,22 @@ static int gator_events_net_start(void)
static void gator_events_net_stop(void)
{
- netdrv_enabled = 0;
netrx_enabled = 0;
nettx_enabled = 0;
}
static int gator_events_net_read(int **buffer)
{
- int len, drv_delta, rx_delta, tx_delta;
- static int last_drv_delta = 0, last_rx_delta = 0, last_tx_delta = 0;
+ int len, rx_delta, tx_delta;
+ static int last_rx_delta = 0, last_tx_delta = 0;
if (smp_processor_id() != 0)
return 0;
schedule_work(&wq_get_stats);
- calculate_delta(&drv_delta, &rx_delta, &tx_delta);
+ calculate_delta(&rx_delta, &tx_delta);
len = 0;
- if (netdrv_enabled && last_drv_delta != drv_delta) {
- last_drv_delta = drv_delta;
- netGet[len++] = netdrv_key;
- netGet[len++] = drv_delta;
- }
-
if (netrx_enabled && last_rx_delta != rx_delta) {
last_rx_delta = rx_delta;
netGet[len++] = netrx_key;
@@ -162,13 +133,9 @@ static struct gator_interface gator_events_net_interface = {
int gator_events_net_init(void)
{
- gator_net_traffic++;
-
- netdrv_key = gator_events_get_key();
netrx_key = gator_events_get_key();
nettx_key = gator_events_get_key();
- netdrv_enabled = 0;
netrx_enabled = 0;
nettx_enabled = 0;
diff --git a/driver/gator_events_perf_pmu.c b/driver/gator_events_perf_pmu.c
new file mode 100644
index 0000000..322ebc4
--- /dev/null
+++ b/driver/gator_events_perf_pmu.c
@@ -0,0 +1,296 @@
+/**
+ * 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 <linux/slab.h>
+#include <linux/perf_event.h>
+#include "gator.h"
+
+// gator_events_armvX.c is used for Linux 2.6.x
+#if GATOR_PERF_PMU_SUPPORT
+
+static const char *pmnc_name;
+int pmnc_counters;
+int ccnt = 0;
+
+#define CNTMAX (6+1)
+
+unsigned long pmnc_enabled[CNTMAX];
+unsigned long pmnc_event[CNTMAX];
+unsigned long pmnc_count[CNTMAX];
+unsigned long pmnc_key[CNTMAX];
+
+static DEFINE_PER_CPU(int[CNTMAX], perfCurr);
+static DEFINE_PER_CPU(int[CNTMAX], perfPrev);
+static DEFINE_PER_CPU(int[CNTMAX], perfPrevDelta);
+static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt);
+static DEFINE_PER_CPU(struct perf_event *[CNTMAX], pevent);
+static DEFINE_PER_CPU(struct perf_event_attr *[CNTMAX], pevent_attr);
+
+static void gator_events_perf_pmu_stop(void);
+
+static int gator_events_perf_pmu_create_files(struct super_block *sb, struct dentry *root)
+{
+ struct dentry *dir;
+ int i;
+
+ for (i = 0; i < pmnc_counters; i++) {
+ char buf[40];
+ if (i == 0) {
+ snprintf(buf, sizeof buf, "%s_ccnt", pmnc_name);
+ } else {
+ snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i-1);
+ }
+ dir = gatorfs_mkdir(sb, root, buf);
+ if (!dir) {
+ return -1;
+ }
+ gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]);
+ gatorfs_create_ulong(sb, dir, "count", &pmnc_count[i]);
+ gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]);
+ if (i > 0) {
+ gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]);
+ }
+ }
+
+ return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
+static void dummy_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs)
+#else
+static void dummy_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
+#endif
+{
+// Required as perf_event_create_kernel_counter() requires an overflow handler, even though all we do is poll
+}
+
+static int gator_events_perf_pmu_online(int** buffer)
+{
+ int cnt, len = 0, cpu = smp_processor_id();
+
+ // read the counters and toss the invalid data, return zero instead
+ for (cnt = 0; cnt < pmnc_counters; cnt++) {
+ struct perf_event * ev = per_cpu(pevent, cpu)[cnt];
+ if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
+ ev->pmu->read(ev);
+ per_cpu(perfPrev, cpu)[cnt] = per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count);
+ per_cpu(perfPrevDelta, cpu)[cnt] = 0;
+ per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt];
+ per_cpu(perfCnt, cpu)[len++] = 0;
+ }
+ }
+
+ if (buffer)
+ *buffer = per_cpu(perfCnt, cpu);
+
+ return len;
+}
+
+static void gator_events_perf_pmu_online_dispatch(int cpu)
+{
+ int cnt;
+
+ for (cnt = 0; cnt < pmnc_counters; cnt++) {
+ if (per_cpu(pevent, cpu)[cnt] != NULL || per_cpu(pevent_attr, cpu)[cnt] == 0)
+ continue;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
+ per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, dummy_handler);
+#else
+ per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, dummy_handler, 0);
+#endif
+ if (IS_ERR(per_cpu(pevent, cpu)[cnt])) {
+ pr_debug("gator: unable to online a counter on cpu %d\n", cpu);
+ per_cpu(pevent, cpu)[cnt] = NULL;
+ continue;
+ }
+
+ if (per_cpu(pevent, cpu)[cnt]->state != PERF_EVENT_STATE_ACTIVE) {
+ pr_debug("gator: inactive counter on cpu %d\n", cpu);
+ perf_event_release_kernel(per_cpu(pevent, cpu)[cnt]);
+ per_cpu(pevent, cpu)[cnt] = NULL;
+ continue;
+ }
+ }
+}
+
+static void gator_events_perf_pmu_offline_dispatch(int cpu)
+{
+ int cnt;
+
+ for (cnt = 0; cnt < pmnc_counters; cnt++) {
+ if (per_cpu(pevent, cpu)[cnt] != NULL) {
+ perf_event_release_kernel(per_cpu(pevent, cpu)[cnt]);
+ per_cpu(pevent, cpu)[cnt] = NULL;
+ }
+ }
+}
+
+static int gator_events_perf_pmu_start(void)
+{
+ int cnt, cpu;
+ u32 size = sizeof(struct perf_event_attr);
+
+ for_each_present_cpu(cpu) {
+ for (cnt = 0; cnt < pmnc_counters; cnt++) {
+ per_cpu(pevent, cpu)[cnt] = NULL;
+ if (!pmnc_enabled[cnt] || pmnc_count[cnt] > 0) // Skip disabled counters and EBS counters
+ continue;
+
+ per_cpu(perfPrev, cpu)[cnt] = 0;
+ per_cpu(perfCurr, cpu)[cnt] = 0;
+ per_cpu(perfPrevDelta, cpu)[cnt] = 0;
+ per_cpu(pevent_attr, cpu)[cnt] = kmalloc(size, GFP_KERNEL);
+ if (!per_cpu(pevent_attr, cpu)[cnt]) {
+ gator_events_perf_pmu_stop();
+ return -1;
+ }
+
+ memset(per_cpu(pevent_attr, cpu)[cnt], 0, size);
+ per_cpu(pevent_attr, cpu)[cnt]->type = PERF_TYPE_RAW;
+ per_cpu(pevent_attr, cpu)[cnt]->size = size;
+ per_cpu(pevent_attr, cpu)[cnt]->config = pmnc_event[cnt];
+ per_cpu(pevent_attr, cpu)[cnt]->sample_period = 0;
+ per_cpu(pevent_attr, cpu)[cnt]->pinned = 1;
+
+ // handle special case for ccnt
+ if (cnt == ccnt) {
+ per_cpu(pevent_attr, cpu)[cnt]->type = PERF_TYPE_HARDWARE;
+ per_cpu(pevent_attr, cpu)[cnt]->config = PERF_COUNT_HW_CPU_CYCLES;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void gator_events_perf_pmu_stop(void)
+{
+ unsigned int cnt, cpu;
+
+ for_each_present_cpu(cpu) {
+ for (cnt = 0; cnt < pmnc_counters; cnt++) {
+ if (per_cpu(pevent_attr, cpu)[cnt]) {
+ kfree(per_cpu(pevent_attr, cpu)[cnt]);
+ per_cpu(pevent_attr, cpu)[cnt] = NULL;
+ }
+ }
+ }
+
+ for (cnt = 0; cnt < pmnc_counters; cnt++) {
+ pmnc_enabled[cnt] = 0;
+ pmnc_event[cnt] = 0;
+ pmnc_count[cnt] = 0;
+ }
+}
+
+static int gator_events_perf_pmu_read(int **buffer)
+{
+ int cnt, delta, len = 0;
+ int cpu = smp_processor_id();
+
+ for (cnt = 0; cnt < pmnc_counters; cnt++) {
+ struct perf_event * ev = per_cpu(pevent, cpu)[cnt];
+ if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
+ ev->pmu->read(ev);
+ per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count);
+ delta = per_cpu(perfCurr, cpu)[cnt] - per_cpu(perfPrev, cpu)[cnt];
+ if (delta != per_cpu(perfPrevDelta, cpu)[cnt]) {
+ per_cpu(perfPrevDelta, cpu)[cnt] = delta;
+ per_cpu(perfPrev, cpu)[cnt] = per_cpu(perfCurr, cpu)[cnt];
+ per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt];
+ if (delta < 0)
+ delta *= -1;
+ per_cpu(perfCnt, cpu)[len++] = delta;
+ }
+ }
+ }
+
+ if (buffer)
+ *buffer = per_cpu(perfCnt, cpu);
+
+ return len;
+}
+
+static struct gator_interface gator_events_perf_pmu_interface = {
+ .create_files = gator_events_perf_pmu_create_files,
+ .start = gator_events_perf_pmu_start,
+ .stop = gator_events_perf_pmu_stop,
+ .online = gator_events_perf_pmu_online,
+ .online_dispatch = gator_events_perf_pmu_online_dispatch,
+ .offline_dispatch = gator_events_perf_pmu_offline_dispatch,
+ .read = gator_events_perf_pmu_read,
+};
+
+int gator_events_perf_pmu_init(void)
+{
+ unsigned int cnt;
+
+ switch (gator_cpuid()) {
+ case ARM1136:
+ case ARM1156:
+ case ARM1176:
+ pmnc_name = "ARM_ARM11";
+ pmnc_counters = 3;
+ ccnt = 2;
+ break;
+ case ARM11MPCORE:
+ pmnc_name = "ARM_ARM11MPCore";
+ pmnc_counters = 3;
+ break;
+ case CORTEX_A5:
+ pmnc_name = "ARM_Cortex-A5";
+ pmnc_counters = 2;
+ break;
+ case CORTEX_A7:
+ pmnc_name = "ARM_Cortex-A7";
+ pmnc_counters = 4;
+ break;
+ case CORTEX_A8:
+ pmnc_name = "ARM_Cortex-A8";
+ pmnc_counters = 4;
+ break;
+ case CORTEX_A9:
+ pmnc_name = "ARM_Cortex-A9";
+ pmnc_counters = 6;
+ break;
+ case CORTEX_A15:
+ pmnc_name = "ARM_Cortex-A15";
+ pmnc_counters = 6;
+ break;
+ case SCORPION:
+ pmnc_name = "Scorpion";
+ pmnc_counters = 4;
+ break;
+ case SCORPIONMP:
+ pmnc_name = "ScorpionMP";
+ pmnc_counters = 4;
+ break;
+ case KRAITSIM:
+ case KRAIT:
+ pmnc_name = "Krait";
+ pmnc_counters = 4;
+ break;
+ default:
+ return -1;
+ }
+
+ pmnc_counters++; // CNT[n] + CCNT
+
+ for (cnt = 0; cnt < CNTMAX; cnt++) {
+ pmnc_enabled[cnt] = 0;
+ pmnc_event[cnt] = 0;
+ pmnc_count[cnt] = 0;
+ pmnc_key[cnt] = gator_events_get_key();
+ }
+
+ return gator_events_install(&gator_events_perf_pmu_interface);
+}
+
+gator_events_init(gator_events_perf_pmu_init);
+#endif
diff --git a/driver/gator_events_power.c b/driver/gator_events_power.c
new file mode 100644
index 0000000..a0ae684
--- /dev/null
+++ b/driver/gator_events_power.c
@@ -0,0 +1,178 @@
+/**
+ * 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 "gator.h"
+#include <linux/slab.h>
+#include <linux/cpufreq.h>
+#include <trace/events/power.h>
+
+// cpu_frequency and cpu_idle trace points were introduced in Linux kernel v2.6.38
+// the now deprecated power_frequency trace point was available prior to 2.6.38, but only for x86
+// CPU Idle is currently disabled in the .xml
+#if GATOR_CPU_FREQ_SUPPORT
+enum {
+ POWER_CPU_FREQ,
+ POWER_CPU_IDLE,
+ POWER_TOTAL
+};
+
+static ulong power_cpu_enabled[POWER_TOTAL];
+static ulong power_cpu_key[POWER_TOTAL];
+static DEFINE_PER_CPU(ulong[POWER_TOTAL], power);
+static DEFINE_PER_CPU(ulong[POWER_TOTAL], prev);
+static DEFINE_PER_CPU(int *, powerGet);
+
+GATOR_DEFINE_PROBE(cpu_frequency, TP_PROTO(unsigned int frequency, unsigned int cpu))
+{
+ per_cpu(power, cpu)[POWER_CPU_FREQ] = frequency * 1000;
+}
+
+GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu))
+{
+ per_cpu(power, cpu)[POWER_CPU_IDLE] = state;
+}
+
+static int gator_events_power_create_files(struct super_block *sb, struct dentry *root)
+{
+ struct dentry *dir;
+
+ // cpu_frequency
+ dir = gatorfs_mkdir(sb, root, "Linux_power_cpu_freq");
+ if (!dir) {
+ return -1;
+ }
+ gatorfs_create_ulong(sb, dir, "enabled", &power_cpu_enabled[POWER_CPU_FREQ]);
+ gatorfs_create_ro_ulong(sb, dir, "key", &power_cpu_key[POWER_CPU_FREQ]);
+
+ // cpu_idle
+ dir = gatorfs_mkdir(sb, root, "Linux_power_cpu_idle");
+ if (!dir) {
+ return -1;
+ }
+ gatorfs_create_ulong(sb, dir, "enabled", &power_cpu_enabled[POWER_CPU_IDLE]);
+ gatorfs_create_ro_ulong(sb, dir, "key", &power_cpu_key[POWER_CPU_IDLE]);
+
+ return 0;
+}
+
+static int gator_events_power_populate(int cpu, int** buffer)
+{
+ int i, len = 0;
+
+ for (i = 0; i < POWER_TOTAL; i++) {
+ if (power_cpu_enabled[i]) {
+ if (per_cpu(power, cpu)[i] != per_cpu(prev, cpu)[i]) {
+ per_cpu(prev, cpu)[i] = per_cpu(power, cpu)[i];
+ per_cpu(powerGet, cpu)[len++] = power_cpu_key[i];
+ per_cpu(powerGet, cpu)[len++] = per_cpu(power, cpu)[i];
+ }
+ }
+ }
+
+ if (buffer)
+ *buffer = per_cpu(powerGet, cpu);
+
+ return len;
+}
+
+static int gator_events_power_online(int** buffer)
+{
+ int i, cpu = smp_processor_id();
+ for (i = 0; i < POWER_TOTAL; i++)
+ per_cpu(prev, cpu)[i] = -1;
+ per_cpu(power, cpu)[POWER_CPU_FREQ] = cpufreq_quick_get(cpu) * 1000;
+ return gator_events_power_populate(cpu, buffer);
+}
+
+static int gator_events_power_offline(int** buffer)
+{
+ int cpu = smp_processor_id();
+ // Set frequency to zero on an offline
+ per_cpu(power, cpu)[POWER_CPU_FREQ] = 0;
+ return gator_events_power_populate(cpu, buffer);
+}
+
+static int gator_events_power_start(void)
+{
+ int cpu;
+
+ for_each_present_cpu(cpu) {
+ per_cpu(powerGet, cpu) = kmalloc(POWER_TOTAL * 2, GFP_KERNEL);
+ if (!per_cpu(powerGet, cpu))
+ return -1;
+ }
+
+ // register tracepoints
+ if (power_cpu_enabled[POWER_CPU_FREQ])
+ if (GATOR_REGISTER_TRACE(cpu_frequency))
+ goto fail_cpu_frequency_exit;
+ if (power_cpu_enabled[POWER_CPU_IDLE])
+ if (GATOR_REGISTER_TRACE(cpu_idle))
+ goto fail_cpu_idle_exit;
+ pr_debug("gator: registered power event tracepoints\n");
+
+ return 0;
+
+ // unregister tracepoints on error
+fail_cpu_idle_exit:
+ GATOR_UNREGISTER_TRACE(cpu_frequency);
+fail_cpu_frequency_exit:
+ pr_err("gator: power event tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n");
+
+ return -1;
+}
+
+static void gator_events_power_stop(void)
+{
+ int i, cpu;
+ if (power_cpu_enabled[POWER_CPU_FREQ])
+ GATOR_UNREGISTER_TRACE(cpu_frequency);
+ if (power_cpu_enabled[POWER_CPU_IDLE])
+ GATOR_UNREGISTER_TRACE(cpu_idle);
+ pr_debug("gator: unregistered power event tracepoints\n");
+
+ for (i = 0; i < POWER_TOTAL; i++) {
+ power_cpu_enabled[i] = 0;
+ }
+
+ for_each_present_cpu(cpu) {
+ kfree(per_cpu(powerGet, cpu));
+ }
+}
+
+static int gator_events_power_read(int **buffer)
+{
+ return gator_events_power_populate(smp_processor_id(), buffer);
+}
+
+static struct gator_interface gator_events_power_interface = {
+ .create_files = gator_events_power_create_files,
+ .online = gator_events_power_online,
+ .offline = gator_events_power_offline,
+ .start = gator_events_power_start,
+ .stop = gator_events_power_stop,
+ .read = gator_events_power_read,
+};
+#endif
+
+int gator_events_power_init(void)
+{
+#if (GATOR_CPU_FREQ_SUPPORT)
+ int i;
+ for (i = 0; i < POWER_TOTAL; i++) {
+ power_cpu_enabled[i] = 0;
+ power_cpu_key[i] = gator_events_get_key();
+ }
+
+ return gator_events_install(&gator_events_power_interface);
+#else
+ return -1;
+#endif
+}
+gator_events_init(gator_events_power_init);
diff --git a/driver/gator_events_sched.c b/driver/gator_events_sched.c
index 7e9db60..9bed364 100644
--- a/driver/gator_events_sched.c
+++ b/driver/gator_events_sched.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/driver/gator_events_scorpion.c b/driver/gator_events_scorpion.c
index f51e292..477e7c9 100644
--- a/driver/gator_events_scorpion.c
+++ b/driver/gator_events_scorpion.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2011. All rights reserved.
+ * 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
@@ -8,8 +8,8 @@
#include "gator.h"
-#define SCORPION 0xf
-#define SCORPIONMP 0x2d
+// gator_events_perf_pmu.c is used if perf is supported
+#if GATOR_NO_PERF_SUPPORT
static const char *pmnc_name;
static int pmnc_counters;
@@ -32,7 +32,6 @@ static int pmnc_counters;
static unsigned long pmnc_enabled[CNTMAX];
static unsigned long pmnc_event[CNTMAX];
-static unsigned long pmnc_count[CNTMAX];
static unsigned long pmnc_key[CNTMAX];
static DEFINE_PER_CPU(int[CNTMAX], perfPrev);
@@ -516,7 +515,6 @@ static int gator_events_scorpion_create_files(struct super_block *sb, struct den
return -1;
}
gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]);
- gatorfs_create_ulong(sb, dir, "count", &pmnc_count[i]);
gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]);
if (i > 0) {
gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]);
@@ -526,9 +524,9 @@ static int gator_events_scorpion_create_files(struct super_block *sb, struct den
return 0;
}
-static void gator_events_scorpion_online(void)
+static int gator_events_scorpion_online(int** buffer)
{
- unsigned int cnt;
+ unsigned int cnt, len = 0, cpu = smp_processor_id();
if (scorpion_pmnc_read() & PMNC_E) {
scorpion_pmnc_write(scorpion_pmnc_read() & ~PMNC_E);
@@ -563,26 +561,34 @@ static void gator_events_scorpion_online(void)
// enable
scorpion_pmnc_write(scorpion_pmnc_read() | PMNC_E);
-}
-static void gator_events_scorpion_offline(void)
-{
- scorpion_pmnc_write(scorpion_pmnc_read() & ~PMNC_E);
+ // read the counters and toss the invalid data, return zero instead
+ for (cnt = 0; cnt < pmnc_counters; cnt++) {
+ if (pmnc_enabled[cnt]) {
+ int value;
+ if (cnt == CCNT) {
+ value = scorpion_ccnt_read();
+ } else if (scorpion_pmnc_select_counter(cnt) == cnt) {
+ value = scorpion_cntn_read();
+ } else {
+ value = 0;
+ }
+ scorpion_pmnc_reset_counter(cnt);
+ per_cpu(perfPrev, cpu)[cnt] = 0;
+ per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt];
+ per_cpu(perfCnt, cpu)[len++] = 0;
+ }
+ }
- // investigate: need to do the clearpmu() here on each counter?
+ if (buffer)
+ *buffer = per_cpu(perfCnt, cpu);
+
+ return len;
}
-static int gator_events_scorpion_start(void)
+static int gator_events_scorpion_offline(int** buffer)
{
- int cnt;
-
- for (cnt = CCNT; cnt < CNTMAX; cnt++) {
- if (pmnc_count[cnt] > 0) {
- pr_err("gator: event based sampling not supported on Scorpion cores\n");
- return -1;
- }
- }
-
+ scorpion_pmnc_write(scorpion_pmnc_read() & ~PMNC_E);
return 0;
}
@@ -593,7 +599,6 @@ static void gator_events_scorpion_stop(void)
for (cnt = CCNT; cnt < CNTMAX; cnt++) {
pmnc_enabled[cnt] = 0;
pmnc_event[cnt] = 0;
- pmnc_count[cnt] = 0;
}
}
@@ -602,9 +607,6 @@ static int gator_events_scorpion_read(int **buffer)
int cnt, len = 0;
int cpu = smp_processor_id();
- if (!pmnc_counters)
- return 0;
-
for (cnt = 0; cnt < pmnc_counters; cnt++) {
if (pmnc_enabled[cnt]) {
int value;
@@ -624,7 +626,6 @@ static int gator_events_scorpion_read(int **buffer)
}
}
- // update or discard
if (buffer)
*buffer = per_cpu(perfCnt, cpu);
@@ -633,25 +634,12 @@ static int gator_events_scorpion_read(int **buffer)
static struct gator_interface gator_events_scorpion_interface = {
.create_files = gator_events_scorpion_create_files,
- .start = gator_events_scorpion_start,
.stop = gator_events_scorpion_stop,
.online = gator_events_scorpion_online,
.offline = gator_events_scorpion_offline,
.read = gator_events_scorpion_read,
};
-
-static void scorpion_clear_pmuregs(void)
-{
- scorpion_write_lpm0(0);
- scorpion_write_lpm1(0);
- scorpion_write_lpm2(0);
- scorpion_write_l2lpm(0);
- scorpion_pre_vlpm();
- scorpion_write_vlpm(0);
- scorpion_post_vlpm();
-}
-
int gator_events_scorpion_init(void)
{
unsigned int cnt;
@@ -674,12 +662,17 @@ int gator_events_scorpion_init(void)
for (cnt = CCNT; cnt < CNTMAX; cnt++) {
pmnc_enabled[cnt] = 0;
pmnc_event[cnt] = 0;
- pmnc_count[cnt] = 0;
pmnc_key[cnt] = gator_events_get_key();
}
- scorpion_clear_pmuregs();
-
return gator_events_install(&gator_events_scorpion_interface);
}
+
gator_events_init(gator_events_scorpion_init);
+
+#else
+int gator_events_scorpion_init(void)
+{
+ return -1;
+}
+#endif
diff --git a/driver/gator_hrtimer_gator.c b/driver/gator_hrtimer_gator.c
new file mode 100644
index 0000000..5896b3c
--- /dev/null
+++ b/driver/gator_hrtimer_gator.c
@@ -0,0 +1,76 @@
+/**
+ * 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.
+ *
+ */
+
+// gator_hrtimer_perf.c is used if perf is supported
+// update, gator_hrtimer_gator.c always used until issues resolved with perf hrtimers
+#if 1
+
+void (*callback)(void);
+DEFINE_PER_CPU(struct hrtimer, percpu_hrtimer);
+static ktime_t profiling_interval;
+static void gator_hrtimer_online(int cpu);
+static void gator_hrtimer_offline(int cpu);
+
+static enum hrtimer_restart gator_hrtimer_notify(struct hrtimer *hrtimer)
+{
+ hrtimer_forward_now(hrtimer, profiling_interval);
+ (*callback)();
+ return HRTIMER_RESTART;
+}
+
+static void gator_hrtimer_switch_cpus_online(void *unused)
+{
+ gator_hrtimer_online(smp_processor_id());
+}
+
+static void gator_hrtimer_online(int cpu)
+{
+ struct hrtimer *hrtimer = &per_cpu(percpu_hrtimer, cpu);
+ if (cpu != smp_processor_id()) {
+ smp_call_function_single(cpu, gator_hrtimer_switch_cpus_online, NULL, 1);
+ return;
+ }
+
+ hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ hrtimer->function = gator_hrtimer_notify;
+ hrtimer_start(hrtimer, profiling_interval, HRTIMER_MODE_REL_PINNED);
+}
+
+static void gator_hrtimer_switch_cpus_offline(void *unused)
+{
+ gator_hrtimer_offline(smp_processor_id());
+}
+
+static void gator_hrtimer_offline(int cpu)
+{
+ struct hrtimer *hrtimer = &per_cpu(percpu_hrtimer, cpu);
+ if (cpu != smp_processor_id()) {
+ smp_call_function_single(cpu, gator_hrtimer_switch_cpus_offline, NULL, 1);
+ return;
+ }
+
+ hrtimer_cancel(hrtimer);
+}
+
+static int gator_hrtimer_init(int interval, void (*func)(void))
+{
+ (callback) = (func);
+
+ // calculate profiling interval
+ profiling_interval = ns_to_ktime(1000000000UL / interval);
+
+ return 0;
+}
+
+static void gator_hrtimer_shutdown(void)
+{
+ /* empty */
+}
+
+#endif
diff --git a/driver/gator_hrtimer_perf.c b/driver/gator_hrtimer_perf.c
new file mode 100644
index 0000000..7c0333f
--- /dev/null
+++ b/driver/gator_hrtimer_perf.c
@@ -0,0 +1,113 @@
+/**
+ * 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.
+ *
+ */
+
+// gator_hrtimer_gator.c is used if perf is not supported
+// update, gator_hrtimer_gator.c always used until issues resolved with perf hrtimers
+#if 0
+
+// Note: perf Cortex support added in 2.6.35 and PERF_COUNT_SW_CPU_CLOCK/hrtimer broken on 2.6.35 and 2.6.36
+// not relevant as this code is not active until 3.0.0, but wanted to document the issue
+
+void (*callback)(void);
+static int profiling_interval;
+static DEFINE_PER_CPU(struct perf_event *, perf_hrtimer);
+static DEFINE_PER_CPU(struct perf_event_attr *, perf_hrtimer_attr);
+
+static void gator_hrtimer_shutdown(void);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
+static void hrtimer_overflow_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs)
+#else
+static void hrtimer_overflow_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
+#endif
+{
+ (*callback)();
+}
+
+static int gator_online_single_hrtimer(int cpu)
+{
+ if (per_cpu(perf_hrtimer, cpu) != 0 || per_cpu(perf_hrtimer_attr, cpu) == 0)
+ return 0;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
+ per_cpu(perf_hrtimer, cpu) = perf_event_create_kernel_counter(per_cpu(perf_hrtimer_attr, cpu), cpu, 0, hrtimer_overflow_handler);
+#else
+ per_cpu(perf_hrtimer, cpu) = perf_event_create_kernel_counter(per_cpu(perf_hrtimer_attr, cpu), cpu, 0, hrtimer_overflow_handler, 0);
+#endif
+ if (IS_ERR(per_cpu(perf_hrtimer, cpu))) {
+ per_cpu(perf_hrtimer, cpu) = NULL;
+ return -1;
+ }
+
+ if (per_cpu(perf_hrtimer, cpu)->state != PERF_EVENT_STATE_ACTIVE) {
+ perf_event_release_kernel(per_cpu(perf_hrtimer, cpu));
+ per_cpu(perf_hrtimer, cpu) = NULL;
+ return -1;
+ }
+
+ return 0;
+}
+
+static void gator_hrtimer_online(int cpu)
+{
+ if (gator_online_single_hrtimer(cpu) < 0) {
+ pr_debug("gator: unable to online the hrtimer on cpu%d\n", cpu);
+ }
+}
+
+static void gator_hrtimer_offline(int cpu)
+{
+ if (per_cpu(perf_hrtimer, cpu)) {
+ perf_event_release_kernel(per_cpu(perf_hrtimer, cpu));
+ per_cpu(perf_hrtimer, cpu) = NULL;
+ }
+}
+
+static int gator_hrtimer_init(int interval, void (*func)(void))
+{
+ u32 size = sizeof(struct perf_event_attr);
+ int cpu;
+
+ callback = func;
+
+ // calculate profiling interval
+ profiling_interval = 1000000000 / interval;
+
+ for_each_present_cpu(cpu) {
+ per_cpu(perf_hrtimer, cpu) = 0;
+ per_cpu(perf_hrtimer_attr, cpu) = kmalloc(size, GFP_KERNEL);
+ if (per_cpu(perf_hrtimer_attr, cpu) == 0) {
+ gator_hrtimer_shutdown();
+ return -1;
+ }
+
+ memset(per_cpu(perf_hrtimer_attr, cpu), 0, size);
+ per_cpu(perf_hrtimer_attr, cpu)->type = PERF_TYPE_SOFTWARE;
+ per_cpu(perf_hrtimer_attr, cpu)->size = size;
+ per_cpu(perf_hrtimer_attr, cpu)->config = PERF_COUNT_SW_CPU_CLOCK;
+ per_cpu(perf_hrtimer_attr, cpu)->sample_period = profiling_interval;
+ per_cpu(perf_hrtimer_attr, cpu)->pinned = 1;
+ }
+
+ return 0;
+}
+
+static void gator_hrtimer_shutdown(void)
+{
+ int cpu;
+
+ for_each_present_cpu(cpu) {
+ if (per_cpu(perf_hrtimer_attr, cpu)) {
+ kfree(per_cpu(perf_hrtimer_attr, cpu));
+ per_cpu(perf_hrtimer_attr, cpu) = NULL;
+ }
+ }
+}
+
+#endif
diff --git a/driver/gator_main.c b/driver/gator_main.c
index 36e951b..fff2d19 100644
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -7,7 +7,7 @@
*
*/
-static unsigned long gator_protocol_version = 7;
+static unsigned long gator_protocol_version = 8;
#include <linux/slab.h>
#include <linux/cpu.h>
@@ -18,16 +18,20 @@ static unsigned long gator_protocol_version = 7;
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/suspend.h>
+#include <linux/module.h>
+#include <linux/perf_event.h>
#include <asm/stacktrace.h>
#include <asm/uaccess.h>
#include "gator.h"
#include "gator_events.h"
-#ifndef CONFIG_GENERIC_TRACER
-#ifndef CONFIG_TRACING
-#error gator requires the kernel to have CONFIG_GENERIC_TRACER or CONFIG_TRACING defined
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+#error kernels prior to 2.6.32 are not supported
#endif
+
+#if !defined(CONFIG_GENERIC_TRACER) && !defined(CONFIG_TRACING)
+#error gator requires the kernel to have CONFIG_GENERIC_TRACER or CONFIG_TRACING defined
#endif
#ifndef CONFIG_PROFILING
@@ -38,16 +42,20 @@ static unsigned long gator_protocol_version = 7;
#error gator requires the kernel to have CONFIG_HIGH_RES_TIMERS defined
#endif
-#if defined (__arm__)
-#ifdef CONFIG_SMP
-#ifndef CONFIG_LOCAL_TIMERS
+#if defined(__arm__) && defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
#error gator requires the kernel to have CONFIG_LOCAL_TIMERS defined on SMP systems
#endif
+
+#if (GATOR_PERF_SUPPORT) && (!(GATOR_PERF_PMU_SUPPORT))
+#ifndef CONFIG_PERF_EVENTS
+#warning gator requires the kernel to have CONFIG_PERF_EVENTS defined to support pmu hardware counters
+#elif !defined CONFIG_HW_PERF_EVENTS
+#warning gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters
#endif
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
-#error kernels prior to 2.6.32 are not supported
+#if (!(GATOR_CPU_FREQ_SUPPORT))
+#warning gator requires kernel version 2.6.38 or greater and CONFIG_CPU_FREQ defined in order to enable the CPU Freq timeline chart
#endif
/******************************************************************************
@@ -69,8 +77,11 @@ static unsigned long gator_protocol_version = 7;
#define MESSAGE_END_BACKTRACE 7
#define MESSAGE_SCHEDULER_TRACE 9
#define MESSAGE_PID_NAME 11
+#define MESSAGE_GPU_TRACE 13
+#define MESSAGE_OVERFLOW 127
-#define LINUX_PMU_SUPPORT LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) && defined(CONFIG_CPU_HAS_PMU)
+#define MAXSIZE_PACK32 5
+#define MAXSIZE_PACK64 9
#if defined(__arm__)
#define PC_REG regs->ARM_pc
@@ -94,27 +105,16 @@ static unsigned long gator_streaming;
static DEFINE_MUTEX(start_mutex);
static DEFINE_MUTEX(gator_buffer_mutex);
-unsigned long gator_net_traffic;
bool event_based_sampling;
-#define COMMIT_SIZE 128
-#define COMMIT_MASK (COMMIT_SIZE-1)
-static DEFINE_SPINLOCK(timer_commit_lock);
-static int *gator_commit[NUM_GATOR_BUFS];
-static int gator_commit_read[NUM_GATOR_BUFS];
-static int gator_commit_write[NUM_GATOR_BUFS];
-
static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
-static DEFINE_PER_CPU(int, gator_first_time);
-#if LINUX_PMU_SUPPORT
-static void event_buffer_check(int cpu);
-static DEFINE_SPINLOCK(event_commit_lock);
-#endif
+static void buffer_check(int cpu, int buftype);
/******************************************************************************
* Prototypes
******************************************************************************/
+static bool buffer_check_space(int cpu, int buftype, int bytes);
static void gator_buffer_write_packed_int(int cpu, int buftype, unsigned int x);
static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long long x);
static void gator_buffer_write_string(int cpu, int buftype, char *x);
@@ -124,15 +124,28 @@ static void gator_add_trace(int cpu, int buftype, unsigned int address);
static void gator_add_sample(int cpu, int buftype, struct pt_regs * const regs);
static uint64_t gator_get_time(void);
+static uint32_t gator_buffer_size[NUM_GATOR_BUFS];
+static uint32_t gator_buffer_mask[NUM_GATOR_BUFS];
+static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_read);
+static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_write);
+static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_commit);
+static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], buffer_space_available);
+static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer);
+static DEFINE_PER_CPU(uint64_t, emit_overflow);
+
/******************************************************************************
* Application Includes
******************************************************************************/
+#include "gator_hrtimer_perf.c"
+#include "gator_hrtimer_gator.c"
#include "gator_cookies.c"
#include "gator_trace_sched.c"
+#include "gator_trace_gpu.c"
#include "gator_backtrace.c"
#include "gator_annotate.c"
#include "gator_fs.c"
#include "gator_ebs.c"
+#include "gator_pack.c"
/******************************************************************************
* Misc
@@ -149,37 +162,55 @@ u32 gator_cpuid(void)
/******************************************************************************
* Commit interface
******************************************************************************/
-static int buffer_commit_ready(int buftype)
+static bool buffer_commit_ready(int* cpu, int* buftype)
{
- return gator_commit_read[buftype] != gator_commit_write[buftype];
-}
-
-static void buffer_commit_read(int *cpu, int buftype, int *readval, int *writeval)
-{
- int read = gator_commit_read[buftype];
- *cpu = gator_commit[buftype][read+0];
- *readval = gator_commit[buftype][read+1];
- *writeval = gator_commit[buftype][read+2];
- gator_commit_read[buftype] = (read + 4) & COMMIT_MASK;
-}
-
-static void buffer_commit_write(int cpu, int buftype, int readval, int writeval) {
- int write = gator_commit_write[buftype];
- gator_commit[buftype][write+0] = cpu;
- gator_commit[buftype][write+1] = readval;
- gator_commit[buftype][write+2] = writeval;
- gator_commit_write[buftype] = (write + 4) & COMMIT_MASK;
+ int cpu_x, x;
+ for_each_present_cpu(cpu_x) {
+ for (x = 0; x < NUM_GATOR_BUFS; x++)
+ if (per_cpu(gator_buffer_commit, cpu_x)[x] != per_cpu(gator_buffer_read, cpu_x)[x]) {
+ *cpu = cpu_x;
+ *buftype = x;
+ return true;
+ }
+ }
+ return false;
}
/******************************************************************************
* Buffer management
******************************************************************************/
-static uint32_t gator_buffer_size[NUM_GATOR_BUFS];
-static uint32_t gator_buffer_mask[NUM_GATOR_BUFS];
-static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_read);
-static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_write);
-static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer);
-#include "gator_pack.c"
+static bool buffer_check_space(int cpu, int buftype, int bytes)
+{
+ int remaining, filled;
+
+ filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_read, cpu)[buftype];
+ if (filled < 0) {
+ filled += gator_buffer_size[buftype];
+ }
+
+ remaining = gator_buffer_size[buftype] - filled;
+
+ if (per_cpu(buffer_space_available, cpu)[buftype]) {
+ // Give some extra room; also allows space to insert the overflow error packet
+ remaining -= 200;
+ } else {
+ // Hysteresis, prevents multiple overflow messages
+ remaining -= 2000;
+ }
+
+ if (remaining < bytes) {
+ if (per_cpu(buffer_space_available, cpu)[buftype] == true) {
+ // overflow packet to be emitted at a later time, as we may be in the middle of writing a message, e.g. counters
+ per_cpu(emit_overflow, cpu) = gator_get_time();
+ pr_err("overflow: remaining = %d\n", gator_buffer_size[buftype] - filled);
+ }
+ per_cpu(buffer_space_available, cpu)[buftype] = false;
+ } else {
+ per_cpu(buffer_space_available, cpu)[buftype] = true;
+ }
+
+ return per_cpu(buffer_space_available, cpu)[buftype];
+}
static void gator_buffer_write_bytes(int cpu, int buftype, char *x, int len)
{
@@ -218,42 +249,24 @@ static void gator_buffer_header(int cpu, int buftype)
gator_buffer_write_packed_int(cpu, buftype, cpu);
}
-static void gator_buffer_commit(int cpu, int buftype)
+static void gator_commit_buffer(int cpu, int buftype)
{
- buffer_commit_write(cpu, buftype, per_cpu(gator_buffer_read, cpu)[buftype], per_cpu(gator_buffer_write, cpu)[buftype]);
- per_cpu(gator_buffer_read, cpu)[buftype] = per_cpu(gator_buffer_write, cpu)[buftype];
+ per_cpu(gator_buffer_commit, cpu)[buftype] = per_cpu(gator_buffer_write, cpu)[buftype];
gator_buffer_header(cpu, buftype);
wake_up(&gator_buffer_wait);
}
-static void timer_buffer_check(int cpu)
+static void buffer_check(int cpu, int buftype)
{
- int available = per_cpu(gator_buffer_write, cpu)[TIMER_BUF] - per_cpu(gator_buffer_read, cpu)[TIMER_BUF];
- if (available < 0) {
- available += gator_buffer_size[TIMER_BUF];
+ int filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_commit, cpu)[buftype];
+ if (filled < 0) {
+ filled += gator_buffer_size[buftype];
}
- if (available >= ((gator_buffer_size[TIMER_BUF] * 3) / 4)) {
- spin_lock(&timer_commit_lock);
- gator_buffer_commit(cpu, TIMER_BUF);
- spin_unlock(&timer_commit_lock);
+ if (filled >= ((gator_buffer_size[buftype] * 3) / 4)) {
+ gator_commit_buffer(cpu, buftype);
}
}
-#if LINUX_PMU_SUPPORT
-static void event_buffer_check(int cpu)
-{
- int available = per_cpu(gator_buffer_write, cpu)[EVENT_BUF] - per_cpu(gator_buffer_read, cpu)[EVENT_BUF];
- if (available < 0) {
- available += gator_buffer_size[EVENT_BUF];
- }
- if (available >= ((gator_buffer_size[EVENT_BUF] * 3) / 4)) {
- spin_lock(&event_commit_lock);
- gator_buffer_commit(cpu, EVENT_BUF);
- spin_unlock(&event_commit_lock);
- }
-}
-#endif
-
static void gator_add_trace(int cpu, int buftype, unsigned int address)
{
off_t offset = 0;
@@ -309,21 +322,9 @@ static void gator_timer_interrupt(void)
long long *buffer64;
struct gator_interface *gi;
- // check full backtrace has enough space, otherwise may
- // have breaks between samples in the same callstack
- if (per_cpu(gator_first_time, cpu)) {
- per_cpu(gator_first_time, cpu) = 0;
-
- list_for_each_entry(gi, &gator_events, list)
- if (gi->read)
- gi->read(NULL);
-
- return;
- }
-
- // Output scheduler
+ // Output scheduler trace
len = gator_trace_sched_read(&buffer64);
- if (len > 0) {
+ if (len > 0 && buffer_check_space(cpu, buftype, len * MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
gator_buffer_write_packed_int(cpu, buftype, MESSAGE_SCHEDULER_TRACE);
gator_buffer_write_packed_int(cpu, buftype, len);
for (i = 0; i < len; i++) {
@@ -331,105 +332,189 @@ static void gator_timer_interrupt(void)
}
}
+ // Output GPU trace
+ len = gator_trace_gpu_read(&buffer64);
+ if (len > 0 && buffer_check_space(cpu, buftype, len * MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, buftype, MESSAGE_GPU_TRACE);
+ gator_buffer_write_packed_int(cpu, buftype, len);
+ for (i = 0; i < len; i++) {
+ gator_buffer_write_packed_int64(cpu, buftype, buffer64[i]);
+ }
+ }
+
// Output counters
- gator_buffer_write_packed_int(cpu, buftype, MESSAGE_COUNTERS);
- gator_buffer_write_packed_int64(cpu, buftype, gator_get_time());
- list_for_each_entry(gi, &gator_events, list) {
- if (gi->read) {
- len = gi->read(&buffer);
- if (len > 0) {
- gator_buffer_write_packed_int(cpu, buftype, len);
- for (i = 0; i < len; i++) {
- gator_buffer_write_packed_int(cpu, buftype, buffer[i]);
+ if (buffer_check_space(cpu, buftype, MAXSIZE_PACK32 * 2 + MAXSIZE_PACK64)) {
+ gator_buffer_write_packed_int(cpu, buftype, MESSAGE_COUNTERS);
+ gator_buffer_write_packed_int64(cpu, buftype, gator_get_time());
+ list_for_each_entry(gi, &gator_events, list) {
+ if (gi->read) {
+ len = gi->read(&buffer);
+ if (len > 0 && buffer_check_space(cpu, buftype, len * MAXSIZE_PACK32 + MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, buftype, len);
+ for (i = 0; i < len; i++) {
+ gator_buffer_write_packed_int(cpu, buftype, buffer[i]);
+ }
}
- }
- } else if (gi->read64) {
- len = gi->read64(&buffer64);
- if (len > 0) {
- gator_buffer_write_packed_int(cpu, buftype, len);
- for (i = 0; i < len; i++) {
- gator_buffer_write_packed_int64(cpu, buftype, buffer64[i]);
+ } else if (gi->read64) {
+ len = gi->read64(&buffer64);
+ if (len > 0 && buffer_check_space(cpu, buftype, len * MAXSIZE_PACK64 + MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, buftype, len);
+ for (i = 0; i < len; i++) {
+ gator_buffer_write_packed_int64(cpu, buftype, buffer64[i]);
+ }
}
}
}
+ gator_buffer_write_packed_int(cpu, buftype, 0);
}
- gator_buffer_write_packed_int(cpu, buftype, 0);
// Output backtrace
- if (!event_based_sampling) {
+ if (!event_based_sampling && buffer_check_space(cpu, buftype, gator_backtrace_depth * 2 * MAXSIZE_PACK32))
gator_add_sample(cpu, buftype, regs);
+
+ // Overflow message
+ if (per_cpu(emit_overflow, cpu)) {
+ gator_buffer_write_packed_int(cpu, buftype, MESSAGE_OVERFLOW);
+ gator_buffer_write_packed_int64(cpu, buftype, per_cpu(emit_overflow, cpu));
+ per_cpu(emit_overflow, cpu) = 0;
}
// Check and commit; generally, commit is set to occur once per second
- timer_buffer_check(cpu);
+ buffer_check(cpu, buftype);
}
-DEFINE_PER_CPU(struct hrtimer, percpu_hrtimer);
DEFINE_PER_CPU(int, hrtimer_is_active);
static int hrtimer_running;
-static ktime_t profiling_interval;
-static enum hrtimer_restart gator_hrtimer_notify(struct hrtimer *hrtimer)
+// This function runs in interrupt context and on the appropriate core
+static void gator_timer_offline(void* unused)
{
- hrtimer_forward_now(hrtimer, profiling_interval);
- gator_timer_interrupt();
- return HRTIMER_RESTART;
-}
+ int i, len, cpu = smp_processor_id();
+ int* buffer;
+ long long* buffer64;
-static int gator_timer_init(void)
-{
- return 0;
-}
-
-static void __gator_timer_offline(void *unused)
-{
- int cpu = smp_processor_id();
if (per_cpu(hrtimer_is_active, cpu)) {
struct gator_interface *gi;
- struct hrtimer *hrtimer = &per_cpu(percpu_hrtimer, cpu);
- hrtimer_cancel(hrtimer);
+ gator_hrtimer_offline(cpu);
per_cpu(hrtimer_is_active, cpu) = 0;
- gator_buffer_commit(cpu, TIMER_BUF);
- if (event_based_sampling)
- gator_buffer_commit(cpu, EVENT_BUF);
-
- // offline any events
- list_for_each_entry(gi, &gator_events, list)
- if (gi->offline)
- gi->offline();
+
+ // Output scheduler trace
+ len = gator_trace_sched_offline(&buffer64);
+ if (len > 0 && buffer_check_space(cpu, TIMER_BUF, len * MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, TIMER_BUF, MESSAGE_SCHEDULER_TRACE);
+ gator_buffer_write_packed_int(cpu, TIMER_BUF, len);
+ for (i = 0; i < len; i++) {
+ gator_buffer_write_packed_int64(cpu, TIMER_BUF, buffer64[i]);
+ }
+ }
+
+ // Output GPU trace
+ len = gator_trace_gpu_offline(&buffer64);
+ if (len > 0 && buffer_check_space(cpu, TIMER_BUF, len * MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, TIMER_BUF, MESSAGE_GPU_TRACE);
+ gator_buffer_write_packed_int(cpu, TIMER_BUF, len);
+ for (i = 0; i < len; i++) {
+ gator_buffer_write_packed_int64(cpu, TIMER_BUF, buffer64[i]);
+ }
+ }
+
+ // offline any events and output counters
+ gator_buffer_write_packed_int(cpu, TIMER_BUF, MESSAGE_COUNTERS);
+ gator_buffer_write_packed_int64(cpu, TIMER_BUF, gator_get_time());
+ list_for_each_entry(gi, &gator_events, list) {
+ if (gi->offline) {
+ len = gi->offline(&buffer);
+ if (len > 0 && buffer_check_space(cpu, TIMER_BUF, len * MAXSIZE_PACK32 + MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, TIMER_BUF, len);
+ for (i = 0; i < len; i++)
+ gator_buffer_write_packed_int(cpu, TIMER_BUF, buffer[i]);
+ }
+ }
+ }
+ gator_buffer_write_packed_int(cpu, TIMER_BUF, 0);
+
+ gator_commit_buffer(cpu, TIMER_BUF);
+ }
+
+ if (event_based_sampling) {
+ gator_commit_buffer(cpu, EVENT_BUF);
}
}
-static void gator_timer_offline(void)
+// This function runs in interrupt context and may be running on a core other than core 'cpu'
+static void gator_timer_offline_dispatch(int cpu)
{
+ struct gator_interface *gi;
+
+ list_for_each_entry(gi, &gator_events, list)
+ if (gi->offline_dispatch)
+ gi->offline_dispatch(cpu);
+
+ gator_event_sampling_offline_dispatch(cpu);
+}
+
+static void gator_timer_stop(void)
+{
+ int cpu;
+
if (hrtimer_running) {
- hrtimer_running = 0;
+ on_each_cpu(gator_timer_offline, NULL, 1);
+ for_each_online_cpu(cpu) {
+ gator_timer_offline_dispatch(cpu);
+ }
- on_each_cpu(__gator_timer_offline, NULL, 1);
+ hrtimer_running = 0;
+ gator_hrtimer_shutdown();
}
}
-static void __gator_timer_online(void *unused)
+// This function runs in interrupt context and on the appropriate core
+static void gator_timer_online(void* unused)
{
- int cpu = smp_processor_id();
+ int i, len, cpu = smp_processor_id();
+ int* buffer;
+
if (!per_cpu(hrtimer_is_active, cpu)) {
struct gator_interface *gi;
- struct hrtimer *hrtimer = &per_cpu(percpu_hrtimer, cpu);
- hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- hrtimer->function = gator_hrtimer_notify;
- hrtimer_start(hrtimer, profiling_interval, HRTIMER_MODE_REL_PINNED);
- per_cpu(gator_first_time, cpu) = 1;
- per_cpu(hrtimer_is_active, cpu) = 1;
- // online any events
- list_for_each_entry(gi, &gator_events, list)
- if (gi->online)
- gi->online();
+ // online any events and output counters
+ gator_buffer_write_packed_int(cpu, TIMER_BUF, MESSAGE_COUNTERS);
+ gator_buffer_write_packed_int64(cpu, TIMER_BUF, gator_get_time());
+ list_for_each_entry(gi, &gator_events, list) {
+ if (gi->online) {
+ len = gi->online(&buffer);
+ if (len > 0 && buffer_check_space(cpu, TIMER_BUF, len * MAXSIZE_PACK32 + MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, TIMER_BUF, len);
+ for (i = 0; i < len; i++)
+ gator_buffer_write_packed_int(cpu, TIMER_BUF, buffer[i]);
+ }
+ }
+ }
+ gator_buffer_write_packed_int(cpu, TIMER_BUF, 0);
+
+ gator_event_sampling_online();
+
+ gator_hrtimer_online(cpu);
+ per_cpu(hrtimer_is_active, cpu) = 1;
}
}
-int gator_timer_online(unsigned long setup)
+// This function runs in interrupt context and may be running on a core other than core 'cpu'
+static void gator_timer_online_dispatch(int cpu)
+{
+ struct gator_interface *gi;
+
+ list_for_each_entry(gi, &gator_events, list)
+ if (gi->online_dispatch)
+ gi->online_dispatch(cpu);
+
+ gator_event_sampling_online_dispatch(cpu);
+}
+
+int gator_timer_start(unsigned long setup)
{
+ int cpu;
+
if (!setup) {
pr_err("gator: cannot start due to a system tick value of zero\n");
return -1;
@@ -440,11 +525,13 @@ int gator_timer_online(unsigned long setup)
hrtimer_running = 1;
- // calculate profiling interval
- profiling_interval = ns_to_ktime(1000000000UL / setup);
+ if (gator_hrtimer_init(setup, gator_timer_interrupt) == -1)
+ return -1;
- // timer interrupt
- on_each_cpu(__gator_timer_online, NULL, 1);
+ for_each_online_cpu(cpu) {
+ gator_timer_online_dispatch(cpu);
+ }
+ on_each_cpu(gator_timer_online, NULL, 1);
return 0;
}
@@ -461,7 +548,7 @@ static uint64_t gator_get_time(void)
}
/******************************************************************************
- * cpu online and pm notifiers
+ * cpu hotplug and pm notifiers
******************************************************************************/
static int __cpuinit gator_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
{
@@ -470,11 +557,13 @@ static int __cpuinit gator_cpu_notify(struct notifier_block *self, unsigned long
switch (action) {
case CPU_DOWN_PREPARE:
case CPU_DOWN_PREPARE_FROZEN:
- smp_call_function_single(cpu, __gator_timer_offline, NULL, 1);
+ smp_call_function_single(cpu, gator_timer_offline, NULL, 1);
+ gator_timer_offline_dispatch(cpu);
break;
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
- smp_call_function_single(cpu, __gator_timer_online, NULL, 1);
+ gator_timer_online_dispatch(cpu);
+ smp_call_function_single(cpu, gator_timer_online, NULL, 1);
break;
}
@@ -489,17 +578,24 @@ static struct notifier_block __refdata gator_cpu_notifier = {
// Registered linux events are not disabled, so their counters will continue to collect
static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy)
{
+ int cpu;
+
switch (event) {
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
unregister_hotcpu_notifier(&gator_cpu_notifier);
unregister_scheduler_tracepoints();
- on_each_cpu(trace_sched_insert_idle, NULL, 1);
- on_each_cpu(__gator_timer_offline, NULL, 1);
+ on_each_cpu(gator_timer_offline, NULL, 1);
+ for_each_online_cpu(cpu) {
+ gator_timer_offline_dispatch(cpu);
+ }
break;
case PM_POST_HIBERNATION:
case PM_POST_SUSPEND:
- on_each_cpu(__gator_timer_online, NULL, 1);
+ for_each_online_cpu(cpu) {
+ gator_timer_online_dispatch(cpu);
+ }
+ on_each_cpu(gator_timer_online, NULL, 1);
register_scheduler_tracepoints();
register_hotcpu_notifier(&gator_cpu_notifier);
break;
@@ -548,10 +644,6 @@ static int gator_init(void)
{
int i;
- if (gator_timer_init())
- return -1;
- if (gator_trace_sched_init())
- return -1;
if (gator_annotate_init())
return -1;
@@ -573,8 +665,7 @@ static int gator_start(void)
struct list_head *ptr = gi->list.prev;
while (ptr != &gator_events) {
- gi = list_entry(ptr, struct gator_interface,
- list);
+ gi = list_entry(ptr, struct gator_interface, list);
if (gi->stop)
gi->stop();
@@ -585,16 +676,18 @@ static int gator_start(void)
}
}
- // cookies shall be initialized before trace_sched_start() and gator_timer_online()
+ // cookies shall be initialized before trace_sched_start() and gator_timer_start()
if (cookies_initialize())
goto cookies_failure;
if (gator_annotate_start())
goto annotate_failure;
if (gator_trace_sched_start())
goto sched_failure;
+ if (gator_trace_gpu_start())
+ goto gpu_failure;
if (gator_event_sampling_start())
goto event_sampling_failure;
- if (gator_timer_online(gator_timer_count))
+ if (gator_timer_start(gator_timer_count))
goto timer_failure;
if (gator_notifier_start())
goto notifier_failure;
@@ -602,10 +695,12 @@ static int gator_start(void)
return 0;
notifier_failure:
- gator_timer_offline();
+ gator_timer_stop();
timer_failure:
gator_event_sampling_stop();
event_sampling_failure:
+ gator_trace_gpu_stop();
+gpu_failure:
gator_trace_sched_stop();
sched_failure:
gator_annotate_stop();
@@ -632,11 +727,12 @@ static void gator_stop(void)
gator_annotate_stop();
gator_trace_sched_stop();
+ gator_trace_gpu_stop();
gator_event_sampling_stop();
// stop all interrupt callback reads before tearing down other interfaces
- gator_notifier_stop(); // should be called before gator_timer_offline to avoid re-enabling the hrtimer after it has been offlined
- gator_timer_offline();
+ gator_notifier_stop(); // should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined
+ gator_timer_stop();
}
static void gator_exit(void)
@@ -667,18 +763,8 @@ static int gator_op_setup(void)
gator_buffer_size[EVENT_BUF] = EVENT_BUFFER_SIZE_DEFAULT;
gator_buffer_mask[EVENT_BUF] = gator_buffer_size[EVENT_BUF] - 1;
- gator_net_traffic = 0;
-
- // Initialize per buffer variables
+ // Initialize percpu per buffer variables
for (i = 0; i < NUM_GATOR_BUFS; i++) {
- gator_commit_read[i] = gator_commit_write[i] = 0;
- gator_commit[i] = vmalloc(COMMIT_SIZE * sizeof(int));
- if (!gator_commit[i]) {
- err = -ENOMEM;
- goto setup_error;
- }
-
- // Initialize percpu per buffer variables
for_each_present_cpu(cpu) {
per_cpu(gator_buffer, cpu)[i] = vmalloc(gator_buffer_size[i]);
if (!per_cpu(gator_buffer, cpu)[i]) {
@@ -688,6 +774,9 @@ static int gator_op_setup(void)
per_cpu(gator_buffer_read, cpu)[i] = 0;
per_cpu(gator_buffer_write, cpu)[i] = 0;
+ per_cpu(gator_buffer_commit, cpu)[i] = 0;
+ per_cpu(buffer_space_available, cpu)[i] = true;
+ per_cpu(emit_overflow, cpu) = 0;
gator_buffer_header(cpu, i);
}
}
@@ -742,11 +831,6 @@ static void gator_shutdown(void)
gator_annotate_shutdown();
- for (i = 0; i < NUM_GATOR_BUFS; i++) {
- vfree(gator_commit[i]);
- gator_commit[i] = NULL;
- }
-
for_each_present_cpu(cpu) {
mutex_lock(&gator_buffer_mutex);
for (i = 0; i < NUM_GATOR_BUFS; i++) {
@@ -754,6 +838,9 @@ static void gator_shutdown(void)
per_cpu(gator_buffer, cpu)[i] = NULL;
per_cpu(gator_buffer_read, cpu)[i] = 0;
per_cpu(gator_buffer_write, cpu)[i] = 0;
+ per_cpu(gator_buffer_commit, cpu)[i] = 0;
+ per_cpu(buffer_space_available, cpu)[i] = true;
+ per_cpu(emit_overflow, cpu) = 0;
}
mutex_unlock(&gator_buffer_mutex);
}
@@ -845,10 +932,10 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf,
size_t count, loff_t *offset)
{
int retval = -EINVAL;
- int commit, length1, length2, read;
+ int commit = 0, length1, length2, read;
char *buffer1;
char *buffer2 = NULL;
- int cpu, i;
+ int cpu, buftype;
/* do not handle partial reads */
if (count != userspace_buffer_size || *offset)
@@ -856,7 +943,8 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf,
// sleep until the condition is true or a signal is received
// the condition is checked each time gator_buffer_wait is woken up
- wait_event_interruptible(gator_buffer_wait, buffer_commit_ready(TIMER_BUF) || buffer_commit_ready(EVENT_BUF) || gator_annotate_ready() || !gator_started);
+ buftype = cpu = -1;
+ wait_event_interruptible(gator_buffer_wait, buffer_commit_ready(&cpu, &buftype) || gator_annotate_ready() || !gator_started);
if (signal_pending(current))
return -EINTR;
@@ -866,28 +954,22 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf,
mutex_lock(&gator_buffer_mutex);
- i = -1;
- if (buffer_commit_ready(TIMER_BUF)) {
- i = TIMER_BUF;
- } else if (buffer_commit_ready(EVENT_BUF)) {
- i = EVENT_BUF;
- }
-
- if (i != -1) {
- buffer_commit_read(&cpu, i, &read, &commit);
+ if (buftype != -1 && cpu != -1) {
+ read = per_cpu(gator_buffer_read, cpu)[buftype];
+ commit = per_cpu(gator_buffer_commit, cpu)[buftype];
/* May happen if the buffer is freed during pending reads. */
- if (!per_cpu(gator_buffer, cpu)[i]) {
+ if (!per_cpu(gator_buffer, cpu)[buftype]) {
retval = -EFAULT;
goto out;
}
/* determine the size of two halves */
length1 = commit - read;
- buffer1 = &(per_cpu(gator_buffer, cpu)[i][read]);
- buffer2 = &(per_cpu(gator_buffer, cpu)[i][0]);
+ buffer1 = &(per_cpu(gator_buffer, cpu)[buftype][read]);
+ buffer2 = &(per_cpu(gator_buffer, cpu)[buftype][0]);
if (length1 < 0) {
- length1 = gator_buffer_size[i] - read;
+ length1 = gator_buffer_size[buftype] - read;
length2 = commit;
}
} else if (gator_annotate_ready()) {
@@ -913,15 +995,15 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf,
}
}
+ if (buftype != -1 && cpu != -1)
+ per_cpu(gator_buffer_read, cpu)[buftype] = commit;
+
retval = length1 + length2;
/* kick just in case we've lost an SMP event */
wake_up(&gator_buffer_wait);
out:
- // only adjust network stats if in streaming mode
- if (gator_streaming)
- gator_net_traffic += retval;
mutex_unlock(&gator_buffer_mutex);
return retval;
}
diff --git a/driver/gator_pack.c b/driver/gator_pack.c
index fbab220..985e960 100644
--- a/driver/gator_pack.c
+++ b/driver/gator_pack.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
diff --git a/driver/gator_trace_gpu.c b/driver/gator_trace_gpu.c
new file mode 100644
index 0000000..bc63995
--- /dev/null
+++ b/driver/gator_trace_gpu.c
@@ -0,0 +1,250 @@
+/**
+ * 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 "gator.h"
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/math64.h>
+
+#ifdef MALI_SUPPORT
+#include "linux/mali_linux_trace.h"
+#endif
+#include "gator_trace_gpu.h"
+
+#define ACTIVITY_START 1
+#define ACTIVITY_STOP 2
+
+/* Note whether tracepoints have been registered */
+static int mali_trace_registered;
+static int gpu_trace_registered;
+
+#define GPU_OVERFLOW -1
+#define GPU_START 1
+#define GPU_STOP 2
+
+#define GPU_UNIT_VP 1
+#define GPU_UNIT_FP 2
+
+#define TRACESIZE (8*1024)
+
+static DEFINE_PER_CPU(uint64_t *[2], theGpuTraceBuf);
+static DEFINE_PER_CPU(int, theGpuTraceSel);
+static DEFINE_PER_CPU(int, theGpuTracePos);
+static DEFINE_PER_CPU(int, theGpuTraceErr);
+
+int gator_trace_gpu_read(long long **buffer);
+
+static void probe_gpu_write(int type, int unit, int core, struct task_struct* task)
+{
+ int tracePos;
+ unsigned long flags;
+ uint64_t *traceBuf, time;
+ int pid, tgid;
+ int cpu = smp_processor_id();
+
+ if (!per_cpu(theGpuTraceBuf, cpu)[per_cpu(theGpuTraceSel, cpu)])
+ return;
+
+ if (task) {
+ tgid = (int)task->tgid;
+ pid = (int)task->pid;
+ } else {
+ tgid = pid = 0;
+ }
+
+ // disable interrupts to synchronize with gator_trace_gpu_read(); spinlocks not needed since percpu buffers are used
+ local_irq_save(flags);
+
+ time = gator_get_time();
+ tracePos = per_cpu(theGpuTracePos, cpu);
+ traceBuf = per_cpu(theGpuTraceBuf, cpu)[per_cpu(theGpuTraceSel, cpu)];
+
+ if (tracePos < (TRACESIZE - 100)) {
+ // capture
+ traceBuf[tracePos++] = type;
+ traceBuf[tracePos++] = time;
+ traceBuf[tracePos++] = unit;
+ traceBuf[tracePos++] = core;
+ traceBuf[tracePos++] = tgid;
+ traceBuf[tracePos++] = pid;
+ } else if (!per_cpu(theGpuTraceErr, cpu)) {
+ per_cpu(theGpuTraceErr, cpu) = 1;
+ traceBuf[tracePos++] = GPU_OVERFLOW;
+ traceBuf[tracePos++] = time;
+ traceBuf[tracePos++] = 0;
+ traceBuf[tracePos++] = 0;
+ traceBuf[tracePos++] = 0;
+ traceBuf[tracePos++] = 0;
+ pr_debug("gator: gpu trace overflow\n");
+ }
+ per_cpu(theGpuTracePos, cpu) = tracePos;
+ local_irq_restore(flags);
+}
+
+#ifdef MALI_SUPPORT
+
+enum components {
+ COMPONENT_VP0 = 1,
+ COMPONENT_FP0 = 5,
+ COMPONENT_FP1,
+ COMPONENT_FP2,
+ COMPONENT_FP3,
+ COMPONENT_FP4,
+ COMPONENT_FP5,
+ COMPONENT_FP6,
+ COMPONENT_FP7,
+};
+
+GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned int d2, unsigned int d3, unsigned int d4))
+{
+ unsigned int component, state;
+
+ // do as much work as possible before disabling interrupts
+ component = (event_id >> 16) & 0xF;
+ state = (event_id >> 24) & 0xF;
+
+ if ((component == COMPONENT_VP0) || (component >= COMPONENT_FP0 && component <= COMPONENT_FP7)) {
+ if (state == ACTIVITY_START || state == ACTIVITY_STOP) {
+ unsigned int type = (state == ACTIVITY_START) ? GPU_START : GPU_STOP;
+ unsigned int unit = (component < COMPONENT_FP0) ? GPU_UNIT_VP : GPU_UNIT_FP;
+ unsigned int core = (component < COMPONENT_FP0) ? component - COMPONENT_VP0 : component - COMPONENT_FP0;
+ struct task_struct* task = (state == ACTIVITY_START) ? (struct task_struct*)d2 : NULL;
+
+ probe_gpu_write(type, unit, core, task);
+ }
+ }
+}
+#endif
+
+GATOR_DEFINE_PROBE(gpu_activity_start, TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p))
+{
+ probe_gpu_write(GPU_START, gpu_unit, gpu_core, p);
+}
+
+GATOR_DEFINE_PROBE(gpu_activity_stop, TP_PROTO(int gpu_unit, int gpu_core))
+{
+ probe_gpu_write(GPU_STOP, gpu_unit, gpu_core, NULL);
+}
+
+int gator_trace_gpu_start(void)
+{
+ int cpu;
+
+ /*
+ * Returns 0 for installation failed
+ * Absence of gpu trace points is not an error
+ */
+
+ gpu_trace_registered = mali_trace_registered = 0;
+
+#ifdef MALI_SUPPORT
+ if (!GATOR_REGISTER_TRACE(mali_timeline_event)) {
+ mali_trace_registered = 1;
+ }
+#endif
+
+ if (!mali_trace_registered) {
+ if (GATOR_REGISTER_TRACE(gpu_activity_start)) {
+ return 0;
+ }
+ if (GATOR_REGISTER_TRACE(gpu_activity_stop)) {
+ GATOR_UNREGISTER_TRACE(gpu_activity_start);
+ return 0;
+ }
+ gpu_trace_registered = 1;
+ }
+
+ if (!gpu_trace_registered && !mali_trace_registered) {
+ return 0;
+ }
+
+ for_each_present_cpu(cpu) {
+ per_cpu(theGpuTraceSel, cpu) = 0;
+ per_cpu(theGpuTracePos, cpu) = 0;
+ per_cpu(theGpuTraceErr, cpu) = 0;
+ per_cpu(theGpuTraceBuf, cpu)[0] = kmalloc(TRACESIZE * sizeof(uint64_t), GFP_KERNEL);
+ per_cpu(theGpuTraceBuf, cpu)[1] = kmalloc(TRACESIZE * sizeof(uint64_t), GFP_KERNEL);
+ if (!per_cpu(theGpuTraceBuf, cpu)[0] || !per_cpu(theGpuTraceBuf, cpu)[1]) {
+#ifdef MALI_SUPPORT
+ if (mali_trace_registered) {
+ GATOR_UNREGISTER_TRACE(mali_timeline_event);
+ }
+#endif
+ if (gpu_trace_registered) {
+ GATOR_UNREGISTER_TRACE(gpu_activity_stop);
+ GATOR_UNREGISTER_TRACE(gpu_activity_start);
+ }
+
+ gpu_trace_registered = mali_trace_registered = 0;
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int gator_trace_gpu_offline(long long **buffer)
+{
+ return gator_trace_gpu_read(buffer);
+}
+
+void gator_trace_gpu_stop(void)
+{
+ int cpu;
+
+ if (gpu_trace_registered || mali_trace_registered) {
+ for_each_present_cpu(cpu) {
+ kfree(per_cpu(theGpuTraceBuf, cpu)[0]);
+ kfree(per_cpu(theGpuTraceBuf, cpu)[1]);
+ per_cpu(theGpuTraceBuf, cpu)[0] = NULL;
+ per_cpu(theGpuTraceBuf, cpu)[1] = NULL;
+ }
+
+#ifdef MALI_SUPPORT
+ if (mali_trace_registered) {
+ GATOR_UNREGISTER_TRACE(mali_timeline_event);
+ }
+#endif
+ if (gpu_trace_registered) {
+ GATOR_UNREGISTER_TRACE(gpu_activity_stop);
+ GATOR_UNREGISTER_TRACE(gpu_activity_start);
+ }
+
+ gpu_trace_registered = mali_trace_registered = 0;
+ }
+}
+
+int gator_trace_gpu_read(long long **buffer)
+{
+ int cpu = smp_processor_id();
+ unsigned long flags;
+ uint64_t *traceBuf;
+ int tracePos;
+
+ if (!per_cpu(theGpuTraceBuf, cpu)[per_cpu(theGpuTraceSel, cpu)])
+ return 0;
+
+ local_irq_save(flags);
+
+ traceBuf = per_cpu(theGpuTraceBuf, cpu)[per_cpu(theGpuTraceSel, cpu)];
+ tracePos = per_cpu(theGpuTracePos, cpu);
+
+ per_cpu(theGpuTraceSel, cpu) = !per_cpu(theGpuTraceSel, cpu);
+ per_cpu(theGpuTracePos, cpu) = 0;
+ per_cpu(theGpuTraceErr, cpu) = 0;
+
+ local_irq_restore(flags);
+
+ if (buffer)
+ *buffer = traceBuf;
+
+ return tracePos;
+}
diff --git a/driver/gator_trace_gpu.h b/driver/gator_trace_gpu.h
new file mode 100644
index 0000000..894289b
--- /dev/null
+++ b/driver/gator_trace_gpu.h
@@ -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.
+ */
+
+#undef TRACE_GPU
+#define TRACE_GPU gpu
+
+#if !defined(_TRACE_GPU_H)
+#define _TRACE_GPU_H
+
+#include <linux/tracepoint.h>
+
+/*
+ * UNIT - the GPU processor type
+ * 1 = Vertex Processor
+ * 2 = Fragment Processor
+ *
+ * CORE - the GPU processor core number
+ * this is not the CPU core number
+ */
+
+/*
+ * Tracepoint for calling GPU unit start activity on core
+ */
+TRACE_EVENT(gpu_activity_start,
+
+ TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p),
+
+ TP_ARGS(gpu_unit, gpu_core, p),
+
+ TP_STRUCT__entry(
+ __field( int, gpu_unit )
+ __field( int, gpu_core )
+ __array( char, comm, TASK_COMM_LEN )
+ __field( pid_t, pid )
+ ),
+
+ TP_fast_assign(
+ __entry->gpu_unit = gpu_unit;
+ __entry->gpu_core = gpu_core;
+ memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
+ __entry->pid = p->pid;
+ ),
+
+ TP_printk("unit=%d core=%d comm=%s pid=%d",
+ __entry->gpu_unit, __entry->gpu_core, __entry->comm, __entry->pid)
+);
+
+/*
+ * Tracepoint for calling GPU unit stop activity on core
+ */
+TRACE_EVENT(gpu_activity_stop,
+
+ TP_PROTO(int gpu_unit, int gpu_core),
+
+ TP_ARGS(gpu_unit, gpu_core),
+
+ TP_STRUCT__entry(
+ __field( int, gpu_unit )
+ __field( int, gpu_core )
+ ),
+
+ TP_fast_assign(
+ __entry->gpu_unit = gpu_unit;
+ __entry->gpu_core = gpu_core;
+ ),
+
+ TP_printk("unit=%d core=%d",
+ __entry->gpu_unit, __entry->gpu_core)
+);
+
+#endif /* _TRACE_GPU_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/driver/gator_trace_sched.c b/driver/gator_trace_sched.c
index 0225bfb..dafacb7 100644
--- a/driver/gator_trace_sched.c
+++ b/driver/gator_trace_sched.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ * 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
@@ -30,6 +30,8 @@ enum {
STATE_WAIT_ON_OTHER
};
+int gator_trace_sched_read(long long **buffer);
+
void emit_pid_name(struct task_struct* task)
{
bool found = false;
@@ -50,7 +52,7 @@ void emit_pid_name(struct task_struct* task)
}
}
- if (!found) {
+ if (!found && buffer_check_space(cpu, TIMER_BUF, TASK_COMM_LEN + 2 * MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
// shift values, new value always in front
uint64_t oldv, newv = value;
for (x = 0; x < TASK_MAX_COLLISIONS; x++) {
@@ -128,7 +130,7 @@ static void probe_sched_write(int type, struct task_struct* task, struct task_st
}
// special case used during a suspend of the system
-static void trace_sched_insert_idle(void* unused)
+static void trace_sched_insert_idle(void)
{
unsigned long flags;
uint64_t *schedBuf;
@@ -170,11 +172,6 @@ GATOR_DEFINE_PROBE(sched_process_free, TP_PROTO(struct task_struct *p))
probe_sched_write(SCHED_PROCESS_FREE, p, 0);
}
-int gator_trace_sched_init(void)
-{
- return 0;
-}
-
static int register_scheduler_tracepoints(void) {
// register tracepoints
if (GATOR_REGISTER_TRACE(sched_switch))
@@ -217,6 +214,12 @@ int gator_trace_sched_start(void)
return register_scheduler_tracepoints();
}
+int gator_trace_sched_offline(long long **buffer)
+{
+ trace_sched_insert_idle();
+ return gator_trace_sched_read(buffer);
+}
+
static void unregister_scheduler_tracepoints(void)
{
GATOR_UNREGISTER_TRACE(sched_switch);