summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 1963aa5)
raw | patch | inline | side by side (parent: 1963aa5)
author | Jon Medhurst <tixy@linaro.org> | |
Fri, 26 Oct 2012 16:05:14 +0000 (17:05 +0100) | ||
committer | Jon Medhurst <tixy@linaro.org> | |
Fri, 26 Oct 2012 16:05:14 +0000 (17:05 +0100) |
Signed-off-by: Jon Medhurst <tixy@linaro.org>
58 files changed:
diff --git a/daemon/CapturedXML.cpp b/daemon/CapturedXML.cpp
index f02ed2a0155192bfb5d36a1608e38eb499967238..30d984f16c35b8d9617934027e95e933f62afe9f 100644 (file)
--- a/daemon/CapturedXML.cpp
+++ b/daemon/CapturedXML.cpp
CapturedXML::~CapturedXML() {
}
-mxml_node_t* CapturedXML::getTree() {
+mxml_node_t* CapturedXML::getTree(bool includeTime) {
bool perfCounters = false;
mxml_node_t *xml;
- mxml_node_t *captured;
- mxml_node_t *target;
- mxml_node_t *counters;
+ mxml_node_t *captured;
+ mxml_node_t *target;
+ mxml_node_t *counters;
mxml_node_t *counter;
int x;
captured = mxmlNewElement(xml, "captured");
mxmlElementSetAttr(captured, "version", "1");
mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION);
- if (gSessionData->mBytes > 0) { // Send the following only after the capture is complete
+ if (includeTime) { // Send the following only after the capture is complete
if (time(NULL) > 1267000000) { // If the time is reasonable (after Feb 23, 2010)
mxmlElementSetAttrf(captured, "created", "%lu", time(NULL)); // Valid until the year 2038
}
- mxmlElementSetAttrf(captured, "bytes", "%d", gSessionData->mBytes);
}
target = mxmlNewElement(captured, "target");
if (gSessionData->mPerfCounterPerCPU[x]) {
mxmlElementSetAttr(counter, "per_cpu", "yes");
}
- if (strlen(gSessionData->mPerfCounterOperation[x]) > 0) {
- mxmlElementSetAttr(counter, "operation", gSessionData->mPerfCounterOperation[x]);
- }
if (gSessionData->mPerfCounterCount[x] > 0) {
mxmlElementSetAttrf(counter, "count", "%d", gSessionData->mPerfCounterCount[x]);
}
- if (gSessionData->mPerfCounterLevel[x]) {
- mxmlElementSetAttr(counter, "level", "yes");
- }
- if (strlen(gSessionData->mPerfCounterAlias[x]) > 0) {
- mxmlElementSetAttr(counter, "alias", gSessionData->mPerfCounterAlias[x]);
- }
if (strlen(gSessionData->mPerfCounterDisplay[x]) > 0) {
mxmlElementSetAttr(counter, "display", gSessionData->mPerfCounterDisplay[x]);
}
return xml;
}
-char* CapturedXML::getXML() {
+char* CapturedXML::getXML(bool includeTime) {
char* xml_string;
- mxml_node_t *xml = getTree();
+ mxml_node_t *xml = getTree(includeTime);
xml_string = mxmlSaveAllocString(xml, mxmlWhitespaceCB);
mxmlDelete(xml);
return xml_string;
// Set full path
snprintf(file, PATH_MAX, "%s/captured.xml", path);
- char* xml = getXML();
+ char* xml = getXML(true);
if (util->writeToDisk(file, xml) < 0) {
logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
handleException();
diff --git a/daemon/CapturedXML.h b/daemon/CapturedXML.h
index 984d1f2d13e83231596b2b2b3e01fd7dd46f4e7d..3f6a4deaccc622902342da52efc694426560c7fa 100644 (file)
--- a/daemon/CapturedXML.h
+++ b/daemon/CapturedXML.h
public:
CapturedXML();
~CapturedXML();
- char* getXML(); // the string should be freed by the caller
+ char* getXML(bool includeTime); // the string should be freed by the caller
void write(char* path);
private:
- mxml_node_t* getTree();
+ mxml_node_t* getTree(bool includeTime);
};
#endif //__CAPTURED_XML_H__
diff --git a/daemon/Child.cpp b/daemon/Child.cpp
index 2c7c292916eab6a4807688a4aa01ddfb4dd9146d..b97e0db1e3ccaa1867c4106d76305d1056eacf70 100644 (file)
--- a/daemon/Child.cpp
+++ b/daemon/Child.cpp
prctl(PR_SET_NAME, (unsigned long)&"gatord-stopper", 0, 0, 0);
while (gSessionData->mSessionIsActive) {
// This thread will stall until the APC_STOP or PING command is received over the socket or the socket is disconnected
- if (socket->receiveNBytes(&type, sizeof(type)) > 0) {
+ const int result = socket->receiveNBytes(&type, sizeof(type));
+ if (result == -1) {
+ child->endSession();
+ } else if (result > 0) {
if ((type != COMMAND_APC_STOP) && (type != COMMAND_PING)) {
logg->logMessage("INVESTIGATE: Received unknown command type %d", type);
} else {
}
gSessionData->parseSessionXML(xmlString);
localCapture = new LocalCapture();
- localCapture->createAPCDirectory(gSessionData->mTargetPath, gSessionData->mTitle);
+ localCapture->createAPCDirectory(gSessionData->mTargetPath);
localCapture->copyImages(gSessionData->mImages);
localCapture->write(xmlString);
sender->createDataFile(gSessionData->mAPCDir);
diff --git a/daemon/Collector.cpp b/daemon/Collector.cpp
index d29cd16bd50b2eccee4989fa993de4eae0a7ef4e..25bb934f0bd9c72358907dc2171114cdedc1bdcf 100644 (file)
--- a/daemon/Collector.cpp
+++ b/daemon/Collector.cpp
int Collector::collect(char* buffer) {
// Calls event_buffer_read in the driver
- int bytesRead = read(mBufferFD, buffer, mBufferSize);
+ int bytesRead;
+
+ errno = 0;
+ bytesRead = read(mBufferFD, buffer, mBufferSize);
// If read() returned due to an interrupt signal, re-read to obtain the last bit of collected data
if (bytesRead == -1 && errno == EINTR) {
index 145ddbdd73633544c223365f3b6acf413e84f34d..a213cbb2ddbfe205f1cd7940afad9fc54bbfd071 100644 (file)
static const char* ATTR_TITLE = "title";
static const char* ATTR_NAME = "name";
static const char* ATTR_EVENT = "event";
-static const char* ATTR_COLOR = "color";
static const char* ATTR_COUNT = "count";
-static const char* ATTR_OPERATION = "operation";
static const char* ATTR_PER_CPU = "per_cpu";
static const char* ATTR_DESCRIPTION = "description";
-static const char* ATTR_EBS = "event_based_sampling";
-static const char* ATTR_LEVEL = "level";
-static const char* ATTR_ALIAS = "alias";
+static const char* ATTR_EBS = "supports_event_based_sampling";
static const char* ATTR_DISPLAY = "display";
static const char* ATTR_UNITS = "units";
static const char* ATTR_AVERAGE_SELECTION = "average_selection";
ConfigurationXML::ConfigurationXML() {
-#include "configuration_xml.h" // defines and initializes char configuration_xml[] and int configuration_xml_len
+ const char * configuration_xml;
+ unsigned int configuration_xml_len;
+ getDefaultConfigurationXml(configuration_xml, configuration_xml_len);
+
mIndex = 0;
char* path = (char*)malloc(PATH_MAX);
gSessionData->mPerfCounterEnabled[i] = 0;
}
+ // clear counter overflow
+ gSessionData->mCounterOverflow = false;
+
int ret = parse(mConfigurationXML);
if (ret == 1) {
// remove configuration.xml on disk to use the default
void ConfigurationXML::configurationTag(mxml_node_t *node) {
// handle all other performance counters
if (mIndex >= MAX_PERFORMANCE_COUNTERS) {
- logg->logError(__FILE__, __LINE__, "Exceeded maximum number of %d performance counters", MAX_PERFORMANCE_COUNTERS);
- handleException();
+ gSessionData->mCounterOverflow = true;
+ return;
}
// read attributes
if (mxmlElementGetAttr(node, ATTR_DESCRIPTION)) strncpy(gSessionData->mPerfCounterDescription[mIndex], mxmlElementGetAttr(node, ATTR_DESCRIPTION), sizeof(gSessionData->mPerfCounterDescription[mIndex]));
if (mxmlElementGetAttr(node, ATTR_EVENT)) gSessionData->mPerfCounterEvent[mIndex] = strtol(mxmlElementGetAttr(node, ATTR_EVENT), NULL, 16);
if (mxmlElementGetAttr(node, ATTR_COUNT)) gSessionData->mPerfCounterCount[mIndex] = strtol(mxmlElementGetAttr(node, ATTR_COUNT), NULL, 10);
- if (mxmlElementGetAttr(node, ATTR_COLOR)) gSessionData->mPerfCounterColor[mIndex] = strtol(mxmlElementGetAttr(node, ATTR_COLOR), NULL, 16);
if (mxmlElementGetAttr(node, ATTR_PER_CPU)) gSessionData->mPerfCounterPerCPU[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_PER_CPU), false);
if (mxmlElementGetAttr(node, ATTR_EBS)) gSessionData->mPerfCounterEBSCapable[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_EBS), false);
- if (mxmlElementGetAttr(node, ATTR_OPERATION)) strncpy(gSessionData->mPerfCounterOperation[mIndex], mxmlElementGetAttr(node, ATTR_OPERATION), sizeof(gSessionData->mPerfCounterOperation[mIndex]));
- if (mxmlElementGetAttr(node, ATTR_LEVEL)) gSessionData->mPerfCounterLevel[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_LEVEL), false);
- if (mxmlElementGetAttr(node, ATTR_ALIAS)) strncpy(gSessionData->mPerfCounterAlias[mIndex], mxmlElementGetAttr(node, ATTR_ALIAS), sizeof(gSessionData->mPerfCounterAlias[mIndex]));
if (mxmlElementGetAttr(node, ATTR_DISPLAY)) strncpy(gSessionData->mPerfCounterDisplay[mIndex], mxmlElementGetAttr(node, ATTR_DISPLAY), sizeof(gSessionData->mPerfCounterDisplay[mIndex]));
if (mxmlElementGetAttr(node, ATTR_UNITS)) strncpy(gSessionData->mPerfCounterUnits[mIndex], mxmlElementGetAttr(node, ATTR_UNITS), sizeof(gSessionData->mPerfCounterUnits[mIndex]));
if (mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION)) gSessionData->mPerfCounterAverageSelection[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION), false);
gSessionData->mPerfCounterTitle[mIndex][sizeof(gSessionData->mPerfCounterTitle[mIndex]) - 1] = 0;
gSessionData->mPerfCounterName[mIndex][sizeof(gSessionData->mPerfCounterName[mIndex]) - 1] = 0;
gSessionData->mPerfCounterDescription[mIndex][sizeof(gSessionData->mPerfCounterDescription[mIndex]) - 1] = 0;
- gSessionData->mPerfCounterOperation[mIndex][sizeof(gSessionData->mPerfCounterOperation[mIndex]) - 1] = 0;
- gSessionData->mPerfCounterAlias[mIndex][sizeof(gSessionData->mPerfCounterAlias[mIndex]) - 1] = 0;
gSessionData->mPerfCounterDisplay[mIndex][sizeof(gSessionData->mPerfCounterDisplay[mIndex]) - 1] = 0;
gSessionData->mPerfCounterUnits[mIndex][sizeof(gSessionData->mPerfCounterUnits[mIndex]) - 1] = 0;
// update counter index
mIndex++;
}
+
+void ConfigurationXML::getDefaultConfigurationXml(const char * & xml, unsigned int & len) {
+ // the first line of configuration_xml.h is "unsigned char configuration_xml", but configuration_xml needs to be const static as well
+ const static
+#include "configuration_xml.h" // defines and initializes char configuration_xml[] and int configuration_xml_len
+ xml = (const char *)configuration_xml;
+ len = configuration_xml_len;
+}
index b48d32f978dc64d6e06c083ef2cfa58ee19215dd..66ad587320ae097120abc7911c53b579213639d4 100644 (file)
class ConfigurationXML {
public:
+ static void getDefaultConfigurationXml(const char * & xml, unsigned int & len);
+
ConfigurationXML();
~ConfigurationXML();
const char* getConfigurationXML() {return mConfigurationXML;}
void validate(void);
+
private:
char* mConfigurationXML;
int mIndex;
index 6449d0352142ae1b69e7699ef2b226c219353bda..f8cd17f00b3b2818691b1c2111bc7c195d29f552 100644 (file)
--- a/daemon/LocalCapture.cpp
+++ b/daemon/LocalCapture.cpp
LocalCapture::~LocalCapture() {}
-void LocalCapture::createAPCDirectory(char* target_path, char* name) {
- gSessionData->mAPCDir = createUniqueDirectory(target_path, ".apc", name);
+void LocalCapture::createAPCDirectory(char* target_path) {
+ gSessionData->mAPCDir = createUniqueDirectory(target_path, ".apc");
if ((removeDirAndAllContents(gSessionData->mAPCDir) != 0 || mkdir(gSessionData->mAPCDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)) {
logg->logError(__FILE__, __LINE__, "Unable to create directory %s", gSessionData->mAPCDir);
handleException();
free(file);
}
-char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* ending, char* title) {
- int i;
+char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* ending) {
char* output;
char* path = (char*)malloc(PATH_MAX);
// Ensure the path is an absolute path, i.e. starts with a slash
if (initialPath == 0 || strlen(initialPath) == 0) {
- if (getcwd(path, PATH_MAX) == 0) {
- logg->logMessage("Unable to retrive the current working directory");
- }
- strncat(path, "/@F_@N", PATH_MAX - strlen(path) - 1);
+ logg->logError(__FILE__, __LINE__, "Missing -o command line option required for a local capture.");
+ handleException();
} else if (initialPath[0] != '/') {
if (getcwd(path, PATH_MAX) == 0) {
logg->logMessage("Unable to retrive the current working directory");
@@ -68,98 +65,17 @@ char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* e
path[PATH_MAX - 1] = 0; // strncpy does not guarantee a null-terminated string
}
- // Convert to uppercase
- replaceAll(path, "@f", "@F", PATH_MAX);
- replaceAll(path, "@n", "@N", PATH_MAX);
-
- // Replace @F with the session xml title
- replaceAll(path, "@F", title, PATH_MAX);
-
// Add ending if it is not already there
if (strcmp(&path[strlen(path) - strlen(ending)], ending) != 0) {
strncat(path, ending, PATH_MAX - strlen(path) - 1);
}
- // Replace @N with a unique integer
- if (strstr(path, "@N")) {
- char* tempPath = (char*)malloc(PATH_MAX);
- for (i = 1; i < 1000; i++) {
- char number[4];
- snprintf(number, sizeof(number), "%03d", i);
- strcpy(tempPath, path);
- replaceAll(tempPath, "@N", number, PATH_MAX);
- struct stat mFileInfo;
- if (stat(tempPath, &mFileInfo) != 0) {
- // if the direcotry does not exist, break
- break;
- }
- }
-
- if (i == 1000) {
- logg->logError(__FILE__, __LINE__, "Unable to create .apc directory, please delete older directories.");
- handleException();
- }
-
- output = strdup(tempPath);
- free(tempPath);
- } else {
- output = strdup(path);
- }
+ output = strdup(path);
free(path);
return output;
}
-//Replaces all occurrences of <find> in <target> with <replace> provided enough <size> is available
-void LocalCapture::replaceAll(char* target, const char* find, const char* replace, unsigned int size) {
- char* nextOccurrence;
- unsigned int count = 0;
-
- // Duplicate the original string
- char* original = strdup(target);
- char* ptr = original;
-
- // Determine number of <find>s
- ptr = strstr(ptr, find);
- while (ptr) {
- count++;
- ptr += strlen(find);
- ptr = strstr(ptr, find);
- }
-
- // Is there enough space available
- if (strlen(target) + (strlen(replace) - strlen(find)) * count > size - 1) {
- free(original);
- return;
- }
-
- // Reset
- ptr = original;
-
- nextOccurrence = strstr(ptr, find);
- while (nextOccurrence) {
- // Move pointers to location of replace
- int length = nextOccurrence - ptr;
- target += length;
- ptr += length;
-
- // Replace <find> with <replace>
- memcpy(target, replace, strlen(replace));
-
- // Increment over <replace>/<find>
- target += strlen(replace);
- ptr += strlen(find);
-
- // Copy remainder of ptr
- strcpy(target, ptr);
-
- // Get next occurrence
- nextOccurrence = strstr(ptr, find);
- }
-
- free(original);
-}
-
int LocalCapture::removeDirAndAllContents(char* path) {
int error = 0;
struct stat mFileInfo;
diff --git a/daemon/LocalCapture.h b/daemon/LocalCapture.h
index ca37f6e7b5152daf4b5e0ff294f56e4cbc6e4be1..40f7883237a4d3cf22a8c87cbeb2ba57f74f20a2 100644 (file)
--- a/daemon/LocalCapture.h
+++ b/daemon/LocalCapture.h
~LocalCapture();
void write(char* string);
void copyImages(ImageLinkList* ptr);
- void createAPCDirectory(char* target_path, char* name);
+ void createAPCDirectory(char* target_path);
private:
- char* createUniqueDirectory(const char* path, const char* ending, char* title);
- void replaceAll(char* target, const char* find, const char* replace, unsigned int size);
+ char* createUniqueDirectory(const char* path, const char* ending);
int removeDirAndAllContents(char* path);
};
diff --git a/daemon/Makefile b/daemon/Makefile
index b62a223c8407910eaa611576b9b54c455482a500..5562db7627099bdbe3fefc6f1998af8150a88d09 100644 (file)
--- a/daemon/Makefile
+++ b/daemon/Makefile
#
# Uncomment and define CROSS_COMPILE if it is not already defined
-# CROSS_COMPILE=/path/to/cross-compiler/arm-none-linux-gnueabi-
+# CROSS_COMPILE=/path/to/cross-compiler/arm-linux-gnueabihf-
+# NOTE: This toolchain uses the hardfloat abi by default. For non-hardfloat
+# targets it is necessary to add options
+# '-marm -march=armv4t -mfloat-abi=soft'.
+
ARCH=arm
CPP=$(CROSS_COMPILE)g++
# -std=c++0x is the planned new c++ standard
# -std=c++98 is the 1998 c++ standard
# -mthumb-interwork is required for interworking to ARM or Thumb stdlibc
-CFLAGS=-O3 -Wall -Werror -Wno-error=sequence-point -mthumb-interwork
+CFLAGS=-O3 -Wall -mthumb-interwork
+ifeq ($(WERROR),1)
+ CFLAGS += -Werror
+endif
# -s strips the binary of debug info
LDFLAGS=-s
TARGET=gatord
diff --git a/daemon/OlyUtility.cpp b/daemon/OlyUtility.cpp
index c72b0d12e8b58c2fdd34f65221e1513dba1308d7..adc7aba0446a7ea313820fe6a2e63b8f87710f81 100644 (file)
--- a/daemon/OlyUtility.cpp
+++ b/daemon/OlyUtility.cpp
bool OlyUtility::stringToBool(const char* string, bool defValue) {
char value[32];
+ if (string == NULL) {
+ return defValue;
+ }
+
strncpy(value, string, sizeof(value));
if (value[0] == 0) {
return defValue;
diff --git a/daemon/Sender.cpp b/daemon/Sender.cpp
index efff7532a0dc4fc0be8a73c790ab8ef4d5e712d0..eba8343b63426b36972b566ec73fa737f4db1c9f 100644 (file)
--- a/daemon/Sender.cpp
+++ b/daemon/Sender.cpp
}
// Send magic sequence - must be done first, afterwhich error messages can be sent
- char magic[] = {'G', 'A', 'T', 'O', 'R', '\n'};
- mDataSocket->send(magic, sizeof(magic));
+ char magic[32];
+ snprintf(magic, 32, "GATOR %i\n", PROTOCOL_VERSION);
+ mDataSocket->send(magic, strlen(magic));
gSessionData->mWaitingOnCommand = true;
logg->logMessage("Completed magic sequence");
diff --git a/daemon/Sender.h b/daemon/Sender.h
index 98467e025c12332b1c8b9fbba8df26f101c46101..ceab343af9fa851347becf5df193221c02cd3e4e 100644 (file)
--- a/daemon/Sender.h
+++ b/daemon/Sender.h
#include "OlySocket.h"
enum {
- RESPONSE_END = 0, // unused
RESPONSE_XML = 1,
RESPONSE_APC_DATA = 3,
RESPONSE_ACK = 4,
diff --git a/daemon/SessionData.cpp b/daemon/SessionData.cpp
index a245369a37a35d37a4bc94c3e490f2865287b346..5aa3f11afe34dd978427976f91b6c32a89716ee2 100644 (file)
--- a/daemon/SessionData.cpp
+++ b/daemon/SessionData.cpp
mConfigurationXMLPath = NULL;
mSessionXMLPath = NULL;
mEventsXMLPath = NULL;
+ mTargetPath = NULL;
mAPCDir = NULL;
mSampleRate = 0;
mDuration = 0;
- mBytes = 0;
mBacktraceDepth = 0;
mTotalBufferSize = 0;
mCores = 1;
mPerfCounterTitle[i][0] = 0;
mPerfCounterName[i][0] = 0;
mPerfCounterDescription[i][0] = 0;
- mPerfCounterOperation[i][0] = 0;
- mPerfCounterAlias[i][0] = 0;
mPerfCounterDisplay[i][0] = 0;
mPerfCounterUnits[i][0] = 0;
mPerfCounterEnabled[i] = 0;
mPerfCounterCount[i] = 0;
mPerfCounterPerCPU[i] = false;
mPerfCounterEBSCapable[i] = false;
- mPerfCounterLevel[i] = false;
mPerfCounterAverageSelection[i] = false;
}
}
SessionXML session(xmlString);
session.parse();
- // Parameter error checking
- if (session.parameters.output_path == 0 && session.parameters.target_path == 0) {
- logg->logError(__FILE__, __LINE__, "No capture path (target or host) was provided.");
- handleException();
- } else if (gSessionData->mLocalCapture && session.parameters.target_path == 0) {
- logg->logError(__FILE__, __LINE__, "Missing target_path tag in session xml required for a local capture.");
- handleException();
- }
-
// Set session data values
if (strcmp(session.parameters.sample_rate, "high") == 0) {
gSessionData->mSampleRate = 10000;
gSessionData->mSampleRate = 1000;
} else if (strcmp(session.parameters.sample_rate, "low") == 0) {
gSessionData->mSampleRate = 100;
- } else {
+ } else if (strcmp(session.parameters.sample_rate, "none") == 0) {
gSessionData->mSampleRate = 0;
+ } else {
+ logg->logError(__FILE__, __LINE__, "Invalid sample rate (%s) in session xml.", session.parameters.sample_rate);
+ handleException();
}
gSessionData->mBacktraceDepth = session.parameters.call_stack_unwinding == true ? 128 : 0;
gSessionData->mDuration = session.parameters.duration;
}
gSessionData->mImages = session.parameters.images;
- gSessionData->mTargetPath = session.parameters.target_path;
- gSessionData->mTitle = session.parameters.title;
}
diff --git a/daemon/SessionData.h b/daemon/SessionData.h
index 6f42c073c4da3cb9204a579ee18554ec81337cbd..00a71b1820181416c19d2ac260ad8e9330f226a1 100644 (file)
--- a/daemon/SessionData.h
+++ b/daemon/SessionData.h
#define MAX_STRING_LEN 80
#define MAX_DESCRIPTION_LEN 400
-#define PROTOCOL_VERSION 10
+#define PROTOCOL_VERSION 11
#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions
struct ImageLinkList {
char* mEventsXMLPath;
char* mTargetPath;
char* mAPCDir;
- char* mTitle;
bool mWaitingOnCommand;
bool mSessionIsActive;
int mSampleRate;
int mDuration;
int mCores;
- int mBytes;
// PMU Counters
+ bool mCounterOverflow;
char mPerfCounterType[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
char mPerfCounterTitle[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
char mPerfCounterName[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
char mPerfCounterDescription[MAX_PERFORMANCE_COUNTERS][MAX_DESCRIPTION_LEN];
- char mPerfCounterOperation[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
- char mPerfCounterAlias[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
char mPerfCounterDisplay[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
char mPerfCounterUnits[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
int mPerfCounterEnabled[MAX_PERFORMANCE_COUNTERS];
int mPerfCounterKey[MAX_PERFORMANCE_COUNTERS];
bool mPerfCounterPerCPU[MAX_PERFORMANCE_COUNTERS];
bool mPerfCounterEBSCapable[MAX_PERFORMANCE_COUNTERS];
- bool mPerfCounterLevel[MAX_PERFORMANCE_COUNTERS];
bool mPerfCounterAverageSelection[MAX_PERFORMANCE_COUNTERS];
};
diff --git a/daemon/SessionXML.cpp b/daemon/SessionXML.cpp
index f1a8258b525e0b5716341c2cadb9c5859ef065a6..4c373d81c179593dfd3e2c5c37824a1026d09c79 100644 (file)
--- a/daemon/SessionXML.cpp
+++ b/daemon/SessionXML.cpp
static const char* TAG_IMAGE = "image";
static const char* ATTR_VERSION = "version";
-static const char* ATTR_TITLE = "title";
-static const char* ATTR_UUID = "uuid";
static const char* ATTR_CALL_STACK_UNWINDING = "call_stack_unwinding";
static const char* ATTR_BUFFER_MODE = "buffer_mode";
static const char* ATTR_SAMPLE_RATE = "sample_rate";
-static const char* ATTR_TARGET_PATH = "target_path";
-static const char* ATTR_OUTPUT_PATH = "output_path";
static const char* ATTR_DURATION = "duration";
static const char* ATTR_PATH = "path";
SessionXML::SessionXML(const char* str) {
- parameters.title = 0;
- parameters.uuid[0] = 0;
- parameters.target_path = 0;
- parameters.output_path = 0;
parameters.buffer_mode[0] = 0;
parameters.sample_rate[0] = 0;
parameters.duration = 0;
handleException();
}
- // allocate strings
- if (mxmlElementGetAttr(node, ATTR_TITLE)) {
- parameters.title = strdup(mxmlElementGetAttr(node, ATTR_TITLE)); // freed when the child process exits
- if (parameters.title == NULL) {
- logg->logError(__FILE__, __LINE__, "failed to allocate parameters.title");
- handleException();
- }
- }
- if (mxmlElementGetAttr(node, ATTR_TARGET_PATH)) {
- parameters.target_path = strdup(mxmlElementGetAttr(node, ATTR_TARGET_PATH)); // freed when the child process exits
- if (parameters.target_path == NULL) {
- logg->logError(__FILE__, __LINE__, "failed to allocate parameters.target_path");
- handleException();
- }
- }
- if (mxmlElementGetAttr(node, ATTR_OUTPUT_PATH)) {
- parameters.output_path = strdup(mxmlElementGetAttr(node, ATTR_OUTPUT_PATH)); // freed when the child process exits
- if (parameters.output_path == NULL) {
- logg->logError(__FILE__, __LINE__, "failed to allocate parameters.output_path");
- handleException();
- }
- }
-
// copy to pre-allocated strings
- if (mxmlElementGetAttr(node, ATTR_UUID)) {
- strncpy(parameters.uuid, mxmlElementGetAttr(node, ATTR_UUID), sizeof(parameters.uuid));
- parameters.uuid[sizeof(parameters.uuid) - 1] = 0; // strncpy does not guarantee a null-terminated string
- }
if (mxmlElementGetAttr(node, ATTR_BUFFER_MODE)) {
strncpy(parameters.buffer_mode, mxmlElementGetAttr(node, ATTR_BUFFER_MODE), sizeof(parameters.buffer_mode));
parameters.buffer_mode[sizeof(parameters.buffer_mode) - 1] = 0; // strncpy does not guarantee a null-terminated string
diff --git a/daemon/SessionXML.h b/daemon/SessionXML.h
index c2b54894441342db5d05cda6d1a6df953d5d604a..f7a5641e498a543aabd8ee12cd887a6aa523faaa 100644 (file)
--- a/daemon/SessionXML.h
+++ b/daemon/SessionXML.h
#include "SessionData.h"
struct ConfigParameters {
- char* title; // status title
- char uuid[64]; // universal unique identifier
- char* target_path; // target path of where to write to disk
- char* output_path; // host path of where to write to disk
char buffer_mode[64]; // buffer mode, "streaming", "low", "normal", "high" defines oneshot and buffer size
char sample_rate[64]; // capture mode, "high", "normal", or "low"
int duration; // length of profile in seconds
index 53729ab0f6e6992541a92e778a6e5a5812a75240..3f59eabeb977f59bebc207a2e250e1d086c28cb6 100644 (file)
static const char* TAG_REQUEST = "request";
static const char* TAG_CONFIGURATIONS = "configurations";
-static const char* ATTR_PROTOCOL = "protocol";
-static const char* ATTR_EVENTS = "events";
-static const char* ATTR_CONFIGURATION = "configuration";
-static const char* ATTR_COUNTERS = "counters";
-static const char* ATTR_SESSION = "session";
-static const char* ATTR_CAPTURED = "captured";
-static const char* ATTR_DEFAULTS = "defaults";
+static const char* ATTR_TYPE = "type";
+static const char* VALUE_EVENTS = "events";
+static const char* VALUE_CONFIGURATION = "configuration";
+static const char* VALUE_COUNTERS = "counters";
+static const char* VALUE_SESSION = "session";
+static const char* VALUE_CAPTURED = "captured";
+static const char* VALUE_DEFAULTS = "defaults";
StreamlineSetup::StreamlineSetup(OlySocket* s) {
bool ready = false;
free(data);
}
+
+ if (gSessionData->mCounterOverflow) {
+ logg->logError(__FILE__, __LINE__, "Exceeded maximum number of %d performance counters", MAX_PERFORMANCE_COUNTERS);
+ handleException();
+ }
}
StreamlineSetup::~StreamlineSetup() {
void StreamlineSetup::handleRequest(char* xml) {
mxml_node_t *tree, *node;
+ const char * attr = NULL;
tree = mxmlLoadString(NULL, xml, MXML_NO_CALLBACK);
- if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_PROTOCOL, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_PROTOCOL), false)) {
- sendProtocol();
- logg->logMessage("Sent protocol xml response");
- } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_EVENTS, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_EVENTS), false)) {
+ node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_TYPE, NULL, MXML_DESCEND_FIRST);
+ if (node) {
+ attr = mxmlElementGetAttr(node, ATTR_TYPE);
+ }
+ if (attr && strcmp(attr, VALUE_EVENTS) == 0) {
sendEvents();
logg->logMessage("Sent events xml response");
- } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_CONFIGURATION, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_CONFIGURATION), false)) {
+ } else if (attr && strcmp(attr, VALUE_CONFIGURATION) == 0) {
sendConfiguration();
logg->logMessage("Sent configuration xml response");
- } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_COUNTERS, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_COUNTERS), false)) {
+ } else if (attr && strcmp(attr, VALUE_COUNTERS) == 0) {
sendCounters();
logg->logMessage("Sent counters xml response");
- } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_SESSION, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_SESSION), false)) {
+ } else if (attr && strcmp(attr, VALUE_SESSION) == 0) {
sendData(mSessionXML, strlen(mSessionXML), RESPONSE_XML);
logg->logMessage("Sent session xml response");
- } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_CAPTURED, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_CAPTURED), false)) {
+ } else if (attr && strcmp(attr, VALUE_CAPTURED) == 0) {
CapturedXML capturedXML;
- char* capturedText = capturedXML.getXML();
+ char* capturedText = capturedXML.getXML(false);
sendData(capturedText, strlen(capturedText), RESPONSE_XML);
free(capturedText);
logg->logMessage("Sent captured xml response");
- } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_DEFAULTS, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_DEFAULTS), false)) {
+ } else if (attr && strcmp(attr, VALUE_DEFAULTS) == 0) {
sendDefaults();
logg->logMessage("Sent default configuration xml response");
} else {
mSocket->send((char*)data, length);
}
-void StreamlineSetup::sendProtocol() {
- mxml_node_t *xml;
- mxml_node_t *protocol;
-
- xml = mxmlNewXML("1.0");
- protocol = mxmlNewElement(xml, "protocol");
- mxmlElementSetAttrf(protocol, "version", "%d", PROTOCOL_VERSION);
-
- char* string = mxmlSaveAllocString(xml, mxmlWhitespaceCB);
- sendString(string, RESPONSE_XML);
-
- free(string);
- mxmlDelete(xml);
-}
-
void StreamlineSetup::sendEvents() {
#include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len
char* path = (char*)malloc(PATH_MAX);;
}
void StreamlineSetup::sendDefaults() {
-#include "configuration_xml.h" // defines and initializes char configuration_xml[] and int configuration_xml_len
// Send the config built into the binary
- char* xml = (char*)configuration_xml;
- unsigned int size = configuration_xml_len;
+ const char* xml;
+ unsigned int size;
+ ConfigurationXML::getDefaultConfigurationXml(xml, size);
// Artificial size restriction
if (size > 1024*1024) {
void StreamlineSetup::sendCounters() {
struct dirent *ent;
mxml_node_t *xml;
- mxml_node_t *counters;
+ mxml_node_t *counters;
mxml_node_t *counter;
// counters.xml is simply a file listing of /dev/gator/events
// Re-populate gSessionData with the configuration, as it has now changed
new ConfigurationXML();
free(path);
+
+ if (gSessionData->mCounterOverflow) {
+ logg->logError(__FILE__, __LINE__, "Exceeded maximum number of %d performance counters", MAX_PERFORMANCE_COUNTERS);
+ handleException();
+ }
}
index c46ae0891a31e20c41b2291e06d3c5d19a8bdc6f..8086fe2d1bbe168b4cb9fd235bb36f578cf99291 100644 (file)
--- a/daemon/StreamlineSetup.h
+++ b/daemon/StreamlineSetup.h
void handleDeliver(char* xml);
void sendData(const char* data, int length, int type);
void sendString(const char* string, int type) {sendData(string, strlen(string), type);}
- void sendProtocol();
void sendEvents();
void sendConfiguration();
void sendDefaults();
index 4875f1f2793231b0d69e6fb5197b1063c74391ec..fbdef31921b6ff428918c374b010ca39e7b7b7a1 100644 (file)
--- a/daemon/configuration.xml
+++ b/daemon/configuration.xml
<?xml version="1.0" encoding='UTF-8'?>
-<configurations version="1" revision="1">
+<configurations revision="1">
<configuration counter="ARM_ARM11_ccnt" title="Clock" name="Cycles" per_cpu="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<configuration counter="ARM_ARM11_cnt0" event="0x7" title="Instruction" name="Executed" per_cpu="yes" description="Instructions executed"/>
<configuration counter="ARM_ARM11_cnt1" event="0xb" title="Cache" name="Data miss" per_cpu="yes" description="Data cache miss, not including Cache Operations"/>
<configuration counter="ARM_ARM11MPCore_ccnt" title="Clock" name="Cycles" per_cpu="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<configuration counter="ARM_ARM11MPCore_cnt0" event="0x08" title="Core" name="Instructions" per_cpu="yes" description="Instructions executed"/>
<configuration counter="ARM_ARM11MPCore_cnt1" event="0x0b" title="Cache" name="Data read miss" per_cpu="yes" description="Data cache miss, not including Cache Operations"/>
- <configuration counter="ARM_Cortex-A5_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="ARM_Cortex-A5_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="ARM_Cortex-A5_cnt1" event="0x1" title="Cache" name="Instruction refill" per_cpu="yes" event_based_sampling="yes" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <configuration counter="ARM_Cortex-A7_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="ARM_Cortex-A7_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="ARM_Cortex-A7_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
- <configuration counter="ARM_Cortex-A7_cnt2" event="0x16" title="Cache" name="L2 data access" per_cpu="yes" event_based_sampling="yes" description="Level 2 data cache access"/>
- <configuration counter="ARM_Cortex-A8_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="ARM_Cortex-A8_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="ARM_Cortex-A8_cnt1" event="0x44" title="Cache" name="L2 miss" per_cpu="yes" event_based_sampling="yes" description="Any cacheable miss in the L2 cache"/>
- <configuration counter="ARM_Cortex-A8_cnt2" event="0x43" title="Cache" name="L1 miss" per_cpu="yes" event_based_sampling="yes" description="Any accesses to the L2 cache"/>
- <configuration counter="ARM_Cortex-A8_cnt3" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
- <configuration counter="ARM_Cortex-A9_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="ARM_Cortex-A9_cnt0" event="0x68" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Counts the number of instructions going through the Register Renaming stage. This number is an approximate number of the total number of instructions speculatively executed, and even more approximate of the total number of instructions architecturally executed"/>
- <configuration counter="ARM_Cortex-A9_cnt1" event="0x06" title="Instruction" name="Memory read" per_cpu="yes" event_based_sampling="yes" description="Memory-reading instruction architecturally executed"/>
- <configuration counter="ARM_Cortex-A9_cnt2" event="0x07" title="Instruction" name="Memory write" per_cpu="yes" event_based_sampling="yes" description="Memory-writing instruction architecturally executed"/>
- <configuration counter="ARM_Cortex-A9_cnt3" event="0x03" title="Cache" name="Data refill" per_cpu="yes" event_based_sampling="yes" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <configuration counter="ARM_Cortex-A9_cnt4" event="0x04" title="Cache" name="Data access" per_cpu="yes" event_based_sampling="yes" 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"/>
- <configuration counter="ARM_Cortex-A15_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="ARM_Cortex-A15_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="ARM_Cortex-A15_cnt1" event="0x16" title="Cache" name="L2 data access" per_cpu="yes" event_based_sampling="yes" description="Level 2 data cache access"/>
- <configuration counter="ARM_Cortex-A15_cnt2" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
- <configuration counter="ARM_Cortex-A15_cnt3" event="0x19" title="Bus" name="Access" per_cpu="yes" event_based_sampling="yes" description=""/>
- <configuration counter="Scorpion_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="Scorpion_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="Scorpion_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
- <configuration counter="ScorpionMP_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="ScorpionMP_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="ScorpionMP_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
- <configuration counter="Krait_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="Krait_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="Krait_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="ARM_Cortex-A5_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A5_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A5_cnt1" event="0x1" title="Cache" name="Instruction refill" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
+ <configuration counter="ARM_Cortex-A7_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A7_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A7_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" supports_event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="ARM_Cortex-A7_cnt2" event="0x16" title="Cache" name="L2 data access" per_cpu="yes" supports_event_based_sampling="yes" description="Level 2 data cache access"/>
+ <configuration counter="ARM_Cortex-A8_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A8_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A8_cnt1" event="0x44" title="Cache" name="L2 miss" per_cpu="yes" supports_event_based_sampling="yes" description="Any cacheable miss in the L2 cache"/>
+ <configuration counter="ARM_Cortex-A8_cnt2" event="0x43" title="Cache" name="L1 miss" per_cpu="yes" supports_event_based_sampling="yes" description="Any accesses to the L2 cache"/>
+ <configuration counter="ARM_Cortex-A8_cnt3" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" supports_event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="ARM_Cortex-A9_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A9_cnt0" event="0x68" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Counts the number of instructions going through the Register Renaming stage. This number is an approximate number of the total number of instructions speculatively executed, and even more approximate of the total number of instructions architecturally executed"/>
+ <configuration counter="ARM_Cortex-A9_cnt1" event="0x06" title="Instruction" name="Memory read" per_cpu="yes" supports_event_based_sampling="yes" description="Memory-reading instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A9_cnt2" event="0x07" title="Instruction" name="Memory write" per_cpu="yes" supports_event_based_sampling="yes" description="Memory-writing instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A9_cnt3" event="0x03" title="Cache" name="Data refill" per_cpu="yes" supports_event_based_sampling="yes" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
+ <configuration counter="ARM_Cortex-A9_cnt4" event="0x04" title="Cache" name="Data access" per_cpu="yes" supports_event_based_sampling="yes" 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"/>
+ <configuration counter="ARM_Cortex-A15_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A15_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A15_cnt1" event="0x16" title="Cache" name="L2 data access" per_cpu="yes" supports_event_based_sampling="yes" description="Level 2 data cache access"/>
+ <configuration counter="ARM_Cortex-A15_cnt2" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" supports_event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="ARM_Cortex-A15_cnt3" event="0x19" title="Bus" name="Access" per_cpu="yes" supports_event_based_sampling="yes" description=""/>
+ <configuration counter="Scorpion_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="Scorpion_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="Scorpion_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" supports_event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="ScorpionMP_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="ScorpionMP_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="ScorpionMP_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" supports_event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="Krait_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="Krait_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="Krait_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" supports_event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
<configuration counter="Linux_block_rq_wr" title="Disk IO" name="Write" units="B" description="Disk IO Bytes Written"/>
<configuration counter="Linux_block_rq_rd" title="Disk IO" name="Read" units="B" description="Disk IO Bytes Read"/>
- <configuration counter="Linux_net_rx" title="Network" name="Receive" units="B" description="Receive network traffic, including effect from Streamline"/>
- <configuration counter="Linux_net_tx" title="Network" name="Transmit" units="B" description="Transmit network traffic, including effect from Streamline"/>
- <configuration counter="Linux_cpuload_system" title="CPU Load" name="System" description="Scheduler CPU Load of System Behavior"/>
- <configuration counter="Linux_cpuload_user" title="CPU Load" name="User" description="Scheduler CPU Load of User Application"/>
<configuration counter="Linux_meminfo_memused" title="Memory" name="Used" display="maximum" units="B" average_selection="yes" description="Total used memory size"/>
<configuration counter="Linux_meminfo_memfree" title="Memory" name="Free" display="minimum" units="B" average_selection="yes" description="Available memory size"/>
<configuration counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" display="maximum" units="Hz" average_selection="yes" description="Frequency setting of the CPU"/>
index d4a2914823095a1421f422671d68c2e721463c49..0a5ee66a2c0a4b310add10084d43504417d89dc7 100644 (file)
--- a/daemon/events-ARM11.xml
+++ b/daemon/events-ARM11.xml
- <counter_set name="ARM_ARM11_cntX">
- <counter name="ARM_ARM11_cnt0"/>
- <counter name="ARM_ARM11_cnt1"/>
- <counter name="ARM_ARM11_cnt2"/>
- </counter_set>
- <category name="ARM11" counter_set="ARM_ARM11_cntX" per_cpu="yes">
+ <counter_set name="ARM_ARM11_cnt" count="3"/>
+ <category name="ARM11" counter_set="ARM_ARM11_cnt" per_cpu="yes">
<event counter="ARM_ARM11_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<event event="0x00" title="Cache" name="Inst miss" description="Instruction cache miss to a cacheable location, which requires a fetch from external memory"/>
<event event="0x01" title="Pipeline" name="Instruction stall" description="Stall because instruction buffer cannot deliver an instruction"/>
index 7de51b0819d904bbc77054a15fbf0979f4362c22..1a9ca3fee7db54e2a1aa79be002e5fb42bdd8b85 100644 (file)
- <counter_set name="ARM_ARM11MPCore_cntX">
- <counter name="ARM_ARM11MPCore_cnt0"/>
- <counter name="ARM_ARM11MPCore_cnt1"/>
- <counter name="ARM_ARM11MPCore_cnt2"/>
- </counter_set>
- <category name="ARM11MPCore" counter_set="ARM_ARM11MPCore_cntX" per_cpu="yes">
+ <counter_set name="ARM_ARM11MPCore_cnt" count="3"/>
+ <category name="ARM11MPCore" counter_set="ARM_ARM11MPCore_cnt" per_cpu="yes">
<event counter="ARM_ARM11MPCore_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<event event="0x00" title="Cache" name="Inst miss" description="Instruction cache miss to a cacheable location, which requires a fetch from external memory"/>
<event event="0x01" title="Pipeline" name="Instruction stall" description="Stall because instruction buffer cannot deliver an instruction"/>
index d6222eb4359191a658036859a901206d0afc0f74..0ec196f96b039128970e74c5333b8c088a7a6441 100644 (file)
- <counter_set name="ARM_Cortex-A15_cntX">
- <counter name="ARM_Cortex-A15_cnt0"/>
- <counter name="ARM_Cortex-A15_cnt1"/>
- <counter name="ARM_Cortex-A15_cnt2"/>
- <counter name="ARM_Cortex-A15_cnt3"/>
- <counter name="ARM_Cortex-A15_cnt4"/>
- <counter name="ARM_Cortex-A15_cnt5"/>
- </counter_set>
- <category name="Cortex-A15" counter_set="ARM_Cortex-A15_cntX" per_cpu="yes" event_based_sampling="yes">
+ <counter_set name="ARM_Cortex-A15_cnt" count="6"/>
+ <category name="Cortex-A15" counter_set="ARM_Cortex-A15_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="ARM_Cortex-A15_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" 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="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
<event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
<event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <event event="0x11" title="Cycle" name="Cycle" description=""/>
<event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
<event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
<event event="0x14" title="Cache" name="L1 inst access" description="Instruction cache access"/>
index e01492be96643fc5c6b73685375edf9a74ad36e9..4a894d37fbfb77cc324d4d5a280b86d2908d71fe 100644 (file)
- <counter_set name="ARM_Cortex-A5_cntX">
- <counter name="ARM_Cortex-A5_cnt0"/>
- <counter name="ARM_Cortex-A5_cnt1"/>
- </counter_set>
- <category name="Cortex-A5" counter_set="ARM_Cortex-A5_cntX" per_cpu="yes" event_based_sampling="yes">
+ <counter_set name="ARM_Cortex-A5_cnt" count="2"/>
+ <category name="Cortex-A5" counter_set="ARM_Cortex-A5_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="ARM_Cortex-A5_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" 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"/>
index 9ee45809a6a095fa190eda4afee4ae6df85d8966..2bd47975cb96447afb8feaeeb114c458adc47bd0 100644 (file)
- <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">
+ <counter_set name="ARM_Cortex-A7_cnt" count="4"/>
+ <category name="Cortex-A7" counter_set="ARM_Cortex-A7_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="ARM_Cortex-A7_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" 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"/>
index 1981c366151f76cf52deab57eabf3a21192e9d4f..fe4c69d09cdc2d099a412057b87280a41afc27f1 100644 (file)
- <counter_set name="ARM_Cortex-A8_cntX">
- <counter name="ARM_Cortex-A8_cnt0"/>
- <counter name="ARM_Cortex-A8_cnt1"/>
- <counter name="ARM_Cortex-A8_cnt2"/>
- <counter name="ARM_Cortex-A8_cnt3"/>
- </counter_set>
- <category name="Cortex-A8" counter_set="ARM_Cortex-A8_cntX" per_cpu="yes" event_based_sampling="yes">
+ <counter_set name="ARM_Cortex-A8_cnt" count="4"/>
+ <category name="Cortex-A8" counter_set="ARM_Cortex-A8_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="ARM_Cortex-A8_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" 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"/>
index faccb2f48574c38736726d19ba37308163cc993f..7597f789c924d8f4b8ba12233f692f16e84188d1 100644 (file)
- <counter_set name="ARM_Cortex-A9_cntX">
- <counter name="ARM_Cortex-A9_cnt0"/>
- <counter name="ARM_Cortex-A9_cnt1"/>
- <counter name="ARM_Cortex-A9_cnt2"/>
- <counter name="ARM_Cortex-A9_cnt3"/>
- <counter name="ARM_Cortex-A9_cnt4"/>
- <counter name="ARM_Cortex-A9_cnt5"/>
- </counter_set>
- <category name="Cortex-A9" counter_set="ARM_Cortex-A9_cntX" per_cpu="yes" event_based_sampling="yes">
+ <counter_set name="ARM_Cortex-A9_cnt" count="6"/>
+ <category name="Cortex-A9" counter_set="ARM_Cortex-A9_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="ARM_Cortex-A9_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" 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"/>
index 6f2982e26a8c55896d73cfb649e0c363b7dbf7e8..06c1901e5b5492afa157a7c63cef33041c993514 100644 (file)
- <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">
+ <counter_set name="Krait_cnt" count="4"/>
+ <category name="Krait" counter_set="Krait_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="Krait_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" 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"/>
index 695b6b8c990f727cb017d52ac61a6161013b7957..4da4d1d6343142b09e01e605a79f6bd1a00a362c 100644 (file)
- <counter_set name="L2C-310_cntX">
- <counter name="L2C-310_cnt0"/>
- <counter name="L2C-310_cnt1"/>
- </counter_set>
- <category name="L2C-310" counter_set="L2C-310_cntX" per_cpu="no">
+ <counter_set name="L2C-310_cnt" count="2"/>
+ <category name="L2C-310" counter_set="L2C-310_cnt" per_cpu="no">
<event event="0x1" title="L2 Cache" name="CO" description="Eviction, CastOUT, of a line from the L2 cache"/>
<event event="0x2" title="L2 Cache" name="DRH" description="Data read hit"/>
<event event="0x3" title="L2 Cache" name="DRREQ" description="Data read request"/>
index 3f626b347e9be3a469eee258ae5cd2fa6775bec9..b45a12254e3ac0c5ff68a4696a0eb798e4510ae9 100644 (file)
--- a/daemon/events-Linux.xml
+++ b/daemon/events-Linux.xml
<category name="Linux">
- <event counter="Linux_cpuload_user" title="CPU Load" name="User" per_cpu="yes" description="Scheduler CPU Load of User Application"/>
- <event counter="Linux_cpuload_system" title="CPU Load" name="System" per_cpu="yes" description="Scheduler CPU Load of System Behavior"/>
<event counter="Linux_irq_softirq" title="Interrupts" name="SoftIRQ" per_cpu="yes" description="Linux SoftIRQ taken"/>
<event counter="Linux_irq_irq" title="Interrupts" name="IRQ" per_cpu="yes" description="Linux IRQ taken"/>
<event counter="Linux_block_rq_wr" title="Disk IO" name="Write" units="B" description="Disk IO Bytes Written"/>
<event counter="Linux_block_rq_rd" title="Disk IO" name="Read" units="B" description="Disk IO Bytes Read"/>
<event counter="Linux_net_rx" title="Network" name="Receive" units="B" description="Receive network traffic, including effect from Streamline"/>
<event counter="Linux_net_tx" title="Network" name="Transmit" units="B" description="Transmit network traffic, including effect from Streamline"/>
- <event counter="Linux_sched_switch" title="Scheduler" name="Switch" description="Context switch events"/>
+ <event counter="Linux_sched_switch" title="Scheduler" name="Switch" per_cpu="yes" description="Context switch events"/>
<event counter="Linux_meminfo_memused" title="Memory" name="Used" display="maximum" units="B" average_selection="yes" description="Total used memory size"/>
<event counter="Linux_meminfo_memfree" title="Memory" name="Free" display="minimum" units="B" average_selection="yes" description="Available memory size"/>
<event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" display="maximum" units="B" average_selection="yes" description="Memory used by buffers"/>
<event counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" display="maximum" units="Hz" average_selection="yes" description="Frequency setting of the CPU"/>
- <event counter="Linux_power_cpu_idle" title="Power" name="Idle" per_cpu="yes" display="maximum" average_selection="yes" description="CPU Idle State, set the Sample Rate to None to prevent the hrtimer from interrupting the system"/>
+ <event counter="Linux_power_cpu_idle" title="Power" name="Idle" per_cpu="yes" display="maximum" average_selection="yes" description="CPU Idle State + 1, set the Sample Rate to None to prevent the hrtimer from interrupting the system"/>
</category>
index cb1c6b40e194101e6f24a064e1948bba7e62f8e5..6830d46769a8ce480ce8775175ca129b6b146fdb 100644 (file)
- <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">
+ <counter_set name="ARM_Mali-400_VP_cnt" count="2"/>
+ <counter_set name="ARM_Mali-400_FP0_cnt" count="2"/>
+ <counter_set name="ARM_Mali-400_FP1_cnt" count="2"/>
+ <counter_set name="ARM_Mali-400_FP2_cnt" count="2"/>
+ <counter_set name="ARM_Mali-400_FP3_cnt" count="2"/>
+ <counter_set name="ARM_Mali-400_L2_cnt" count="2"/>
+ <counter_set name="ARM_Mali-400_SW_cnt" count="0"/>
+ <counter_set name="ARM_Mali-400_Filmstrip_cnt" count="1"/>
+ <category name="Mali-400-VP" counter_set="ARM_Mali-400_VP_cnt" 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="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">
+ <category name="Mali-400-FP0" counter_set="ARM_Mali-400_FP0_cnt" 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="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">
+ <category name="Mali-400-FP1" counter_set="ARM_Mali-400_FP1_cnt" 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="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">
+ <category name="Mali-400-FP2" counter_set="ARM_Mali-400_FP2_cnt" 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="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">
+ <category name="Mali-400-FP3" counter_set="ARM_Mali-400_FP3_cnt" 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="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">
+ <category name="Mali-400-L2" counter_set="ARM_Mali-400_L2_cnt" 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="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">
+ <category name="ARM_Mali-400_Filmstrip" counter_set="ARM_Mali-400_Filmstrip_cnt" per_cpu="no">
<event event="0x040a" title="ARM_Mali-400_Filmstrip" name="Freq 1:10" description="Scaled framebuffer captures every 10th frame." />
<event event="0x041e" title="ARM_Mali-400_Filmstrip" name="Freq 1:30" description="Scaled framebuffer captures every 30th frame." />
<event event="0x043c" title="ARM_Mali-400_Filmstrip" name="Freq 1:60" description="Scaled framebuffer captures every 60th frame." />
<category name="ARM_Mali-400_Frequency" per_cpu="no">
<event counter="ARM_Mali-400_Frequency" title="Mali GPU Frequency" name="Frequency" display="average" average_selection="yes" units="MHz" description="GPU core frequency."/>
</category>
- <category name="Mali-400-SW" counter_set="ARM_Mali-400_SW_cntX" per_cpu="no">
+ <category name="Mali-400-SW" counter_set="ARM_Mali-400_SW_cnt" 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 -->
index 51ed93766a53e61e8ed28f845d09dfa5d6383413..1642e85c609f976fe86fd52740e6695f6e4e3d21 100644 (file)
- <counter_set name="Scorpion_cntX">
- <counter name="Scorpion_cnt0"/>
- <counter name="Scorpion_cnt1"/>
- <counter name="Scorpion_cnt2"/>
- <counter name="Scorpion_cnt3"/>
- </counter_set>
- <category name="Scorpion" counter_set="Scorpion_cntX" per_cpu="yes">
+ <counter_set name="Scorpion_cnt" count="4"/>
+ <category name="Scorpion" counter_set="Scorpion_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="Scorpion_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" 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"/>
index d3dd4305ef7348ad5dffdabc97e63f0b3e263927..42acc641675287fadd8522787d6fa431f59e0247 100644 (file)
- <counter_set name="ScorpionMP_cntX">
- <counter name="ScorpionMP_cnt0"/>
- <counter name="ScorpionMP_cnt1"/>
- <counter name="ScorpionMP_cnt2"/>
- <counter name="ScorpionMP_cnt3"/>
- </counter_set>
- <category name="ScorpionMP" counter_set="ScorpionMP_cntX" per_cpu="yes">
+ <counter_set name="ScorpionMP_cnt" count="4"/>
+ <category name="ScorpionMP" counter_set="ScorpionMP_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="ScorpionMP_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" 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"/>
diff --git a/daemon/main.cpp b/daemon/main.cpp
index d9729130031715049b025947ea98a41887887832..5bc75ef798d7c731a0ebda74e18f7aff4e3ffc1d 100644 (file)
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h>
+#include <fcntl.h>
+#include <sys/mman.h>
#include "Child.h"
#include "SessionData.h"
#include "OlySocket.h"
}
}
+bool init_module (const char * const location) {
+ bool ret(false);
+ const int fd = open(location, O_RDONLY);
+ if (fd >= 0) {
+ struct stat st;
+ if (fstat(fd, &st) == 0) {
+ void * const p = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (p != MAP_FAILED) {
+ if (syscall(__NR_init_module, p, st.st_size, "") == 0) {
+ ret = true;
+ }
+ munmap(p, st.st_size);
+ }
+ }
+ close(fd);
+ }
+
+ return ret;
+}
+
int setupFilesystem(char* module) {
int retval;
}
// Load driver
- snprintf(command, sizeof(command), "insmod %s >/dev/null 2>&1", location);
- if (system(command) != 0) {
- logg->logMessage("Unable to load gator.ko driver with command: %s", command);
- logg->logError(__FILE__, __LINE__, "Unable to load (insmod) gator.ko driver:\n >>> gator.ko must be built against the current kernel version & configuration\n >>> See dmesg for more details");
- handleException();
+ bool success = init_module(location);
+ if (!success) {
+ logg->logMessage("init_module failed, trying insmod");
+ snprintf(command, sizeof(command), "insmod %s >/dev/null 2>&1", location);
+ if (system(command) != 0) {
+ logg->logMessage("Unable to load gator.ko driver with command: %s", command);
+ logg->logError(__FILE__, __LINE__, "Unable to load (insmod) gator.ko driver:\n >>> gator.ko must be built against the current kernel version & configuration\n >>> See dmesg for more details");
+ handleException();
+ }
}
if (mountGatorFS() == -1) {
umount("/dev/gator");
}
if (driverRunningAtStart == false) {
- if (system("rmmod gator >/dev/null 2>&1") != 0) {
- return -1;
+ if (syscall(__NR_delete_module, "gator", O_NONBLOCK) != 0) {
+ logg->logMessage("delete_module failed, trying rmmod");
+ if (system("rmmod gator >/dev/null 2>&1") != 0) {
+ return -1;
+ }
}
}
snprintf(version_string, sizeof(version_string), "Streamline gatord development version %d", PROTOCOL_VERSION);
}
- while ((c = getopt(argc, argv, "hvp:s:c:e:m:")) != -1) {
+ while ((c = getopt(argc, argv, "hvp:s:c:e:m:o:")) != -1) {
switch(c) {
case 'c':
gSessionData->mConfigurationXMLPath = optarg;
case 's':
gSessionData->mSessionXMLPath = optarg;
break;
+ case 'o':
+ gSessionData->mTargetPath = optarg;
+ break;
case 'h':
case '?':
logg->logError(__FILE__, __LINE__,
"-m module path and filename of gator.ko\n"
"-p port_number port upon which the server listens; default is 8080\n"
"-s session_xml path and filename of a session xml used for local capture\n"
+ "-o apc_dir path and name of the output for a local capture\n"
"-v version information\n"
, version_string);
handleException();
handleException();
}
+ if (gSessionData->mTargetPath != NULL && gSessionData->mSessionXMLPath == NULL) {
+ logg->logError(__FILE__, __LINE__, "Missing -s command line option required for a local capture.");
+ handleException();
+ }
+
if (optind < argc) {
logg->logError(__FILE__, __LINE__, "Unknown argument: %s. Use '-h' for help.", argv[optind]);
handleException();
// Gator data flow: collector -> collector fifo -> sender
int main(int argc, char** argv, char* envp[]) {
+ setsid();
gSessionData = new SessionData(); // Global data class
logg = new Logging(DEBUG); // Set up global thread-safe logging
util = new OlyUtility(); // Set up global utility class
diff --git a/driver/Makefile b/driver/Makefile
index 025dd9e54b87344172120834340921e760587429..6cafecf337daded930b625b1f07a9f578fdfffc6 100644 (file)
--- a/driver/Makefile
+++ b/driver/Makefile
EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT)
endif
+# GATOR_TEST controls whether to include (=1) or exclude (=0) test code.
+GATOR_TEST ?= 0
+EXTRA_CFLAGS += -DGATOR_TEST=$(GATOR_TEST)
+
gator-$(CONFIG_ARM) += gator_events_armv6.o \
gator_events_armv7.o \
gator_events_l2c-310.o \
diff --git a/driver/gator.h b/driver/gator.h
index 6b961099531e540d48608de87ed6e52ca50267c7..5a40e17c21936c2a43844aaf4bcf1fd1fd1227b2 100644 (file)
--- a/driver/gator.h
+++ b/driver/gator.h
#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 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 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
+#define AARCH64 0xd0f
/******************************************************************************
* Filesystem
int gator_events_get_key(void);
extern u32 gator_cpuid(void);
+void gator_backtrace_handler(struct pt_regs * const regs);
+
#endif // GATOR_H_
index b4447891b9fa2524573e80615f62dc147ec06b12..928e252423217554e8a3f6200a538288718d32ac 100644 (file)
--- a/driver/gator_annotate.c
+++ b/driver/gator_annotate.c
@@ -38,26 +38,34 @@ static int annotate_copy(struct file *file, char const __user *buf, size_t count
static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count_orig, loff_t *offset)
{
- int tid, cpu, header_size, available, contiguous, length1, length2, size, count = count_orig & 0x7fffffff;
+ int pid, cpu, header_size, available, contiguous, length1, length2, size, count = count_orig & 0x7fffffff;
- if (*offset)
+ if (*offset) {
return -EINVAL;
+ }
+
+ // Annotation is not supported in interrupt context
+ if (in_interrupt()) {
+ return -EINVAL;
+ }
- if (!collect_annotations)
+ // synchronize between cores and with collect_annotations
+ spin_lock(&annotate_lock);
+
+ if (!collect_annotations) {
// Not collecting annotations, tell the caller everything was written
- return count_orig;
+ size = count_orig;
+ goto annotate_write_out;
+ }
cpu = 0; // Annotation only uses a single per-cpu buffer as the data must be in order to the engine
- if (file == NULL) {
- tid = -1; // set the thread id to the kernel thread
+ if (current == NULL) {
+ pid = 0;
} else {
- tid = current->pid;
+ pid = current->pid;
}
- // synchronize between cores
- spin_lock(&annotate_lock);
-
// determine total size of the payload
header_size = MAXSIZE_PACK32 * 3 + MAXSIZE_PACK64;
available = buffer_bytes_available(cpu, ANNOTATE_BUF) - header_size;
}
// synchronize shared variables annotateBuf and annotatePos
- if (collect_annotations && per_cpu(gator_buffer, cpu)[ANNOTATE_BUF]) {
+ if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF]) {
gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id());
- gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, tid);
+ gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, gator_get_time());
gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, size);
spin_lock(&annotate_lock);
if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF] && buffer_check_space(cpu, ANNOTATE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
- uint32_t tid = current->pid;
+ uint32_t pid = current->pid;
gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id());
- gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, tid);
+ gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); // time
gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); // size
}
static void gator_annotate_stop(void)
{
+ // the spinlock here will ensure that when this function exits, we are not in the middle of an annotation
+ spin_lock(&annotate_lock);
collect_annotations = false;
+ spin_unlock(&annotate_lock);
}
index ffab08795b770237b8cc89bc436b5f70fe3ca096..bc68fa807e05592add4c96d7da245cd94adc6810 100644 (file)
*
*/
-static void kannotate_write(char* ptr, unsigned int size)
+#define ESCAPE_CODE 0x1c
+#define STRING_ANNOTATION 0x03
+#define VISUAL_ANNOTATION 0x04
+#define MARKER_ANNOTATION 0x05
+
+static void kannotate_write(const char* ptr, unsigned int size)
{
int retval;
int pos = 0;
loff_t offset = 0;
while (pos < size) {
- retval = annotate_write(NULL, &ptr[pos], size - pos, &offset);
- if (retval < 0) {
- printk(KERN_WARNING "gator: kannotate_write failed with return value %d\n", retval);
- return;
- }
- pos += retval;
+ retval = annotate_write(NULL, &ptr[pos], size - pos, &offset);
+ if (retval < 0) {
+ printk(KERN_WARNING "gator: kannotate_write failed with return value %d\n", retval);
+ return;
+ }
+ pos += retval;
}
}
+static void gator_annotate_code(char code)
+{
+ int header = ESCAPE_CODE | (code << 8);
+ kannotate_write((char*)&header, sizeof(header));
+}
+
+static void gator_annotate_code_str(char code, const char* string)
+{
+ int str_size = strlen(string) & 0xffff;
+ int header = ESCAPE_CODE | (code << 8) | (str_size << 16);
+ kannotate_write((char*)&header, sizeof(header));
+ kannotate_write(string, str_size);
+}
+
+static void gator_annotate_code_color(char code, int color)
+{
+ long long header = (ESCAPE_CODE | (code << 8) | 0x00040000 | ((long long)color << 32));
+ kannotate_write((char*)&header, sizeof(header));
+}
+
+static void gator_annotate_code_color_str(char code, int color, const char* string)
+{
+ int str_size = (strlen(string) + 4) & 0xffff;
+ long long header = ESCAPE_CODE | (code << 8) | (str_size << 16) | ((long long)color << 32);
+ kannotate_write((char*)&header, sizeof(header));
+ kannotate_write(string, str_size - 4);
+}
+
// String annotation
-void gator_annotate(char* string)
+void gator_annotate(const char* string)
{
- kannotate_write(string, strlen(string) + 1);
+ gator_annotate_code_str(STRING_ANNOTATION, string);
}
EXPORT_SYMBOL(gator_annotate);
// String annotation with color
-void gator_annotate_color(int color, char* string)
+void gator_annotate_color(int color, const char* string)
{
- kannotate_write((char*)&color, sizeof(color));
- kannotate_write(string, strlen(string) + 1);
+ gator_annotate_code_color_str(STRING_ANNOTATION, color, string);
}
EXPORT_SYMBOL(gator_annotate_color);
// Terminate an annotation
void gator_annotate_end(void)
{
- char nul = 0;
- kannotate_write(&nul, sizeof(nul));
+ gator_annotate_code(STRING_ANNOTATION);
}
EXPORT_SYMBOL(gator_annotate_end);
// Image annotation with optional string
-void gator_annotate_visual(char* data, unsigned int length, char* string)
+void gator_annotate_visual(const char* data, unsigned int length, const char* string)
{
- long long visual_annotation = 0x011c | (strlen(string) << 16) | ((long long)length << 32);
- kannotate_write((char*)&visual_annotation, 8);
- kannotate_write(string, strlen(string));
+ int str_size = strlen(string) & 0xffff;
+ int visual_annotation = ESCAPE_CODE | (VISUAL_ANNOTATION << 8) | (str_size << 16);
+ kannotate_write((char*)&visual_annotation, sizeof(visual_annotation));
+ kannotate_write(string, str_size);
+ kannotate_write((char*)&length, sizeof(length));
kannotate_write(data, length);
}
EXPORT_SYMBOL(gator_annotate_visual);
// Marker annotation
void gator_annotate_marker(void)
{
- int marker_annotation = 0x00021c;
- kannotate_write((char*)&marker_annotation, 3);
+ gator_annotate_code(MARKER_ANNOTATION);
}
EXPORT_SYMBOL(gator_annotate_marker);
// Marker annotation with a string
-void gator_annotate_marker_str(char* string)
+void gator_annotate_marker_str(const char* string)
{
- int marker_annotation = 0x021c;
- kannotate_write((char*)&marker_annotation, 2);
- kannotate_write(string, strlen(string) + 1);
+ gator_annotate_code_str(MARKER_ANNOTATION, string);
}
EXPORT_SYMBOL(gator_annotate_marker_str);
// Marker annotation with a color
void gator_annotate_marker_color(int color)
{
- long long marker_annotation = (0x021c | ((long long)color << 16)) & 0x0000ffffffffffffLL;
- kannotate_write((char*)&marker_annotation, 7);
+ gator_annotate_code_color(MARKER_ANNOTATION, color);
}
EXPORT_SYMBOL(gator_annotate_marker_color);
-// Marker annotationw ith a string and color
-void gator_annotate_marker_color_str(int color, char* string)
+// Marker annotation with a string and color
+void gator_annotate_marker_color_str(int color, const char* string)
{
- long long marker_annotation = 0x021c | ((long long)color << 16);
- kannotate_write((char*)&marker_annotation, 6);
- kannotate_write(string, strlen(string) + 1);
+ gator_annotate_code_color_str(MARKER_ANNOTATION, color, string);
}
EXPORT_SYMBOL(gator_annotate_marker_color_str);
index 50783d69594e1fadcecde00839cd715d37d13b46..2173d8a6ea5ab7823ca3134723995aa78067d22b 100644 (file)
--- a/driver/gator_backtrace.c
+++ b/driver/gator_backtrace.c
unsigned long lr;
};
-static void arm_backtrace_eabi(int cpu, int buftype, struct pt_regs * const regs, unsigned int depth)
+static void arm_backtrace_eabi(int cpu, struct pt_regs * const regs, unsigned int depth)
{
#if defined(__arm__)
struct frame_tail_eabi *tail;
}
/* entry preamble may not have executed */
- gator_add_trace(cpu, buftype, lr);
+ gator_add_trace(cpu, lr);
/* check tail is valid */
if (fp == 0 || fp < sp) {
ptrtail = &buftail;
lr = ptrtail[0].lr;
- gator_add_trace(cpu, buftype, lr);
+ gator_add_trace(cpu, lr);
/* frame pointers should progress back up the stack, towards higher addresses */
next = (struct frame_tail_eabi *)(lr - 4);
@@ -69,16 +69,16 @@ static void arm_backtrace_eabi(int cpu, int buftype, struct pt_regs * const regs
}
#if defined(__arm__)
-static DEFINE_PER_CPU(int, backtrace_buffer);
static int report_trace(struct stackframe *frame, void *d)
{
struct module *mod;
- unsigned int *depth = d, addr = frame->pc, cookie = NO_COOKIE, cpu = smp_processor_id();
+ unsigned int *depth = d, cookie = NO_COOKIE, cpu = smp_processor_id();
+ unsigned long addr = frame->pc;
if (*depth) {
mod = __module_address(addr);
if (mod) {
- cookie = get_cookie(cpu, per_cpu(backtrace_buffer, cpu), current, NULL, mod, true);
+ cookie = get_cookie(cpu, current, NULL, mod, true);
addr = addr - (unsigned long)mod->module_core;
}
marshal_backtrace(addr & ~1, cookie);
// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile
// #define GATOR_KERNEL_STACK_UNWINDING
-static void kernel_backtrace(int cpu, int buftype, struct pt_regs * const regs)
+static void kernel_backtrace(int cpu, struct pt_regs * const regs)
{
#if defined(__arm__)
#ifdef GATOR_KERNEL_STACK_UNWINDING
frame.sp = regs->ARM_sp;
frame.lr = regs->ARM_lr;
frame.pc = regs->ARM_pc;
- per_cpu(backtrace_buffer, cpu) = buftype;
walk_stackframe(&frame, report_trace, &depth);
#else
marshal_backtrace(PC_REG & ~1, NO_COOKIE);
diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c
index d7d8e8499f18779add01bf062f57d3ef7904c262..b2ed68665321816ba08e1f4bbc2ee53ba87d2557 100644 (file)
--- a/driver/gator_cookies.c
+++ b/driver/gator_cookies.c
#define MAX_COLLISIONS 2
static uint32_t *gator_crc32_table;
-static uint32_t translate_buffer_mask;
+static unsigned int translate_buffer_mask;
static DEFINE_PER_CPU(char *, translate_text);
static DEFINE_PER_CPU(uint32_t, cookie_next_key);
static DEFINE_PER_CPU(uint32_t *, cookie_values);
static DEFINE_PER_CPU(int, translate_buffer_read);
static DEFINE_PER_CPU(int, translate_buffer_write);
-static DEFINE_PER_CPU(unsigned int *, translate_buffer);
+static DEFINE_PER_CPU(void * *, translate_buffer);
-static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt);
+static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt);
static void wq_cookie_handler(struct work_struct *unused);
DECLARE_WORK(cookie_work, wq_cookie_handler);
static struct timer_list app_process_wake_up_timer;
static uint32_t gator_chksum_crc32(char *data)
{
- register unsigned long crc;
- unsigned char *block = data;
- int i, length = strlen(data);
+ register unsigned long crc;
+ unsigned char *block = data;
+ int i, length = strlen(data);
- crc = 0xFFFFFFFF;
- for (i = 0; i < length; i++) {
- crc = ((crc >> 8) & 0x00FFFFFF) ^ gator_crc32_table[(crc ^ *block++) & 0xFF];
- }
+ crc = 0xFFFFFFFF;
+ for (i = 0; i < length; i++) {
+ crc = ((crc >> 8) & 0x00FFFFFF) ^ gator_crc32_table[(crc ^ *block++) & 0xFF];
+ }
- return (crc ^ 0xFFFFFFFF);
+ return (crc ^ 0xFFFFFFFF);
}
/*
values[0] = value;
}
-static void translate_buffer_write_int(int cpu, unsigned int x)
+static void translate_buffer_write_ptr(int cpu, void * x)
{
per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x;
per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask;
}
-static unsigned int translate_buffer_read_int(int cpu)
+static void * translate_buffer_read_ptr(int cpu)
{
- unsigned int value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++];
+ void * value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++];
per_cpu(translate_buffer_read, cpu) &= translate_buffer_mask;
return value;
}
if (gator_started != 0) {
commit = per_cpu(translate_buffer_write, cpu);
while (per_cpu(translate_buffer_read, cpu) != commit) {
- task = (struct task_struct *)translate_buffer_read_int(cpu);
- vma = (struct vm_area_struct *)translate_buffer_read_int(cpu);
- cookie = get_cookie(cpu, BACKTRACE_BUF, task, vma, NULL, false);
+ task = (struct task_struct *)translate_buffer_read_ptr(cpu);
+ vma = (struct vm_area_struct *)translate_buffer_read_ptr(cpu);
+ cookie = get_cookie(cpu, task, vma, NULL, false);
}
}
@@ -163,13 +163,13 @@ static int translate_app_process(char** text, int cpu, struct task_struct * task
// Check if already in buffer
ptr = per_cpu(translate_buffer_read, cpu);
while (ptr != per_cpu(translate_buffer_write, cpu)) {
- if (per_cpu(translate_buffer, cpu)[ptr] == (int)task)
+ if (per_cpu(translate_buffer, cpu)[ptr] == (void *)task)
goto out;
ptr = (ptr + 2) & translate_buffer_mask;
}
- translate_buffer_write_int(cpu, (unsigned int)task);
- translate_buffer_write_int(cpu, (unsigned int)vma);
+ translate_buffer_write_ptr(cpu, (void *)task);
+ translate_buffer_write_ptr(cpu, (void *)vma);
mod_timer(&app_process_wake_up_timer, jiffies + 1);
goto out;
return retval;
}
-static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt)
+static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt)
{
unsigned long flags, cookie;
struct path *path;
@@ -271,7 +271,7 @@ static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task
return cookie;
}
-static int get_exec_cookie(int cpu, int buftype, struct task_struct *task)
+static int get_exec_cookie(int cpu, struct task_struct *task)
{
unsigned long cookie = NO_COOKIE;
struct mm_struct *mm = task->mm;
continue;
if (!(vma->vm_flags & VM_EXECUTABLE))
continue;
- cookie = get_cookie(cpu, buftype, task, vma, NULL, true);
+ cookie = get_cookie(cpu, task, vma, NULL, true);
break;
}
return cookie;
}
-static unsigned long get_address_cookie(int cpu, int buftype, struct task_struct *task, unsigned long addr, off_t *offset)
+static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsigned long addr, off_t *offset)
{
unsigned long cookie = NO_COOKIE;
struct mm_struct *mm = task->mm;
@@ -307,7 +307,7 @@ static unsigned long get_address_cookie(int cpu, int buftype, struct task_struct
continue;
if (vma->vm_file) {
- cookie = get_cookie(cpu, buftype, task, vma, NULL, true);
+ cookie = get_cookie(cpu, task, vma, NULL, true);
*offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start;
} else {
/* must be an anonymous map */
}
memset(per_cpu(cookie_values, cpu), 0, size);
- per_cpu(translate_buffer, cpu) = (unsigned int *)kmalloc(translate_buffer_size, GFP_KERNEL);
+ per_cpu(translate_buffer, cpu) = (void * *)kmalloc(translate_buffer_size, GFP_KERNEL);
if (!per_cpu(translate_buffer, cpu)) {
err = -ENOMEM;
goto cookie_setup_error;
diff --git a/driver/gator_ebs.c b/driver/gator_ebs.c
--- a/driver/gator_ebs.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/**
- * 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
- * published by the Free Software Foundation.
- *
- */
-
-#if defined(__arm__) && (GATOR_PERF_PMU_SUPPORT)
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-
-#include <asm/pmu.h>
-
-static DEFINE_MUTEX(perf_mutex);
-
-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_attr *, pevent_attr);
-static DEFINE_PER_CPU(int, key);
-
-#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
-{
- int cpu = smp_processor_id();
-
- if (event != per_cpu(pevent_ebs, cpu))
- return;
-
- // Output backtrace
- gator_add_sample(cpu, BACKTRACE_BUF, regs);
-
- // Collect counters
- collect_counters();
-}
-
-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 = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu), cpu, 0, ebs_overflow_handler);
-#else
- ev = 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(pevent_ebs, cpu) = ev;
-}
-
-static void gator_event_sampling_offline_dispatch(int cpu)
-{
- struct perf_event * pe = NULL;
-
- mutex_lock(&perf_mutex);
- if (per_cpu(pevent_ebs, cpu)) {
- pe = per_cpu(pevent_ebs, cpu);
- per_cpu(pevent_ebs, cpu) = NULL;
- }
- mutex_unlock(&perf_mutex);
-
- if (pe) {
- perf_event_release_kernel(pe);
- }
-}
-
-static int gator_event_sampling_start(void)
-{
- int cnt, event = 0, count = 0, ebs_key = 0, cpu;
-
- for_each_present_cpu(cpu) {
- per_cpu(pevent_ebs, cpu) = NULL;
- per_cpu(pevent_attr, cpu) = NULL;
- }
-
- event_based_sampling = false;
- 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 (!event_based_sampling)
- return 0;
-
- 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;
-
- 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;
- }
-
- per_cpu(key, cpu) = ebs_key;
- }
-
- return 0;
-}
-
-static void gator_event_sampling_stop(void)
-{
- 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;
- }
- }
-}
-
-#else
-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
index a8b811413f3080974708d0607fdbb889e1b0c10b..b18c3ca5c1198cc0f88a26ab6acc3c886deb1b6b 100644 (file)
static ulong block_rq_rd_enabled;
static ulong block_rq_wr_key;
static ulong block_rq_rd_key;
-static DEFINE_PER_CPU(int[BLOCK_TOTAL], blockCnt);
-static DEFINE_PER_CPU(int[BLOCK_TOTAL * 4], blockGet);
-static DEFINE_PER_CPU(bool, new_data_avail);
+static atomic_t blockCnt[BLOCK_TOTAL];
+static int blockGet[BLOCK_TOTAL * 4];
GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct request *rq))
{
unsigned long flags;
int write, size;
- int cpu = smp_processor_id();
if (!rq)
return;
@@ -47,13 +45,16 @@ GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct r
// disable interrupts to synchronize with gator_events_block_read()
// spinlocks not needed since percpu buffers are used
local_irq_save(flags);
- if (write)
- per_cpu(blockCnt, cpu)[BLOCK_RQ_WR] += size;
- else
- per_cpu(blockCnt, cpu)[BLOCK_RQ_RD] += size;
+ if (write) {
+ if (block_rq_wr_enabled) {
+ atomic_add(size, &blockCnt[BLOCK_RQ_WR]);
+ }
+ } else {
+ if (block_rq_rd_enabled) {
+ atomic_add(size, &blockCnt[BLOCK_RQ_RD]);
+ }
+ }
local_irq_restore(flags);
-
- per_cpu(new_data_avail, cpu) = true;
}
static int gator_events_block_create_files(struct super_block *sb, struct dentry *root)
static int gator_events_block_start(void)
{
- int cpu;
-
- for_each_present_cpu(cpu)
- per_cpu(new_data_avail, cpu) = true;
-
// register tracepoints
if (block_rq_wr_enabled || block_rq_rd_enabled)
if (GATOR_REGISTER_TRACE(block_rq_complete))
static int gator_events_block_read(int **buffer)
{
- unsigned long flags;
- int len, value, cpu, data = 0;
- cpu = smp_processor_id();
+ int len, value, data = 0;
- if (per_cpu(new_data_avail, cpu) == false)
+ if (smp_processor_id() != 0) {
return 0;
-
- per_cpu(new_data_avail, cpu) = false;
+ }
len = 0;
- if (block_rq_wr_enabled) {
- local_irq_save(flags);
- value = per_cpu(blockCnt, cpu)[BLOCK_RQ_WR];
- per_cpu(blockCnt, cpu)[BLOCK_RQ_WR] = 0;
- local_irq_restore(flags);
- per_cpu(blockGet, cpu)[len++] = block_rq_wr_key;
- per_cpu(blockGet, cpu)[len++] = 0; // indicates to Streamline that value bytes were written now, not since the last message
- per_cpu(blockGet, cpu)[len++] = block_rq_wr_key;
- per_cpu(blockGet, cpu)[len++] = value;
+ if (block_rq_wr_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_WR])) > 0) {
+ atomic_sub(value, &blockCnt[BLOCK_RQ_WR]);
+ blockGet[len++] = block_rq_wr_key;
+ blockGet[len++] = 0; // indicates to Streamline that value bytes were written now, not since the last message
+ blockGet[len++] = block_rq_wr_key;
+ blockGet[len++] = value;
data += value;
}
- if (block_rq_rd_enabled) {
- local_irq_save(flags);
- value = per_cpu(blockCnt, cpu)[BLOCK_RQ_RD];
- per_cpu(blockCnt, cpu)[BLOCK_RQ_RD] = 0;
- local_irq_restore(flags);
- per_cpu(blockGet, cpu)[len++] = block_rq_rd_key;
- per_cpu(blockGet, cpu)[len++] = 0; // indicates to Streamline that value bytes were read now, not since the last message
- per_cpu(blockGet, cpu)[len++] = block_rq_rd_key;
- per_cpu(blockGet, cpu)[len++] = value;
+ if (block_rq_rd_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_RD])) > 0) {
+ atomic_sub(value, &blockCnt[BLOCK_RQ_RD]);
+ blockGet[len++] = block_rq_rd_key;
+ blockGet[len++] = 0; // indicates to Streamline that value bytes were read now, not since the last message
+ blockGet[len++] = block_rq_rd_key;
+ blockGet[len++] = value;
data += value;
}
- if (data != 0)
- per_cpu(new_data_avail, cpu) = true;
-
if (buffer)
- *buffer = per_cpu(blockGet, cpu);
+ *buffer = blockGet;
return len;
}
index 38d5b3d94ae69112d8e9ff2763252d13ea568e34..65eeb4f37d94af578040dafac7b5e2337eb61c04 100644 (file)
#include "gator_events_mali_common.h"
#include "gator_events_mali_400.h"
-#if !defined(GATOR_MALI_INTERFACE_STYLE)
-/*
- * At the moment, we only have users with the old style interface, so
- * make our life easier by making it the default...
- */
-#define GATOR_MALI_INTERFACE_STYLE (2)
-#endif
-
/*
* There are (currently) three different variants of the comms between gator and Mali:
* 1 (deprecated): No software counter support
switch(event) {
case COUNTER_FILMSTRIP:
- snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip", mali_name);
+ snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip_cnt0", mali_name);
break;
case COUNTER_FREQUENCY:
index b784ae97877d71847cc8705c0c71287c1ab5247f..a09757eb502449ff95919aae52e2a5add0684668 100644 (file)
-/*
- * This confidential and proprietary software may be used only as
- * authorised by a licensing agreement from ARM Limited
- * (C) COPYRIGHT 2011-2012 ARM Limited
- * ALL RIGHTS RESERVED
- * The entire notice above must be reproduced on all authorised
- * copies and copies may only be made to the extent permitted
- * by a licensing agreement from ARM Limited.
+/**
+ * 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.
+ *
*/
/*
index 2dd9ad6eb6c3df27854e984277eefdcaf4f8b836..62e441c037d2953fd90f1fc4a2dfa7f4bb532de7 100644 (file)
-/*
- * This confidential and proprietary software may be used only as
- * authorised by a licensing agreement from ARM Limited
- * (C) COPYRIGHT 2011-2012 ARM Limited
- * ALL RIGHTS RESERVED
- * The entire notice above must be reproduced on all authorised
- * copies and copies may only be made to the extent permitted
- * by a licensing agreement from ARM Limited.
+/**
+ * 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
+ * published by the Free Software Foundation.
+ *
*/
#include "gator_events_mali_common.h"
index cb851d542f47f877764aa31c6d58ac2739b77269..2c9457f118991f0bf635c33f8593c077defea50c 100644 (file)
-/*
- * This confidential and proprietary software may be used only as
- * authorised by a licensing agreement from ARM Limited
- * (C) COPYRIGHT 2011-2012 ARM Limited
- * ALL RIGHTS RESERVED
- * The entire notice above must be reproduced on all authorised
- * copies and copies may only be made to the extent permitted
- * by a licensing agreement from ARM Limited.
+/**
+ * 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
+ * published by the Free Software Foundation.
+ *
*/
+
#if !defined(GATOR_EVENTS_MALI_COMMON_H)
#define GATOR_EVENTS_MALI_COMMON_H
unsigned long enabled; /* counter enable state */
} mali_counter;
+/*
+ * Mali-400
+ */
typedef void mali_profiling_set_event_type(unsigned int, unsigned int);
typedef void mali_osk_fb_control_set_type(unsigned int, unsigned int);
typedef void mali_profiling_control_type(unsigned int, unsigned int);
index 79af7648de8cc51106fff0445eae5b44c6bb20c9..f8f868ea8c60d93e573e281285e54b01f799c185 100644 (file)
-/*
- * This confidential and proprietary software may be used only as
- * authorised by a licensing agreement from ARM Limited
- * (C) COPYRIGHT 2011 ARM Limited
- * ALL RIGHTS RESERVED
- * The entire notice above must be reproduced on all authorised
- * copies and copies may only be made to the extent permitted
- * by a licensing agreement from ARM Limited.
+/**
+ * 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"
index 12ffebcaf26aba9806e83bb8c16503e21dec9e9f..854d02df5d9a041483550b15f0dc17c64dc43aac 100644 (file)
-/*
- * This confidential and proprietary software may be used only as
- * authorised by a licensing agreement from ARM Limited
- * (C) COPYRIGHT 2011-2012 ARM Limited
- * ALL RIGHTS RESERVED
- * The entire notice above must be reproduced on all authorised
- * copies and copies may only be made to the extent permitted
- * by a licensing agreement from ARM Limited.
+/**
+ * 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
+ * published by the Free Software Foundation.
+ *
*/
#include "gator.h"
#include "gator_events_mali_common.h"
+/*
+ * Mali-T6xx
+ */
+typedef struct kbase_device *kbase_find_device_type(int);
+typedef kbase_context *kbase_create_context_type(kbase_device*);
+typedef void kbase_destroy_context_type(kbase_context *);
+typedef void *kbase_va_alloc_type(kbase_context *, u32);
+typedef void kbase_va_free_type(kbase_context *, void *);
+typedef mali_error kbase_instr_hwcnt_enable_type(kbase_context *, kbase_uk_hwcnt_setup *);
+typedef mali_error kbase_instr_hwcnt_disable_type(kbase_context *);
+typedef mali_error kbase_instr_hwcnt_clear_type(kbase_context *);
+typedef mali_error kbase_instr_hwcnt_dump_irq_type(kbase_context *);
+typedef mali_bool kbase_instr_hwcnt_dump_complete_type(kbase_context *, mali_bool *);
+
+static kbase_find_device_type * kbase_find_device_symbol;
+static kbase_create_context_type * kbase_create_context_symbol;
+static kbase_va_alloc_type * kbase_va_alloc_symbol;
+static kbase_instr_hwcnt_enable_type * kbase_instr_hwcnt_enable_symbol;
+static kbase_instr_hwcnt_clear_type * kbase_instr_hwcnt_clear_symbol;
+static kbase_instr_hwcnt_dump_irq_type * kbase_instr_hwcnt_dump_irq_symbol;
+static kbase_instr_hwcnt_dump_complete_type * kbase_instr_hwcnt_dump_complete_symbol;
+static kbase_instr_hwcnt_disable_type * kbase_instr_hwcnt_disable_symbol;
+static kbase_va_free_type * kbase_va_free_symbol;
+static kbase_destroy_context_type * kbase_destroy_context_symbol;
+
+/** The interval between reads, in ns. */
+static const int READ_INTERVAL_NSEC = 1000000;
+
+
+#if GATOR_TEST
+#include "gator_events_mali_t6xx_hw_test.c"
+#endif
+
/* Blocks for HW counters */
enum
{
static kbase_context *kbcontext = NULL;
static struct kbase_device *kbdevice = NULL;
-extern struct kbase_device *kbase_find_device(int minor);
+/*
+ * The following function has no external prototype in older DDK revisions. When the DDK
+ * is updated then this should be removed.
+ */
+struct kbase_device *kbase_find_device(int minor);
+
static volatile bool kbase_device_busy = false;
static unsigned int num_hardware_counters_enabled;
*/
static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2];
+#define SYMBOL_GET(FUNCTION, ERROR_COUNT) \
+ if(FUNCTION ## _symbol) \
+ { \
+ printk("gator: mali " #FUNCTION " symbol was already registered\n"); \
+ (ERROR_COUNT)++; \
+ } \
+ else \
+ { \
+ FUNCTION ## _symbol = symbol_get(FUNCTION); \
+ if(! FUNCTION ## _symbol) \
+ { \
+ printk("gator: mali online " #FUNCTION " symbol not found\n"); \
+ (ERROR_COUNT)++; \
+ } \
+ }
+
+#define SYMBOL_CLEANUP(FUNCTION) \
+ if(FUNCTION ## _symbol) \
+ { \
+ symbol_put(FUNCTION); \
+ FUNCTION ## _symbol = NULL; \
+ }
+
+/**
+ * Execute symbol_get for all the Mali symbols and check for success.
+ * @return the number of symbols not loaded.
+ */
+static int init_symbols(void)
+{
+ int error_count = 0;
+ SYMBOL_GET(kbase_find_device, error_count);
+ SYMBOL_GET(kbase_create_context, error_count);
+ SYMBOL_GET(kbase_va_alloc, error_count);
+ SYMBOL_GET(kbase_instr_hwcnt_enable, error_count);
+ SYMBOL_GET(kbase_instr_hwcnt_clear, error_count);
+ SYMBOL_GET(kbase_instr_hwcnt_dump_irq, error_count);
+ SYMBOL_GET(kbase_instr_hwcnt_dump_complete, error_count);
+ SYMBOL_GET(kbase_instr_hwcnt_disable, error_count);
+ SYMBOL_GET(kbase_va_free, error_count);
+ SYMBOL_GET(kbase_destroy_context, error_count);
+
+ return error_count;
+}
+
+/**
+ * Execute symbol_put for all the registered Mali symbols.
+ */
+static void clean_symbols(void)
+{
+ SYMBOL_CLEANUP(kbase_find_device);
+ SYMBOL_CLEANUP(kbase_create_context);
+ SYMBOL_CLEANUP(kbase_va_alloc);
+ SYMBOL_CLEANUP(kbase_instr_hwcnt_enable);
+ SYMBOL_CLEANUP(kbase_instr_hwcnt_clear);
+ SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_irq);
+ SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_complete);
+ SYMBOL_CLEANUP(kbase_instr_hwcnt_disable);
+ SYMBOL_CLEANUP(kbase_va_free);
+ SYMBOL_CLEANUP(kbase_destroy_context);
+}
+
+/**
+ * Determines whether a read should take place
+ * @param current_time The current time, obtained from getnstimeofday()
+ * @param prev_time_s The number of seconds at the previous read attempt.
+ * @param next_read_time_ns The time (in ns) when the next read should be allowed.
+ *
+ * Note that this function has been separated out here to allow it to be tested.
+ */
+static int is_read_scheduled(const struct timespec *current_time, u32* prev_time_s, s32* next_read_time_ns)
+{
+ /* If the current ns count rolls over a second, roll the next read time too. */
+ if(current_time->tv_sec != *prev_time_s)
+ {
+ *next_read_time_ns = *next_read_time_ns - NSEC_PER_SEC;
+ }
+
+ /* Abort the read if the next read time has not arrived. */
+ if(current_time->tv_nsec < *next_read_time_ns)
+ {
+ return 0;
+ }
+
+ /* Set the next read some fixed time after this one, and update the read timestamp. */
+ *next_read_time_ns = current_time->tv_nsec + READ_INTERVAL_NSEC;
+
+ *prev_time_s = current_time->tv_sec;
+ return 1;
+}
+
static int start(void)
{
kbase_uk_hwcnt_setup setup;
/* Create a kbase context for HW counters */
if (num_hardware_counters_enabled > 0)
{
- kbdevice = kbase_find_device(-1);
-
- if (kbcontext)
- return -1;
-
- kbcontext = kbase_create_context(kbdevice);
+ if(init_symbols() > 0)
+ {
+ clean_symbols();
+ /* No Mali driver code entrypoints found - not a fault. */
+ return 0;
+ }
+
+ kbdevice = kbase_find_device_symbol(-1);
+
+ /* If we already got a context, fail */
+ if (kbcontext) {
+ pr_debug("gator: Mali-T6xx: error context already present\n");
+ goto out;
+ }
+
+ /* kbcontext will only be valid after all the Mali symbols are loaded successfully */
+ kbcontext = kbase_create_context_symbol(kbdevice);
if (!kbcontext)
{
pr_debug("gator: Mali-T6xx: error creating kbase context\n");
* * number of bytes per counter (always 4 in midgard)
* For a Mali-T6xx with a single core group = 1 * 8 * 64 * 4
*/
- kernel_dump_buffer = kbase_va_alloc(kbcontext, 2048);
+ kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 2048);
if (!kernel_dump_buffer)
{
pr_debug("gator: Mali-T6xx: error trying to allocate va\n");
setup.l3_cache_bm = 0;
/* Use kbase API to enable hardware counters and provide dump buffer */
- err = kbase_instr_hwcnt_enable(kbcontext, &setup);
+ err = kbase_instr_hwcnt_enable_symbol(kbcontext, &setup);
if (err != MALI_ERROR_NONE)
{
pr_debug("gator: Mali-T6xx: can't setup hardware counters\n");
goto free_buffer;
}
pr_debug("gator: Mali-T6xx: hardware counters enabled\n");
- kbase_instr_hwcnt_clear(kbcontext);
+ kbase_instr_hwcnt_clear_symbol(kbcontext);
pr_debug("gator: Mali-T6xx: hardware counters cleared \n");
kbase_device_busy = false;
return 0;
free_buffer:
- kbase_va_free(kbcontext, kernel_dump_buffer);
+ kbase_va_free_symbol(kbcontext, kernel_dump_buffer);
+
destroy_context:
- kbase_destroy_context(kbcontext);
+ kbase_destroy_context_symbol(kbcontext);
+
out:
+ clean_symbols();
return -1;
}
temp_kbcontext = kbcontext;
kbcontext = NULL;
- kbase_instr_hwcnt_disable(temp_kbcontext);
- kbase_va_free(temp_kbcontext, kernel_dump_buffer);
- kbase_destroy_context(temp_kbcontext);
+ kbase_instr_hwcnt_disable_symbol(temp_kbcontext);
+ kbase_va_free_symbol(temp_kbcontext, kernel_dump_buffer);
+ kbase_destroy_context_symbol(temp_kbcontext);
+
pr_debug("gator: Mali-T6xx: hardware counters stopped\n");
+
+ clean_symbols();
}
}
u32 value = 0;
mali_bool success;
+ struct timespec current_time;
+ static u32 prev_time_s = 0;
+ static s32 next_read_time_ns = 0;
+
if (smp_processor_id()!=0)
{
return 0;
}
+ getnstimeofday(¤t_time);
+
+ /*
+ * Discard reads unless a respectable time has passed. This reduces the load on the GPU without sacrificing
+ * accuracy on the Streamline display.
+ */
+ if(!is_read_scheduled(¤t_time, &prev_time_s, &next_read_time_ns))
+ {
+ return 0;
+ }
+
/*
* Report the HW counters
* Only process hardware counters if at least one of the hardware counters is enabled.
return -1;
}
- // TODO: SYMBOL_GET (all kbase functions)
- if (kbase_instr_hwcnt_dump_complete(kbcontext, &success) == MALI_TRUE)
+ /* Mali symbols can be called safely since a kbcontext is valid */
+ if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE)
{
kbase_device_busy = false;
if (! kbase_device_busy)
{
kbase_device_busy = true;
- kbase_instr_hwcnt_dump_irq(kbcontext);
+ kbase_instr_hwcnt_dump_irq_symbol(kbcontext);
}
}
return 0;
}
-
static struct gator_interface gator_events_mali_t6xx_interface = {
.create_files = create_files,
.start = start,
{
pr_debug("gator: Mali-T6xx: sw_counters init\n");
+#if GATOR_TEST
+ test_all_is_read_scheduled();
+#endif
+
gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS);
return gator_events_install(&gator_events_mali_t6xx_interface);
diff --git a/driver/gator_events_mali_t6xx_hw_test.c b/driver/gator_events_mali_t6xx_hw_test.c
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * 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
+ * published by the Free Software Foundation.
+ *
+ */
+
+/**
+ * Test functions for mali_t600_hw code.
+ */
+
+static int is_read_scheduled(const struct timespec *current_time, u32* prev_time_s, s32* next_read_time_ns);
+
+static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int expected_result, s32 expected_next_ns)
+{
+ struct timespec current_time;
+ u32 prev_time_s = prev_s;
+ s32 next_read_time_ns = next_ns;
+
+ current_time.tv_sec = s;
+ current_time.tv_nsec = ns;
+
+ if(is_read_scheduled(¤t_time, &prev_time_s, &next_read_time_ns) != expected_result)
+ {
+ printk("Failed do_read(%u, %u, %u, %d): expected %d\n", s, ns, prev_s, next_ns, expected_result);
+ return 0;
+ }
+
+ if(next_read_time_ns != expected_next_ns)
+ {
+ printk("Failed: next_read_ns expected=%d, actual=%d\n", expected_next_ns, next_read_time_ns);
+ return 0;
+ }
+
+ return 1;
+}
+
+static void test_all_is_read_scheduled(void)
+{
+ const int HIGHEST_NS = 999999999;
+ int n_tests_passed = 0;
+
+ printk("gator: running tests on %s\n", __FILE__);
+
+ n_tests_passed += test_is_read_scheduled(0,0,0,0, 1, READ_INTERVAL_NSEC); /* Null time */
+ n_tests_passed += test_is_read_scheduled(100,1000,0,0, 1, READ_INTERVAL_NSEC + 1000); /* Initial values */
+
+ n_tests_passed += test_is_read_scheduled(100, HIGHEST_NS, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500);
+ n_tests_passed += test_is_read_scheduled(101, 0001, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500 - NSEC_PER_SEC);
+ n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500 - NSEC_PER_SEC, 1, 600 + READ_INTERVAL_NSEC);
+
+ n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500, 1, 600 + READ_INTERVAL_NSEC);
+
+ printk("gator: %d tests passed\n", n_tests_passed);
+}
index f81c40240d9d63aabe4575a02fcf30a2d070dfaa..1be6e66320e2dd5007a42033bdf91ef70d71d965 100644 (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"/>
- * <counter name="mmaped_cnt1"/>
- * <counter name="mmaped_cnt2"/>
- * </counter_set>
- * <category name="mmaped" counter_set="mmaped_cntX" per_cpu="no">
+ * <counter_set name="mmaped_cnt" count="3"/>
+ * <category name="mmaped" counter_set="mmaped_cnt" per_cpu="no">
* <event event="0x0" title="Simulated" name="Sine" display="maximum" average_selection="yes" description="Sort-of-sine"/>
* <event event="0x1" title="Simulated" name="Triangle" display="maximum" average_selection="yes" description="Triangular wave"/>
* <event event="0x2" title="Simulated" name="PWM" display="maximum" average_selection="yes" description="PWM Signal"/>
index 11282b50d0401978ac9558d33e06befdb7a87d10..31cc3efdf8a85f6d8ffbf999578378e7ff919640 100644 (file)
get_network_stats(0);
netPrev[NETRX] = rx_total;
netPrev[NETTX] = tx_total;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
setup_timer(&net_wake_up_timer, net_wake_up_handler, 0);
+#else
+ setup_deferrable_timer_on_stack(&net_wake_up_timer, net_wake_up_handler, 0);
+#endif
return 0;
}
index 9d78b466ac844c32cac43dd601548cc652916fe4..e025155497acee0ffc5441a41e4195a2144c275b 100644 (file)
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);
-extern DEFINE_PER_CPU(struct perf_event *, pevent_ebs);
static void gator_events_perf_pmu_stop(void);
return 0;
}
+#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
+{
+ gator_backtrace_handler(regs);
+}
+
#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
@@ -75,15 +83,10 @@ static void dummy_handler(struct perf_event *event, struct perf_sample_data *dat
static int gator_events_perf_pmu_online(int** buffer)
{
int cnt, len = 0, cpu = smp_processor_id();
- struct perf_event * ev;
// read the counters and toss the invalid data, return zero instead
for (cnt = 0; cnt < pmnc_counters; cnt++) {
- if (pmnc_count[cnt] > 0) {
- ev = per_cpu(pevent_ebs, cpu); // special case for EBS
- } else {
- ev = per_cpu(pevent, cpu)[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);
static void gator_events_perf_pmu_online_dispatch(int cpu)
{
int cnt;
+ perf_overflow_handler_t handler;
for (cnt = 0; cnt < pmnc_counters; cnt++) {
if (per_cpu(pevent, cpu)[cnt] != NULL || per_cpu(pevent_attr, cpu)[cnt] == 0)
continue;
- if (pmnc_count[cnt] > 0)
- continue; // skip the EBS counter
+ if (pmnc_count[cnt] > 0) {
+ handler = ebs_overflow_handler;
+ } else {
+ handler = dummy_handler;
+ }
#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);
+ per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, handler);
#else
- per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, dummy_handler, 0);
+ per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, handler, 0);
#endif
if (IS_ERR(per_cpu(pevent, cpu)[cnt])) {
pr_debug("gator: unable to online a counter on cpu %d\n", cpu);
{
int cnt, cpu;
u32 size = sizeof(struct perf_event_attr);
+ int found_ebs = false;
+
+ for (cnt = 0; cnt < pmnc_counters; cnt++) {
+ if (pmnc_count[cnt] > 0) {
+ if (!found_ebs) {
+ found_ebs = true;
+ } else {
+ // Only one ebs counter is allowed
+ return -1;
+ }
+ }
+ }
for_each_present_cpu(cpu) {
for (cnt = 0; cnt < pmnc_counters; cnt++) {
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]->sample_period = pmnc_count[cnt];
per_cpu(pevent_attr, cpu)[cnt]->pinned = 1;
// handle special case for ccnt
{
int cnt, delta, len = 0;
int cpu = smp_processor_id();
- struct perf_event * ev;
for (cnt = 0; cnt < pmnc_counters; cnt++) {
- if (pmnc_count[cnt] > 0) {
- ev = per_cpu(pevent_ebs, cpu); // special case for EBS
- } else {
- ev = per_cpu(pevent, cpu)[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);
pmnc_name = "Krait";
pmnc_counters = 4;
break;
+ case AARCH64:
+ pmnc_name = "ARM_AArch64";
+ // Copied from A15, get the correct number
+ pmnc_counters = 6;
+ break;
default:
return -1;
}
diff --git a/driver/gator_main.c b/driver/gator_main.c
index f6c1135ae1d818ad25c1195fe5686fd9672c5017..309c6c23ad559c50c2cb007798b2f6ba89845216 100644 (file)
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
*
*/
-static unsigned long gator_protocol_version = 10;
+static unsigned long gator_protocol_version = 11;
#include <linux/slab.h>
#include <linux/cpu.h>
#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
+#error 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
+#error gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters
#endif
#endif
/******************************************************************************
* DEFINES
******************************************************************************/
-#define BACKTRACE_BUFFER_SIZE (128*1024)
-#define COUNTER_BUFFER_SIZE (128*1024)
-#define ANNOTATE_BUFFER_SIZE (64*1024) // annotate counters have the core as part of the data and the core value in the frame header may be discarded
-#define SCHED_TRACE_BUFFER_SIZE (128*1024)
-#define GPU_TRACE_BUFFER_SIZE (64*1024)
-#define COUNTER2_BUFFER_SIZE (64*1024) // counters2 counters have the core as part of the data and the core value in the frame header may be discarded
-#define WFI_BUFFER_SIZE (32*1024) // wfi counters have the core as part of the data and the core value in the frame header may be discarded
-
-#define NO_COOKIE 0UL
-#define INVALID_COOKIE ~0UL
-
-#define FRAME_BACKTRACE 1
-#define FRAME_COUNTER 2
-#define FRAME_ANNOTATE 3
-#define FRAME_SCHED_TRACE 4
-#define FRAME_GPU_TRACE 5
-#define FRAME_COUNTER2 6
-#define FRAME_WFI 7
-
-#define MESSAGE_COOKIE 1
-#define MESSAGE_START_BACKTRACE 5
-#define MESSAGE_END_BACKTRACE 7
-#define MESSAGE_SUMMARY 9
-#define MESSAGE_PID_NAME 11
-
-#define MAXSIZE_PACK32 5
-#define MAXSIZE_PACK64 9
+#define SUMMARY_BUFFER_SIZE (1*1024)
+#define BACKTRACE_BUFFER_SIZE (128*1024)
+#define NAME_BUFFER_SIZE (64*1024)
+#define COUNTER_BUFFER_SIZE (64*1024) // counters have the core as part of the data and the core value in the frame header may be discarded
+#define BLOCK_COUNTER_BUFFER_SIZE (128*1024)
+#define ANNOTATE_BUFFER_SIZE (64*1024) // annotate counters have the core as part of the data and the core value in the frame header may be discarded
+#define SCHED_TRACE_BUFFER_SIZE (128*1024)
+#define GPU_TRACE_BUFFER_SIZE (64*1024) // gpu trace counters have the core as part of the data and the core value in the frame header may be discarded
+#define IDLE_BUFFER_SIZE (32*1024) // idle counters have the core as part of the data and the core value in the frame header may be discarded
+
+#define NO_COOKIE 0U
+#define INVALID_COOKIE ~0U
+
+#define FRAME_SUMMARY 1
+#define FRAME_BACKTRACE 2
+#define FRAME_NAME 3
+#define FRAME_COUNTER 4
+#define FRAME_BLOCK_COUNTER 5
+#define FRAME_ANNOTATE 6
+#define FRAME_SCHED_TRACE 7
+#define FRAME_GPU_TRACE 8
+#define FRAME_IDLE 9
+
+#define MESSAGE_END_BACKTRACE 1
+
+#define MESSAGE_COOKIE 1
+#define MESSAGE_THREAD_NAME 2
+#define HRTIMER_CORE_NAME 3
+
+#define MESSAGE_GPU_START 1
+#define MESSAGE_GPU_STOP 2
+
+#define MESSAGE_SCHED_SWITCH 1
+#define MESSAGE_SCHED_EXIT 2
+
+#define MAXSIZE_PACK32 5
+#define MAXSIZE_PACK64 10
+#define MAXSIZE_CORE_NAME 32
#if defined(__arm__)
#define PC_REG regs->ARM_pc
+#elif defined(__aarch64__)
+#define PC_REG regs->pc
#else
#define PC_REG regs->ip
#endif
-enum {BACKTRACE_BUF, COUNTER_BUF, SCHED_TRACE_BUF, GPU_TRACE_BUF, ANNOTATE_BUF, COUNTER2_BUF, WFI_BUF, NUM_GATOR_BUFS};
+enum {
+ SUMMARY_BUF,
+ BACKTRACE_BUF,
+ NAME_BUF,
+ COUNTER_BUF,
+ BLOCK_COUNTER_BUF,
+ ANNOTATE_BUF,
+ SCHED_TRACE_BUF,
+ GPU_TRACE_BUF,
+ IDLE_BUF,
+ NUM_GATOR_BUFS
+};
/******************************************************************************
* Globals
static unsigned long gator_backtrace_depth;
static unsigned long gator_started;
+static uint64_t monotonic_started;
static unsigned long gator_buffer_opened;
static unsigned long gator_timer_count;
static unsigned long gator_response_type;
static DEFINE_MUTEX(start_mutex);
static DEFINE_MUTEX(gator_buffer_mutex);
-bool event_based_sampling;
-#if defined(__arm__) && (GATOR_PERF_PMU_SUPPORT)
-DEFINE_PER_CPU(struct perf_event *, pevent_ebs);
-#endif
-
static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
static struct timer_list gator_buffer_wake_up_timer;
static LIST_HEAD(gator_events);
static int contiguous_space_available(int cpu, int bufytpe);
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_bytes(int cpu, int buftype, char *x, int len);
-static void gator_buffer_write_string(int cpu, int buftype, char *x);
-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 void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len);
+static void gator_buffer_write_string(int cpu, int buftype, const char *x);
+static void gator_add_trace(int cpu, unsigned long address);
+static void gator_add_sample(int cpu, struct pt_regs * const regs);
static uint64_t gator_get_time(void);
static uint32_t gator_buffer_size[NUM_GATOR_BUFS];
#include "gator_backtrace.c"
#include "gator_annotate.c"
#include "gator_fs.c"
-#include "gator_ebs.c"
#include "gator_pack.c"
/******************************************************************************
* Misc
******************************************************************************/
-#if defined(__arm__)
+#if defined(__arm__) || defined(__aarch64__)
u32 gator_cpuid(void)
{
u32 val;
+#if !defined(__aarch64__)
asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (val));
+#else
+ asm volatile("mrs %0, midr_el1" : "=r" (val));
+#endif
return (val >> 4) & 0xfff;
}
#endif
return per_cpu(buffer_space_available, cpu)[buftype];
}
-static void gator_buffer_write_bytes(int cpu, int buftype, char *x, int len)
+static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len)
{
int i;
u32 write = per_cpu(gator_buffer_write, cpu)[buftype];
per_cpu(gator_buffer_write, cpu)[buftype] = write;
}
-static void gator_buffer_write_string(int cpu, int buftype, char *x)
+static void gator_buffer_write_string(int cpu, int buftype, const char *x)
{
int len = strlen(x);
gator_buffer_write_packed_int(cpu, buftype, len);
{
int frame;
- if (buftype == BACKTRACE_BUF)
+ switch (buftype) {
+ case SUMMARY_BUF:
+ frame = FRAME_SUMMARY;
+ break;
+ case BACKTRACE_BUF:
frame = FRAME_BACKTRACE;
- else if (buftype == COUNTER_BUF)
+ break;
+ case NAME_BUF:
+ frame = FRAME_NAME;
+ break;
+ case COUNTER_BUF:
frame = FRAME_COUNTER;
- else if (buftype == ANNOTATE_BUF)
+ break;
+ case BLOCK_COUNTER_BUF:
+ frame = FRAME_BLOCK_COUNTER;
+ break;
+ case ANNOTATE_BUF:
frame = FRAME_ANNOTATE;
- else if (buftype == SCHED_TRACE_BUF)
+ break;
+ case SCHED_TRACE_BUF:
frame = FRAME_SCHED_TRACE;
- else if (buftype == GPU_TRACE_BUF)
+ break;
+ case GPU_TRACE_BUF:
frame = FRAME_GPU_TRACE;
- else if (buftype == COUNTER2_BUF)
- frame = FRAME_COUNTER2;
- else if (buftype == WFI_BUF)
- frame = FRAME_WFI;
- else
+ break;
+ case IDLE_BUF:
+ frame = FRAME_IDLE;
+ break;
+ default:
frame = -1;
+ break;
+ }
if (per_cpu(gator_buffer, cpu)[buftype]) {
marshal_frame(cpu, buftype, frame);
}
}
-static void gator_add_trace(int cpu, int buftype, unsigned int address)
+static void gator_add_trace(int cpu, unsigned long address)
{
off_t offset = 0;
- unsigned long cookie = get_address_cookie(cpu, buftype, current, address & ~1, &offset);
+ unsigned long cookie = get_address_cookie(cpu, current, address & ~1, &offset);
if (cookie == NO_COOKIE || cookie == INVALID_COOKIE) {
offset = address;
marshal_backtrace(offset & ~1, cookie);
}
-static void gator_add_sample(int cpu, int buftype, struct pt_regs * const regs)
+static void gator_add_sample(int cpu, struct pt_regs * const regs)
{
- int inKernel = regs ? !user_mode(regs) : 1;
- unsigned long exec_cookie = inKernel ? NO_COOKIE : get_exec_cookie(cpu, buftype, current);
+ bool inKernel;
+ unsigned long exec_cookie;
if (!regs)
return;
+ inKernel = !user_mode(regs);
+ exec_cookie = get_exec_cookie(cpu, current);
+
if (!marshal_backtrace_header(exec_cookie, current->tgid, current->pid, inKernel))
return;
if (inKernel) {
- kernel_backtrace(cpu, buftype, regs);
+ kernel_backtrace(cpu, regs);
} else {
// Cookie+PC
- gator_add_trace(cpu, buftype, PC_REG);
+ gator_add_trace(cpu, PC_REG);
// Backtrace
if (gator_backtrace_depth)
- arm_backtrace_eabi(cpu, buftype, regs, gator_backtrace_depth);
+ arm_backtrace_eabi(cpu, regs, gator_backtrace_depth);
}
marshal_backtrace_footer();
@@ -351,13 +393,20 @@ static void gator_add_sample(int cpu, int buftype, struct pt_regs * const regs)
static void gator_timer_interrupt(void)
{
struct pt_regs * const regs = get_irq_regs();
+ gator_backtrace_handler(regs);
+}
+
+void gator_backtrace_handler(struct pt_regs * const regs)
+{
int cpu = smp_processor_id();
// Output backtrace
- gator_add_sample(cpu, BACKTRACE_BUF, regs);
+ gator_add_sample(cpu, regs);
// Collect counters
- collect_counters();
+ if (!per_cpu(collecting, cpu)) {
+ collect_counters();
+ }
}
static int gator_running;
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)
}
gator_hrtimer_online(cpu);
+#if defined(__arm__) || defined(__aarch64__)
+ {
+ const char * core_name = NULL;
+
+ // String lengths must be less than MAXSIZE_CORE_NAME
+ switch (gator_cpuid()) {
+ case ARM1136: core_name = "ARM1136"; break;
+ case ARM1156: core_name = "ARM1156"; break;
+ case ARM1176: core_name = "ARM1176"; break;
+ case ARM11MPCORE: core_name = "ARM11MPCore"; break;
+ case CORTEX_A5: core_name = "Cortex-A5"; break;
+ case CORTEX_A7: core_name = "Cortex-A7"; break;
+ case CORTEX_A8: core_name = "Cortex-A8"; break;
+ case CORTEX_A9: core_name = "Cortex-A9"; break;
+ case CORTEX_A15: core_name = "Cortex-A15"; break;
+ case SCORPION: core_name = "Scorpion"; break;
+ case SCORPIONMP: core_name = "ScorpionMP"; break;
+ case KRAITSIM: core_name = "KraitSIM"; break;
+ case KRAIT: core_name = "Krait"; break;
+ case AARCH64: core_name = "AArch64"; break;
+ default: core_name = "Unknown"; break;
+ }
+
+ marshal_core_name(core_name);
+ }
+#endif
}
// This function runs in interrupt context and may be running on a core other than core 'cpu'
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 sample_rate)
gator_running = 1;
- // event based sampling trumps hr timer based sampling
- if (event_based_sampling)
- sample_rate = 0;
-
if (gator_hrtimer_init(sample_rate, gator_timer_interrupt) == -1)
return -1;
struct timespec ts;
uint64_t timestamp;
- getnstimeofday(&ts);
- timestamp = timespec_to_ns(&ts);
+ //getnstimeofday(&ts);
+ do_posix_clock_monotonic_gettime(&ts);
+ timestamp = timespec_to_ns(&ts) - monotonic_started;
return timestamp;
}
******************************************************************************/
static void gator_summary(void)
{
- uint64_t timestamp, uptime = 0;
+ uint64_t timestamp;
struct timespec uptime_ts;
- void (*m2b)(struct timespec *ts);
timestamp = gator_get_time();
do_posix_clock_monotonic_gettime(&uptime_ts);
- m2b = symbol_get(monotonic_to_bootbased);
- if (m2b) {
- m2b(&uptime_ts);
- uptime = (long long)uptime_ts.tv_sec * 1000000000 + uptime_ts.tv_nsec;
- }
+ monotonic_started = timespec_to_ns(&uptime_ts);
- marshal_summary(timestamp, uptime);
+ marshal_summary(timestamp, monotonic_started);
}
int gator_events_install(struct gator_interface *interface)
goto power_failure;
if (gator_trace_gpu_start())
goto gpu_failure;
- if (gator_event_sampling_start())
- goto event_sampling_failure;
if (gator_timer_start(gator_timer_count))
goto timer_failure;
if (gator_notifier_start())
notifier_failure:
gator_timer_stop();
timer_failure:
- gator_event_sampling_stop();
-event_sampling_failure:
gator_trace_gpu_stop();
gpu_failure:
gator_trace_power_stop();
gator_trace_sched_stop();
gator_trace_power_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_stop to avoid re-enabling the hrtimer after it has been offlined
mutex_lock(&start_mutex);
+ gator_buffer_size[SUMMARY_BUF] = SUMMARY_BUFFER_SIZE;
+ gator_buffer_mask[SUMMARY_BUF] = SUMMARY_BUFFER_SIZE - 1;
+
gator_buffer_size[BACKTRACE_BUF] = BACKTRACE_BUFFER_SIZE;
gator_buffer_mask[BACKTRACE_BUF] = BACKTRACE_BUFFER_SIZE - 1;
+ gator_buffer_size[NAME_BUF] = NAME_BUFFER_SIZE;
+ gator_buffer_mask[NAME_BUF] = NAME_BUFFER_SIZE - 1;
+
gator_buffer_size[COUNTER_BUF] = COUNTER_BUFFER_SIZE;
gator_buffer_mask[COUNTER_BUF] = COUNTER_BUFFER_SIZE - 1;
+ gator_buffer_size[BLOCK_COUNTER_BUF] = BLOCK_COUNTER_BUFFER_SIZE;
+ gator_buffer_mask[BLOCK_COUNTER_BUF] = BLOCK_COUNTER_BUFFER_SIZE - 1;
+
+ gator_buffer_size[ANNOTATE_BUF] = ANNOTATE_BUFFER_SIZE;
+ gator_buffer_mask[ANNOTATE_BUF] = ANNOTATE_BUFFER_SIZE - 1;
+
gator_buffer_size[SCHED_TRACE_BUF] = SCHED_TRACE_BUFFER_SIZE;
gator_buffer_mask[SCHED_TRACE_BUF] = SCHED_TRACE_BUFFER_SIZE - 1;
gator_buffer_size[GPU_TRACE_BUF] = GPU_TRACE_BUFFER_SIZE;
gator_buffer_mask[GPU_TRACE_BUF] = GPU_TRACE_BUFFER_SIZE - 1;
- gator_buffer_size[ANNOTATE_BUF] = ANNOTATE_BUFFER_SIZE;
- gator_buffer_mask[ANNOTATE_BUF] = ANNOTATE_BUFFER_SIZE - 1;
-
- gator_buffer_size[COUNTER2_BUF] = COUNTER2_BUFFER_SIZE;
- gator_buffer_mask[COUNTER2_BUF] = COUNTER2_BUFFER_SIZE - 1;
-
- gator_buffer_size[WFI_BUF] = WFI_BUFFER_SIZE;
- gator_buffer_mask[WFI_BUF] = WFI_BUFFER_SIZE - 1;
+ gator_buffer_size[IDLE_BUF] = IDLE_BUFFER_SIZE;
+ gator_buffer_mask[IDLE_BUF] = IDLE_BUFFER_SIZE - 1;
// Initialize percpu per buffer variables
for (i = 0; i < NUM_GATOR_BUFS; i++) {
gatorfs_create_file(sb, root, "enable", &enable_fops);
gatorfs_create_file(sb, root, "buffer", &gator_event_buffer_fops);
gatorfs_create_file(sb, root, "backtrace_depth", &depth_fops);
- gatorfs_create_ulong(sb, root, "cpu_cores", &gator_cpu_cores);
- gatorfs_create_ulong(sb, root, "buffer_size", &userspace_buffer_size);
+ gatorfs_create_ro_ulong(sb, root, "cpu_cores", &gator_cpu_cores);
+ gatorfs_create_ro_ulong(sb, root, "buffer_size", &userspace_buffer_size);
gatorfs_create_ulong(sb, root, "tick", &gator_timer_count);
gatorfs_create_ulong(sb, root, "response_type", &gator_response_type);
gatorfs_create_ro_ulong(sb, root, "version", &gator_protocol_version);
index 630d142bf70e610ea8f4c248a13f75c9ca23379f..a84b28045723e19cf5e47959e727bbcc53000d64 100644 (file)
static void marshal_summary(long long timestamp, long long uptime) {
int cpu = 0;
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_SUMMARY);
- gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, timestamp);
- gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, uptime);
+ gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, timestamp);
+ gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, uptime);
+ buffer_check(cpu, SUMMARY_BUF);
}
static bool marshal_cookie_header(char* text) {
int cpu = smp_processor_id();
- return buffer_check_space(cpu, BACKTRACE_BUF, strlen(text) + 2 * MAXSIZE_PACK32);
+ return buffer_check_space(cpu, NAME_BUF, strlen(text) + 2*MAXSIZE_PACK32);
}
static void marshal_cookie(int cookie, char* text) {
int cpu = smp_processor_id();
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_COOKIE);
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie);
- gator_buffer_write_string(cpu, BACKTRACE_BUF, text);
+ // TODO(dreric01) How long can the string be?
+ if (buffer_check_space(cpu, NAME_BUF, 2*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_COOKIE);
+ gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
+ gator_buffer_write_string(cpu, NAME_BUF, text);
+ }
+ buffer_check(cpu, NAME_BUF);
}
-static void marshal_pid_name(int pid, char* name) {
+static void marshal_thread_name(int pid, char* name) {
unsigned long flags, cpu;
local_irq_save(flags);
cpu = smp_processor_id();
- if (buffer_check_space(cpu, BACKTRACE_BUF, TASK_COMM_LEN + 2 * MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_PID_NAME);
- gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, gator_get_time());
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, pid);
- gator_buffer_write_string(cpu, BACKTRACE_BUF, name);
+ if (buffer_check_space(cpu, NAME_BUF, TASK_COMM_LEN + 2*MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
+ gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_THREAD_NAME);
+ gator_buffer_write_packed_int64(cpu, NAME_BUF, gator_get_time());
+ gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
+ gator_buffer_write_string(cpu, NAME_BUF, name);
}
local_irq_restore(flags);
+ buffer_check(cpu, NAME_BUF);
}
static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel) {
int cpu = smp_processor_id();
- if (buffer_check_space(cpu, BACKTRACE_BUF, gator_backtrace_depth * 2 * MAXSIZE_PACK32)) {
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_START_BACKTRACE);
+ if (buffer_check_space(cpu, BACKTRACE_BUF, gator_backtrace_depth*2*MAXSIZE_PACK32)) {
gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, gator_get_time());
gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, exec_cookie);
gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, tgid);
return false;
}
-static void marshal_backtrace(int address, int cookie) {
+static void marshal_backtrace(unsigned long address, int cookie) {
int cpu = smp_processor_id();
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, address);
+ gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, address);
gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie);
}
bool retval = false;
local_irq_save(flags);
- if (buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
- gator_buffer_write_packed_int(cpu, COUNTER_BUF, 0); // key of zero indicates a timestamp
- gator_buffer_write_packed_int64(cpu, COUNTER_BUF, gator_get_time());
+ if (buffer_check_space(cpu, BLOCK_COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
+ gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0); // key of zero indicates a timestamp
+ gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, gator_get_time());
retval = true;
}
local_irq_restore(flags);
// Check and commit; commit is set to occur once buffer is 3/4 full
- buffer_check(cpu, COUNTER_BUF);
+ buffer_check(cpu, BLOCK_COUNTER_BUF);
return retval;
}
// events must be written in key,value pairs
for (i = 0; i < len; i += 2) {
local_irq_save(flags);
- if (!buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK32 * 2)) {
+ if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2*MAXSIZE_PACK32)) {
local_irq_restore(flags);
break;
}
- gator_buffer_write_packed_int(cpu, COUNTER_BUF, buffer[i]);
- gator_buffer_write_packed_int(cpu, COUNTER_BUF, buffer[i + 1]);
+ gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i]);
+ gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i + 1]);
local_irq_restore(flags);
}
// Check and commit; commit is set to occur once buffer is 3/4 full
- buffer_check(cpu, COUNTER_BUF);
+ buffer_check(cpu, BLOCK_COUNTER_BUF);
}
static void marshal_event64(int len, long long* buffer64) {
// events must be written in key,value pairs
for (i = 0; i < len; i += 2) {
local_irq_save(flags);
- if (!buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK64 * 2)) {
+ if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2*MAXSIZE_PACK64)) {
local_irq_restore(flags);
break;
}
- gator_buffer_write_packed_int64(cpu, COUNTER_BUF, buffer64[i]);
- gator_buffer_write_packed_int64(cpu, COUNTER_BUF, buffer64[i + 1]);
+ gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i]);
+ gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i + 1]);
local_irq_restore(flags);
}
// Check and commit; commit is set to occur once buffer is 3/4 full
- buffer_check(cpu, COUNTER_BUF);
+ buffer_check(cpu, BLOCK_COUNTER_BUF);
}
#if GATOR_CPU_FREQ_SUPPORT
local_irq_save(flags);
cpu = smp_processor_id();
- if (buffer_check_space(cpu, COUNTER2_BUF, MAXSIZE_PACK64 + MAXSIZE_PACK32 * 3)) {
- gator_buffer_write_packed_int64(cpu, COUNTER2_BUF, gator_get_time());
- gator_buffer_write_packed_int(cpu, COUNTER2_BUF, core);
- gator_buffer_write_packed_int(cpu, COUNTER2_BUF, key);
- gator_buffer_write_packed_int(cpu, COUNTER2_BUF, value);
+ if (buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK64 + 3*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int64(cpu, COUNTER_BUF, gator_get_time());
+ gator_buffer_write_packed_int(cpu, COUNTER_BUF, core);
+ gator_buffer_write_packed_int(cpu, COUNTER_BUF, key);
+ gator_buffer_write_packed_int(cpu, COUNTER_BUF, value);
}
local_irq_restore(flags);
// Check and commit; commit is set to occur once buffer is 3/4 full
- buffer_check(cpu, COUNTER2_BUF);
+ buffer_check(cpu, COUNTER_BUF);
}
#endif
-static void marshal_sched_gpu(int type, int unit, int core, int tgid, int pid) {
+static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid) {
unsigned long cpu = smp_processor_id(), flags;
if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
return;
local_irq_save(flags);
- if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
- gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, type);
+ if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_START);
gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, gator_get_time());
gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
@@ -185,18 +189,37 @@ static void marshal_sched_gpu(int type, int unit, int core, int tgid, int pid) {
buffer_check(cpu, GPU_TRACE_BUF);
}
-static void marshal_sched_trace(int type, int pid, int tgid, int cookie, int state) {
+static void marshal_sched_gpu_stop(int unit, int core) {
+ unsigned long cpu = smp_processor_id(), flags;
+
+ if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
+ return;
+
+ local_irq_save(flags);
+ if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 3*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_STOP);
+ gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, gator_get_time());
+ gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
+ gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
+ }
+ local_irq_restore(flags);
+
+ // Check and commit; commit is set to occur once buffer is 3/4 full
+ buffer_check(cpu, GPU_TRACE_BUF);
+}
+
+static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state) {
unsigned long cpu = smp_processor_id(), flags;
if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
return;
local_irq_save(flags);
- if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
- gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, type);
+ if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_SWITCH);
gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, gator_get_time());
- gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid);
+ gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie);
gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state);
}
@@ -206,21 +229,39 @@ static void marshal_sched_trace(int type, int pid, int tgid, int cookie, int sta
buffer_check(cpu, SCHED_TRACE_BUF);
}
+static void marshal_sched_trace_exit(int tgid, int pid) {
+ unsigned long cpu = smp_processor_id(), flags;
+
+ if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
+ return;
+
+ local_irq_save(flags);
+ if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 2*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_EXIT);
+ gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, gator_get_time());
+ gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
+ }
+ local_irq_restore(flags);
+
+ // Check and commit; commit is set to occur once buffer is 3/4 full
+ buffer_check(cpu, SCHED_TRACE_BUF);
+}
+
#if GATOR_CPU_FREQ_SUPPORT
-static void marshal_wfi(int core, int state) {
+static void marshal_idle(int core, int state) {
unsigned long flags, cpu;
local_irq_save(flags);
cpu = smp_processor_id();
- if (buffer_check_space(cpu, WFI_BUF, MAXSIZE_PACK64 + MAXSIZE_PACK32 * 2)) {
- gator_buffer_write_packed_int64(cpu, WFI_BUF, gator_get_time());
- gator_buffer_write_packed_int(cpu, WFI_BUF, core);
- gator_buffer_write_packed_int(cpu, WFI_BUF, state);
+ if (buffer_check_space(cpu, IDLE_BUF, MAXSIZE_PACK64 + 2*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, IDLE_BUF, state);
+ gator_buffer_write_packed_int64(cpu, IDLE_BUF, gator_get_time());
+ gator_buffer_write_packed_int(cpu, IDLE_BUF, core);
}
local_irq_restore(flags);
// Check and commit; commit is set to occur once buffer is 3/4 full
- buffer_check(cpu, WFI_BUF);
+ buffer_check(cpu, IDLE_BUF);
}
#endif
gator_buffer_write_packed_int(cpu, buftype, frame);
gator_buffer_write_packed_int(cpu, buftype, cpu);
}
+
+#if defined(__arm__) || defined(__aarch64__)
+static void marshal_core_name(const char* name) {
+ int cpu = smp_processor_id();
+ unsigned long flags;
+ local_irq_save(flags);
+ if (buffer_check_space(cpu, NAME_BUF, MAXSIZE_PACK32 + MAXSIZE_CORE_NAME)) {
+ gator_buffer_write_packed_int(cpu, NAME_BUF, HRTIMER_CORE_NAME);
+ gator_buffer_write_string(cpu, NAME_BUF, name);
+ }
+ local_irq_restore(flags);
+
+ buffer_check(cpu, NAME_BUF);
+}
+#endif
diff --git a/driver/gator_pack.c b/driver/gator_pack.c
index 925469a5b894f068968be6dc2ace524872aebdaa..5ad53db3b311f553dfeb1a399e043a413cfa7f1d 100644 (file)
--- a/driver/gator_pack.c
+++ b/driver/gator_pack.c
buffer[write6] = (x>>42) | 0x80;
buffer[write7] = (x>>49) & 0x7f;
per_cpu(gator_buffer_write, cpu)[buftype] = write8;
- } else {
+ } else if ((x & 0x8000000000000000LL) == 0) {
int write2 = (write + 2) & mask;
int write3 = (write + 3) & mask;
int write4 = (write + 4) & mask;
@@ -158,7 +158,28 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long
buffer[write5] = (x>>35) | 0x80;
buffer[write6] = (x>>42) | 0x80;
buffer[write7] = (x>>49) | 0x80;
- buffer[write8] = (x>>56) & 0xff;
+ buffer[write8] = (x>>56) & 0x7f;
per_cpu(gator_buffer_write, cpu)[buftype] = write9;
+ } else {
+ int write2 = (write + 2) & mask;
+ int write3 = (write + 3) & mask;
+ int write4 = (write + 4) & mask;
+ int write5 = (write + 5) & mask;
+ int write6 = (write + 6) & mask;
+ int write7 = (write + 7) & mask;
+ int write8 = (write + 8) & mask;
+ int write9 = (write + 9) & mask;
+ int write10 = (write + 10) & mask;
+ buffer[write0] = x | 0x80;
+ buffer[write1] = (x>>7) | 0x80;
+ buffer[write2] = (x>>14) | 0x80;
+ buffer[write3] = (x>>21) | 0x80;
+ buffer[write4] = (x>>28) | 0x80;
+ buffer[write5] = (x>>35) | 0x80;
+ buffer[write6] = (x>>42) | 0x80;
+ buffer[write7] = (x>>49) | 0x80;
+ buffer[write8] = (x>>56) | 0x80;
+ buffer[write9] = (x>>63) & 0x7f;
+ per_cpu(gator_buffer_write, cpu)[buftype] = write10;
}
}
index d0539877c06b492d0c93faa4520617da70595e96..0511d71a5636d6f31b8e43b0ac0f11b83c777704 100644 (file)
--- a/driver/gator_trace_gpu.c
+++ b/driver/gator_trace_gpu.c
static int mali_job_slots_trace_registered;
static int gpu_trace_registered;
-#define GPU_START 1
-#define GPU_STOP 2
-
+#define GPU_UNIT_NONE 0
#define GPU_UNIT_VP 1
#define GPU_UNIT_FP 2
#define GPU_UNIT_CL 3
@@ -84,18 +82,18 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned
case EVENT_TYPE_START:
if (component == EVENT_CHANNEL_VP0) {
/* tgid = d0; pid = d1; */
- marshal_sched_gpu(GPU_START, GPU_UNIT_VP, 0, d0, d1);
+ marshal_sched_gpu_start(GPU_UNIT_VP, 0, d0, d1);
} else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
/* tgid = d0; pid = d1; */
- marshal_sched_gpu(GPU_START, GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, d0, d1);
+ marshal_sched_gpu_start(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, d0, d1);
}
break;
case EVENT_TYPE_STOP:
if (component == EVENT_CHANNEL_VP0) {
- marshal_sched_gpu(GPU_STOP, GPU_UNIT_VP, 0, 0, 0);
+ marshal_sched_gpu_stop(GPU_UNIT_VP, 0);
} else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
- marshal_sched_gpu(GPU_STOP, GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, 0, 0);
+ marshal_sched_gpu_stop(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0);
}
break;
@@ -118,11 +116,10 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned
#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid))
{
- unsigned int component, state, type, unit = 0;
+ unsigned int component, state, unit;
component = (event_id >> 16) & 0xFF; // component is an 8-bit field
state = (event_id >> 24) & 0xF; // state is a 4-bit field
- type = (state == EVENT_TYPE_START) ? GPU_START : GPU_STOP;
switch (component)
{
@@ -135,23 +132,37 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne
case 2:
unit = GPU_UNIT_CL;
break;
+ default:
+ unit = GPU_UNIT_NONE;
}
- if (unit != 0)
+ if (unit != GPU_UNIT_NONE)
{
- marshal_sched_gpu(type, unit, 0, tgid, (pid != 0 ? pid : tgid));
+ switch(state) {
+ case EVENT_TYPE_START:
+ marshal_sched_gpu_start(unit, 0, tgid, (pid != 0 ? pid : tgid));
+ break;
+ case EVENT_TYPE_STOP:
+ marshal_sched_gpu_stop(unit, 0);
+ break;
+ default:
+ /*
+ * Some jobs can be soft-stopped, so ensure that this terminates the activity trace.
+ */
+ marshal_sched_gpu_stop(unit, 0);
+ }
}
}
#endif
GATOR_DEFINE_PROBE(gpu_activity_start, TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p))
{
- marshal_sched_gpu(GPU_START, gpu_unit, gpu_core, (int)p->tgid, (int)p->pid);
+ marshal_sched_gpu_start(gpu_unit, gpu_core, (int)p->tgid, (int)p->pid);
}
GATOR_DEFINE_PROBE(gpu_activity_stop, TP_PROTO(int gpu_unit, int gpu_core))
{
- marshal_sched_gpu(GPU_STOP, gpu_unit, gpu_core, 0, 0);
+ marshal_sched_gpu_stop(gpu_unit, gpu_core);
}
int gator_trace_gpu_start(void)
index ca89b19908f82d6e42124fe6e24ca8bf29a4dfa5..b1687e1a9ebbbc0f10fbcedf5c7a24e82dcf5bab 100644 (file)
#include <linux/cpufreq.h>
#include <trace/events/power.h>
+#include <asm/mach-types.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
marshal_event_single(cpu, power_cpu_key[POWER_CPU_FREQ], frequency * 1000);
}
-#define WFI_ACTIVE_THRESHOLD 2 // may vary on platform/OS
-#define WFI_EXIT 0
+#define WFI_EXIT 2
#define WFI_ENTER 1
GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu))
{
- // the streamline engine treats all counter values as unsigned
- if (state & 0x80000000) {
- state = 0;
- }
-
if (state == per_cpu(idle_prev_state, cpu)) {
return;
}
- if (state < WFI_ACTIVE_THRESHOLD && per_cpu(idle_prev_state, cpu) >= WFI_ACTIVE_THRESHOLD) {
- // transition from wfi to non-wfi
- marshal_wfi(cpu, WFI_EXIT);
- } else if (state >= WFI_ACTIVE_THRESHOLD && per_cpu(idle_prev_state, cpu) < WFI_ACTIVE_THRESHOLD) {
- // transition from non-wfi to wfi
- marshal_wfi(cpu, WFI_ENTER);
+ if (!machine_is_omap3_beagle()) {
+ if (state == PWR_EVENT_EXIT) {
+ // transition from wfi to non-wfi
+ marshal_idle(cpu, WFI_EXIT);
+ } else {
+ // transition from non-wfi to wfi
+ marshal_idle(cpu, WFI_ENTER);
+ }
}
per_cpu(idle_prev_state, cpu) = state;
if (power_cpu_enabled[POWER_CPU_IDLE]) {
- marshal_event_single(cpu, power_cpu_key[POWER_CPU_IDLE], state);
+ // Increment state so that no negative numbers are sent
+ marshal_event_single(cpu, power_cpu_key[POWER_CPU_IDLE], state + 1);
}
}
index 08b027094853f4f0454089eb1ff185255dc5e22e..9ddb8224e25c16f7fe12f620de23b0e67d8a8d2b 100644 (file)
#define TASK_MAX_COLLISIONS 2
static DEFINE_PER_CPU(uint64_t *, taskname_keys);
+static DEFINE_PER_CPU(int, collecting);
enum {
STATE_WAIT_ON_OTHER = 0,
strcat(taskcomm, "...");
}
- marshal_pid_name(task->pid, taskcomm);
+ marshal_thread_name(task->pid, taskcomm);
}
}
@@ -87,12 +88,12 @@ static void probe_sched_write(int type, struct task_struct* task, struct task_st
{
int cookie = 0, state = 0;
int cpu = smp_processor_id();
- int pid = task->pid;
int tgid = task->tgid;
+ int pid = task->pid;
if (type == SCHED_SWITCH) {
// do as much work as possible before disabling interrupts
- cookie = get_exec_cookie(cpu, BACKTRACE_BUF, task);
+ cookie = get_exec_cookie(cpu, task);
emit_pid_name(task);
if (old_task->state == TASK_RUNNING) {
state = STATE_CONTENTION;
@@ -106,18 +107,24 @@ static void probe_sched_write(int type, struct task_struct* task, struct task_st
state = STATE_WAIT_ON_OTHER;
}
+ per_cpu(collecting, cpu) = 1;
collect_counters();
+ per_cpu(collecting, cpu) = 0;
}
// marshal_sched_trace() disables interrupts as the free may trigger while switch is writing to the buffer; disabling preemption is not sufficient
// is disable interrupts necessary now that exit is used instead of free?
- marshal_sched_trace(type, pid, tgid, cookie, state);
+ if (type == SCHED_SWITCH) {
+ marshal_sched_trace_switch(tgid, pid, cookie, state);
+ } else {
+ marshal_sched_trace_exit(tgid, pid);
+ }
}
// special case used during a suspend of the system
static void trace_sched_insert_idle(void)
{
- marshal_sched_trace(SCHED_SWITCH, 0, 0, 0, 0);
+ marshal_sched_trace_switch(0, 0, 0, 0);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
diff --git a/driver/mali_t6xx.mk b/driver/mali_t6xx.mk
index 2e5167030d337e47de18323b2b350cee627094d5..2cc64113ea2c575332ccbb5f58350db00a58617c 100644 (file)
--- a/driver/mali_t6xx.mk
+++ b/driver/mali_t6xx.mk
KBASE_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase
OSK_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase/osk
-UMP_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/ump
+UMP_DIR = $(DDK_DIR)/kernel/include/linux
# Include directories in the DDK
EXTRA_CFLAGS += -I$(DDK_DIR) \
-I$(KBASE_DIR)/.. \
-I$(OSK_DIR)/.. \
-I$(UMP_DIR)/.. \
+ -I$(DDK_DIR)/kernel/include \
-I$(KBASE_DIR)/osk/src/linux/include \
-I$(KBASE_DIR)/platform_dummy \
-I$(KBASE_DIR)/src