From e17241f3e69b79e9470797e0dcc2a34094b542c7 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Fri, 26 Oct 2012 17:05:14 +0100 Subject: gator: Version 5.12 Signed-off-by: Jon Medhurst --- daemon/CapturedXML.cpp | 26 +--- daemon/CapturedXML.h | 4 +- daemon/Child.cpp | 7 +- daemon/Collector.cpp | 5 +- daemon/ConfigurationXML.cpp | 32 ++-- daemon/ConfigurationXML.h | 3 + daemon/LocalCapture.cpp | 96 +----------- daemon/LocalCapture.h | 5 +- daemon/Makefile | 11 +- daemon/OlyUtility.cpp | 4 + daemon/Sender.cpp | 5 +- daemon/Sender.h | 1 - daemon/SessionData.cpp | 21 +-- daemon/SessionData.h | 8 +- daemon/SessionXML.cpp | 35 ----- daemon/SessionXML.h | 4 - daemon/StreamlineSetup.cpp | 69 ++++----- daemon/StreamlineSetup.h | 1 - daemon/configuration.xml | 70 ++++----- daemon/events-ARM11.xml | 8 +- daemon/events-ARM11MPCore.xml | 8 +- daemon/events-Cortex-A15.xml | 12 +- daemon/events-Cortex-A5.xml | 7 +- daemon/events-Cortex-A7.xml | 9 +- daemon/events-Cortex-A8.xml | 9 +- daemon/events-Cortex-A9.xml | 11 +- daemon/events-Krait-architected.xml | 9 +- daemon/events-L2C-310.xml | 7 +- daemon/events-Linux.xml | 6 +- daemon/events-Mali-400.xml | 53 ++----- daemon/events-Scorpion.xml | 9 +- daemon/events-ScorpionMP.xml | 9 +- daemon/main.cpp | 55 ++++++- driver/Makefile | 4 + driver/gator.h | 25 ++-- driver/gator_annotate.c | 39 +++-- driver/gator_annotate_kernel.c | 89 +++++++---- driver/gator_backtrace.c | 15 +- driver/gator_cookies.c | 52 +++---- driver/gator_ebs.c | 156 ------------------- driver/gator_events_block.c | 70 ++++----- driver/gator_events_mali_400.c | 10 +- driver/gator_events_mali_400.h | 15 +- driver/gator_events_mali_common.c | 15 +- driver/gator_events_mali_common.h | 19 ++- driver/gator_events_mali_t6xx.c | 15 +- driver/gator_events_mali_t6xx_hw.c | 216 ++++++++++++++++++++++---- driver/gator_events_mali_t6xx_hw_test.c | 57 +++++++ driver/gator_events_mmaped.c | 8 +- driver/gator_events_net.c | 4 + driver/gator_events_perf_pmu.c | 55 ++++--- driver/gator_main.c | 258 ++++++++++++++++++++------------ driver/gator_marshaling.c | 152 +++++++++++++------ driver/gator_pack.c | 25 +++- driver/gator_trace_gpu.c | 37 +++-- driver/gator_trace_power.c | 26 ++-- driver/gator_trace_sched.c | 17 ++- driver/mali_t6xx.mk | 3 +- 58 files changed, 1045 insertions(+), 956 deletions(-) delete mode 100644 driver/gator_ebs.c create mode 100644 driver/gator_events_mali_t6xx_hw_test.c diff --git a/daemon/CapturedXML.cpp b/daemon/CapturedXML.cpp index f02ed2a..30d984f 100644 --- a/daemon/CapturedXML.cpp +++ b/daemon/CapturedXML.cpp @@ -22,12 +22,12 @@ CapturedXML::CapturedXML() { 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; @@ -43,11 +43,10 @@ mxml_node_t* CapturedXML::getTree() { 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"); @@ -69,18 +68,9 @@ mxml_node_t* CapturedXML::getTree() { 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]); } @@ -98,9 +88,9 @@ mxml_node_t* CapturedXML::getTree() { 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; @@ -112,7 +102,7 @@ void CapturedXML::write(char* path) { // 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 984d1f2..3f6a4de 100644 --- a/daemon/CapturedXML.h +++ b/daemon/CapturedXML.h @@ -16,10 +16,10 @@ class CapturedXML { 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 2c7c292..b97e0db 100644 --- a/daemon/Child.cpp +++ b/daemon/Child.cpp @@ -102,7 +102,10 @@ void* stopThread(void* pVoid) { 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 { @@ -228,7 +231,7 @@ void Child::run() { } 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 d29cd16..25bb934 100644 --- a/daemon/Collector.cpp +++ b/daemon/Collector.cpp @@ -202,7 +202,10 @@ void Collector::stop() { 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) { diff --git a/daemon/ConfigurationXML.cpp b/daemon/ConfigurationXML.cpp index 145ddbd..a213cbb 100644 --- a/daemon/ConfigurationXML.cpp +++ b/daemon/ConfigurationXML.cpp @@ -21,20 +21,19 @@ static const char* ATTR_REVISION = "revision"; 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); @@ -61,6 +60,9 @@ ConfigurationXML::ConfigurationXML() { 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 @@ -151,8 +153,8 @@ int ConfigurationXML::configurationsTag(mxml_node_t *node) { 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 @@ -162,12 +164,8 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) { 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); @@ -178,11 +176,17 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) { 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; +} diff --git a/daemon/ConfigurationXML.h b/daemon/ConfigurationXML.h index b48d32f..66ad587 100644 --- a/daemon/ConfigurationXML.h +++ b/daemon/ConfigurationXML.h @@ -13,10 +13,13 @@ 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; diff --git a/daemon/LocalCapture.cpp b/daemon/LocalCapture.cpp index 6449d03..f8cd17f 100644 --- a/daemon/LocalCapture.cpp +++ b/daemon/LocalCapture.cpp @@ -23,8 +23,8 @@ LocalCapture::LocalCapture() {} 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(); @@ -46,17 +46,14 @@ void LocalCapture::write(char* string) { 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 in with provided enough 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 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 with - memcpy(target, replace, strlen(replace)); - - // Increment over / - 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 ca37f6e..40f7883 100644 --- a/daemon/LocalCapture.h +++ b/daemon/LocalCapture.h @@ -17,10 +17,9 @@ public: ~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 b62a223..5562db7 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -3,7 +3,11 @@ # # 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++ @@ -17,7 +21,10 @@ GCC=$(CROSS_COMPILE)gcc # -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 c72b0d1..adc7aba 100644 --- a/daemon/OlyUtility.cpp +++ b/daemon/OlyUtility.cpp @@ -24,6 +24,10 @@ OlyUtility* util = NULL; 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 efff753..eba8343 100644 --- a/daemon/Sender.cpp +++ b/daemon/Sender.cpp @@ -38,8 +38,9 @@ Sender::Sender(OlySocket* socket) { } // 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 98467e0..ceab343 100644 --- a/daemon/Sender.h +++ b/daemon/Sender.h @@ -14,7 +14,6 @@ #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 a245369..5aa3f11 100644 --- a/daemon/SessionData.cpp +++ b/daemon/SessionData.cpp @@ -30,10 +30,10 @@ void SessionData::initialize() { mConfigurationXMLPath = NULL; mSessionXMLPath = NULL; mEventsXMLPath = NULL; + mTargetPath = NULL; mAPCDir = NULL; mSampleRate = 0; mDuration = 0; - mBytes = 0; mBacktraceDepth = 0; mTotalBufferSize = 0; mCores = 1; @@ -48,8 +48,6 @@ void SessionData::initializeCounters() { 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; @@ -59,7 +57,6 @@ void SessionData::initializeCounters() { mPerfCounterCount[i] = 0; mPerfCounterPerCPU[i] = false; mPerfCounterEBSCapable[i] = false; - mPerfCounterLevel[i] = false; mPerfCounterAverageSelection[i] = false; } } @@ -68,15 +65,6 @@ void SessionData::parseSessionXML(char* xmlString) { SessionXML session(xmlString); session.parse(); - // Parameter error checking - if (session.parameters.output_path == 0 && session.parameters.target_path == 0) { - logg->logError(__FILE__, __LINE__, "No capture path (target or host) was provided."); - handleException(); - } else if (gSessionData->mLocalCapture && session.parameters.target_path == 0) { - logg->logError(__FILE__, __LINE__, "Missing target_path tag in session xml required for a local capture."); - handleException(); - } - // Set session data values if (strcmp(session.parameters.sample_rate, "high") == 0) { gSessionData->mSampleRate = 10000; @@ -84,8 +72,11 @@ void SessionData::parseSessionXML(char* xmlString) { 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; @@ -107,6 +98,4 @@ void SessionData::parseSessionXML(char* xmlString) { } 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 6f42c07..00a71b1 100644 --- a/daemon/SessionData.h +++ b/daemon/SessionData.h @@ -13,7 +13,7 @@ #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 { @@ -36,7 +36,6 @@ public: char* mEventsXMLPath; char* mTargetPath; char* mAPCDir; - char* mTitle; bool mWaitingOnCommand; bool mSessionIsActive; @@ -48,15 +47,13 @@ public: 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]; @@ -66,7 +63,6 @@ public: 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 f1a8258..4c373d8 100644 --- a/daemon/SessionXML.cpp +++ b/daemon/SessionXML.cpp @@ -19,21 +19,13 @@ static const char* TAG_SESSION = "session"; static const char* TAG_IMAGE = "image"; static const char* ATTR_VERSION = "version"; -static const char* ATTR_TITLE = "title"; -static const char* ATTR_UUID = "uuid"; static const char* ATTR_CALL_STACK_UNWINDING = "call_stack_unwinding"; static const char* ATTR_BUFFER_MODE = "buffer_mode"; static const char* ATTR_SAMPLE_RATE = "sample_rate"; -static const char* ATTR_TARGET_PATH = "target_path"; -static const char* ATTR_OUTPUT_PATH = "output_path"; static const char* ATTR_DURATION = "duration"; static const char* ATTR_PATH = "path"; SessionXML::SessionXML(const char* str) { - parameters.title = 0; - parameters.uuid[0] = 0; - parameters.target_path = 0; - parameters.output_path = 0; parameters.buffer_mode[0] = 0; parameters.sample_rate[0] = 0; parameters.duration = 0; @@ -75,34 +67,7 @@ void SessionXML::sessionTag(mxml_node_t *tree, mxml_node_t *node) { 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 c2b5489..f7a5641 100644 --- a/daemon/SessionXML.h +++ b/daemon/SessionXML.h @@ -13,10 +13,6 @@ #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 diff --git a/daemon/StreamlineSetup.cpp b/daemon/StreamlineSetup.cpp index 53729ab..3f59eab 100644 --- a/daemon/StreamlineSetup.cpp +++ b/daemon/StreamlineSetup.cpp @@ -28,13 +28,13 @@ static const char* TAG_SESSION = "session"; 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; @@ -81,6 +81,11 @@ StreamlineSetup::StreamlineSetup(OlySocket* s) { free(data); } + + if (gSessionData->mCounterOverflow) { + logg->logError(__FILE__, __LINE__, "Exceeded maximum number of %d performance counters", MAX_PERFORMANCE_COUNTERS); + handleException(); + } } StreamlineSetup::~StreamlineSetup() { @@ -143,30 +148,32 @@ char* StreamlineSetup::readCommand(int* command) { 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 { @@ -215,21 +222,6 @@ void StreamlineSetup::sendData(const char* data, int length, int type) { 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);; @@ -264,10 +256,10 @@ void StreamlineSetup::sendConfiguration() { } 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) { @@ -282,7 +274,7 @@ void StreamlineSetup::sendDefaults() { 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 @@ -328,4 +320,9 @@ void StreamlineSetup::writeConfiguration(char* xml) { // 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(); + } } diff --git a/daemon/StreamlineSetup.h b/daemon/StreamlineSetup.h index c46ae08..8086fe2 100644 --- a/daemon/StreamlineSetup.h +++ b/daemon/StreamlineSetup.h @@ -35,7 +35,6 @@ private: 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(); diff --git a/daemon/configuration.xml b/daemon/configuration.xml index 4875f1f..fbdef31 100644 --- a/daemon/configuration.xml +++ b/daemon/configuration.xml @@ -1,49 +1,45 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - diff --git a/daemon/events-ARM11.xml b/daemon/events-ARM11.xml index d4a2914..0a5ee66 100644 --- a/daemon/events-ARM11.xml +++ b/daemon/events-ARM11.xml @@ -1,9 +1,5 @@ - - - - - - + + diff --git a/daemon/events-ARM11MPCore.xml b/daemon/events-ARM11MPCore.xml index 7de51b0..1a9ca3f 100644 --- a/daemon/events-ARM11MPCore.xml +++ b/daemon/events-ARM11MPCore.xml @@ -1,9 +1,5 @@ - - - - - - + + diff --git a/daemon/events-Cortex-A15.xml b/daemon/events-Cortex-A15.xml index d6222eb..0ec196f 100644 --- a/daemon/events-Cortex-A15.xml +++ b/daemon/events-Cortex-A15.xml @@ -1,12 +1,5 @@ - - - - - - - - - + + @@ -19,7 +12,6 @@ - diff --git a/daemon/events-Cortex-A5.xml b/daemon/events-Cortex-A5.xml index e01492b..4a894d3 100644 --- a/daemon/events-Cortex-A5.xml +++ b/daemon/events-Cortex-A5.xml @@ -1,8 +1,5 @@ - - - - - + + diff --git a/daemon/events-Cortex-A7.xml b/daemon/events-Cortex-A7.xml index 9ee4580..2bd4797 100644 --- a/daemon/events-Cortex-A7.xml +++ b/daemon/events-Cortex-A7.xml @@ -1,10 +1,5 @@ - - - - - - - + + diff --git a/daemon/events-Cortex-A8.xml b/daemon/events-Cortex-A8.xml index 1981c36..fe4c69d 100644 --- a/daemon/events-Cortex-A8.xml +++ b/daemon/events-Cortex-A8.xml @@ -1,10 +1,5 @@ - - - - - - - + + diff --git a/daemon/events-Cortex-A9.xml b/daemon/events-Cortex-A9.xml index faccb2f..7597f78 100644 --- a/daemon/events-Cortex-A9.xml +++ b/daemon/events-Cortex-A9.xml @@ -1,12 +1,5 @@ - - - - - - - - - + + diff --git a/daemon/events-Krait-architected.xml b/daemon/events-Krait-architected.xml index 6f2982e..06c1901 100644 --- a/daemon/events-Krait-architected.xml +++ b/daemon/events-Krait-architected.xml @@ -1,10 +1,5 @@ - - - - - - - + + diff --git a/daemon/events-L2C-310.xml b/daemon/events-L2C-310.xml index 695b6b8..4da4d1d 100644 --- a/daemon/events-L2C-310.xml +++ b/daemon/events-L2C-310.xml @@ -1,8 +1,5 @@ - - - - - + + diff --git a/daemon/events-Linux.xml b/daemon/events-Linux.xml index 3f626b3..b45a122 100644 --- a/daemon/events-Linux.xml +++ b/daemon/events-Linux.xml @@ -1,17 +1,15 @@ - - - + - + diff --git a/daemon/events-Mali-400.xml b/daemon/events-Mali-400.xml index cb1c6b4..6830d46 100644 --- a/daemon/events-Mali-400.xml +++ b/daemon/events-Mali-400.xml @@ -1,33 +1,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + @@ -54,7 +33,7 @@ - + @@ -113,7 +92,7 @@ - + @@ -172,7 +151,7 @@ - + @@ -231,7 +210,7 @@ - + @@ -290,7 +269,7 @@ - + @@ -352,7 +331,7 @@ - + @@ -363,7 +342,7 @@ - + diff --git a/daemon/events-Scorpion.xml b/daemon/events-Scorpion.xml index 51ed937..1642e85 100644 --- a/daemon/events-Scorpion.xml +++ b/daemon/events-Scorpion.xml @@ -1,10 +1,5 @@ - - - - - - - + + diff --git a/daemon/events-ScorpionMP.xml b/daemon/events-ScorpionMP.xml index d3dd430..42acc64 100644 --- a/daemon/events-ScorpionMP.xml +++ b/daemon/events-ScorpionMP.xml @@ -1,10 +1,5 @@ - - - - - - - + + diff --git a/daemon/main.cpp b/daemon/main.cpp index d972913..5bc75ef 100644 --- a/daemon/main.cpp +++ b/daemon/main.cpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include "Child.h" #include "SessionData.h" #include "OlySocket.h" @@ -114,6 +116,26 @@ int mountGatorFS() { } } +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; @@ -162,11 +184,15 @@ int setupFilesystem(char* module) { } // 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) { @@ -183,8 +209,11 @@ int shutdownFilesystem() { 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; + } } } @@ -205,7 +234,7 @@ struct cmdline_t parseCommandLine(int argc, char** argv) { snprintf(version_string, sizeof(version_string), "Streamline gatord development version %d", PROTOCOL_VERSION); } - while ((c = getopt(argc, argv, "hvp:s:c:e:m:")) != -1) { + while ((c = getopt(argc, argv, "hvp:s:c:e:m:o:")) != -1) { switch(c) { case 'c': gSessionData->mConfigurationXMLPath = optarg; @@ -222,6 +251,9 @@ struct cmdline_t parseCommandLine(int argc, char** argv) { case 's': gSessionData->mSessionXMLPath = optarg; break; + case 'o': + gSessionData->mTargetPath = optarg; + break; case 'h': case '?': logg->logError(__FILE__, __LINE__, @@ -232,6 +264,7 @@ struct cmdline_t parseCommandLine(int argc, char** argv) { "-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(); @@ -249,6 +282,11 @@ struct cmdline_t parseCommandLine(int argc, char** argv) { 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(); @@ -259,6 +297,7 @@ struct cmdline_t parseCommandLine(int argc, char** argv) { // 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 025dd9e..6cafecf 100644 --- a/driver/Makefile +++ b/driver/Makefile @@ -27,6 +27,10 @@ gator-y += gator_events_mali_common.o 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 6b96109..5a40e17 100644 --- a/driver/gator.h +++ b/driver/gator.h @@ -20,19 +20,20 @@ #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 @@ -97,4 +98,6 @@ int gator_events_install(struct gator_interface *interface); int gator_events_get_key(void); extern u32 gator_cpuid(void); +void gator_backtrace_handler(struct pt_regs * const regs); + #endif // GATOR_H_ diff --git a/driver/gator_annotate.c b/driver/gator_annotate.c index b444789..928e252 100644 --- 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; @@ -71,9 +79,9 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t } // 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); @@ -118,9 +126,9 @@ static int annotate_release(struct inode *inode, struct file *file) 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 } @@ -148,5 +156,8 @@ static int gator_annotate_start(void) static void gator_annotate_stop(void) { + // the spinlock here will ensure that when this function exits, we are not in the middle of an annotation + spin_lock(&annotate_lock); collect_annotations = false; + spin_unlock(&annotate_lock); } diff --git a/driver/gator_annotate_kernel.c b/driver/gator_annotate_kernel.c index ffab087..bc68fa8 100644 --- a/driver/gator_annotate_kernel.c +++ b/driver/gator_annotate_kernel.c @@ -7,50 +7,83 @@ * */ -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); @@ -58,33 +91,27 @@ 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); diff --git a/driver/gator_backtrace.c b/driver/gator_backtrace.c index 50783d6..2173d8a 100644 --- a/driver/gator_backtrace.c +++ b/driver/gator_backtrace.c @@ -15,7 +15,7 @@ struct frame_tail_eabi { 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; @@ -32,7 +32,7 @@ static void arm_backtrace_eabi(int cpu, int buftype, struct pt_regs * const regs } /* 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) { @@ -50,7 +50,7 @@ static void arm_backtrace_eabi(int cpu, int buftype, struct pt_regs * const regs 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); @@ -91,7 +91,7 @@ static int report_trace(struct stackframe *frame, void *d) // 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 @@ -106,7 +106,6 @@ static void kernel_backtrace(int cpu, int buftype, struct pt_regs * const regs) 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 d7d8e84..b2ed686 100644 --- a/driver/gator_cookies.c +++ b/driver/gator_cookies.c @@ -12,7 +12,7 @@ #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); @@ -20,9 +20,9 @@ static DEFINE_PER_CPU(uint64_t *, cookie_keys); 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; @@ -40,16 +40,16 @@ static uint32_t cookiemap_code(uint64_t value64) { 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); } /* @@ -104,15 +104,15 @@ static void cookiemap_add(uint64_t key, uint32_t value) { 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; } @@ -129,9 +129,9 @@ static void wq_cookie_handler(struct work_struct *unused) 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; @@ -222,7 +222,7 @@ 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; @@ -286,14 +286,14 @@ static int get_exec_cookie(int cpu, int buftype, struct task_struct *task) 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 */ @@ -350,7 +350,7 @@ static int cookies_initialize(void) } 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 deleted file mode 100644 index 6abdfa4..0000000 --- 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 -#include -#include - -#include - -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 diff --git a/driver/gator_events_block.c b/driver/gator_events_block.c index a8b8114..b18c3ca 100644 --- a/driver/gator_events_block.c +++ b/driver/gator_events_block.c @@ -25,15 +25,13 @@ static ulong block_rq_wr_enabled; 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) @@ -81,11 +82,6 @@ static int gator_events_block_create_files(struct super_block *sb, struct dentry 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)) @@ -113,44 +109,32 @@ static void gator_events_block_stop(void) 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; } diff --git a/driver/gator_events_mali_400.c b/driver/gator_events_mali_400.c index 38d5b3d..65eeb4f 100644 --- a/driver/gator_events_mali_400.c +++ b/driver/gator_events_mali_400.c @@ -17,14 +17,6 @@ #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 @@ -393,7 +385,7 @@ static int create_files(struct super_block *sb, struct dentry *root) { 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: diff --git a/driver/gator_events_mali_400.h b/driver/gator_events_mali_400.h index b784ae9..a09757e 100644 --- a/driver/gator_events_mali_400.h +++ b/driver/gator_events_mali_400.h @@ -1,11 +1,10 @@ -/* - * 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. + * */ /* diff --git a/driver/gator_events_mali_common.c b/driver/gator_events_mali_common.c index 2dd9ad6..62e441c 100644 --- a/driver/gator_events_mali_common.c +++ b/driver/gator_events_mali_common.c @@ -1,11 +1,10 @@ -/* - * 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" diff --git a/driver/gator_events_mali_common.h b/driver/gator_events_mali_common.h index cb851d5..2c9457f 100644 --- a/driver/gator_events_mali_common.h +++ b/driver/gator_events_mali_common.h @@ -1,12 +1,12 @@ -/* - * 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 @@ -39,6 +39,9 @@ typedef struct { 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); diff --git a/driver/gator_events_mali_t6xx.c b/driver/gator_events_mali_t6xx.c index 79af764..f8f868e 100644 --- a/driver/gator_events_mali_t6xx.c +++ b/driver/gator_events_mali_t6xx.c @@ -1,11 +1,10 @@ -/* - * 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" diff --git a/driver/gator_events_mali_t6xx_hw.c b/driver/gator_events_mali_t6xx_hw.c index 12ffebc..854d02d 100644 --- a/driver/gator_events_mali_t6xx_hw.c +++ b/driver/gator_events_mali_t6xx_hw.c @@ -1,11 +1,10 @@ -/* - * 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" @@ -23,6 +22,39 @@ #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 { @@ -322,7 +354,12 @@ static void *kernel_dump_buffer; 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; @@ -336,6 +373,96 @@ static mali_counter counters[NUMBER_OF_HARDWARE_COUNTERS]; */ 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; @@ -368,12 +495,23 @@ static int start(void) /* 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"); @@ -388,7 +526,7 @@ static int start(void) * * 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"); @@ -404,14 +542,14 @@ static int start(void) 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; @@ -420,10 +558,13 @@ static int start(void) 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; } @@ -448,10 +589,13 @@ static void stop(void) { 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(); } } @@ -461,11 +605,26 @@ static int read(int **buffer) { 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. @@ -484,8 +643,8 @@ static int read(int **buffer) { 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; @@ -520,7 +679,7 @@ static int read(int **buffer) { if (! kbase_device_busy) { kbase_device_busy = true; - kbase_instr_hwcnt_dump_irq(kbcontext); + kbase_instr_hwcnt_dump_irq_symbol(kbcontext); } } @@ -551,7 +710,6 @@ static int create_files(struct super_block *sb, struct dentry *root) return 0; } - static struct gator_interface gator_events_mali_t6xx_interface = { .create_files = create_files, .start = start, @@ -563,6 +721,10 @@ int gator_events_mali_t6xx_hw_init(void) { pr_debug("gator: Mali-T6xx: sw_counters init\n"); +#if GATOR_TEST + test_all_is_read_scheduled(); +#endif + gator_mali_initialise_counters(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 new file mode 100644 index 0000000..2a35e77 --- /dev/null +++ b/driver/gator_events_mali_t6xx_hw_test.c @@ -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); +} diff --git a/driver/gator_events_mmaped.c b/driver/gator_events_mmaped.c index f81c402..1be6e66 100644 --- a/driver/gator_events_mmaped.c +++ b/driver/gator_events_mmaped.c @@ -11,12 +11,8 @@ * To add them to the events.xml, create an events-mmap.xml with the * following contents and rebuild gatord: * - * - * - * - * - * - * + * + * * * * diff --git a/driver/gator_events_net.c b/driver/gator_events_net.c index 11282b5..31cc3ef 100644 --- a/driver/gator_events_net.c +++ b/driver/gator_events_net.c @@ -95,7 +95,11 @@ static int gator_events_net_start(void) 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; } diff --git a/driver/gator_events_perf_pmu.c b/driver/gator_events_perf_pmu.c index 9d78b46..e025155 100644 --- a/driver/gator_events_perf_pmu.c +++ b/driver/gator_events_perf_pmu.c @@ -32,7 +32,6 @@ static DEFINE_PER_CPU(int[CNTMAX], perfPrevDelta); static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt); static DEFINE_PER_CPU(struct perf_event *[CNTMAX], pevent); static DEFINE_PER_CPU(struct perf_event_attr *[CNTMAX], pevent_attr); -extern DEFINE_PER_CPU(struct perf_event *, pevent_ebs); static void gator_events_perf_pmu_stop(void); @@ -63,6 +62,15 @@ static int gator_events_perf_pmu_create_files(struct super_block *sb, struct den 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); @@ -102,18 +105,22 @@ static int gator_events_perf_pmu_online(int** buffer) 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); @@ -154,6 +161,18 @@ static int gator_events_perf_pmu_start(void) { 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++) { @@ -174,7 +193,7 @@ static int gator_events_perf_pmu_start(void) 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 @@ -212,14 +231,9 @@ static int gator_events_perf_pmu_read(int **buffer) { 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); @@ -300,6 +314,11 @@ int gator_events_perf_pmu_init(void) 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 f6c1135..309c6c2 100644 --- a/driver/gator_main.c +++ b/driver/gator_main.c @@ -7,7 +7,7 @@ * */ -static unsigned long gator_protocol_version = 10; +static unsigned long gator_protocol_version = 11; #include #include @@ -48,50 +48,74 @@ static unsigned long gator_protocol_version = 10; #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 @@ -101,17 +125,13 @@ static unsigned long userspace_buffer_size; 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); @@ -125,10 +145,10 @@ static bool buffer_check_space(int cpu, int buftype, int bytes); 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]; @@ -152,17 +172,20 @@ static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer); #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 @@ -237,7 +260,7 @@ static bool buffer_check_space(int cpu, int buftype, int bytes) 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]; @@ -252,7 +275,7 @@ static void gator_buffer_write_bytes(int cpu, int buftype, char *x, int len) 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); @@ -263,22 +286,38 @@ static void gator_buffer_header(int cpu, int buftype) { 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); @@ -308,10 +347,10 @@ static void buffer_check(int cpu, int buftype) } } -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; @@ -320,26 +359,29 @@ static void gator_add_trace(int cpu, int buftype, unsigned int 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; @@ -397,8 +446,6 @@ static void gator_timer_offline_dispatch(int cpu) 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) @@ -436,6 +483,32 @@ static void gator_timer_online(void* unused) } 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' @@ -446,8 +519,6 @@ static void gator_timer_online_dispatch(int 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) @@ -461,10 +532,6 @@ 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; @@ -481,8 +548,9 @@ static uint64_t gator_get_time(void) 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; } @@ -568,20 +636,15 @@ static void gator_notifier_stop(void) ******************************************************************************/ 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) @@ -656,8 +719,6 @@ static int gator_start(void) 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()) @@ -668,8 +729,6 @@ static int gator_start(void) notifier_failure: gator_timer_stop(); timer_failure: - gator_event_sampling_stop(); -event_sampling_failure: gator_trace_gpu_stop(); gpu_failure: gator_trace_power_stop(); @@ -697,7 +756,6 @@ static void gator_stop(void) 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 @@ -720,26 +778,32 @@ static int gator_op_setup(void) 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++) { @@ -1047,8 +1111,8 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root) 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); diff --git a/driver/gator_marshaling.c b/driver/gator_marshaling.c index 630d142..a84b280 100644 --- a/driver/gator_marshaling.c +++ b/driver/gator_marshaling.c @@ -9,40 +9,44 @@ 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); @@ -57,9 +61,9 @@ static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inK 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); } @@ -76,15 +80,15 @@ static bool marshal_event_header(void) { 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; } @@ -104,17 +108,17 @@ static void marshal_event(int len, int* buffer) { // 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) { @@ -132,17 +136,17 @@ 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 @@ -151,28 +155,28 @@ static void marshal_event_single(int core, int key, int value) { 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 @@ -237,3 +278,18 @@ static void marshal_frame(int cpu, int buftype, int frame) { 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 925469a..5ad53db 100644 --- a/driver/gator_pack.c +++ b/driver/gator_pack.c @@ -141,7 +141,7 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long 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; } } diff --git a/driver/gator_trace_gpu.c b/driver/gator_trace_gpu.c index d053987..0511d71 100644 --- a/driver/gator_trace_gpu.c +++ b/driver/gator_trace_gpu.c @@ -33,9 +33,7 @@ static int mali_timeline_trace_registered; 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) diff --git a/driver/gator_trace_power.c b/driver/gator_trace_power.c index ca89b19..b1687e1 100644 --- a/driver/gator_trace_power.c +++ b/driver/gator_trace_power.c @@ -9,6 +9,7 @@ #include #include +#include // 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 @@ -52,32 +53,29 @@ GATOR_DEFINE_PROBE(cpu_frequency, TP_PROTO(unsigned int frequency, unsigned int 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); } } diff --git a/driver/gator_trace_sched.c b/driver/gator_trace_sched.c index 08b0270..9ddb822 100644 --- a/driver/gator_trace_sched.c +++ b/driver/gator_trace_sched.c @@ -17,6 +17,7 @@ #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, @@ -59,7 +60,7 @@ void emit_pid_name(struct task_struct* task) 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 2e51670..2cc6411 100644 --- a/driver/mali_t6xx.mk +++ b/driver/mali_t6xx.mk @@ -11,13 +11,14 @@ EXTRA_CFLAGS += -DMALI_USE_UMP=1 \ 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 -- cgit v1.2.3