summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--daemon/Android.mk80
-rw-r--r--daemon/CapturedXML.cpp41
-rw-r--r--daemon/CapturedXML.h2
-rw-r--r--daemon/Collector.cpp2
-rw-r--r--daemon/ConfigurationXML.cpp8
-rw-r--r--daemon/Fifo.cpp16
-rw-r--r--daemon/Fifo.h12
-rw-r--r--daemon/LocalCapture.cpp4
-rw-r--r--daemon/Logging.h2
-rw-r--r--daemon/Makefile42
-rw-r--r--daemon/OlySocket.cpp362
-rw-r--r--daemon/OlySocket.h40
-rw-r--r--daemon/OlyUtility.cpp361
-rw-r--r--daemon/OlyUtility.h28
-rw-r--r--daemon/Sender.cpp4
-rw-r--r--daemon/SessionData.cpp1
-rw-r--r--daemon/SessionData.h2
-rw-r--r--daemon/SessionXML.cpp2
-rw-r--r--daemon/StreamlineSetup.cpp2
-rw-r--r--daemon/events-Cortex-A15.xml2
-rw-r--r--daemon/events-Cortex-A7.xml2
-rw-r--r--daemon/events-Cortex-A9.xml12
-rw-r--r--daemon/events-Linux.xml4
-rw-r--r--daemon/events-Mali-400.xml8
-rw-r--r--daemon/events-Mali-T6xx.xml12
-rw-r--r--daemon/events-Mali-T6xx_hw.xml8
-rw-r--r--daemon/events-ScorpionMP.xml2
-rw-r--r--daemon/main.cpp9
-rw-r--r--driver/Makefile2
-rw-r--r--driver/gator.h52
-rw-r--r--driver/gator_annotate.c17
-rw-r--r--driver/gator_annotate_kernel.c132
-rw-r--r--driver/gator_backtrace.c36
-rw-r--r--driver/gator_cookies.c105
-rw-r--r--driver/gator_events_armv6.c6
-rw-r--r--driver/gator_events_armv7.c18
-rw-r--r--driver/gator_events_block.c5
-rw-r--r--driver/gator_events_irq.c11
-rw-r--r--driver/gator_events_l2c-310.c18
-rw-r--r--driver/gator_events_mali_400.c1001
-rw-r--r--driver/gator_events_mali_common.c90
-rw-r--r--driver/gator_events_mali_common.h14
-rw-r--r--driver/gator_events_mali_t6xx.c716
-rw-r--r--driver/gator_events_mali_t6xx_hw.c1007
-rw-r--r--driver/gator_events_mali_t6xx_hw_test.c20
-rw-r--r--driver/gator_events_meminfo.c14
-rw-r--r--driver/gator_events_mmaped.c34
-rw-r--r--driver/gator_events_net.c9
-rw-r--r--driver/gator_events_perf_pmu.c77
-rw-r--r--driver/gator_events_sched.c1
-rw-r--r--driver/gator_events_scorpion.c218
-rw-r--r--driver/gator_fs.c58
-rw-r--r--driver/gator_main.c368
-rw-r--r--driver/gator_marshaling.c179
-rw-r--r--driver/gator_pack.c110
-rw-r--r--driver/gator_trace_gpu.c76
-rw-r--r--driver/gator_trace_gpu.h60
-rw-r--r--driver/gator_trace_power.c46
-rw-r--r--driver/gator_trace_sched.c24
59 files changed, 2867 insertions, 2727 deletions
diff --git a/daemon/Android.mk b/daemon/Android.mk
index cbaf42d..b8cc7ff 100644
--- a/daemon/Android.mk
+++ b/daemon/Android.mk
@@ -1,41 +1,39 @@
1LOCAL_PATH:= $(call my-dir) 1LOCAL_PATH := $(call my-dir)
2include $(CLEAR_VARS) 2include $(CLEAR_VARS)
3 3
4$(shell cd $(LOCAL_PATH);cat events_header.xml events-*\.xml events_footer.xml > events.xml;xxd -i events.xml > events_xml.h;xxd -i configuration.xml > configuration_xml.h) 4XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h configuration_xml.h)
5 5
6LOCAL_CFLAGS += -Wall -O3 -ftree-vectorize -Wno-error=sequence-point 6LOCAL_CFLAGS += -Wall -O3 -mthumb-interwork -fno-exceptions
7 7
8LOCAL_SRC_FILES:= \ 8LOCAL_SRC_FILES := \
9 CapturedXML.cpp \ 9 CapturedXML.cpp \
10 Child.cpp \ 10 Child.cpp \
11 Collector.cpp \ 11 Collector.cpp \
12 ConfigurationXML.cpp \ 12 ConfigurationXML.cpp \
13 Fifo.cpp \ 13 Fifo.cpp \
14 LocalCapture.cpp \ 14 LocalCapture.cpp \
15 Logging.cpp \ 15 Logging.cpp \
16 main.cpp \ 16 main.cpp \
17 OlySocket.cpp \ 17 OlySocket.cpp \
18 OlyUtility.cpp \ 18 OlyUtility.cpp \
19 Sender.cpp \ 19 Sender.cpp \
20 SessionData.cpp \ 20 SessionData.cpp \
21 SessionXML.cpp \ 21 SessionXML.cpp \
22 StreamlineSetup.cpp \ 22 StreamlineSetup.cpp \
23 mxml/mxml-attr.c \ 23 mxml/mxml-attr.c \
24 mxml/mxml-entity.c \ 24 mxml/mxml-entity.c \
25 mxml/mxml-file.c \ 25 mxml/mxml-file.c \
26 mxml/mxml-get.c \ 26 mxml/mxml-get.c \
27 mxml/mxml-index.c \ 27 mxml/mxml-index.c \
28 mxml/mxml-node.c \ 28 mxml/mxml-node.c \
29 mxml/mxml-private.c \ 29 mxml/mxml-private.c \
30 mxml/mxml-search.c \ 30 mxml/mxml-search.c \
31 mxml/mxml-set.c \ 31 mxml/mxml-set.c \
32 mxml/mxml-string.c 32 mxml/mxml-string.c
33 33
34LOCAL_C_INCLUDES := $(LOCAL_PATH) 34LOCAL_C_INCLUDES := $(LOCAL_PATH)
35 35
36LOCAL_MODULE:= gatord 36LOCAL_MODULE := gatord
37LOCAL_MODULE_TAGS:= optional 37LOCAL_MODULE_TAGS := optional
38 38
39LOCAL_LDLIBS := -lz -llog 39include $(BUILD_EXECUTABLE)
40
41include $(BUILD_EXECUTABLE)
diff --git a/daemon/CapturedXML.cpp b/daemon/CapturedXML.cpp
index 30d984f..cc218d7 100644
--- a/daemon/CapturedXML.cpp
+++ b/daemon/CapturedXML.cpp
@@ -14,8 +14,6 @@
14#include "Logging.h" 14#include "Logging.h"
15#include "OlyUtility.h" 15#include "OlyUtility.h"
16 16
17extern void handleException();
18
19CapturedXML::CapturedXML() { 17CapturedXML::CapturedXML() {
20} 18}
21 19
@@ -111,3 +109,42 @@ void CapturedXML::write(char* path) {
111 free(xml); 109 free(xml);
112 free(file); 110 free(file);
113} 111}
112
113// whitespace callback utility function used with mini-xml
114const char * mxmlWhitespaceCB(mxml_node_t *node, int loc) {
115 const char *name;
116
117 name = mxmlGetElement(node);
118
119 if (loc == MXML_WS_BEFORE_OPEN) {
120 // Single indentation
121 if (!strcmp(name, "target") || !strcmp(name, "counters"))
122 return("\n ");
123
124 // Double indentation
125 if (!strcmp(name, "counter"))
126 return("\n ");
127
128 // Avoid a carriage return on the first line of the xml file
129 if (!strncmp(name, "?xml", 4))
130 return(NULL);
131
132 // Default - no indentation
133 return("\n");
134 }
135
136 if (loc == MXML_WS_BEFORE_CLOSE) {
137 // No indentation
138 if (!strcmp(name, "captured"))
139 return("\n");
140
141 // Single indentation
142 if (!strcmp(name, "counters"))
143 return("\n ");
144
145 // Default - no carriage return
146 return(NULL);
147 }
148
149 return(NULL);
150}
diff --git a/daemon/CapturedXML.h b/daemon/CapturedXML.h
index 3f6a4de..3cac576 100644
--- a/daemon/CapturedXML.h
+++ b/daemon/CapturedXML.h
@@ -22,4 +22,6 @@ private:
22 mxml_node_t* getTree(bool includeTime); 22 mxml_node_t* getTree(bool includeTime);
23}; 23};
24 24
25const char * mxmlWhitespaceCB(mxml_node_t *node, int where);
26
25#endif //__CAPTURED_XML_H__ 27#endif //__CAPTURED_XML_H__
diff --git a/daemon/Collector.cpp b/daemon/Collector.cpp
index 25bb934..2e4af0c 100644
--- a/daemon/Collector.cpp
+++ b/daemon/Collector.cpp
@@ -18,8 +18,6 @@
18#include "Logging.h" 18#include "Logging.h"
19#include "Sender.h" 19#include "Sender.h"
20 20
21extern void handleException();
22
23// Driver initialization independent of session settings 21// Driver initialization independent of session settings
24Collector::Collector() { 22Collector::Collector() {
25 char text[sizeof(gSessionData->mPerfCounterType[0]) + 30]; // sufficiently large to hold all /dev/gator/events/<types>/<file> 23 char text[sizeof(gSessionData->mPerfCounterType[0]) + 30]; // sufficiently large to hold all /dev/gator/events/<types>/<file>
diff --git a/daemon/ConfigurationXML.cpp b/daemon/ConfigurationXML.cpp
index a213cbb..14c2809 100644
--- a/daemon/ConfigurationXML.cpp
+++ b/daemon/ConfigurationXML.cpp
@@ -14,8 +14,6 @@
14#include "OlyUtility.h" 14#include "OlyUtility.h"
15#include "SessionData.h" 15#include "SessionData.h"
16 16
17extern void handleException();
18
19static const char* ATTR_COUNTER = "counter"; 17static const char* ATTR_COUNTER = "counter";
20static const char* ATTR_REVISION = "revision"; 18static const char* ATTR_REVISION = "revision";
21static const char* ATTR_TITLE = "title"; 19static const char* ATTR_TITLE = "title";
@@ -33,7 +31,7 @@ ConfigurationXML::ConfigurationXML() {
33 const char * configuration_xml; 31 const char * configuration_xml;
34 unsigned int configuration_xml_len; 32 unsigned int configuration_xml_len;
35 getDefaultConfigurationXml(configuration_xml, configuration_xml_len); 33 getDefaultConfigurationXml(configuration_xml, configuration_xml_len);
36 34
37 mIndex = 0; 35 mIndex = 0;
38 char* path = (char*)malloc(PATH_MAX); 36 char* path = (char*)malloc(PATH_MAX);
39 37
@@ -171,7 +169,7 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) {
171 if (mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION)) gSessionData->mPerfCounterAverageSelection[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION), false); 169 if (mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION)) gSessionData->mPerfCounterAverageSelection[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION), false);
172 gSessionData->mPerfCounterEnabled[mIndex] = true; 170 gSessionData->mPerfCounterEnabled[mIndex] = true;
173 171
174 // strncpy does not guarantee a null-termianted string 172 // strncpy does not guarantee a null-terminated string
175 gSessionData->mPerfCounterType[mIndex][sizeof(gSessionData->mPerfCounterType[mIndex]) - 1] = 0; 173 gSessionData->mPerfCounterType[mIndex][sizeof(gSessionData->mPerfCounterType[mIndex]) - 1] = 0;
176 gSessionData->mPerfCounterTitle[mIndex][sizeof(gSessionData->mPerfCounterTitle[mIndex]) - 1] = 0; 174 gSessionData->mPerfCounterTitle[mIndex][sizeof(gSessionData->mPerfCounterTitle[mIndex]) - 1] = 0;
177 gSessionData->mPerfCounterName[mIndex][sizeof(gSessionData->mPerfCounterName[mIndex]) - 1] = 0; 175 gSessionData->mPerfCounterName[mIndex][sizeof(gSessionData->mPerfCounterName[mIndex]) - 1] = 0;
@@ -184,8 +182,6 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) {
184} 182}
185 183
186void ConfigurationXML::getDefaultConfigurationXml(const char * & xml, unsigned int & len) { 184void ConfigurationXML::getDefaultConfigurationXml(const char * & xml, unsigned int & len) {
187 // the first line of configuration_xml.h is "unsigned char configuration_xml", but configuration_xml needs to be const static as well
188 const static
189#include "configuration_xml.h" // defines and initializes char configuration_xml[] and int configuration_xml_len 185#include "configuration_xml.h" // defines and initializes char configuration_xml[] and int configuration_xml_len
190 xml = (const char *)configuration_xml; 186 xml = (const char *)configuration_xml;
191 len = configuration_xml_len; 187 len = configuration_xml_len;
diff --git a/daemon/Fifo.cpp b/daemon/Fifo.cpp
index 191536f..4a27452 100644
--- a/daemon/Fifo.cpp
+++ b/daemon/Fifo.cpp
@@ -12,8 +12,6 @@
12#include "Fifo.h" 12#include "Fifo.h"
13#include "Logging.h" 13#include "Logging.h"
14 14
15extern void handleException();
16
17// bufferSize is the amount of data to be filled 15// bufferSize is the amount of data to be filled
18// singleBufferSize is the maximum size that may be filled during a single write 16// singleBufferSize is the maximum size that may be filled during a single write
19// (bufferSize + singleBufferSize) will be allocated 17// (bufferSize + singleBufferSize) will be allocated
@@ -37,27 +35,29 @@ Fifo::Fifo(int singleBufferSize, int bufferSize) {
37 35
38Fifo::~Fifo() { 36Fifo::~Fifo() {
39 free(mBuffer); 37 free(mBuffer);
38 sem_destroy(&mWaitForSpaceSem);
39 sem_destroy(&mWaitForDataSem);
40} 40}
41 41
42int Fifo::numBytesFilled() { 42int Fifo::numBytesFilled() const {
43 return mWrite - mRead + mRaggedEnd; 43 return mWrite - mRead + mRaggedEnd;
44} 44}
45 45
46char* Fifo::start() { 46char* Fifo::start() const {
47 return mBuffer; 47 return mBuffer;
48} 48}
49 49
50bool Fifo::isEmpty() { 50bool Fifo::isEmpty() const {
51 return mRead == mWrite && mRaggedEnd == 0; 51 return mRead == mWrite && mRaggedEnd == 0;
52} 52}
53 53
54bool Fifo::isFull() { 54bool Fifo::isFull() const {
55 return willFill(0); 55 return willFill(0);
56} 56}
57 57
58// Determines if the buffer will fill assuming 'additional' bytes will be added to the buffer 58// Determines if the buffer will fill assuming 'additional' bytes will be added to the buffer
59// 'full' means there is less than singleBufferSize bytes available contiguously; it does not mean there are zero bytes available 59// 'full' means there is less than singleBufferSize bytes available contiguously; it does not mean there are zero bytes available
60bool Fifo::willFill(int additional) { 60bool Fifo::willFill(int additional) const {
61 if (mWrite > mRead) { 61 if (mWrite > mRead) {
62 if (numBytesFilled() + additional < mWrapThreshold) { 62 if (numBytesFilled() + additional < mWrapThreshold) {
63 return false; 63 return false;
@@ -98,7 +98,7 @@ char* Fifo::write(int length) {
98} 98}
99 99
100// This function will stall until data is available 100// This function will stall until data is available
101char* Fifo::read(int* length) { 101char* Fifo::read(int *const length) {
102 // update the read pointer now that the data has been handled 102 // update the read pointer now that the data has been handled
103 mRead = mReadCommit; 103 mRead = mReadCommit;
104 104
diff --git a/daemon/Fifo.h b/daemon/Fifo.h
index b460549..e2a5d94 100644
--- a/daemon/Fifo.h
+++ b/daemon/Fifo.h
@@ -15,13 +15,13 @@ class Fifo {
15public: 15public:
16 Fifo(int singleBufferSize, int totalBufferSize); 16 Fifo(int singleBufferSize, int totalBufferSize);
17 ~Fifo(); 17 ~Fifo();
18 int numBytesFilled(); 18 int numBytesFilled() const;
19 bool isEmpty(); 19 bool isEmpty() const;
20 bool isFull(); 20 bool isFull() const;
21 bool willFill(int additional); 21 bool willFill(int additional) const;
22 char* start(); 22 char* start() const;
23 char* write(int length); 23 char* write(int length);
24 char* read(int* length); 24 char* read(int *const length);
25 25
26private: 26private:
27 int mSingleBufferSize, mWrite, mRead, mReadCommit, mRaggedEnd, mWrapThreshold; 27 int mSingleBufferSize, mWrite, mRead, mReadCommit, mRaggedEnd, mWrapThreshold;
diff --git a/daemon/LocalCapture.cpp b/daemon/LocalCapture.cpp
index f8cd17f..2dd3aff 100644
--- a/daemon/LocalCapture.cpp
+++ b/daemon/LocalCapture.cpp
@@ -17,8 +17,6 @@
17#include "Logging.h" 17#include "Logging.h"
18#include "OlyUtility.h" 18#include "OlyUtility.h"
19 19
20extern void handleException();
21
22LocalCapture::LocalCapture() {} 20LocalCapture::LocalCapture() {}
23 21
24LocalCapture::~LocalCapture() {} 22LocalCapture::~LocalCapture() {}
@@ -56,7 +54,7 @@ char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* e
56 handleException(); 54 handleException();
57 } else if (initialPath[0] != '/') { 55 } else if (initialPath[0] != '/') {
58 if (getcwd(path, PATH_MAX) == 0) { 56 if (getcwd(path, PATH_MAX) == 0) {
59 logg->logMessage("Unable to retrive the current working directory"); 57 logg->logMessage("Unable to retrieve the current working directory");
60 } 58 }
61 strncat(path, "/", PATH_MAX - strlen(path) - 1); 59 strncat(path, "/", PATH_MAX - strlen(path) - 1);
62 strncat(path, initialPath, PATH_MAX - strlen(path) - 1); 60 strncat(path, initialPath, PATH_MAX - strlen(path) - 1);
diff --git a/daemon/Logging.h b/daemon/Logging.h
index 4247966..37f7dd3 100644
--- a/daemon/Logging.h
+++ b/daemon/Logging.h
@@ -42,4 +42,6 @@ private:
42 42
43extern Logging* logg; 43extern Logging* logg;
44 44
45extern void handleException();
46
45#endif //__LOGGING_H__ 47#endif //__LOGGING_H__
diff --git a/daemon/Makefile b/daemon/Makefile
index 5562db7..95d1809 100644
--- a/daemon/Makefile
+++ b/daemon/Makefile
@@ -8,10 +8,8 @@
8# targets it is necessary to add options 8# targets it is necessary to add options
9# '-marm -march=armv4t -mfloat-abi=soft'. 9# '-marm -march=armv4t -mfloat-abi=soft'.
10 10
11ARCH=arm 11CPP = $(CROSS_COMPILE)g++
12 12GCC = $(CROSS_COMPILE)gcc
13CPP=$(CROSS_COMPILE)g++
14GCC=$(CROSS_COMPILE)gcc
15 13
16# -g produces debugging information 14# -g produces debugging information
17# -O3 maximum optimization 15# -O3 maximum optimization
@@ -21,34 +19,40 @@ GCC=$(CROSS_COMPILE)gcc
21# -std=c++0x is the planned new c++ standard 19# -std=c++0x is the planned new c++ standard
22# -std=c++98 is the 1998 c++ standard 20# -std=c++98 is the 1998 c++ standard
23# -mthumb-interwork is required for interworking to ARM or Thumb stdlibc 21# -mthumb-interwork is required for interworking to ARM or Thumb stdlibc
24CFLAGS=-O3 -Wall -mthumb-interwork 22CFLAGS = -O3 -Wall -mthumb-interwork -fno-exceptions
23CXXFLAGS = -fno-rtti
25ifeq ($(WERROR),1) 24ifeq ($(WERROR),1)
26 CFLAGS += -Werror 25 CFLAGS += -Werror
27endif 26endif
28# -s strips the binary of debug info 27# -s strips the binary of debug info
29LDFLAGS=-s 28LDFLAGS = -s
30TARGET=gatord 29TARGET = gatord
31C_SRC = $(wildcard mxml/*.c) 30C_SRC = $(wildcard mxml/*.c)
32CPP_SRC = $(wildcard *.cpp) 31CPP_SRC = $(wildcard *.cpp)
33TGT_OBJS = $(CPP_SRC:%.cpp=%.o) \
34 $(C_SRC:%.c=%.o)
35 32
36all: $(TARGET) 33all: $(TARGET)
37 34
35events.xml: events_header.xml $(wildcard events-*.xml) events_footer.xml
36 cat $^ > $@
37
38StreamlineSetup.cpp: events_xml.h
39ConfigurationXML.cpp: configuration_xml.h
40
41%_xml.h: %.xml escape
42 ./escape $< > $@
43
38%.o: %.c *.h 44%.o: %.c *.h
39 $(GCC) -c $(CFLAGS) -o $@ $< 45 $(GCC) -c $(CFLAGS) -o $@ $<
40 46
41%.o: %.cpp *.h 47%.o: %.cpp *.h
42 $(CPP) -c $(CFLAGS) -o $@ $< 48 $(CPP) -c $(CFLAGS) $(CXXFLAGS) -o $@ $<
43 49
44$(TARGET): convert $(TGT_OBJS) 50$(TARGET): $(CPP_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o)
45 $(CPP) $(LDFLAGS) -o $@ $(TGT_OBJS) -lc -lrt -lpthread 51 $(CPP) $(LDFLAGS) -o $@ $^ -lc -lrt -lpthread
46 rm events_xml.h configuration_xml.h 52 rm -f events_xml.h configuration_xml.h
47 53
48convert: 54escape: escape.c
49 cat events_header.xml events-*\.xml events_footer.xml > events.xml 55 gcc $^ -o $@
50 xxd -i events.xml > events_xml.h
51 xxd -i configuration.xml > configuration_xml.h
52 56
53clean: 57clean:
54 rm -f *.o mxml/*.o $(TARGET) events.xml events_xml.h configuration_xml.h 58 rm -f *.o mxml/*.o $(TARGET) escape events.xml events_xml.h configuration_xml.h
diff --git a/daemon/OlySocket.cpp b/daemon/OlySocket.cpp
index a3bf746..6128dc0 100644
--- a/daemon/OlySocket.cpp
+++ b/daemon/OlySocket.cpp
@@ -20,242 +20,240 @@
20 20
21#ifdef WIN32 21#ifdef WIN32
22#define CLOSE_SOCKET(x) closesocket(x) 22#define CLOSE_SOCKET(x) closesocket(x)
23#define SHUTDOWN_RX_TX SD_BOTH 23#define SHUTDOWN_RX_TX SD_BOTH
24#define snprintf _snprintf 24#define snprintf _snprintf
25#else 25#else
26#define CLOSE_SOCKET(x) close(x) 26#define CLOSE_SOCKET(x) close(x)
27#define SHUTDOWN_RX_TX SHUT_RDWR 27#define SHUTDOWN_RX_TX SHUT_RDWR
28#endif 28#endif
29 29
30extern void handleException();
31
32OlySocket::OlySocket(int port, bool multiple) { 30OlySocket::OlySocket(int port, bool multiple) {
33#ifdef WIN32 31#ifdef WIN32
34 WSADATA wsaData; 32 WSADATA wsaData;
35 if (WSAStartup(0x0202, &wsaData) != 0) { 33 if (WSAStartup(0x0202, &wsaData) != 0) {
36 logg->logError(__FILE__, __LINE__, "Windows socket initialization failed"); 34 logg->logError(__FILE__, __LINE__, "Windows socket initialization failed");
37 handleException(); 35 handleException();
38 } 36 }
39#endif 37#endif
40 38
41 if (multiple) { 39 if (multiple) {
42 createServerSocket(port); 40 createServerSocket(port);
43 } else { 41 } else {
44 createSingleServerConnection(port); 42 createSingleServerConnection(port);
45 } 43 }
46} 44}
47 45
48OlySocket::OlySocket(int port, char* host) { 46OlySocket::OlySocket(int port, char* host) {
49 mFDServer = 0; 47 mFDServer = 0;
50 createClientSocket(host, port); 48 createClientSocket(host, port);
51} 49}
52 50
53OlySocket::~OlySocket() { 51OlySocket::~OlySocket() {
54 if (mSocketID > 0) { 52 if (mSocketID > 0) {
55 CLOSE_SOCKET(mSocketID); 53 CLOSE_SOCKET(mSocketID);
56 } 54 }
57} 55}
58 56
59void OlySocket::shutdownConnection() { 57void OlySocket::shutdownConnection() {
60 // Shutdown is primarily used to unblock other threads that are blocking on send/receive functions 58 // Shutdown is primarily used to unblock other threads that are blocking on send/receive functions
61 shutdown(mSocketID, SHUTDOWN_RX_TX); 59 shutdown(mSocketID, SHUTDOWN_RX_TX);
62} 60}
63 61
64void OlySocket::closeSocket() { 62void OlySocket::closeSocket() {
65 // Used for closing an accepted socket but keeping the server socket active 63 // Used for closing an accepted socket but keeping the server socket active
66 if (mSocketID > 0) { 64 if (mSocketID > 0) {
67 CLOSE_SOCKET(mSocketID); 65 CLOSE_SOCKET(mSocketID);
68 mSocketID = -1; 66 mSocketID = -1;
69 } 67 }
70} 68}
71 69
72void OlySocket::closeServerSocket() { 70void OlySocket::closeServerSocket() {
73 if (CLOSE_SOCKET(mFDServer) != 0) { 71 if (CLOSE_SOCKET(mFDServer) != 0) {
74 logg->logError(__FILE__, __LINE__, "Failed to close server socket."); 72 logg->logError(__FILE__, __LINE__, "Failed to close server socket.");
75 handleException(); 73 handleException();
76 } 74 }
77 mFDServer = 0; 75 mFDServer = 0;
78} 76}
79 77
80void OlySocket::createClientSocket(char* hostname, int portno) { 78void OlySocket::createClientSocket(char* hostname, int portno) {
81#ifdef WIN32 79#ifdef WIN32
82 // TODO: Implement for Windows 80 // TODO: Implement for Windows
83#else 81#else
84 char buf[32]; 82 char buf[32];
85 struct addrinfo hints, *res, *res0; 83 struct addrinfo hints, *res, *res0;
86 84
87 snprintf(buf, sizeof(buf), "%d", portno); 85 snprintf(buf, sizeof(buf), "%d", portno);
88 mSocketID = -1; 86 mSocketID = -1;
89 memset((void*)&hints, 0, sizeof(hints)); 87 memset((void*)&hints, 0, sizeof(hints));
90 hints.ai_family = PF_UNSPEC; 88 hints.ai_family = PF_UNSPEC;
91 hints.ai_socktype = SOCK_STREAM; 89 hints.ai_socktype = SOCK_STREAM;
92 90
93 if (getaddrinfo(hostname, buf, &hints, &res0)) { 91 if (getaddrinfo(hostname, buf, &hints, &res0)) {
94 logg->logError(__FILE__, __LINE__, "Client socket failed to get address info for %s", hostname); 92 logg->logError(__FILE__, __LINE__, "Client socket failed to get address info for %s", hostname);
95 handleException(); 93 handleException();
96 } 94 }
97 for (res=res0; res!=NULL; res = res->ai_next) { 95 for (res=res0; res!=NULL; res = res->ai_next) {
98 if ( res->ai_family != PF_INET || res->ai_socktype != SOCK_STREAM ) { 96 if ( res->ai_family != PF_INET || res->ai_socktype != SOCK_STREAM ) {
99 continue; 97 continue;
100 } 98 }
101 mSocketID = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 99 mSocketID = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
102 if (mSocketID < 0) { 100 if (mSocketID < 0) {
103 continue; 101 continue;
104 } 102 }
105 if (connect(mSocketID, res->ai_addr, res->ai_addrlen) < 0) { 103 if (connect(mSocketID, res->ai_addr, res->ai_addrlen) < 0) {
106 close(mSocketID); 104 close(mSocketID);
107 mSocketID = -1; 105 mSocketID = -1;
108 } 106 }
109 if (mSocketID > 0) { 107 if (mSocketID > 0) {
110 break; 108 break;
111 } 109 }
112 } 110 }
113 freeaddrinfo(res0); 111 freeaddrinfo(res0);
114 if (mSocketID <= 0) { 112 if (mSocketID <= 0) {
115 logg->logError(__FILE__, __LINE__, "Could not connect to client socket. Ensure ARM Streamline is running."); 113 logg->logError(__FILE__, __LINE__, "Could not connect to client socket. Ensure ARM Streamline is running.");
116 handleException(); 114 handleException();
117 } 115 }
118#endif 116#endif
119} 117}
120 118
121void OlySocket::createSingleServerConnection(int port) { 119void OlySocket::createSingleServerConnection(int port) {
122 createServerSocket(port); 120 createServerSocket(port);
123 121
124 mSocketID = acceptConnection(); 122 mSocketID = acceptConnection();
125 closeServerSocket(); 123 closeServerSocket();
126} 124}
127 125
128void OlySocket::createServerSocket(int port) { 126void OlySocket::createServerSocket(int port) {
129 // Create socket 127 // Create socket
130 mFDServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 128 mFDServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
131 if (mFDServer < 0) { 129 if (mFDServer < 0) {
132 logg->logError(__FILE__, __LINE__, "Error creating server socket"); 130 logg->logError(__FILE__, __LINE__, "Error creating server socket");
133 handleException(); 131 handleException();
134 } 132 }
135 133
136 // Enable address reuse, another solution would be to create the server socket once and only close it when the object exits 134 // Enable address reuse, another solution would be to create the server socket once and only close it when the object exits
137 int on = 1; 135 int on = 1;
138 if (setsockopt(mFDServer, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) != 0) { 136 if (setsockopt(mFDServer, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) != 0) {
139 logg->logError(__FILE__, __LINE__, "Setting server socket options failed"); 137 logg->logError(__FILE__, __LINE__, "Setting server socket options failed");
140 handleException(); 138 handleException();
141 } 139 }
142 140
143 // Create sockaddr_in structure, ensuring non-populated fields are zero 141 // Create sockaddr_in structure, ensuring non-populated fields are zero
144 struct sockaddr_in sockaddr; 142 struct sockaddr_in sockaddr;
145 memset((void*)&sockaddr, 0, sizeof(struct sockaddr_in)); 143 memset((void*)&sockaddr, 0, sizeof(struct sockaddr_in));
146 sockaddr.sin_family = AF_INET; 144 sockaddr.sin_family = AF_INET;
147 sockaddr.sin_port = htons(port); 145 sockaddr.sin_port = htons(port);
148 sockaddr.sin_addr.s_addr = INADDR_ANY; 146 sockaddr.sin_addr.s_addr = INADDR_ANY;
149 147
150 // Bind the socket to an address 148 // Bind the socket to an address
151 if (bind(mFDServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) { 149 if (bind(mFDServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
152 logg->logError(__FILE__, __LINE__, "Binding of server socket failed.\nIs an instance already running?"); 150 logg->logError(__FILE__, __LINE__, "Binding of server socket failed.\nIs an instance already running?");
153 handleException(); 151 handleException();
154 } 152 }
155 153
156 // Listen for connections on this socket 154 // Listen for connections on this socket
157 if (listen(mFDServer, 1) < 0) { 155 if (listen(mFDServer, 1) < 0) {
158 logg->logError(__FILE__, __LINE__, "Listening of server socket failed"); 156 logg->logError(__FILE__, __LINE__, "Listening of server socket failed");
159 handleException(); 157 handleException();
160 } 158 }
161} 159}
162 160
163// mSocketID is always set to the most recently accepted connection 161// mSocketID is always set to the most recently accepted connection
164// The user of this class should maintain the different socket connections, e.g. by forking the process 162// The user of this class should maintain the different socket connections, e.g. by forking the process
165int OlySocket::acceptConnection() { 163int OlySocket::acceptConnection() {
166 if (mFDServer <= 0) { 164 if (mFDServer <= 0) {
167 logg->logError(__FILE__, __LINE__, "Attempting multiple connections on a single connection server socket or attempting to accept on a client socket"); 165 logg->logError(__FILE__, __LINE__, "Attempting multiple connections on a single connection server socket or attempting to accept on a client socket");
168 handleException(); 166 handleException();
169 } 167 }
170 168
171 // Accept a connection, note that this call blocks until a client connects 169 // Accept a connection, note that this call blocks until a client connects
172 mSocketID = accept(mFDServer, NULL, NULL); 170 mSocketID = accept(mFDServer, NULL, NULL);
173 if (mSocketID < 0) { 171 if (mSocketID < 0) {
174 logg->logError(__FILE__, __LINE__, "Socket acceptance failed"); 172 logg->logError(__FILE__, __LINE__, "Socket acceptance failed");
175 handleException(); 173 handleException();
176 } 174 }
177 return mSocketID; 175 return mSocketID;
178} 176}
179 177
180void OlySocket::send(char* buffer, int size) { 178void OlySocket::send(char* buffer, int size) {
181 if (size <= 0 || buffer == NULL) { 179 if (size <= 0 || buffer == NULL) {
182 return; 180 return;
183 } 181 }
184 182
185 while (size > 0) { 183 while (size > 0) {
186 int n = ::send(mSocketID, buffer, size, 0); 184 int n = ::send(mSocketID, buffer, size, 0);
187 if (n < 0) { 185 if (n < 0) {
188 logg->logError(__FILE__, __LINE__, "Socket send error"); 186 logg->logError(__FILE__, __LINE__, "Socket send error");
189 handleException(); 187 handleException();
190 } 188 }
191 size -= n; 189 size -= n;
192 buffer += n; 190 buffer += n;
193 } 191 }
194} 192}
195 193
196// Returns the number of bytes received 194// Returns the number of bytes received
197int OlySocket::receive(char* buffer, int size) { 195int OlySocket::receive(char* buffer, int size) {
198 if (size <= 0 || buffer == NULL) { 196 if (size <= 0 || buffer == NULL) {
199 return 0; 197 return 0;
200 } 198 }
201 199
202 int bytes = recv(mSocketID, buffer, size, 0); 200 int bytes = recv(mSocketID, buffer, size, 0);
203 if (bytes < 0) { 201 if (bytes < 0) {
204 logg->logError(__FILE__, __LINE__, "Socket receive error"); 202 logg->logError(__FILE__, __LINE__, "Socket receive error");
205 handleException(); 203 handleException();
206 } else if (bytes == 0) { 204 } else if (bytes == 0) {
207 logg->logMessage("Socket disconnected"); 205 logg->logMessage("Socket disconnected");
208 return -1; 206 return -1;
209 } 207 }
210 return bytes; 208 return bytes;
211} 209}
212 210
213// Receive exactly size bytes of data. Note, this function will block until all bytes are received 211// Receive exactly size bytes of data. Note, this function will block until all bytes are received
214int OlySocket::receiveNBytes(char* buffer, int size) { 212int OlySocket::receiveNBytes(char* buffer, int size) {
215 int bytes = 0; 213 int bytes = 0;
216 while (size > 0 && buffer != NULL) { 214 while (size > 0 && buffer != NULL) {
217 bytes = recv(mSocketID, buffer, size, 0); 215 bytes = recv(mSocketID, buffer, size, 0);
218 if (bytes < 0) { 216 if (bytes < 0) {
219 logg->logError(__FILE__, __LINE__, "Socket receive error"); 217 logg->logError(__FILE__, __LINE__, "Socket receive error");
220 handleException(); 218 handleException();
221 } else if (bytes == 0) { 219 } else if (bytes == 0) {
222 logg->logMessage("Socket disconnected"); 220 logg->logMessage("Socket disconnected");
223 return -1; 221 return -1;
224 } 222 }
225 buffer += bytes; 223 buffer += bytes;
226 size -= bytes; 224 size -= bytes;
227 } 225 }
228 return bytes; 226 return bytes;
229} 227}
230 228
231// Receive data until a carriage return, line feed, or null is encountered, or the buffer fills 229// Receive data until a carriage return, line feed, or null is encountered, or the buffer fills
232int OlySocket::receiveString(char* buffer, int size) { 230int OlySocket::receiveString(char* buffer, int size) {
233 int bytes_received = 0; 231 int bytes_received = 0;
234 bool found = false; 232 bool found = false;
235 233
236 if (buffer == 0) { 234 if (buffer == 0) {
237 return 0; 235 return 0;
238 } 236 }
239 237
240 while (!found && bytes_received < size) { 238 while (!found && bytes_received < size) {
241 // Receive a single character 239 // Receive a single character
242 int bytes = recv(mSocketID, &buffer[bytes_received], 1, 0); 240 int bytes = recv(mSocketID, &buffer[bytes_received], 1, 0);
243 if (bytes < 0) { 241 if (bytes < 0) {
244 logg->logError(__FILE__, __LINE__, "Socket receive error"); 242 logg->logError(__FILE__, __LINE__, "Socket receive error");
245 handleException(); 243 handleException();
246 } else if (bytes == 0) { 244 } else if (bytes == 0) {
247 logg->logMessage("Socket disconnected"); 245 logg->logMessage("Socket disconnected");
248 return -1; 246 return -1;
249 } 247 }
250 248
251 // Replace carriage returns and line feeds with zero 249 // Replace carriage returns and line feeds with zero
252 if (buffer[bytes_received] == '\n' || buffer[bytes_received] == '\r' || buffer[bytes_received] == '\0') { 250 if (buffer[bytes_received] == '\n' || buffer[bytes_received] == '\r' || buffer[bytes_received] == '\0') {
253 buffer[bytes_received] = '\0'; 251 buffer[bytes_received] = '\0';
254 found = true; 252 found = true;
255 } 253 }
256 254
257 bytes_received++; 255 bytes_received++;
258 } 256 }
259 257
260 return bytes_received; 258 return bytes_received;
261} 259}
diff --git a/daemon/OlySocket.h b/daemon/OlySocket.h
index 266a831..b306908 100644
--- a/daemon/OlySocket.h
+++ b/daemon/OlySocket.h
@@ -6,31 +6,31 @@
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8 8
9#ifndef __OLY_SOCKET_H__ 9#ifndef __OLY_SOCKET_H__
10#define __OLY_SOCKET_H__ 10#define __OLY_SOCKET_H__
11 11
12#include <string.h> 12#include <string.h>
13 13
14class OlySocket { 14class OlySocket {
15public: 15public:
16 OlySocket(int port, bool multipleConnections = false); 16 OlySocket(int port, bool multipleConnections = false);
17 OlySocket(int port, char* hostname); 17 OlySocket(int port, char* hostname);
18 ~OlySocket(); 18 ~OlySocket();
19 int acceptConnection(); 19 int acceptConnection();
20 void closeSocket(); 20 void closeSocket();
21 void closeServerSocket(); 21 void closeServerSocket();
22 void shutdownConnection(); 22 void shutdownConnection();
23 void send(char* buffer, int size); 23 void send(char* buffer, int size);
24 void sendString(const char* string) {send((char*)string, strlen(string));} 24 void sendString(const char* string) {send((char*)string, strlen(string));}
25 int receive(char* buffer, int size); 25 int receive(char* buffer, int size);
26 int receiveNBytes(char* buffer, int size); 26 int receiveNBytes(char* buffer, int size);
27 int receiveString(char* buffer, int size); 27 int receiveString(char* buffer, int size);
28 int getSocketID() {return mSocketID;} 28 int getSocketID() {return mSocketID;}
29private: 29private:
30 int mSocketID, mFDServer; 30 int mSocketID, mFDServer;
31 void createClientSocket(char* hostname, int port); 31 void createClientSocket(char* hostname, int port);
32 void createSingleServerConnection(int port); 32 void createSingleServerConnection(int port);
33 void createServerSocket(int port); 33 void createServerSocket(int port);
34}; 34};
35 35
36#endif //__OLY_SOCKET_H__ 36#endif //__OLY_SOCKET_H__
diff --git a/daemon/OlyUtility.cpp b/daemon/OlyUtility.cpp
index adc7aba..df4fe22 100644
--- a/daemon/OlyUtility.cpp
+++ b/daemon/OlyUtility.cpp
@@ -11,10 +11,12 @@
11#include <string.h> 11#include <string.h>
12#include <ctype.h> 12#include <ctype.h>
13 13
14#ifndef WIN32 14#if defined(WIN32)
15#include <windows.h>
16#elif defined(__linux__)
15#include <unistd.h> 17#include <unistd.h>
16#else 18#elif defined(DARWIN)
17#include <Windows.h> 19#include <mach-o/dyld.h>
18#endif 20#endif
19 21
20#include "OlyUtility.h" 22#include "OlyUtility.h"
@@ -22,138 +24,144 @@
22OlyUtility* util = NULL; 24OlyUtility* util = NULL;
23 25
24bool OlyUtility::stringToBool(const char* string, bool defValue) { 26bool OlyUtility::stringToBool(const char* string, bool defValue) {
25 char value[32]; 27 char value[32];
26 28
27 if (string == NULL) { 29 if (string == NULL) {
28 return defValue; 30 return defValue;
29 } 31 }
30 32
31 strncpy(value, string, sizeof(value)); 33 strncpy(value, string, sizeof(value));
32 if (value[0] == 0) { 34 if (value[0] == 0) {
33 return defValue; 35 return defValue;
34 } 36 }
35 value[sizeof(value) - 1] = 0; // strncpy does not guarantee a null-terminated string 37 value[sizeof(value) - 1] = 0; // strncpy does not guarantee a null-terminated string
36 38
37 // Convert to lowercase 39 // Convert to lowercase
38 int i = 0; 40 int i = 0;
39 while (value[i]) { 41 while (value[i]) {
40 value[i] = tolower(value[i]); 42 value[i] = tolower(value[i]);
41 i++; 43 i++;
42 } 44 }
43 45
44 if (strcmp(value, "true") == 0 || strcmp(value, "yes") == 0 || strcmp(value, "1") == 0 || strcmp(value, "on") == 0) { 46 if (strcmp(value, "true") == 0 || strcmp(value, "yes") == 0 || strcmp(value, "1") == 0 || strcmp(value, "on") == 0) {
45 return true; 47 return true;
46 } else if (strcmp(value, "false") == 0 || strcmp(value, "no") == 0 || strcmp(value, "0") == 0 || strcmp(value, "off") == 0) { 48 } else if (strcmp(value, "false") == 0 || strcmp(value, "no") == 0 || strcmp(value, "0") == 0 || strcmp(value, "off") == 0) {
47 return false; 49 return false;
48 } else { 50 } else {
49 return defValue; 51 return defValue;
50 } 52 }
51} 53}
52 54
53void OlyUtility::stringToLower(char* string) { 55void OlyUtility::stringToLower(char* string) {
54 if (string == NULL) { 56 if (string == NULL) {
55 return; 57 return;
56 } 58 }
57 59
58 while (*string) { 60 while (*string) {
59 *string = tolower(*string); 61 *string = tolower(*string);
60 string++; 62 string++;
61 } 63 }
62} 64}
63 65
64// Modifies fullpath with the path part including the trailing path separator 66// Modifies fullpath with the path part including the trailing path separator
65int OlyUtility::getApplicationFullPath(char* fullpath, int sizeOfPath) { 67int OlyUtility::getApplicationFullPath(char* fullpath, int sizeOfPath) {
66 memset(fullpath, 0, sizeOfPath); 68 memset(fullpath, 0, sizeOfPath);
67#ifdef WIN32 69#if defined(WIN32)
68 int length = GetModuleFileName(NULL, fullpath, sizeOfPath); 70 int length = GetModuleFileName(NULL, fullpath, sizeOfPath);
69#else 71#elif defined(__linux__)
70 int length = readlink("/proc/self/exe", fullpath, sizeOfPath); 72 int length = readlink("/proc/self/exe", fullpath, sizeOfPath);
73#elif defined(DARWIN)
74 uint32_t length_u = (uint32_t)sizeOfPath;
75 int length = sizeOfPath;
76 if (_NSGetExecutablePath(fullpath, &length_u) == 0) {
77 length = strlen(fullpath);
78 }
71#endif 79#endif
72 80
73 if (length == sizeOfPath) { 81 if (length == sizeOfPath) {
74 return -1; 82 return -1;
75 } 83 }
76 84
77 fullpath[length] = 0; 85 fullpath[length] = 0;
78 fullpath = getPathPart(fullpath); 86 fullpath = getPathPart(fullpath);
79 87
80 return 0; 88 return 0;
81} 89}
82 90
83char* OlyUtility::readFromDisk(const char* file, unsigned int *size, bool appendNull) { 91char* OlyUtility::readFromDisk(const char* file, unsigned int *size, bool appendNull) {
84 // Open the file 92 // Open the file
85 FILE* pFile = fopen(file, "rb"); 93 FILE* pFile = fopen(file, "rb");
86 if (pFile==NULL) { 94 if (pFile==NULL) {
87 return NULL; 95 return NULL;
88 } 96 }
89 97
90 // Obtain file size 98 // Obtain file size
91 fseek(pFile , 0 , SEEK_END); 99 fseek(pFile , 0 , SEEK_END);
92 unsigned int lSize = ftell(pFile); 100 unsigned int lSize = ftell(pFile);
93 rewind(pFile); 101 rewind(pFile);
94 102
95 // Allocate memory to contain the whole file 103 // Allocate memory to contain the whole file
96 char* buffer = (char*)malloc(lSize + (int)appendNull); 104 char* buffer = (char*)malloc(lSize + (int)appendNull);
97 if (buffer == NULL) { 105 if (buffer == NULL) {
98 fclose(pFile); 106 fclose(pFile);
99 return NULL; 107 return NULL;
100 } 108 }
101 109
102 // Copy the file into the buffer 110 // Copy the file into the buffer
103 if (fread(buffer, 1, lSize, pFile) != lSize) { 111 if (fread(buffer, 1, lSize, pFile) != lSize) {
104 free(buffer); 112 free(buffer);
105 fclose(pFile); 113 fclose(pFile);
106 return NULL; 114 return NULL;
107 } 115 }
108 116
109 // Terminate 117 // Terminate
110 fclose(pFile); 118 fclose(pFile);
111 119
112 if (appendNull) { 120 if (appendNull) {
113 buffer[lSize] = 0; 121 buffer[lSize] = 0;
114 } 122 }
115 123
116 if (size) { 124 if (size) {
117 *size = lSize; 125 *size = lSize;
118 } 126 }
119 127
120 return buffer; 128 return buffer;
121} 129}
122 130
123int OlyUtility::writeToDisk(const char* path, const char* data) { 131int OlyUtility::writeToDisk(const char* path, const char* data) {
124 // Open the file 132 // Open the file
125 FILE* pFile = fopen(path, "wb"); 133 FILE* pFile = fopen(path, "wb");
126 if (pFile == NULL) { 134 if (pFile == NULL) {
127 return -1; 135 return -1;
128 } 136 }
129 137
130 // Write the data to disk 138 // Write the data to disk
131 if (fwrite(data, 1, strlen(data), pFile) != strlen(data)) { 139 if (fwrite(data, 1, strlen(data), pFile) != strlen(data)) {
132 fclose(pFile); 140 fclose(pFile);
133 return -1; 141 return -1;
134 } 142 }
135 143
136 // Terminate 144 // Terminate
137 fclose(pFile); 145 fclose(pFile);
138 return 0; 146 return 0;
139} 147}
140 148
141int OlyUtility::appendToDisk(const char* path, const char* data) { 149int OlyUtility::appendToDisk(const char* path, const char* data) {
142 // Open the file 150 // Open the file
143 FILE* pFile = fopen(path, "a"); 151 FILE* pFile = fopen(path, "a");
144 if (pFile == NULL) { 152 if (pFile == NULL) {
145 return -1; 153 return -1;
146 } 154 }
147 155
148 // Write the data to disk 156 // Write the data to disk
149 if (fwrite(data, 1, strlen(data), pFile) != strlen(data)) { 157 if (fwrite(data, 1, strlen(data), pFile) != strlen(data)) {
150 fclose(pFile); 158 fclose(pFile);
151 return -1; 159 return -1;
152 } 160 }
153 161
154 // Terminate 162 // Terminate
155 fclose(pFile); 163 fclose(pFile);
156 return 0; 164 return 0;
157} 165}
158 166
159/** 167/**
@@ -163,97 +171,58 @@ int OlyUtility::appendToDisk(const char* path, const char* data) {
163 */ 171 */
164#define TRANSFER_SIZE 1024 172#define TRANSFER_SIZE 1024
165int OlyUtility::copyFile(const char* srcFile, const char* dstFile) { 173int OlyUtility::copyFile(const char* srcFile, const char* dstFile) {
166 char* buffer = (char*)malloc(TRANSFER_SIZE); 174 char* buffer = (char*)malloc(TRANSFER_SIZE);
167 FILE * f_src = fopen(srcFile,"rb"); 175 FILE * f_src = fopen(srcFile,"rb");
168 if (!f_src) { 176 if (!f_src) {
169 return 0; 177 return 0;
170 } 178 }
171 FILE * f_dst = fopen(dstFile,"wb"); 179 FILE * f_dst = fopen(dstFile,"wb");
172 if (!f_dst) { 180 if (!f_dst) {
173 fclose(f_src); 181 fclose(f_src);
174 return 0; 182 return 0;
175 } 183 }
176 while (!feof(f_src)) { 184 while (!feof(f_src)) {
177 int num_bytes_read = fread(buffer, 1, TRANSFER_SIZE, f_src); 185 int num_bytes_read = fread(buffer, 1, TRANSFER_SIZE, f_src);
178 if (num_bytes_read < TRANSFER_SIZE && !feof(f_src)) { 186 if (num_bytes_read < TRANSFER_SIZE && !feof(f_src)) {
179 fclose(f_src); 187 fclose(f_src);
180 fclose(f_dst); 188 fclose(f_dst);
181 return 0; 189 return 0;
182 } 190 }
183 int num_bytes_written = fwrite(buffer, 1, num_bytes_read, f_dst); 191 int num_bytes_written = fwrite(buffer, 1, num_bytes_read, f_dst);
184 if (num_bytes_written != num_bytes_read) { 192 if (num_bytes_written != num_bytes_read) {
185 fclose(f_src); 193 fclose(f_src);
186 fclose(f_dst); 194 fclose(f_dst);
187 return 0; 195 return 0;
188 } 196 }
189 } 197 }
190 fclose(f_src); 198 fclose(f_src);
191 fclose(f_dst); 199 fclose(f_dst);
192 free(buffer); 200 free(buffer);
193 return 1; 201 return 1;
194} 202}
195 203
196const char* OlyUtility::getFilePart(const char* path) { 204const char* OlyUtility::getFilePart(const char* path) {
197 const char* last_sep = strrchr(path, PATH_SEPARATOR); 205 const char* last_sep = strrchr(path, PATH_SEPARATOR);
198 206
199 // in case path is not a full path 207 // in case path is not a full path
200 if (last_sep == NULL) { 208 if (last_sep == NULL) {
201 return path; 209 return path;
202 } 210 }
203 211
204 return last_sep++; 212 return last_sep++;
205} 213}
206 214
207// getPathPart may modify the contents of path 215// getPathPart may modify the contents of path
208// returns the path including the trailing path separator 216// returns the path including the trailing path separator
209char* OlyUtility::getPathPart(char* path) { 217char* OlyUtility::getPathPart(char* path) {
210 char* last_sep = strrchr(path, PATH_SEPARATOR); 218 char* last_sep = strrchr(path, PATH_SEPARATOR);
211 219
212 // in case path is not a full path 220 // in case path is not a full path
213 if (last_sep == NULL) { 221 if (last_sep == NULL) {
214 return 0; 222 return 0;
215 } 223 }
216 last_sep++; 224 last_sep++;
217 *last_sep = 0; 225 *last_sep = 0;
218 226
219 return (path); 227 return (path);
220}
221
222// whitespace callback utility function used with mini-xml
223const char * mxmlWhitespaceCB(mxml_node_t *node, int loc) {
224 const char *name;
225
226 name = mxmlGetElement(node);
227
228 if (loc == MXML_WS_BEFORE_OPEN) {
229 // Single indentation
230 if (!strcmp(name, "target") || !strcmp(name, "counters"))
231 return("\n ");
232
233 // Double indentation
234 if (!strcmp(name, "counter"))
235 return("\n ");
236
237 // Avoid a carriage return on the first line of the xml file
238 if (!strncmp(name, "?xml", 4))
239 return(NULL);
240
241 // Default - no indentation
242 return("\n");
243 }
244
245 if (loc == MXML_WS_BEFORE_CLOSE) {
246 // No indentation
247 if (!strcmp(name, "captured"))
248 return("\n");
249
250 // Single indentation
251 if (!strcmp(name, "counters"))
252 return("\n ");
253
254 // Default - no carriage return
255 return(NULL);
256 }
257
258 return(NULL);
259} 228}
diff --git a/daemon/OlyUtility.h b/daemon/OlyUtility.h
index 793a733..424c583 100644
--- a/daemon/OlyUtility.h
+++ b/daemon/OlyUtility.h
@@ -11,28 +11,30 @@
11 11
12#ifdef WIN32 12#ifdef WIN32
13#define PATH_SEPARATOR '\\' 13#define PATH_SEPARATOR '\\'
14#define CAIMAN_PATH_MAX MAX_PATH
15#define snprintf _snprintf
14#else 16#else
17#include <limits.h>
15#define PATH_SEPARATOR '/' 18#define PATH_SEPARATOR '/'
19#define CAIMAN_PATH_MAX PATH_MAX
16#endif 20#endif
17 21
18class OlyUtility { 22class OlyUtility {
19public: 23public:
20 OlyUtility() {}; 24 OlyUtility() {};
21 ~OlyUtility() {}; 25 ~OlyUtility() {};
22 bool stringToBool(const char* string, bool defValue); 26 bool stringToBool(const char* string, bool defValue);
23 void stringToLower(char* string); 27 void stringToLower(char* string);
24 int getApplicationFullPath(char* path, int sizeOfPath); 28 int getApplicationFullPath(char* path, int sizeOfPath);
25 char* readFromDisk(const char* file, unsigned int *size = NULL, bool appendNull = true); 29 char* readFromDisk(const char* file, unsigned int *size = NULL, bool appendNull = true);
26 int writeToDisk(const char* path, const char* file); 30 int writeToDisk(const char* path, const char* file);
27 int appendToDisk(const char* path, const char* file); 31 int appendToDisk(const char* path, const char* file);
28 int copyFile(const char* srcFile, const char* dstFile); 32 int copyFile(const char* srcFile, const char* dstFile);
29 const char* getFilePart(const char* path); 33 const char* getFilePart(const char* path);
30 char* getPathPart(char* path); 34 char* getPathPart(char* path);
31private: 35private:
32}; 36};
33 37
34#include "mxml/mxml.h"
35const char * mxmlWhitespaceCB(mxml_node_t *node, int where);
36extern OlyUtility* util; 38extern OlyUtility* util;
37 39
38#endif // OLY_UTILITY_H 40#endif // OLY_UTILITY_H
diff --git a/daemon/Sender.cpp b/daemon/Sender.cpp
index eba8343..54f2207 100644
--- a/daemon/Sender.cpp
+++ b/daemon/Sender.cpp
@@ -17,8 +17,6 @@
17#include "Logging.h" 17#include "Logging.h"
18#include "SessionData.h" 18#include "SessionData.h"
19 19
20extern void handleException();
21
22Sender::Sender(OlySocket* socket) { 20Sender::Sender(OlySocket* socket) {
23 mDataFile = NULL; 21 mDataFile = NULL;
24 mDataSocket = NULL; 22 mDataSocket = NULL;
@@ -37,7 +35,7 @@ Sender::Sender(OlySocket* socket) {
37 } 35 }
38 } 36 }
39 37
40 // Send magic sequence - must be done first, afterwhich error messages can be sent 38 // Send magic sequence - must be done first, after which error messages can be sent
41 char magic[32]; 39 char magic[32];
42 snprintf(magic, 32, "GATOR %i\n", PROTOCOL_VERSION); 40 snprintf(magic, 32, "GATOR %i\n", PROTOCOL_VERSION);
43 mDataSocket->send(magic, strlen(magic)); 41 mDataSocket->send(magic, strlen(magic));
diff --git a/daemon/SessionData.cpp b/daemon/SessionData.cpp
index 5aa3f11..53a3ea6 100644
--- a/daemon/SessionData.cpp
+++ b/daemon/SessionData.cpp
@@ -10,7 +10,6 @@
10#include "SessionData.h" 10#include "SessionData.h"
11#include "SessionXML.h" 11#include "SessionXML.h"
12#include "Logging.h" 12#include "Logging.h"
13extern void handleException();
14 13
15SessionData* gSessionData = NULL; 14SessionData* gSessionData = NULL;
16 15
diff --git a/daemon/SessionData.h b/daemon/SessionData.h
index 00a71b1..e0e0b7a 100644
--- a/daemon/SessionData.h
+++ b/daemon/SessionData.h
@@ -13,7 +13,7 @@
13#define MAX_STRING_LEN 80 13#define MAX_STRING_LEN 80
14#define MAX_DESCRIPTION_LEN 400 14#define MAX_DESCRIPTION_LEN 400
15 15
16#define PROTOCOL_VERSION 11 16#define PROTOCOL_VERSION 12
17#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions 17#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions
18 18
19struct ImageLinkList { 19struct ImageLinkList {
diff --git a/daemon/SessionXML.cpp b/daemon/SessionXML.cpp
index 4c373d8..b2b6c30 100644
--- a/daemon/SessionXML.cpp
+++ b/daemon/SessionXML.cpp
@@ -13,8 +13,6 @@
13#include "Logging.h" 13#include "Logging.h"
14#include "OlyUtility.h" 14#include "OlyUtility.h"
15 15
16extern void handleException();
17
18static const char* TAG_SESSION = "session"; 16static const char* TAG_SESSION = "session";
19static const char* TAG_IMAGE = "image"; 17static const char* TAG_IMAGE = "image";
20 18
diff --git a/daemon/StreamlineSetup.cpp b/daemon/StreamlineSetup.cpp
index 3f59eab..d13cf1d 100644
--- a/daemon/StreamlineSetup.cpp
+++ b/daemon/StreamlineSetup.cpp
@@ -22,8 +22,6 @@
22#include "StreamlineSetup.h" 22#include "StreamlineSetup.h"
23#include "ConfigurationXML.h" 23#include "ConfigurationXML.h"
24 24
25extern void handleException();
26
27static const char* TAG_SESSION = "session"; 25static const char* TAG_SESSION = "session";
28static const char* TAG_REQUEST = "request"; 26static const char* TAG_REQUEST = "request";
29static const char* TAG_CONFIGURATIONS = "configurations"; 27static const char* TAG_CONFIGURATIONS = "configurations";
diff --git a/daemon/events-Cortex-A15.xml b/daemon/events-Cortex-A15.xml
index 0ec196f..e0bd201 100644
--- a/daemon/events-Cortex-A15.xml
+++ b/daemon/events-Cortex-A15.xml
@@ -65,4 +65,4 @@
65 <event event="0x7c" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/> 65 <event event="0x7c" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
66 <event event="0x7d" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/> 66 <event event="0x7d" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
67 <event event="0x7e" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/> 67 <event event="0x7e" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
68 </category> 68 </category>
diff --git a/daemon/events-Cortex-A7.xml b/daemon/events-Cortex-A7.xml
index 2bd4797..50bba7f 100644
--- a/daemon/events-Cortex-A7.xml
+++ b/daemon/events-Cortex-A7.xml
@@ -41,4 +41,4 @@
41 <event event="0xC8" title="ETM" name="ETM Ext Out[1]" description=""/> 41 <event event="0xC8" title="ETM" name="ETM Ext Out[1]" description=""/>
42 <event event="0xC9" title="Instruction" name="Pipeline stall" description="Data Write operation that stalls the pipeline because the store buffer is full"/> 42 <event event="0xC9" title="Instruction" name="Pipeline stall" description="Data Write operation that stalls the pipeline because the store buffer is full"/>
43 <event event="0xCA" title="Memory" name="Snoop" description="Data snooped from other processor. This event counts memory-read operations that read data from another processor within the local cluster, rather than accessing the L2 cache or issuing an external read."/> 43 <event event="0xCA" title="Memory" name="Snoop" description="Data snooped from other processor. This event counts memory-read operations that read data from another processor within the local cluster, rather than accessing the L2 cache or issuing an external read."/>
44 </category> 44 </category>
diff --git a/daemon/events-Cortex-A9.xml b/daemon/events-Cortex-A9.xml
index 7597f78..89d6a19 100644
--- a/daemon/events-Cortex-A9.xml
+++ b/daemon/events-Cortex-A9.xml
@@ -31,9 +31,9 @@
31 <event event="0x66" title="Pipeline" name="Issue stage no dispatch" description="Counts the number of cycles where the issue stage does not dispatch any instruction because it is empty or cannot dispatch any instructions"/> 31 <event event="0x66" title="Pipeline" name="Issue stage no dispatch" description="Counts the number of cycles where the issue stage does not dispatch any instruction because it is empty or cannot dispatch any instructions"/>
32 <event event="0x67" title="Pipeline" name="Issue stage empty" description="Counts the number of cycles where the issue stage is empty"/> 32 <event event="0x67" title="Pipeline" name="Issue stage empty" description="Counts the number of cycles where the issue stage is empty"/>
33 <event event="0x68" title="Instruction" name="Executed" description="Counts the number of instructions going through the Register Renaming stage. This number is an approximate number of the total number of instructions speculatively executed, and even more approximate of the total number of instructions architecturally executed"/> 33 <event event="0x68" title="Instruction" name="Executed" description="Counts the number of instructions going through the Register Renaming stage. This number is an approximate number of the total number of instructions speculatively executed, and even more approximate of the total number of instructions architecturally executed"/>
34 <event event="0x69" title="Cache" name="Data linefills" description="Counts the number of linefills performed on the external AXI bus"/> 34 <event event="0x69" title="Cache" name="Data linefills" description="Counts the number of linefills performed on the external AXI bus"/>
35 <event event="0x6A" title="Cache" name="Prefetch linefills" description="Counts the number of data linefills caused by prefetcher requests"/> 35 <event event="0x6A" title="Cache" name="Prefetch linefills" description="Counts the number of data linefills caused by prefetcher requests"/>
36 <event event="0x6B" title="Cache" name="Prefetch hits" description="Counts the number of cache hits in a line that belongs to a stream followed by the prefetcher"/> 36 <event event="0x6B" title="Cache" name="Prefetch hits" description="Counts the number of cache hits in a line that belongs to a stream followed by the prefetcher"/>
37 <event event="0x6E" title="Core" name="Functions" description="Counts the number of procedure returns whose condition codes do not fail, excluding all returns from exception"/> 37 <event event="0x6E" title="Core" name="Functions" description="Counts the number of procedure returns whose condition codes do not fail, excluding all returns from exception"/>
38 <event event="0x70" title="Instruction" name="Main execution unit" description="Counts the number of instructions being executed in the main execution pipeline of the processor, the multiply pipeline and arithmetic logic unit pipeline"/> 38 <event event="0x70" title="Instruction" name="Main execution unit" description="Counts the number of instructions being executed in the main execution pipeline of the processor, the multiply pipeline and arithmetic logic unit pipeline"/>
39 <event event="0x71" title="Instruction" name="Second execution unit" description="Counts the number of instructions being executed in the processor second execution pipeline (ALU)"/> 39 <event event="0x71" title="Instruction" name="Second execution unit" description="Counts the number of instructions being executed in the processor second execution pipeline (ALU)"/>
@@ -49,9 +49,9 @@
49 <event event="0x86" title="Stalls" name="DMB" description="Counts the number of stall cycles because of the execution of a DMB memory barrier"/> 49 <event event="0x86" title="Stalls" name="DMB" description="Counts the number of stall cycles because of the execution of a DMB memory barrier"/>
50 <event event="0x8A" title="Clock" name="Integer core" description="Counts the number of cycles during which the integer core clock is enabled"/> 50 <event event="0x8A" title="Clock" name="Integer core" description="Counts the number of cycles during which the integer core clock is enabled"/>
51 <event event="0x8B" title="Clock" name="Data engine" description="Counts the number of cycles during which the Data Engine clock is enabled"/> 51 <event event="0x8B" title="Clock" name="Data engine" description="Counts the number of cycles during which the Data Engine clock is enabled"/>
52 <event event="0x8C" title="Clock" name="NEON" description="Counts the number of cycles when the NEON SIMD clock is enabled"/> 52 <event event="0x8C" title="Clock" name="NEON" description="Counts the number of cycles when the NEON SIMD clock is enabled"/>
53 <event event="0x8D" title="Memory" name="TLB inst allocations" description="Counts the number of TLB allocations because of Instruction requests"/> 53 <event event="0x8D" title="Memory" name="TLB inst allocations" description="Counts the number of TLB allocations because of Instruction requests"/>
54 <event event="0x8E" title="Memory" name="TLB data allocations" description="Counts the number of TLB allocations because of Data requests"/> 54 <event event="0x8E" title="Memory" name="TLB data allocations" description="Counts the number of TLB allocations because of Data requests"/>
55 <event event="0x90" title="Instruction" name="ISB" description="Counts the number of ISB instructions architecturally executed"/> 55 <event event="0x90" title="Instruction" name="ISB" description="Counts the number of ISB instructions architecturally executed"/>
56 <event event="0x91" title="Instruction" name="DSB" description="Counts the number of DSB instructions architecturally executed"/> 56 <event event="0x91" title="Instruction" name="DSB" description="Counts the number of DSB instructions architecturally executed"/>
57 <event event="0x92" title="Instruction" name="DMB" description="Counts the number of DMB instructions speculatively executed"/> 57 <event event="0x92" title="Instruction" name="DMB" description="Counts the number of DMB instructions speculatively executed"/>
diff --git a/daemon/events-Linux.xml b/daemon/events-Linux.xml
index b45a122..42baf14 100644
--- a/daemon/events-Linux.xml
+++ b/daemon/events-Linux.xml
@@ -8,8 +8,8 @@
8 <event counter="Linux_sched_switch" title="Scheduler" name="Switch" per_cpu="yes" description="Context switch events"/> 8 <event counter="Linux_sched_switch" title="Scheduler" name="Switch" per_cpu="yes" description="Context switch events"/>
9 <event counter="Linux_meminfo_memused" title="Memory" name="Used" display="maximum" units="B" average_selection="yes" description="Total used memory size"/> 9 <event counter="Linux_meminfo_memused" title="Memory" name="Used" display="maximum" units="B" average_selection="yes" description="Total used memory size"/>
10 <event counter="Linux_meminfo_memfree" title="Memory" name="Free" display="minimum" units="B" average_selection="yes" description="Available memory size"/> 10 <event counter="Linux_meminfo_memfree" title="Memory" name="Free" display="minimum" units="B" average_selection="yes" description="Available memory size"/>
11 <event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" display="maximum" units="B" average_selection="yes" description="Memory used by buffers"/> 11 <event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" display="maximum" units="B" average_selection="yes" description="Memory used by OS disk buffers"/>
12 <event counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" display="maximum" units="Hz" average_selection="yes" description="Frequency setting of the CPU"/> 12 <event counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" display="maximum" units="Hz" average_selection="yes" description="Frequency setting of the CPU"/>
13 <event counter="Linux_power_cpu_idle" title="Power" name="Idle" per_cpu="yes" display="maximum" average_selection="yes" description="CPU Idle State + 1, set the Sample Rate to None to prevent the hrtimer from interrupting the system"/> 13 <event counter="Linux_power_cpu_idle" title="Power" name="Idle" per_cpu="yes" display="maximum" average_selection="yes" description="CPU Idle State + 1, set the Sample Rate to None to prevent the hrtimer from interrupting the system"/>
14 </category> 14 </category>
15 15
diff --git a/daemon/events-Mali-400.xml b/daemon/events-Mali-400.xml
index 6830d46..cb0b9d5 100644
--- a/daemon/events-Mali-400.xml
+++ b/daemon/events-Mali-400.xml
@@ -30,7 +30,7 @@
30 <event event="0x1b" title="Mali GPU Vertex Processor" name="Active cycles, PLBU primitive assembly" description="Number of active cycles per frame spent by the MaliGP2 PLBU doing primitive assembly. This does not include scissoring or final output. This includes time spent waiting on the bus."/> 30 <event event="0x1b" title="Mali GPU Vertex Processor" name="Active cycles, PLBU primitive assembly" description="Number of active cycles per frame spent by the MaliGP2 PLBU doing primitive assembly. This does not include scissoring or final output. This includes time spent waiting on the bus."/>
31 <event event="0x1c" title="Mali GPU Vertex Processor" name="Active cycles, PLBU vertex fetcher" description="Number of active cycles per frame spent by the MaliGP2 PLBU fetching vertex data. This includes time spent waiting on the bus."/> 31 <event event="0x1c" title="Mali GPU Vertex Processor" name="Active cycles, PLBU vertex fetcher" description="Number of active cycles per frame spent by the MaliGP2 PLBU fetching vertex data. This includes time spent waiting on the bus."/>
32 <event event="0x1e" title="Mali GPU Vertex Processor" name="Active cycles, Bounding-box and command generator" description="Number of active cycles per frame spent by the MaliGP2 PLBU setting up bounding boxes and commands (mainly graphics primitives). This includes time spent waiting on the bus."/> 32 <event event="0x1e" title="Mali GPU Vertex Processor" name="Active cycles, Bounding-box and command generator" description="Number of active cycles per frame spent by the MaliGP2 PLBU setting up bounding boxes and commands (mainly graphics primitives). This includes time spent waiting on the bus."/>
33 <event event="0x20" title="Mali GPU Vertex Processor" name="Active cycles, Scissor tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over tiles to perform scissoringi. This includes time spent waiting on the bus."/> 33 <event event="0x20" title="Mali GPU Vertex Processor" name="Active cycles, Scissor tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over tiles to perform scissoring. This includes time spent waiting on the bus."/>
34 <event event="0x21" title="Mali GPU Vertex Processor" name="Active cycles, PLBU tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over the tiles in the bounding box generating commands (mainly graphics primitives). This includes time spent waiting on the bus."/> 34 <event event="0x21" title="Mali GPU Vertex Processor" name="Active cycles, PLBU tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over the tiles in the bounding box generating commands (mainly graphics primitives). This includes time spent waiting on the bus."/>
35 </category> 35 </category>
36 <category name="Mali-400-FP0" counter_set="ARM_Mali-400_FP0_cnt" per_cpu="no"> 36 <category name="Mali-400-FP0" counter_set="ARM_Mali-400_FP0_cnt" per_cpu="no">
@@ -344,10 +344,10 @@
344 </category> 344 </category>
345 <category name="Mali-400-SW" counter_set="ARM_Mali-400_SW_cnt" per_cpu="no"> 345 <category name="Mali-400-SW" counter_set="ARM_Mali-400_SW_cnt" per_cpu="no">
346 <!-- EGL Counters --> 346 <!-- EGL Counters -->
347 <event counter="ARM_Mali-400_SW_17" title="Mali EGL Software Counters" name="Blit Time" description="Time spent blitting the the framebuffer from video memory to framebuffer."/> 347 <event counter="ARM_Mali-400_SW_17" title="Mali EGL Software Counters" name="Blit Time" description="Time spent blitting the framebuffer from video memory to framebuffer."/>
348 <!-- glDrawElements Counters --> 348 <!-- glDrawElements Counters -->
349 <event counter="ARM_Mali-400_SW_18" title="glDrawElements Statistics" name="Calls to glDrawElements" description="Number of calls to glDrawElements."/> 349 <event counter="ARM_Mali-400_SW_18" title="glDrawElements Statistics" name="Calls to glDrawElements" description="Number of calls to glDrawElements."/>
350 <event counter="ARM_Mali-400_SW_19" title="glDrawElements Statistics" name="Indices to glDrawElements" description="Number of indicies to glDrawElements."/> 350 <event counter="ARM_Mali-400_SW_19" title="glDrawElements Statistics" name="Indices to glDrawElements" description="Number of indices to glDrawElements."/>
351 <event counter="ARM_Mali-400_SW_20" title="glDrawElements Statistics" name="Transformed by glDrawElements" description="Number of vertices transformed by glDrawElements."/> 351 <event counter="ARM_Mali-400_SW_20" title="glDrawElements Statistics" name="Transformed by glDrawElements" description="Number of vertices transformed by glDrawElements."/>
352 <!-- glDrawArrays Counters --> 352 <!-- glDrawArrays Counters -->
353 <event counter="ARM_Mali-400_SW_21" title="glDrawArrays Statistics" name="Calls to glDrawArrays" description="Number of calls to glDrawArrays."/> 353 <event counter="ARM_Mali-400_SW_21" title="glDrawArrays Statistics" name="Calls to glDrawArrays" description="Number of calls to glDrawArrays."/>
@@ -365,7 +365,7 @@
365 <!-- Buffer Profiling Counters --> 365 <!-- Buffer Profiling Counters -->
366 <event counter="ARM_Mali-400_SW_32" title="Buffer Profiling" name="Texture Upload Time (ms)" description="Time spent uploading textures."/> 366 <event counter="ARM_Mali-400_SW_32" title="Buffer Profiling" name="Texture Upload Time (ms)" description="Time spent uploading textures."/>
367 <event counter="ARM_Mali-400_SW_33" title="Buffer Profiling" name="VBO Upload Time (ms)" description="Time spent uploading vertex buffer objects."/> 367 <event counter="ARM_Mali-400_SW_33" title="Buffer Profiling" name="VBO Upload Time (ms)" description="Time spent uploading vertex buffer objects."/>
368 <event counter="ARM_Mali-400_SW_34" title="Buffer Profiling" name="FBO Flushes" description="Number of flushed on framebuffer attachement."/> 368 <event counter="ARM_Mali-400_SW_34" title="Buffer Profiling" name="FBO Flushes" description="Number of flushed on framebuffer attachment."/>
369 <!-- OpenGL ES 1.1 Emulation --> 369 <!-- OpenGL ES 1.1 Emulation -->
370 <event counter="ARM_Mali-400_SW_35" title="Fixed-function Emulation" name="# Vertex Shaders Generated" description="Number of vertex shaders generated."/> 370 <event counter="ARM_Mali-400_SW_35" title="Fixed-function Emulation" name="# Vertex Shaders Generated" description="Number of vertex shaders generated."/>
371 <event counter="ARM_Mali-400_SW_36" title="Fixed-function Emulation" name="# Fragment Shaders Generated" description="Number of fragment shaders generated."/> 371 <event counter="ARM_Mali-400_SW_36" title="Fixed-function Emulation" name="# Fragment Shaders Generated" description="Number of fragment shaders generated."/>
diff --git a/daemon/events-Mali-T6xx.xml b/daemon/events-Mali-T6xx.xml
index 5237e30..3d795de 100644
--- a/daemon/events-Mali-T6xx.xml
+++ b/daemon/events-Mali-T6xx.xml
@@ -1,8 +1,8 @@
1 1
2 <category name="Mali-T6xx-SW-counters" per_cpu="no"> 2 <category name="Mali-T6xx-SW-counters" per_cpu="no">
3 <event counter="ARM_Mali-T6xx_TOTAL_ALLOC_PAGES" title="Mali Total Alloc Pages" name="Total number of allocated pages" description="Mali total number of allocated pages."/> 3 <event counter="ARM_Mali-T6xx_TOTAL_ALLOC_PAGES" title="Mali Total Alloc Pages" name="Total number of allocated pages" description="Mali total number of allocated pages."/>
4 </category> 4 </category>
5 5
6 <category name="Mali-T6xx-PMShader" per_cpu="no"> 6 <category name="Mali-T6xx-PMShader" per_cpu="no">
7 <event counter="ARM_Mali-T6xx_PM_SHADER_0" display="average" average_selection="yes" units="%" title="Mali PM Shader" name="PM Shader Core 0" description="Mali PM Shader: PM Shader Core 0."/> 7 <event counter="ARM_Mali-T6xx_PM_SHADER_0" display="average" average_selection="yes" units="%" title="Mali PM Shader" name="PM Shader Core 0" description="Mali PM Shader: PM Shader Core 0."/>
8 <event counter="ARM_Mali-T6xx_PM_SHADER_1" display="average" average_selection="yes" units="%" title="Mali PM Shader" name="PM Shader Core 1" description="Mali PM Shader: PM Shader Core 1."/> 8 <event counter="ARM_Mali-T6xx_PM_SHADER_1" display="average" average_selection="yes" units="%" title="Mali PM Shader" name="PM Shader Core 1" description="Mali PM Shader: PM Shader Core 1."/>
@@ -13,23 +13,23 @@
13 <event counter="ARM_Mali-T6xx_PM_SHADER_6" display="average" average_selection="yes" units="%" title="Mali PM Shader" name="PM Shader Core 6" description="Mali PM Shader: PM Shader Core 6."/> 13 <event counter="ARM_Mali-T6xx_PM_SHADER_6" display="average" average_selection="yes" units="%" title="Mali PM Shader" name="PM Shader Core 6" description="Mali PM Shader: PM Shader Core 6."/>
14 <event counter="ARM_Mali-T6xx_PM_SHADER_7" display="average" average_selection="yes" units="%" title="Mali PM Shader" name="PM Shader Core 7" description="Mali PM Shader: PM Shader Core 7."/> 14 <event counter="ARM_Mali-T6xx_PM_SHADER_7" display="average" average_selection="yes" units="%" title="Mali PM Shader" name="PM Shader Core 7" description="Mali PM Shader: PM Shader Core 7."/>
15 </category> 15 </category>
16 16
17 <category name="Mali-T6xx-PMTiler" per_cpu="no"> 17 <category name="Mali-T6xx-PMTiler" per_cpu="no">
18 <event counter="ARM_Mali-T6xx_PM_TILER_0" display="average" average_selection="yes" units="%" title="Mali PM Tiler" name="PM Tiler Core 0" description="Mali PM Tiler: PM Tiler Core 0."/> 18 <event counter="ARM_Mali-T6xx_PM_TILER_0" display="average" average_selection="yes" units="%" title="Mali PM Tiler" name="PM Tiler Core 0" description="Mali PM Tiler: PM Tiler Core 0."/>
19 </category> 19 </category>
20 20
21 <category name="Mali-T6xx-PML2" per_cpu="no"> 21 <category name="Mali-T6xx-PML2" per_cpu="no">
22 <event counter="ARM_Mali-T6xx_PM_L2_0" display="average" average_selection="yes" units="%" title="Mali PM L2" name="PM L2 Core 0" description="Mali PM L2: PM L2 Core 0."/> 22 <event counter="ARM_Mali-T6xx_PM_L2_0" display="average" average_selection="yes" units="%" title="Mali PM L2" name="PM L2 Core 0" description="Mali PM L2: PM L2 Core 0."/>
23 <event counter="ARM_Mali-T6xx_PM_L2_1" display="average" average_selection="yes" units="%" title="Mali PM L2" name="PM L2 Core 1" description="Mali PM L2: PM L2 Core 1."/> 23 <event counter="ARM_Mali-T6xx_PM_L2_1" display="average" average_selection="yes" units="%" title="Mali PM L2" name="PM L2 Core 1" description="Mali PM L2: PM L2 Core 1."/>
24 </category> 24 </category>
25 25
26 <category name="Mali-T6xx-MMU_AS" per_cpu="no"> 26 <category name="Mali-T6xx-MMU_AS" per_cpu="no">
27 <event counter="ARM_Mali-T6xx_MMU_AS_0" display="average" average_selection="yes" units="%" title="Mali MMU Address Space" name="MMU Address Space 0" description="Mali MMU Address Space 0 usage."/> 27 <event counter="ARM_Mali-T6xx_MMU_AS_0" display="average" average_selection="yes" units="%" title="Mali MMU Address Space" name="MMU Address Space 0" description="Mali MMU Address Space 0 usage."/>
28 <event counter="ARM_Mali-T6xx_MMU_AS_1" display="average" average_selection="yes" units="%" title="Mali MMU Address Space" name="MMU Address Space 1" description="Mali MMU Address Space 1 usage."/> 28 <event counter="ARM_Mali-T6xx_MMU_AS_1" display="average" average_selection="yes" units="%" title="Mali MMU Address Space" name="MMU Address Space 1" description="Mali MMU Address Space 1 usage."/>
29 <event counter="ARM_Mali-T6xx_MMU_AS_2" display="average" average_selection="yes" units="%" title="Mali MMU Address Space" name="MMU Address Space 2" description="Mali MMU Address Space 2 usage."/> 29 <event counter="ARM_Mali-T6xx_MMU_AS_2" display="average" average_selection="yes" units="%" title="Mali MMU Address Space" name="MMU Address Space 2" description="Mali MMU Address Space 2 usage."/>
30 <event counter="ARM_Mali-T6xx_MMU_AS_3" display="average" average_selection="yes" units="%" title="Mali MMU Address Space" name="MMU Address Space 3" description="Mali MMU Address Space 3 usage."/> 30 <event counter="ARM_Mali-T6xx_MMU_AS_3" display="average" average_selection="yes" units="%" title="Mali MMU Address Space" name="MMU Address Space 3" description="Mali MMU Address Space 3 usage."/>
31 </category> 31 </category>
32 32
33 <category name="Mali-T6xx-MMU_page_fault" per_cpu="no"> 33 <category name="Mali-T6xx-MMU_page_fault" per_cpu="no">
34 <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_0" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 0" description="Reports the number of newly allocated pages after a MMU page fault in address space 0."/> 34 <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_0" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 0" description="Reports the number of newly allocated pages after a MMU page fault in address space 0."/>
35 <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_1" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 1" description="Reports the number of newly allocated pages after a MMU page fault in address space 1."/> 35 <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_1" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 1" description="Reports the number of newly allocated pages after a MMU page fault in address space 1."/>
diff --git a/daemon/events-Mali-T6xx_hw.xml b/daemon/events-Mali-T6xx_hw.xml
index 77f7aec..825b668 100644
--- a/daemon/events-Mali-T6xx_hw.xml
+++ b/daemon/events-Mali-T6xx_hw.xml
@@ -1,5 +1,5 @@
1 1
2 <category name="Mali-T6xx-JobManager" per_cpu="no"> 2 <category name="Mali-T6xx-JobManager" per_cpu="no">
3 <event counter="ARM_Mali-T6xx_MESSAGES_SENT" title="Mali GPU Job Manager" name="Job Manager messages sent" description="Number of JCB messages sent by the Job Manager."/> 3 <event counter="ARM_Mali-T6xx_MESSAGES_SENT" title="Mali GPU Job Manager" name="Job Manager messages sent" description="Number of JCB messages sent by the Job Manager."/>
4 <event counter="ARM_Mali-T6xx_MESSAGES_RECEIVED" title="Mali GPU Job Manager" name="Job Manager messages received " description="Number of JCB messages received by the Job Manager."/> 4 <event counter="ARM_Mali-T6xx_MESSAGES_RECEIVED" title="Mali GPU Job Manager" name="Job Manager messages received " description="Number of JCB messages received by the Job Manager."/>
5 <event counter="ARM_Mali-T6xx_GPU_ACTIVE" title="Mali GPU Job Manager" name="GPU active cycles" description="Number of cycles the GPU was active."/> 5 <event counter="ARM_Mali-T6xx_GPU_ACTIVE" title="Mali GPU Job Manager" name="GPU active cycles" description="Number of cycles the GPU was active."/>
@@ -63,7 +63,7 @@
63--> 63-->
64 </category> 64 </category>
65 65
66 <category name="Mali-T6xx-Tiler" per_cpu="no"> 66 <category name="Mali-T6xx-Tiler" per_cpu="no">
67<!-- 67<!--
68 <event counter="ARM_Mali-T6xx_JOBS_PROCESSED" title="Mali GPU Tiler" name="Jobs processed" description="Number of jobs processed."/> 68 <event counter="ARM_Mali-T6xx_JOBS_PROCESSED" title="Mali GPU Tiler" name="Jobs processed" description="Number of jobs processed."/>
69--> 69-->
@@ -119,7 +119,7 @@
119 119
120 <event counter="ARM_Mali-T6xx_WRBUF_STALL" title="Mali GPU Tiler" name="Write-buffer stalls" description="Number of write-buffer stalls."/> 120 <event counter="ARM_Mali-T6xx_WRBUF_STALL" title="Mali GPU Tiler" name="Write-buffer stalls" description="Number of write-buffer stalls."/>
121 <event counter="ARM_Mali-T6xx_ACTIVE" title="Mali GPU Tiler" name="Tiler active cycles" description="Number of cycles the tiler is active."/> 121 <event counter="ARM_Mali-T6xx_ACTIVE" title="Mali GPU Tiler" name="Tiler active cycles" description="Number of cycles the tiler is active."/>
122 <event counter="ARM_Mali-T6xx_LOADING_DESC" title="Mali GPU Tiler" name="Cycles loading descriptors" description="Number of cycle spent loading descriptors while the tiler frontend is otherwise idle."/> 122 <event counter="ARM_Mali-T6xx_LOADING_DESC" title="Mali GPU Tiler" name="Cycles loading descriptors" description="Number of cycle spent loading descriptors while the tiler frontend is otherwise idle."/>
123 <event counter="ARM_Mali-T6xx_INDEX_WAIT" title="Mali GPU Tiler" name="Cycles index fetch miss" description="Number of cycles the vertex cache could accept an index, but due to a miss, the index fetcher could not provide one."/> 123 <event counter="ARM_Mali-T6xx_INDEX_WAIT" title="Mali GPU Tiler" name="Cycles index fetch miss" description="Number of cycles the vertex cache could accept an index, but due to a miss, the index fetcher could not provide one."/>
124 124
125 <event counter="ARM_Mali-T6xx_INDEX_RANGE_WAIT" title="Mali GPU Tiler" name="Cycles index out of range" description="Number of cycles the index fetcher provides an index, but the index is outside the range of currently shaded vertices. Only relevant for fused jobs."/> 125 <event counter="ARM_Mali-T6xx_INDEX_RANGE_WAIT" title="Mali GPU Tiler" name="Cycles index out of range" description="Number of cycles the index fetcher provides an index, but the index is outside the range of currently shaded vertices. Only relevant for fused jobs."/>
@@ -132,7 +132,7 @@
132 132
133 <event counter="ARM_Mali-T6xx_UTLB_STALL" title="Mali GPU Tiler" name="uTLB cycles stall" description="uTLB: Cycles with stall on input AXI address channel."/> 133 <event counter="ARM_Mali-T6xx_UTLB_STALL" title="Mali GPU Tiler" name="uTLB cycles stall" description="uTLB: Cycles with stall on input AXI address channel."/>
134 134
135 <event counter="ARM_Mali-T6xx_UTLB_REPLAY_MISS" title="Mali GPU Tiler" name="uTLB replay buffer cache misses" description="uTLB: Number of cache misses on accesses from replay buffer."/> 135 <event counter="ARM_Mali-T6xx_UTLB_REPLAY_MISS" title="Mali GPU Tiler" name="uTLB replay buffer cache misses" description="uTLB: Number of cache misses on accesses from replay buffer."/>
136 <event counter="ARM_Mali-T6xx_UTLB_REPLAY_FULL" title="Mali GPU Tiler" name="uTLB cycle reply buffer full" description="uTLB: Number of cycles replay buffer is full."/> 136 <event counter="ARM_Mali-T6xx_UTLB_REPLAY_FULL" title="Mali GPU Tiler" name="uTLB cycle reply buffer full" description="uTLB: Number of cycles replay buffer is full."/>
137 <event counter="ARM_Mali-T6xx_UTLB_NEW_MISS" title="Mali GPU Tiler" name="uTLB cache misses on new request" description="uTLB: Number of cache misses on new requests."/> 137 <event counter="ARM_Mali-T6xx_UTLB_NEW_MISS" title="Mali GPU Tiler" name="uTLB cache misses on new request" description="uTLB: Number of cache misses on new requests."/>
138 <event counter="ARM_Mali-T6xx_UTLB_HIT" title="Mali GPU Tiler" name="uTLB cache hits" description="uTLB: Number of cache hits."/> 138 <event counter="ARM_Mali-T6xx_UTLB_HIT" title="Mali GPU Tiler" name="uTLB cache hits" description="uTLB: Number of cache hits."/>
diff --git a/daemon/events-ScorpionMP.xml b/daemon/events-ScorpionMP.xml
index 42acc64..309f103 100644
--- a/daemon/events-ScorpionMP.xml
+++ b/daemon/events-ScorpionMP.xml
@@ -87,4 +87,4 @@
87 <event event="0x8d" title="Scorpion" name="EXCEPTIONS_DENORM" description="Scorpion denorm exceptions"/> 87 <event event="0x8d" title="Scorpion" name="EXCEPTIONS_DENORM" description="Scorpion denorm exceptions"/>
88 <event event="0x8e" title="ScorpionMP" name="NUM_BARRIERS" description="Barriers"/> 88 <event event="0x8e" title="ScorpionMP" name="NUM_BARRIERS" description="Barriers"/>
89 <event event="0x8f" title="ScorpionMP" name="BARRIER_CYCLES" description="Barrier cycles"/> 89 <event event="0x8f" title="ScorpionMP" name="BARRIER_CYCLES" description="Barrier cycles"/>
90 </category> 90 </category>
diff --git a/daemon/main.cpp b/daemon/main.cpp
index 5bc75ef..894bad7 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -19,6 +19,8 @@
19#include <sys/mount.h> 19#include <sys/mount.h>
20#include <fcntl.h> 20#include <fcntl.h>
21#include <sys/mman.h> 21#include <sys/mman.h>
22#include <sys/time.h>
23#include <sys/resource.h>
22#include "Child.h" 24#include "Child.h"
23#include "SessionData.h" 25#include "SessionData.h"
24#include "OlySocket.h" 26#include "OlySocket.h"
@@ -28,7 +30,6 @@
28#define DEBUG false 30#define DEBUG false
29 31
30extern Child* child; 32extern Child* child;
31extern void handleException();
32int shutdownFilesystem(); 33int shutdownFilesystem();
33static pthread_mutex_t numSessions_mutex; 34static pthread_mutex_t numSessions_mutex;
34static int numSessions = 0; 35static int numSessions = 0;
@@ -297,7 +298,10 @@ struct cmdline_t parseCommandLine(int argc, char** argv) {
297 298
298// Gator data flow: collector -> collector fifo -> sender 299// Gator data flow: collector -> collector fifo -> sender
299int main(int argc, char** argv, char* envp[]) { 300int main(int argc, char** argv, char* envp[]) {
301 // Ensure proper signal handling by making gatord the process group leader
302 // e.g. it may not be the group leader when launched as 'sudo gatord'
300 setsid(); 303 setsid();
304
301 gSessionData = new SessionData(); // Global data class 305 gSessionData = new SessionData(); // Global data class
302 logg = new Logging(DEBUG); // Set up global thread-safe logging 306 logg = new Logging(DEBUG); // Set up global thread-safe logging
303 util = new OlyUtility(); // Set up global utility class 307 util = new OlyUtility(); // Set up global utility class
@@ -314,9 +318,6 @@ int main(int argc, char** argv, char* envp[]) {
314 logg->logMessage("setpriority() failed"); 318 logg->logMessage("setpriority() failed");
315 } 319 }
316 320
317 // Initialize session data
318 gSessionData->initialize();
319
320 // Parse the command line parameters 321 // Parse the command line parameters
321 struct cmdline_t cmdline = parseCommandLine(argc, argv); 322 struct cmdline_t cmdline = parseCommandLine(argc, argv);
322 323
diff --git a/driver/Makefile b/driver/Makefile
index 6cafecf..d22d29d 100644
--- a/driver/Makefile
+++ b/driver/Makefile
@@ -27,7 +27,7 @@ gator-y += gator_events_mali_common.o
27EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT) 27EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT)
28endif 28endif
29 29
30# GATOR_TEST controls whether to include (=1) or exclude (=0) test code. 30# GATOR_TEST controls whether to include (=1) or exclude (=0) test code.
31GATOR_TEST ?= 0 31GATOR_TEST ?= 0
32EXTRA_CFLAGS += -DGATOR_TEST=$(GATOR_TEST) 32EXTRA_CFLAGS += -DGATOR_TEST=$(GATOR_TEST)
33 33
diff --git a/driver/gator.h b/driver/gator.h
index 5a40e17..9a4617b 100644
--- a/driver/gator.h
+++ b/driver/gator.h
@@ -15,7 +15,7 @@
15#include <linux/list.h> 15#include <linux/list.h>
16 16
17#define GATOR_PERF_SUPPORT LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) 17#define GATOR_PERF_SUPPORT LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
18#define GATOR_PERF_PMU_SUPPORT GATOR_PERF_SUPPORT && defined(CONFIG_PERF_EVENTS) && defined(CONFIG_HW_PERF_EVENTS) 18#define GATOR_PERF_PMU_SUPPORT GATOR_PERF_SUPPORT && defined(CONFIG_PERF_EVENTS) && (!(defined(__arm__) || defined(__aarch64__)) || defined(CONFIG_HW_PERF_EVENTS))
19#define GATOR_NO_PERF_SUPPORT (!(GATOR_PERF_SUPPORT)) 19#define GATOR_NO_PERF_SUPPORT (!(GATOR_PERF_SUPPORT))
20#define GATOR_CPU_FREQ_SUPPORT (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) && defined(CONFIG_CPU_FREQ) 20#define GATOR_CPU_FREQ_SUPPORT (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) && defined(CONFIG_CPU_FREQ)
21 21
@@ -33,22 +33,39 @@
33#define SCORPIONMP 0x02d 33#define SCORPIONMP 0x02d
34#define KRAITSIM 0x049 34#define KRAITSIM 0x049
35#define KRAIT 0x04d 35#define KRAIT 0x04d
36#define KRAIT_S4_PRO 0x06f
37#define CORTEX_A53 0xd03
38#define CORTEX_A57 0xd07
36#define AARCH64 0xd0f 39#define AARCH64 0xd0f
40#define OTHER 0xfff
41
42#define MAXSIZE_CORE_NAME 32
43
44struct gator_cpu {
45 const int cpuid;
46 const char core_name[MAXSIZE_CORE_NAME];
47 const char * const pmnc_name;
48 const int pmnc_counters;
49 const int ccnt;
50};
51
52extern struct gator_cpu gator_cpus[];
37 53
38/****************************************************************************** 54/******************************************************************************
39 * Filesystem 55 * Filesystem
40 ******************************************************************************/ 56 ******************************************************************************/
41int gatorfs_create_file_perm(struct super_block *sb, struct dentry *root, 57int gatorfs_create_file_perm(struct super_block *sb, struct dentry *root,
42 char const *name, const struct file_operations *fops, int perm); 58 char const *name,
59 const struct file_operations *fops, int perm);
43 60
44struct dentry *gatorfs_mkdir(struct super_block *sb, 61struct dentry *gatorfs_mkdir(struct super_block *sb, struct dentry *root,
45 struct dentry *root, char const *name); 62 char const *name);
46 63
47int gatorfs_create_ulong(struct super_block *sb, struct dentry *root, 64int gatorfs_create_ulong(struct super_block *sb, struct dentry *root,
48 char const *name, unsigned long *val); 65 char const *name, unsigned long *val);
49 66
50int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root, 67int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root,
51 char const *name, unsigned long *val); 68 char const *name, unsigned long *val);
52 69
53void gator_op_create_files(struct super_block *sb, struct dentry *root); 70void gator_op_create_files(struct super_block *sb, struct dentry *root);
54 71
@@ -77,15 +94,16 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root);
77 * Events 94 * Events
78 ******************************************************************************/ 95 ******************************************************************************/
79struct gator_interface { 96struct gator_interface {
80 int (*create_files)(struct super_block *sb, struct dentry *root); 97 void (*shutdown)(void); // Complementary function to init
81 int (*start)(void); 98 int (*create_files)(struct super_block *sb, struct dentry *root);
82 void (*stop)(void); 99 int (*start)(void);
83 int (*online)(int** buffer); 100 void (*stop)(void); // Complementary function to start
84 int (*offline)(int** buffer); 101 int (*online)(int **buffer);
85 void (*online_dispatch)(int cpu); // called in process context but may not be running on core 'cpu' 102 int (*offline)(int **buffer);
86 void (*offline_dispatch)(int cpu); // called in process context but may not be running on core 'cpu' 103 void (*online_dispatch)(int cpu); // called in process context but may not be running on core 'cpu'
87 int (*read)(int **buffer); 104 void (*offline_dispatch)(int cpu); // called in process context but may not be running on core 'cpu'
88 int (*read64)(long long **buffer); 105 int (*read)(int **buffer);
106 int (*read64)(long long **buffer);
89 struct list_head list; 107 struct list_head list;
90}; 108};
91 109
@@ -96,8 +114,8 @@ struct gator_interface {
96 114
97int gator_events_install(struct gator_interface *interface); 115int gator_events_install(struct gator_interface *interface);
98int gator_events_get_key(void); 116int gator_events_get_key(void);
99extern u32 gator_cpuid(void); 117u32 gator_cpuid(void);
100 118
101void gator_backtrace_handler(struct pt_regs * const regs); 119void gator_backtrace_handler(struct pt_regs *const regs);
102 120
103#endif // GATOR_H_ 121#endif // GATOR_H_
diff --git a/driver/gator_annotate.c b/driver/gator_annotate.c
index 928e252..42f9951 100644
--- a/driver/gator_annotate.c
+++ b/driver/gator_annotate.c
@@ -44,8 +44,9 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t
44 return -EINVAL; 44 return -EINVAL;
45 } 45 }
46 46
47 // Annotation is not supported in interrupt context 47 // Annotations are not supported in interrupt context
48 if (in_interrupt()) { 48 if (in_interrupt()) {
49 printk(KERN_WARNING "gator: Annotations are not supported in interrupt context\n");
49 return -EINVAL; 50 return -EINVAL;
50 } 51 }
51 52
@@ -58,7 +59,8 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t
58 goto annotate_write_out; 59 goto annotate_write_out;
59 } 60 }
60 61
61 cpu = 0; // Annotation only uses a single per-cpu buffer as the data must be in order to the engine 62 // Annotation only uses a single per-cpu buffer as the data must be in order to the engine
63 cpu = 0;
62 64
63 if (current == NULL) { 65 if (current == NULL) {
64 pid = 0; 66 pid = 0;
@@ -129,18 +131,21 @@ static int annotate_release(struct inode *inode, struct file *file)
129 uint32_t pid = current->pid; 131 uint32_t pid = current->pid;
130 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id()); 132 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id());
131 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid); 133 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
132 gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); // time 134 gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); // time
133 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); // size 135 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); // size
134 } 136 }
135 137
138 // Check and commit; commit is set to occur once buffer is 3/4 full
139 buffer_check(cpu, ANNOTATE_BUF);
140
136 spin_unlock(&annotate_lock); 141 spin_unlock(&annotate_lock);
137 142
138 return 0; 143 return 0;
139} 144}
140 145
141static const struct file_operations annotate_fops = { 146static const struct file_operations annotate_fops = {
142 .write = annotate_write, 147 .write = annotate_write,
143 .release = annotate_release 148 .release = annotate_release
144}; 149};
145 150
146static int gator_annotate_create_files(struct super_block *sb, struct dentry *root) 151static int gator_annotate_create_files(struct super_block *sb, struct dentry *root)
diff --git a/driver/gator_annotate_kernel.c b/driver/gator_annotate_kernel.c
index bc68fa8..67d2d6c 100644
--- a/driver/gator_annotate_kernel.c
+++ b/driver/gator_annotate_kernel.c
@@ -8,11 +8,13 @@
8 */ 8 */
9 9
10#define ESCAPE_CODE 0x1c 10#define ESCAPE_CODE 0x1c
11#define STRING_ANNOTATION 0x03 11#define STRING_ANNOTATION 0x06
12#define NAME_CHANNEL_ANNOTATION 0x07
13#define NAME_GROUP_ANNOTATION 0x08
12#define VISUAL_ANNOTATION 0x04 14#define VISUAL_ANNOTATION 0x04
13#define MARKER_ANNOTATION 0x05 15#define MARKER_ANNOTATION 0x05
14 16
15static void kannotate_write(const char* ptr, unsigned int size) 17static void kannotate_write(const char *ptr, unsigned int size)
16{ 18{
17 int retval; 19 int retval;
18 int pos = 0; 20 int pos = 0;
@@ -27,91 +29,129 @@ static void kannotate_write(const char* ptr, unsigned int size)
27 } 29 }
28} 30}
29 31
30static void gator_annotate_code(char code) 32void gator_annotate_channel(int channel, const char *str)
31{ 33{
32 int header = ESCAPE_CODE | (code << 8); 34 int str_size = strlen(str) & 0xffff;
33 kannotate_write((char*)&header, sizeof(header)); 35 long long header = ESCAPE_CODE | (STRING_ANNOTATION << 8) | (channel << 16) | ((long long)str_size << 48);
36 kannotate_write((char *)&header, sizeof(header));
37 kannotate_write(str, str_size);
34} 38}
35 39
36static void gator_annotate_code_str(char code, const char* string) 40EXPORT_SYMBOL(gator_annotate_channel);
37{
38 int str_size = strlen(string) & 0xffff;
39 int header = ESCAPE_CODE | (code << 8) | (str_size << 16);
40 kannotate_write((char*)&header, sizeof(header));
41 kannotate_write(string, str_size);
42}
43 41
44static void gator_annotate_code_color(char code, int color) 42void gator_annotate(const char *str)
45{ 43{
46 long long header = (ESCAPE_CODE | (code << 8) | 0x00040000 | ((long long)color << 32)); 44 gator_annotate_channel(0, str);
47 kannotate_write((char*)&header, sizeof(header));
48} 45}
49 46
50static void gator_annotate_code_color_str(char code, int color, const char* string) 47EXPORT_SYMBOL(gator_annotate);
48
49void gator_annotate_channel_color(int channel, int color, const char *str)
51{ 50{
52 int str_size = (strlen(string) + 4) & 0xffff; 51 int str_size = (strlen(str) + 4) & 0xffff;
53 long long header = ESCAPE_CODE | (code << 8) | (str_size << 16) | ((long long)color << 32); 52 char header[12];
54 kannotate_write((char*)&header, sizeof(header)); 53 header[0] = ESCAPE_CODE;
55 kannotate_write(string, str_size - 4); 54 header[1] = STRING_ANNOTATION;
55 *(u32 *)(&header[2]) = channel;
56 *(u16 *)(&header[6]) = str_size;
57 *(u32 *)(&header[8]) = color;
58 kannotate_write((char *)&header, sizeof(header));
59 kannotate_write(str, str_size - 4);
56} 60}
57 61
58// String annotation 62EXPORT_SYMBOL(gator_annotate_channel_color);
59void gator_annotate(const char* string) 63
64void gator_annotate_color(int color, const char *str)
60{ 65{
61 gator_annotate_code_str(STRING_ANNOTATION, string); 66 gator_annotate_channel_color(0, color, str);
62} 67}
63EXPORT_SYMBOL(gator_annotate);
64 68
65// String annotation with color 69EXPORT_SYMBOL(gator_annotate_color);
66void gator_annotate_color(int color, const char* string) 70
71void gator_annotate_channel_end(int channel)
67{ 72{
68 gator_annotate_code_color_str(STRING_ANNOTATION, color, string); 73 long long header = ESCAPE_CODE | (STRING_ANNOTATION << 8) | (channel << 16);
74 kannotate_write((char *)&header, sizeof(header));
69} 75}
70EXPORT_SYMBOL(gator_annotate_color);
71 76
72// Terminate an annotation 77EXPORT_SYMBOL(gator_annotate_channel_end);
78
73void gator_annotate_end(void) 79void gator_annotate_end(void)
74{ 80{
75 gator_annotate_code(STRING_ANNOTATION); 81 gator_annotate_channel_end(0);
76} 82}
83
77EXPORT_SYMBOL(gator_annotate_end); 84EXPORT_SYMBOL(gator_annotate_end);
78 85
79// Image annotation with optional string 86void gator_annotate_name_channel(int channel, int group, const char* str)
80void gator_annotate_visual(const char* data, unsigned int length, const char* string) 87{
88 int str_size = strlen(str) & 0xffff;
89 char header[12];
90 header[0] = ESCAPE_CODE;
91 header[1] = NAME_CHANNEL_ANNOTATION;
92 *(u32 *)(&header[2]) = channel;
93 *(u32 *)(&header[6]) = group;
94 *(u16 *)(&header[10]) = str_size;
95 kannotate_write((char *)&header, sizeof(header));
96 kannotate_write(str, str_size);
97}
98
99EXPORT_SYMBOL(gator_annotate_name_channel);
100
101void gator_annotate_name_group(int group, const char* str)
102{
103 int str_size = strlen(str) & 0xffff;
104 long long header = ESCAPE_CODE | (NAME_GROUP_ANNOTATION << 8) | (group << 16) | ((long long)str_size << 48);
105 kannotate_write((char *)&header, sizeof(header));
106 kannotate_write(str, str_size);
107}
108
109EXPORT_SYMBOL(gator_annotate_name_group);
110
111void gator_annotate_visual(const char *data, unsigned int length, const char *str)
81{ 112{
82 int str_size = strlen(string) & 0xffff; 113 int str_size = strlen(str) & 0xffff;
83 int visual_annotation = ESCAPE_CODE | (VISUAL_ANNOTATION << 8) | (str_size << 16); 114 int visual_annotation = ESCAPE_CODE | (VISUAL_ANNOTATION << 8) | (str_size << 16);
84 kannotate_write((char*)&visual_annotation, sizeof(visual_annotation)); 115 kannotate_write((char *)&visual_annotation, sizeof(visual_annotation));
85 kannotate_write(string, str_size); 116 kannotate_write(str, str_size);
86 kannotate_write((char*)&length, sizeof(length)); 117 kannotate_write((char *)&length, sizeof(length));
87 kannotate_write(data, length); 118 kannotate_write(data, length);
88} 119}
120
89EXPORT_SYMBOL(gator_annotate_visual); 121EXPORT_SYMBOL(gator_annotate_visual);
90 122
91// Marker annotation
92void gator_annotate_marker(void) 123void gator_annotate_marker(void)
93{ 124{
94 gator_annotate_code(MARKER_ANNOTATION); 125 int header = ESCAPE_CODE | (MARKER_ANNOTATION << 8);
126 kannotate_write((char *)&header, sizeof(header));
95} 127}
128
96EXPORT_SYMBOL(gator_annotate_marker); 129EXPORT_SYMBOL(gator_annotate_marker);
97 130
98// Marker annotation with a string 131void gator_annotate_marker_str(const char *str)
99void gator_annotate_marker_str(const char* string)
100{ 132{
101 gator_annotate_code_str(MARKER_ANNOTATION, string); 133 int str_size = strlen(str) & 0xffff;
134 int header = ESCAPE_CODE | (MARKER_ANNOTATION << 8) | (str_size << 16);
135 kannotate_write((char *)&header, sizeof(header));
136 kannotate_write(str, str_size);
102} 137}
138
103EXPORT_SYMBOL(gator_annotate_marker_str); 139EXPORT_SYMBOL(gator_annotate_marker_str);
104 140
105// Marker annotation with a color
106void gator_annotate_marker_color(int color) 141void gator_annotate_marker_color(int color)
107{ 142{
108 gator_annotate_code_color(MARKER_ANNOTATION, color); 143 long long header = (ESCAPE_CODE | (MARKER_ANNOTATION << 8) | 0x00040000 | ((long long)color << 32));
144 kannotate_write((char *)&header, sizeof(header));
109} 145}
146
110EXPORT_SYMBOL(gator_annotate_marker_color); 147EXPORT_SYMBOL(gator_annotate_marker_color);
111 148
112// Marker annotation with a string and color 149void gator_annotate_marker_color_str(int color, const char *str)
113void gator_annotate_marker_color_str(int color, const char* string)
114{ 150{
115 gator_annotate_code_color_str(MARKER_ANNOTATION, color, string); 151 int str_size = (strlen(str) + 4) & 0xffff;
152 long long header = ESCAPE_CODE | (MARKER_ANNOTATION << 8) | (str_size << 16) | ((long long)color << 32);
153 kannotate_write((char *)&header, sizeof(header));
154 kannotate_write(str, str_size - 4);
116} 155}
156
117EXPORT_SYMBOL(gator_annotate_marker_color_str); 157EXPORT_SYMBOL(gator_annotate_marker_color_str);
diff --git a/driver/gator_backtrace.c b/driver/gator_backtrace.c
index 2173d8a..e6125b3 100644
--- a/driver/gator_backtrace.c
+++ b/driver/gator_backtrace.c
@@ -11,20 +11,28 @@
11 * EABI backtrace stores {fp,lr} on the stack. 11 * EABI backtrace stores {fp,lr} on the stack.
12 */ 12 */
13struct frame_tail_eabi { 13struct frame_tail_eabi {
14 unsigned long fp; // points to prev_lr 14 unsigned long fp; // points to prev_lr
15 unsigned long lr; 15 unsigned long lr;
16}; 16};
17 17
18static void arm_backtrace_eabi(int cpu, struct pt_regs * const regs, unsigned int depth) 18static void arm_backtrace_eabi(int cpu, struct pt_regs *const regs, unsigned int depth)
19{ 19{
20#if defined(__arm__) 20#if defined(__arm__) || defined(__aarch64__)
21 struct frame_tail_eabi *tail; 21 struct frame_tail_eabi *tail;
22 struct frame_tail_eabi *next; 22 struct frame_tail_eabi *next;
23 struct frame_tail_eabi *ptrtail; 23 struct frame_tail_eabi *ptrtail;
24 struct frame_tail_eabi buftail; 24 struct frame_tail_eabi buftail;
25#if defined(__arm__)
25 unsigned long fp = regs->ARM_fp; 26 unsigned long fp = regs->ARM_fp;
26 unsigned long sp = regs->ARM_sp; 27 unsigned long sp = regs->ARM_sp;
27 unsigned long lr = regs->ARM_lr; 28 unsigned long lr = regs->ARM_lr;
29 const int frame_offset = 4;
30#else
31 unsigned long fp = regs->regs[29];
32 unsigned long sp = regs->sp;
33 unsigned long lr = regs->regs[30];
34 const int frame_offset = 0;
35#endif
28 int is_user_mode = user_mode(regs); 36 int is_user_mode = user_mode(regs);
29 37
30 if (!is_user_mode) { 38 if (!is_user_mode) {
@@ -39,9 +47,9 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs * const regs, unsigned in
39 return; 47 return;
40 } 48 }
41 49
42 tail = (struct frame_tail_eabi *)(fp - 4); 50 tail = (struct frame_tail_eabi *)(fp - frame_offset);
43 51
44 while (depth-- && tail && !((unsigned long) tail & 3)) { 52 while (depth-- && tail && !((unsigned long)tail & 3)) {
45 /* Also check accessibility of one struct frame_tail beyond */ 53 /* Also check accessibility of one struct frame_tail beyond */
46 if (!access_ok(VERIFY_READ, tail, sizeof(struct frame_tail_eabi))) 54 if (!access_ok(VERIFY_READ, tail, sizeof(struct frame_tail_eabi)))
47 return; 55 return;
@@ -53,10 +61,10 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs * const regs, unsigned in
53 gator_add_trace(cpu, lr); 61 gator_add_trace(cpu, lr);
54 62
55 /* frame pointers should progress back up the stack, towards higher addresses */ 63 /* frame pointers should progress back up the stack, towards higher addresses */
56 next = (struct frame_tail_eabi *)(lr - 4); 64 next = (struct frame_tail_eabi *)(lr - frame_offset);
57 if (tail >= next || lr == 0) { 65 if (tail >= next || lr == 0) {
58 fp = ptrtail[0].fp; 66 fp = ptrtail[0].fp;
59 next = (struct frame_tail_eabi *)(fp - 4); 67 next = (struct frame_tail_eabi *)(fp - frame_offset);
60 /* check tail is valid */ 68 /* check tail is valid */
61 if (tail >= next || fp == 0) { 69 if (tail >= next || fp == 0) {
62 return; 70 return;
@@ -68,7 +76,7 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs * const regs, unsigned in
68#endif 76#endif
69} 77}
70 78
71#if defined(__arm__) 79#if defined(__arm__) || defined(__aarch64__)
72static int report_trace(struct stackframe *frame, void *d) 80static int report_trace(struct stackframe *frame, void *d)
73{ 81{
74 struct module *mod; 82 struct module *mod;
@@ -78,7 +86,7 @@ static int report_trace(struct stackframe *frame, void *d)
78 if (*depth) { 86 if (*depth) {
79 mod = __module_address(addr); 87 mod = __module_address(addr);
80 if (mod) { 88 if (mod) {
81 cookie = get_cookie(cpu, current, NULL, mod, true); 89 cookie = get_cookie(cpu, current, mod->name, false);
82 addr = addr - (unsigned long)mod->module_core; 90 addr = addr - (unsigned long)mod->module_core;
83 } 91 }
84 marshal_backtrace(addr & ~1, cookie); 92 marshal_backtrace(addr & ~1, cookie);
@@ -91,9 +99,9 @@ static int report_trace(struct stackframe *frame, void *d)
91 99
92// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile 100// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile
93// #define GATOR_KERNEL_STACK_UNWINDING 101// #define GATOR_KERNEL_STACK_UNWINDING
94static void kernel_backtrace(int cpu, struct pt_regs * const regs) 102static void kernel_backtrace(int cpu, struct pt_regs *const regs)
95{ 103{
96#if defined(__arm__) 104#if defined(__arm__) || defined(__aarch64__)
97#ifdef GATOR_KERNEL_STACK_UNWINDING 105#ifdef GATOR_KERNEL_STACK_UNWINDING
98 int depth = gator_backtrace_depth; 106 int depth = gator_backtrace_depth;
99#else 107#else
@@ -102,10 +110,16 @@ static void kernel_backtrace(int cpu, struct pt_regs * const regs)
102 struct stackframe frame; 110 struct stackframe frame;
103 if (depth == 0) 111 if (depth == 0)
104 depth = 1; 112 depth = 1;
113#if defined(__arm__)
105 frame.fp = regs->ARM_fp; 114 frame.fp = regs->ARM_fp;
106 frame.sp = regs->ARM_sp; 115 frame.sp = regs->ARM_sp;
107 frame.lr = regs->ARM_lr; 116 frame.lr = regs->ARM_lr;
108 frame.pc = regs->ARM_pc; 117 frame.pc = regs->ARM_pc;
118#else
119 frame.fp = regs->regs[29];
120 frame.sp = regs->sp;
121 frame.pc = regs->pc;
122#endif
109 walk_stackframe(&frame, report_trace, &depth); 123 walk_stackframe(&frame, report_trace, &depth);
110#else 124#else
111 marshal_backtrace(PC_REG & ~1, NO_COOKIE); 125 marshal_backtrace(PC_REG & ~1, NO_COOKIE);
diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c
index 21dc4eb..bb401bb 100644
--- a/driver/gator_cookies.c
+++ b/driver/gator_cookies.c
@@ -7,7 +7,7 @@
7 * 7 *
8 */ 8 */
9 9
10#define COOKIEMAP_ENTRIES 1024 /* must be power of 2 */ 10#define COOKIEMAP_ENTRIES 1024 /* must be power of 2 */
11#define TRANSLATE_SIZE 256 11#define TRANSLATE_SIZE 256
12#define MAX_COLLISIONS 2 12#define MAX_COLLISIONS 2
13 13
@@ -20,28 +20,29 @@ static DEFINE_PER_CPU(uint64_t *, cookie_keys);
20static DEFINE_PER_CPU(uint32_t *, cookie_values); 20static DEFINE_PER_CPU(uint32_t *, cookie_values);
21static DEFINE_PER_CPU(int, translate_buffer_read); 21static DEFINE_PER_CPU(int, translate_buffer_read);
22static DEFINE_PER_CPU(int, translate_buffer_write); 22static DEFINE_PER_CPU(int, translate_buffer_write);
23static DEFINE_PER_CPU(void * *, translate_buffer); 23static DEFINE_PER_CPU(void **, translate_buffer);
24 24
25static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt); 25static inline uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq);
26static void wq_cookie_handler(struct work_struct *unused); 26static void wq_cookie_handler(struct work_struct *unused);
27DECLARE_WORK(cookie_work, wq_cookie_handler); 27DECLARE_WORK(cookie_work, wq_cookie_handler);
28static struct timer_list app_process_wake_up_timer; 28static struct timer_list app_process_wake_up_timer;
29static void app_process_wake_up_handler(unsigned long unused_data); 29static void app_process_wake_up_handler(unsigned long unused_data);
30 30
31static uint32_t cookiemap_code(uint64_t value64) { 31static uint32_t cookiemap_code(uint64_t value64)
32{
32 uint32_t value = (uint32_t)((value64 >> 32) + value64); 33 uint32_t value = (uint32_t)((value64 >> 32) + value64);
33 uint32_t cookiecode = (value >> 24) & 0xff; 34 uint32_t cookiecode = (value >> 24) & 0xff;
34 cookiecode = cookiecode * 31 + ((value >> 16) & 0xff); 35 cookiecode = cookiecode * 31 + ((value >> 16) & 0xff);
35 cookiecode = cookiecode * 31 + ((value >> 8) & 0xff); 36 cookiecode = cookiecode * 31 + ((value >> 8) & 0xff);
36 cookiecode = cookiecode * 31 + ((value >> 0) & 0xff); 37 cookiecode = cookiecode * 31 + ((value >> 0) & 0xff);
37 cookiecode &= (COOKIEMAP_ENTRIES-1); 38 cookiecode &= (COOKIEMAP_ENTRIES - 1);
38 return cookiecode * MAX_COLLISIONS; 39 return cookiecode * MAX_COLLISIONS;
39} 40}
40 41
41static uint32_t gator_chksum_crc32(char *data) 42static uint32_t gator_chksum_crc32(const char *data)
42{ 43{
43 register unsigned long crc; 44 register unsigned long crc;
44 unsigned char *block = data; 45 const unsigned char *block = data;
45 int i, length = strlen(data); 46 int i, length = strlen(data);
46 47
47 crc = 0xFFFFFFFF; 48 crc = 0xFFFFFFFF;
@@ -57,7 +58,8 @@ static uint32_t gator_chksum_crc32(char *data)
57 * Pre: [0][1][v][3]..[n-1] 58 * Pre: [0][1][v][3]..[n-1]
58 * Post: [v][0][1][3]..[n-1] 59 * Post: [v][0][1][3]..[n-1]
59 */ 60 */
60static uint32_t cookiemap_exists(uint64_t key) { 61static uint32_t cookiemap_exists(uint64_t key)
62{
61 unsigned long x, flags, retval = 0; 63 unsigned long x, flags, retval = 0;
62 int cpu = smp_processor_id(); 64 int cpu = smp_processor_id();
63 uint32_t cookiecode = cookiemap_code(key); 65 uint32_t cookiecode = cookiemap_code(key);
@@ -70,8 +72,8 @@ static uint32_t cookiemap_exists(uint64_t key) {
70 if (keys[x] == key) { 72 if (keys[x] == key) {
71 uint32_t value = values[x]; 73 uint32_t value = values[x];
72 for (; x > 0; x--) { 74 for (; x > 0; x--) {
73 keys[x] = keys[x-1]; 75 keys[x] = keys[x - 1];
74 values[x] = values[x-1]; 76 values[x] = values[x - 1];
75 } 77 }
76 keys[0] = key; 78 keys[0] = key;
77 values[0] = value; 79 values[0] = value;
@@ -89,30 +91,31 @@ static uint32_t cookiemap_exists(uint64_t key) {
89 * Pre: [0][1][2][3]..[n-1] 91 * Pre: [0][1][2][3]..[n-1]
90 * Post: [v][0][1][2]..[n-2] 92 * Post: [v][0][1][2]..[n-2]
91 */ 93 */
92static void cookiemap_add(uint64_t key, uint32_t value) { 94static void cookiemap_add(uint64_t key, uint32_t value)
95{
93 int cpu = smp_processor_id(); 96 int cpu = smp_processor_id();
94 int cookiecode = cookiemap_code(key); 97 int cookiecode = cookiemap_code(key);
95 uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]); 98 uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]);
96 uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]); 99 uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]);
97 int x; 100 int x;
98 101
99 for (x = MAX_COLLISIONS-1; x > 0; x--) { 102 for (x = MAX_COLLISIONS - 1; x > 0; x--) {
100 keys[x] = keys[x-1]; 103 keys[x] = keys[x - 1];
101 values[x] = values[x-1]; 104 values[x] = values[x - 1];
102 } 105 }
103 keys[0] = key; 106 keys[0] = key;
104 values[0] = value; 107 values[0] = value;
105} 108}
106 109
107static void translate_buffer_write_ptr(int cpu, void * x) 110static void translate_buffer_write_ptr(int cpu, void *x)
108{ 111{
109 per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x; 112 per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x;
110 per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask; 113 per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask;
111} 114}
112 115
113static void * translate_buffer_read_ptr(int cpu) 116static void *translate_buffer_read_ptr(int cpu)
114{ 117{
115 void * value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++]; 118 void *value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++];
116 per_cpu(translate_buffer_read, cpu) &= translate_buffer_mask; 119 per_cpu(translate_buffer_read, cpu) &= translate_buffer_mask;
117 return value; 120 return value;
118} 121}
@@ -120,9 +123,9 @@ static void * translate_buffer_read_ptr(int cpu)
120static void wq_cookie_handler(struct work_struct *unused) 123static void wq_cookie_handler(struct work_struct *unused)
121{ 124{
122 struct task_struct *task; 125 struct task_struct *task;
123 struct vm_area_struct *vma; 126 char *text;
124 int cpu = smp_processor_id(); 127 int cpu = smp_processor_id();
125 unsigned int cookie, commit; 128 unsigned int commit;
126 129
127 mutex_lock(&start_mutex); 130 mutex_lock(&start_mutex);
128 131
@@ -130,8 +133,8 @@ static void wq_cookie_handler(struct work_struct *unused)
130 commit = per_cpu(translate_buffer_write, cpu); 133 commit = per_cpu(translate_buffer_write, cpu);
131 while (per_cpu(translate_buffer_read, cpu) != commit) { 134 while (per_cpu(translate_buffer_read, cpu) != commit) {
132 task = (struct task_struct *)translate_buffer_read_ptr(cpu); 135 task = (struct task_struct *)translate_buffer_read_ptr(cpu);
133 vma = (struct vm_area_struct *)translate_buffer_read_ptr(cpu); 136 text = (char *)translate_buffer_read_ptr(cpu);
134 cookie = get_cookie(cpu, task, vma, NULL, false); 137 get_cookie(cpu, task, text, true);
135 } 138 }
136 } 139 }
137 140
@@ -145,7 +148,7 @@ static void app_process_wake_up_handler(unsigned long unused_data)
145} 148}
146 149
147// Retrieve full name from proc/pid/cmdline for java processes on Android 150// Retrieve full name from proc/pid/cmdline for java processes on Android
148static int translate_app_process(char** text, int cpu, struct task_struct * task, struct vm_area_struct *vma, bool in_interrupt) 151static int translate_app_process(const char **text, int cpu, struct task_struct *task, bool from_wq)
149{ 152{
150 void *maddr; 153 void *maddr;
151 unsigned int len; 154 unsigned int len;
@@ -154,12 +157,12 @@ static int translate_app_process(char** text, int cpu, struct task_struct * task
154 struct page *page = NULL; 157 struct page *page = NULL;
155 struct vm_area_struct *page_vma; 158 struct vm_area_struct *page_vma;
156 int bytes, offset, retval = 0, ptr; 159 int bytes, offset, retval = 0, ptr;
157 char * buf = per_cpu(translate_text, cpu); 160 char *buf = per_cpu(translate_text, cpu);
158 161
159 // Push work into a work queue if in atomic context as the kernel functions below might sleep 162 // Push work into a work queue if in atomic context as the kernel functions below might sleep
160 // Rely on the in_interrupt variable rather than in_irq() or in_interrupt() kernel functions, as the value of these functions seems 163 // Rely on the in_interrupt variable rather than in_irq() or in_interrupt() kernel functions, as the value of these functions seems
161 // inconsistent during a context switch between android/linux versions 164 // inconsistent during a context switch between android/linux versions
162 if (in_interrupt) { 165 if (!from_wq) {
163 // Check if already in buffer 166 // Check if already in buffer
164 ptr = per_cpu(translate_buffer_read, cpu); 167 ptr = per_cpu(translate_buffer_read, cpu);
165 while (ptr != per_cpu(translate_buffer_write, cpu)) { 168 while (ptr != per_cpu(translate_buffer_write, cpu)) {
@@ -169,7 +172,7 @@ static int translate_app_process(char** text, int cpu, struct task_struct * task
169 } 172 }
170 173
171 translate_buffer_write_ptr(cpu, (void *)task); 174 translate_buffer_write_ptr(cpu, (void *)task);
172 translate_buffer_write_ptr(cpu, (void *)vma); 175 translate_buffer_write_ptr(cpu, (void *)*text);
173 176
174 mod_timer(&app_process_wake_up_timer, jiffies + 1); 177 mod_timer(&app_process_wake_up_timer, jiffies + 1);
175 goto out; 178 goto out;
@@ -192,7 +195,7 @@ static int translate_app_process(char** text, int cpu, struct task_struct * task
192 goto outsem; 195 goto outsem;
193 196
194 maddr = kmap(page); 197 maddr = kmap(page);
195 offset = addr & (PAGE_SIZE-1); 198 offset = addr & (PAGE_SIZE - 1);
196 bytes = len; 199 bytes = len;
197 if (bytes > PAGE_SIZE - offset) 200 if (bytes > PAGE_SIZE - offset)
198 bytes = PAGE_SIZE - offset; 201 bytes = PAGE_SIZE - offset;
@@ -222,29 +225,10 @@ out:
222 return retval; 225 return retval;
223} 226}
224 227
225static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt) 228static inline uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq)
226{ 229{
227 unsigned long flags, cookie; 230 unsigned long flags, cookie;
228 struct path *path;
229 uint64_t key; 231 uint64_t key;
230 char *text;
231
232 if (mod) {
233 text = mod->name;
234 } else {
235 if (vma && vma->vm_file) {
236 path = &vma->vm_file->f_path;
237 } else if (task && task->mm && task->mm->exe_file) {
238 path = &task->mm->exe_file->f_path;
239 } else {
240 return INVALID_COOKIE;
241 }
242 if (!path || !path->dentry) {
243 return INVALID_COOKIE;
244 }
245
246 text = (char*)path->dentry->d_name.name;
247 }
248 232
249 key = gator_chksum_crc32(text); 233 key = gator_chksum_crc32(text);
250 key = (key << 32) | (uint32_t)task->tgid; 234 key = (key << 32) | (uint32_t)task->tgid;
@@ -254,8 +238,8 @@ static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_a
254 return cookie; 238 return cookie;
255 } 239 }
256 240
257 if (strcmp(text, "app_process") == 0 && !mod) { 241 if (strcmp(text, "app_process") == 0) {
258 if (!translate_app_process(&text, cpu, task, vma, in_interrupt)) 242 if (!translate_app_process(&text, cpu, task, from_wq))
259 return INVALID_COOKIE; 243 return INVALID_COOKIE;
260 } 244 }
261 245
@@ -276,16 +260,19 @@ static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_a
276 260
277static int get_exec_cookie(int cpu, struct task_struct *task) 261static int get_exec_cookie(int cpu, struct task_struct *task)
278{ 262{
279 unsigned long cookie = NO_COOKIE;
280 struct mm_struct *mm = task->mm; 263 struct mm_struct *mm = task->mm;
264 const char *text;
281 265
282 // kernel threads have no address space 266 // kernel threads have no address space
283 if (!mm) 267 if (!mm)
284 return cookie; 268 return NO_COOKIE;
285 269
286 cookie = get_cookie(cpu, task, NULL, NULL, true); 270 if (task && task->mm && task->mm->exe_file) {
271 text = task->mm->exe_file->f_path.dentry->d_name.name;
272 return get_cookie(cpu, task, text, false);
273 }
287 274
288 return cookie; 275 return INVALID_COOKIE;
289} 276}
290 277
291static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsigned long addr, off_t *offset) 278static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsigned long addr, off_t *offset)
@@ -293,6 +280,7 @@ static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsig
293 unsigned long cookie = NO_COOKIE; 280 unsigned long cookie = NO_COOKIE;
294 struct mm_struct *mm = task->mm; 281 struct mm_struct *mm = task->mm;
295 struct vm_area_struct *vma; 282 struct vm_area_struct *vma;
283 const char *text;
296 284
297 if (!mm) 285 if (!mm)
298 return cookie; 286 return cookie;
@@ -302,7 +290,8 @@ static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsig
302 continue; 290 continue;
303 291
304 if (vma->vm_file) { 292 if (vma->vm_file) {
305 cookie = get_cookie(cpu, task, vma, NULL, true); 293 text = vma->vm_file->f_path.dentry->d_name.name;
294 cookie = get_cookie(cpu, task, text, false);
306 *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; 295 *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start;
307 } else { 296 } else {
308 /* must be an anonymous map */ 297 /* must be an anonymous map */
@@ -323,14 +312,14 @@ static int cookies_initialize(void)
323 uint32_t crc, poly; 312 uint32_t crc, poly;
324 int i, j, cpu, size, err = 0; 313 int i, j, cpu, size, err = 0;
325 314
326 int translate_buffer_size = 512; // must be a power of 2 315 int translate_buffer_size = 512; // must be a power of 2
327 translate_buffer_mask = translate_buffer_size / sizeof(per_cpu(translate_buffer, 0)[0]) - 1; 316 translate_buffer_mask = translate_buffer_size / sizeof(per_cpu(translate_buffer, 0)[0]) - 1;
328 317
329 for_each_present_cpu(cpu) { 318 for_each_present_cpu(cpu) {
330 per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu; 319 per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu;
331 320
332 size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint64_t); 321 size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint64_t);
333 per_cpu(cookie_keys, cpu) = (uint64_t*)kmalloc(size, GFP_KERNEL); 322 per_cpu(cookie_keys, cpu) = (uint64_t *)kmalloc(size, GFP_KERNEL);
334 if (!per_cpu(cookie_keys, cpu)) { 323 if (!per_cpu(cookie_keys, cpu)) {
335 err = -ENOMEM; 324 err = -ENOMEM;
336 goto cookie_setup_error; 325 goto cookie_setup_error;
@@ -338,14 +327,14 @@ static int cookies_initialize(void)
338 memset(per_cpu(cookie_keys, cpu), 0, size); 327 memset(per_cpu(cookie_keys, cpu), 0, size);
339 328
340 size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint32_t); 329 size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint32_t);
341 per_cpu(cookie_values, cpu) = (uint32_t*)kmalloc(size, GFP_KERNEL); 330 per_cpu(cookie_values, cpu) = (uint32_t *)kmalloc(size, GFP_KERNEL);
342 if (!per_cpu(cookie_values, cpu)) { 331 if (!per_cpu(cookie_values, cpu)) {
343 err = -ENOMEM; 332 err = -ENOMEM;
344 goto cookie_setup_error; 333 goto cookie_setup_error;
345 } 334 }
346 memset(per_cpu(cookie_values, cpu), 0, size); 335 memset(per_cpu(cookie_values, cpu), 0, size);
347 336
348 per_cpu(translate_buffer, cpu) = (void * *)kmalloc(translate_buffer_size, GFP_KERNEL); 337 per_cpu(translate_buffer, cpu) = (void **)kmalloc(translate_buffer_size, GFP_KERNEL);
349 if (!per_cpu(translate_buffer, cpu)) { 338 if (!per_cpu(translate_buffer, cpu)) {
350 err = -ENOMEM; 339 err = -ENOMEM;
351 goto cookie_setup_error; 340 goto cookie_setup_error;
@@ -363,7 +352,7 @@ static int cookies_initialize(void)
363 352
364 // build CRC32 table 353 // build CRC32 table
365 poly = 0x04c11db7; 354 poly = 0x04c11db7;
366 gator_crc32_table = (uint32_t*)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL); 355 gator_crc32_table = (uint32_t *)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL);
367 for (i = 0; i < 256; i++) { 356 for (i = 0; i < 256; i++) {
368 crc = i; 357 crc = i;
369 for (j = 8; j > 0; j--) { 358 for (j = 8; j > 0; j--) {
diff --git a/driver/gator_events_armv6.c b/driver/gator_events_armv6.c
index 5f989ba..ee36dd0 100644
--- a/driver/gator_events_armv6.c
+++ b/driver/gator_events_armv6.c
@@ -93,7 +93,7 @@ int gator_events_armv6_create_files(struct super_block *sb, struct dentry *root)
93 return 0; 93 return 0;
94} 94}
95 95
96static int gator_events_armv6_online(int** buffer) 96static int gator_events_armv6_online(int **buffer)
97{ 97{
98 unsigned int cnt, len = 0, cpu = smp_processor_id(); 98 unsigned int cnt, len = 0, cpu = smp_processor_id();
99 u32 pmnc; 99 u32 pmnc;
@@ -104,7 +104,7 @@ static int gator_events_armv6_online(int** buffer)
104 104
105 /* initialize PMNC, reset overflow, D bit, C bit and P bit. */ 105 /* initialize PMNC, reset overflow, D bit, C bit and P bit. */
106 armv6_pmnc_write(PMCR_OFL_PMN0 | PMCR_OFL_PMN1 | PMCR_OFL_CCNT | 106 armv6_pmnc_write(PMCR_OFL_PMN0 | PMCR_OFL_PMN1 | PMCR_OFL_CCNT |
107 PMCR_C | PMCR_P); 107 PMCR_C | PMCR_P);
108 108
109 /* configure control register */ 109 /* configure control register */
110 for (pmnc = 0, cnt = PMN0; cnt <= CCNT; cnt++) { 110 for (pmnc = 0, cnt = PMN0; cnt <= CCNT; cnt++) {
@@ -141,7 +141,7 @@ static int gator_events_armv6_online(int** buffer)
141 return len; 141 return len;
142} 142}
143 143
144static int gator_events_armv6_offline(int** buffer) 144static int gator_events_armv6_offline(int **buffer)
145{ 145{
146 unsigned int cnt; 146 unsigned int cnt;
147 147
diff --git a/driver/gator_events_armv7.c b/driver/gator_events_armv7.c
index 590421d..212b17b 100644
--- a/driver/gator_events_armv7.c
+++ b/driver/gator_events_armv7.c
@@ -22,7 +22,7 @@
22#define PMNC_E (1 << 0) /* Enable all counters */ 22#define PMNC_E (1 << 0) /* Enable all counters */
23#define PMNC_P (1 << 1) /* Reset all counters */ 23#define PMNC_P (1 << 1) /* Reset all counters */
24#define PMNC_C (1 << 2) /* Cycle counter reset */ 24#define PMNC_C (1 << 2) /* Cycle counter reset */
25#define PMNC_MASK 0x3f /* Mask for writable bits */ 25#define PMNC_MASK 0x3f /* Mask for writable bits */
26 26
27// ccnt reg 27// ccnt reg
28#define CCNT_REG (1 << 31) 28#define CCNT_REG (1 << 31)
@@ -63,7 +63,7 @@ inline u32 armv7_ccnt_read(u32 reset_value)
63 local_irq_save(flags); 63 local_irq_save(flags);
64 asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); // disable 64 asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); // disable
65 asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); // read 65 asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); // read
66 asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (newval));// new value 66 asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (newval)); // new value
67 asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable 67 asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable
68 local_irq_restore(flags); 68 local_irq_restore(flags);
69 69
@@ -82,7 +82,7 @@ inline u32 armv7_cntn_read(unsigned int cnt, u32 reset_value)
82 asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); // disable 82 asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); // disable
83 asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (sel)); // select 83 asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (sel)); // select
84 asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (oldval)); // read 84 asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (oldval)); // read
85 asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (newval));// new value 85 asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (newval)); // new value
86 asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable 86 asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable
87 local_irq_restore(flags); 87 local_irq_restore(flags);
88 88
@@ -143,7 +143,7 @@ static int gator_events_armv7_create_files(struct super_block *sb, struct dentry
143 if (i == 0) { 143 if (i == 0) {
144 snprintf(buf, sizeof buf, "ARM_%s_ccnt", pmnc_name); 144 snprintf(buf, sizeof buf, "ARM_%s_ccnt", pmnc_name);
145 } else { 145 } else {
146 snprintf(buf, sizeof buf, "ARM_%s_cnt%d", pmnc_name, i-1); 146 snprintf(buf, sizeof buf, "ARM_%s_cnt%d", pmnc_name, i - 1);
147 } 147 }
148 dir = gatorfs_mkdir(sb, root, buf); 148 dir = gatorfs_mkdir(sb, root, buf);
149 if (!dir) { 149 if (!dir) {
@@ -159,7 +159,7 @@ static int gator_events_armv7_create_files(struct super_block *sb, struct dentry
159 return 0; 159 return 0;
160} 160}
161 161
162static int gator_events_armv7_online(int** buffer) 162static int gator_events_armv7_online(int **buffer)
163{ 163{
164 unsigned int cnt, len = 0, cpu = smp_processor_id(); 164 unsigned int cnt, len = 0, cpu = smp_processor_id();
165 165
@@ -214,11 +214,11 @@ static int gator_events_armv7_online(int** buffer)
214 return len; 214 return len;
215} 215}
216 216
217static int gator_events_armv7_offline(int** buffer) 217static int gator_events_armv7_offline(int **buffer)
218{ 218{
219 // disbale all counters, including PMCCNTR; overflow IRQs will not be signaled 219 // disable all counters, including PMCCNTR; overflow IRQs will not be signaled
220 armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E); 220 armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E);
221 221
222 return 0; 222 return 0;
223} 223}
224 224
@@ -298,7 +298,7 @@ int gator_events_armv7_init(void)
298 return -1; 298 return -1;
299 } 299 }
300 300
301 pmnc_counters++; // CNT[n] + CCNT 301 pmnc_counters++; // CNT[n] + CCNT
302 302
303 for (cnt = CCNT; cnt < CNTMAX; cnt++) { 303 for (cnt = CCNT; cnt < CNTMAX; cnt++) {
304 pmnc_enabled[cnt] = 0; 304 pmnc_enabled[cnt] = 0;
diff --git a/driver/gator_events_block.c b/driver/gator_events_block.c
index b18c3ca..f512b13 100644
--- a/driver/gator_events_block.c
+++ b/driver/gator_events_block.c
@@ -119,7 +119,7 @@ static int gator_events_block_read(int **buffer)
119 if (block_rq_wr_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_WR])) > 0) { 119 if (block_rq_wr_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_WR])) > 0) {
120 atomic_sub(value, &blockCnt[BLOCK_RQ_WR]); 120 atomic_sub(value, &blockCnt[BLOCK_RQ_WR]);
121 blockGet[len++] = block_rq_wr_key; 121 blockGet[len++] = block_rq_wr_key;
122 blockGet[len++] = 0; // indicates to Streamline that value bytes were written now, not since the last message 122 blockGet[len++] = 0; // indicates to Streamline that value bytes were written now, not since the last message
123 blockGet[len++] = block_rq_wr_key; 123 blockGet[len++] = block_rq_wr_key;
124 blockGet[len++] = value; 124 blockGet[len++] = value;
125 data += value; 125 data += value;
@@ -127,7 +127,7 @@ static int gator_events_block_read(int **buffer)
127 if (block_rq_rd_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_RD])) > 0) { 127 if (block_rq_rd_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_RD])) > 0) {
128 atomic_sub(value, &blockCnt[BLOCK_RQ_RD]); 128 atomic_sub(value, &blockCnt[BLOCK_RQ_RD]);
129 blockGet[len++] = block_rq_rd_key; 129 blockGet[len++] = block_rq_rd_key;
130 blockGet[len++] = 0; // indicates to Streamline that value bytes were read now, not since the last message 130 blockGet[len++] = 0; // indicates to Streamline that value bytes were read now, not since the last message
131 blockGet[len++] = block_rq_rd_key; 131 blockGet[len++] = block_rq_rd_key;
132 blockGet[len++] = value; 132 blockGet[len++] = value;
133 data += value; 133 data += value;
@@ -156,4 +156,5 @@ int gator_events_block_init(void)
156 156
157 return gator_events_install(&gator_events_block_interface); 157 return gator_events_install(&gator_events_block_interface);
158} 158}
159
159gator_events_init(gator_events_block_init); 160gator_events_init(gator_events_block_init);
diff --git a/driver/gator_events_irq.c b/driver/gator_events_irq.c
index 435bc86..1221372 100644
--- a/driver/gator_events_irq.c
+++ b/driver/gator_events_irq.c
@@ -21,8 +21,8 @@ static ulong softirq_key;
21static DEFINE_PER_CPU(int[TOTALIRQ], irqCnt); 21static DEFINE_PER_CPU(int[TOTALIRQ], irqCnt);
22static DEFINE_PER_CPU(int[TOTALIRQ * 2], irqGet); 22static DEFINE_PER_CPU(int[TOTALIRQ * 2], irqGet);
23 23
24GATOR_DEFINE_PROBE(irq_handler_exit, TP_PROTO(int irq, 24GATOR_DEFINE_PROBE(irq_handler_exit,
25 struct irqaction *action, int ret)) 25 TP_PROTO(int irq, struct irqaction *action, int ret))
26{ 26{
27 unsigned long flags; 27 unsigned long flags;
28 28
@@ -71,10 +71,10 @@ static int gator_events_irq_create_files(struct super_block *sb, struct dentry *
71 return 0; 71 return 0;
72} 72}
73 73
74static int gator_events_irq_online(int** buffer) 74static int gator_events_irq_online(int **buffer)
75{ 75{
76 int len = 0, cpu = smp_processor_id(); 76 int len = 0, cpu = smp_processor_id();
77 unsigned long flags; // not necessary as we are in interrupt context anyway, but doesn't hurt 77 unsigned long flags; // not necessary as we are in interrupt context anyway, but doesn't hurt
78 78
79 // synchronization with the irq_exit functions is not necessary as the values are being reset 79 // synchronization with the irq_exit functions is not necessary as the values are being reset
80 if (hardirq_enabled) { 80 if (hardirq_enabled) {
@@ -136,7 +136,7 @@ static void gator_events_irq_stop(void)
136 136
137static int gator_events_irq_read(int **buffer) 137static int gator_events_irq_read(int **buffer)
138{ 138{
139 unsigned long flags; // not necessary as we are in interrupt context anyway, but doesn't hurt 139 unsigned long flags; // not necessary as we are in interrupt context anyway, but doesn't hurt
140 int len, value; 140 int len, value;
141 int cpu = smp_processor_id(); 141 int cpu = smp_processor_id();
142 142
@@ -185,4 +185,5 @@ int gator_events_irq_init(void)
185 185
186 return gator_events_install(&gator_events_irq_interface); 186 return gator_events_install(&gator_events_irq_interface);
187} 187}
188
188gator_events_init(gator_events_irq_init); 189gator_events_init(gator_events_irq_init);
diff --git a/driver/gator_events_l2c-310.c b/driver/gator_events_l2c-310.c
index bd1c48a..197af04 100644
--- a/driver/gator_events_l2c-310.c
+++ b/driver/gator_events_l2c-310.c
@@ -26,8 +26,6 @@ static int l2c310_buffer[L2C310_COUNTERS_NUM * 2];
26 26
27static void __iomem *l2c310_base; 27static void __iomem *l2c310_base;
28 28
29
30
31static void gator_events_l2c310_reset_counters(void) 29static void gator_events_l2c310_reset_counters(void)
32{ 30{
33 u32 val = readl(l2c310_base + L2X0_EVENT_CNT_CTRL); 31 u32 val = readl(l2c310_base + L2X0_EVENT_CNT_CTRL);
@@ -37,9 +35,8 @@ static void gator_events_l2c310_reset_counters(void)
37 writel(val, l2c310_base + L2X0_EVENT_CNT_CTRL); 35 writel(val, l2c310_base + L2X0_EVENT_CNT_CTRL);
38} 36}
39 37
40
41static int gator_events_l2c310_create_files(struct super_block *sb, 38static int gator_events_l2c310_create_files(struct super_block *sb,
42 struct dentry *root) 39 struct dentry *root)
43{ 40{
44 int i; 41 int i;
45 42
@@ -52,11 +49,11 @@ static int gator_events_l2c310_create_files(struct super_block *sb,
52 if (WARN_ON(!dir)) 49 if (WARN_ON(!dir))
53 return -1; 50 return -1;
54 gatorfs_create_ulong(sb, dir, "enabled", 51 gatorfs_create_ulong(sb, dir, "enabled",
55 &l2c310_counters[i].enabled); 52 &l2c310_counters[i].enabled);
56 gatorfs_create_ulong(sb, dir, "event", 53 gatorfs_create_ulong(sb, dir, "event",
57 &l2c310_counters[i].event); 54 &l2c310_counters[i].event);
58 gatorfs_create_ro_ulong(sb, dir, "key", 55 gatorfs_create_ro_ulong(sb, dir, "key",
59 &l2c310_counters[i].key); 56 &l2c310_counters[i].key);
60 } 57 }
61 58
62 return 0; 59 return 0;
@@ -73,7 +70,7 @@ static int gator_events_l2c310_start(void)
73 /* Counter event sources */ 70 /* Counter event sources */
74 for (i = 0; i < L2C310_COUNTERS_NUM; i++) 71 for (i = 0; i < L2C310_COUNTERS_NUM; i++)
75 writel((l2c310_counters[i].event & 0xf) << 2, 72 writel((l2c310_counters[i].event & 0xf) << 2,
76 l2c310_base + l2x0_event_cntx_cfg[i]); 73 l2c310_base + l2x0_event_cntx_cfg[i]);
77 74
78 gator_events_l2c310_reset_counters(); 75 gator_events_l2c310_reset_counters();
79 76
@@ -105,10 +102,10 @@ static int gator_events_l2c310_read(int **buffer)
105 if (l2c310_counters[i].enabled) { 102 if (l2c310_counters[i].enabled) {
106 l2c310_buffer[len++] = l2c310_counters[i].key; 103 l2c310_buffer[len++] = l2c310_counters[i].key;
107 l2c310_buffer[len++] = readl(l2c310_base + 104 l2c310_buffer[len++] = readl(l2c310_base +
108 l2x0_event_cntx_val[i]); 105 l2x0_event_cntx_val[i]);
109 } 106 }
110 } 107 }
111 108
112 /* l2c310 counters are saturating, not wrapping in case of overflow */ 109 /* l2c310 counters are saturating, not wrapping in case of overflow */
113 gator_events_l2c310_reset_counters(); 110 gator_events_l2c310_reset_counters();
114 111
@@ -176,4 +173,5 @@ int gator_events_l2c310_init(void)
176 173
177 return gator_events_install(&gator_events_l2c310_interface); 174 return gator_events_install(&gator_events_l2c310_interface);
178} 175}
176
179gator_events_init(gator_events_l2c310_init); 177gator_events_init(gator_events_l2c310_init);
diff --git a/driver/gator_events_mali_400.c b/driver/gator_events_mali_400.c
index a44cd8e..4888b54 100644
--- a/driver/gator_events_mali_400.c
+++ b/driver/gator_events_mali_400.c
@@ -60,81 +60,81 @@
60#define NUM_FP_UNITS (4) 60#define NUM_FP_UNITS (4)
61 61
62enum counters { 62enum counters {
63 /* Timeline activity */ 63 /* Timeline activity */
64 ACTIVITY_VP = 0, 64 ACTIVITY_VP = 0,
65 ACTIVITY_FP0, 65 ACTIVITY_FP0,
66 ACTIVITY_FP1, 66 ACTIVITY_FP1,
67 ACTIVITY_FP2, 67 ACTIVITY_FP2,
68 ACTIVITY_FP3, 68 ACTIVITY_FP3,
69 69
70 /* L2 cache counters */ 70 /* L2 cache counters */
71 COUNTER_L2_C0, 71 COUNTER_L2_C0,
72 COUNTER_L2_C1, 72 COUNTER_L2_C1,
73 73
74 /* Vertex processor counters */ 74 /* Vertex processor counters */
75 COUNTER_VP_C0, 75 COUNTER_VP_C0,
76 COUNTER_VP_C1, 76 COUNTER_VP_C1,
77 77
78 /* Fragment processor counters */ 78 /* Fragment processor counters */
79 COUNTER_FP0_C0, 79 COUNTER_FP0_C0,
80 COUNTER_FP0_C1, 80 COUNTER_FP0_C1,
81 COUNTER_FP1_C0, 81 COUNTER_FP1_C0,
82 COUNTER_FP1_C1, 82 COUNTER_FP1_C1,
83 COUNTER_FP2_C0, 83 COUNTER_FP2_C0,
84 COUNTER_FP2_C1, 84 COUNTER_FP2_C1,
85 COUNTER_FP3_C0, 85 COUNTER_FP3_C0,
86 COUNTER_FP3_C1, 86 COUNTER_FP3_C1,
87 87
88 /* EGL Software Counters */ 88 /* EGL Software Counters */
89 COUNTER_EGL_BLIT_TIME, 89 COUNTER_EGL_BLIT_TIME,
90 90
91 /* GLES Software Counters */ 91 /* GLES Software Counters */
92 COUNTER_GLES_DRAW_ELEMENTS_CALLS, 92 COUNTER_GLES_DRAW_ELEMENTS_CALLS,
93 COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, 93 COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES,
94 COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, 94 COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED,
95 COUNTER_GLES_DRAW_ARRAYS_CALLS, 95 COUNTER_GLES_DRAW_ARRAYS_CALLS,
96 COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, 96 COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED,
97 COUNTER_GLES_DRAW_POINTS, 97 COUNTER_GLES_DRAW_POINTS,
98 COUNTER_GLES_DRAW_LINES, 98 COUNTER_GLES_DRAW_LINES,
99 COUNTER_GLES_DRAW_LINE_LOOP, 99 COUNTER_GLES_DRAW_LINE_LOOP,
100 COUNTER_GLES_DRAW_LINE_STRIP, 100 COUNTER_GLES_DRAW_LINE_STRIP,
101 COUNTER_GLES_DRAW_TRIANGLES, 101 COUNTER_GLES_DRAW_TRIANGLES,
102 COUNTER_GLES_DRAW_TRIANGLE_STRIP, 102 COUNTER_GLES_DRAW_TRIANGLE_STRIP,
103 COUNTER_GLES_DRAW_TRIANGLE_FAN, 103 COUNTER_GLES_DRAW_TRIANGLE_FAN,
104 COUNTER_GLES_NON_VBO_DATA_COPY_TIME, 104 COUNTER_GLES_NON_VBO_DATA_COPY_TIME,
105 COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, 105 COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI,
106 COUNTER_GLES_UPLOAD_TEXTURE_TIME, 106 COUNTER_GLES_UPLOAD_TEXTURE_TIME,
107 COUNTER_GLES_UPLOAD_VBO_TIME, 107 COUNTER_GLES_UPLOAD_VBO_TIME,
108 COUNTER_GLES_NUM_FLUSHES, 108 COUNTER_GLES_NUM_FLUSHES,
109 COUNTER_GLES_NUM_VSHADERS_GENERATED, 109 COUNTER_GLES_NUM_VSHADERS_GENERATED,
110 COUNTER_GLES_NUM_FSHADERS_GENERATED, 110 COUNTER_GLES_NUM_FSHADERS_GENERATED,
111 COUNTER_GLES_VSHADER_GEN_TIME, 111 COUNTER_GLES_VSHADER_GEN_TIME,
112 COUNTER_GLES_FSHADER_GEN_TIME, 112 COUNTER_GLES_FSHADER_GEN_TIME,
113 COUNTER_GLES_INPUT_TRIANGLES, 113 COUNTER_GLES_INPUT_TRIANGLES,
114 COUNTER_GLES_VXCACHE_HIT, 114 COUNTER_GLES_VXCACHE_HIT,
115 COUNTER_GLES_VXCACHE_MISS, 115 COUNTER_GLES_VXCACHE_MISS,
116 COUNTER_GLES_VXCACHE_COLLISION, 116 COUNTER_GLES_VXCACHE_COLLISION,
117 COUNTER_GLES_CULLED_TRIANGLES, 117 COUNTER_GLES_CULLED_TRIANGLES,
118 COUNTER_GLES_CULLED_LINES, 118 COUNTER_GLES_CULLED_LINES,
119 COUNTER_GLES_BACKFACE_TRIANGLES, 119 COUNTER_GLES_BACKFACE_TRIANGLES,
120 COUNTER_GLES_GBCLIP_TRIANGLES, 120 COUNTER_GLES_GBCLIP_TRIANGLES,
121 COUNTER_GLES_GBCLIP_LINES, 121 COUNTER_GLES_GBCLIP_LINES,
122 COUNTER_GLES_TRIANGLES_DRAWN, 122 COUNTER_GLES_TRIANGLES_DRAWN,
123 COUNTER_GLES_DRAWCALL_TIME, 123 COUNTER_GLES_DRAWCALL_TIME,
124 COUNTER_GLES_TRIANGLES_COUNT, 124 COUNTER_GLES_TRIANGLES_COUNT,
125 COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, 125 COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT,
126 COUNTER_GLES_STRIP_TRIANGLES_COUNT, 126 COUNTER_GLES_STRIP_TRIANGLES_COUNT,
127 COUNTER_GLES_FAN_TRIANGLES_COUNT, 127 COUNTER_GLES_FAN_TRIANGLES_COUNT,
128 COUNTER_GLES_LINES_COUNT, 128 COUNTER_GLES_LINES_COUNT,
129 COUNTER_GLES_INDEPENDENT_LINES_COUNT, 129 COUNTER_GLES_INDEPENDENT_LINES_COUNT,
130 COUNTER_GLES_STRIP_LINES_COUNT, 130 COUNTER_GLES_STRIP_LINES_COUNT,
131 COUNTER_GLES_LOOP_LINES_COUNT, 131 COUNTER_GLES_LOOP_LINES_COUNT,
132 132
133 COUNTER_FILMSTRIP, 133 COUNTER_FILMSTRIP,
134 COUNTER_FREQUENCY, 134 COUNTER_FREQUENCY,
135 COUNTER_VOLTAGE, 135 COUNTER_VOLTAGE,
136 136
137 NUMBER_OF_EVENTS 137 NUMBER_OF_EVENTS
138}; 138};
139 139
140#define FIRST_ACTIVITY_EVENT ACTIVITY_VP 140#define FIRST_ACTIVITY_EVENT ACTIVITY_VP
@@ -161,7 +161,7 @@ static unsigned long counter_key[NUMBER_OF_EVENTS];
161/* The data we have recorded */ 161/* The data we have recorded */
162static u32 counter_data[NUMBER_OF_EVENTS]; 162static u32 counter_data[NUMBER_OF_EVENTS];
163/* The address to sample (or 0 if samples are sent to us) */ 163/* The address to sample (or 0 if samples are sent to us) */
164static u32* counter_address[NUMBER_OF_EVENTS]; 164static u32 *counter_address[NUMBER_OF_EVENTS];
165 165
166/* An array used to return the data we recorded 166/* An array used to return the data we recorded
167 * as key,value pairs hence the *2 167 * as key,value pairs hence the *2
@@ -177,13 +177,12 @@ static int trace_registered;
177 */ 177 */
178static u32 get_difference(u32 start, u32 end) 178static u32 get_difference(u32 start, u32 end)
179{ 179{
180 if (start - end >= 0) 180 if (start - end >= 0) {
181 { 181 return start - end;
182 return start - end; 182 }
183 }
184 183
185 // Mali counters are unsigned 32 bit values that wrap. 184 // Mali counters are unsigned 32 bit values that wrap.
186 return (4294967295u - end) + start; 185 return (4294967295u - end) + start;
187} 186}
188 187
189/** 188/**
@@ -191,8 +190,8 @@ static u32 get_difference(u32 start, u32 end)
191 */ 190 */
192static inline int is_activity_counter(unsigned int event_id) 191static inline int is_activity_counter(unsigned int event_id)
193{ 192{
194 return (event_id >= FIRST_ACTIVITY_EVENT && 193 return (event_id >= FIRST_ACTIVITY_EVENT &&
195 event_id <= LAST_ACTIVITY_EVENT); 194 event_id <= LAST_ACTIVITY_EVENT);
196} 195}
197 196
198/** 197/**
@@ -200,7 +199,7 @@ static inline int is_activity_counter(unsigned int event_id)
200 */ 199 */
201static inline int is_hw_counter(unsigned int event_id) 200static inline int is_hw_counter(unsigned int event_id)
202{ 201{
203 return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER); 202 return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER);
204} 203}
205 204
206#if GATOR_MALI_INTERFACE_STYLE == 2 205#if GATOR_MALI_INTERFACE_STYLE == 2
@@ -209,7 +208,7 @@ static inline int is_hw_counter(unsigned int event_id)
209 */ 208 */
210static inline int is_sw_counter(unsigned int event_id) 209static inline int is_sw_counter(unsigned int event_id)
211{ 210{
212 return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER); 211 return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER);
213} 212}
214#endif 213#endif
215 214
@@ -217,209 +216,204 @@ static inline int is_sw_counter(unsigned int event_id)
217/* 216/*
218 * The Mali DDK uses s64 types to contain software counter values, but gator 217 * The Mali DDK uses s64 types to contain software counter values, but gator
219 * can only use a maximum of 32 bits. This function scales a software counter 218 * can only use a maximum of 32 bits. This function scales a software counter
220 * to an appopriate range. 219 * to an appropriate range.
221 */ 220 */
222static u32 scale_sw_counter_value(unsigned int event_id, signed long long value) 221static u32 scale_sw_counter_value(unsigned int event_id, signed long long value)
223{ 222{
224 u32 scaled_value; 223 u32 scaled_value;
225 224
226 switch (event_id) { 225 switch (event_id) {
227 case COUNTER_GLES_UPLOAD_TEXTURE_TIME: 226 case COUNTER_GLES_UPLOAD_TEXTURE_TIME:
228 case COUNTER_GLES_UPLOAD_VBO_TIME: 227 case COUNTER_GLES_UPLOAD_VBO_TIME:
229 scaled_value = (u32)div_s64(value, 1000000); 228 scaled_value = (u32)div_s64(value, 1000000);
230 break; 229 break;
231 default: 230 default:
232 scaled_value = (u32)value; 231 scaled_value = (u32)value;
233 break; 232 break;
234 } 233 }
235 234
236 return scaled_value; 235 return scaled_value;
237} 236}
238#endif 237#endif
239 238
240/* Probe for continuously sampled counter */ 239/* Probe for continuously sampled counter */
241#if 0 //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING 240#if 0 //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING
242GATOR_DEFINE_PROBE(mali_sample_address, TP_PROTO(unsigned int event_id, u32* addr)) 241GATOR_DEFINE_PROBE(mali_sample_address, TP_PROTO(unsigned int event_id, u32 *addr))
243{ 242{
244 /* Turning on too many pr_debug statements in frequently called functions 243 /* Turning on too many pr_debug statements in frequently called functions
245 * can cause stability and/or performance problems 244 * can cause stability and/or performance problems
246 */ 245 */
247 //pr_debug("gator: mali_sample_address %d %d\n", event_id, addr); 246 //pr_debug("gator: mali_sample_address %d %d\n", event_id, addr);
248 if (event_id >= ACTIVITY_VP && event_id <= COUNTER_FP3_C1) { 247 if (event_id >= ACTIVITY_VP && event_id <= COUNTER_FP3_C1) {
249 counter_address[event_id] = addr; 248 counter_address[event_id] = addr;
250 } 249 }
251} 250}
252#endif 251#endif
253 252
254/* Probe for hardware counter events */ 253/* Probe for hardware counter events */
255GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int value)) 254GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int value))
256{ 255{
257 /* Turning on too many pr_debug statements in frequently called functions 256 /* Turning on too many pr_debug statements in frequently called functions
258 * can cause stability and/or performance problems 257 * can cause stability and/or performance problems
259 */ 258 */
260 //pr_debug("gator: mali_hw_counter %d %d\n", event_id, value); 259 //pr_debug("gator: mali_hw_counter %d %d\n", event_id, value);
261 if (is_hw_counter(event_id)) { 260 if (is_hw_counter(event_id)) {
262 counter_data[event_id] = value; 261 counter_data[event_id] = value;
263 } 262 }
264} 263}
265 264
266#if GATOR_MALI_INTERFACE_STYLE == 2 265#if GATOR_MALI_INTERFACE_STYLE == 2
267GATOR_DEFINE_PROBE(mali_sw_counter, TP_PROTO(unsigned int event_id, signed long long value)) 266GATOR_DEFINE_PROBE(mali_sw_counter, TP_PROTO(unsigned int event_id, signed long long value))
268{ 267{
269 if (is_sw_counter(event_id)) { 268 if (is_sw_counter(event_id)) {
270 counter_data[event_id] = scale_sw_counter_value(event_id, value); 269 counter_data[event_id] = scale_sw_counter_value(event_id, value);
271 } 270 }
272} 271}
273#endif /* GATOR_MALI_INTERFACE_STYLE == 2 */ 272#endif /* GATOR_MALI_INTERFACE_STYLE == 2 */
274 273
275
276#if GATOR_MALI_INTERFACE_STYLE == 3 274#if GATOR_MALI_INTERFACE_STYLE == 3
277GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void * surface_id, unsigned int * counters)) 275GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surface_id, unsigned int *counters))
278{ 276{
279 u32 i; 277 u32 i;
280 278
281 /* Copy over the values for those counters which are enabled. */ 279 /* Copy over the values for those counters which are enabled. */
282 for(i=FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) 280 for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) {
283 { 281 if (counter_enabled[i]) {
284 if(counter_enabled[i]) 282 counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]);
285 { 283 }
286 counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]); 284 }
287 }
288 }
289} 285}
290#endif /* GATOR_MALI_INTERFACE_STYLE == 3 */ 286#endif /* GATOR_MALI_INTERFACE_STYLE == 3 */
291 287
292static int create_files(struct super_block *sb, struct dentry *root) { 288static int create_files(struct super_block *sb, struct dentry *root)
293 struct dentry *dir; 289{
294 int event; 290 struct dentry *dir;
295 int n_fp = NUM_FP_UNITS; 291 int event;
296 292 int n_fp = NUM_FP_UNITS;
297 const char* mali_name = gator_mali_get_mali_name(); 293
298 294 const char *mali_name = gator_mali_get_mali_name();
299 /* 295
300 * Create the filesystem entries for vertex processor, fragement processor 296 /*
301 * and L2 cache timeline and hardware counters. Software counters get 297 * Create the filesystem entries for vertex processor, fragment processor
302 * special handling after this block. 298 * and L2 cache timeline and hardware counters. Software counters get
303 */ 299 * special handling after this block.
304 for (event = FIRST_ACTIVITY_EVENT; event <= LAST_HW_COUNTER; event++) 300 */
305 { 301 for (event = FIRST_ACTIVITY_EVENT; event <= LAST_HW_COUNTER; event++) {
306 char buf[40]; 302 char buf[40];
307 303
308 /* 304 /*
309 * We can skip this event if it's for a non-existent fragment 305 * We can skip this event if it's for a non-existent fragment
310 * processor. 306 * processor.
311 */ 307 */
312 if (((event - ACTIVITY_FP0 >= n_fp) && (event < COUNTER_L2_C0)) || 308 if (((event - ACTIVITY_FP0 >= n_fp) && (event < COUNTER_L2_C0))
313 (((event - COUNTER_FP0_C0)/2 >= n_fp))) 309 || (((event - COUNTER_FP0_C0) / 2 >= n_fp))) {
314 { 310 continue;
315 continue; 311 }
316 } 312
317 313 /* Otherwise, set up the filesystem entry for this event. */
318 /* Otherwise, set up the filesystem entry for this event. */ 314 switch (event) {
319 switch (event) { 315 case ACTIVITY_VP:
320 case ACTIVITY_VP: 316 snprintf(buf, sizeof buf, "ARM_%s_VP_active", mali_name);
321 snprintf(buf, sizeof buf, "ARM_%s_VP_active", mali_name); 317 break;
322 break; 318 case ACTIVITY_FP0:
323 case ACTIVITY_FP0: 319 case ACTIVITY_FP1:
324 case ACTIVITY_FP1: 320 case ACTIVITY_FP2:
325 case ACTIVITY_FP2: 321 case ACTIVITY_FP3:
326 case ACTIVITY_FP3: 322 snprintf(buf, sizeof buf, "ARM_%s_FP%d_active",
327 snprintf(buf, sizeof buf, "ARM_%s_FP%d_active", 323 mali_name, event - ACTIVITY_FP0);
328 mali_name, event - ACTIVITY_FP0); 324 break;
329 break; 325 case COUNTER_L2_C0:
330 case COUNTER_L2_C0: 326 case COUNTER_L2_C1:
331 case COUNTER_L2_C1: 327 snprintf(buf, sizeof buf, "ARM_%s_L2_cnt%d",
332 snprintf(buf, sizeof buf, "ARM_%s_L2_cnt%d", 328 mali_name, event - COUNTER_L2_C0);
333 mali_name, event - COUNTER_L2_C0); 329 break;
334 break; 330 case COUNTER_VP_C0:
335 case COUNTER_VP_C0: 331 case COUNTER_VP_C1:
336 case COUNTER_VP_C1: 332 snprintf(buf, sizeof buf, "ARM_%s_VP_cnt%d",
337 snprintf(buf, sizeof buf, "ARM_%s_VP_cnt%d", 333 mali_name, event - COUNTER_VP_C0);
338 mali_name, event - COUNTER_VP_C0); 334 break;
339 break; 335 case COUNTER_FP0_C0:
340 case COUNTER_FP0_C0: 336 case COUNTER_FP0_C1:
341 case COUNTER_FP0_C1: 337 case COUNTER_FP1_C0:
342 case COUNTER_FP1_C0: 338 case COUNTER_FP1_C1:
343 case COUNTER_FP1_C1: 339 case COUNTER_FP2_C0:
344 case COUNTER_FP2_C0: 340 case COUNTER_FP2_C1:
345 case COUNTER_FP2_C1: 341 case COUNTER_FP3_C0:
346 case COUNTER_FP3_C0: 342 case COUNTER_FP3_C1:
347 case COUNTER_FP3_C1: 343 snprintf(buf, sizeof buf, "ARM_%s_FP%d_cnt%d",
348 snprintf(buf, sizeof buf, "ARM_%s_FP%d_cnt%d", mali_name, 344 mali_name, (event - COUNTER_FP0_C0) / 2,
349 (event - COUNTER_FP0_C0) / 2, (event - COUNTER_FP0_C0) % 2); 345 (event - COUNTER_FP0_C0) % 2);
350 break; 346 break;
351 default: 347 default:
352 printk("gator: trying to create file for non-existent counter (%d)\n", event); 348 printk("gator: trying to create file for non-existent counter (%d)\n", event);
353 continue; 349 continue;
354 } 350 }
355 351
356 dir = gatorfs_mkdir(sb, root, buf); 352 dir = gatorfs_mkdir(sb, root, buf);
357 353
358 if (!dir) { 354 if (!dir) {
359 return -1; 355 return -1;
360 } 356 }
361 357
362 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]); 358 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
363 359
364 /* Only create an event node for counters that can change what they count */ 360 /* Only create an event node for counters that can change what they count */
365 if (event >= COUNTER_L2_C0) { 361 if (event >= COUNTER_L2_C0) {
366 gatorfs_create_ulong(sb, dir, "event", &counter_event[event]); 362 gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
367 } 363 }
368 364
369 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]); 365 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
370 } 366 }
371 367
372 /* Now set up the software counter entries */ 368 /* Now set up the software counter entries */
373 for (event = FIRST_SW_COUNTER; event <= LAST_SW_COUNTER; event++) 369 for (event = FIRST_SW_COUNTER; event <= LAST_SW_COUNTER; event++) {
374 { 370 char buf[40];
375 char buf[40]; 371
376 372 snprintf(buf, sizeof(buf), "ARM_%s_SW_%d", mali_name, event);
377 snprintf(buf, sizeof(buf), "ARM_%s_SW_%d", mali_name, event); 373
378 374 dir = gatorfs_mkdir(sb, root, buf);
379 dir = gatorfs_mkdir(sb, root, buf); 375
380 376 if (!dir) {
381 if (!dir) { 377 return -1;
382 return -1; 378 }
383 } 379
384 380 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
385 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]); 381 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
386 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]); 382 }
387 } 383
388 384 /* Now set up the special counter entries */
389 /* Now set up the special counter entries */ 385 for (event = FIRST_SPECIAL_COUNTER; event <= LAST_SPECIAL_COUNTER; event++) {
390 for (event = FIRST_SPECIAL_COUNTER; event <= LAST_SPECIAL_COUNTER; event++) 386 char buf[40];
391 { 387
392 char buf[40]; 388 switch (event) {
393 389 case COUNTER_FILMSTRIP:
394 switch(event) { 390 snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip_cnt0", mali_name);
395 case COUNTER_FILMSTRIP: 391 break;
396 snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip_cnt0", mali_name); 392
397 break; 393 case COUNTER_FREQUENCY:
398 394 snprintf(buf, sizeof(buf), "ARM_%s_Frequency", mali_name);
399 case COUNTER_FREQUENCY: 395 break;
400 snprintf(buf, sizeof(buf), "ARM_%s_Frequency", mali_name); 396
401 break; 397 case COUNTER_VOLTAGE:
402 398 snprintf(buf, sizeof(buf), "ARM_%s_Voltage", mali_name);
403 case COUNTER_VOLTAGE: 399 break;
404 snprintf(buf, sizeof(buf), "ARM_%s_Voltage", mali_name); 400
405 break; 401 default:
406 402 break;
407 default: 403 }
408 break; 404
409 } 405 dir = gatorfs_mkdir(sb, root, buf);
410 406
411 dir = gatorfs_mkdir(sb, root, buf); 407 if (!dir) {
412 408 return -1;
413 if (!dir) { 409 }
414 return -1; 410
415 } 411 gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
416 412 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
417 gatorfs_create_ulong(sb, dir, "event", &counter_event[event]); 413 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
418 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]); 414 }
419 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]); 415
420 } 416 return 0;
421
422 return 0;
423} 417}
424 418
425/* 419/*
@@ -434,312 +428,311 @@ static mali_profiling_get_counters_type *mali_get_counters = NULL;
434 */ 428 */
435static int is_any_sw_counter_enabled(void) 429static int is_any_sw_counter_enabled(void)
436{ 430{
437 unsigned int i; 431 unsigned int i;
438 432
439 for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) 433 for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) {
440 { 434 if (counter_enabled[i]) {
441 if (counter_enabled[i]) 435 return 1; /* At least one counter is enabled */
442 { 436 }
443 return 1; /* At least one counter is enabled */ 437 }
444 }
445 }
446 438
447 return 0; /* No s/w counters enabled */ 439 return 0; /* No s/w counters enabled */
448} 440}
449 441
450static void mali_counter_initialize(void) 442static void mali_counter_initialize(void)
451{ 443{
452 /* If a Mali driver is present and exporting the appropriate symbol 444 /* If a Mali driver is present and exporting the appropriate symbol
453 * then we can request the HW counters (of which there are only 2) 445 * then we can request the HW counters (of which there are only 2)
454 * be configured to count the desired events 446 * be configured to count the desired events
455 */ 447 */
456 mali_profiling_set_event_type *mali_set_hw_event; 448 mali_profiling_set_event_type *mali_set_hw_event;
457 mali_osk_fb_control_set_type *mali_set_fb_event; 449 mali_osk_fb_control_set_type *mali_set_fb_event;
458 mali_profiling_control_type *mali_control; 450 mali_profiling_control_type *mali_control;
459 451
460 mali_set_hw_event = symbol_get(_mali_profiling_set_event); 452 mali_set_hw_event = symbol_get(_mali_profiling_set_event);
461 453
462 if (mali_set_hw_event) { 454 if (mali_set_hw_event) {
463 int i; 455 int i;
464 456
465 pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n",mali_set_hw_event); 457 pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n", mali_set_hw_event);
466 458
467 for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) { 459 for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
468 if (counter_enabled[i]) { 460 if (counter_enabled[i]) {
469 mali_set_hw_event(i, counter_event[i]); 461 mali_set_hw_event(i, counter_event[i]);
470 } else { 462 } else {
471 mali_set_hw_event(i, 0xFFFFFFFF); 463 mali_set_hw_event(i, 0xFFFFFFFF);
472 } 464 }
473 } 465 }
474 466
475 symbol_put(_mali_profiling_set_event); 467 symbol_put(_mali_profiling_set_event);
476 } else { 468 } else {
477 printk("gator: mali online _mali_profiling_set_event symbol not found\n"); 469 printk("gator: mali online _mali_profiling_set_event symbol not found\n");
478 } 470 }
479 471
480 mali_set_fb_event = symbol_get(_mali_osk_fb_control_set); 472 mali_set_fb_event = symbol_get(_mali_osk_fb_control_set);
481 473
482 if (mali_set_fb_event) { 474 if (mali_set_fb_event) {
483 pr_debug("gator: mali online _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event); 475 pr_debug("gator: mali online _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
484 476
485 mali_set_fb_event(0,(counter_enabled[COUNTER_FILMSTRIP]?1:0)); 477 mali_set_fb_event(0, (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0));
486 478
487 symbol_put(_mali_osk_fb_control_set); 479 symbol_put(_mali_osk_fb_control_set);
488 } else { 480 } else {
489 printk("gator: mali online _mali_osk_fb_control_set symbol not found\n"); 481 printk("gator: mali online _mali_osk_fb_control_set symbol not found\n");
490 } 482 }
491 483
492 /* Generic control interface for Mali DDK. */ 484 /* Generic control interface for Mali DDK. */
493 mali_control = symbol_get(_mali_profiling_control); 485 mali_control = symbol_get(_mali_profiling_control);
494 if (mali_control) { 486 if (mali_control) {
495 /* The event attribute in the XML file keeps the actual frame rate. */ 487 /* The event attribute in the XML file keeps the actual frame rate. */
496 unsigned int rate = counter_event[COUNTER_FILMSTRIP] & 0xff; 488 unsigned int rate = counter_event[COUNTER_FILMSTRIP] & 0xff;
497 unsigned int resize_factor = (counter_event[COUNTER_FILMSTRIP] >> 8) & 0xff; 489 unsigned int resize_factor = (counter_event[COUNTER_FILMSTRIP] >> 8) & 0xff;
498 490
499 pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control); 491 pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control);
500 492
501 mali_control(SW_EVENTS_ENABLE, (is_any_sw_counter_enabled()?1:0)); 493 mali_control(SW_EVENTS_ENABLE, (is_any_sw_counter_enabled() ? 1 : 0));
502 mali_control(FBDUMP_CONTROL_ENABLE, (counter_enabled[COUNTER_FILMSTRIP]?1:0)); 494 mali_control(FBDUMP_CONTROL_ENABLE, (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0));
503 mali_control(FBDUMP_CONTROL_RATE, rate); 495 mali_control(FBDUMP_CONTROL_RATE, rate);
504 mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor); 496 mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor);
505 497
506 pr_debug("gator: sent mali_control enabled=%d, rate=%d\n", (counter_enabled[COUNTER_FILMSTRIP]?1:0), rate); 498 pr_debug("gator: sent mali_control enabled=%d, rate=%d\n", (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0), rate);
507 499
508 symbol_put(_mali_profiling_control); 500 symbol_put(_mali_profiling_control);
509 } else { 501 } else {
510 printk("gator: mali online _mali_profiling_control symbol not found\n"); 502 printk("gator: mali online _mali_profiling_control symbol not found\n");
511 } 503 }
512 504
513 mali_get_counters = symbol_get(_mali_profiling_get_counters); 505 mali_get_counters = symbol_get(_mali_profiling_get_counters);
514 if (mali_get_counters){ 506 if (mali_get_counters) {
515 pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", mali_get_counters); 507 pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", mali_get_counters);
516 counter_prev[COUNTER_L2_C0] = 0; 508 counter_prev[COUNTER_L2_C0] = 0;
517 counter_prev[COUNTER_L2_C1] = 0; 509 counter_prev[COUNTER_L2_C1] = 0;
518 } 510 } else {
519 else{ 511 pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined");
520 pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined"); 512 }
521 }
522} 513}
523 514
524static void mali_counter_deinitialize(void) 515static void mali_counter_deinitialize(void)
525{ 516{
526 mali_profiling_set_event_type *mali_set_hw_event; 517 mali_profiling_set_event_type *mali_set_hw_event;
527 mali_osk_fb_control_set_type *mali_set_fb_event; 518 mali_osk_fb_control_set_type *mali_set_fb_event;
528 mali_profiling_control_type *mali_control; 519 mali_profiling_control_type *mali_control;
520
521 mali_set_hw_event = symbol_get(_mali_profiling_set_event);
529 522
530 mali_set_hw_event = symbol_get(_mali_profiling_set_event); 523 if (mali_set_hw_event) {
524 int i;
531 525
532 if (mali_set_hw_event) { 526 pr_debug("gator: mali offline _mali_profiling_set_event symbol @ %p\n", mali_set_hw_event);
533 int i; 527 for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
534 528 mali_set_hw_event(i, 0xFFFFFFFF);
535 pr_debug("gator: mali offline _mali_profiling_set_event symbol @ %p\n",mali_set_hw_event); 529 }
536 for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
537 mali_set_hw_event(i, 0xFFFFFFFF);
538 }
539
540 symbol_put(_mali_profiling_set_event);
541 } else {
542 printk("gator: mali offline _mali_profiling_set_event symbol not found\n");
543 }
544 530
545 mali_set_fb_event = symbol_get(_mali_osk_fb_control_set); 531 symbol_put(_mali_profiling_set_event);
532 } else {
533 printk("gator: mali offline _mali_profiling_set_event symbol not found\n");
534 }
546 535
547 if (mali_set_fb_event) { 536 mali_set_fb_event = symbol_get(_mali_osk_fb_control_set);
548 pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
549 537
550 mali_set_fb_event(0,0); 538 if (mali_set_fb_event) {
539 pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
551 540
552 symbol_put(_mali_osk_fb_control_set); 541 mali_set_fb_event(0, 0);
553 } else {
554 printk("gator: mali offline _mali_osk_fb_control_set symbol not found\n");
555 }
556 542
557 /* Generic control interface for Mali DDK. */ 543 symbol_put(_mali_osk_fb_control_set);
558 mali_control = symbol_get(_mali_profiling_control); 544 } else {
545 printk("gator: mali offline _mali_osk_fb_control_set symbol not found\n");
546 }
559 547
560 if (mali_control) { 548 /* Generic control interface for Mali DDK. */
561 pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_set_fb_event); 549 mali_control = symbol_get(_mali_profiling_control);
562 550
563 /* Reset the DDK state - disable counter collection */ 551 if (mali_control) {
564 mali_control(SW_EVENTS_ENABLE, 0); 552 pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_set_fb_event);
565 553
566 mali_control(FBDUMP_CONTROL_ENABLE, 0); 554 /* Reset the DDK state - disable counter collection */
555 mali_control(SW_EVENTS_ENABLE, 0);
567 556
568 symbol_put(_mali_profiling_control); 557 mali_control(FBDUMP_CONTROL_ENABLE, 0);
569 } else {
570 printk("gator: mali offline _mali_profiling_control symbol not found\n");
571 }
572 558
573 if (mali_get_counters){ 559 symbol_put(_mali_profiling_control);
574 symbol_put(_mali_profiling_get_counters); 560 } else {
575 } 561 printk("gator: mali offline _mali_profiling_control symbol not found\n");
562 }
563
564 if (mali_get_counters) {
565 symbol_put(_mali_profiling_get_counters);
566 }
576 567
577} 568}
578 569
579static int start(void) { 570static int start(void)
580 // register tracepoints 571{
581 if (GATOR_REGISTER_TRACE(mali_hw_counter)) { 572 // register tracepoints
582 printk("gator: mali_hw_counter tracepoint failed to activate\n"); 573 if (GATOR_REGISTER_TRACE(mali_hw_counter)) {
583 return -1; 574 printk("gator: mali_hw_counter tracepoint failed to activate\n");
584 } 575 return -1;
576 }
585 577
586#if GATOR_MALI_INTERFACE_STYLE == 1 578#if GATOR_MALI_INTERFACE_STYLE == 1
587 /* None. */ 579 /* None. */
588#elif GATOR_MALI_INTERFACE_STYLE == 2 580#elif GATOR_MALI_INTERFACE_STYLE == 2
589 /* For patched Mali driver. */ 581 /* For patched Mali driver. */
590 if (GATOR_REGISTER_TRACE(mali_sw_counter)) { 582 if (GATOR_REGISTER_TRACE(mali_sw_counter)) {
591 printk("gator: mali_sw_counter tracepoint failed to activate\n"); 583 printk("gator: mali_sw_counter tracepoint failed to activate\n");
592 return -1; 584 return -1;
593 } 585 }
594#elif GATOR_MALI_INTERFACE_STYLE == 3 586#elif GATOR_MALI_INTERFACE_STYLE == 3
595/* For Mali drivers with built-in support. */ 587/* For Mali drivers with built-in support. */
596 if (GATOR_REGISTER_TRACE(mali_sw_counters)) { 588 if (GATOR_REGISTER_TRACE(mali_sw_counters)) {
597 printk("gator: mali_sw_counters tracepoint failed to activate\n"); 589 printk("gator: mali_sw_counters tracepoint failed to activate\n");
598 return -1; 590 return -1;
599 } 591 }
600#else 592#else
601#error Unknown GATOR_MALI_INTERFACE_STYLE option. 593#error Unknown GATOR_MALI_INTERFACE_STYLE option.
602#endif 594#endif
603 595
604 trace_registered = 1; 596 trace_registered = 1;
605 597
606 mali_counter_initialize(); 598 mali_counter_initialize();
607 return 0; 599 return 0;
608} 600}
609 601
610static void stop(void) { 602static void stop(void)
611 unsigned int cnt; 603{
604 unsigned int cnt;
612 605
613 pr_debug("gator: mali stop\n"); 606 pr_debug("gator: mali stop\n");
614 607
615 if (trace_registered) { 608 if (trace_registered) {
616 GATOR_UNREGISTER_TRACE(mali_hw_counter); 609 GATOR_UNREGISTER_TRACE(mali_hw_counter);
617 610
618#if GATOR_MALI_INTERFACE_STYLE == 1 611#if GATOR_MALI_INTERFACE_STYLE == 1
619 /* None. */ 612 /* None. */
620#elif GATOR_MALI_INTERFACE_STYLE == 2 613#elif GATOR_MALI_INTERFACE_STYLE == 2
621 /* For patched Mali driver. */ 614 /* For patched Mali driver. */
622 GATOR_UNREGISTER_TRACE(mali_sw_counter); 615 GATOR_UNREGISTER_TRACE(mali_sw_counter);
623#elif GATOR_MALI_INTERFACE_STYLE == 3 616#elif GATOR_MALI_INTERFACE_STYLE == 3
624 /* For Mali drivers with built-in support. */ 617 /* For Mali drivers with built-in support. */
625 GATOR_UNREGISTER_TRACE(mali_sw_counters); 618 GATOR_UNREGISTER_TRACE(mali_sw_counters);
626#else 619#else
627#error Unknown GATOR_MALI_INTERFACE_STYLE option. 620#error Unknown GATOR_MALI_INTERFACE_STYLE option.
628#endif 621#endif
629 622
630 pr_debug("gator: mali timeline tracepoint deactivated\n"); 623 pr_debug("gator: mali timeline tracepoint deactivated\n");
631 624
632 trace_registered = 0; 625 trace_registered = 0;
633 } 626 }
634 627
635 for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) { 628 for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) {
636 counter_enabled[cnt] = 0; 629 counter_enabled[cnt] = 0;
637 counter_event[cnt] = 0; 630 counter_event[cnt] = 0;
638 counter_address[cnt] = NULL; 631 counter_address[cnt] = NULL;
639 } 632 }
640 633
641 mali_counter_deinitialize(); 634 mali_counter_deinitialize();
642} 635}
643 636
644static int read(int **buffer) { 637static int read(int **buffer)
645 int cnt, len = 0; 638{
646 639 int cnt, len = 0;
647 if (smp_processor_id()) return 0; 640
648 641 if (smp_processor_id())
649 // Read the L2 C0 and C1 here. 642 return 0;
650 if (counter_enabled[COUNTER_L2_C0] || counter_enabled[COUNTER_L2_C1] ) { 643
651 u32 src0 = 0; 644 // Read the L2 C0 and C1 here.
652 u32 val0 = 0; 645 if (counter_enabled[COUNTER_L2_C0] || counter_enabled[COUNTER_L2_C1]) {
653 u32 src1 = 0; 646 u32 src0 = 0;
654 u32 val1 = 0; 647 u32 val0 = 0;
655 648 u32 src1 = 0;
656 // Poke the driver to get the counter values 649 u32 val1 = 0;
657 if (mali_get_counters){ 650
658 mali_get_counters(&src0, &val0, &src1, &val1); 651 // Poke the driver to get the counter values
659 } 652 if (mali_get_counters) {
660 653 mali_get_counters(&src0, &val0, &src1, &val1);
661 if (counter_enabled[COUNTER_L2_C0]) 654 }
662 { 655
663 // Calculate and save src0's counter val0 656 if (counter_enabled[COUNTER_L2_C0]) {
664 counter_dump[len++] = counter_key[COUNTER_L2_C0]; 657 // Calculate and save src0's counter val0
665 counter_dump[len++] = get_difference(val0, counter_prev[COUNTER_L2_C0]); 658 counter_dump[len++] = counter_key[COUNTER_L2_C0];
666 } 659 counter_dump[len++] = get_difference(val0, counter_prev[COUNTER_L2_C0]);
667 660 }
668 if (counter_enabled[COUNTER_L2_C1]) 661
669 { 662 if (counter_enabled[COUNTER_L2_C1]) {
670 // Calculate and save src1's counter val1 663 // Calculate and save src1's counter val1
671 counter_dump[len++] = counter_key[COUNTER_L2_C1]; 664 counter_dump[len++] = counter_key[COUNTER_L2_C1];
672 counter_dump[len++] = get_difference(val1, counter_prev[COUNTER_L2_C1]); 665 counter_dump[len++] = get_difference(val1, counter_prev[COUNTER_L2_C1]);
673 } 666 }
674 667
675 // Save the previous values for the counters. 668 // Save the previous values for the counters.
676 counter_prev[COUNTER_L2_C0] = val0; 669 counter_prev[COUNTER_L2_C0] = val0;
677 counter_prev[COUNTER_L2_C1] = val1; 670 counter_prev[COUNTER_L2_C1] = val1;
678 } 671 }
679 672
680 // Process other (non-timeline) counters. 673 // Process other (non-timeline) counters.
681 for (cnt = COUNTER_VP_C0; cnt <= LAST_SW_COUNTER; cnt++) { 674 for (cnt = COUNTER_VP_C0; cnt <= LAST_SW_COUNTER; cnt++) {
682 if (counter_enabled[cnt]) { 675 if (counter_enabled[cnt]) {
683 counter_dump[len++] = counter_key[cnt]; 676 counter_dump[len++] = counter_key[cnt];
684 counter_dump[len++] = counter_data[cnt]; 677 counter_dump[len++] = counter_data[cnt];
685 678
686 counter_data[cnt] = 0; 679 counter_data[cnt] = 0;
687 } 680 }
688 } 681 }
689 682
690 /* 683 /*
691 * Add in the voltage and frequency counters if enabled. Note that, since these are 684 * Add in the voltage and frequency counters if enabled. Note that, since these are
692 * actually passed as events, the counter value should not be cleared. 685 * actually passed as events, the counter value should not be cleared.
693 */ 686 */
694 cnt = COUNTER_FREQUENCY; 687 cnt = COUNTER_FREQUENCY;
695 if (counter_enabled[cnt]) { 688 if (counter_enabled[cnt]) {
696 counter_dump[len++] = counter_key[cnt]; 689 counter_dump[len++] = counter_key[cnt];
697 counter_dump[len++] = counter_data[cnt]; 690 counter_dump[len++] = counter_data[cnt];
698 } 691 }
699 692
700 cnt = COUNTER_VOLTAGE; 693 cnt = COUNTER_VOLTAGE;
701 if (counter_enabled[cnt]) { 694 if (counter_enabled[cnt]) {
702 counter_dump[len++] = counter_key[cnt]; 695 counter_dump[len++] = counter_key[cnt];
703 counter_dump[len++] = counter_data[cnt]; 696 counter_dump[len++] = counter_data[cnt];
704 } 697 }
705 698
706 699 if (buffer) {
707 if (buffer) { 700 *buffer = (int *)counter_dump;
708 *buffer = (int*) counter_dump; 701 }
709 } 702
710 703 return len;
711 return len;
712} 704}
713 705
714static struct gator_interface gator_events_mali_interface = { 706static struct gator_interface gator_events_mali_interface = {
715 .create_files = create_files, 707 .create_files = create_files,
716 .start = start, 708 .start = start,
717 .stop = stop, 709 .stop = stop,
718 .read = read, 710 .read = read,
719}; 711};
720 712
721extern void gator_events_mali_log_dvfs_event(unsigned int frequency_mhz, unsigned int voltage_mv) { 713extern void gator_events_mali_log_dvfs_event(unsigned int frequency_mhz, unsigned int voltage_mv)
714{
722 counter_data[COUNTER_FREQUENCY] = frequency_mhz; 715 counter_data[COUNTER_FREQUENCY] = frequency_mhz;
723 counter_data[COUNTER_VOLTAGE] = voltage_mv; 716 counter_data[COUNTER_VOLTAGE] = voltage_mv;
724} 717}
725 718
726int gator_events_mali_init(void) 719int gator_events_mali_init(void)
727{ 720{
728 unsigned int cnt; 721 unsigned int cnt;
729 722
730 pr_debug("gator: mali init\n"); 723 pr_debug("gator: mali init\n");
731 724
732 for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) { 725 for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) {
733 counter_enabled[cnt] = 0; 726 counter_enabled[cnt] = 0;
734 counter_event[cnt] = 0; 727 counter_event[cnt] = 0;
735 counter_key[cnt] = gator_events_get_key(); 728 counter_key[cnt] = gator_events_get_key();
736 counter_address[cnt] = NULL; 729 counter_address[cnt] = NULL;
737 counter_data[cnt] = 0; 730 counter_data[cnt] = 0;
738 } 731 }
739 732
740 trace_registered = 0; 733 trace_registered = 0;
741 734
742 return gator_events_install(&gator_events_mali_interface); 735 return gator_events_install(&gator_events_mali_interface);
743} 736}
744 737
745gator_events_init(gator_events_mali_init); 738gator_events_init(gator_events_mali_init);
diff --git a/driver/gator_events_mali_common.c b/driver/gator_events_mali_common.c
index 62e441c..2186eee 100644
--- a/driver/gator_events_mali_common.c
+++ b/driver/gator_events_mali_common.c
@@ -10,69 +10,65 @@
10 10
11static u32 gator_mali_get_id(void) 11static u32 gator_mali_get_id(void)
12{ 12{
13 return MALI_SUPPORT; 13 return MALI_SUPPORT;
14} 14}
15 15
16extern const char* gator_mali_get_mali_name(void) 16extern const char *gator_mali_get_mali_name(void)
17{ 17{
18 u32 id = gator_mali_get_id(); 18 u32 id = gator_mali_get_id();
19 19
20 switch (id) { 20 switch (id) {
21 case MALI_T6xx: 21 case MALI_T6xx:
22 return "Mali-T6xx"; 22 return "Mali-T6xx";
23 case MALI_400: 23 case MALI_400:
24 return "Mali-400"; 24 return "Mali-400";
25 default: 25 default:
26 pr_debug("gator: Mali-T6xx: unknown Mali ID (%d)\n", id); 26 pr_debug("gator: Mali-T6xx: unknown Mali ID (%d)\n", id);
27 return "Mali-Unknown"; 27 return "Mali-Unknown";
28 } 28 }
29} 29}
30 30
31extern int gator_mali_create_file_system(const char* mali_name, const char* event_name, struct super_block *sb, struct dentry *root, mali_counter *counter) 31extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter)
32{ 32{
33 int err; 33 int err;
34 char buf[255]; 34 char buf[255];
35 struct dentry *dir; 35 struct dentry *dir;
36 36
37 /* If the counter name is empty ignore it*/ 37 /* If the counter name is empty ignore it */
38 if (strlen(event_name) != 0) 38 if (strlen(event_name) != 0) {
39 { 39 /* Set up the filesystem entry for this event. */
40 /* Set up the filesystem entry for this event. */ 40 snprintf(buf, sizeof(buf), "ARM_%s_%s", mali_name, event_name);
41 snprintf(buf, sizeof(buf), "ARM_%s_%s", mali_name, event_name);
42 41
43 dir = gatorfs_mkdir(sb, root, buf); 42 dir = gatorfs_mkdir(sb, root, buf);
44 43
45 if (dir == NULL) 44 if (dir == NULL) {
46 { 45 pr_debug("gator: Mali-T6xx: error creating file system for: %s (%s)", event_name, buf);
47 pr_debug("gator: Mali-T6xx: error creating file system for: %s (%s)", event_name, buf); 46 return -1;
48 return -1; 47 }
49 }
50 48
51 err = gatorfs_create_ulong(sb, dir, "enabled", &counter->enabled); 49 err = gatorfs_create_ulong(sb, dir, "enabled", &counter->enabled);
52 if (err != 0) 50 if (err != 0) {
53 { 51 pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ulong for: %s (%s)", event_name, buf);
54 pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ulong for: %s (%s)", event_name, buf); 52 return -1;
55 return -1; 53 }
56 } 54 err = gatorfs_create_ro_ulong(sb, dir, "key", &counter->key);
57 err = gatorfs_create_ro_ulong(sb, dir, "key", &counter->key); 55 if (err != 0) {
58 if (err != 0) 56 pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf);
59 { 57 return -1;
60 pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf); 58 }
61 return -1; 59 }
62 }
63 }
64 60
65 return 0; 61 return 0;
66} 62}
67 63
68extern void gator_mali_initialise_counters(mali_counter counters[], unsigned int n_counters) 64extern void gator_mali_initialise_counters(mali_counter counters[], unsigned int n_counters)
69{ 65{
70 unsigned int cnt; 66 unsigned int cnt;
71 67
72 for (cnt = 0; cnt < n_counters; cnt++) { 68 for (cnt = 0; cnt < n_counters; cnt++) {
73 mali_counter *counter = &counters[cnt]; 69 mali_counter *counter = &counters[cnt];
74 70
75 counter->key = gator_events_get_key(); 71 counter->key = gator_events_get_key();
76 counter->enabled = 0; 72 counter->enabled = 0;
77 } 73 }
78} 74}
diff --git a/driver/gator_events_mali_common.h b/driver/gator_events_mali_common.h
index 2c9457f..8e33edf 100644
--- a/driver/gator_events_mali_common.h
+++ b/driver/gator_events_mali_common.h
@@ -35,8 +35,8 @@
35 * Runtime state information for a counter. 35 * Runtime state information for a counter.
36 */ 36 */
37typedef struct { 37typedef struct {
38 unsigned long key; /* 'key' (a unique id set by gatord and returned by gator.ko) */ 38 unsigned long key; /* 'key' (a unique id set by gatord and returned by gator.ko) */
39 unsigned long enabled; /* counter enable state */ 39 unsigned long enabled; /* counter enable state */
40} mali_counter; 40} mali_counter;
41 41
42/* 42/*
@@ -45,7 +45,7 @@ typedef struct {
45typedef void mali_profiling_set_event_type(unsigned int, unsigned int); 45typedef void mali_profiling_set_event_type(unsigned int, unsigned int);
46typedef void mali_osk_fb_control_set_type(unsigned int, unsigned int); 46typedef void mali_osk_fb_control_set_type(unsigned int, unsigned int);
47typedef void mali_profiling_control_type(unsigned int, unsigned int); 47typedef void mali_profiling_control_type(unsigned int, unsigned int);
48typedef void mali_profiling_get_counters_type(unsigned int*, unsigned int*, unsigned int*, unsigned int*); 48typedef void mali_profiling_get_counters_type(unsigned int *, unsigned int *, unsigned int *, unsigned int *);
49 49
50/* 50/*
51 * Driver entry points for functions called directly by gator. 51 * Driver entry points for functions called directly by gator.
@@ -53,14 +53,14 @@ typedef void mali_profiling_get_counters_type(unsigned int*, unsigned int*, unsi
53extern void _mali_profiling_set_event(unsigned int, unsigned int); 53extern void _mali_profiling_set_event(unsigned int, unsigned int);
54extern void _mali_osk_fb_control_set(unsigned int, unsigned int); 54extern void _mali_osk_fb_control_set(unsigned int, unsigned int);
55extern void _mali_profiling_control(unsigned int, unsigned int); 55extern void _mali_profiling_control(unsigned int, unsigned int);
56extern void _mali_profiling_get_counters(unsigned int*, unsigned int*, unsigned int*, unsigned int*); 56extern void _mali_profiling_get_counters(unsigned int *, unsigned int *, unsigned int *, unsigned int *);
57 57
58/** 58/**
59 * Returns a name which identifies the GPU type (eg Mali-400, Mali-T6xx). 59 * Returns a name which identifies the GPU type (eg Mali-400, Mali-T6xx).
60 * 60 *
61 * @return The name as a constant string. 61 * @return The name as a constant string.
62 */ 62 */
63extern const char* gator_mali_get_mali_name(void); 63extern const char *gator_mali_get_mali_name(void);
64 64
65/** 65/**
66 * Creates a filesystem entry under /dev/gator relating to the specified event name and key, and 66 * Creates a filesystem entry under /dev/gator relating to the specified event name and key, and
@@ -75,10 +75,10 @@ extern const char* gator_mali_get_mali_name(void);
75 * 75 *
76 * @return 0 if entry point was created, non-zero if not. 76 * @return 0 if entry point was created, non-zero if not.
77 */ 77 */
78extern int gator_mali_create_file_system(const char* mali_name, const char* event_name, struct super_block *sb, struct dentry *root, mali_counter *counter); 78extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter);
79 79
80/** 80/**
81 * Initialises the counter array. 81 * Initializes the counter array.
82 * 82 *
83 * @param keys The array of counters 83 * @param keys The array of counters
84 * @param n_counters The number of entries in each of the arrays. 84 * @param n_counters The number of entries in each of the arrays.
diff --git a/driver/gator_events_mali_t6xx.c b/driver/gator_events_mali_t6xx.c
index f8f868e..1b3a53d 100644
--- a/driver/gator_events_mali_t6xx.c
+++ b/driver/gator_events_mali_t6xx.c
@@ -17,7 +17,6 @@
17 17
18#include "linux/mali_linux_trace.h" 18#include "linux/mali_linux_trace.h"
19 19
20
21#include "gator_events_mali_common.h" 20#include "gator_events_mali_common.h"
22 21
23/* 22/*
@@ -27,7 +26,6 @@
27#error MALI_SUPPORT set to an invalid device code: expecting MALI_T6xx 26#error MALI_SUPPORT set to an invalid device code: expecting MALI_T6xx
28#endif 27#endif
29 28
30
31/* Counters for Mali-T6xx: 29/* Counters for Mali-T6xx:
32 * 30 *
33 * - Timeline events 31 * - Timeline events
@@ -43,72 +41,66 @@
43 */ 41 */
44 42
45/* Timeline (start/stop) activity */ 43/* Timeline (start/stop) activity */
46static const char* timeline_event_names [] = 44static const char *timeline_event_names[] = {
47{ 45 "PM_SHADER_0",
48 "PM_SHADER_0", 46 "PM_SHADER_1",
49 "PM_SHADER_1", 47 "PM_SHADER_2",
50 "PM_SHADER_2", 48 "PM_SHADER_3",
51 "PM_SHADER_3", 49 "PM_SHADER_4",
52 "PM_SHADER_4", 50 "PM_SHADER_5",
53 "PM_SHADER_5", 51 "PM_SHADER_6",
54 "PM_SHADER_6", 52 "PM_SHADER_7",
55 "PM_SHADER_7", 53 "PM_TILER_0",
56 "PM_TILER_0", 54 "PM_L2_0",
57 "PM_L2_0", 55 "PM_L2_1",
58 "PM_L2_1", 56 "MMU_AS_0",
59 "MMU_AS_0", 57 "MMU_AS_1",
60 "MMU_AS_1", 58 "MMU_AS_2",
61 "MMU_AS_2", 59 "MMU_AS_3"
62 "MMU_AS_3"
63}; 60};
64 61
65enum 62enum {
66{ 63 PM_SHADER_0 = 0,
67 PM_SHADER_0 = 0, 64 PM_SHADER_1,
68 PM_SHADER_1, 65 PM_SHADER_2,
69 PM_SHADER_2, 66 PM_SHADER_3,
70 PM_SHADER_3, 67 PM_SHADER_4,
71 PM_SHADER_4, 68 PM_SHADER_5,
72 PM_SHADER_5, 69 PM_SHADER_6,
73 PM_SHADER_6, 70 PM_SHADER_7,
74 PM_SHADER_7, 71 PM_TILER_0,
75 PM_TILER_0, 72 PM_L2_0,
76 PM_L2_0, 73 PM_L2_1,
77 PM_L2_1, 74 MMU_AS_0,
78 MMU_AS_0, 75 MMU_AS_1,
79 MMU_AS_1, 76 MMU_AS_2,
80 MMU_AS_2, 77 MMU_AS_3
81 MMU_AS_3
82}; 78};
83/* The number of shader blocks in the enum above */ 79/* The number of shader blocks in the enum above */
84#define NUM_PM_SHADER (8) 80#define NUM_PM_SHADER (8)
85 81
86/* Software Counters */ 82/* Software Counters */
87static const char* software_counter_names [] = 83static const char *software_counter_names[] = {
88{ 84 "MMU_PAGE_FAULT_0",
89 "MMU_PAGE_FAULT_0", 85 "MMU_PAGE_FAULT_1",
90 "MMU_PAGE_FAULT_1", 86 "MMU_PAGE_FAULT_2",
91 "MMU_PAGE_FAULT_2", 87 "MMU_PAGE_FAULT_3"
92 "MMU_PAGE_FAULT_3"
93}; 88};
94 89
95enum 90enum {
96{ 91 MMU_PAGE_FAULT_0 = 0,
97 MMU_PAGE_FAULT_0 = 0, 92 MMU_PAGE_FAULT_1,
98 MMU_PAGE_FAULT_1, 93 MMU_PAGE_FAULT_2,
99 MMU_PAGE_FAULT_2, 94 MMU_PAGE_FAULT_3
100 MMU_PAGE_FAULT_3
101}; 95};
102 96
103/* Software Counters */ 97/* Software Counters */
104static const char* accumulators_names [] = 98static const char *accumulators_names[] = {
105{ 99 "TOTAL_ALLOC_PAGES"
106 "TOTAL_ALLOC_PAGES"
107}; 100};
108 101
109enum 102enum {
110{ 103 TOTAL_ALLOC_PAGES = 0
111 TOTAL_ALLOC_PAGES = 0
112}; 104};
113 105
114#define FIRST_TIMELINE_EVENT (0) 106#define FIRST_TIMELINE_EVENT (0)
@@ -153,49 +145,46 @@ static struct timespec prev_timestamp;
153 */ 145 */
154static inline long get_duration_us(const struct timespec *start, const struct timespec *end) 146static inline long get_duration_us(const struct timespec *start, const struct timespec *end)
155{ 147{
156 long event_duration_us = (end->tv_nsec - start->tv_nsec)/1000; 148 long event_duration_us = (end->tv_nsec - start->tv_nsec) / 1000;
157 event_duration_us += (end->tv_sec - start->tv_sec) * 1000000; 149 event_duration_us += (end->tv_sec - start->tv_sec) * 1000000;
158 150
159 return event_duration_us; 151 return event_duration_us;
160} 152}
161 153
162static void record_timeline_event(unsigned int timeline_index, unsigned int type) 154static void record_timeline_event(unsigned int timeline_index, unsigned int type)
163{ 155{
164 struct timespec event_timestamp; 156 struct timespec event_timestamp;
165 struct timespec *event_start = &timeline_event_starttime[timeline_index]; 157 struct timespec *event_start = &timeline_event_starttime[timeline_index];
166 158
167 switch(type) 159 switch (type) {
168 { 160 case ACTIVITY_START:
169 case ACTIVITY_START: 161 /* Get the event time... */
170 /* Get the event time... */ 162 getnstimeofday(&event_timestamp);
171 getnstimeofday(&event_timestamp); 163
172 164 /* Remember the start time if the activity is not already started */
173 /* Remember the start time if the activity is not already started */ 165 if (event_start->tv_sec == 0) {
174 if(event_start->tv_sec == 0) 166 *event_start = event_timestamp; /* Structure copy */
175 { 167 }
176 *event_start = event_timestamp; /* Structure copy */ 168 break;
177 } 169
178 break; 170 case ACTIVITY_STOP:
179 171 /* if the counter was started... */
180 case ACTIVITY_STOP: 172 if (event_start->tv_sec != 0) {
181 /* if the counter was started... */ 173 /* Get the event time... */
182 if(event_start->tv_sec != 0) 174 getnstimeofday(&event_timestamp);
183 { 175
184 /* Get the event time... */ 176 /* Accumulate the duration in us */
185 getnstimeofday(&event_timestamp); 177 timeline_data[timeline_index] += get_duration_us(event_start, &event_timestamp);
186 178
187 /* Accumulate the duration in us */ 179 /* Reset the start time to indicate the activity is stopped. */
188 timeline_data[timeline_index] += get_duration_us(event_start, &event_timestamp); 180 event_start->tv_sec = 0;
189 181 }
190 /* Reset the start time to indicate the activity is stopped. */ 182 break;
191 event_start->tv_sec = 0; 183
192 } 184 default:
193 break; 185 /* Other activity events are ignored. */
194 186 break;
195 default: 187 }
196 /* Other activity events are ignored. */
197 break;
198 }
199} 188}
200 189
201/* 190/*
@@ -204,68 +193,62 @@ static void record_timeline_event(unsigned int timeline_index, unsigned int type
204 193
205GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long long value)) 194GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long long value))
206{ 195{
207#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */ 196#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */
208#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */ 197#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */
209#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */ 198#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */
210#define BIT_AT(value, pos) ((value >> pos) & 1) 199#define BIT_AT(value, pos) ((value >> pos) & 1)
211 200
212 static unsigned long long previous_shader_bitmask = 0; 201 static unsigned long long previous_shader_bitmask = 0;
213 static unsigned long long previous_tiler_bitmask = 0; 202 static unsigned long long previous_tiler_bitmask = 0;
214 static unsigned long long previous_l2_bitmask = 0; 203 static unsigned long long previous_l2_bitmask = 0;
215 204
216 switch (event_id) 205 switch (event_id) {
217 { 206 case SHADER_PRESENT_LO:
218 case SHADER_PRESENT_LO: 207 {
219 { 208 unsigned long long changed_bitmask = previous_shader_bitmask ^ value;
220 unsigned long long changed_bitmask = previous_shader_bitmask ^ value; 209 int pos;
221 int pos; 210
222 211 for (pos = 0; pos < NUM_PM_SHADER; ++pos) {
223 for (pos = 0; pos < NUM_PM_SHADER; ++pos) 212 if (BIT_AT(changed_bitmask, pos)) {
224 { 213 record_timeline_event(PM_SHADER_0 + pos, BIT_AT(value, pos) ? ACTIVITY_START : ACTIVITY_STOP);
225 if (BIT_AT(changed_bitmask, pos)) 214 }
226 { 215 }
227 record_timeline_event(PM_SHADER_0 + pos, BIT_AT(value, pos) ? ACTIVITY_START : ACTIVITY_STOP); 216
228 } 217 previous_shader_bitmask = value;
229 } 218 break;
230 219 }
231 previous_shader_bitmask = value; 220
232 break; 221 case TILER_PRESENT_LO:
233 } 222 {
234 223 unsigned long long changed = previous_tiler_bitmask ^ value;
235 case TILER_PRESENT_LO: 224
236 { 225 if (BIT_AT(changed, 0)) {
237 unsigned long long changed = previous_tiler_bitmask ^ value; 226 record_timeline_event(PM_TILER_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP);
238 227 }
239 if (BIT_AT(changed, 0)) 228
240 { 229 previous_tiler_bitmask = value;
241 record_timeline_event(PM_TILER_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP); 230 break;
242 } 231 }
243 232
244 previous_tiler_bitmask = value; 233 case L2_PRESENT_LO:
245 break; 234 {
246 } 235 unsigned long long changed = previous_l2_bitmask ^ value;
247 236
248 case L2_PRESENT_LO: 237 if (BIT_AT(changed, 0)) {
249 { 238 record_timeline_event(PM_L2_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP);
250 unsigned long long changed = previous_l2_bitmask ^ value; 239 }
251 240 if (BIT_AT(changed, 4)) {
252 if (BIT_AT(changed, 0)) 241 record_timeline_event(PM_L2_1, BIT_AT(value, 4) ? ACTIVITY_START : ACTIVITY_STOP);
253 { 242 }
254 record_timeline_event(PM_L2_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP); 243
255 } 244 previous_l2_bitmask = value;
256 if (BIT_AT(changed, 4)) 245 break;
257 { 246 }
258 record_timeline_event(PM_L2_1, BIT_AT(value, 4) ? ACTIVITY_START : ACTIVITY_STOP); 247
259 } 248 default:
260 249 /* No other blocks are supported at present */
261 previous_l2_bitmask = value; 250 break;
262 break; 251 }
263 }
264
265 default:
266 /* No other blocks are supported at present */
267 break;
268 }
269 252
270#undef SHADER_PRESENT_LO 253#undef SHADER_PRESENT_LO
271#undef TILER_PRESENT_LO 254#undef TILER_PRESENT_LO
@@ -275,278 +258,255 @@ GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long
275 258
276GATOR_DEFINE_PROBE(mali_page_fault_insert_pages, TP_PROTO(int event_id, unsigned long value)) 259GATOR_DEFINE_PROBE(mali_page_fault_insert_pages, TP_PROTO(int event_id, unsigned long value))
277{ 260{
278 /* We add to the previous since we may receive many tracepoints in one sample period */ 261 /* We add to the previous since we may receive many tracepoints in one sample period */
279 sw_counter_data[MMU_PAGE_FAULT_0 + event_id] += value; 262 sw_counter_data[MMU_PAGE_FAULT_0 + event_id] += value;
280} 263}
281 264
282GATOR_DEFINE_PROBE(mali_mmu_as_in_use, TP_PROTO(int event_id)) 265GATOR_DEFINE_PROBE(mali_mmu_as_in_use, TP_PROTO(int event_id))
283{ 266{
284 record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_START); 267 record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_START);
285} 268}
286 269
287GATOR_DEFINE_PROBE(mali_mmu_as_released, TP_PROTO(int event_id)) 270GATOR_DEFINE_PROBE(mali_mmu_as_released, TP_PROTO(int event_id))
288{ 271{
289 record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_STOP); 272 record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_STOP);
290} 273}
291 274
292GATOR_DEFINE_PROBE(mali_total_alloc_pages_change, TP_PROTO(long long int event_id)) 275GATOR_DEFINE_PROBE(mali_total_alloc_pages_change, TP_PROTO(long long int event_id))
293{ 276{
294 accumulators_data[TOTAL_ALLOC_PAGES] = event_id; 277 accumulators_data[TOTAL_ALLOC_PAGES] = event_id;
295} 278}
296 279
297static int create_files(struct super_block *sb, struct dentry *root) 280static int create_files(struct super_block *sb, struct dentry *root)
298{ 281{
299 int event; 282 int event;
300 /* 283 /*
301 * Create the filesystem for all events 284 * Create the filesystem for all events
302 */ 285 */
303 int counter_index = 0; 286 int counter_index = 0;
304 const char* mali_name = gator_mali_get_mali_name(); 287 const char *mali_name = gator_mali_get_mali_name();
305 288
306 for (event = FIRST_TIMELINE_EVENT; event < FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS; event++) 289 for (event = FIRST_TIMELINE_EVENT; event < FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS; event++) {
307 { 290 if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event]) != 0) {
308 if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event]) != 0) 291 return -1;
309 { 292 }
310 return -1; 293 counter_index++;
311 } 294 }
312 counter_index++; 295 counter_index = 0;
313 } 296 for (event = FIRST_SOFTWARE_COUNTER; event < FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS; event++) {
314 counter_index = 0; 297 if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event]) != 0) {
315 for (event = FIRST_SOFTWARE_COUNTER; event < FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS; event++) 298 return -1;
316 { 299 }
317 if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event]) != 0) 300 counter_index++;
318 { 301 }
319 return -1; 302 counter_index = 0;
320 } 303 for (event = FIRST_ACCUMULATOR; event < FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS; event++) {
321 counter_index++; 304 if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event]) != 0) {
322 } 305 return -1;
323 counter_index = 0; 306 }
324 for (event = FIRST_ACCUMULATOR; event < FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS; event++) 307 counter_index++;
325 { 308 }
326 if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event]) != 0) 309
327 { 310 return 0;
328 return -1;
329 }
330 counter_index++;
331 }
332
333 return 0;
334} 311}
335 312
336static int register_tracepoints(void) 313static int register_tracepoints(void)
337{ 314{
338 if (GATOR_REGISTER_TRACE(mali_pm_status)) 315 if (GATOR_REGISTER_TRACE(mali_pm_status)) {
339 { 316 pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint failed to activate\n");
340 pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint failed to activate\n"); 317 return 0;
341 return 0; 318 }
342 } 319
343 320 if (GATOR_REGISTER_TRACE(mali_page_fault_insert_pages)) {
344 if (GATOR_REGISTER_TRACE(mali_page_fault_insert_pages)) 321 pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint failed to activate\n");
345 { 322 return 0;
346 pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint failed to activate\n"); 323 }
347 return 0; 324
348 } 325 if (GATOR_REGISTER_TRACE(mali_mmu_as_in_use)) {
349 326 pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint failed to activate\n");
350 if (GATOR_REGISTER_TRACE(mali_mmu_as_in_use)) 327 return 0;
351 { 328 }
352 pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint failed to activate\n"); 329
353 return 0; 330 if (GATOR_REGISTER_TRACE(mali_mmu_as_released)) {
354 } 331 pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint failed to activate\n");
355 332 return 0;
356 if (GATOR_REGISTER_TRACE(mali_mmu_as_released)) 333 }
357 { 334
358 pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint failed to activate\n"); 335 if (GATOR_REGISTER_TRACE(mali_total_alloc_pages_change)) {
359 return 0; 336 pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint failed to activate\n");
360 } 337 return 0;
361 338 }
362 if (GATOR_REGISTER_TRACE(mali_total_alloc_pages_change)) 339
363 { 340 pr_debug("gator: Mali-T6xx: start\n");
364 pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint failed to activate\n"); 341 pr_debug("gator: Mali-T6xx: mali_pm_status probe is at %p\n", &probe_mali_pm_status);
365 return 0; 342 pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages probe is at %p\n", &probe_mali_page_fault_insert_pages);
366 } 343 pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use probe is at %p\n", &probe_mali_mmu_as_in_use);
367 344 pr_debug("gator: Mali-T6xx: mali_mmu_as_released probe is at %p\n", &probe_mali_mmu_as_released);
368 pr_debug("gator: Mali-T6xx: start\n"); 345 pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change probe is at %p\n", &probe_mali_total_alloc_pages_change);
369 pr_debug("gator: Mali-T6xx: mali_pm_status probe is at %p\n", &probe_mali_pm_status); 346
370 pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages probe is at %p\n", &probe_mali_page_fault_insert_pages); 347 return 1;
371 pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use probe is at %p\n", &probe_mali_mmu_as_in_use);
372 pr_debug("gator: Mali-T6xx: mali_mmu_as_released probe is at %p\n", &probe_mali_mmu_as_released);
373 pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change probe is at %p\n", &probe_mali_total_alloc_pages_change);
374
375 return 1;
376} 348}
377 349
378static int start(void) 350static int start(void)
379{ 351{
380 unsigned int cnt; 352 unsigned int cnt;
381 353
382 /* Clean all data for the next capture */ 354 /* Clean all data for the next capture */
383 for (cnt = 0; cnt < NUMBER_OF_TIMELINE_EVENTS; cnt++) 355 for (cnt = 0; cnt < NUMBER_OF_TIMELINE_EVENTS; cnt++) {
384 { 356 timeline_event_starttime[cnt].tv_sec = timeline_event_starttime[cnt].tv_nsec = 0;
385 timeline_event_starttime[cnt].tv_sec = timeline_event_starttime[cnt].tv_nsec = 0; 357 timeline_data[cnt] = 0;
386 timeline_data[cnt] = 0; 358 }
387 } 359
388 360 for (cnt = 0; cnt < NUMBER_OF_SOFTWARE_COUNTERS; cnt++) {
389 for (cnt = 0; cnt < NUMBER_OF_SOFTWARE_COUNTERS; cnt++) 361 sw_counter_data[cnt] = 0;
390 { 362 }
391 sw_counter_data[cnt] = 0; 363
392 } 364 for (cnt = 0; cnt < NUMBER_OF_ACCUMULATORS; cnt++) {
393 365 accumulators_data[cnt] = 0;
394 for (cnt = 0; cnt < NUMBER_OF_ACCUMULATORS; cnt++) 366 }
395 { 367
396 accumulators_data[cnt] = 0; 368 /* Register tracepoints */
397 } 369 if (register_tracepoints() == 0) {
398 370 return -1;
399 /* Register tracepoints */ 371 }
400 if (register_tracepoints() == 0) 372
401 { 373 /*
402 return -1; 374 * Set the first timestamp for calculating the sample interval. The first interval could be quite long,
403 } 375 * since it will be the time between 'start' and the first 'read'.
404 376 * This means that timeline values will be divided by a big number for the first sample.
405 /* 377 */
406 * Set the first timestamp for calculating the sample interval. The first interval could be quite long, 378 getnstimeofday(&prev_timestamp);
407 * since it will be the time between 'start' and the first 'read'. 379
408 * This means that timeline values will be divided by a big number for the first sample. 380 return 0;
409 */
410 getnstimeofday(&prev_timestamp);
411
412 return 0;
413} 381}
414 382
415static void stop(void) 383static void stop(void)
416{ 384{
417 pr_debug("gator: Mali-T6xx: stop\n"); 385 pr_debug("gator: Mali-T6xx: stop\n");
418 386
419 /* 387 /*
420 * It is safe to unregister traces even if they were not successfully 388 * It is safe to unregister traces even if they were not successfully
421 * registered, so no need to check. 389 * registered, so no need to check.
422 */ 390 */
423 GATOR_UNREGISTER_TRACE(mali_pm_status); 391 GATOR_UNREGISTER_TRACE(mali_pm_status);
424 pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint deactivated\n"); 392 pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint deactivated\n");
425 393
426 GATOR_UNREGISTER_TRACE(mali_page_fault_insert_pages); 394 GATOR_UNREGISTER_TRACE(mali_page_fault_insert_pages);
427 pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint deactivated\n"); 395 pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint deactivated\n");
428 396
429 GATOR_UNREGISTER_TRACE(mali_mmu_as_in_use); 397 GATOR_UNREGISTER_TRACE(mali_mmu_as_in_use);
430 pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint deactivated\n"); 398 pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint deactivated\n");
431 399
432 GATOR_UNREGISTER_TRACE(mali_mmu_as_released); 400 GATOR_UNREGISTER_TRACE(mali_mmu_as_released);
433 pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint deactivated\n"); 401 pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint deactivated\n");
434 402
435 GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change); 403 GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change);
436 pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint deactivated\n"); 404 pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint deactivated\n");
437} 405}
438 406
439static int read(int **buffer) 407static int read(int **buffer)
440{ 408{
441 int cnt; 409 int cnt;
442 int len = 0; 410 int len = 0;
443 long sample_interval_us = 0; 411 long sample_interval_us = 0;
444 struct timespec read_timestamp; 412 struct timespec read_timestamp;
445 413
446 if (smp_processor_id()!=0) 414 if (smp_processor_id() != 0) {
447 { 415 return 0;
448 return 0; 416 }
449 } 417
450 418 /* Get the start of this sample period. */
451 /* Get the start of this sample period. */ 419 getnstimeofday(&read_timestamp);
452 getnstimeofday(&read_timestamp); 420
453 421 /*
454 /* 422 * Calculate the sample interval if the previous sample time is valid.
455 * Calculate the sample interval if the previous sample time is valid. 423 * We use tv_sec since it will not be 0.
456 * We use tv_sec since it will not be 0. 424 */
457 */ 425 if (prev_timestamp.tv_sec != 0) {
458 if(prev_timestamp.tv_sec != 0) { 426 sample_interval_us = get_duration_us(&prev_timestamp, &read_timestamp);
459 sample_interval_us = get_duration_us(&prev_timestamp, &read_timestamp); 427 }
460 } 428
461 429 /* Structure copy. Update the previous timestamp. */
462 /* Structure copy. Update the previous timestamp. */ 430 prev_timestamp = read_timestamp;
463 prev_timestamp = read_timestamp; 431
464 432 /*
465 /* 433 * Report the timeline counters (ACTIVITY_START/STOP)
466 * Report the timeline counters (ACTIVITY_START/STOP) 434 */
467 */ 435 for (cnt = FIRST_TIMELINE_EVENT; cnt < (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS); cnt++) {
468 for (cnt = FIRST_TIMELINE_EVENT; cnt < (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS); cnt++) 436 mali_counter *counter = &counters[cnt];
469 { 437 if (counter->enabled) {
470 mali_counter *counter = &counters[cnt]; 438 const int index = cnt - FIRST_TIMELINE_EVENT;
471 if (counter->enabled) 439 unsigned int value;
472 { 440
473 const int index = cnt - FIRST_TIMELINE_EVENT; 441 /* If the activity is still running, reset its start time to the start of this sample period
474 unsigned int value; 442 * to correct the count. Add the time up to the end of the sample onto the count. */
475 443 if (timeline_event_starttime[index].tv_sec != 0) {
476 /* If the activity is still running, reset its start time to the start of this sample period 444 const long event_duration = get_duration_us(&timeline_event_starttime[index], &read_timestamp);
477 * to correct the count. Add the time up to the end of the sample onto the count. */ 445 timeline_data[index] += event_duration;
478 if(timeline_event_starttime[index].tv_sec != 0) { 446 timeline_event_starttime[index] = read_timestamp; /* Activity is still running. */
479 const long event_duration = get_duration_us(&timeline_event_starttime[index], &read_timestamp); 447 }
480 timeline_data[index] += event_duration; 448
481 timeline_event_starttime[index] = read_timestamp; /* Activity is still running. */ 449 if (sample_interval_us != 0) {
482 } 450 /* Convert the counter to a percent-of-sample value */
483 451 value = (timeline_data[index] * 100) / sample_interval_us;
484 if(sample_interval_us != 0) { 452 } else {
485 /* Convert the counter to a percent-of-sample value */ 453 pr_debug("gator: Mali-T6xx: setting value to zero\n");
486 value = (timeline_data[index] * 100) / sample_interval_us; 454 value = 0;
487 } else { 455 }
488 pr_debug("gator: Mali-T6xx: setting value to zero\n"); 456
489 value = 0; 457 /* Clear the counter value ready for the next sample. */
490 } 458 timeline_data[index] = 0;
491 459
492 /* Clear the counter value ready for the next sample. */ 460 counter_dump[len++] = counter->key;
493 timeline_data[index] = 0; 461 counter_dump[len++] = value;
494 462 }
495 counter_dump[len++] = counter->key; 463 }
496 counter_dump[len++] = value; 464
497 } 465 /* Report the software counters */
498 } 466 for (cnt = FIRST_SOFTWARE_COUNTER; cnt < (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS); cnt++) {
499 467 const mali_counter *counter = &counters[cnt];
500 /* Report the software counters */ 468 if (counter->enabled) {
501 for (cnt = FIRST_SOFTWARE_COUNTER; cnt < (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS); cnt++) 469 const int index = cnt - FIRST_SOFTWARE_COUNTER;
502 { 470 counter_dump[len++] = counter->key;
503 const mali_counter *counter = &counters[cnt]; 471 counter_dump[len++] = sw_counter_data[index];
504 if (counter->enabled) 472 /* Set the value to zero for the next time */
505 { 473 sw_counter_data[index] = 0;
506 const int index = cnt - FIRST_SOFTWARE_COUNTER; 474 }
507 counter_dump[len++] = counter->key; 475 }
508 counter_dump[len++] = sw_counter_data[index]; 476
509 /* Set the value to zero for the next time */ 477 /* Report the accumulators */
510 sw_counter_data[index] = 0; 478 for (cnt = FIRST_ACCUMULATOR; cnt < (FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS); cnt++) {
511 } 479 const mali_counter *counter = &counters[cnt];
512 } 480 if (counter->enabled) {
513 481 const int index = cnt - FIRST_ACCUMULATOR;
514 /* Report the accumulators */ 482 counter_dump[len++] = counter->key;
515 for (cnt = FIRST_ACCUMULATOR; cnt < (FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS); cnt++) 483 counter_dump[len++] = accumulators_data[index];
516 { 484 /* Do not zero the accumulator */
517 const mali_counter *counter = &counters[cnt]; 485 }
518 if (counter->enabled) 486 }
519 { 487
520 const int index = cnt - FIRST_ACCUMULATOR; 488 /* Update the buffer */
521 counter_dump[len++] = counter->key; 489 if (buffer) {
522 counter_dump[len++] = accumulators_data[index]; 490 *buffer = (int *)counter_dump;
523 /* Do not zero the accumulator */ 491 }
524 } 492
525 } 493 return len;
526
527 /* Update the buffer */
528 if (buffer)
529 {
530 *buffer = (int*) counter_dump;
531 }
532
533 return len;
534} 494}
535 495
536static struct gator_interface gator_events_mali_t6xx_interface = { 496static struct gator_interface gator_events_mali_t6xx_interface = {
537 .create_files = create_files, 497 .create_files = create_files,
538 .start = start, 498 .start = start,
539 .stop = stop, 499 .stop = stop,
540 .read = read 500 .read = read
541}; 501};
542 502
543extern int gator_events_mali_t6xx_init(void) 503extern int gator_events_mali_t6xx_init(void)
544{ 504{
545 pr_debug("gator: Mali-T6xx: sw_counters init\n"); 505 pr_debug("gator: Mali-T6xx: sw_counters init\n");
546 506
547 gator_mali_initialise_counters(counters, NUMBER_OF_EVENTS); 507 gator_mali_initialise_counters(counters, NUMBER_OF_EVENTS);
548 508
549 return gator_events_install(&gator_events_mali_t6xx_interface); 509 return gator_events_install(&gator_events_mali_t6xx_interface);
550} 510}
551 511
552gator_events_init(gator_events_mali_t6xx_init); 512gator_events_init(gator_events_mali_t6xx_init);
diff --git a/driver/gator_events_mali_t6xx_hw.c b/driver/gator_events_mali_t6xx_hw.c
index 854d02d..72498c8 100644
--- a/driver/gator_events_mali_t6xx_hw.c
+++ b/driver/gator_events_mali_t6xx_hw.c
@@ -26,7 +26,7 @@
26 * Mali-T6xx 26 * Mali-T6xx
27 */ 27 */
28typedef struct kbase_device *kbase_find_device_type(int); 28typedef struct kbase_device *kbase_find_device_type(int);
29typedef kbase_context *kbase_create_context_type(kbase_device*); 29typedef kbase_context *kbase_create_context_type(kbase_device *);
30typedef void kbase_destroy_context_type(kbase_context *); 30typedef void kbase_destroy_context_type(kbase_context *);
31typedef void *kbase_va_alloc_type(kbase_context *, u32); 31typedef void *kbase_va_alloc_type(kbase_context *, u32);
32typedef void kbase_va_free_type(kbase_context *, void *); 32typedef void kbase_va_free_type(kbase_context *, void *);
@@ -36,32 +36,41 @@ typedef mali_error kbase_instr_hwcnt_clear_type(kbase_context *);
36typedef mali_error kbase_instr_hwcnt_dump_irq_type(kbase_context *); 36typedef mali_error kbase_instr_hwcnt_dump_irq_type(kbase_context *);
37typedef mali_bool kbase_instr_hwcnt_dump_complete_type(kbase_context *, mali_bool *); 37typedef mali_bool kbase_instr_hwcnt_dump_complete_type(kbase_context *, mali_bool *);
38 38
39static kbase_find_device_type * kbase_find_device_symbol; 39static kbase_find_device_type *kbase_find_device_symbol;
40static kbase_create_context_type * kbase_create_context_symbol; 40static kbase_create_context_type *kbase_create_context_symbol;
41static kbase_va_alloc_type * kbase_va_alloc_symbol; 41static kbase_va_alloc_type *kbase_va_alloc_symbol;
42static kbase_instr_hwcnt_enable_type * kbase_instr_hwcnt_enable_symbol; 42static kbase_instr_hwcnt_enable_type *kbase_instr_hwcnt_enable_symbol;
43static kbase_instr_hwcnt_clear_type * kbase_instr_hwcnt_clear_symbol; 43static kbase_instr_hwcnt_clear_type *kbase_instr_hwcnt_clear_symbol;
44static kbase_instr_hwcnt_dump_irq_type * kbase_instr_hwcnt_dump_irq_symbol; 44static kbase_instr_hwcnt_dump_irq_type *kbase_instr_hwcnt_dump_irq_symbol;
45static kbase_instr_hwcnt_dump_complete_type * kbase_instr_hwcnt_dump_complete_symbol; 45static kbase_instr_hwcnt_dump_complete_type *kbase_instr_hwcnt_dump_complete_symbol;
46static kbase_instr_hwcnt_disable_type * kbase_instr_hwcnt_disable_symbol; 46static kbase_instr_hwcnt_disable_type *kbase_instr_hwcnt_disable_symbol;
47static kbase_va_free_type * kbase_va_free_symbol; 47static kbase_va_free_type *kbase_va_free_symbol;
48static kbase_destroy_context_type * kbase_destroy_context_symbol; 48static kbase_destroy_context_type *kbase_destroy_context_symbol;
49 49
50/** The interval between reads, in ns. */ 50/** The interval between reads, in ns.
51static const int READ_INTERVAL_NSEC = 1000000; 51 *
52 52 * Earlier we introduced
53 * a 'hold off for 1ms after last read' to resolve MIDBASE-2178 and MALINE-724.
54 * However, the 1ms hold off is too long if no context switches occur as there is a race
55 * between this value and the tick of the read clock in gator which is also 1ms. If we 'miss' the
56 * current read, the counter values are effectively 'spread' over 2ms and the values seen are half
57 * what they should be (since Streamline averages over sample time). In the presence of context switches
58 * this spread can vary and markedly affect the counters. Currently there is no 'proper' solution to
59 * this, but empirically we have found that reducing the minimum read interval to 950us causes the
60 * counts to be much more stable.
61 */
62static const int READ_INTERVAL_NSEC = 950000;
53 63
54#if GATOR_TEST 64#if GATOR_TEST
55#include "gator_events_mali_t6xx_hw_test.c" 65#include "gator_events_mali_t6xx_hw_test.c"
56#endif 66#endif
57 67
58/* Blocks for HW counters */ 68/* Blocks for HW counters */
59enum 69enum {
60{ 70 JM_BLOCK = 0,
61 JM_BLOCK = 0, 71 TILER_BLOCK,
62 TILER_BLOCK, 72 SHADER_BLOCK,
63 SHADER_BLOCK, 73 MMU_BLOCK
64 MMU_BLOCK
65}; 74};
66 75
67/* Counters for Mali-T6xx: 76/* Counters for Mali-T6xx:
@@ -75,271 +84,270 @@ enum
75 */ 84 */
76 85
77/* Hardware Counters */ 86/* Hardware Counters */
78static const char* const hardware_counter_names [] = 87static const char *const hardware_counter_names[] = {
79{ 88 /* Job Manager */
80 /* Job Manager */ 89 "",
81 "", 90 "",
82 "", 91 "",
83 "", 92 "",
84 "", 93 "MESSAGES_SENT",
85 "MESSAGES_SENT", 94 "MESSAGES_RECEIVED",
86 "MESSAGES_RECEIVED", 95 "GPU_ACTIVE", /* 6 */
87 "GPU_ACTIVE", /* 6 */ 96 "IRQ_ACTIVE",
88 "IRQ_ACTIVE", 97 "JS0_JOBS",
89 "JS0_JOBS", 98 "JS0_TASKS",
90 "JS0_TASKS", 99 "JS0_ACTIVE",
91 "JS0_ACTIVE", 100 "",
92 "", 101 "JS0_WAIT_READ",
93 "JS0_WAIT_READ", 102 "JS0_WAIT_ISSUE",
94 "JS0_WAIT_ISSUE", 103 "JS0_WAIT_DEPEND",
95 "JS0_WAIT_DEPEND", 104 "JS0_WAIT_FINISH",
96 "JS0_WAIT_FINISH", 105 "JS1_JOBS",
97 "JS1_JOBS", 106 "JS1_TASKS",
98 "JS1_TASKS", 107 "JS1_ACTIVE",
99 "JS1_ACTIVE", 108 "",
100 "", 109 "JS1_WAIT_READ",
101 "JS1_WAIT_READ", 110 "JS1_WAIT_ISSUE",
102 "JS1_WAIT_ISSUE", 111 "JS1_WAIT_DEPEND",
103 "JS1_WAIT_DEPEND", 112 "JS1_WAIT_FINISH",
104 "JS1_WAIT_FINISH", 113 "JS2_JOBS",
105 "JS2_JOBS", 114 "JS2_TASKS",
106 "JS2_TASKS", 115 "JS2_ACTIVE",
107 "JS2_ACTIVE", 116 "",
108 "", 117 "JS2_WAIT_READ",
109 "JS2_WAIT_READ", 118 "JS2_WAIT_ISSUE",
110 "JS2_WAIT_ISSUE", 119 "JS2_WAIT_DEPEND",
111 "JS2_WAIT_DEPEND", 120 "JS2_WAIT_FINISH",
112 "JS2_WAIT_FINISH", 121 "JS3_JOBS",
113 "JS3_JOBS", 122 "JS3_TASKS",
114 "JS3_TASKS", 123 "JS3_ACTIVE",
115 "JS3_ACTIVE", 124 "",
116 "", 125 "JS3_WAIT_READ",
117 "JS3_WAIT_READ", 126 "JS3_WAIT_ISSUE",
118 "JS3_WAIT_ISSUE", 127 "JS3_WAIT_DEPEND",
119 "JS3_WAIT_DEPEND", 128 "JS3_WAIT_FINISH",
120 "JS3_WAIT_FINISH", 129 "JS4_JOBS",
121 "JS4_JOBS", 130 "JS4_TASKS",
122 "JS4_TASKS", 131 "JS4_ACTIVE",
123 "JS4_ACTIVE", 132 "",
124 "", 133 "JS4_WAIT_READ",
125 "JS4_WAIT_READ", 134 "JS4_WAIT_ISSUE",
126 "JS4_WAIT_ISSUE", 135 "JS4_WAIT_DEPEND",
127 "JS4_WAIT_DEPEND", 136 "JS4_WAIT_FINISH",
128 "JS4_WAIT_FINISH", 137 "JS5_JOBS",
129 "JS5_JOBS", 138 "JS5_TASKS",
130 "JS5_TASKS", 139 "JS5_ACTIVE",
131 "JS5_ACTIVE", 140 "",
132 "", 141 "JS5_WAIT_READ",
133 "JS5_WAIT_READ", 142 "JS5_WAIT_ISSUE",
134 "JS5_WAIT_ISSUE", 143 "JS5_WAIT_DEPEND",
135 "JS5_WAIT_DEPEND", 144 "JS5_WAIT_FINISH",
136 "JS5_WAIT_FINISH", 145 "JS6_JOBS",
137 "JS6_JOBS", 146 "JS6_TASKS",
138 "JS6_TASKS", 147 "JS6_ACTIVE",
139 "JS6_ACTIVE", 148 "",
140 "", 149 "JS6_WAIT_READ",
141 "JS6_WAIT_READ", 150 "JS6_WAIT_ISSUE",
142 "JS6_WAIT_ISSUE", 151 "JS6_WAIT_DEPEND",
143 "JS6_WAIT_DEPEND", 152 "JS6_WAIT_FINISH",
144 "JS6_WAIT_FINISH", 153
145 154 /*Tiler */
146 /*Tiler*/ 155 "",
147 "", 156 "",
148 "", 157 "",
149 "", 158 "JOBS_PROCESSED",
150 "JOBS_PROCESSED", 159 "TRIANGLES",
151 "TRIANGLES", 160 "QUADS",
152 "QUADS", 161 "POLYGONS",
153 "POLYGONS", 162 "POINTS",
154 "POINTS", 163 "LINES",
155 "LINES", 164 "VCACHE_HIT",
156 "VCACHE_HIT", 165 "VCACHE_MISS",
157 "VCACHE_MISS", 166 "FRONT_FACING",
158 "FRONT_FACING", 167 "BACK_FACING",
159 "BACK_FACING", 168 "PRIM_VISIBLE",
160 "PRIM_VISIBLE", 169 "PRIM_CULLED",
161 "PRIM_CULLED", 170 "PRIM_CLIPPED",
162 "PRIM_CLIPPED", 171 "LEVEL0",
163 "LEVEL0", 172 "LEVEL1",
164 "LEVEL1", 173 "LEVEL2",
165 "LEVEL2", 174 "LEVEL3",
166 "LEVEL3", 175 "LEVEL4",
167 "LEVEL4", 176 "LEVEL5",
168 "LEVEL5", 177 "LEVEL6",
169 "LEVEL6", 178 "LEVEL7",
170 "LEVEL7", 179 "COMMAND_1",
171 "COMMAND_1", 180 "COMMAND_2",
172 "COMMAND_2", 181 "COMMAND_3",
173 "COMMAND_3", 182 "COMMAND_4",
174 "COMMAND_4", 183 "COMMAND_4_7",
175 "COMMAND_4_7", 184 "COMMAND_8_15",
176 "COMMAND_8_15", 185 "COMMAND_16_63",
177 "COMMAND_16_63", 186 "COMMAND_64",
178 "COMMAND_64", 187 "COMPRESS_IN",
179 "COMPRESS_IN", 188 "COMPRESS_OUT",
180 "COMPRESS_OUT", 189 "COMPRESS_FLUSH",
181 "COMPRESS_FLUSH", 190 "TIMESTAMPS",
182 "TIMESTAMPS", 191 "PCACHE_HIT",
183 "PCACHE_HIT", 192 "PCACHE_MISS",
184 "PCACHE_MISS", 193 "PCACHE_LINE",
185 "PCACHE_LINE", 194 "PCACHE_STALL",
186 "PCACHE_STALL", 195 "WRBUF_HIT",
187 "WRBUF_HIT", 196 "WRBUF_MISS",
188 "WRBUF_MISS", 197 "WRBUF_LINE",
189 "WRBUF_LINE", 198 "WRBUF_PARTIAL",
190 "WRBUF_PARTIAL", 199 "WRBUF_STALL",
191 "WRBUF_STALL", 200 "ACTIVE",
192 "ACTIVE", 201 "LOADING_DESC",
193 "LOADING_DESC", 202 "INDEX_WAIT",
194 "INDEX_WAIT", 203 "INDEX_RANGE_WAIT",
195 "INDEX_RANGE_WAIT", 204 "VERTEX_WAIT",
196 "VERTEX_WAIT", 205 "PCACHE_WAIT",
197 "PCACHE_WAIT", 206 "WRBUF_WAIT",
198 "WRBUF_WAIT", 207 "BUS_READ",
199 "BUS_READ", 208 "BUS_WRITE",
200 "BUS_WRITE", 209 "",
201 "", 210 "",
202 "", 211 "",
203 "", 212 "",
204 "", 213 "",
205 "", 214 "UTLB_STALL",
206 "UTLB_STALL", 215 "UTLB_REPLAY_MISS",
207 "UTLB_REPLAY_MISS", 216 "UTLB_REPLAY_FULL",
208 "UTLB_REPLAY_FULL", 217 "UTLB_NEW_MISS",
209 "UTLB_NEW_MISS", 218 "UTLB_HIT",
210 "UTLB_HIT", 219
211 220 /* Shader Core */
212 /* Shader Core */ 221 "",
213 "", 222 "",
214 "", 223 "",
215 "", 224 "SHADER_CORE_ACTIVE",
216 "SHADER_CORE_ACTIVE", 225 "FRAG_ACTIVE",
217 "FRAG_ACTIVE", 226 "FRAG_PRIMATIVES",
218 "FRAG_PRIMATIVES", 227 "FRAG_PRIMATIVES_DROPPED",
219 "FRAG_PRIMATIVES_DROPPED", 228 "FRAG_CYCLE_DESC",
220 "FRAG_CYCLE_DESC", 229 "FRAG_CYCLES_PLR",
221 "FRAG_CYCLES_PLR", 230 "FRAG_CYCLES_VERT",
222 "FRAG_CYCLES_VERT", 231 "FRAG_CYCLES_TRISETUP",
223 "FRAG_CYCLES_TRISETUP", 232 "FRAG_CYCLES_RAST",
224 "FRAG_CYCLES_RAST", 233 "FRAG_THREADS",
225 "FRAG_THREADS", 234 "FRAG_DUMMY_THREADS",
226 "FRAG_DUMMY_THREADS", 235 "FRAG_QUADS_RAST",
227 "FRAG_QUADS_RAST", 236 "FRAG_QUADS_EZS_TEST",
228 "FRAG_QUADS_EZS_TEST", 237 "FRAG_QUADS_EZS_KILLED",
229 "FRAG_QUADS_EZS_KILLED", 238 "FRAG_QUADS_LZS_TEST",
230 "FRAG_QUADS_LZS_TEST", 239 "FRAG_QUADS_LZS_KILLED",
231 "FRAG_QUADS_LZS_KILLED", 240 "FRAG_CYCLE_NO_TILE",
232 "FRAG_CYCLE_NO_TILE", 241 "FRAG_NUM_TILES",
233 "FRAG_NUM_TILES", 242 "FRAG_TRANS_ELIM",
234 "FRAG_TRANS_ELIM", 243 "COMPUTE_ACTIVE",
235 "COMPUTE_ACTIVE", 244 "COMPUTE_TASKS",
236 "COMPUTE_TASKS", 245 "COMPUTE_THREADS",
237 "COMPUTE_THREADS", 246 "COMPUTE_CYCLES_DESC",
238 "COMPUTE_CYCLES_DESC", 247 "TRIPIPE_ACTIVE",
239 "TRIPIPE_ACTIVE", 248 "ARITH_WORDS",
240 "ARITH_WORDS", 249 "ARITH_CYCLES_REG",
241 "ARITH_CYCLES_REG", 250 "ARITH_CYCLES_L0",
242 "ARITH_CYCLES_L0", 251 "ARITH_FRAG_DEPEND",
243 "ARITH_FRAG_DEPEND", 252 "LS_WORDS",
244 "LS_WORDS", 253 "LS_ISSUES",
245 "LS_ISSUES", 254 "LS_RESTARTS",
246 "LS_RESTARTS", 255 "LS_REISSUES_MISS",
247 "LS_REISSUES_MISS", 256 "LS_REISSUES_VD",
248 "LS_REISSUES_VD", 257 "LS_REISSUE_ATTRIB_MISS",
249 "LS_REISSUE_ATTRIB_MISS", 258 "LS_NO_WB",
250 "LS_NO_WB", 259 "TEX_WORDS",
251 "TEX_WORDS", 260 "TEX_BUBBLES",
252 "TEX_BUBBLES", 261 "TEX_WORDS_L0",
253 "TEX_WORDS_L0", 262 "TEX_WORDS_DESC",
254 "TEX_WORDS_DESC", 263 "TEX_THREADS",
255 "TEX_THREADS", 264 "TEX_RECIRC_FMISS",
256 "TEX_RECIRC_FMISS", 265 "TEX_RECIRC_DESC",
257 "TEX_RECIRC_DESC", 266 "TEX_RECIRC_MULTI",
258 "TEX_RECIRC_MULTI", 267 "TEX_RECIRC_PMISS",
259 "TEX_RECIRC_PMISS", 268 "TEX_RECIRC_CONF",
260 "TEX_RECIRC_CONF", 269 "LSC_READ_HITS",
261 "LSC_READ_HITS", 270 "LSC_READ_MISSES",
262 "LSC_READ_MISSES", 271 "LSC_WRITE_HITS",
263 "LSC_WRITE_HITS", 272 "LSC_WRITE_MISSES",
264 "LSC_WRITE_MISSES", 273 "LSC_ATOMIC_HITS",
265 "LSC_ATOMIC_HITS", 274 "LSC_ATOMIC_MISSES",
266 "LSC_ATOMIC_MISSES", 275 "LSC_LINE_FETCHES",
267 "LSC_LINE_FETCHES", 276 "LSC_DIRTY_LINE",
268 "LSC_DIRTY_LINE", 277 "LSC_SNOOPS",
269 "LSC_SNOOPS", 278 "AXI_TLB_STALL",
270 "AXI_TLB_STALL", 279 "AXI_TLB_MIESS",
271 "AXI_TLB_MIESS", 280 "AXI_TLB_TRANSACTION",
272 "AXI_TLB_TRANSACTION", 281 "LS_TLB_MISS",
273 "LS_TLB_MISS", 282 "LS_TLB_HIT",
274 "LS_TLB_HIT", 283 "AXI_BEATS_READ",
275 "AXI_BEATS_READ", 284 "AXI_BEATS_WRITTEN",
276 "AXI_BEATS_WRITTEN", 285
277 286 /*L2 and MMU */
278 /*L2 and MMU */ 287 "",
279 "", 288 "",
280 "", 289 "",
281 "", 290 "",
282 "", 291 "MMU_TABLE_WALK",
283 "MMU_TABLE_WALK", 292 "MMU_REPLAY_MISS",
284 "MMU_REPLAY_MISS", 293 "MMU_REPLAY_FULL",
285 "MMU_REPLAY_FULL", 294 "MMU_NEW_MISS",
286 "MMU_NEW_MISS", 295 "MMU_HIT",
287 "MMU_HIT", 296 "",
288 "", 297 "",
289 "", 298 "",
290 "", 299 "",
291 "", 300 "",
292 "", 301 "",
293 "", 302 "",
294 "", 303 "UTLB_STALL",
295 "UTLB_STALL", 304 "UTLB_REPLAY_MISS",
296 "UTLB_REPLAY_MISS", 305 "UTLB_REPLAY_FULL",
297 "UTLB_REPLAY_FULL", 306 "UTLB_NEW_MISS",
298 "UTLB_NEW_MISS", 307 "UTLB_HIT",
299 "UTLB_HIT", 308 "",
300 "", 309 "",
301 "", 310 "",
302 "", 311 "",
303 "", 312 "",
304 "", 313 "",
305 "", 314 "",
306 "", 315 "",
307 "", 316 "",
308 "", 317 "L2_WRITE_BEATS",
309 "L2_WRITE_BEATS", 318 "L2_READ_BEATS",
310 "L2_READ_BEATS", 319 "L2_ANY_LOOKUP",
311 "L2_ANY_LOOKUP", 320 "L2_READ_LOOKUP",
312 "L2_READ_LOOKUP", 321 "L2_SREAD_LOOKUP",
313 "L2_SREAD_LOOKUP", 322 "L2_READ_REPLAY",
314 "L2_READ_REPLAY", 323 "L2_READ_SNOOP",
315 "L2_READ_SNOOP", 324 "L2_READ_HIT",
316 "L2_READ_HIT", 325 "L2_CLEAN_MISS",
317 "L2_CLEAN_MISS", 326 "L2_WRITE_LOOKUP",
318 "L2_WRITE_LOOKUP", 327 "L2_SWRITE_LOOKUP",
319 "L2_SWRITE_LOOKUP", 328 "L2_WRITE_REPLAY",
320 "L2_WRITE_REPLAY", 329 "L2_WRITE_SNOOP",
321 "L2_WRITE_SNOOP", 330 "L2_WRITE_HIT",
322 "L2_WRITE_HIT", 331 "L2_EXT_READ_FULL",
323 "L2_EXT_READ_FULL", 332 "L2_EXT_READ_HALF",
324 "L2_EXT_READ_HALF", 333 "L2_EXT_WRITE_FULL",
325 "L2_EXT_WRITE_FULL", 334 "L2_EXT_WRITE_HALF",
326 "L2_EXT_WRITE_HALF", 335 "L2_EXT_READ",
327 "L2_EXT_READ", 336 "L2_EXT_READ_LINE",
328 "L2_EXT_READ_LINE", 337 "L2_EXT_WRITE",
329 "L2_EXT_WRITE", 338 "L2_EXT_WRITE_LINE",
330 "L2_EXT_WRITE_LINE", 339 "L2_EXT_WRITE_SMALL",
331 "L2_EXT_WRITE_SMALL", 340 "L2_EXT_BARRIER",
332 "L2_EXT_BARRIER", 341 "L2_EXT_AR_STALL",
333 "L2_EXT_AR_STALL", 342 "L2_EXT_R_BUF_FULL",
334 "L2_EXT_R_BUF_FULL", 343 "L2_EXT_RD_BUF_FULL",
335 "L2_EXT_RD_BUF_FULL", 344 "L2_EXT_R_RAW",
336 "L2_EXT_R_RAW", 345 "L2_EXT_W_STALL",
337 "L2_EXT_W_STALL", 346 "L2_EXT_W_BUF_FULL",
338 "L2_EXT_W_BUF_FULL", 347 "L2_EXT_R_W_HAZARD",
339 "L2_EXT_R_W_HAZARD", 348 "L2_TAG_HAZARD",
340 "L2_TAG_HAZARD", 349 "L2_SNOOP_FULL",
341 "L2_SNOOP_FULL", 350 "L2_REPLAY_FULL"
342 "L2_REPLAY_FULL"
343}; 351};
344 352
345#define NUMBER_OF_HARDWARE_COUNTERS (sizeof(hardware_counter_names) / sizeof(hardware_counter_names[0])) 353#define NUMBER_OF_HARDWARE_COUNTERS (sizeof(hardware_counter_names) / sizeof(hardware_counter_names[0]))
@@ -392,8 +400,8 @@ static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2];
392#define SYMBOL_CLEANUP(FUNCTION) \ 400#define SYMBOL_CLEANUP(FUNCTION) \
393 if(FUNCTION ## _symbol) \ 401 if(FUNCTION ## _symbol) \
394 { \ 402 { \
395 symbol_put(FUNCTION); \ 403 symbol_put(FUNCTION); \
396 FUNCTION ## _symbol = NULL; \ 404 FUNCTION ## _symbol = NULL; \
397 } 405 }
398 406
399/** 407/**
@@ -442,17 +450,15 @@ static void clean_symbols(void)
442 * 450 *
443 * Note that this function has been separated out here to allow it to be tested. 451 * Note that this function has been separated out here to allow it to be tested.
444 */ 452 */
445static int is_read_scheduled(const struct timespec *current_time, u32* prev_time_s, s32* next_read_time_ns) 453static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns)
446{ 454{
447 /* If the current ns count rolls over a second, roll the next read time too. */ 455 /* If the current ns count rolls over a second, roll the next read time too. */
448 if(current_time->tv_sec != *prev_time_s) 456 if (current_time->tv_sec != *prev_time_s) {
449 {
450 *next_read_time_ns = *next_read_time_ns - NSEC_PER_SEC; 457 *next_read_time_ns = *next_read_time_ns - NSEC_PER_SEC;
451 } 458 }
452 459
453 /* Abort the read if the next read time has not arrived. */ 460 /* Abort the read if the next read time has not arrived. */
454 if(current_time->tv_nsec < *next_read_time_ns) 461 if (current_time->tv_nsec < *next_read_time_ns) {
455 {
456 return 0; 462 return 0;
457 } 463 }
458 464
@@ -465,154 +471,146 @@ static int is_read_scheduled(const struct timespec *current_time, u32* prev_time
465 471
466static int start(void) 472static int start(void)
467{ 473{
468 kbase_uk_hwcnt_setup setup; 474 kbase_uk_hwcnt_setup setup;
469 mali_error err; 475 mali_error err;
470 int cnt; 476 int cnt;
471 u16 bitmask[] = {0, 0, 0, 0}; 477 u16 bitmask[] = { 0, 0, 0, 0 };
472 478
473 /* Setup HW counters */ 479 /* Setup HW counters */
474 num_hardware_counters_enabled = 0; 480 num_hardware_counters_enabled = 0;
475 481
476 if(NUMBER_OF_HARDWARE_COUNTERS != 256) 482 if (NUMBER_OF_HARDWARE_COUNTERS != 256) {
477 { 483 pr_debug("Unexpected number of hardware counters defined: expecting 256, got %d\n", NUMBER_OF_HARDWARE_COUNTERS);
478 pr_debug("Unexpected number of hardware counters defined: expecting 256, got %d\n", NUMBER_OF_HARDWARE_COUNTERS); 484 }
479 } 485
480 486 /* Calculate enable bitmasks based on counters_enabled array */
481 /* Calculate enable bitmasks based on counters_enabled array */ 487 for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) {
482 for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) 488 const mali_counter *counter = &counters[cnt];
483 { 489 if (counter->enabled) {
484 const mali_counter *counter = &counters[cnt]; 490 int block = GET_HW_BLOCK(cnt);
485 if (counter->enabled) 491 int enable_bit = GET_COUNTER_OFFSET(cnt) / 4;
486 { 492 bitmask[block] |= (1 << enable_bit);
487 int block = GET_HW_BLOCK(cnt); 493 pr_debug("gator: Mali-T6xx: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt);
488 int enable_bit = GET_COUNTER_OFFSET(cnt) / 4; 494 num_hardware_counters_enabled++;
489 bitmask[block] |= (1 << enable_bit); 495 }
490 pr_debug("gator: Mali-T6xx: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt); 496 }
491 num_hardware_counters_enabled++; 497
492 } 498 /* Create a kbase context for HW counters */
493 } 499 if (num_hardware_counters_enabled > 0) {
494 500 if (init_symbols() > 0) {
495 /* Create a kbase context for HW counters */ 501 clean_symbols();
496 if (num_hardware_counters_enabled > 0) 502 /* No Mali driver code entrypoints found - not a fault. */
497 { 503 return 0;
498 if(init_symbols() > 0) 504 }
499 { 505
500 clean_symbols(); 506 kbdevice = kbase_find_device_symbol(-1);
501 /* No Mali driver code entrypoints found - not a fault. */ 507
502 return 0; 508 /* If we already got a context, fail */
503 } 509 if (kbcontext) {
504 510 pr_debug("gator: Mali-T6xx: error context already present\n");
505 kbdevice = kbase_find_device_symbol(-1); 511 goto out;
506 512 }
507 /* If we already got a context, fail */ 513
508 if (kbcontext) { 514 /* kbcontext will only be valid after all the Mali symbols are loaded successfully */
509 pr_debug("gator: Mali-T6xx: error context already present\n"); 515 kbcontext = kbase_create_context_symbol(kbdevice);
510 goto out; 516 if (!kbcontext) {
511 } 517 pr_debug("gator: Mali-T6xx: error creating kbase context\n");
512 518 goto out;
513 /* kbcontext will only be valid after all the Mali symbols are loaded successfully */ 519 }
514 kbcontext = kbase_create_context_symbol(kbdevice); 520
515 if (!kbcontext) 521 /*
516 { 522 * The amount of memory needed to store the dump (bytes)
517 pr_debug("gator: Mali-T6xx: error creating kbase context\n"); 523 * DUMP_SIZE = number of core groups
518 goto out; 524 * * number of blocks (always 8 for midgard)
519 } 525 * * number of counters per block (always 64 for midgard)
520 526 * * number of bytes per counter (always 4 in midgard)
521 /* 527 * For a Mali-T6xx with a single core group = 1 * 8 * 64 * 4
522 * The amount of memory needed to store the dump (bytes) 528 */
523 * DUMP_SIZE = number of core groups 529 kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 2048);
524 * * number of blocks (always 8 for midgard) 530 if (!kernel_dump_buffer) {
525 * * number of counters per block (always 64 for midgard) 531 pr_debug("gator: Mali-T6xx: error trying to allocate va\n");
526 * * number of bytes per counter (always 4 in midgard) 532 goto destroy_context;
527 * For a Mali-T6xx with a single core group = 1 * 8 * 64 * 4 533 }
528 */ 534
529 kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 2048); 535 setup.dump_buffer = (uintptr_t)kernel_dump_buffer;
530 if (!kernel_dump_buffer) 536 setup.jm_bm = bitmask[JM_BLOCK];
531 { 537 setup.tiler_bm = bitmask[TILER_BLOCK];
532 pr_debug("gator: Mali-T6xx: error trying to allocate va\n"); 538 setup.shader_bm = bitmask[SHADER_BLOCK];
533 goto destroy_context; 539 setup.mmu_l2_bm = bitmask[MMU_BLOCK];
534 } 540 /* These counters do not exist on Mali-T60x */
535 541 setup.l3_cache_bm = 0;
536 setup.dump_buffer = (uintptr_t)kernel_dump_buffer; 542
537 setup.jm_bm = bitmask[JM_BLOCK]; 543 /* Use kbase API to enable hardware counters and provide dump buffer */
538 setup.tiler_bm = bitmask[TILER_BLOCK]; 544 err = kbase_instr_hwcnt_enable_symbol(kbcontext, &setup);
539 setup.shader_bm = bitmask[SHADER_BLOCK]; 545 if (err != MALI_ERROR_NONE) {
540 setup.mmu_l2_bm = bitmask[MMU_BLOCK]; 546 pr_debug("gator: Mali-T6xx: can't setup hardware counters\n");
541 /* These counters do not exist on Mali-T60x */ 547 goto free_buffer;
542 setup.l3_cache_bm = 0; 548 }
543 549 pr_debug("gator: Mali-T6xx: hardware counters enabled\n");
544 /* Use kbase API to enable hardware counters and provide dump buffer */ 550 kbase_instr_hwcnt_clear_symbol(kbcontext);
545 err = kbase_instr_hwcnt_enable_symbol(kbcontext, &setup); 551 pr_debug("gator: Mali-T6xx: hardware counters cleared \n");
546 if (err != MALI_ERROR_NONE) 552
547 { 553 kbase_device_busy = false;
548 pr_debug("gator: Mali-T6xx: can't setup hardware counters\n"); 554 }
549 goto free_buffer; 555
550 } 556 return 0;
551 pr_debug("gator: Mali-T6xx: hardware counters enabled\n"); 557
552 kbase_instr_hwcnt_clear_symbol(kbcontext); 558free_buffer:
553 pr_debug("gator: Mali-T6xx: hardware counters cleared \n");
554
555 kbase_device_busy = false;
556 }
557
558 return 0;
559
560 free_buffer:
561 kbase_va_free_symbol(kbcontext, kernel_dump_buffer); 559 kbase_va_free_symbol(kbcontext, kernel_dump_buffer);
562 560
563 destroy_context: 561destroy_context:
564 kbase_destroy_context_symbol(kbcontext); 562 kbase_destroy_context_symbol(kbcontext);
565 563
566 out: 564out:
567 clean_symbols(); 565 clean_symbols();
568 return -1; 566 return -1;
569} 567}
570 568
571static void stop(void) { 569static void stop(void)
572 unsigned int cnt; 570{
573 kbase_context *temp_kbcontext; 571 unsigned int cnt;
572 kbase_context *temp_kbcontext;
574 573
575 pr_debug("gator: Mali-T6xx: stop\n"); 574 pr_debug("gator: Mali-T6xx: stop\n");
576 575
577 /* Set all counters as disabled */ 576 /* Set all counters as disabled */
578 for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) { 577 for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) {
579 counters[cnt].enabled = 0; 578 counters[cnt].enabled = 0;
580 } 579 }
581 580
582 /* Destroy the context for HW counters */ 581 /* Destroy the context for HW counters */
583 if (num_hardware_counters_enabled > 0 && kbcontext != NULL) 582 if (num_hardware_counters_enabled > 0 && kbcontext != NULL) {
584 { 583 /*
585 /* 584 * Set the global variable to NULL before destroying it, because
586 * Set the global variable to NULL before destroying it, because 585 * other function will check this before using it.
587 * other function will check this before using it. 586 */
588 */ 587 temp_kbcontext = kbcontext;
589 temp_kbcontext = kbcontext; 588 kbcontext = NULL;
590 kbcontext = NULL;
591 589
592 kbase_instr_hwcnt_disable_symbol(temp_kbcontext); 590 kbase_instr_hwcnt_disable_symbol(temp_kbcontext);
593 kbase_va_free_symbol(temp_kbcontext, kernel_dump_buffer); 591 kbase_va_free_symbol(temp_kbcontext, kernel_dump_buffer);
594 kbase_destroy_context_symbol(temp_kbcontext); 592 kbase_destroy_context_symbol(temp_kbcontext);
595 593
596 pr_debug("gator: Mali-T6xx: hardware counters stopped\n"); 594 pr_debug("gator: Mali-T6xx: hardware counters stopped\n");
597 595
598 clean_symbols(); 596 clean_symbols();
599 } 597 }
600} 598}
601 599
602static int read(int **buffer) { 600static int read(int **buffer)
603 int cnt; 601{
604 int len = 0; 602 int cnt;
605 u32 value = 0; 603 int len = 0;
606 mali_bool success; 604 u32 value = 0;
605 mali_bool success;
607 606
608 struct timespec current_time; 607 struct timespec current_time;
609 static u32 prev_time_s = 0; 608 static u32 prev_time_s = 0;
610 static s32 next_read_time_ns = 0; 609 static s32 next_read_time_ns = 0;
611 610
612 if (smp_processor_id()!=0) 611 if (smp_processor_id() != 0) {
613 { 612 return 0;
614 return 0; 613 }
615 }
616 614
617 getnstimeofday(&current_time); 615 getnstimeofday(&current_time);
618 616
@@ -620,114 +618,105 @@ static int read(int **buffer) {
620 * Discard reads unless a respectable time has passed. This reduces the load on the GPU without sacrificing 618 * Discard reads unless a respectable time has passed. This reduces the load on the GPU without sacrificing
621 * accuracy on the Streamline display. 619 * accuracy on the Streamline display.
622 */ 620 */
623 if(!is_read_scheduled(&current_time, &prev_time_s, &next_read_time_ns)) 621 if (!is_read_scheduled(&current_time, &prev_time_s, &next_read_time_ns)) {
624 {
625 return 0; 622 return 0;
626 } 623 }
627 624
628 /* 625 /*
629 * Report the HW counters 626 * Report the HW counters
630 * Only process hardware counters if at least one of the hardware counters is enabled. 627 * Only process hardware counters if at least one of the hardware counters is enabled.
631 */ 628 */
632 if (num_hardware_counters_enabled > 0) 629 if (num_hardware_counters_enabled > 0) {
633 { 630 const unsigned int vithar_blocks[] = {
634 const unsigned int vithar_blocks[] = { 631 0x700, /* VITHAR_JOB_MANAGER, Block 0 */
635 0x700, /* VITHAR_JOB_MANAGER, Block 0 */ 632 0x400, /* VITHAR_TILER, Block 1 */
636 0x400, /* VITHAR_TILER, Block 1 */ 633 0x000, /* VITHAR_SHADER_CORE, Block 2 */
637 0x000, /* VITHAR_SHADER_CORE, Block 2 */ 634 0x500 /* VITHAR_MEMORY_SYSTEM, Block 3 */
638 0x500 /* VITHAR_MEMORY_SYSTEM, Block 3 */ 635 };
639 }; 636
640 637 if (!kbcontext) {
641 if (!kbcontext) 638 return -1;
642 { 639 }
643 return -1; 640
644 } 641 /* Mali symbols can be called safely since a kbcontext is valid */
645 642 if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE) {
646 /* Mali symbols can be called safely since a kbcontext is valid */ 643 kbase_device_busy = false;
647 if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE) 644
648 { 645 if (success == MALI_TRUE) {
649 kbase_device_busy = false; 646 for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) {
650 647 const mali_counter *counter = &counters[cnt];
651 if (success == MALI_TRUE) 648 if (counter->enabled) {
652 { 649 const int block = GET_HW_BLOCK(cnt);
653 for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) 650 const int counter_offset = GET_COUNTER_OFFSET(cnt);
654 { 651 const u32 *counter_block = (u32 *) ((uintptr_t)kernel_dump_buffer + vithar_blocks[block]);
655 const mali_counter *counter = &counters[cnt]; 652 const u32 *counter_address = counter_block + counter_offset;
656 if (counter->enabled) 653
657 { 654 value = *counter_address;
658 const int block = GET_HW_BLOCK(cnt); 655
659 const int counter_offset = GET_COUNTER_OFFSET(cnt); 656 if (block == SHADER_BLOCK) {
660 const u32 *counter_block = (u32 *)((uintptr_t)kernel_dump_buffer + vithar_blocks[block]); 657 /* (counter_address + 0x000) has already been accounted-for above. */
661 const u32 *counter_address = counter_block + counter_offset; 658 value += *(counter_address + 0x100);
662 659 value += *(counter_address + 0x200);
663 value = *counter_address; 660 value += *(counter_address + 0x300);
664 661 }
665 if(block == SHADER_BLOCK){ 662
666 /* (counter_address + 0x000) has already been accounted-for above. */ 663 counter_dump[len++] = counter->key;
667 value += *(counter_address + 0x100); 664 counter_dump[len++] = value;
668 value += *(counter_address + 0x200); 665 }
669 value += *(counter_address + 0x300); 666 }
670 } 667 }
671 668 }
672 counter_dump[len++] = counter->key; 669
673 counter_dump[len++] = value; 670 if (!kbase_device_busy) {
674 } 671 kbase_device_busy = true;
675 } 672 kbase_instr_hwcnt_dump_irq_symbol(kbcontext);
676 } 673 }
677 } 674 }
678 675
679 if (! kbase_device_busy) 676 /* Update the buffer */
680 { 677 if (buffer) {
681 kbase_device_busy = true; 678 *buffer = (int *)counter_dump;
682 kbase_instr_hwcnt_dump_irq_symbol(kbcontext); 679 }
683 } 680
684 } 681 return len;
685
686 /* Update the buffer */
687 if (buffer) {
688 *buffer = (int*) counter_dump;
689 }
690
691 return len;
692} 682}
693 683
694static int create_files(struct super_block *sb, struct dentry *root) 684static int create_files(struct super_block *sb, struct dentry *root)
695{ 685{
696 unsigned int event; 686 unsigned int event;
697 /* 687 /*
698 * Create the filesystem for all events 688 * Create the filesystem for all events
699 */ 689 */
700 int counter_index = 0; 690 int counter_index = 0;
701 const char* mali_name = gator_mali_get_mali_name(); 691 const char *mali_name = gator_mali_get_mali_name();
702 692
703 for (event = 0; event < NUMBER_OF_HARDWARE_COUNTERS; event++) 693 for (event = 0; event < NUMBER_OF_HARDWARE_COUNTERS; event++) {
704 { 694 if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event]) != 0)
705 if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event]) != 0) 695 return -1;
706 return -1; 696 counter_index++;
707 counter_index++; 697 }
708 } 698
709 699 return 0;
710 return 0;
711} 700}
712 701
713static struct gator_interface gator_events_mali_t6xx_interface = { 702static struct gator_interface gator_events_mali_t6xx_interface = {
714 .create_files = create_files, 703 .create_files = create_files,
715 .start = start, 704 .start = start,
716 .stop = stop, 705 .stop = stop,
717 .read = read 706 .read = read
718}; 707};
719 708
720int gator_events_mali_t6xx_hw_init(void) 709int gator_events_mali_t6xx_hw_init(void)
721{ 710{
722 pr_debug("gator: Mali-T6xx: sw_counters init\n"); 711 pr_debug("gator: Mali-T6xx: sw_counters init\n");
723 712
724#if GATOR_TEST 713#if GATOR_TEST
725 test_all_is_read_scheduled(); 714 test_all_is_read_scheduled();
726#endif 715#endif
727 716
728 gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS); 717 gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS);
729 718
730 return gator_events_install(&gator_events_mali_t6xx_interface); 719 return gator_events_install(&gator_events_mali_t6xx_interface);
731} 720}
732 721
733gator_events_init(gator_events_mali_t6xx_hw_init); 722gator_events_init(gator_events_mali_t6xx_hw_init);
diff --git a/driver/gator_events_mali_t6xx_hw_test.c b/driver/gator_events_mali_t6xx_hw_test.c
index 2a35e77..eb77110 100644
--- a/driver/gator_events_mali_t6xx_hw_test.c
+++ b/driver/gator_events_mali_t6xx_hw_test.c
@@ -11,7 +11,7 @@
11 * Test functions for mali_t600_hw code. 11 * Test functions for mali_t600_hw code.
12 */ 12 */
13 13
14static int is_read_scheduled(const struct timespec *current_time, u32* prev_time_s, s32* next_read_time_ns); 14static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns);
15 15
16static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int expected_result, s32 expected_next_ns) 16static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int expected_result, s32 expected_next_ns)
17{ 17{
@@ -22,14 +22,12 @@ static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int ex
22 current_time.tv_sec = s; 22 current_time.tv_sec = s;
23 current_time.tv_nsec = ns; 23 current_time.tv_nsec = ns;
24 24
25 if(is_read_scheduled(&current_time, &prev_time_s, &next_read_time_ns) != expected_result) 25 if (is_read_scheduled(&current_time, &prev_time_s, &next_read_time_ns) != expected_result) {
26 {
27 printk("Failed do_read(%u, %u, %u, %d): expected %d\n", s, ns, prev_s, next_ns, expected_result); 26 printk("Failed do_read(%u, %u, %u, %d): expected %d\n", s, ns, prev_s, next_ns, expected_result);
28 return 0; 27 return 0;
29 } 28 }
30 29
31 if(next_read_time_ns != expected_next_ns) 30 if (next_read_time_ns != expected_next_ns) {
32 {
33 printk("Failed: next_read_ns expected=%d, actual=%d\n", expected_next_ns, next_read_time_ns); 31 printk("Failed: next_read_ns expected=%d, actual=%d\n", expected_next_ns, next_read_time_ns);
34 return 0; 32 return 0;
35 } 33 }
@@ -44,14 +42,14 @@ static void test_all_is_read_scheduled(void)
44 42
45 printk("gator: running tests on %s\n", __FILE__); 43 printk("gator: running tests on %s\n", __FILE__);
46 44
47 n_tests_passed += test_is_read_scheduled(0,0,0,0, 1, READ_INTERVAL_NSEC); /* Null time */ 45 n_tests_passed += test_is_read_scheduled(0, 0, 0, 0, 1, READ_INTERVAL_NSEC); /* Null time */
48 n_tests_passed += test_is_read_scheduled(100,1000,0,0, 1, READ_INTERVAL_NSEC + 1000); /* Initial values */ 46 n_tests_passed += test_is_read_scheduled(100, 1000, 0, 0, 1, READ_INTERVAL_NSEC + 1000); /* Initial values */
49 47
50 n_tests_passed += test_is_read_scheduled(100, HIGHEST_NS, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500); 48 n_tests_passed += test_is_read_scheduled(100, HIGHEST_NS, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500);
51 n_tests_passed += test_is_read_scheduled(101, 0001, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500 - NSEC_PER_SEC); 49 n_tests_passed += test_is_read_scheduled(101, 0001, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500 - NSEC_PER_SEC);
52 n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500 - NSEC_PER_SEC, 1, 600 + READ_INTERVAL_NSEC); 50 n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500 - NSEC_PER_SEC, 1, 600 + READ_INTERVAL_NSEC);
53 51
54 n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500, 1, 600 + READ_INTERVAL_NSEC); 52 n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500, 1, 600 + READ_INTERVAL_NSEC);
55 53
56 printk("gator: %d tests passed\n", n_tests_passed); 54 printk("gator: %d tests passed\n", n_tests_passed);
57} 55}
diff --git a/driver/gator_events_meminfo.c b/driver/gator_events_meminfo.c
index b962641..fd063b2 100644
--- a/driver/gator_events_meminfo.c
+++ b/driver/gator_events_meminfo.c
@@ -31,22 +31,25 @@ static struct timer_list meminfo_wake_up_timer;
31static void meminfo_wake_up_handler(unsigned long unused_data); 31static void meminfo_wake_up_handler(unsigned long unused_data);
32 32
33#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) 33#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
34GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order)) { 34GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order))
35#else 35#else
36GATOR_DEFINE_PROBE(mm_page_free, TP_PROTO(struct page *page, unsigned int order)) { 36GATOR_DEFINE_PROBE(mm_page_free, TP_PROTO(struct page *page, unsigned int order))
37#endif 37#endif
38{
38 mem_event++; 39 mem_event++;
39} 40}
40 41
41#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) 42#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
42GATOR_DEFINE_PROBE(mm_pagevec_free, TP_PROTO(struct page *page, int cold)) { 43GATOR_DEFINE_PROBE(mm_pagevec_free, TP_PROTO(struct page *page, int cold))
43#else 44#else
44GATOR_DEFINE_PROBE(mm_page_free_batched, TP_PROTO(struct page *page, int cold)) { 45GATOR_DEFINE_PROBE(mm_page_free_batched, TP_PROTO(struct page *page, int cold))
45#endif 46#endif
47{
46 mem_event++; 48 mem_event++;
47} 49}
48 50
49GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype)) { 51GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype))
52{
50 mem_event++; 53 mem_event++;
51} 54}
52 55
@@ -233,4 +236,5 @@ int gator_events_meminfo_init(void)
233 236
234 return gator_events_install(&gator_events_meminfo_interface); 237 return gator_events_install(&gator_events_meminfo_interface);
235} 238}
239
236gator_events_init(gator_events_meminfo_init); 240gator_events_init(gator_events_meminfo_init);
diff --git a/driver/gator_events_mmaped.c b/driver/gator_events_mmaped.c
index 1be6e66..c4cb44f 100644
--- a/driver/gator_events_mmaped.c
+++ b/driver/gator_events_mmaped.c
@@ -45,7 +45,7 @@ static s64 prev_time;
45 45
46/* Adds mmaped_cntX directories and enabled, event, and key files to /dev/gator/events */ 46/* Adds mmaped_cntX directories and enabled, event, and key files to /dev/gator/events */
47static int gator_events_mmaped_create_files(struct super_block *sb, 47static int gator_events_mmaped_create_files(struct super_block *sb,
48 struct dentry *root) 48 struct dentry *root)
49{ 49{
50 int i; 50 int i;
51 51
@@ -58,11 +58,11 @@ static int gator_events_mmaped_create_files(struct super_block *sb,
58 if (WARN_ON(!dir)) 58 if (WARN_ON(!dir))
59 return -1; 59 return -1;
60 gatorfs_create_ulong(sb, dir, "enabled", 60 gatorfs_create_ulong(sb, dir, "enabled",
61 &mmaped_counters[i].enabled); 61 &mmaped_counters[i].enabled);
62 gatorfs_create_ulong(sb, dir, "event", 62 gatorfs_create_ulong(sb, dir, "event",
63 &mmaped_counters[i].event); 63 &mmaped_counters[i].event);
64 gatorfs_create_ro_ulong(sb, dir, "key", 64 gatorfs_create_ro_ulong(sb, dir, "key",
65 &mmaped_counters[i].key); 65 &mmaped_counters[i].key);
66 } 66 }
67 67
68 return 0; 68 return 0;
@@ -73,7 +73,7 @@ static int gator_events_mmaped_start(void)
73#ifdef TODO 73#ifdef TODO
74 for (i = 0; i < MMAPED_COUNTERS_NUM; i++) 74 for (i = 0; i < MMAPED_COUNTERS_NUM; i++)
75 writel(mmaped_counters[i].event, 75 writel(mmaped_counters[i].event,
76 mmaped_base + COUNTERS_CONFIG_OFFSET[i]); 76 mmaped_base + COUNTERS_CONFIG_OFFSET[i]);
77 77
78 writel(ENABLED, COUNTERS_CONTROL_OFFSET); 78 writel(ENABLED, COUNTERS_CONTROL_OFFSET);
79#endif 79#endif
@@ -102,7 +102,7 @@ static int mmaped_simulate(int counter, int delta_in_us)
102 int result = 0; 102 int result = 0;
103 103
104 switch (counter) { 104 switch (counter) {
105 case 0: /* sort-of-sine */ 105 case 0: /* sort-of-sine */
106 { 106 {
107 static int t = 0; 107 static int t = 0;
108 int x; 108 int x;
@@ -123,7 +123,7 @@ static int mmaped_simulate(int counter, int delta_in_us)
123 result = 1922 - result; 123 result = 1922 - result;
124 } 124 }
125 break; 125 break;
126 case 1: /* triangle */ 126 case 1: /* triangle */
127 { 127 {
128 static int v, d = 1; 128 static int v, d = 1;
129 129
@@ -139,7 +139,7 @@ static int mmaped_simulate(int counter, int delta_in_us)
139 result = v; 139 result = v;
140 } 140 }
141 break; 141 break;
142 case 2: /* PWM signal */ 142 case 2: /* PWM signal */
143 { 143 {
144 static int t, dc, x; 144 static int t, dc, x;
145 145
@@ -149,7 +149,7 @@ static int mmaped_simulate(int counter, int delta_in_us)
149 if (x / 1000000 != (x + delta_in_us) / 1000000) 149 if (x / 1000000 != (x + delta_in_us) / 1000000)
150 dc = (dc + 100000) % 1000000; 150 dc = (dc + 100000) % 1000000;
151 x += delta_in_us; 151 x += delta_in_us;
152 152
153 result = t < dc ? 0 : 10; 153 result = t < dc ? 0 : 10;
154 } 154 }
155 break; 155 break;
@@ -173,7 +173,7 @@ static int gator_events_mmaped_read(int **buffer)
173 if (smp_processor_id()) 173 if (smp_processor_id())
174 return 0; 174 return 0;
175 175
176#ifndef TODO 176#ifndef TODO
177 getnstimeofday(&ts); 177 getnstimeofday(&ts);
178 time = timespec_to_ns(&ts); 178 time = timespec_to_ns(&ts);
179 delta_in_us = (int)(time - prev_time) / 1000; 179 delta_in_us = (int)(time - prev_time) / 1000;
@@ -184,15 +184,16 @@ static int gator_events_mmaped_read(int **buffer)
184 if (mmaped_counters[i].enabled) { 184 if (mmaped_counters[i].enabled) {
185 mmaped_buffer[len++] = mmaped_counters[i].key; 185 mmaped_buffer[len++] = mmaped_counters[i].key;
186#ifdef TODO 186#ifdef TODO
187 mmaped_buffer[len++] = readl(mmaped_base + 187 mmaped_buffer[len++] =
188 COUNTERS_VALUE_OFFSET[i]); 188 readl(mmaped_base + COUNTERS_VALUE_OFFSET[i]);
189#else 189#else
190 mmaped_buffer[len++] = mmaped_simulate( 190 mmaped_buffer[len++] =
191 mmaped_counters[i].event, delta_in_us); 191 mmaped_simulate(mmaped_counters[i].event,
192 delta_in_us);
192#endif 193#endif
193 } 194 }
194 } 195 }
195 196
196 if (buffer) 197 if (buffer)
197 *buffer = mmaped_buffer; 198 *buffer = mmaped_buffer;
198 199
@@ -214,7 +215,7 @@ int __init gator_events_mmaped_init(void)
214#ifdef TODO 215#ifdef TODO
215 mmaped_base = ioremap(COUNTERS_PHYS_ADDR, SZ_4K); 216 mmaped_base = ioremap(COUNTERS_PHYS_ADDR, SZ_4K);
216 if (!mmaped_base) 217 if (!mmaped_base)
217 return -ENOMEM; 218 return -ENOMEM;
218#endif 219#endif
219 220
220 for (i = 0; i < MMAPED_COUNTERS_NUM; i++) { 221 for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
@@ -224,4 +225,5 @@ int __init gator_events_mmaped_init(void)
224 225
225 return gator_events_install(&gator_events_mmaped_interface); 226 return gator_events_install(&gator_events_mmaped_interface);
226} 227}
228
227gator_events_init(gator_events_mmaped_init); 229gator_events_init(gator_events_mmaped_init);
diff --git a/driver/gator_events_net.c b/driver/gator_events_net.c
index 31cc3ef..b6ce06a 100644
--- a/driver/gator_events_net.c
+++ b/driver/gator_events_net.c
@@ -26,7 +26,8 @@ static int netGet[TOTALNET * 4];
26static struct timer_list net_wake_up_timer; 26static struct timer_list net_wake_up_timer;
27 27
28// Must be run in process context as the kernel function dev_get_stats() can sleep 28// Must be run in process context as the kernel function dev_get_stats() can sleep
29static void get_network_stats(struct work_struct *wsptr) { 29static void get_network_stats(struct work_struct *wsptr)
30{
30 int rx = 0, tx = 0; 31 int rx = 0, tx = 0;
31 struct net_device *dev; 32 struct net_device *dev;
32 33
@@ -43,6 +44,7 @@ static void get_network_stats(struct work_struct *wsptr) {
43 rx_total = rx; 44 rx_total = rx;
44 tx_total = tx; 45 tx_total = tx;
45} 46}
47
46DECLARE_WORK(wq_get_stats, get_network_stats); 48DECLARE_WORK(wq_get_stats, get_network_stats);
47 49
48static void net_wake_up_handler(unsigned long unused_data) 50static void net_wake_up_handler(unsigned long unused_data)
@@ -129,7 +131,7 @@ static int gator_events_net_read(int **buffer)
129 if (netrx_enabled && last_rx_delta != rx_delta) { 131 if (netrx_enabled && last_rx_delta != rx_delta) {
130 last_rx_delta = rx_delta; 132 last_rx_delta = rx_delta;
131 netGet[len++] = netrx_key; 133 netGet[len++] = netrx_key;
132 netGet[len++] = 0; // indicates to Streamline that rx_delta bytes were transmitted now, not since the last message 134 netGet[len++] = 0; // indicates to Streamline that rx_delta bytes were transmitted now, not since the last message
133 netGet[len++] = netrx_key; 135 netGet[len++] = netrx_key;
134 netGet[len++] = rx_delta; 136 netGet[len++] = rx_delta;
135 } 137 }
@@ -137,7 +139,7 @@ static int gator_events_net_read(int **buffer)
137 if (nettx_enabled && last_tx_delta != tx_delta) { 139 if (nettx_enabled && last_tx_delta != tx_delta) {
138 last_tx_delta = tx_delta; 140 last_tx_delta = tx_delta;
139 netGet[len++] = nettx_key; 141 netGet[len++] = nettx_key;
140 netGet[len++] = 0; // indicates to Streamline that tx_delta bytes were transmitted now, not since the last message 142 netGet[len++] = 0; // indicates to Streamline that tx_delta bytes were transmitted now, not since the last message
141 netGet[len++] = nettx_key; 143 netGet[len++] = nettx_key;
142 netGet[len++] = tx_delta; 144 netGet[len++] = tx_delta;
143 } 145 }
@@ -165,4 +167,5 @@ int gator_events_net_init(void)
165 167
166 return gator_events_install(&gator_events_net_interface); 168 return gator_events_install(&gator_events_net_interface);
167} 169}
170
168gator_events_init(gator_events_net_init); 171gator_events_init(gator_events_net_init);
diff --git a/driver/gator_events_perf_pmu.c b/driver/gator_events_perf_pmu.c
index e025155..ce3a40f 100644
--- a/driver/gator_events_perf_pmu.c
+++ b/driver/gator_events_perf_pmu.c
@@ -45,7 +45,7 @@ static int gator_events_perf_pmu_create_files(struct super_block *sb, struct den
45 if (i == 0) { 45 if (i == 0) {
46 snprintf(buf, sizeof buf, "%s_ccnt", pmnc_name); 46 snprintf(buf, sizeof buf, "%s_ccnt", pmnc_name);
47 } else { 47 } else {
48 snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i-1); 48 snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i - 1);
49 } 49 }
50 dir = gatorfs_mkdir(sb, root, buf); 50 dir = gatorfs_mkdir(sb, root, buf);
51 if (!dir) { 51 if (!dir) {
@@ -80,13 +80,13 @@ static void dummy_handler(struct perf_event *event, struct perf_sample_data *dat
80// Required as perf_event_create_kernel_counter() requires an overflow handler, even though all we do is poll 80// Required as perf_event_create_kernel_counter() requires an overflow handler, even though all we do is poll
81} 81}
82 82
83static int gator_events_perf_pmu_online(int** buffer) 83static int gator_events_perf_pmu_online(int **buffer)
84{ 84{
85 int cnt, len = 0, cpu = smp_processor_id(); 85 int cnt, len = 0, cpu = smp_processor_id();
86 86
87 // read the counters and toss the invalid data, return zero instead 87 // read the counters and toss the invalid data, return zero instead
88 for (cnt = 0; cnt < pmnc_counters; cnt++) { 88 for (cnt = 0; cnt < pmnc_counters; cnt++) {
89 struct perf_event * ev = per_cpu(pevent, cpu)[cnt]; 89 struct perf_event *ev = per_cpu(pevent, cpu)[cnt];
90 if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) { 90 if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
91 ev->pmu->read(ev); 91 ev->pmu->read(ev);
92 per_cpu(perfPrev, cpu)[cnt] = per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count); 92 per_cpu(perfPrev, cpu)[cnt] = per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count);
@@ -140,7 +140,7 @@ static void gator_events_perf_pmu_online_dispatch(int cpu)
140static void gator_events_perf_pmu_offline_dispatch(int cpu) 140static void gator_events_perf_pmu_offline_dispatch(int cpu)
141{ 141{
142 int cnt; 142 int cnt;
143 struct perf_event * pe; 143 struct perf_event *pe;
144 144
145 for (cnt = 0; cnt < pmnc_counters; cnt++) { 145 for (cnt = 0; cnt < pmnc_counters; cnt++) {
146 pe = NULL; 146 pe = NULL;
@@ -177,7 +177,7 @@ static int gator_events_perf_pmu_start(void)
177 for_each_present_cpu(cpu) { 177 for_each_present_cpu(cpu) {
178 for (cnt = 0; cnt < pmnc_counters; cnt++) { 178 for (cnt = 0; cnt < pmnc_counters; cnt++) {
179 per_cpu(pevent, cpu)[cnt] = NULL; 179 per_cpu(pevent, cpu)[cnt] = NULL;
180 if (!pmnc_enabled[cnt]) // Skip disabled counters 180 if (!pmnc_enabled[cnt]) // Skip disabled counters
181 continue; 181 continue;
182 182
183 per_cpu(perfPrev, cpu)[cnt] = 0; 183 per_cpu(perfPrev, cpu)[cnt] = 0;
@@ -233,7 +233,7 @@ static int gator_events_perf_pmu_read(int **buffer)
233 int cpu = smp_processor_id(); 233 int cpu = smp_processor_id();
234 234
235 for (cnt = 0; cnt < pmnc_counters; cnt++) { 235 for (cnt = 0; cnt < pmnc_counters; cnt++) {
236 struct perf_event * ev = per_cpu(pevent, cpu)[cnt]; 236 struct perf_event *ev = per_cpu(pevent, cpu)[cnt];
237 if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) { 237 if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
238 ev->pmu->read(ev); 238 ev->pmu->read(ev);
239 per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count); 239 per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count);
@@ -268,62 +268,21 @@ static struct gator_interface gator_events_perf_pmu_interface = {
268int gator_events_perf_pmu_init(void) 268int gator_events_perf_pmu_init(void)
269{ 269{
270 unsigned int cnt; 270 unsigned int cnt;
271 271 const u32 cpuid = gator_cpuid();
272 switch (gator_cpuid()) { 272
273 case ARM1136: 273 for (cnt = 0; gator_cpus[cnt].cpuid != 0; ++cnt) {
274 case ARM1156: 274 if (gator_cpus[cnt].cpuid == cpuid) {
275 case ARM1176: 275 pmnc_name = gator_cpus[cnt].pmnc_name;
276 pmnc_name = "ARM_ARM11"; 276 pmnc_counters = gator_cpus[cnt].pmnc_counters;
277 pmnc_counters = 3; 277 ccnt = gator_cpus[cnt].ccnt;
278 ccnt = 2; 278 break;
279 break; 279 }
280 case ARM11MPCORE: 280 }
281 pmnc_name = "ARM_ARM11MPCore"; 281 if (gator_cpus[cnt].cpuid == 0) {
282 pmnc_counters = 3;
283 break;
284 case CORTEX_A5:
285 pmnc_name = "ARM_Cortex-A5";
286 pmnc_counters = 2;
287 break;
288 case CORTEX_A7:
289 pmnc_name = "ARM_Cortex-A7";
290 pmnc_counters = 4;
291 break;
292 case CORTEX_A8:
293 pmnc_name = "ARM_Cortex-A8";
294 pmnc_counters = 4;
295 break;
296 case CORTEX_A9:
297 pmnc_name = "ARM_Cortex-A9";
298 pmnc_counters = 6;
299 break;
300 case CORTEX_A15:
301 pmnc_name = "ARM_Cortex-A15";
302 pmnc_counters = 6;
303 break;
304 case SCORPION:
305 pmnc_name = "Scorpion";
306 pmnc_counters = 4;
307 break;
308 case SCORPIONMP:
309 pmnc_name = "ScorpionMP";
310 pmnc_counters = 4;
311 break;
312 case KRAITSIM:
313 case KRAIT:
314 pmnc_name = "Krait";
315 pmnc_counters = 4;
316 break;
317 case AARCH64:
318 pmnc_name = "ARM_AArch64";
319 // Copied from A15, get the correct number
320 pmnc_counters = 6;
321 break;
322 default:
323 return -1; 282 return -1;
324 } 283 }
325 284
326 pmnc_counters++; // CNT[n] + CCNT 285 pmnc_counters++; // CNT[n] + CCNT
327 286
328 for (cnt = 0; cnt < CNTMAX; cnt++) { 287 for (cnt = 0; cnt < CNTMAX; cnt++) {
329 pmnc_enabled[cnt] = 0; 288 pmnc_enabled[cnt] = 0;
diff --git a/driver/gator_events_sched.c b/driver/gator_events_sched.c
index 9bed364..ba6744d 100644
--- a/driver/gator_events_sched.c
+++ b/driver/gator_events_sched.c
@@ -111,4 +111,5 @@ int gator_events_sched_init(void)
111 111
112 return gator_events_install(&gator_events_sched_interface); 112 return gator_events_install(&gator_events_sched_interface);
113} 113}
114
114gator_events_init(gator_events_sched_init); 115gator_events_init(gator_events_sched_init);
diff --git a/driver/gator_events_scorpion.c b/driver/gator_events_scorpion.c
index ed0d8de..5ffc63a 100644
--- a/driver/gator_events_scorpion.c
+++ b/driver/gator_events_scorpion.c
@@ -20,8 +20,8 @@ static int pmnc_counters;
20#define PMNC_C (1 << 2) /* Cycle counter reset */ 20#define PMNC_C (1 << 2) /* Cycle counter reset */
21#define PMNC_D (1 << 3) /* CCNT counts every 64th cpu cycle */ 21#define PMNC_D (1 << 3) /* CCNT counts every 64th cpu cycle */
22#define PMNC_X (1 << 4) /* Export to ETM */ 22#define PMNC_X (1 << 4) /* Export to ETM */
23#define PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ 23#define PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug */
24#define PMNC_MASK 0x3f /* Mask for writable bits */ 24#define PMNC_MASK 0x3f /* Mask for writable bits */
25 25
26// ccnt reg 26// ccnt reg
27#define CCNT_REG (1 << 31) 27#define CCNT_REG (1 << 31)
@@ -37,95 +37,95 @@ static unsigned long pmnc_key[CNTMAX];
37static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt); 37static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt);
38 38
39enum scorpion_perf_types { 39enum scorpion_perf_types {
40 SCORPION_ICACHE_EXPL_INV = 0x4c, 40 SCORPION_ICACHE_EXPL_INV = 0x4c,
41 SCORPION_ICACHE_MISS = 0x4d, 41 SCORPION_ICACHE_MISS = 0x4d,
42 SCORPION_ICACHE_ACCESS = 0x4e, 42 SCORPION_ICACHE_ACCESS = 0x4e,
43 SCORPION_ICACHE_CACHEREQ_L2 = 0x4f, 43 SCORPION_ICACHE_CACHEREQ_L2 = 0x4f,
44 SCORPION_ICACHE_NOCACHE_L2 = 0x50, 44 SCORPION_ICACHE_NOCACHE_L2 = 0x50,
45 SCORPION_HIQUP_NOPED = 0x51, 45 SCORPION_HIQUP_NOPED = 0x51,
46 SCORPION_DATA_ABORT = 0x52, 46 SCORPION_DATA_ABORT = 0x52,
47 SCORPION_IRQ = 0x53, 47 SCORPION_IRQ = 0x53,
48 SCORPION_FIQ = 0x54, 48 SCORPION_FIQ = 0x54,
49 SCORPION_ALL_EXCPT = 0x55, 49 SCORPION_ALL_EXCPT = 0x55,
50 SCORPION_UNDEF = 0x56, 50 SCORPION_UNDEF = 0x56,
51 SCORPION_SVC = 0x57, 51 SCORPION_SVC = 0x57,
52 SCORPION_SMC = 0x58, 52 SCORPION_SMC = 0x58,
53 SCORPION_PREFETCH_ABORT = 0x59, 53 SCORPION_PREFETCH_ABORT = 0x59,
54 SCORPION_INDEX_CHECK = 0x5a, 54 SCORPION_INDEX_CHECK = 0x5a,
55 SCORPION_NULL_CHECK = 0x5b, 55 SCORPION_NULL_CHECK = 0x5b,
56 SCORPION_EXPL_ICIALLU = 0x5c, 56 SCORPION_EXPL_ICIALLU = 0x5c,
57 SCORPION_IMPL_ICIALLU = 0x5d, 57 SCORPION_IMPL_ICIALLU = 0x5d,
58 SCORPION_NONICIALLU_BTAC_INV = 0x5e, 58 SCORPION_NONICIALLU_BTAC_INV = 0x5e,
59 SCORPION_ICIMVAU_IMPL_ICIALLU = 0x5f, 59 SCORPION_ICIMVAU_IMPL_ICIALLU = 0x5f,
60 SCORPION_SPIPE_ONLY_CYCLES = 0x60, 60 SCORPION_SPIPE_ONLY_CYCLES = 0x60,
61 SCORPION_XPIPE_ONLY_CYCLES = 0x61, 61 SCORPION_XPIPE_ONLY_CYCLES = 0x61,
62 SCORPION_DUAL_CYCLES = 0x62, 62 SCORPION_DUAL_CYCLES = 0x62,
63 SCORPION_DISPATCH_ANY_CYCLES = 0x63, 63 SCORPION_DISPATCH_ANY_CYCLES = 0x63,
64 SCORPION_FIFO_FULLBLK_CMT = 0x64, 64 SCORPION_FIFO_FULLBLK_CMT = 0x64,
65 SCORPION_FAIL_COND_INST = 0x65, 65 SCORPION_FAIL_COND_INST = 0x65,
66 SCORPION_PASS_COND_INST = 0x66, 66 SCORPION_PASS_COND_INST = 0x66,
67 SCORPION_ALLOW_VU_CLK = 0x67, 67 SCORPION_ALLOW_VU_CLK = 0x67,
68 SCORPION_VU_IDLE = 0x68, 68 SCORPION_VU_IDLE = 0x68,
69 SCORPION_ALLOW_L2_CLK = 0x69, 69 SCORPION_ALLOW_L2_CLK = 0x69,
70 SCORPION_L2_IDLE = 0x6a, 70 SCORPION_L2_IDLE = 0x6a,
71 SCORPION_DTLB_IMPL_INV_SCTLR_DACR = 0x6b, 71 SCORPION_DTLB_IMPL_INV_SCTLR_DACR = 0x6b,
72 SCORPION_DTLB_EXPL_INV = 0x6c, 72 SCORPION_DTLB_EXPL_INV = 0x6c,
73 SCORPION_DTLB_MISS = 0x6d, 73 SCORPION_DTLB_MISS = 0x6d,
74 SCORPION_DTLB_ACCESS = 0x6e, 74 SCORPION_DTLB_ACCESS = 0x6e,
75 SCORPION_ITLB_MISS = 0x6f, 75 SCORPION_ITLB_MISS = 0x6f,
76 SCORPION_ITLB_IMPL_INV = 0x70, 76 SCORPION_ITLB_IMPL_INV = 0x70,
77 SCORPION_ITLB_EXPL_INV = 0x71, 77 SCORPION_ITLB_EXPL_INV = 0x71,
78 SCORPION_UTLB_D_MISS = 0x72, 78 SCORPION_UTLB_D_MISS = 0x72,
79 SCORPION_UTLB_D_ACCESS = 0x73, 79 SCORPION_UTLB_D_ACCESS = 0x73,
80 SCORPION_UTLB_I_MISS = 0x74, 80 SCORPION_UTLB_I_MISS = 0x74,
81 SCORPION_UTLB_I_ACCESS = 0x75, 81 SCORPION_UTLB_I_ACCESS = 0x75,
82 SCORPION_UTLB_INV_ASID = 0x76, 82 SCORPION_UTLB_INV_ASID = 0x76,
83 SCORPION_UTLB_INV_MVA = 0x77, 83 SCORPION_UTLB_INV_MVA = 0x77,
84 SCORPION_UTLB_INV_ALL = 0x78, 84 SCORPION_UTLB_INV_ALL = 0x78,
85 SCORPION_S2_HOLD_RDQ_UNAVAIL = 0x79, 85 SCORPION_S2_HOLD_RDQ_UNAVAIL = 0x79,
86 SCORPION_S2_HOLD = 0x7a, 86 SCORPION_S2_HOLD = 0x7a,
87 SCORPION_S2_HOLD_DEV_OP = 0x7b, 87 SCORPION_S2_HOLD_DEV_OP = 0x7b,
88 SCORPION_S2_HOLD_ORDER = 0x7c, 88 SCORPION_S2_HOLD_ORDER = 0x7c,
89 SCORPION_S2_HOLD_BARRIER = 0x7d, 89 SCORPION_S2_HOLD_BARRIER = 0x7d,
90 SCORPION_VIU_DUAL_CYCLE = 0x7e, 90 SCORPION_VIU_DUAL_CYCLE = 0x7e,
91 SCORPION_VIU_SINGLE_CYCLE = 0x7f, 91 SCORPION_VIU_SINGLE_CYCLE = 0x7f,
92 SCORPION_VX_PIPE_WAR_STALL_CYCLES = 0x80, 92 SCORPION_VX_PIPE_WAR_STALL_CYCLES = 0x80,
93 SCORPION_VX_PIPE_WAW_STALL_CYCLES = 0x81, 93 SCORPION_VX_PIPE_WAW_STALL_CYCLES = 0x81,
94 SCORPION_VX_PIPE_RAW_STALL_CYCLES = 0x82, 94 SCORPION_VX_PIPE_RAW_STALL_CYCLES = 0x82,
95 SCORPION_VX_PIPE_LOAD_USE_STALL = 0x83, 95 SCORPION_VX_PIPE_LOAD_USE_STALL = 0x83,
96 SCORPION_VS_PIPE_WAR_STALL_CYCLES = 0x84, 96 SCORPION_VS_PIPE_WAR_STALL_CYCLES = 0x84,
97 SCORPION_VS_PIPE_WAW_STALL_CYCLES = 0x85, 97 SCORPION_VS_PIPE_WAW_STALL_CYCLES = 0x85,
98 SCORPION_VS_PIPE_RAW_STALL_CYCLES = 0x86, 98 SCORPION_VS_PIPE_RAW_STALL_CYCLES = 0x86,
99 SCORPION_EXCEPTIONS_INV_OPERATION = 0x87, 99 SCORPION_EXCEPTIONS_INV_OPERATION = 0x87,
100 SCORPION_EXCEPTIONS_DIV_BY_ZERO = 0x88, 100 SCORPION_EXCEPTIONS_DIV_BY_ZERO = 0x88,
101 SCORPION_COND_INST_FAIL_VX_PIPE = 0x89, 101 SCORPION_COND_INST_FAIL_VX_PIPE = 0x89,
102 SCORPION_COND_INST_FAIL_VS_PIPE = 0x8a, 102 SCORPION_COND_INST_FAIL_VS_PIPE = 0x8a,
103 SCORPION_EXCEPTIONS_OVERFLOW = 0x8b, 103 SCORPION_EXCEPTIONS_OVERFLOW = 0x8b,
104 SCORPION_EXCEPTIONS_UNDERFLOW = 0x8c, 104 SCORPION_EXCEPTIONS_UNDERFLOW = 0x8c,
105 SCORPION_EXCEPTIONS_DENORM = 0x8d, 105 SCORPION_EXCEPTIONS_DENORM = 0x8d,
106#ifdef CONFIG_ARCH_MSM_SCORPIONMP 106#ifdef CONFIG_ARCH_MSM_SCORPIONMP
107 SCORPIONMP_NUM_BARRIERS = 0x8e, 107 SCORPIONMP_NUM_BARRIERS = 0x8e,
108 SCORPIONMP_BARRIER_CYCLES = 0x8f, 108 SCORPIONMP_BARRIER_CYCLES = 0x8f,
109#else 109#else
110 SCORPION_BANK_AB_HIT = 0x8e, 110 SCORPION_BANK_AB_HIT = 0x8e,
111 SCORPION_BANK_AB_ACCESS = 0x8f, 111 SCORPION_BANK_AB_ACCESS = 0x8f,
112 SCORPION_BANK_CD_HIT = 0x90, 112 SCORPION_BANK_CD_HIT = 0x90,
113 SCORPION_BANK_CD_ACCESS = 0x91, 113 SCORPION_BANK_CD_ACCESS = 0x91,
114 SCORPION_BANK_AB_DSIDE_HIT = 0x92, 114 SCORPION_BANK_AB_DSIDE_HIT = 0x92,
115 SCORPION_BANK_AB_DSIDE_ACCESS = 0x93, 115 SCORPION_BANK_AB_DSIDE_ACCESS = 0x93,
116 SCORPION_BANK_CD_DSIDE_HIT = 0x94, 116 SCORPION_BANK_CD_DSIDE_HIT = 0x94,
117 SCORPION_BANK_CD_DSIDE_ACCESS = 0x95, 117 SCORPION_BANK_CD_DSIDE_ACCESS = 0x95,
118 SCORPION_BANK_AB_ISIDE_HIT = 0x96, 118 SCORPION_BANK_AB_ISIDE_HIT = 0x96,
119 SCORPION_BANK_AB_ISIDE_ACCESS = 0x97, 119 SCORPION_BANK_AB_ISIDE_ACCESS = 0x97,
120 SCORPION_BANK_CD_ISIDE_HIT = 0x98, 120 SCORPION_BANK_CD_ISIDE_HIT = 0x98,
121 SCORPION_BANK_CD_ISIDE_ACCESS = 0x99, 121 SCORPION_BANK_CD_ISIDE_ACCESS = 0x99,
122 SCORPION_ISIDE_RD_WAIT = 0x9a, 122 SCORPION_ISIDE_RD_WAIT = 0x9a,
123 SCORPION_DSIDE_RD_WAIT = 0x9b, 123 SCORPION_DSIDE_RD_WAIT = 0x9b,
124 SCORPION_BANK_BYPASS_WRITE = 0x9c, 124 SCORPION_BANK_BYPASS_WRITE = 0x9c,
125 SCORPION_BANK_AB_NON_CASTOUT = 0x9d, 125 SCORPION_BANK_AB_NON_CASTOUT = 0x9d,
126 SCORPION_BANK_AB_L2_CASTOUT = 0x9e, 126 SCORPION_BANK_AB_L2_CASTOUT = 0x9e,
127 SCORPION_BANK_CD_NON_CASTOUT = 0x9f, 127 SCORPION_BANK_CD_NON_CASTOUT = 0x9f,
128 SCORPION_BANK_CD_L2_CASTOUT = 0xa0, 128 SCORPION_BANK_CD_L2_CASTOUT = 0xa0,
129#endif 129#endif
130 MSM_MAX_EVT 130 MSM_MAX_EVT
131}; 131};
@@ -209,8 +209,8 @@ static const struct scorp_evt sc_evt[] = {
209 {SCORPION_EXCEPTIONS_DENORM, 0x8c000000, 4, 0x5f}, 209 {SCORPION_EXCEPTIONS_DENORM, 0x8c000000, 4, 0x5f},
210 210
211#ifdef CONFIG_ARCH_MSM_SCORPIONMP 211#ifdef CONFIG_ARCH_MSM_SCORPIONMP
212 {SCORPIONMP_NUM_BARRIERS, 0x80000e00, 3, 0x59}, 212 {SCORPIONMP_NUM_BARRIERS, 0x80000e00, 3, 0x59},
213 {SCORPIONMP_BARRIER_CYCLES, 0x800e0000, 3, 0x5a}, 213 {SCORPIONMP_BARRIER_CYCLES, 0x800e0000, 3, 0x5a},
214#else 214#else
215 {SCORPION_BANK_AB_HIT, 0x80000001, 3, 0x58}, 215 {SCORPION_BANK_AB_HIT, 0x80000001, 3, 0x58},
216 {SCORPION_BANK_AB_ACCESS, 0x80000100, 3, 0x59}, 216 {SCORPION_BANK_AB_ACCESS, 0x80000100, 3, 0x59},
@@ -375,8 +375,8 @@ static void scorpion_write_vlpm(u32 val)
375} 375}
376 376
377struct scorpion_access_funcs { 377struct scorpion_access_funcs {
378 u32 (*read) (void); 378 u32(*read)(void);
379 void (*write) (u32); 379 void (*write)(u32);
380}; 380};
381 381
382struct scorpion_access_funcs scor_func[] = { 382struct scorpion_access_funcs scor_func[] = {
@@ -395,7 +395,7 @@ static void scorpion_pre_vlpm(void)
395 u32 venum_new_val; 395 u32 venum_new_val;
396 u32 fp_new_val; 396 u32 fp_new_val;
397 397
398 /* CPACR Enable CP10 access*/ 398 /* CPACR Enable CP10 access */
399 asm volatile("mrc p15, 0, %0, c1, c0, 2" : "=r" (venum_orig_val)); 399 asm volatile("mrc p15, 0, %0, c1, c0, 2" : "=r" (venum_orig_val));
400 venum_new_val = venum_orig_val | 0x00300000; 400 venum_new_val = venum_orig_val | 0x00300000;
401 asm volatile("mcr p15, 0, %0, c1, c0, 2" : : "r" (venum_new_val)); 401 asm volatile("mcr p15, 0, %0, c1, c0, 2" : : "r" (venum_new_val));
@@ -407,9 +407,9 @@ static void scorpion_pre_vlpm(void)
407 407
408static void scorpion_post_vlpm(void) 408static void scorpion_post_vlpm(void)
409{ 409{
410 /* Restore FPEXC*/ 410 /* Restore FPEXC */
411 asm volatile("mcr p10, 7, %0, c8, c0, 0" : : "r" (fp_orig_val)); 411 asm volatile("mcr p10, 7, %0, c8, c0, 0" : : "r" (fp_orig_val));
412 /* Restore CPACR*/ 412 /* Restore CPACR */
413 asm volatile("mcr p15, 0, %0, c1, c0, 2" : : "r" (venum_orig_val)); 413 asm volatile("mcr p15, 0, %0, c1, c0, 2" : : "r" (venum_orig_val));
414} 414}
415 415
@@ -464,7 +464,8 @@ static inline void scorpion_pmnc_write_evtsel(unsigned int cnt, u32 val)
464 u32 zero = 0; 464 u32 zero = 0;
465 struct scorp_evt evtinfo; 465 struct scorp_evt evtinfo;
466 // extract evtinfo.grp and evtinfo.tevt_type_act from val 466 // extract evtinfo.grp and evtinfo.tevt_type_act from val
467 if (get_scorpion_evtinfo(val, &evtinfo) == 0) return; 467 if (get_scorpion_evtinfo(val, &evtinfo) == 0)
468 return;
468 asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (evtinfo.evt_type_act)); 469 asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (evtinfo.evt_type_act));
469 asm volatile("mcr p15, 0, %0, c9, c15, 0" : : "r" (zero)); 470 asm volatile("mcr p15, 0, %0, c9, c15, 0" : : "r" (zero));
470 scorpion_evt_setup(evtinfo.grp, val); 471 scorpion_evt_setup(evtinfo.grp, val);
@@ -482,7 +483,7 @@ static void scorpion_pmnc_reset_counter(unsigned int cnt)
482 asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (val)); 483 asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (val));
483 484
484 if (pmnc_enabled[cnt] != 0) 485 if (pmnc_enabled[cnt] != 0)
485 scorpion_pmnc_enable_counter(cnt); 486 scorpion_pmnc_enable_counter(cnt);
486 487
487 } else if (cnt >= CNTMAX) { 488 } else if (cnt >= CNTMAX) {
488 pr_err("gator: CPU%u resetting wrong PMNC counter %d\n", smp_processor_id(), cnt); 489 pr_err("gator: CPU%u resetting wrong PMNC counter %d\n", smp_processor_id(), cnt);
@@ -490,10 +491,10 @@ static void scorpion_pmnc_reset_counter(unsigned int cnt)
490 scorpion_pmnc_disable_counter(cnt); 491 scorpion_pmnc_disable_counter(cnt);
491 492
492 if (scorpion_pmnc_select_counter(cnt) == cnt) 493 if (scorpion_pmnc_select_counter(cnt) == cnt)
493 asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (val)); 494 asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (val));
494 495
495 if (pmnc_enabled[cnt] != 0) 496 if (pmnc_enabled[cnt] != 0)
496 scorpion_pmnc_enable_counter(cnt); 497 scorpion_pmnc_enable_counter(cnt);
497 } 498 }
498} 499}
499 500
@@ -507,14 +508,14 @@ static int gator_events_scorpion_create_files(struct super_block *sb, struct den
507 if (i == 0) { 508 if (i == 0) {
508 snprintf(buf, sizeof buf, "%s_ccnt", pmnc_name); 509 snprintf(buf, sizeof buf, "%s_ccnt", pmnc_name);
509 } else { 510 } else {
510 snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i-1); 511 snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i - 1);
511 } 512 }
512 dir = gatorfs_mkdir(sb, root, buf); 513 dir = gatorfs_mkdir(sb, root, buf);
513 if (!dir) { 514 if (!dir) {
514 return -1; 515 return -1;
515 } 516 }
516 gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]); 517 gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]);
517 gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]); 518 gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]);
518 if (i > 0) { 519 if (i > 0) {
519 gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]); 520 gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]);
520 } 521 }
@@ -523,7 +524,7 @@ static int gator_events_scorpion_create_files(struct super_block *sb, struct den
523 return 0; 524 return 0;
524} 525}
525 526
526static int gator_events_scorpion_online(int** buffer) 527static int gator_events_scorpion_online(int **buffer)
527{ 528{
528 unsigned int cnt, len = 0, cpu = smp_processor_id(); 529 unsigned int cnt, len = 0, cpu = smp_processor_id();
529 530
@@ -562,13 +563,10 @@ static int gator_events_scorpion_online(int** buffer)
562 // read the counters and toss the invalid data, return zero instead 563 // read the counters and toss the invalid data, return zero instead
563 for (cnt = 0; cnt < pmnc_counters; cnt++) { 564 for (cnt = 0; cnt < pmnc_counters; cnt++) {
564 if (pmnc_enabled[cnt]) { 565 if (pmnc_enabled[cnt]) {
565 int value;
566 if (cnt == CCNT) { 566 if (cnt == CCNT) {
567 value = scorpion_ccnt_read(); 567 scorpion_ccnt_read();
568 } else if (scorpion_pmnc_select_counter(cnt) == cnt) { 568 } else if (scorpion_pmnc_select_counter(cnt) == cnt) {
569 value = scorpion_cntn_read(); 569 scorpion_cntn_read();
570 } else {
571 value = 0;
572 } 570 }
573 scorpion_pmnc_reset_counter(cnt); 571 scorpion_pmnc_reset_counter(cnt);
574 572
@@ -583,7 +581,7 @@ static int gator_events_scorpion_online(int** buffer)
583 return len; 581 return len;
584} 582}
585 583
586static int gator_events_scorpion_offline(int** buffer) 584static int gator_events_scorpion_offline(int **buffer)
587{ 585{
588 scorpion_pmnc_write(scorpion_pmnc_read() & ~PMNC_E); 586 scorpion_pmnc_write(scorpion_pmnc_read() & ~PMNC_E);
589 return 0; 587 return 0;
@@ -657,7 +655,7 @@ int gator_events_scorpion_init(void)
657 return -1; 655 return -1;
658 } 656 }
659 657
660 pmnc_counters++; // CNT[n] + CCNT 658 pmnc_counters++; // CNT[n] + CCNT
661 659
662 for (cnt = CCNT; cnt < CNTMAX; cnt++) { 660 for (cnt = CCNT; cnt < CNTMAX; cnt++) {
663 pmnc_enabled[cnt] = 0; 661 pmnc_enabled[cnt] = 0;
diff --git a/driver/gator_fs.c b/driver/gator_fs.c
index 81b0d5b..9ff118b 100644
--- a/driver/gator_fs.c
+++ b/driver/gator_fs.c
@@ -35,8 +35,8 @@ static struct inode *gatorfs_get_inode(struct super_block *sb, int mode)
35} 35}
36 36
37static const struct super_operations s_ops = { 37static const struct super_operations s_ops = {
38 .statfs = simple_statfs, 38 .statfs = simple_statfs,
39 .drop_inode = generic_delete_inode, 39 .drop_inode = generic_delete_inode,
40}; 40};
41 41
42ssize_t gatorfs_str_to_user(char const *str, char __user *buf, size_t count, loff_t *offset) 42ssize_t gatorfs_str_to_user(char const *str, char __user *buf, size_t count, loff_t *offset)
@@ -104,19 +104,21 @@ static int default_open(struct inode *inode, struct file *filp)
104} 104}
105 105
106static const struct file_operations ulong_fops = { 106static const struct file_operations ulong_fops = {
107 .read = ulong_read_file, 107 .read = ulong_read_file,
108 .write = ulong_write_file, 108 .write = ulong_write_file,
109 .open = default_open, 109 .open = default_open,
110}; 110};
111 111
112static const struct file_operations ulong_ro_fops = { 112static const struct file_operations ulong_ro_fops = {
113 .read = ulong_read_file, 113 .read = ulong_read_file,
114 .open = default_open, 114 .open = default_open,
115}; 115};
116 116
117static struct dentry *__gatorfs_create_file(struct super_block *sb, 117static struct dentry *__gatorfs_create_file(struct super_block *sb,
118 struct dentry *root, char const *name, const struct file_operations *fops, 118 struct dentry *root,
119 int perm) 119 char const *name,
120 const struct file_operations *fops,
121 int perm)
120{ 122{
121 struct dentry *dentry; 123 struct dentry *dentry;
122 struct inode *inode; 124 struct inode *inode;
@@ -135,10 +137,10 @@ static struct dentry *__gatorfs_create_file(struct super_block *sb,
135} 137}
136 138
137int gatorfs_create_ulong(struct super_block *sb, struct dentry *root, 139int gatorfs_create_ulong(struct super_block *sb, struct dentry *root,
138 char const *name, unsigned long *val) 140 char const *name, unsigned long *val)
139{ 141{
140 struct dentry *d = __gatorfs_create_file(sb, root, name, 142 struct dentry *d = __gatorfs_create_file(sb, root, name,
141 &ulong_fops, 0644); 143 &ulong_fops, 0644);
142 if (!d) 144 if (!d)
143 return -EFAULT; 145 return -EFAULT;
144 146
@@ -147,10 +149,10 @@ int gatorfs_create_ulong(struct super_block *sb, struct dentry *root,
147} 149}
148 150
149int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root, 151int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root,
150 char const *name, unsigned long *val) 152 char const *name, unsigned long *val)
151{ 153{
152 struct dentry *d = __gatorfs_create_file(sb, root, name, 154 struct dentry *d = __gatorfs_create_file(sb, root, name,
153 &ulong_ro_fops, 0444); 155 &ulong_ro_fops, 0444);
154 if (!d) 156 if (!d)
155 return -EFAULT; 157 return -EFAULT;
156 158
@@ -165,15 +167,15 @@ static ssize_t atomic_read_file(struct file *file, char __user *buf, size_t coun
165} 167}
166 168
167static const struct file_operations atomic_ro_fops = { 169static const struct file_operations atomic_ro_fops = {
168 .read = atomic_read_file, 170 .read = atomic_read_file,
169 .open = default_open, 171 .open = default_open,
170}; 172};
171 173
172int gatorfs_create_ro_atomic(struct super_block *sb, struct dentry *root, 174int gatorfs_create_ro_atomic(struct super_block *sb, struct dentry *root,
173 char const *name, atomic_t *val) 175 char const *name, atomic_t *val)
174{ 176{
175 struct dentry *d = __gatorfs_create_file(sb, root, name, 177 struct dentry *d = __gatorfs_create_file(sb, root, name,
176 &atomic_ro_fops, 0444); 178 &atomic_ro_fops, 0444);
177 if (!d) 179 if (!d)
178 return -EFAULT; 180 return -EFAULT;
179 181
@@ -182,7 +184,7 @@ int gatorfs_create_ro_atomic(struct super_block *sb, struct dentry *root,
182} 184}
183 185
184int gatorfs_create_file(struct super_block *sb, struct dentry *root, 186int gatorfs_create_file(struct super_block *sb, struct dentry *root,
185 char const *name, const struct file_operations *fops) 187 char const *name, const struct file_operations *fops)
186{ 188{
187 if (!__gatorfs_create_file(sb, root, name, fops, 0644)) 189 if (!__gatorfs_create_file(sb, root, name, fops, 0644))
188 return -EFAULT; 190 return -EFAULT;
@@ -190,7 +192,8 @@ int gatorfs_create_file(struct super_block *sb, struct dentry *root,
190} 192}
191 193
192int gatorfs_create_file_perm(struct super_block *sb, struct dentry *root, 194int gatorfs_create_file_perm(struct super_block *sb, struct dentry *root,
193 char const *name, const struct file_operations *fops, int perm) 195 char const *name,
196 const struct file_operations *fops, int perm)
194{ 197{
195 if (!__gatorfs_create_file(sb, root, name, fops, perm)) 198 if (!__gatorfs_create_file(sb, root, name, fops, perm))
196 return -EFAULT; 199 return -EFAULT;
@@ -198,7 +201,7 @@ int gatorfs_create_file_perm(struct super_block *sb, struct dentry *root,
198} 201}
199 202
200struct dentry *gatorfs_mkdir(struct super_block *sb, 203struct dentry *gatorfs_mkdir(struct super_block *sb,
201 struct dentry *root, char const *name) 204 struct dentry *root, char const *name)
202{ 205{
203 struct dentry *dentry; 206 struct dentry *dentry;
204 struct inode *inode; 207 struct inode *inode;
@@ -256,28 +259,29 @@ static int gatorfs_fill_super(struct super_block *sb, void *data, int silent)
256 259
257#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) 260#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
258static int gatorfs_get_sb(struct file_system_type *fs_type, 261static int gatorfs_get_sb(struct file_system_type *fs_type,
259 int flags, const char *dev_name, void *data, struct vfsmount *mnt) 262 int flags, const char *dev_name, void *data,
263 struct vfsmount *mnt)
260{ 264{
261 return get_sb_single(fs_type, flags, data, gatorfs_fill_super, mnt); 265 return get_sb_single(fs_type, flags, data, gatorfs_fill_super, mnt);
262} 266}
263#else 267#else
264static struct dentry *gatorfs_mount(struct file_system_type *fs_type, 268static struct dentry *gatorfs_mount(struct file_system_type *fs_type,
265 int flags, const char *dev_name, void *data) 269 int flags, const char *dev_name, void *data)
266{ 270{
267 return mount_nodev(fs_type, flags, data, gatorfs_fill_super); 271 return mount_nodev(fs_type, flags, data, gatorfs_fill_super);
268} 272}
269#endif 273#endif
270 274
271static struct file_system_type gatorfs_type = { 275static struct file_system_type gatorfs_type = {
272 .owner = THIS_MODULE, 276 .owner = THIS_MODULE,
273 .name = "gatorfs", 277 .name = "gatorfs",
274#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) 278#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
275 .get_sb = gatorfs_get_sb, 279 .get_sb = gatorfs_get_sb,
276#else 280#else
277 .mount = gatorfs_mount, 281 .mount = gatorfs_mount,
278#endif 282#endif
279 283
280 .kill_sb = kill_litter_super, 284 .kill_sb = kill_litter_super,
281}; 285};
282 286
283int __init gatorfs_register(void) 287int __init gatorfs_register(void)
diff --git a/driver/gator_main.c b/driver/gator_main.c
index a2d8ef0..8c35caa 100644
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
@@ -7,7 +7,7 @@
7 * 7 *
8 */ 8 */
9 9
10static unsigned long gator_protocol_version = 11; 10static unsigned long gator_protocol_version = 12;
11 11
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/cpu.h> 13#include <linux/cpu.h>
@@ -60,12 +60,12 @@ static unsigned long gator_protocol_version = 11;
60#define SUMMARY_BUFFER_SIZE (1*1024) 60#define SUMMARY_BUFFER_SIZE (1*1024)
61#define BACKTRACE_BUFFER_SIZE (128*1024) 61#define BACKTRACE_BUFFER_SIZE (128*1024)
62#define NAME_BUFFER_SIZE (64*1024) 62#define NAME_BUFFER_SIZE (64*1024)
63#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 63#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
64#define BLOCK_COUNTER_BUFFER_SIZE (128*1024) 64#define BLOCK_COUNTER_BUFFER_SIZE (128*1024)
65#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 65#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
66#define SCHED_TRACE_BUFFER_SIZE (128*1024) 66#define SCHED_TRACE_BUFFER_SIZE (128*1024)
67#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 67#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
68#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 68#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
69 69
70#define NO_COOKIE 0U 70#define NO_COOKIE 0U
71#define INVALID_COOKIE ~0U 71#define INVALID_COOKIE ~0U
@@ -94,7 +94,6 @@ static unsigned long gator_protocol_version = 11;
94 94
95#define MAXSIZE_PACK32 5 95#define MAXSIZE_PACK32 5
96#define MAXSIZE_PACK64 10 96#define MAXSIZE_PACK64 10
97#define MAXSIZE_CORE_NAME 32
98 97
99#if defined(__arm__) 98#if defined(__arm__)
100#define PC_REG regs->ARM_pc 99#define PC_REG regs->ARM_pc
@@ -121,6 +120,7 @@ enum {
121 * Globals 120 * Globals
122 ******************************************************************************/ 121 ******************************************************************************/
123static unsigned long gator_cpu_cores; 122static unsigned long gator_cpu_cores;
123// Size of the largest buffer. Effectively constant, set in gator_op_create_files
124static unsigned long userspace_buffer_size; 124static unsigned long userspace_buffer_size;
125static unsigned long gator_backtrace_depth; 125static unsigned long gator_backtrace_depth;
126 126
@@ -148,15 +148,23 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long
148static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len); 148static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len);
149static void gator_buffer_write_string(int cpu, int buftype, const char *x); 149static void gator_buffer_write_string(int cpu, int buftype, const char *x);
150static void gator_add_trace(int cpu, unsigned long address); 150static void gator_add_trace(int cpu, unsigned long address);
151static void gator_add_sample(int cpu, struct pt_regs * const regs); 151static void gator_add_sample(int cpu, struct pt_regs *const regs);
152static uint64_t gator_get_time(void); 152static uint64_t gator_get_time(void);
153 153
154// Size of the buffer, must be a power of 2. Effectively constant, set in gator_op_setup.
154static uint32_t gator_buffer_size[NUM_GATOR_BUFS]; 155static uint32_t gator_buffer_size[NUM_GATOR_BUFS];
156// gator_buffer_size - 1, bitwise and with pos to get offset into the array. Effectively constant, set in gator_op_setup.
155static uint32_t gator_buffer_mask[NUM_GATOR_BUFS]; 157static uint32_t gator_buffer_mask[NUM_GATOR_BUFS];
158// Read position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are read by userspace in userspace_buffer_read
156static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_read); 159static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_read);
160// Write position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are written to the buffer
157static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_write); 161static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_write);
162// Commit position in the buffer. Initialized to zero in gator_op_setup and incremented after a frame is ready to be read by userspace
158static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_commit); 163static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_commit);
164// If set to false, decreases the number of bytes returned by buffer_bytes_available. Set in buffer_check_space if no space is remaining. Initialized to true in gator_op_setup
165// This means that if we run out of space, continue to report that no space is available until bytes are read by userspace
159static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], buffer_space_available); 166static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], buffer_space_available);
167// The buffer. Allocated in gator_op_setup
160static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer); 168static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer);
161 169
162/****************************************************************************** 170/******************************************************************************
@@ -177,9 +185,125 @@ static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer);
177/****************************************************************************** 185/******************************************************************************
178 * Misc 186 * Misc
179 ******************************************************************************/ 187 ******************************************************************************/
180#if defined(__arm__) || defined(__aarch64__) 188
189struct gator_cpu gator_cpus[] = {
190 {
191 .cpuid = ARM1136,
192 .core_name = "ARM1136",
193 .pmnc_name = "ARM_ARM11",
194 .pmnc_counters = 3,
195 .ccnt = 2,
196 },
197 {
198 .cpuid = ARM1156,
199 .core_name = "ARM1156",
200 .pmnc_name = "ARM_ARM11",
201 .pmnc_counters = 3,
202 .ccnt = 2,
203 },
204 {
205 .cpuid = ARM1176,
206 .core_name = "ARM1176",
207 .pmnc_name = "ARM_ARM11",
208 .pmnc_counters = 3,
209 .ccnt = 2,
210 },
211 {
212 .cpuid = ARM11MPCORE,
213 .core_name = "ARM11MPCore",
214 .pmnc_name = "ARM_ARM11MPCore",
215 .pmnc_counters = 3,
216 },
217 {
218 .cpuid = CORTEX_A5,
219 .core_name = "Cortex-A5",
220 .pmnc_name = "ARM_Cortex-A5",
221 .pmnc_counters = 2,
222 },
223 {
224 .cpuid = CORTEX_A7,
225 .core_name = "Cortex-A7",
226 .pmnc_name = "ARM_Cortex-A7",
227 .pmnc_counters = 4,
228 },
229 {
230 .cpuid = CORTEX_A8,
231 .core_name = "Cortex-A8",
232 .pmnc_name = "ARM_Cortex-A8",
233 .pmnc_counters = 4,
234 },
235 {
236 .cpuid = CORTEX_A9,
237 .core_name = "Cortex-A9",
238 .pmnc_name = "ARM_Cortex-A9",
239 .pmnc_counters = 6,
240 },
241 {
242 .cpuid = CORTEX_A15,
243 .core_name = "Cortex-A15",
244 .pmnc_name = "ARM_Cortex-A15",
245 .pmnc_counters = 6,
246 },
247 {
248 .cpuid = SCORPION,
249 .core_name = "Scorpion",
250 .pmnc_name = "Scorpion",
251 .pmnc_counters = 4,
252 },
253 {
254 .cpuid = SCORPIONMP,
255 .core_name = "ScorpionMP",
256 .pmnc_name = "ScorpionMP",
257 .pmnc_counters = 4,
258 },
259 {
260 .cpuid = KRAITSIM,
261 .core_name = "KraitSIM",
262 .pmnc_name = "Krait",
263 .pmnc_counters = 4,
264 },
265 {
266 .cpuid = KRAIT,
267 .core_name = "Krait",
268 .pmnc_name = "Krait",
269 .pmnc_counters = 4,
270 },
271 {
272 .cpuid = KRAIT_S4_PRO,
273 .core_name = "Krait S4 Pro",
274 .pmnc_name = "Krait",
275 .pmnc_counters = 4,
276 },
277 {
278 .cpuid = CORTEX_A53,
279 .core_name = "Cortex-A53",
280 .pmnc_name = "ARM_Cortex-A53",
281 .pmnc_counters = 6,
282 },
283 {
284 .cpuid = CORTEX_A57,
285 .core_name = "Cortex-A57",
286 .pmnc_name = "ARM_Cortex-A57",
287 .pmnc_counters = 6,
288 },
289 {
290 .cpuid = AARCH64,
291 .core_name = "AArch64",
292 .pmnc_name = "ARM_AArch64",
293 .pmnc_counters = 6,
294 },
295 {
296 .cpuid = OTHER,
297 .core_name = "Other",
298 .pmnc_name = "Other",
299 .pmnc_counters = 6,
300 },
301 {}
302};
303
181u32 gator_cpuid(void) 304u32 gator_cpuid(void)
182{ 305{
306#if defined(__arm__) || defined(__aarch64__)
183 u32 val; 307 u32 val;
184#if !defined(__aarch64__) 308#if !defined(__aarch64__)
185 asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (val)); 309 asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (val));
@@ -187,8 +311,10 @@ u32 gator_cpuid(void)
187 asm volatile("mrs %0, midr_el1" : "=r" (val)); 311 asm volatile("mrs %0, midr_el1" : "=r" (val));
188#endif 312#endif
189 return (val >> 4) & 0xfff; 313 return (val >> 4) & 0xfff;
190} 314#else
315 return OTHER;
191#endif 316#endif
317}
192 318
193static void gator_buffer_wake_up(unsigned long data) 319static void gator_buffer_wake_up(unsigned long data)
194{ 320{
@@ -198,7 +324,7 @@ static void gator_buffer_wake_up(unsigned long data)
198/****************************************************************************** 324/******************************************************************************
199 * Commit interface 325 * Commit interface
200 ******************************************************************************/ 326 ******************************************************************************/
201static bool buffer_commit_ready(int* cpu, int* buftype) 327static bool buffer_commit_ready(int *cpu, int *buftype)
202{ 328{
203 int cpu_x, x; 329 int cpu_x, x;
204 for_each_present_cpu(cpu_x) { 330 for_each_present_cpu(cpu_x) {
@@ -265,7 +391,7 @@ static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int le
265 int i; 391 int i;
266 u32 write = per_cpu(gator_buffer_write, cpu)[buftype]; 392 u32 write = per_cpu(gator_buffer_write, cpu)[buftype];
267 u32 mask = gator_buffer_mask[buftype]; 393 u32 mask = gator_buffer_mask[buftype];
268 char* buffer = per_cpu(gator_buffer, cpu)[buftype]; 394 char *buffer = per_cpu(gator_buffer, cpu)[buftype];
269 395
270 for (i = 0; i < len; i++) { 396 for (i = 0; i < len; i++) {
271 buffer[write] = x[i]; 397 buffer[write] = x[i];
@@ -282,55 +408,27 @@ static void gator_buffer_write_string(int cpu, int buftype, const char *x)
282 gator_buffer_write_bytes(cpu, buftype, x, len); 408 gator_buffer_write_bytes(cpu, buftype, x, len);
283} 409}
284 410
285static void gator_buffer_header(int cpu, int buftype)
286{
287 int frame;
288
289 switch (buftype) {
290 case SUMMARY_BUF:
291 frame = FRAME_SUMMARY;
292 break;
293 case BACKTRACE_BUF:
294 frame = FRAME_BACKTRACE;
295 break;
296 case NAME_BUF:
297 frame = FRAME_NAME;
298 break;
299 case COUNTER_BUF:
300 frame = FRAME_COUNTER;
301 break;
302 case BLOCK_COUNTER_BUF:
303 frame = FRAME_BLOCK_COUNTER;
304 break;
305 case ANNOTATE_BUF:
306 frame = FRAME_ANNOTATE;
307 break;
308 case SCHED_TRACE_BUF:
309 frame = FRAME_SCHED_TRACE;
310 break;
311 case GPU_TRACE_BUF:
312 frame = FRAME_GPU_TRACE;
313 break;
314 case IDLE_BUF:
315 frame = FRAME_IDLE;
316 break;
317 default:
318 frame = -1;
319 break;
320 }
321
322 if (per_cpu(gator_buffer, cpu)[buftype]) {
323 marshal_frame(cpu, buftype, frame);
324 }
325}
326
327static void gator_commit_buffer(int cpu, int buftype) 411static void gator_commit_buffer(int cpu, int buftype)
328{ 412{
413 int type_length, commit, length, byte;
414
329 if (!per_cpu(gator_buffer, cpu)[buftype]) 415 if (!per_cpu(gator_buffer, cpu)[buftype])
330 return; 416 return;
331 417
418 // post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload
419 type_length = gator_response_type ? 1 : 0;
420 commit = per_cpu(gator_buffer_commit, cpu)[buftype];
421 length = per_cpu(gator_buffer_write, cpu)[buftype] - commit;
422 if (length < 0) {
423 length += gator_buffer_size[buftype];
424 }
425 length = length - type_length - sizeof(int);
426 for (byte = 0; byte < sizeof(int); byte++) {
427 per_cpu(gator_buffer, cpu)[buftype][(commit + type_length + byte) & gator_buffer_mask[buftype]] = (length >> byte * 8) & 0xFF;
428 }
429
332 per_cpu(gator_buffer_commit, cpu)[buftype] = per_cpu(gator_buffer_write, cpu)[buftype]; 430 per_cpu(gator_buffer_commit, cpu)[buftype] = per_cpu(gator_buffer_write, cpu)[buftype];
333 gator_buffer_header(cpu, buftype); 431 marshal_frame(cpu, buftype);
334 432
335 // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater 433 // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
336 mod_timer(&gator_buffer_wake_up_timer, jiffies + 1); 434 mod_timer(&gator_buffer_wake_up_timer, jiffies + 1);
@@ -359,7 +457,7 @@ static void gator_add_trace(int cpu, unsigned long address)
359 marshal_backtrace(offset & ~1, cookie); 457 marshal_backtrace(offset & ~1, cookie);
360} 458}
361 459
362static void gator_add_sample(int cpu, struct pt_regs * const regs) 460static void gator_add_sample(int cpu, struct pt_regs *const regs)
363{ 461{
364 bool inKernel; 462 bool inKernel;
365 unsigned long exec_cookie; 463 unsigned long exec_cookie;
@@ -392,11 +490,11 @@ static void gator_add_sample(int cpu, struct pt_regs * const regs)
392 ******************************************************************************/ 490 ******************************************************************************/
393static void gator_timer_interrupt(void) 491static void gator_timer_interrupt(void)
394{ 492{
395 struct pt_regs * const regs = get_irq_regs(); 493 struct pt_regs *const regs = get_irq_regs();
396 gator_backtrace_handler(regs); 494 gator_backtrace_handler(regs);
397} 495}
398 496
399void gator_backtrace_handler(struct pt_regs * const regs) 497void gator_backtrace_handler(struct pt_regs *const regs)
400{ 498{
401 int cpu = smp_processor_id(); 499 int cpu = smp_processor_id();
402 500
@@ -412,11 +510,11 @@ void gator_backtrace_handler(struct pt_regs * const regs)
412static int gator_running; 510static int gator_running;
413 511
414// This function runs in interrupt context and on the appropriate core 512// This function runs in interrupt context and on the appropriate core
415static void gator_timer_offline(void* unused) 513static void gator_timer_offline(void *unused)
416{ 514{
417 struct gator_interface *gi; 515 struct gator_interface *gi;
418 int i, len, cpu = smp_processor_id(); 516 int i, len, cpu = smp_processor_id();
419 int* buffer; 517 int *buffer;
420 518
421 gator_trace_sched_offline(); 519 gator_trace_sched_offline();
422 gator_trace_power_offline(); 520 gator_trace_power_offline();
@@ -444,8 +542,8 @@ static void gator_timer_offline_dispatch(int cpu)
444 struct gator_interface *gi; 542 struct gator_interface *gi;
445 543
446 list_for_each_entry(gi, &gator_events, list) 544 list_for_each_entry(gi, &gator_events, list)
447 if (gi->offline_dispatch) 545 if (gi->offline_dispatch)
448 gi->offline_dispatch(cpu); 546 gi->offline_dispatch(cpu);
449} 547}
450 548
451static void gator_timer_stop(void) 549static void gator_timer_stop(void)
@@ -464,11 +562,11 @@ static void gator_timer_stop(void)
464} 562}
465 563
466// This function runs in interrupt context and on the appropriate core 564// This function runs in interrupt context and on the appropriate core
467static void gator_timer_online(void* unused) 565static void gator_timer_online(void *unused)
468{ 566{
469 struct gator_interface *gi; 567 struct gator_interface *gi;
470 int len, cpu = smp_processor_id(); 568 int len, cpu = smp_processor_id();
471 int* buffer; 569 int *buffer;
472 570
473 gator_trace_power_online(); 571 gator_trace_power_online();
474 572
@@ -485,25 +583,15 @@ static void gator_timer_online(void* unused)
485 gator_hrtimer_online(cpu); 583 gator_hrtimer_online(cpu);
486#if defined(__arm__) || defined(__aarch64__) 584#if defined(__arm__) || defined(__aarch64__)
487 { 585 {
488 const char * core_name = NULL; 586 const char *core_name = "Unknown";
489 587 const u32 cpuid = gator_cpuid();
490 // String lengths must be less than MAXSIZE_CORE_NAME 588 int i;
491 switch (gator_cpuid()) { 589
492 case ARM1136: core_name = "ARM1136"; break; 590 for (i = 0; gator_cpus[i].cpuid != 0; ++i) {
493 case ARM1156: core_name = "ARM1156"; break; 591 if (gator_cpus[i].cpuid == cpuid) {
494 case ARM1176: core_name = "ARM1176"; break; 592 core_name = gator_cpus[i].core_name;
495 case ARM11MPCORE: core_name = "ARM11MPCore"; break; 593 break;
496 case CORTEX_A5: core_name = "Cortex-A5"; break; 594 }
497 case CORTEX_A7: core_name = "Cortex-A7"; break;
498 case CORTEX_A8: core_name = "Cortex-A8"; break;
499 case CORTEX_A9: core_name = "Cortex-A9"; break;
500 case CORTEX_A15: core_name = "Cortex-A15"; break;
501 case SCORPION: core_name = "Scorpion"; break;
502 case SCORPIONMP: core_name = "ScorpionMP"; break;
503 case KRAITSIM: core_name = "KraitSIM"; break;
504 case KRAIT: core_name = "Krait"; break;
505 case AARCH64: core_name = "AArch64"; break;
506 default: core_name = "Unknown"; break;
507 } 595 }
508 596
509 marshal_core_name(core_name); 597 marshal_core_name(core_name);
@@ -517,8 +605,8 @@ static void gator_timer_online_dispatch(int cpu)
517 struct gator_interface *gi; 605 struct gator_interface *gi;
518 606
519 list_for_each_entry(gi, &gator_events, list) 607 list_for_each_entry(gi, &gator_events, list)
520 if (gi->online_dispatch) 608 if (gi->online_dispatch)
521 gi->online_dispatch(cpu); 609 gi->online_dispatch(cpu);
522} 610}
523 611
524int gator_timer_start(unsigned long sample_rate) 612int gator_timer_start(unsigned long sample_rate)
@@ -563,16 +651,16 @@ static int __cpuinit gator_hotcpu_notify(struct notifier_block *self, unsigned l
563 long cpu = (long)hcpu; 651 long cpu = (long)hcpu;
564 652
565 switch (action) { 653 switch (action) {
566 case CPU_DOWN_PREPARE: 654 case CPU_DOWN_PREPARE:
567 case CPU_DOWN_PREPARE_FROZEN: 655 case CPU_DOWN_PREPARE_FROZEN:
568 smp_call_function_single(cpu, gator_timer_offline, NULL, 1); 656 smp_call_function_single(cpu, gator_timer_offline, NULL, 1);
569 gator_timer_offline_dispatch(cpu); 657 gator_timer_offline_dispatch(cpu);
570 break; 658 break;
571 case CPU_ONLINE: 659 case CPU_ONLINE:
572 case CPU_ONLINE_FROZEN: 660 case CPU_ONLINE_FROZEN:
573 gator_timer_online_dispatch(cpu); 661 gator_timer_online_dispatch(cpu);
574 smp_call_function_single(cpu, gator_timer_online, NULL, 1); 662 smp_call_function_single(cpu, gator_timer_online, NULL, 1);
575 break; 663 break;
576 } 664 }
577 665
578 return NOTIFY_OK; 666 return NOTIFY_OK;
@@ -589,24 +677,24 @@ static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void
589 int cpu; 677 int cpu;
590 678
591 switch (event) { 679 switch (event) {
592 case PM_HIBERNATION_PREPARE: 680 case PM_HIBERNATION_PREPARE:
593 case PM_SUSPEND_PREPARE: 681 case PM_SUSPEND_PREPARE:
594 unregister_hotcpu_notifier(&gator_hotcpu_notifier); 682 unregister_hotcpu_notifier(&gator_hotcpu_notifier);
595 unregister_scheduler_tracepoints(); 683 unregister_scheduler_tracepoints();
596 on_each_cpu(gator_timer_offline, NULL, 1); 684 on_each_cpu(gator_timer_offline, NULL, 1);
597 for_each_online_cpu(cpu) { 685 for_each_online_cpu(cpu) {
598 gator_timer_offline_dispatch(cpu); 686 gator_timer_offline_dispatch(cpu);
599 } 687 }
600 break; 688 break;
601 case PM_POST_HIBERNATION: 689 case PM_POST_HIBERNATION:
602 case PM_POST_SUSPEND: 690 case PM_POST_SUSPEND:
603 for_each_online_cpu(cpu) { 691 for_each_online_cpu(cpu) {
604 gator_timer_online_dispatch(cpu); 692 gator_timer_online_dispatch(cpu);
605 } 693 }
606 on_each_cpu(gator_timer_online, NULL, 1); 694 on_each_cpu(gator_timer_online, NULL, 1);
607 register_scheduler_tracepoints(); 695 register_scheduler_tracepoints();
608 register_hotcpu_notifier(&gator_hotcpu_notifier); 696 register_hotcpu_notifier(&gator_hotcpu_notifier);
609 break; 697 break;
610 } 698 }
611 699
612 return NOTIFY_OK; 700 return NOTIFY_OK;
@@ -676,6 +764,15 @@ static int gator_init(void)
676 return 0; 764 return 0;
677} 765}
678 766
767static void gator_exit(void)
768{
769 struct gator_interface *gi;
770
771 list_for_each_entry(gi, &gator_events, list)
772 if (gi->shutdown)
773 gi->shutdown();
774}
775
679static int gator_start(void) 776static int gator_start(void)
680{ 777{
681 unsigned long cpu, i; 778 unsigned long cpu, i;
@@ -684,7 +781,7 @@ static int gator_start(void)
684 // Initialize the buffer with the frame type and core 781 // Initialize the buffer with the frame type and core
685 for_each_present_cpu(cpu) { 782 for_each_present_cpu(cpu) {
686 for (i = 0; i < NUM_GATOR_BUFS; i++) { 783 for (i = 0; i < NUM_GATOR_BUFS; i++) {
687 gator_buffer_header(cpu, i); 784 marshal_frame(cpu, i);
688 } 785 }
689 } 786 }
690 787
@@ -741,8 +838,8 @@ annotate_failure:
741cookies_failure: 838cookies_failure:
742 // stop all events 839 // stop all events
743 list_for_each_entry(gi, &gator_events, list) 840 list_for_each_entry(gi, &gator_events, list)
744 if (gi->stop) 841 if (gi->stop)
745 gi->stop(); 842 gi->stop();
746events_failure: 843events_failure:
747 844
748 return -1; 845 return -1;
@@ -758,13 +855,13 @@ static void gator_stop(void)
758 gator_trace_gpu_stop(); 855 gator_trace_gpu_stop();
759 856
760 // stop all interrupt callback reads before tearing down other interfaces 857 // stop all interrupt callback reads before tearing down other interfaces
761 gator_notifier_stop(); // should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined 858 gator_notifier_stop(); // should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined
762 gator_timer_stop(); 859 gator_timer_stop();
763 860
764 // stop all events 861 // stop all events
765 list_for_each_entry(gi, &gator_events, list) 862 list_for_each_entry(gi, &gator_events, list)
766 if (gi->stop) 863 if (gi->stop)
767 gi->stop(); 864 gi->stop();
768} 865}
769 866
770/****************************************************************************** 867/******************************************************************************
@@ -941,8 +1038,8 @@ static ssize_t enable_write(struct file *file, char const __user *buf, size_t co
941} 1038}
942 1039
943static const struct file_operations enable_fops = { 1040static const struct file_operations enable_fops = {
944 .read = enable_read, 1041 .read = enable_read,
945 .write = enable_write, 1042 .write = enable_write,
946}; 1043};
947 1044
948static int userspace_buffer_open(struct inode *inode, struct file *file) 1045static int userspace_buffer_open(struct inode *inode, struct file *file)
@@ -978,10 +1075,10 @@ static int userspace_buffer_release(struct inode *inode, struct file *file)
978} 1075}
979 1076
980static ssize_t userspace_buffer_read(struct file *file, char __user *buf, 1077static ssize_t userspace_buffer_read(struct file *file, char __user *buf,
981 size_t count, loff_t *offset) 1078 size_t count, loff_t *offset)
982{ 1079{
983 int retval = -EINVAL; 1080 int retval = -EINVAL;
984 int commit = 0, length, length1, length2, read, byte, type_length; 1081 int commit = 0, length1, length2, read;
985 char *buffer1; 1082 char *buffer1;
986 char *buffer2 = NULL; 1083 char *buffer2 = NULL;
987 int cpu, buftype; 1084 int cpu, buftype;
@@ -1026,13 +1123,6 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf,
1026 length2 = commit; 1123 length2 = commit;
1027 } 1124 }
1028 1125
1029 // post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload
1030 type_length = gator_response_type ? 1 : 0;
1031 length = length1 + length2 - type_length - sizeof(int);
1032 for (byte = 0; byte < sizeof(int); byte++) {
1033 per_cpu(gator_buffer, cpu)[buftype][(read + type_length + byte) & gator_buffer_mask[buftype]] = (length >> byte * 8) & 0xFF;
1034 }
1035
1036 /* start, middle or end */ 1126 /* start, middle or end */
1037 if (length1 > 0) { 1127 if (length1 > 0) {
1038 if (copy_to_user(&buf[0], buffer1, length1)) { 1128 if (copy_to_user(&buf[0], buffer1, length1)) {
@@ -1059,15 +1149,14 @@ out:
1059} 1149}
1060 1150
1061const struct file_operations gator_event_buffer_fops = { 1151const struct file_operations gator_event_buffer_fops = {
1062 .open = userspace_buffer_open, 1152 .open = userspace_buffer_open,
1063 .release = userspace_buffer_release, 1153 .release = userspace_buffer_release,
1064 .read = userspace_buffer_read, 1154 .read = userspace_buffer_read,
1065}; 1155};
1066 1156
1067static ssize_t depth_read(struct file *file, char __user *buf, size_t count, loff_t *offset) 1157static ssize_t depth_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
1068{ 1158{
1069 return gatorfs_ulong_to_user(gator_backtrace_depth, buf, count, 1159 return gatorfs_ulong_to_user(gator_backtrace_depth, buf, count, offset);
1070 offset);
1071} 1160}
1072 1161
1073static ssize_t depth_write(struct file *file, char const __user *buf, size_t count, loff_t *offset) 1162static ssize_t depth_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
@@ -1090,8 +1179,8 @@ static ssize_t depth_write(struct file *file, char const __user *buf, size_t cou
1090} 1179}
1091 1180
1092static const struct file_operations depth_fops = { 1181static const struct file_operations depth_fops = {
1093 .read = depth_read, 1182 .read = depth_read,
1094 .write = depth_write 1183 .write = depth_write
1095}; 1184};
1096 1185
1097void gator_op_create_files(struct super_block *sb, struct dentry *root) 1186void gator_op_create_files(struct super_block *sb, struct dentry *root)
@@ -1105,7 +1194,7 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root)
1105 for_each_present_cpu(cpu) { 1194 for_each_present_cpu(cpu) {
1106 gator_cpu_cores++; 1195 gator_cpu_cores++;
1107 } 1196 }
1108 userspace_buffer_size = BACKTRACE_BUFFER_SIZE; 1197 userspace_buffer_size = BACKTRACE_BUFFER_SIZE;
1109 gator_response_type = 1; 1198 gator_response_type = 1;
1110 1199
1111 gatorfs_create_file(sb, root, "enable", &enable_fops); 1200 gatorfs_create_file(sb, root, "enable", &enable_fops);
@@ -1123,8 +1212,8 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root)
1123 // Linux Events 1212 // Linux Events
1124 dir = gatorfs_mkdir(sb, root, "events"); 1213 dir = gatorfs_mkdir(sb, root, "events");
1125 list_for_each_entry(gi, &gator_events, list) 1214 list_for_each_entry(gi, &gator_events, list)
1126 if (gi->create_files) 1215 if (gi->create_files)
1127 gi->create_files(sb, dir); 1216 gi->create_files(sb, dir);
1128 1217
1129 // Power interface 1218 // Power interface
1130 gator_trace_power_create_files(sb, dir); 1219 gator_trace_power_create_files(sb, dir);
@@ -1153,6 +1242,7 @@ static void __exit gator_module_exit(void)
1153{ 1242{
1154 del_timer_sync(&gator_buffer_wake_up_timer); 1243 del_timer_sync(&gator_buffer_wake_up_timer);
1155 tracepoint_synchronize_unregister(); 1244 tracepoint_synchronize_unregister();
1245 gator_exit();
1156 gatorfs_unregister(); 1246 gatorfs_unregister();
1157} 1247}
1158 1248
diff --git a/driver/gator_marshaling.c b/driver/gator_marshaling.c
index a84b280..b2efdd2 100644
--- a/driver/gator_marshaling.c
+++ b/driver/gator_marshaling.c
@@ -7,49 +7,52 @@
7 * 7 *
8 */ 8 */
9 9
10static void marshal_summary(long long timestamp, long long uptime) { 10static void marshal_summary(long long timestamp, long long uptime)
11{
11 int cpu = 0; 12 int cpu = 0;
12 gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, timestamp); 13 gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, timestamp);
13 gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, uptime); 14 gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, uptime);
14 buffer_check(cpu, SUMMARY_BUF); 15 buffer_check(cpu, SUMMARY_BUF);
15} 16}
16 17
17static bool marshal_cookie_header(char* text) { 18static bool marshal_cookie_header(const char *text)
19{
18 int cpu = smp_processor_id(); 20 int cpu = smp_processor_id();
19 return buffer_check_space(cpu, NAME_BUF, strlen(text) + 2*MAXSIZE_PACK32); 21 return buffer_check_space(cpu, NAME_BUF, strlen(text) + 3 * MAXSIZE_PACK32);
20} 22}
21 23
22static void marshal_cookie(int cookie, char* text) { 24static void marshal_cookie(int cookie, const char *text)
25{
23 int cpu = smp_processor_id(); 26 int cpu = smp_processor_id();
24 // TODO(dreric01) How long can the string be? 27 // buffer_check_space already called by marshal_cookie_header
25 if (buffer_check_space(cpu, NAME_BUF, 2*MAXSIZE_PACK32)) { 28 gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_COOKIE);
26 gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_COOKIE); 29 gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
27 gator_buffer_write_packed_int(cpu, NAME_BUF, cookie); 30 gator_buffer_write_string(cpu, NAME_BUF, text);
28 gator_buffer_write_string(cpu, NAME_BUF, text);
29 }
30 buffer_check(cpu, NAME_BUF); 31 buffer_check(cpu, NAME_BUF);
31} 32}
32 33
33static void marshal_thread_name(int pid, char* name) { 34static void marshal_thread_name(int pid, char *name)
35{
34 unsigned long flags, cpu; 36 unsigned long flags, cpu;
35 local_irq_save(flags); 37 local_irq_save(flags);
36 cpu = smp_processor_id(); 38 cpu = smp_processor_id();
37 if (buffer_check_space(cpu, NAME_BUF, TASK_COMM_LEN + 2*MAXSIZE_PACK32 + MAXSIZE_PACK64)) { 39 if (buffer_check_space(cpu, NAME_BUF, TASK_COMM_LEN + 3 * MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
38 gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_THREAD_NAME); 40 gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_THREAD_NAME);
39 gator_buffer_write_packed_int64(cpu, NAME_BUF, gator_get_time()); 41 gator_buffer_write_packed_int64(cpu, NAME_BUF, gator_get_time());
40 gator_buffer_write_packed_int(cpu, NAME_BUF, pid); 42 gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
41 gator_buffer_write_string(cpu, NAME_BUF, name); 43 gator_buffer_write_string(cpu, NAME_BUF, name);
42 } 44 }
43 local_irq_restore(flags);
44 buffer_check(cpu, NAME_BUF); 45 buffer_check(cpu, NAME_BUF);
46 local_irq_restore(flags);
45} 47}
46 48
47static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel) { 49static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel)
50{
48 int cpu = smp_processor_id(); 51 int cpu = smp_processor_id();
49 if (buffer_check_space(cpu, BACKTRACE_BUF, gator_backtrace_depth*2*MAXSIZE_PACK32)) { 52 if (buffer_check_space(cpu, BACKTRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32 + gator_backtrace_depth * 2 * MAXSIZE_PACK32)) {
50 gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, gator_get_time()); 53 gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, gator_get_time());
51 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, exec_cookie); 54 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, exec_cookie);
52 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, tgid); 55 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, tgid);
53 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, pid); 56 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, pid);
54 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, inKernel); 57 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, inKernel);
55 return true; 58 return true;
@@ -61,13 +64,15 @@ static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inK
61 return false; 64 return false;
62} 65}
63 66
64static void marshal_backtrace(unsigned long address, int cookie) { 67static void marshal_backtrace(unsigned long address, int cookie)
68{
65 int cpu = smp_processor_id(); 69 int cpu = smp_processor_id();
66 gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, address);
67 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie); 70 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie);
71 gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, address);
68} 72}
69 73
70static void marshal_backtrace_footer(void) { 74static void marshal_backtrace_footer(void)
75{
71 int cpu = smp_processor_id(); 76 int cpu = smp_processor_id();
72 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_END_BACKTRACE); 77 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_END_BACKTRACE);
73 78
@@ -75,30 +80,31 @@ static void marshal_backtrace_footer(void) {
75 buffer_check(cpu, BACKTRACE_BUF); 80 buffer_check(cpu, BACKTRACE_BUF);
76} 81}
77 82
78static bool marshal_event_header(void) { 83static bool marshal_event_header(void)
84{
79 unsigned long flags, cpu = smp_processor_id(); 85 unsigned long flags, cpu = smp_processor_id();
80 bool retval = false; 86 bool retval = false;
81 87
82 local_irq_save(flags); 88 local_irq_save(flags);
83 if (buffer_check_space(cpu, BLOCK_COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) { 89 if (buffer_check_space(cpu, BLOCK_COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
84 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0); // key of zero indicates a timestamp 90 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0); // key of zero indicates a timestamp
85 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, gator_get_time()); 91 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, gator_get_time());
86 retval = true; 92 retval = true;
87 } 93 }
88 local_irq_restore(flags);
89
90 // Check and commit; commit is set to occur once buffer is 3/4 full 94 // Check and commit; commit is set to occur once buffer is 3/4 full
91 buffer_check(cpu, BLOCK_COUNTER_BUF); 95 buffer_check(cpu, BLOCK_COUNTER_BUF);
96 local_irq_restore(flags);
92 97
93 return retval; 98 return retval;
94} 99}
95 100
96static void marshal_event(int len, int* buffer) { 101static void marshal_event(int len, int *buffer)
102{
97 unsigned long i, flags, cpu = smp_processor_id(); 103 unsigned long i, flags, cpu = smp_processor_id();
98 104
99 if (len <= 0) 105 if (len <= 0)
100 return; 106 return;
101 107
102 // length must be even since all data is a (key, value) pair 108 // length must be even since all data is a (key, value) pair
103 if (len & 0x1) { 109 if (len & 0x1) {
104 pr_err("gator: invalid counter data detected and discarded"); 110 pr_err("gator: invalid counter data detected and discarded");
@@ -106,27 +112,26 @@ static void marshal_event(int len, int* buffer) {
106 } 112 }
107 113
108 // events must be written in key,value pairs 114 // events must be written in key,value pairs
115 local_irq_save(flags);
109 for (i = 0; i < len; i += 2) { 116 for (i = 0; i < len; i += 2) {
110 local_irq_save(flags); 117 if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK32)) {
111 if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2*MAXSIZE_PACK32)) {
112 local_irq_restore(flags);
113 break; 118 break;
114 } 119 }
115 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i]); 120 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i]);
116 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i + 1]); 121 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i + 1]);
117 local_irq_restore(flags);
118 } 122 }
119
120 // Check and commit; commit is set to occur once buffer is 3/4 full 123 // Check and commit; commit is set to occur once buffer is 3/4 full
121 buffer_check(cpu, BLOCK_COUNTER_BUF); 124 buffer_check(cpu, BLOCK_COUNTER_BUF);
125 local_irq_restore(flags);
122} 126}
123 127
124static void marshal_event64(int len, long long* buffer64) { 128static void marshal_event64(int len, long long *buffer64)
129{
125 unsigned long i, flags, cpu = smp_processor_id(); 130 unsigned long i, flags, cpu = smp_processor_id();
126 131
127 if (len <= 0) 132 if (len <= 0)
128 return; 133 return;
129 134
130 // length must be even since all data is a (key, value) pair 135 // length must be even since all data is a (key, value) pair
131 if (len & 0x1) { 136 if (len & 0x1) {
132 pr_err("gator: invalid counter data detected and discarded"); 137 pr_err("gator: invalid counter data detected and discarded");
@@ -134,48 +139,47 @@ static void marshal_event64(int len, long long* buffer64) {
134 } 139 }
135 140
136 // events must be written in key,value pairs 141 // events must be written in key,value pairs
142 local_irq_save(flags);
137 for (i = 0; i < len; i += 2) { 143 for (i = 0; i < len; i += 2) {
138 local_irq_save(flags); 144 if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK64)) {
139 if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2*MAXSIZE_PACK64)) {
140 local_irq_restore(flags);
141 break; 145 break;
142 } 146 }
143 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i]); 147 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i]);
144 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i + 1]); 148 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i + 1]);
145 local_irq_restore(flags);
146 } 149 }
147
148 // Check and commit; commit is set to occur once buffer is 3/4 full 150 // Check and commit; commit is set to occur once buffer is 3/4 full
149 buffer_check(cpu, BLOCK_COUNTER_BUF); 151 buffer_check(cpu, BLOCK_COUNTER_BUF);
152 local_irq_restore(flags);
150} 153}
151 154
152#if GATOR_CPU_FREQ_SUPPORT 155#if GATOR_CPU_FREQ_SUPPORT
153static void marshal_event_single(int core, int key, int value) { 156static void marshal_event_single(int core, int key, int value)
157{
154 unsigned long flags, cpu; 158 unsigned long flags, cpu;
155 159
156 local_irq_save(flags); 160 local_irq_save(flags);
157 cpu = smp_processor_id(); 161 cpu = smp_processor_id();
158 if (buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK64 + 3*MAXSIZE_PACK32)) { 162 if (buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
159 gator_buffer_write_packed_int64(cpu, COUNTER_BUF, gator_get_time()); 163 gator_buffer_write_packed_int64(cpu, COUNTER_BUF, gator_get_time());
160 gator_buffer_write_packed_int(cpu, COUNTER_BUF, core); 164 gator_buffer_write_packed_int(cpu, COUNTER_BUF, core);
161 gator_buffer_write_packed_int(cpu, COUNTER_BUF, key); 165 gator_buffer_write_packed_int(cpu, COUNTER_BUF, key);
162 gator_buffer_write_packed_int(cpu, COUNTER_BUF, value); 166 gator_buffer_write_packed_int(cpu, COUNTER_BUF, value);
163 } 167 }
164 local_irq_restore(flags);
165
166 // Check and commit; commit is set to occur once buffer is 3/4 full 168 // Check and commit; commit is set to occur once buffer is 3/4 full
167 buffer_check(cpu, COUNTER_BUF); 169 buffer_check(cpu, COUNTER_BUF);
170 local_irq_restore(flags);
168} 171}
169#endif 172#endif
170 173
171static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid) { 174static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid)
175{
172 unsigned long cpu = smp_processor_id(), flags; 176 unsigned long cpu = smp_processor_id(), flags;
173 177
174 if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF]) 178 if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
175 return; 179 return;
176 180
177 local_irq_save(flags); 181 local_irq_save(flags);
178 if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5*MAXSIZE_PACK32)) { 182 if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
179 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_START); 183 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_START);
180 gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, gator_get_time()); 184 gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, gator_get_time());
181 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit); 185 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
@@ -183,39 +187,39 @@ static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid) {
183 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, tgid); 187 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, tgid);
184 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, pid); 188 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, pid);
185 } 189 }
186 local_irq_restore(flags);
187
188 // Check and commit; commit is set to occur once buffer is 3/4 full 190 // Check and commit; commit is set to occur once buffer is 3/4 full
189 buffer_check(cpu, GPU_TRACE_BUF); 191 buffer_check(cpu, GPU_TRACE_BUF);
192 local_irq_restore(flags);
190} 193}
191 194
192static void marshal_sched_gpu_stop(int unit, int core) { 195static void marshal_sched_gpu_stop(int unit, int core)
196{
193 unsigned long cpu = smp_processor_id(), flags; 197 unsigned long cpu = smp_processor_id(), flags;
194 198
195 if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF]) 199 if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
196 return; 200 return;
197 201
198 local_irq_save(flags); 202 local_irq_save(flags);
199 if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 3*MAXSIZE_PACK32)) { 203 if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
200 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_STOP); 204 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_STOP);
201 gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, gator_get_time()); 205 gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, gator_get_time());
202 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit); 206 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
203 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core); 207 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
204 } 208 }
205 local_irq_restore(flags);
206
207 // Check and commit; commit is set to occur once buffer is 3/4 full 209 // Check and commit; commit is set to occur once buffer is 3/4 full
208 buffer_check(cpu, GPU_TRACE_BUF); 210 buffer_check(cpu, GPU_TRACE_BUF);
211 local_irq_restore(flags);
209} 212}
210 213
211static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state) { 214static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state)
215{
212 unsigned long cpu = smp_processor_id(), flags; 216 unsigned long cpu = smp_processor_id(), flags;
213 217
214 if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF]) 218 if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
215 return; 219 return;
216 220
217 local_irq_save(flags); 221 local_irq_save(flags);
218 if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5*MAXSIZE_PACK32)) { 222 if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
219 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_SWITCH); 223 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_SWITCH);
220 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, gator_get_time()); 224 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, gator_get_time());
221 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid); 225 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid);
@@ -223,49 +227,88 @@ static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state)
223 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie); 227 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie);
224 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state); 228 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state);
225 } 229 }
226 local_irq_restore(flags);
227
228 // Check and commit; commit is set to occur once buffer is 3/4 full 230 // Check and commit; commit is set to occur once buffer is 3/4 full
229 buffer_check(cpu, SCHED_TRACE_BUF); 231 buffer_check(cpu, SCHED_TRACE_BUF);
232 local_irq_restore(flags);
230} 233}
231 234
232static void marshal_sched_trace_exit(int tgid, int pid) { 235static void marshal_sched_trace_exit(int tgid, int pid)
236{
233 unsigned long cpu = smp_processor_id(), flags; 237 unsigned long cpu = smp_processor_id(), flags;
234 238
235 if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF]) 239 if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
236 return; 240 return;
237 241
238 local_irq_save(flags); 242 local_irq_save(flags);
239 if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 2*MAXSIZE_PACK32)) { 243 if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
240 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_EXIT); 244 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_EXIT);
241 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, gator_get_time()); 245 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, gator_get_time());
242 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid); 246 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
243 } 247 }
244 local_irq_restore(flags);
245
246 // Check and commit; commit is set to occur once buffer is 3/4 full 248 // Check and commit; commit is set to occur once buffer is 3/4 full
247 buffer_check(cpu, SCHED_TRACE_BUF); 249 buffer_check(cpu, SCHED_TRACE_BUF);
250 local_irq_restore(flags);
248} 251}
249 252
250#if GATOR_CPU_FREQ_SUPPORT 253#if GATOR_CPU_FREQ_SUPPORT
251static void marshal_idle(int core, int state) { 254static void marshal_idle(int core, int state)
255{
252 unsigned long flags, cpu; 256 unsigned long flags, cpu;
253 257
254 local_irq_save(flags); 258 local_irq_save(flags);
255 cpu = smp_processor_id(); 259 cpu = smp_processor_id();
256 if (buffer_check_space(cpu, IDLE_BUF, MAXSIZE_PACK64 + 2*MAXSIZE_PACK32)) { 260 if (buffer_check_space(cpu, IDLE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
257 gator_buffer_write_packed_int(cpu, IDLE_BUF, state); 261 gator_buffer_write_packed_int(cpu, IDLE_BUF, state);
258 gator_buffer_write_packed_int64(cpu, IDLE_BUF, gator_get_time()); 262 gator_buffer_write_packed_int64(cpu, IDLE_BUF, gator_get_time());
259 gator_buffer_write_packed_int(cpu, IDLE_BUF, core); 263 gator_buffer_write_packed_int(cpu, IDLE_BUF, core);
260 } 264 }
261 local_irq_restore(flags);
262
263 // Check and commit; commit is set to occur once buffer is 3/4 full 265 // Check and commit; commit is set to occur once buffer is 3/4 full
264 buffer_check(cpu, IDLE_BUF); 266 buffer_check(cpu, IDLE_BUF);
267 local_irq_restore(flags);
265} 268}
266#endif 269#endif
267 270
268static void marshal_frame(int cpu, int buftype, int frame) { 271static void marshal_frame(int cpu, int buftype)
272{
273 int frame;
274
275 if (!per_cpu(gator_buffer, cpu)[buftype]) {
276 return;
277 }
278
279 switch (buftype) {
280 case SUMMARY_BUF:
281 frame = FRAME_SUMMARY;
282 break;
283 case BACKTRACE_BUF:
284 frame = FRAME_BACKTRACE;
285 break;
286 case NAME_BUF:
287 frame = FRAME_NAME;
288 break;
289 case COUNTER_BUF:
290 frame = FRAME_COUNTER;
291 break;
292 case BLOCK_COUNTER_BUF:
293 frame = FRAME_BLOCK_COUNTER;
294 break;
295 case ANNOTATE_BUF:
296 frame = FRAME_ANNOTATE;
297 break;
298 case SCHED_TRACE_BUF:
299 frame = FRAME_SCHED_TRACE;
300 break;
301 case GPU_TRACE_BUF:
302 frame = FRAME_GPU_TRACE;
303 break;
304 case IDLE_BUF:
305 frame = FRAME_IDLE;
306 break;
307 default:
308 frame = -1;
309 break;
310 }
311
269 // add response type 312 // add response type
270 if (gator_response_type > 0) { 313 if (gator_response_type > 0) {
271 gator_buffer_write_packed_int(cpu, buftype, gator_response_type); 314 gator_buffer_write_packed_int(cpu, buftype, gator_response_type);
@@ -280,7 +323,8 @@ static void marshal_frame(int cpu, int buftype, int frame) {
280} 323}
281 324
282#if defined(__arm__) || defined(__aarch64__) 325#if defined(__arm__) || defined(__aarch64__)
283static void marshal_core_name(const char* name) { 326static void marshal_core_name(const char *name)
327{
284 int cpu = smp_processor_id(); 328 int cpu = smp_processor_id();
285 unsigned long flags; 329 unsigned long flags;
286 local_irq_save(flags); 330 local_irq_save(flags);
@@ -288,8 +332,7 @@ static void marshal_core_name(const char* name) {
288 gator_buffer_write_packed_int(cpu, NAME_BUF, HRTIMER_CORE_NAME); 332 gator_buffer_write_packed_int(cpu, NAME_BUF, HRTIMER_CORE_NAME);
289 gator_buffer_write_string(cpu, NAME_BUF, name); 333 gator_buffer_write_string(cpu, NAME_BUF, name);
290 } 334 }
291 local_irq_restore(flags);
292
293 buffer_check(cpu, NAME_BUF); 335 buffer_check(cpu, NAME_BUF);
336 local_irq_restore(flags);
294} 337}
295#endif 338#endif
diff --git a/driver/gator_pack.c b/driver/gator_pack.c
index 5ad53db..119746b 100644
--- a/driver/gator_pack.c
+++ b/driver/gator_pack.c
@@ -21,23 +21,23 @@ static void gator_buffer_write_packed_int(int cpu, int buftype, unsigned int x)
21 } else if ((x & 0xffffc000) == 0) { 21 } else if ((x & 0xffffc000) == 0) {
22 int write2 = (write + 2) & mask; 22 int write2 = (write + 2) & mask;
23 buffer[write0] = x | 0x80; 23 buffer[write0] = x | 0x80;
24 buffer[write1] = (x>>7) & 0x7f; 24 buffer[write1] = (x >> 7) & 0x7f;
25 per_cpu(gator_buffer_write, cpu)[buftype] = write2; 25 per_cpu(gator_buffer_write, cpu)[buftype] = write2;
26 } else if ((x & 0xffe00000) == 0) { 26 } else if ((x & 0xffe00000) == 0) {
27 int write2 = (write + 2) & mask; 27 int write2 = (write + 2) & mask;
28 int write3 = (write + 3) & mask; 28 int write3 = (write + 3) & mask;
29 buffer[write0] = x | 0x80; 29 buffer[write0] = x | 0x80;
30 buffer[write1] = (x>>7) | 0x80; 30 buffer[write1] = (x >> 7) | 0x80;
31 buffer[write2] = (x>>14) & 0x7f; 31 buffer[write2] = (x >> 14) & 0x7f;
32 per_cpu(gator_buffer_write, cpu)[buftype] = write3; 32 per_cpu(gator_buffer_write, cpu)[buftype] = write3;
33 } else if ((x & 0xf0000000) == 0) { 33 } else if ((x & 0xf0000000) == 0) {
34 int write2 = (write + 2) & mask; 34 int write2 = (write + 2) & mask;
35 int write3 = (write + 3) & mask; 35 int write3 = (write + 3) & mask;
36 int write4 = (write + 4) & mask; 36 int write4 = (write + 4) & mask;
37 buffer[write0] = x | 0x80; 37 buffer[write0] = x | 0x80;
38 buffer[write1] = (x>>7) | 0x80; 38 buffer[write1] = (x >> 7) | 0x80;
39 buffer[write2] = (x>>14) | 0x80; 39 buffer[write2] = (x >> 14) | 0x80;
40 buffer[write3] = (x>>21) & 0x7f; 40 buffer[write3] = (x >> 21) & 0x7f;
41 per_cpu(gator_buffer_write, cpu)[buftype] = write4; 41 per_cpu(gator_buffer_write, cpu)[buftype] = write4;
42 } else { 42 } else {
43 int write2 = (write + 2) & mask; 43 int write2 = (write + 2) & mask;
@@ -45,10 +45,10 @@ static void gator_buffer_write_packed_int(int cpu, int buftype, unsigned int x)
45 int write4 = (write + 4) & mask; 45 int write4 = (write + 4) & mask;
46 int write5 = (write + 5) & mask; 46 int write5 = (write + 5) & mask;
47 buffer[write0] = x | 0x80; 47 buffer[write0] = x | 0x80;
48 buffer[write1] = (x>>7) | 0x80; 48 buffer[write1] = (x >> 7) | 0x80;
49 buffer[write2] = (x>>14) | 0x80; 49 buffer[write2] = (x >> 14) | 0x80;
50 buffer[write3] = (x>>21) | 0x80; 50 buffer[write3] = (x >> 21) | 0x80;
51 buffer[write4] = (x>>28) & 0x0f; 51 buffer[write4] = (x >> 28) & 0x0f;
52 per_cpu(gator_buffer_write, cpu)[buftype] = write5; 52 per_cpu(gator_buffer_write, cpu)[buftype] = write5;
53 } 53 }
54} 54}
@@ -67,23 +67,23 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long
67 } else if ((x & 0xffffffffffffc000LL) == 0) { 67 } else if ((x & 0xffffffffffffc000LL) == 0) {
68 int write2 = (write + 2) & mask; 68 int write2 = (write + 2) & mask;
69 buffer[write0] = x | 0x80; 69 buffer[write0] = x | 0x80;
70 buffer[write1] = (x>>7) & 0x7f; 70 buffer[write1] = (x >> 7) & 0x7f;
71 per_cpu(gator_buffer_write, cpu)[buftype] = write2; 71 per_cpu(gator_buffer_write, cpu)[buftype] = write2;
72 } else if ((x & 0xffffffffffe00000LL) == 0) { 72 } else if ((x & 0xffffffffffe00000LL) == 0) {
73 int write2 = (write + 2) & mask; 73 int write2 = (write + 2) & mask;
74 int write3 = (write + 3) & mask; 74 int write3 = (write + 3) & mask;
75 buffer[write0] = x | 0x80; 75 buffer[write0] = x | 0x80;
76 buffer[write1] = (x>>7) | 0x80; 76 buffer[write1] = (x >> 7) | 0x80;
77 buffer[write2] = (x>>14) & 0x7f; 77 buffer[write2] = (x >> 14) & 0x7f;
78 per_cpu(gator_buffer_write, cpu)[buftype] = write3; 78 per_cpu(gator_buffer_write, cpu)[buftype] = write3;
79 } else if ((x & 0xfffffffff0000000LL) == 0) { 79 } else if ((x & 0xfffffffff0000000LL) == 0) {
80 int write2 = (write + 2) & mask; 80 int write2 = (write + 2) & mask;
81 int write3 = (write + 3) & mask; 81 int write3 = (write + 3) & mask;
82 int write4 = (write + 4) & mask; 82 int write4 = (write + 4) & mask;
83 buffer[write0] = x | 0x80; 83 buffer[write0] = x | 0x80;
84 buffer[write1] = (x>>7) | 0x80; 84 buffer[write1] = (x >> 7) | 0x80;
85 buffer[write2] = (x>>14) | 0x80; 85 buffer[write2] = (x >> 14) | 0x80;
86 buffer[write3] = (x>>21) & 0x7f; 86 buffer[write3] = (x >> 21) & 0x7f;
87 per_cpu(gator_buffer_write, cpu)[buftype] = write4; 87 per_cpu(gator_buffer_write, cpu)[buftype] = write4;
88 } else if ((x & 0xfffffff800000000LL) == 0) { 88 } else if ((x & 0xfffffff800000000LL) == 0) {
89 int write2 = (write + 2) & mask; 89 int write2 = (write + 2) & mask;
@@ -91,10 +91,10 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long
91 int write4 = (write + 4) & mask; 91 int write4 = (write + 4) & mask;
92 int write5 = (write + 5) & mask; 92 int write5 = (write + 5) & mask;
93 buffer[write0] = x | 0x80; 93 buffer[write0] = x | 0x80;
94 buffer[write1] = (x>>7) | 0x80; 94 buffer[write1] = (x >> 7) | 0x80;
95 buffer[write2] = (x>>14) | 0x80; 95 buffer[write2] = (x >> 14) | 0x80;
96 buffer[write3] = (x>>21) | 0x80; 96 buffer[write3] = (x >> 21) | 0x80;
97 buffer[write4] = (x>>28) & 0x7f; 97 buffer[write4] = (x >> 28) & 0x7f;
98 per_cpu(gator_buffer_write, cpu)[buftype] = write5; 98 per_cpu(gator_buffer_write, cpu)[buftype] = write5;
99 } else if ((x & 0xfffffc0000000000LL) == 0) { 99 } else if ((x & 0xfffffc0000000000LL) == 0) {
100 int write2 = (write + 2) & mask; 100 int write2 = (write + 2) & mask;
@@ -103,11 +103,11 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long
103 int write5 = (write + 5) & mask; 103 int write5 = (write + 5) & mask;
104 int write6 = (write + 6) & mask; 104 int write6 = (write + 6) & mask;
105 buffer[write0] = x | 0x80; 105 buffer[write0] = x | 0x80;
106 buffer[write1] = (x>>7) | 0x80; 106 buffer[write1] = (x >> 7) | 0x80;
107 buffer[write2] = (x>>14) | 0x80; 107 buffer[write2] = (x >> 14) | 0x80;
108 buffer[write3] = (x>>21) | 0x80; 108 buffer[write3] = (x >> 21) | 0x80;
109 buffer[write4] = (x>>28) | 0x80; 109 buffer[write4] = (x >> 28) | 0x80;
110 buffer[write5] = (x>>35) & 0x7f; 110 buffer[write5] = (x >> 35) & 0x7f;
111 per_cpu(gator_buffer_write, cpu)[buftype] = write6; 111 per_cpu(gator_buffer_write, cpu)[buftype] = write6;
112 } else if ((x & 0xfffe000000000000LL) == 0) { 112 } else if ((x & 0xfffe000000000000LL) == 0) {
113 int write2 = (write + 2) & mask; 113 int write2 = (write + 2) & mask;
@@ -117,12 +117,12 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long
117 int write6 = (write + 6) & mask; 117 int write6 = (write + 6) & mask;
118 int write7 = (write + 7) & mask; 118 int write7 = (write + 7) & mask;
119 buffer[write0] = x | 0x80; 119 buffer[write0] = x | 0x80;
120 buffer[write1] = (x>>7) | 0x80; 120 buffer[write1] = (x >> 7) | 0x80;
121 buffer[write2] = (x>>14) | 0x80; 121 buffer[write2] = (x >> 14) | 0x80;
122 buffer[write3] = (x>>21) | 0x80; 122 buffer[write3] = (x >> 21) | 0x80;
123 buffer[write4] = (x>>28) | 0x80; 123 buffer[write4] = (x >> 28) | 0x80;
124 buffer[write5] = (x>>35) | 0x80; 124 buffer[write5] = (x >> 35) | 0x80;
125 buffer[write6] = (x>>42) & 0x7f; 125 buffer[write6] = (x >> 42) & 0x7f;
126 per_cpu(gator_buffer_write, cpu)[buftype] = write7; 126 per_cpu(gator_buffer_write, cpu)[buftype] = write7;
127 } else if ((x & 0xff00000000000000LL) == 0) { 127 } else if ((x & 0xff00000000000000LL) == 0) {
128 int write2 = (write + 2) & mask; 128 int write2 = (write + 2) & mask;
@@ -133,13 +133,13 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long
133 int write7 = (write + 7) & mask; 133 int write7 = (write + 7) & mask;
134 int write8 = (write + 8) & mask; 134 int write8 = (write + 8) & mask;
135 buffer[write0] = x | 0x80; 135 buffer[write0] = x | 0x80;
136 buffer[write1] = (x>>7) | 0x80; 136 buffer[write1] = (x >> 7) | 0x80;
137 buffer[write2] = (x>>14) | 0x80; 137 buffer[write2] = (x >> 14) | 0x80;
138 buffer[write3] = (x>>21) | 0x80; 138 buffer[write3] = (x >> 21) | 0x80;
139 buffer[write4] = (x>>28) | 0x80; 139 buffer[write4] = (x >> 28) | 0x80;
140 buffer[write5] = (x>>35) | 0x80; 140 buffer[write5] = (x >> 35) | 0x80;
141 buffer[write6] = (x>>42) | 0x80; 141 buffer[write6] = (x >> 42) | 0x80;
142 buffer[write7] = (x>>49) & 0x7f; 142 buffer[write7] = (x >> 49) & 0x7f;
143 per_cpu(gator_buffer_write, cpu)[buftype] = write8; 143 per_cpu(gator_buffer_write, cpu)[buftype] = write8;
144 } else if ((x & 0x8000000000000000LL) == 0) { 144 } else if ((x & 0x8000000000000000LL) == 0) {
145 int write2 = (write + 2) & mask; 145 int write2 = (write + 2) & mask;
@@ -151,14 +151,14 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long
151 int write8 = (write + 8) & mask; 151 int write8 = (write + 8) & mask;
152 int write9 = (write + 9) & mask; 152 int write9 = (write + 9) & mask;
153 buffer[write0] = x | 0x80; 153 buffer[write0] = x | 0x80;
154 buffer[write1] = (x>>7) | 0x80; 154 buffer[write1] = (x >> 7) | 0x80;
155 buffer[write2] = (x>>14) | 0x80; 155 buffer[write2] = (x >> 14) | 0x80;
156 buffer[write3] = (x>>21) | 0x80; 156 buffer[write3] = (x >> 21) | 0x80;
157 buffer[write4] = (x>>28) | 0x80; 157 buffer[write4] = (x >> 28) | 0x80;
158 buffer[write5] = (x>>35) | 0x80; 158 buffer[write5] = (x >> 35) | 0x80;
159 buffer[write6] = (x>>42) | 0x80; 159 buffer[write6] = (x >> 42) | 0x80;
160 buffer[write7] = (x>>49) | 0x80; 160 buffer[write7] = (x >> 49) | 0x80;
161 buffer[write8] = (x>>56) & 0x7f; 161 buffer[write8] = (x >> 56) & 0x7f;
162 per_cpu(gator_buffer_write, cpu)[buftype] = write9; 162 per_cpu(gator_buffer_write, cpu)[buftype] = write9;
163 } else { 163 } else {
164 int write2 = (write + 2) & mask; 164 int write2 = (write + 2) & mask;
@@ -171,15 +171,15 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long
171 int write9 = (write + 9) & mask; 171 int write9 = (write + 9) & mask;
172 int write10 = (write + 10) & mask; 172 int write10 = (write + 10) & mask;
173 buffer[write0] = x | 0x80; 173 buffer[write0] = x | 0x80;
174 buffer[write1] = (x>>7) | 0x80; 174 buffer[write1] = (x >> 7) | 0x80;
175 buffer[write2] = (x>>14) | 0x80; 175 buffer[write2] = (x >> 14) | 0x80;
176 buffer[write3] = (x>>21) | 0x80; 176 buffer[write3] = (x >> 21) | 0x80;
177 buffer[write4] = (x>>28) | 0x80; 177 buffer[write4] = (x >> 28) | 0x80;
178 buffer[write5] = (x>>35) | 0x80; 178 buffer[write5] = (x >> 35) | 0x80;
179 buffer[write6] = (x>>42) | 0x80; 179 buffer[write6] = (x >> 42) | 0x80;
180 buffer[write7] = (x>>49) | 0x80; 180 buffer[write7] = (x >> 49) | 0x80;
181 buffer[write8] = (x>>56) | 0x80; 181 buffer[write8] = (x >> 56) | 0x80;
182 buffer[write9] = (x>>63) & 0x7f; 182 buffer[write9] = (x >> 63) & 0x7f;
183 per_cpu(gator_buffer_write, cpu)[buftype] = write10; 183 per_cpu(gator_buffer_write, cpu)[buftype] = write10;
184 } 184 }
185} 185}
diff --git a/driver/gator_trace_gpu.c b/driver/gator_trace_gpu.c
index 0511d71..9fc488b 100644
--- a/driver/gator_trace_gpu.c
+++ b/driver/gator_trace_gpu.c
@@ -27,7 +27,6 @@
27#define EVENT_TYPE_SUSPEND 3 27#define EVENT_TYPE_SUSPEND 3
28#define EVENT_TYPE_RESUME 4 28#define EVENT_TYPE_RESUME 4
29 29
30
31/* Note whether tracepoints have been registered */ 30/* Note whether tracepoints have been registered */
32static int mali_timeline_trace_registered; 31static int mali_timeline_trace_registered;
33static int mali_job_slots_trace_registered; 32static int mali_job_slots_trace_registered;
@@ -49,34 +48,33 @@ static int gpu_trace_registered;
49 */ 48 */
50enum { 49enum {
51 EVENT_CHANNEL_SOFTWARE = 0, 50 EVENT_CHANNEL_SOFTWARE = 0,
52 EVENT_CHANNEL_VP0 = 1, 51 EVENT_CHANNEL_VP0 = 1,
53 EVENT_CHANNEL_FP0 = 5, 52 EVENT_CHANNEL_FP0 = 5,
54 EVENT_CHANNEL_FP1, 53 EVENT_CHANNEL_FP1,
55 EVENT_CHANNEL_FP2, 54 EVENT_CHANNEL_FP2,
56 EVENT_CHANNEL_FP3, 55 EVENT_CHANNEL_FP3,
57 EVENT_CHANNEL_FP4, 56 EVENT_CHANNEL_FP4,
58 EVENT_CHANNEL_FP5, 57 EVENT_CHANNEL_FP5,
59 EVENT_CHANNEL_FP6, 58 EVENT_CHANNEL_FP6,
60 EVENT_CHANNEL_FP7, 59 EVENT_CHANNEL_FP7,
61 EVENT_CHANNEL_GPU = 21 60 EVENT_CHANNEL_GPU = 21
62}; 61};
63 62
64/** 63/**
65 * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from the GPU channel 64 * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from the GPU channel
66 */ 65 */
67enum { 66enum {
68 EVENT_REASON_SINGLE_GPU_NONE = 0, 67 EVENT_REASON_SINGLE_GPU_NONE = 0,
69 EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1, 68 EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1,
70}; 69};
71 70
72
73GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned int d2, unsigned int d3, unsigned int d4)) 71GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned int d2, unsigned int d3, unsigned int d4))
74{ 72{
75 unsigned int component, state; 73 unsigned int component, state;
76 74
77 // do as much work as possible before disabling interrupts 75 // do as much work as possible before disabling interrupts
78 component = (event_id >> 16) & 0xFF; // component is an 8-bit field 76 component = (event_id >> 16) & 0xFF; // component is an 8-bit field
79 state = (event_id >> 24) & 0xF; // state is a 4-bit field 77 state = (event_id >> 24) & 0xF; // state is a 4-bit field
80 78
81 switch (state) { 79 switch (state) {
82 case EVENT_TYPE_START: 80 case EVENT_TYPE_START:
@@ -101,7 +99,7 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned
101 if (component == EVENT_CHANNEL_GPU) { 99 if (component == EVENT_CHANNEL_GPU) {
102 unsigned int reason = (event_id & 0xffff); 100 unsigned int reason = (event_id & 0xffff);
103 101
104 if(reason == EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE) { 102 if (reason == EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE) {
105 gator_events_mali_log_dvfs_event(d0, d1); 103 gator_events_mali_log_dvfs_event(d0, d1);
106 } 104 }
107 } 105 }
@@ -118,11 +116,10 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne
118{ 116{
119 unsigned int component, state, unit; 117 unsigned int component, state, unit;
120 118
121 component = (event_id >> 16) & 0xFF; // component is an 8-bit field 119 component = (event_id >> 16) & 0xFF; // component is an 8-bit field
122 state = (event_id >> 24) & 0xF; // state is a 4-bit field 120 state = (event_id >> 24) & 0xF; // state is a 4-bit field
123 121
124 switch (component) 122 switch (component) {
125 {
126 case 0: 123 case 0:
127 unit = GPU_UNIT_FP; 124 unit = GPU_UNIT_FP;
128 break; 125 break;
@@ -136,9 +133,8 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne
136 unit = GPU_UNIT_NONE; 133 unit = GPU_UNIT_NONE;
137 } 134 }
138 135
139 if (unit != GPU_UNIT_NONE) 136 if (unit != GPU_UNIT_NONE) {
140 { 137 switch (state) {
141 switch(state) {
142 case EVENT_TYPE_START: 138 case EVENT_TYPE_START:
143 marshal_sched_gpu_start(unit, 0, tgid, (pid != 0 ? pid : tgid)); 139 marshal_sched_gpu_start(unit, 0, tgid, (pid != 0 ? pid : tgid));
144 break; 140 break;
@@ -175,27 +171,27 @@ int gator_trace_gpu_start(void)
175 gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0; 171 gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
176 172
177#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx) 173#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
178 if (!GATOR_REGISTER_TRACE(mali_timeline_event)) { 174 if (!GATOR_REGISTER_TRACE(mali_timeline_event)) {
179 mali_timeline_trace_registered = 1; 175 mali_timeline_trace_registered = 1;
180 } 176 }
181#endif 177#endif
182 178
183#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx) 179#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
184 if (!GATOR_REGISTER_TRACE(mali_job_slots_event)) { 180 if (!GATOR_REGISTER_TRACE(mali_job_slots_event)) {
185 mali_job_slots_trace_registered = 1; 181 mali_job_slots_trace_registered = 1;
186 } 182 }
187#endif 183#endif
188 184
189 if (!mali_timeline_trace_registered) { 185 if (!mali_timeline_trace_registered) {
190 if (GATOR_REGISTER_TRACE(gpu_activity_start)) { 186 if (GATOR_REGISTER_TRACE(gpu_activity_start)) {
191 return 0; 187 return 0;
192 } 188 }
193 if (GATOR_REGISTER_TRACE(gpu_activity_stop)) { 189 if (GATOR_REGISTER_TRACE(gpu_activity_stop)) {
194 GATOR_UNREGISTER_TRACE(gpu_activity_start); 190 GATOR_UNREGISTER_TRACE(gpu_activity_start);
195 return 0; 191 return 0;
196 } 192 }
197 gpu_trace_registered = 1; 193 gpu_trace_registered = 1;
198 } 194 }
199 195
200 return 0; 196 return 0;
201} 197}
diff --git a/driver/gator_trace_gpu.h b/driver/gator_trace_gpu.h
index 894289b..efb47c6 100644
--- a/driver/gator_trace_gpu.h
+++ b/driver/gator_trace_gpu.h
@@ -28,50 +28,50 @@
28 */ 28 */
29TRACE_EVENT(gpu_activity_start, 29TRACE_EVENT(gpu_activity_start,
30 30
31 TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p), 31 TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p),
32 32
33 TP_ARGS(gpu_unit, gpu_core, p), 33 TP_ARGS(gpu_unit, gpu_core, p),
34 34
35 TP_STRUCT__entry( 35 TP_STRUCT__entry(
36 __field( int, gpu_unit ) 36 __field(int, gpu_unit)
37 __field( int, gpu_core ) 37 __field(int, gpu_core)
38 __array( char, comm, TASK_COMM_LEN ) 38 __array(char, comm, TASK_COMM_LEN)
39 __field( pid_t, pid ) 39 __field(pid_t, pid)
40 ), 40 ),
41 41
42 TP_fast_assign( 42 TP_fast_assign(
43 __entry->gpu_unit = gpu_unit; 43 __entry->gpu_unit = gpu_unit;
44 __entry->gpu_core = gpu_core; 44 __entry->gpu_core = gpu_core;
45 memcpy(__entry->comm, p->comm, TASK_COMM_LEN); 45 memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
46 __entry->pid = p->pid; 46 __entry->pid = p->pid;
47 ), 47 ),
48 48
49 TP_printk("unit=%d core=%d comm=%s pid=%d", 49 TP_printk("unit=%d core=%d comm=%s pid=%d",
50 __entry->gpu_unit, __entry->gpu_core, __entry->comm, __entry->pid) 50 __entry->gpu_unit, __entry->gpu_core, __entry->comm,
51); 51 __entry->pid)
52 );
52 53
53/* 54/*
54 * Tracepoint for calling GPU unit stop activity on core 55 * Tracepoint for calling GPU unit stop activity on core
55 */ 56 */
56TRACE_EVENT(gpu_activity_stop, 57TRACE_EVENT(gpu_activity_stop,
57 58
58 TP_PROTO(int gpu_unit, int gpu_core), 59 TP_PROTO(int gpu_unit, int gpu_core),
59 60
60 TP_ARGS(gpu_unit, gpu_core), 61 TP_ARGS(gpu_unit, gpu_core),
61 62
62 TP_STRUCT__entry( 63 TP_STRUCT__entry(
63 __field( int, gpu_unit ) 64 __field(int, gpu_unit)
64 __field( int, gpu_core ) 65 __field(int, gpu_core)
65 ), 66 ),
66 67
67 TP_fast_assign( 68 TP_fast_assign(
68 __entry->gpu_unit = gpu_unit; 69 __entry->gpu_unit = gpu_unit;
69 __entry->gpu_core = gpu_core; 70 __entry->gpu_core = gpu_core;
70 ), 71 ),
71 72
72 TP_printk("unit=%d core=%d", 73 TP_printk("unit=%d core=%d", __entry->gpu_unit, __entry->gpu_core)
73 __entry->gpu_unit, __entry->gpu_core) 74 );
74);
75 75
76#endif /* _TRACE_GPU_H */ 76#endif /* _TRACE_GPU_H */
77 77
diff --git a/driver/gator_trace_power.c b/driver/gator_trace_power.c
index b1687e1..79fa13c 100644
--- a/driver/gator_trace_power.c
+++ b/driver/gator_trace_power.c
@@ -9,8 +9,19 @@
9 9
10#include <linux/cpufreq.h> 10#include <linux/cpufreq.h>
11#include <trace/events/power.h> 11#include <trace/events/power.h>
12
13#if defined(__arm__)
14
12#include <asm/mach-types.h> 15#include <asm/mach-types.h>
13 16
17#define implements_wfi() (!machine_is_omap3_beagle())
18
19#else
20
21#define implements_wfi() false
22
23#endif
24
14// cpu_frequency and cpu_idle trace points were introduced in Linux kernel v2.6.38 25// cpu_frequency and cpu_idle trace points were introduced in Linux kernel v2.6.38
15// the now deprecated power_frequency trace point was available prior to 2.6.38, but only for x86 26// the now deprecated power_frequency trace point was available prior to 2.6.38, but only for x86
16#if GATOR_CPU_FREQ_SUPPORT 27#if GATOR_CPU_FREQ_SUPPORT
@@ -61,9 +72,9 @@ GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu))
61 return; 72 return;
62 } 73 }
63 74
64 if (!machine_is_omap3_beagle()) { 75 if (implements_wfi()) {
65 if (state == PWR_EVENT_EXIT) { 76 if (state == PWR_EVENT_EXIT) {
66 // transition from wfi to non-wfi 77 // transition from wfi to non-wfi
67 marshal_idle(cpu, WFI_EXIT); 78 marshal_idle(cpu, WFI_EXIT);
68 } else { 79 } else {
69 // transition from non-wfi to wfi 80 // transition from non-wfi to wfi
@@ -149,10 +160,29 @@ void gator_trace_power_init(void)
149 } 160 }
150} 161}
151#else 162#else
152static int gator_trace_power_create_files(struct super_block *sb, struct dentry *root) {return 0;} 163static int gator_trace_power_create_files(struct super_block *sb, struct dentry *root)
153static void gator_trace_power_online(void) {} 164{
154static void gator_trace_power_offline(void) {} 165 return 0;
155static int gator_trace_power_start(void) {return 0;} 166}
156static void gator_trace_power_stop(void) {} 167
157void gator_trace_power_init(void) {} 168static void gator_trace_power_online(void)
169{
170}
171
172static void gator_trace_power_offline(void)
173{
174}
175
176static int gator_trace_power_start(void)
177{
178 return 0;
179}
180
181static void gator_trace_power_stop(void)
182{
183}
184
185void gator_trace_power_init(void)
186{
187}
158#endif 188#endif
diff --git a/driver/gator_trace_sched.c b/driver/gator_trace_sched.c
index 9ddb822..d0336f9 100644
--- a/driver/gator_trace_sched.c
+++ b/driver/gator_trace_sched.c
@@ -13,7 +13,7 @@
13#define SCHED_SWITCH 1 13#define SCHED_SWITCH 1
14#define SCHED_PROCESS_EXIT 2 14#define SCHED_PROCESS_EXIT 2
15 15
16#define TASK_MAP_ENTRIES 1024 /* must be power of 2 */ 16#define TASK_MAP_ENTRIES 1024 /* must be power of 2 */
17#define TASK_MAX_COLLISIONS 2 17#define TASK_MAX_COLLISIONS 2
18 18
19static DEFINE_PER_CPU(uint64_t *, taskname_keys); 19static DEFINE_PER_CPU(uint64_t *, taskname_keys);
@@ -26,14 +26,14 @@ enum {
26 STATE_WAIT_ON_MUTEX, 26 STATE_WAIT_ON_MUTEX,
27}; 27};
28 28
29void emit_pid_name(struct task_struct* task) 29void emit_pid_name(struct task_struct *task)
30{ 30{
31 bool found = false; 31 bool found = false;
32 char taskcomm[TASK_COMM_LEN + 3]; 32 char taskcomm[TASK_COMM_LEN + 3];
33 unsigned long x, cpu = smp_processor_id(); 33 unsigned long x, cpu = smp_processor_id();
34 uint64_t *keys = &(per_cpu(taskname_keys, cpu)[(task->pid & 0xFF) * TASK_MAX_COLLISIONS]); 34 uint64_t *keys = &(per_cpu(taskname_keys, cpu)[(task->pid & 0xFF) * TASK_MAX_COLLISIONS]);
35 uint64_t value; 35 uint64_t value;
36 36
37 value = gator_chksum_crc32(task->comm); 37 value = gator_chksum_crc32(task->comm);
38 value = (value << 32) | (uint32_t)task->pid; 38 value = (value << 32) | (uint32_t)task->pid;
39 39
@@ -64,7 +64,6 @@ void emit_pid_name(struct task_struct* task)
64 } 64 }
65} 65}
66 66
67
68static void collect_counters(void) 67static void collect_counters(void)
69{ 68{
70 int *buffer, len; 69 int *buffer, len;
@@ -84,7 +83,7 @@ static void collect_counters(void)
84 } 83 }
85} 84}
86 85
87static void probe_sched_write(int type, struct task_struct* task, struct task_struct* old_task) 86static void probe_sched_write(int type, struct task_struct *task, struct task_struct *old_task)
88{ 87{
89 int cookie = 0, state = 0; 88 int cookie = 0, state = 0;
90 int cpu = smp_processor_id(); 89 int cpu = smp_processor_id();
@@ -141,7 +140,14 @@ GATOR_DEFINE_PROBE(sched_process_exit, TP_PROTO(struct task_struct *p))
141 probe_sched_write(SCHED_PROCESS_EXIT, p, 0); 140 probe_sched_write(SCHED_PROCESS_EXIT, p, 0);
142} 141}
143 142
144static int register_scheduler_tracepoints(void) { 143static void do_nothing(void *info)
144{
145 // Intentionally do nothing
146 (void)info;
147}
148
149static int register_scheduler_tracepoints(void)
150{
145 // register tracepoints 151 // register tracepoints
146 if (GATOR_REGISTER_TRACE(sched_switch)) 152 if (GATOR_REGISTER_TRACE(sched_switch))
147 goto fail_sched_switch; 153 goto fail_sched_switch;
@@ -149,6 +155,10 @@ static int register_scheduler_tracepoints(void) {
149 goto fail_sched_process_exit; 155 goto fail_sched_process_exit;
150 pr_debug("gator: registered tracepoints\n"); 156 pr_debug("gator: registered tracepoints\n");
151 157
158 // Now that the scheduler tracepoint is registered, force a context switch
159 // on all cpus to capture what is currently running.
160 on_each_cpu(do_nothing, NULL, 0);
161
152 return 0; 162 return 0;
153 163
154 // unregister tracepoints on error 164 // unregister tracepoints on error
@@ -166,7 +176,7 @@ int gator_trace_sched_start(void)
166 176
167 for_each_present_cpu(cpu) { 177 for_each_present_cpu(cpu) {
168 size = TASK_MAP_ENTRIES * TASK_MAX_COLLISIONS * sizeof(uint64_t); 178 size = TASK_MAP_ENTRIES * TASK_MAX_COLLISIONS * sizeof(uint64_t);
169 per_cpu(taskname_keys, cpu) = (uint64_t*)kmalloc(size, GFP_KERNEL); 179 per_cpu(taskname_keys, cpu) = (uint64_t *)kmalloc(size, GFP_KERNEL);
170 if (!per_cpu(taskname_keys, cpu)) 180 if (!per_cpu(taskname_keys, cpu))
171 return -1; 181 return -1;
172 memset(per_cpu(taskname_keys, cpu), 0, size); 182 memset(per_cpu(taskname_keys, cpu), 0, size);