summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Medhurst2013-12-18 08:45:18 -0600
committerJon Medhurst2013-12-18 08:45:18 -0600
commitc3fc2b13fd58f1f5db521a062f0bbf782874383c (patch)
tree76c3c628d80d00aba867dafecbf6fe39813d1500
parent6f4705753bf6ede126239aa56eb518dfc4397b11 (diff)
downloadarm-ds5-gator-c3fc2b13fd58f1f5db521a062f0bbf782874383c.tar.gz
arm-ds5-gator-c3fc2b13fd58f1f5db521a062f0bbf782874383c.tar.xz
arm-ds5-gator-c3fc2b13fd58f1f5db521a062f0bbf782874383c.zip
gator: Version 5.17
Signed-off-by: Jon Medhurst <tixy@linaro.org>
-rw-r--r--daemon/Buffer.cpp11
-rw-r--r--daemon/Buffer.h5
-rw-r--r--daemon/Child.cpp13
-rw-r--r--daemon/Child.h4
-rw-r--r--daemon/ConfigurationXML.h4
-rw-r--r--daemon/Driver.h6
-rw-r--r--daemon/Fifo.h4
-rw-r--r--daemon/Hwmon.cpp4
-rw-r--r--daemon/Hwmon.h4
-rw-r--r--daemon/OlySocket.cpp23
-rw-r--r--daemon/Sender.h4
-rw-r--r--daemon/SessionData.cpp12
-rw-r--r--daemon/SessionData.h6
-rw-r--r--daemon/SessionXML.h4
-rw-r--r--daemon/StreamlineSetup.h4
-rw-r--r--daemon/common.mk2
-rw-r--r--daemon/events-CCI-400.xml62
-rw-r--r--daemon/events-Linux.xml10
-rw-r--r--daemon/events-Mali-T6xx.xml10
-rw-r--r--daemon/events-Mali-T6xx_hw.xml5
-rw-r--r--daemon/main.cpp25
-rw-r--r--driver/Makefile61
-rw-r--r--driver/gator.h6
-rw-r--r--driver/gator_annotate_kernel.c107
-rw-r--r--driver/gator_backtrace.c10
-rw-r--r--driver/gator_cookies.c36
-rwxr-xr-xdriver/gator_events.sh19
-rw-r--r--driver/gator_events_armv6.c7
-rw-r--r--driver/gator_events_armv7.c7
-rw-r--r--driver/gator_events_block.c2
-rw-r--r--driver/gator_events_ccn-504.c192
-rw-r--r--driver/gator_events_irq.c2
-rw-r--r--driver/gator_events_l2c-310.c2
-rw-r--r--driver/gator_events_mali_4xx.c30
-rw-r--r--driver/gator_events_mali_common.c9
-rw-r--r--driver/gator_events_mali_common.h4
-rw-r--r--driver/gator_events_mali_t6xx.c60
-rw-r--r--driver/gator_events_mali_t6xx_hw.c46
-rw-r--r--driver/gator_events_meminfo.c301
-rw-r--r--driver/gator_events_mmapped.c (renamed from driver/gator_events_mmaped.c)124
-rw-r--r--driver/gator_events_net.c5
-rw-r--r--driver/gator_events_perf_pmu.c83
-rw-r--r--driver/gator_events_sched.c2
-rw-r--r--driver/gator_events_scorpion.c7
-rw-r--r--driver/gator_main.c114
-rw-r--r--driver/gator_marshaling.c19
-rw-r--r--driver/gator_trace_gpu.c6
-rw-r--r--driver/gator_trace_sched.c20
-rw-r--r--driver/mali/mali_mjollnir_profiling_gator_api.h15
-rw-r--r--driver/mali/mali_utgard_profiling_gator_api.h15
-rw-r--r--driver/mali_t6xx.mk11
51 files changed, 1058 insertions, 486 deletions
diff --git a/daemon/Buffer.cpp b/daemon/Buffer.cpp
index c7abbf3..090a715 100644
--- a/daemon/Buffer.cpp
+++ b/daemon/Buffer.cpp
@@ -193,6 +193,17 @@ bool Buffer::eventHeader (const uint64_t curr_time) {
193 return retval; 193 return retval;
194} 194}
195 195
196bool Buffer::eventTid (const int tid) {
197 bool retval = false;
198 if (checkSpace(2*MAXSIZE_PACK32)) {
199 packInt(1); // key of 1 indicates a tid
200 packInt(tid);
201 retval = true;
202 }
203
204 return retval;
205}
206
196void Buffer::event (const int32_t key, const int32_t value) { 207void Buffer::event (const int32_t key, const int32_t value) {
197 if (checkSpace(2 * MAXSIZE_PACK32)) { 208 if (checkSpace(2 * MAXSIZE_PACK32)) {
198 packInt(key); 209 packInt(key);
diff --git a/daemon/Buffer.h b/daemon/Buffer.h
index f820cfd..b3c8d78 100644
--- a/daemon/Buffer.h
+++ b/daemon/Buffer.h
@@ -32,6 +32,7 @@ public:
32 void frame (); 32 void frame ();
33 33
34 bool eventHeader (uint64_t curr_time); 34 bool eventHeader (uint64_t curr_time);
35 bool eventTid (int tid);
35 void event (int32_t key, int32_t value); 36 void event (int32_t key, int32_t value);
36 void event64 (int64_t key, int64_t value); 37 void event64 (int64_t key, int64_t value);
37 38
@@ -56,6 +57,10 @@ private:
56 char *const buf; 57 char *const buf;
57 uint64_t commitTime; 58 uint64_t commitTime;
58 sem_t *const readerSem; 59 sem_t *const readerSem;
60
61 // Intentionally unimplemented
62 Buffer(const Buffer &);
63 Buffer &operator=(const Buffer &);
59}; 64};
60 65
61#endif // BUFFER_H 66#endif // BUFFER_H
diff --git a/daemon/Child.cpp b/daemon/Child.cpp
index c054076..9ee2ef8 100644
--- a/daemon/Child.cpp
+++ b/daemon/Child.cpp
@@ -86,7 +86,7 @@ static void child_handler(int signum) {
86 } 86 }
87} 87}
88 88
89static void* durationThread(void* pVoid) { 89static void *durationThread(void *) {
90 prctl(PR_SET_NAME, (unsigned long)&"gatord-duration", 0, 0, 0); 90 prctl(PR_SET_NAME, (unsigned long)&"gatord-duration", 0, 0, 0);
91 sem_wait(&startProfile); 91 sem_wait(&startProfile);
92 if (gSessionData->mSessionIsActive) { 92 if (gSessionData->mSessionIsActive) {
@@ -102,7 +102,7 @@ static void* durationThread(void* pVoid) {
102 return 0; 102 return 0;
103} 103}
104 104
105static void* stopThread(void* pVoid) { 105static void *stopThread(void *) {
106 OlySocket* socket = child->socket; 106 OlySocket* socket = child->socket;
107 107
108 prctl(PR_SET_NAME, (unsigned long)&"gatord-stopper", 0, 0, 0); 108 prctl(PR_SET_NAME, (unsigned long)&"gatord-stopper", 0, 0, 0);
@@ -139,7 +139,7 @@ static void* stopThread(void* pVoid) {
139 return 0; 139 return 0;
140} 140}
141 141
142void* countersThread(void* pVoid) { 142static void *countersThread(void *) {
143 prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0); 143 prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0);
144 144
145 gSessionData->hwmon.start(); 145 gSessionData->hwmon.start();
@@ -192,7 +192,7 @@ void* countersThread(void* pVoid) {
192 return NULL; 192 return NULL;
193} 193}
194 194
195static void* senderThread(void* pVoid) { 195static void *senderThread(void *) {
196 int length = 1; 196 int length = 1;
197 char* data; 197 char* data;
198 char end_sequence[] = {RESPONSE_APC_DATA, 0, 0, 0, 0}; 198 char end_sequence[] = {RESPONSE_APC_DATA, 0, 0, 0, 0};
@@ -340,7 +340,8 @@ void Child::run() {
340 thread_creation_success = false; 340 thread_creation_success = false;
341 } 341 }
342 342
343 if (gSessionData->hwmon.countersEnabled()) { 343 bool startcountersThread = gSessionData->hwmon.countersEnabled();
344 if (startcountersThread) {
344 if (pthread_create(&countersThreadID, NULL, countersThread, this)) { 345 if (pthread_create(&countersThreadID, NULL, countersThread, this)) {
345 thread_creation_success = false; 346 thread_creation_success = false;
346 } 347 }
@@ -378,7 +379,7 @@ void Child::run() {
378 } while (bytesCollected > 0); 379 } while (bytesCollected > 0);
379 logg->logMessage("Exit collect data loop"); 380 logg->logMessage("Exit collect data loop");
380 381
381 if (gSessionData->hwmon.countersEnabled()) { 382 if (startcountersThread) {
382 pthread_join(countersThreadID, NULL); 383 pthread_join(countersThreadID, NULL);
383 } 384 }
384 385
diff --git a/daemon/Child.h b/daemon/Child.h
index e39d182..0330e9d 100644
--- a/daemon/Child.h
+++ b/daemon/Child.h
@@ -26,6 +26,10 @@ private:
26 int mNumConnections; 26 int mNumConnections;
27 27
28 void initialization(); 28 void initialization();
29
30 // Intentionally unimplemented
31 Child(const Child &);
32 Child &operator=(const Child &);
29}; 33};
30 34
31#endif //__CHILD_H__ 35#endif //__CHILD_H__
diff --git a/daemon/ConfigurationXML.h b/daemon/ConfigurationXML.h
index eba7dc4..5650f48 100644
--- a/daemon/ConfigurationXML.h
+++ b/daemon/ConfigurationXML.h
@@ -29,6 +29,10 @@ private:
29 int parse(const char* xmlFile); 29 int parse(const char* xmlFile);
30 int configurationsTag(mxml_node_t *node); 30 int configurationsTag(mxml_node_t *node);
31 void configurationTag(mxml_node_t *node); 31 void configurationTag(mxml_node_t *node);
32
33 // Intentionally unimplemented
34 ConfigurationXML(const ConfigurationXML &);
35 ConfigurationXML &operator=(const ConfigurationXML &);
32}; 36};
33 37
34#endif // COUNTERS_H 38#endif // COUNTERS_H
diff --git a/daemon/Driver.h b/daemon/Driver.h
index dd1dc27..f3a932f 100644
--- a/daemon/Driver.h
+++ b/daemon/Driver.h
@@ -29,7 +29,7 @@ public:
29 // Emits available counters 29 // Emits available counters
30 virtual void writeCounters(mxml_node_t *root) const = 0; 30 virtual void writeCounters(mxml_node_t *root) const = 0;
31 // Emits possible dynamically generated events/counters 31 // Emits possible dynamically generated events/counters
32 virtual void writeEvents(mxml_node_t *root) const {} 32 virtual void writeEvents(mxml_node_t *) const {}
33 33
34 Driver *getNext() const { return next; } 34 Driver *getNext() const { return next; }
35 35
@@ -39,6 +39,10 @@ protected:
39private: 39private:
40 static Driver *head; 40 static Driver *head;
41 Driver *next; 41 Driver *next;
42
43 // Intentionally unimplemented
44 Driver(const Driver &);
45 Driver &operator=(const Driver &);
42}; 46};
43 47
44#endif // DRIVER_H 48#endif // DRIVER_H
diff --git a/daemon/Fifo.h b/daemon/Fifo.h
index ada42b9..d25cd68 100644
--- a/daemon/Fifo.h
+++ b/daemon/Fifo.h
@@ -39,6 +39,10 @@ private:
39 sem_t* mReaderSem; 39 sem_t* mReaderSem;
40 char* mBuffer; 40 char* mBuffer;
41 bool mEnd; 41 bool mEnd;
42
43 // Intentionally unimplemented
44 Fifo(const Fifo &);
45 Fifo &operator=(const Fifo &);
42}; 46};
43 47
44#endif //__FIFO_H__ 48#endif //__FIFO_H__
diff --git a/daemon/Hwmon.cpp b/daemon/Hwmon.cpp
index 0792568..1d7c0da 100644
--- a/daemon/Hwmon.cpp
+++ b/daemon/Hwmon.cpp
@@ -63,6 +63,10 @@ private:
63 double previous_value; 63 double previous_value;
64 64
65 sensors_subfeature_type input; 65 sensors_subfeature_type input;
66
67 // Intentionally unimplemented
68 HwmonCounter(const HwmonCounter &);
69 HwmonCounter &operator=(const HwmonCounter &);
66}; 70};
67 71
68HwmonCounter::HwmonCounter(HwmonCounter *next, int key, const sensors_chip_name *chip, const sensors_feature *feature) : next(next), key(key), polled(false), readable(false), enabled(false), duplicate(false), chip(chip), feature(feature) { 72HwmonCounter::HwmonCounter(HwmonCounter *next, int key, const sensors_chip_name *chip, const sensors_feature *feature) : next(next), key(key), polled(false), readable(false), enabled(false), duplicate(false), chip(chip), feature(feature) {
diff --git a/daemon/Hwmon.h b/daemon/Hwmon.h
index 35981dc..46bb42e 100644
--- a/daemon/Hwmon.h
+++ b/daemon/Hwmon.h
@@ -34,6 +34,10 @@ private:
34 HwmonCounter *findCounter(const Counter &counter) const; 34 HwmonCounter *findCounter(const Counter &counter) const;
35 35
36 HwmonCounter *counters; 36 HwmonCounter *counters;
37
38 // Intentionally unimplemented
39 Hwmon(const Hwmon &);
40 Hwmon &operator=(const Hwmon &);
37}; 41};
38 42
39#endif // HWMON_H 43#endif // HWMON_H
diff --git a/daemon/OlySocket.cpp b/daemon/OlySocket.cpp
index 132510d..ab5c3c2 100644
--- a/daemon/OlySocket.cpp
+++ b/daemon/OlySocket.cpp
@@ -11,6 +11,7 @@
11#include <stdio.h> 11#include <stdio.h>
12#ifdef WIN32 12#ifdef WIN32
13#include <Winsock2.h> 13#include <Winsock2.h>
14#include <ws2tcpip.h>
14#else 15#else
15#include <netinet/in.h> 16#include <netinet/in.h>
16#include <sys/socket.h> 17#include <sys/socket.h>
@@ -126,11 +127,17 @@ void OlySocket::createSingleServerConnection(int port) {
126} 127}
127 128
128void OlySocket::createServerSocket(int port) { 129void OlySocket::createServerSocket(int port) {
130 int family = AF_INET6;
131
129 // Create socket 132 // Create socket
130 mFDServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 133 mFDServer = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
131 if (mFDServer < 0) { 134 if (mFDServer < 0) {
132 logg->logError(__FILE__, __LINE__, "Error creating server socket"); 135 family = AF_INET;
133 handleException(); 136 mFDServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
137 if (mFDServer < 0) {
138 logg->logError(__FILE__, __LINE__, "Error creating server socket");
139 handleException();
140 }
134 } 141 }
135 142
136 // Enable address reuse, another solution would be to create the server socket once and only close it when the object exits 143 // Enable address reuse, another solution would be to create the server socket once and only close it when the object exits
@@ -141,11 +148,11 @@ void OlySocket::createServerSocket(int port) {
141 } 148 }
142 149
143 // Create sockaddr_in structure, ensuring non-populated fields are zero 150 // Create sockaddr_in structure, ensuring non-populated fields are zero
144 struct sockaddr_in sockaddr; 151 struct sockaddr_in6 sockaddr;
145 memset((void*)&sockaddr, 0, sizeof(struct sockaddr_in)); 152 memset((void*)&sockaddr, 0, sizeof(sockaddr));
146 sockaddr.sin_family = AF_INET; 153 sockaddr.sin6_family = family;
147 sockaddr.sin_port = htons(port); 154 sockaddr.sin6_port = htons(port);
148 sockaddr.sin_addr.s_addr = INADDR_ANY; 155 sockaddr.sin6_addr = in6addr_any;
149 156
150 // Bind the socket to an address 157 // Bind the socket to an address
151 if (bind(mFDServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) { 158 if (bind(mFDServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
diff --git a/daemon/Sender.h b/daemon/Sender.h
index 8f23361..b388f03 100644
--- a/daemon/Sender.h
+++ b/daemon/Sender.h
@@ -33,6 +33,10 @@ private:
33 FILE* mDataFile; 33 FILE* mDataFile;
34 char* mDataFileName; 34 char* mDataFileName;
35 pthread_mutex_t mSendMutex; 35 pthread_mutex_t mSendMutex;
36
37 // Intentionally unimplemented
38 Sender(const Sender &);
39 Sender &operator=(const Sender &);
36}; 40};
37 41
38#endif //__SENDER_H__ 42#endif //__SENDER_H__
diff --git a/daemon/SessionData.cpp b/daemon/SessionData.cpp
index 4068d4e..cf84407 100644
--- a/daemon/SessionData.cpp
+++ b/daemon/SessionData.cpp
@@ -44,13 +44,13 @@ void SessionData::parseSessionXML(char* xmlString) {
44 SessionXML session(xmlString); 44 SessionXML session(xmlString);
45 session.parse(); 45 session.parse();
46 46
47 // Set session data values 47 // Set session data values - use prime numbers just below the desired value to reduce the chance of events firing at the same time
48 if (strcmp(session.parameters.sample_rate, "high") == 0) { 48 if (strcmp(session.parameters.sample_rate, "high") == 0) {
49 mSampleRate = 10000; 49 mSampleRate = 9973; // 10000
50 } else if (strcmp(session.parameters.sample_rate, "normal") == 0) { 50 } else if (strcmp(session.parameters.sample_rate, "normal") == 0) {
51 mSampleRate = 1000; 51 mSampleRate = 997; // 1000
52 } else if (strcmp(session.parameters.sample_rate, "low") == 0) { 52 } else if (strcmp(session.parameters.sample_rate, "low") == 0) {
53 mSampleRate = 100; 53 mSampleRate = 97; // 100
54 } else if (strcmp(session.parameters.sample_rate, "none") == 0) { 54 } else if (strcmp(session.parameters.sample_rate, "none") == 0) {
55 mSampleRate = 0; 55 mSampleRate = 0;
56 } else { 56 } else {
@@ -139,7 +139,9 @@ void SessionData::readCpuInfo() {
139 } 139 }
140 140
141int getEventKey() { 141int getEventKey() {
142 // Start one after the gator.ko's value of 1 142 // key 0 is reserved as a timestamp
143 // key 1 is reserved as the marker for thread specific counters
144 // Odd keys are assigned by the driver, even keys by the daemon
143 static int key = 2; 145 static int key = 2;
144 146
145 const int ret = key; 147 const int ret = key;
diff --git a/daemon/SessionData.h b/daemon/SessionData.h
index e72fa5d..c834251 100644
--- a/daemon/SessionData.h
+++ b/daemon/SessionData.h
@@ -16,7 +16,7 @@
16 16
17#define MAX_PERFORMANCE_COUNTERS 50 17#define MAX_PERFORMANCE_COUNTERS 50
18 18
19#define PROTOCOL_VERSION 16 19#define PROTOCOL_VERSION 17
20#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions 20#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions
21 21
22struct ImageLinkList { 22struct ImageLinkList {
@@ -62,6 +62,10 @@ public:
62 62
63private: 63private:
64 void readCpuInfo(); 64 void readCpuInfo();
65
66 // Intentionally unimplemented
67 SessionData(const SessionData &);
68 SessionData &operator=(const SessionData &);
65}; 69};
66 70
67extern SessionData* gSessionData; 71extern SessionData* gSessionData;
diff --git a/daemon/SessionXML.h b/daemon/SessionXML.h
index c7e3798..0fb03bd 100644
--- a/daemon/SessionXML.h
+++ b/daemon/SessionXML.h
@@ -33,6 +33,10 @@ private:
33 char* mPath; 33 char* mPath;
34 void sessionTag(mxml_node_t *tree, mxml_node_t *node); 34 void sessionTag(mxml_node_t *tree, mxml_node_t *node);
35 void sessionImage(mxml_node_t *node); 35 void sessionImage(mxml_node_t *node);
36
37 // Intentionally unimplemented
38 SessionXML(const SessionXML &);
39 SessionXML &operator=(const SessionXML &);
36}; 40};
37 41
38#endif // SESSION_XML_H 42#endif // SESSION_XML_H
diff --git a/daemon/StreamlineSetup.h b/daemon/StreamlineSetup.h
index 092d956..d6d9a6e 100644
--- a/daemon/StreamlineSetup.h
+++ b/daemon/StreamlineSetup.h
@@ -38,6 +38,10 @@ private:
38 void sendDefaults(); 38 void sendDefaults();
39 void sendCounters(); 39 void sendCounters();
40 void writeConfiguration(char* xml); 40 void writeConfiguration(char* xml);
41
42 // Intentionally unimplemented
43 StreamlineSetup(const StreamlineSetup &);
44 StreamlineSetup &operator=(const StreamlineSetup &);
41}; 45};
42 46
43#endif //__STREAMLINE_SETUP_H__ 47#endif //__STREAMLINE_SETUP_H__
diff --git a/daemon/common.mk b/daemon/common.mk
index ee2415b..031d169 100644
--- a/daemon/common.mk
+++ b/daemon/common.mk
@@ -6,7 +6,7 @@
6# -std=c++0x is the planned new c++ standard 6# -std=c++0x is the planned new c++ standard
7# -std=c++98 is the 1998 c++ standard 7# -std=c++98 is the 1998 c++ standard
8CFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors 8CFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors
9CXXFLAGS += -fno-rtti 9CXXFLAGS += -fno-rtti -Wextra # -Weffc++
10ifeq ($(WERROR),1) 10ifeq ($(WERROR),1)
11 CFLAGS += -Werror 11 CFLAGS += -Werror
12endif 12endif
diff --git a/daemon/events-CCI-400.xml b/daemon/events-CCI-400.xml
index 86db208..4fa7711 100644
--- a/daemon/events-CCI-400.xml
+++ b/daemon/events-CCI-400.xml
@@ -17,7 +17,7 @@
17 <event event="0x04" option_set="Slave" title="CCI-400" name="Read: cache" description="Read request handshake: cache maintenance operation, CleanInvalid, CleanShared, MakeInvalid"/> 17 <event event="0x04" option_set="Slave" title="CCI-400" name="Read: cache" description="Read request handshake: cache maintenance operation, CleanInvalid, CleanShared, MakeInvalid"/>
18 <event event="0x05" option_set="Slave" title="CCI-400" name="Read: memory barrier" description="Read request handshake: memory barrier"/> 18 <event event="0x05" option_set="Slave" title="CCI-400" name="Read: memory barrier" description="Read request handshake: memory barrier"/>
19 <event event="0x06" option_set="Slave" title="CCI-400" name="Read: sync barrier" description="Read request handshake: synchronization barrier"/> 19 <event event="0x06" option_set="Slave" title="CCI-400" name="Read: sync barrier" description="Read request handshake: synchronization barrier"/>
20 <event event="0x07" option_set="Slave" title="CCI-400" name="Read: DVM message, no sync" description="Read request handshake: DVM message, no synchronization"/> 20 <event event="0x07" option_set="Slave" title="CCI-400" name="Read: DVM message, no sync" description="Read request handshake: DVM message, not synchronization"/>
21 <event event="0x08" option_set="Slave" title="CCI-400" name="Read: DVM message, sync" description="Read request handshake: DVM message, synchronization"/> 21 <event event="0x08" option_set="Slave" title="CCI-400" name="Read: DVM message, sync" description="Read request handshake: DVM message, synchronization"/>
22 <event event="0x09" option_set="Slave" title="CCI-400" name="Read: stall" description="Read request stall cycle because the transaction tracker is full. Increase SIx_R_MAX to avoid this stall"/> 22 <event event="0x09" option_set="Slave" title="CCI-400" name="Read: stall" description="Read request stall cycle because the transaction tracker is full. Increase SIx_R_MAX to avoid this stall"/>
23 <event event="0x0a" option_set="Slave" title="CCI-400" name="Read data last handshake" description="Read data last handshake: data returned from the snoop instead of from downstream"/> 23 <event event="0x0a" option_set="Slave" title="CCI-400" name="Read data last handshake" description="Read data last handshake: data returned from the snoop instead of from downstream"/>
@@ -45,3 +45,63 @@
45 <event event="0x19" option_set="Master" title="CCI-400" name="Write stall: barrier hazard" description="Write request stall cycle because of a barrier hazard"/> 45 <event event="0x19" option_set="Master" title="CCI-400" name="Write stall: barrier hazard" description="Write request stall cycle because of a barrier hazard"/>
46 <event event="0x1a" option_set="Master" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase MIx_W_MAX to avoid this stall. See the CoreLink CCI-400 Cache Coherent Interconnect Integration Manual"/> 46 <event event="0x1a" option_set="Master" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase MIx_W_MAX to avoid this stall. See the CoreLink CCI-400 Cache Coherent Interconnect Integration Manual"/>
47 </category> 47 </category>
48
49 <counter_set name="cci-400-r1_cnt" count="4"/>
50 <category name="CCI-400" counter_set="cci-400-r1_cnt" per_cpu="no" supports_event_based_sampling="yes">
51 <event counter="cci-400-r1_ccnt" event="0xff" title="CCI-400 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
52
53 <option_set name="Slave">
54 <option event_delta="0x00" name="S0" description="Slave interface 0"/>
55 <option event_delta="0x20" name="S1" description="Slave interface 1"/>
56 <option event_delta="0x40" name="S2" description="Slave interface 2"/>
57 <option event_delta="0x60" name="S3" description="Slave interface 3"/>
58 <option event_delta="0x80" name="S4" description="Slave interface 4"/>
59 </option_set>
60
61 <event event="0x00" option_set="Slave" title="CCI-400" name="Read: any" description="Read request handshake: any"/>
62 <event event="0x01" option_set="Slave" title="CCI-400" name="Read: transaction" description="Read request handshake: device transaction"/>
63 <event event="0x02" option_set="Slave" title="CCI-400" name="Read: normal" description="Read request handshake: normal, non-shareable or system-shareable, but not barrier or cache maintenance operation"/>
64 <event event="0x03" option_set="Slave" title="CCI-400" name="Read: shareable" description="Read request handshake: inner- or outer-shareable, but not barrier, DVM message or cache maintenance operation"/>
65 <event event="0x04" option_set="Slave" title="CCI-400" name="Read: cache" description="Read request handshake: cache maintenance operation"/>
66 <event event="0x05" option_set="Slave" title="CCI-400" name="Read: memory barrier" description="Read request handshake: memory barrier"/>
67 <event event="0x06" option_set="Slave" title="CCI-400" name="Read: sync barrier" description="Read request handshake: synchronization barrier"/>
68 <event event="0x07" option_set="Slave" title="CCI-400" name="Read: DVM message, no sync" description="Read request handshake: DVM message, not synchronization"/>
69 <event event="0x08" option_set="Slave" title="CCI-400" name="Read: DVM message, sync" description="Read request handshake: DVM message, synchronization"/>
70 <event event="0x09" option_set="Slave" title="CCI-400" name="Read: stall" description="Read request stall cycle because the transaction tracker is full. Increase SIx_R_MAX to avoid this stall"/>
71 <event event="0x0a" option_set="Slave" title="CCI-400" name="Read data last handshake" description="Read data last handshake: data returned from the snoop instead of from downstream"/>
72 <event event="0x0b" option_set="Slave" title="CCI-400" name="Read data stall cycle" description="Read data stall cycle: RVALIDS is HIGH, RREADYS is LOW"/>
73 <event event="0x0c" option_set="Slave" title="CCI-400" name="Write: any" description="Write request handshake: any"/>
74 <event event="0x0d" option_set="Slave" title="CCI-400" name="Write: transaction" description="Write request handshake: device transaction"/>
75 <event event="0x0e" option_set="Slave" title="CCI-400" name="Write: normal" description="Write request handshake: normal, non-shareable, or system-shareable, but not barrier"/>
76 <event event="0x0f" option_set="Slave" title="CCI-400" name="Write: shareable" description="Write request handshake: inner- or outer-shareable, WriteBack or WriteClean"/>
77 <event event="0x10" option_set="Slave" title="CCI-400" name="Write: WriteUnique" description="Write request handshake: WriteUnique"/>
78 <event event="0x11" option_set="Slave" title="CCI-400" name="Write: WriteLineUnique" description="Write request handshake: WriteLineUnique"/>
79 <event event="0x12" option_set="Slave" title="CCI-400" name="Write: Evict" description="Write request handshake: Evict"/>
80 <event event="0x13" option_set="Slave" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase SIx_W_MAX to avoid this stall"/>
81 <event event="0x14" option_set="Slave" title="CCI-400" name="Read stall: slave hazard" description="Read request stall cycle because of a slave interface ID hazard"/>
82
83 <option_set name="Master">
84 <option event_delta="0xa0" name="M0" description="Master interface 0"/>
85 <option event_delta="0xc0" name="M1" description="Master interface 1"/>
86 <option event_delta="0xe0" name="M2" description="Master interface 2"/>
87 </option_set>
88
89 <event event="0x00" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/>
90 <event event="0x01" option_set="Master" title="CCI-400" name="Read stall: address hazard" description="Stall cycle because of an address hazard. A read or write invalidation is stalled because of an outstanding transaction to an overlapping address"/>
91 <event event="0x02" option_set="Master" title="CCI-400" name="Read stall: ID hazard" description="Read request stall cycle because of a master interface ID hazard"/>
92 <event event="0x03" option_set="Master" title="CCI-400" name="Read stall: tracker full" description="A read request with a QoS value in the high priority group is stalled for a cycle because the read transaction queue is full. Increase MIx_R_MAX to avoid this stall"/>
93 <event event="0x04" option_set="Master" title="CCI-400" name="Read stall: barrier hazard" description="Read request stall cycle because of a barrier hazard"/>
94 <event event="0x05" option_set="Master" title="CCI-400" name="Write stall: barrier hazard" description="Write request stall cycle because of a barrier hazard"/>
95 <event event="0x06" option_set="Master" title="CCI-400" name="Write stall: tracker full" description="A write request is stalled for a cycle because the write transaction tracker is full. Increase MIx_W_MAX to avoid this stall"/>
96 <event event="0x07" option_set="Master" title="CCI-400" name="Read Stall: Low Priority" description="A read request with a QoS value in the low priority group is stalled for a cycle because there are no slots available in the read queue for the low priority group"/>
97 <event event="0x08" option_set="Master" title="CCI-400" name="Read Stall: Medium Priority" description="A read request with a QoS value in the medium priority group is stalled for a cycle because there are no slots available in the read queue for the medium priority group"/>
98 <event event="0x09" option_set="Master" title="CCI-400" name="Read Stall: VN0" description="A read request is stalled for a cycle while it was waiting for a QVN token on VN0"/>
99 <event event="0x0a" option_set="Master" title="CCI-400" name="Read Stall: VN1" description="A read request is stalled for a cycle while it was waiting for a QVN token on VN1"/>
100 <event event="0x0b" option_set="Master" title="CCI-400" name="Read Stall: VN2" description="A read request is stalled for a cycle while it was waiting for a QVN token on VN2"/>
101 <event event="0x0c" option_set="Master" title="CCI-400" name="Read Stall: VN3" description="A read request is stalled for a cycle while it was waiting for a QVN token on VN3"/>
102 <event event="0x0d" option_set="Master" title="CCI-400" name="Write Stall: VN0" description="A write request is stalled for a cycle while it was waiting for a QVN token on VN0"/>
103 <event event="0x0e" option_set="Master" title="CCI-400" name="Write Stall: VN1" description="A write request is stalled for a cycle while it was waiting for a QVN token on VN1"/>
104 <event event="0x0f" option_set="Master" title="CCI-400" name="Write Stall: VN2" description="A write request is stalled for a cycle while it was waiting for a QVN token on VN2"/>
105 <event event="0x10" option_set="Master" title="CCI-400" name="Write Stall: VN" description="A write request is stalled for a cycle while it was waiting for a QVN token on VN"/>
106 <event event="0x11" option_set="Master" title="CCI-400" name="WriteUnique or WriteLineUnique Stall" description="A WriteUnique or WriteLineUnique request is stalled for a cycle because of an address hazard"/>
107 </category>
diff --git a/daemon/events-Linux.xml b/daemon/events-Linux.xml
index 4a30ad6..31a90a1 100644
--- a/daemon/events-Linux.xml
+++ b/daemon/events-Linux.xml
@@ -6,11 +6,11 @@
6 <event counter="Linux_net_rx" title="Network" name="Receive" units="B" description="Receive network traffic, including effect from Streamline"/> 6 <event counter="Linux_net_rx" title="Network" name="Receive" units="B" description="Receive network traffic, including effect from Streamline"/>
7 <event counter="Linux_net_tx" title="Network" name="Transmit" units="B" description="Transmit network traffic, including effect from Streamline"/> 7 <event counter="Linux_net_tx" title="Network" name="Transmit" units="B" description="Transmit network traffic, including effect from Streamline"/>
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" proc="yes" description="Total used memory size. Note: a process' used memory includes shared memory that may be counted more than once (equivalent to RES from top). Kernel threads are not filterable."/>
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" 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 OS disk buffers"/> 11 <event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" display="maximum" units="B" 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" series_composition="overlay" average_selection="yes" average_cores="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" series_composition="overlay" average_cores="yes" description="Frequency setting of the CPU"/>
13 <event counter="Linux_power_cpu_idle" title="Idle" name="State" 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="Idle" name="State" per_cpu="yes" display="maximum" description="CPU Idle State + 1, set the Sample Rate to None to prevent the hrtimer from interrupting the system"/>
14 <event counter="Linux_cpu_wait_contention" title="CPU Contention" name="Wait" per_cpu="no" display="average" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" description="Thread waiting on contended resource"/> 14 <event counter="Linux_cpu_wait_contention" title="CPU Contention" name="Wait" per_cpu="no" display="average" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" description="Thread waiting on contended resource"/>
15 <event counter="Linux_cpu_wait_io" title="CPU I/O" name="Wait" per_cpu="no" display="average" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" description="Thread waiting on I/O resource"/> 15 <event counter="Linux_cpu_wait_io" title="CPU I/O" name="Wait" per_cpu="no" display="average" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" description="Thread waiting on I/O resource"/>
16 </category> 16 </category>
diff --git a/daemon/events-Mali-T6xx.xml b/daemon/events-Mali-T6xx.xml
index 647e3d5..2465238 100644
--- a/daemon/events-Mali-T6xx.xml
+++ b/daemon/events-Mali-T6xx.xml
@@ -36,3 +36,13 @@
36 <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_2" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 2" description="Reports the number of newly allocated pages after a MMU page fault in address space 2."/> 36 <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_2" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 2" description="Reports the number of newly allocated pages after a MMU page fault in address space 2."/>
37 <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_3" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 3" description="Reports the number of newly allocated pages after a MMU page fault in address space 3."/> 37 <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_3" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 3" description="Reports the number of newly allocated pages after a MMU page fault in address space 3."/>
38 </category> 38 </category>
39
40 <counter_set name="ARM_Mali-T6xx_Filmstrip_cnt" count="1"/>
41 <category name="ARM Mali-T6xx Filmstrip" counter_set="ARM_Mali-T6xx_Filmstrip_cnt" per_cpu="no">
42 <option_set name="fs">
43 <option event_delta="0x3c" name="1:60" description="captures every 60th frame"/>
44 <option event_delta="0x1e" name="1:30" description="captures every 30th frame"/>
45 <option event_delta="0xa" name="1:10" description="captures every 10th frame"/>
46 </option_set>
47 <event event="0x0400" option_set="fs" title="ARM Mali-T6xx" name="Filmstrip" description="Scaled framebuffer"/>
48 </category>
diff --git a/daemon/events-Mali-T6xx_hw.xml b/daemon/events-Mali-T6xx_hw.xml
index 8cfe7c3..03566cb 100644
--- a/daemon/events-Mali-T6xx_hw.xml
+++ b/daemon/events-Mali-T6xx_hw.xml
@@ -60,12 +60,15 @@
60 60
61 <event counter="ARM_Mali-T6xx_FRAG_THREADS" title="Mali Core Threads" name="Fragment threads" description="Number of fragment threads started"/> 61 <event counter="ARM_Mali-T6xx_FRAG_THREADS" title="Mali Core Threads" name="Fragment threads" description="Number of fragment threads started"/>
62 <event counter="ARM_Mali-T6xx_FRAG_DUMMY_THREADS" title="Mali Core Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/> 62 <event counter="ARM_Mali-T6xx_FRAG_DUMMY_THREADS" title="Mali Core Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
63 <event counter="ARM_Mali-T6xx_COMPUTE_THREADS" title="Mali Core Threads" name="Compute threads" description="Number of vertex\compute threads started"/>
64 <event counter="ARM_Mali-T6xx_FRAG_QUADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/> 63 <event counter="ARM_Mali-T6xx_FRAG_QUADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
65 <event counter="ARM_Mali-T6xx_FRAG_QUADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/> 64 <event counter="ARM_Mali-T6xx_FRAG_QUADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
66 <event counter="ARM_Mali-T6xx_FRAG_THREADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/> 65 <event counter="ARM_Mali-T6xx_FRAG_THREADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
67 <event counter="ARM_Mali-T6xx_FRAG_THREADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/> 66 <event counter="ARM_Mali-T6xx_FRAG_THREADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
68 67
68 <event counter="ARM_Mali-T6xx_COMPUTE_TASKS" title="Mali Compute Threads" name="Compute tasks" description="Number of compute tasks"/>
69 <event counter="ARM_Mali-T6xx_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads started" description="Number of compute threads started"/>
70 <event counter="ARM_Mali-T6xx_COMPUTE_CYCLES_DESC" title="Mali Compute Threads" name="Compute cycles awaiting descriptors" description="Number of compute cycles spent waiting for descriptors"/>
71
69 <event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/> 72 <event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
70 <event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/> 73 <event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
71 <event counter="ARM_Mali-T6xx_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/> 74 <event counter="ARM_Mali-T6xx_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
diff --git a/daemon/main.cpp b/daemon/main.cpp
index d1b0913..bfd36b9 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -93,7 +93,7 @@ static void handler(int signum) {
93} 93}
94 94
95// Child exit Signal Handler 95// Child exit Signal Handler
96static void child_exit(int signum) { 96static void child_exit(int) {
97 int status; 97 int status;
98 int pid = wait(&status); 98 int pid = wait(&status);
99 if (pid != -1) { 99 if (pid != -1) {
@@ -106,13 +106,18 @@ static void child_exit(int signum) {
106 106
107static int udpPort(int port) { 107static int udpPort(int port) {
108 int s; 108 int s;
109 struct sockaddr_in sockaddr; 109 struct sockaddr_in6 sockaddr;
110 int on; 110 int on;
111 int family = AF_INET6;
111 112
112 s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 113 s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
113 if (s == -1) { 114 if (s == -1) {
114 logg->logError(__FILE__, __LINE__, "socket failed"); 115 family = AF_INET;
115 handleException(); 116 s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
117 if (s == -1) {
118 logg->logError(__FILE__, __LINE__, "socket failed");
119 handleException();
120 }
116 } 121 }
117 122
118 on = 1; 123 on = 1;
@@ -122,9 +127,9 @@ static int udpPort(int port) {
122 } 127 }
123 128
124 memset((void*)&sockaddr, 0, sizeof(sockaddr)); 129 memset((void*)&sockaddr, 0, sizeof(sockaddr));
125 sockaddr.sin_family = AF_INET; 130 sockaddr.sin6_family = family;
126 sockaddr.sin_port = htons(port); 131 sockaddr.sin6_port = htons(port);
127 sockaddr.sin_addr.s_addr = INADDR_ANY; 132 sockaddr.sin6_addr = in6addr_any;
128 if (bind(s, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) { 133 if (bind(s, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) {
129 logg->logError(__FILE__, __LINE__, "socket failed"); 134 logg->logError(__FILE__, __LINE__, "socket failed");
130 handleException(); 135 handleException();
@@ -173,7 +178,7 @@ static void* answerThread(void* pVoid) {
173 178
174 for (;;) { 179 for (;;) {
175 char buf[128]; 180 char buf[128];
176 struct sockaddr_in sockaddr; 181 struct sockaddr_in6 sockaddr;
177 socklen_t addrlen; 182 socklen_t addrlen;
178 int read; 183 int read;
179 addrlen = sizeof(sockaddr); 184 addrlen = sizeof(sockaddr);
@@ -386,7 +391,7 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
386} 391}
387 392
388// Gator data flow: collector -> collector fifo -> sender 393// Gator data flow: collector -> collector fifo -> sender
389int main(int argc, char** argv, char* envp[]) { 394int main(int argc, char** argv) {
390 // Ensure proper signal handling by making gatord the process group leader 395 // Ensure proper signal handling by making gatord the process group leader
391 // e.g. it may not be the group leader when launched as 'sudo gatord' 396 // e.g. it may not be the group leader when launched as 'sudo gatord'
392 setsid(); 397 setsid();
diff --git a/driver/Makefile b/driver/Makefile
index 0d4ca68..3dc9d05 100644
--- a/driver/Makefile
+++ b/driver/Makefile
@@ -3,7 +3,8 @@ ifneq ($(KERNELRELEASE),)
3# Uncomment the following line to enable kernel stack unwinding within gator, or update gator_backtrace.c 3# Uncomment the following line to enable kernel stack unwinding within gator, or update gator_backtrace.c
4# EXTRA_CFLAGS += -DGATOR_KERNEL_STACK_UNWINDING 4# EXTRA_CFLAGS += -DGATOR_KERNEL_STACK_UNWINDING
5 5
6obj-m := gator.o 6CONFIG_GATOR ?= m
7obj-$(CONFIG_GATOR) := gator.o
7 8
8gator-y := gator_main.o \ 9gator-y := gator_main.o \
9 gator_events_irq.o \ 10 gator_events_irq.o \
@@ -11,23 +12,40 @@ gator-y := gator_main.o \
11 gator_events_net.o \ 12 gator_events_net.o \
12 gator_events_block.o \ 13 gator_events_block.o \
13 gator_events_meminfo.o \ 14 gator_events_meminfo.o \
14 gator_events_perf_pmu.o 15 gator_events_perf_pmu.o \
15 16 gator_events_mmapped.o \
16gator-y += gator_events_mmaped.o
17 17
18# Convert the old GATOR_WITH_MALI_SUPPORT to the new kernel flags
18ifneq ($(GATOR_WITH_MALI_SUPPORT),) 19ifneq ($(GATOR_WITH_MALI_SUPPORT),)
19ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_T6xx) 20 CONFIG_GATOR_WITH_MALI_SUPPORT := y
20gator-y += gator_events_mali_t6xx.o \ 21 ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_T6xx)
21 gator_events_mali_t6xx_hw.o 22 CONFIG_GATOR_MALI_4XXMP := n
22include $(M)/mali_t6xx.mk 23 CONFIG_GATOR_MALI_T6XX := y
23else 24 else
24gator-y += gator_events_mali_4xx.o 25 CONFIG_GATOR_MALI_4XXMP := y
25endif 26 CONFIG_GATOR_MALI_T6XX := n
26gator-y += gator_events_mali_common.o 27 endif
27EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT) 28 EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT)
28ifneq ($(GATOR_MALI_INTERFACE_STYLE),) 29 ifneq ($(GATOR_MALI_INTERFACE_STYLE),)
29EXTRA_CFLAGS += -DGATOR_MALI_INTERFACE_STYLE=$(GATOR_MALI_INTERFACE_STYLE) 30 EXTRA_CFLAGS += -DGATOR_MALI_INTERFACE_STYLE=$(GATOR_MALI_INTERFACE_STYLE)
31 endif
30endif 32endif
33
34ifeq ($(CONFIG_GATOR_WITH_MALI_SUPPORT),y)
35 ifeq ($(CONFIG_GATOR_MALI_T6XX),y)
36 gator-y += gator_events_mali_t6xx.o \
37 gator_events_mali_t6xx_hw.o
38 include $(src)/mali_t6xx.mk
39 else
40 gator-y += gator_events_mali_4xx.o
41 endif
42 gator-y += gator_events_mali_common.o
43
44 ifneq ($(CONFIG_GATOR_MALI_PATH),)
45 ccflags-y += -I$(CONFIG_GATOR_MALI_PATH)
46 endif
47 ccflags-$(CONFIG_GATOR_MALI_4XXMP) += -DMALI_SUPPORT=MALI_4xx
48 ccflags-$(CONFIG_GATOR_MALI_T6XX) += -DMALI_SUPPORT=MALI_T6xx
31endif 49endif
32 50
33# GATOR_TEST controls whether to include (=1) or exclude (=0) test code. 51# GATOR_TEST controls whether to include (=1) or exclude (=0) test code.
@@ -42,17 +60,6 @@ gator-$(CONFIG_ARM) += gator_events_armv6.o \
42 60
43gator-$(CONFIG_ARM64) += gator_events_ccn-504.o 61gator-$(CONFIG_ARM64) += gator_events_ccn-504.o
44 62
45$(obj)/gator_main.o: gator_events.h
46
47clean-files := gator_events.h
48
49 chk_events.h = :
50 quiet_chk_events.h = echo ' CHK $@'
51silent_chk_events.h = :
52gator_events.h: FORCE
53 @$($(quiet)chk_events.h)
54 $(Q)cd $(obj) ; $(CONFIG_SHELL) $(obj)/gator_events.sh $@
55
56else 63else
57 64
58all: 65all:
@@ -63,7 +70,7 @@ all:
63 $(error) 70 $(error)
64 71
65clean: 72clean:
66 rm -f *.o .*.cmd gator_events.h modules.order Module.symvers gator.ko gator.mod.c 73 rm -f *.o .*.cmd modules.order Module.symvers gator.ko gator.mod.c
67 rm -rf .tmp_versions 74 rm -rf .tmp_versions
68 75
69endif 76endif
diff --git a/driver/gator.h b/driver/gator.h
index 2e122da..d8981ed 100644
--- a/driver/gator.h
+++ b/driver/gator.h
@@ -112,14 +112,10 @@ struct gator_interface {
112 void (*offline_dispatch)(int cpu, bool migrate); // called in process context but may not be running on core 'cpu' 112 void (*offline_dispatch)(int cpu, bool migrate); // called in process context but may not be running on core 'cpu'
113 int (*read)(int **buffer); 113 int (*read)(int **buffer);
114 int (*read64)(long long **buffer); 114 int (*read64)(long long **buffer);
115 int (*read_proc)(long long **buffer, struct task_struct *);
115 struct list_head list; 116 struct list_head list;
116}; 117};
117 118
118// gator_events_init is used as a search term in gator_events.sh
119#define gator_events_init(initfn) \
120 static inline int __gator_events_init_test(void) \
121 { return initfn(); }
122
123int gator_events_install(struct gator_interface *interface); 119int gator_events_install(struct gator_interface *interface);
124int gator_events_get_key(void); 120int gator_events_get_key(void);
125u32 gator_cpuid(void); 121u32 gator_cpuid(void);
diff --git a/driver/gator_annotate_kernel.c b/driver/gator_annotate_kernel.c
index 4715f64..a406e48 100644
--- a/driver/gator_annotate_kernel.c
+++ b/driver/gator_annotate_kernel.c
@@ -29,11 +29,27 @@ static void kannotate_write(const char *ptr, unsigned int size)
29 } 29 }
30} 30}
31 31
32static void marshal_u16(char *buf, u16 val) {
33 buf[0] = val & 0xff;
34 buf[1] = (val >> 8) & 0xff;
35}
36
37static void marshal_u32(char *buf, u32 val) {
38 buf[0] = val & 0xff;
39 buf[1] = (val >> 8) & 0xff;
40 buf[2] = (val >> 16) & 0xff;
41 buf[3] = (val >> 24) & 0xff;
42}
43
32void gator_annotate_channel(int channel, const char *str) 44void gator_annotate_channel(int channel, const char *str)
33{ 45{
34 int str_size = strlen(str) & 0xffff; 46 const u16 str_size = strlen(str) & 0xffff;
35 long long header = ESCAPE_CODE | (STRING_ANNOTATION << 8) | (channel << 16) | ((long long)str_size << 48); 47 char header[8];
36 kannotate_write((char *)&header, sizeof(header)); 48 header[0] = ESCAPE_CODE;
49 header[1] = STRING_ANNOTATION;
50 marshal_u32(header + 2, channel);
51 marshal_u16(header + 6, str_size);
52 kannotate_write(header, sizeof(header));
37 kannotate_write(str, str_size); 53 kannotate_write(str, str_size);
38} 54}
39 55
@@ -48,14 +64,14 @@ EXPORT_SYMBOL(gator_annotate);
48 64
49void gator_annotate_channel_color(int channel, int color, const char *str) 65void gator_annotate_channel_color(int channel, int color, const char *str)
50{ 66{
51 int str_size = (strlen(str) + 4) & 0xffff; 67 const u16 str_size = (strlen(str) + 4) & 0xffff;
52 char header[12]; 68 char header[12];
53 header[0] = ESCAPE_CODE; 69 header[0] = ESCAPE_CODE;
54 header[1] = STRING_ANNOTATION; 70 header[1] = STRING_ANNOTATION;
55 *(u32 *)(&header[2]) = channel; 71 marshal_u32(header + 2, channel);
56 *(u16 *)(&header[6]) = str_size; 72 marshal_u16(header + 6, str_size);
57 *(u32 *)(&header[8]) = color; 73 marshal_u32(header + 8, color);
58 kannotate_write((char *)&header, sizeof(header)); 74 kannotate_write(header, sizeof(header));
59 kannotate_write(str, str_size - 4); 75 kannotate_write(str, str_size - 4);
60} 76}
61 77
@@ -70,8 +86,12 @@ EXPORT_SYMBOL(gator_annotate_color);
70 86
71void gator_annotate_channel_end(int channel) 87void gator_annotate_channel_end(int channel)
72{ 88{
73 long long header = ESCAPE_CODE | (STRING_ANNOTATION << 8) | (channel << 16); 89 char header[8];
74 kannotate_write((char *)&header, sizeof(header)); 90 header[0] = ESCAPE_CODE;
91 header[1] = STRING_ANNOTATION;
92 marshal_u32(header + 2, channel);
93 marshal_u16(header + 6, 0);
94 kannotate_write(header, sizeof(header));
75} 95}
76 96
77EXPORT_SYMBOL(gator_annotate_channel_end); 97EXPORT_SYMBOL(gator_annotate_channel_end);
@@ -85,14 +105,14 @@ EXPORT_SYMBOL(gator_annotate_end);
85 105
86void gator_annotate_name_channel(int channel, int group, const char* str) 106void gator_annotate_name_channel(int channel, int group, const char* str)
87{ 107{
88 int str_size = strlen(str) & 0xffff; 108 const u16 str_size = strlen(str) & 0xffff;
89 char header[12]; 109 char header[12];
90 header[0] = ESCAPE_CODE; 110 header[0] = ESCAPE_CODE;
91 header[1] = NAME_CHANNEL_ANNOTATION; 111 header[1] = NAME_CHANNEL_ANNOTATION;
92 *(u32 *)(&header[2]) = channel; 112 marshal_u32(header + 2, channel);
93 *(u32 *)(&header[6]) = group; 113 marshal_u32(header + 6, group);
94 *(u16 *)(&header[10]) = str_size; 114 marshal_u16(header + 10, str_size);
95 kannotate_write((char *)&header, sizeof(header)); 115 kannotate_write(header, sizeof(header));
96 kannotate_write(str, str_size); 116 kannotate_write(str, str_size);
97} 117}
98 118
@@ -100,9 +120,13 @@ EXPORT_SYMBOL(gator_annotate_name_channel);
100 120
101void gator_annotate_name_group(int group, const char* str) 121void gator_annotate_name_group(int group, const char* str)
102{ 122{
103 int str_size = strlen(str) & 0xffff; 123 const u16 str_size = strlen(str) & 0xffff;
104 long long header = ESCAPE_CODE | (NAME_GROUP_ANNOTATION << 8) | (group << 16) | ((long long)str_size << 48); 124 char header[8];
105 kannotate_write((char *)&header, sizeof(header)); 125 header[0] = ESCAPE_CODE;
126 header[1] = NAME_GROUP_ANNOTATION;
127 marshal_u32(header + 2, group);
128 marshal_u16(header + 6, str_size);
129 kannotate_write(header, sizeof(header));
106 kannotate_write(str, str_size); 130 kannotate_write(str, str_size);
107} 131}
108 132
@@ -110,11 +134,16 @@ EXPORT_SYMBOL(gator_annotate_name_group);
110 134
111void gator_annotate_visual(const char *data, unsigned int length, const char *str) 135void gator_annotate_visual(const char *data, unsigned int length, const char *str)
112{ 136{
113 int str_size = strlen(str) & 0xffff; 137 const u16 str_size = strlen(str) & 0xffff;
114 int visual_annotation = ESCAPE_CODE | (VISUAL_ANNOTATION << 8) | (str_size << 16); 138 char header[4];
115 kannotate_write((char *)&visual_annotation, sizeof(visual_annotation)); 139 char header_length[4];
140 header[0] = ESCAPE_CODE;
141 header[1] = VISUAL_ANNOTATION;
142 marshal_u16(header + 2, str_size);
143 marshal_u32(header_length, length);
144 kannotate_write(header, sizeof(header));
116 kannotate_write(str, str_size); 145 kannotate_write(str, str_size);
117 kannotate_write((char *)&length, sizeof(length)); 146 kannotate_write(header_length, sizeof(header_length));
118 kannotate_write(data, length); 147 kannotate_write(data, length);
119} 148}
120 149
@@ -122,17 +151,23 @@ EXPORT_SYMBOL(gator_annotate_visual);
122 151
123void gator_annotate_marker(void) 152void gator_annotate_marker(void)
124{ 153{
125 int header = ESCAPE_CODE | (MARKER_ANNOTATION << 8); 154 char header[4];
126 kannotate_write((char *)&header, sizeof(header)); 155 header[0] = ESCAPE_CODE;
156 header[1] = MARKER_ANNOTATION;
157 marshal_u16(header + 2, 0);
158 kannotate_write(header, sizeof(header));
127} 159}
128 160
129EXPORT_SYMBOL(gator_annotate_marker); 161EXPORT_SYMBOL(gator_annotate_marker);
130 162
131void gator_annotate_marker_str(const char *str) 163void gator_annotate_marker_str(const char *str)
132{ 164{
133 int str_size = strlen(str) & 0xffff; 165 const u16 str_size = strlen(str) & 0xffff;
134 int header = ESCAPE_CODE | (MARKER_ANNOTATION << 8) | (str_size << 16); 166 char header[4];
135 kannotate_write((char *)&header, sizeof(header)); 167 header[0] = ESCAPE_CODE;
168 header[1] = MARKER_ANNOTATION;
169 marshal_u16(header + 2, str_size);
170 kannotate_write(header, sizeof(header));
136 kannotate_write(str, str_size); 171 kannotate_write(str, str_size);
137} 172}
138 173
@@ -140,17 +175,25 @@ EXPORT_SYMBOL(gator_annotate_marker_str);
140 175
141void gator_annotate_marker_color(int color) 176void gator_annotate_marker_color(int color)
142{ 177{
143 long long header = (ESCAPE_CODE | (MARKER_ANNOTATION << 8) | 0x00040000 | ((long long)color << 32)); 178 char header[8];
144 kannotate_write((char *)&header, sizeof(header)); 179 header[0] = ESCAPE_CODE;
180 header[1] = MARKER_ANNOTATION;
181 marshal_u16(header + 2, 4);
182 marshal_u32(header + 4, color);
183 kannotate_write(header, sizeof(header));
145} 184}
146 185
147EXPORT_SYMBOL(gator_annotate_marker_color); 186EXPORT_SYMBOL(gator_annotate_marker_color);
148 187
149void gator_annotate_marker_color_str(int color, const char *str) 188void gator_annotate_marker_color_str(int color, const char *str)
150{ 189{
151 int str_size = (strlen(str) + 4) & 0xffff; 190 const u16 str_size = (strlen(str) + 4) & 0xffff;
152 long long header = ESCAPE_CODE | (MARKER_ANNOTATION << 8) | (str_size << 16) | ((long long)color << 32); 191 char header[8];
153 kannotate_write((char *)&header, sizeof(header)); 192 header[0] = ESCAPE_CODE;
193 header[1] = MARKER_ANNOTATION;
194 marshal_u16(header + 2, str_size);
195 marshal_u32(header + 4, color);
196 kannotate_write(header, sizeof(header));
154 kannotate_write(str, str_size - 4); 197 kannotate_write(str, str_size - 4);
155} 198}
156 199
diff --git a/driver/gator_backtrace.c b/driver/gator_backtrace.c
index 0670d6c..ffacb49 100644
--- a/driver/gator_backtrace.c
+++ b/driver/gator_backtrace.c
@@ -132,13 +132,21 @@ static int report_trace(struct stackframe *frame, void *d)
132 132
133// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile 133// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile
134// #define GATOR_KERNEL_STACK_UNWINDING 134// #define GATOR_KERNEL_STACK_UNWINDING
135
136#if (defined(__arm__) || defined(__aarch64__)) && !defined(GATOR_KERNEL_STACK_UNWINDING)
137// Disabled by default
138MODULE_PARM_DESC(kernel_stack_unwinding, "Allow kernel stack unwinding.");
139bool kernel_stack_unwinding = 0;
140module_param(kernel_stack_unwinding, bool, 0644);
141#endif
142
135static void kernel_backtrace(int cpu, struct pt_regs *const regs) 143static void kernel_backtrace(int cpu, struct pt_regs *const regs)
136{ 144{
137#if defined(__arm__) || defined(__aarch64__) 145#if defined(__arm__) || defined(__aarch64__)
138#ifdef GATOR_KERNEL_STACK_UNWINDING 146#ifdef GATOR_KERNEL_STACK_UNWINDING
139 int depth = gator_backtrace_depth; 147 int depth = gator_backtrace_depth;
140#else 148#else
141 int depth = 1; 149 int depth = (kernel_stack_unwinding ? gator_backtrace_depth : 1);
142#endif 150#endif
143 struct stackframe frame; 151 struct stackframe frame;
144 if (depth == 0) 152 if (depth == 0)
diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c
index 5f98a1c..91adfdd 100644
--- a/driver/gator_cookies.c
+++ b/driver/gator_cookies.c
@@ -8,7 +8,8 @@
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_BUFFER_SIZE 512 // must be a power of 2 - 512/4 = 128 entries
12#define TRANSLATE_TEXT_SIZE 256
12#define MAX_COLLISIONS 2 13#define MAX_COLLISIONS 2
13 14
14static uint32_t *gator_crc32_table; 15static uint32_t *gator_crc32_table;
@@ -22,7 +23,7 @@ static DEFINE_PER_CPU(int, translate_buffer_read);
22static DEFINE_PER_CPU(int, translate_buffer_write); 23static DEFINE_PER_CPU(int, translate_buffer_write);
23static DEFINE_PER_CPU(void **, translate_buffer); 24static DEFINE_PER_CPU(void **, translate_buffer);
24 25
25static inline uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq); 26static 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); 27static void wq_cookie_handler(struct work_struct *unused);
27DECLARE_WORK(cookie_work, wq_cookie_handler); 28DECLARE_WORK(cookie_work, wq_cookie_handler);
28static struct timer_list app_process_wake_up_timer; 29static struct timer_list app_process_wake_up_timer;
@@ -107,11 +108,13 @@ static void cookiemap_add(uint64_t key, uint32_t value)
107 values[0] = value; 108 values[0] = value;
108} 109}
109 110
111#ifndef CONFIG_PREEMPT_RT_FULL
110static void translate_buffer_write_ptr(int cpu, void *x) 112static void translate_buffer_write_ptr(int cpu, void *x)
111{ 113{
112 per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x; 114 per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x;
113 per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask; 115 per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask;
114} 116}
117#endif
115 118
116static void *translate_buffer_read_ptr(int cpu) 119static void *translate_buffer_read_ptr(int cpu)
117{ 120{
@@ -124,7 +127,7 @@ static void wq_cookie_handler(struct work_struct *unused)
124{ 127{
125 struct task_struct *task; 128 struct task_struct *task;
126 char *text; 129 char *text;
127 int cpu = get_physical_cpu(); 130 int cpu = get_physical_cpu(), cookie;
128 unsigned int commit; 131 unsigned int commit;
129 132
130 mutex_lock(&start_mutex); 133 mutex_lock(&start_mutex);
@@ -134,7 +137,8 @@ static void wq_cookie_handler(struct work_struct *unused)
134 while (per_cpu(translate_buffer_read, cpu) != commit) { 137 while (per_cpu(translate_buffer_read, cpu) != commit) {
135 task = (struct task_struct *)translate_buffer_read_ptr(cpu); 138 task = (struct task_struct *)translate_buffer_read_ptr(cpu);
136 text = (char *)translate_buffer_read_ptr(cpu); 139 text = (char *)translate_buffer_read_ptr(cpu);
137 get_cookie(cpu, task, text, true); 140 cookie = get_cookie(cpu, task, text, true);
141 marshal_link(cookie, task->tgid, task->pid);
138 } 142 }
139 } 143 }
140 144
@@ -156,15 +160,16 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
156 struct mm_struct *mm; 160 struct mm_struct *mm;
157 struct page *page = NULL; 161 struct page *page = NULL;
158 struct vm_area_struct *page_vma; 162 struct vm_area_struct *page_vma;
159 int bytes, offset, retval = 0, ptr; 163 int bytes, offset, retval = 0;
160 char *buf = per_cpu(translate_text, cpu); 164 char *buf = per_cpu(translate_text, cpu);
161 165
166#ifndef CONFIG_PREEMPT_RT_FULL
162 // Push work into a work queue if in atomic context as the kernel functions below might sleep 167 // Push work into a work queue if in atomic context as the kernel functions below might sleep
163 // Rely on the in_interrupt variable rather than in_irq() or in_interrupt() kernel functions, as the value of these functions seems 168 // Rely on the in_interrupt variable rather than in_irq() or in_interrupt() kernel functions, as the value of these functions seems
164 // inconsistent during a context switch between android/linux versions 169 // inconsistent during a context switch between android/linux versions
165 if (!from_wq) { 170 if (!from_wq) {
166 // Check if already in buffer 171 // Check if already in buffer
167 ptr = per_cpu(translate_buffer_read, cpu); 172 int ptr = per_cpu(translate_buffer_read, cpu);
168 while (ptr != per_cpu(translate_buffer_write, cpu)) { 173 while (ptr != per_cpu(translate_buffer_write, cpu)) {
169 if (per_cpu(translate_buffer, cpu)[ptr] == (void *)task) 174 if (per_cpu(translate_buffer, cpu)[ptr] == (void *)task)
170 goto out; 175 goto out;
@@ -174,9 +179,11 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
174 translate_buffer_write_ptr(cpu, (void *)task); 179 translate_buffer_write_ptr(cpu, (void *)task);
175 translate_buffer_write_ptr(cpu, (void *)*text); 180 translate_buffer_write_ptr(cpu, (void *)*text);
176 181
182 // Not safe to call in RT-Preempt full in schedule switch context
177 mod_timer(&app_process_wake_up_timer, jiffies + 1); 183 mod_timer(&app_process_wake_up_timer, jiffies + 1);
178 goto out; 184 goto out;
179 } 185 }
186#endif
180 187
181 mm = get_task_mm(task); 188 mm = get_task_mm(task);
182 if (!mm) 189 if (!mm)
@@ -186,8 +193,8 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
186 addr = mm->arg_start; 193 addr = mm->arg_start;
187 len = mm->arg_end - mm->arg_start; 194 len = mm->arg_end - mm->arg_start;
188 195
189 if (len > TRANSLATE_SIZE) 196 if (len > TRANSLATE_TEXT_SIZE)
190 len = TRANSLATE_SIZE; 197 len = TRANSLATE_TEXT_SIZE;
191 198
192 down_read(&mm->mmap_sem); 199 down_read(&mm->mmap_sem);
193 while (len) { 200 while (len) {
@@ -225,7 +232,7 @@ out:
225 return retval; 232 return retval;
226} 233}
227 234
228static inline uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq) 235static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq)
229{ 236{
230 unsigned long flags, cookie; 237 unsigned long flags, cookie;
231 uint64_t key; 238 uint64_t key;
@@ -312,8 +319,7 @@ static int cookies_initialize(void)
312 uint32_t crc, poly; 319 uint32_t crc, poly;
313 int i, j, cpu, size, err = 0; 320 int i, j, cpu, size, err = 0;
314 321
315 int translate_buffer_size = 512; // must be a power of 2 322 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;
317 323
318 for_each_present_cpu(cpu) { 324 for_each_present_cpu(cpu) {
319 per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu; 325 per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu;
@@ -334,7 +340,7 @@ static int cookies_initialize(void)
334 } 340 }
335 memset(per_cpu(cookie_values, cpu), 0, size); 341 memset(per_cpu(cookie_values, cpu), 0, size);
336 342
337 per_cpu(translate_buffer, cpu) = (void **)kmalloc(translate_buffer_size, GFP_KERNEL); 343 per_cpu(translate_buffer, cpu) = (void **)kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL);
338 if (!per_cpu(translate_buffer, cpu)) { 344 if (!per_cpu(translate_buffer, cpu)) {
339 err = -ENOMEM; 345 err = -ENOMEM;
340 goto cookie_setup_error; 346 goto cookie_setup_error;
@@ -343,7 +349,7 @@ static int cookies_initialize(void)
343 per_cpu(translate_buffer_write, cpu) = 0; 349 per_cpu(translate_buffer_write, cpu) = 0;
344 per_cpu(translate_buffer_read, cpu) = 0; 350 per_cpu(translate_buffer_read, cpu) = 0;
345 351
346 per_cpu(translate_text, cpu) = (char *)kmalloc(TRANSLATE_SIZE, GFP_KERNEL); 352 per_cpu(translate_text, cpu) = (char *)kmalloc(TRANSLATE_TEXT_SIZE, GFP_KERNEL);
347 if (!per_cpu(translate_text, cpu)) { 353 if (!per_cpu(translate_text, cpu)) {
348 err = -ENOMEM; 354 err = -ENOMEM;
349 goto cookie_setup_error; 355 goto cookie_setup_error;
@@ -353,6 +359,10 @@ static int cookies_initialize(void)
353 // build CRC32 table 359 // build CRC32 table
354 poly = 0x04c11db7; 360 poly = 0x04c11db7;
355 gator_crc32_table = (uint32_t *)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL); 361 gator_crc32_table = (uint32_t *)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL);
362 if (!gator_crc32_table) {
363 err = -ENOMEM;
364 goto cookie_setup_error;
365 }
356 for (i = 0; i < 256; i++) { 366 for (i = 0; i < 256; i++) {
357 crc = i; 367 crc = i;
358 for (j = 8; j > 0; j--) { 368 for (j = 8; j > 0; j--) {
diff --git a/driver/gator_events.sh b/driver/gator_events.sh
deleted file mode 100755
index 5467dd6..0000000
--- a/driver/gator_events.sh
+++ /dev/null
@@ -1,19 +0,0 @@
1#!/bin/sh
2
3EVENTS=`grep gator_events_init *.c | sed 's/.\+gator_events_init(\(.\+\)).\+/\1/'`
4
5(
6 echo /\* This file is auto generated \*/
7 echo
8 for EVENT in $EVENTS; do
9 echo __weak int $EVENT\(void\)\;
10 done
11 echo
12 echo static int \(*gator_events_list[]\)\(void\) = {
13 for EVENT in $EVENTS; do
14 echo \ $EVENT,
15 done
16 echo }\;
17) > $1.tmp
18
19cmp -s $1 $1.tmp && rm $1.tmp || mv $1.tmp $1
diff --git a/driver/gator_events_armv6.c b/driver/gator_events_armv6.c
index 4f1bca6..dd79740 100644
--- a/driver/gator_events_armv6.c
+++ b/driver/gator_events_armv6.c
@@ -234,11 +234,4 @@ int gator_events_armv6_init(void)
234 return gator_events_install(&gator_events_armv6_interface); 234 return gator_events_install(&gator_events_armv6_interface);
235} 235}
236 236
237gator_events_init(gator_events_armv6_init);
238
239#else
240int gator_events_armv6_init(void)
241{
242 return -1;
243}
244#endif 237#endif
diff --git a/driver/gator_events_armv7.c b/driver/gator_events_armv7.c
index 58f2956..30881c8 100644
--- a/driver/gator_events_armv7.c
+++ b/driver/gator_events_armv7.c
@@ -309,11 +309,4 @@ int gator_events_armv7_init(void)
309 return gator_events_install(&gator_events_armv7_interface); 309 return gator_events_install(&gator_events_armv7_interface);
310} 310}
311 311
312gator_events_init(gator_events_armv7_init);
313
314#else
315int gator_events_armv7_init(void)
316{
317 return -1;
318}
319#endif 312#endif
diff --git a/driver/gator_events_block.c b/driver/gator_events_block.c
index 56c6a67..691ef25 100644
--- a/driver/gator_events_block.c
+++ b/driver/gator_events_block.c
@@ -151,5 +151,3 @@ int gator_events_block_init(void)
151 151
152 return gator_events_install(&gator_events_block_interface); 152 return gator_events_install(&gator_events_block_interface);
153} 153}
154
155gator_events_init(gator_events_block_init);
diff --git a/driver/gator_events_ccn-504.c b/driver/gator_events_ccn-504.c
index b91a9a1..b892319 100644
--- a/driver/gator_events_ccn-504.c
+++ b/driver/gator_events_ccn-504.c
@@ -6,23 +6,16 @@
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8 8
9/*******************************************************************************
10 * WARNING: This code is an experimental implementation of the CCN-504 hardware
11 * counters which has not been tested on the hardware. Commented debug
12 * statements are present and can be uncommented for diagnostic purposes.
13 ******************************************************************************/
14
15#include <linux/io.h> 9#include <linux/io.h>
16#include <linux/module.h> 10#include <linux/module.h>
17 11
18#include "gator.h" 12#include "gator.h"
19 13
20#define PERIPHBASE 0x2E000000
21
22#define NUM_REGIONS 256 14#define NUM_REGIONS 256
23#define REGION_SIZE (64*1024) 15#define REGION_SIZE (64*1024)
24#define REGION_DEBUG 1 16#define REGION_DEBUG 1
25#define REGION_XP 64 17#define REGION_XP 64
18#define NUM_XPS 11
26 19
27// DT (Debug) region 20// DT (Debug) region
28#define PMEVCNTSR0 0x0150 21#define PMEVCNTSR0 0x0150
@@ -34,27 +27,86 @@
34 27
35// XP region 28// XP region
36#define DT_CONFIG 0x0300 29#define DT_CONFIG 0x0300
30#define DT_CONTROL 0x0370
37 31
38// Multiple 32// Multiple
39#define PMU_EVENT_SEL 0x0600 33#define PMU_EVENT_SEL 0x0600
40#define OLY_ID 0xFF00 34#define OLY_ID 0xFF00
41 35
42#define CCNT 4 36#define CCNT 4
43#define CNTMAX (4 + 1) 37#define CNTMAX (CCNT + 1)
44 38
45#define get_pmu_event_id(event) (((event) >> 0) & 0xFF) 39#define get_pmu_event_id(event) (((event) >> 0) & 0xFF)
46#define get_node_type(event) (((event) >> 8) & 0xFF) 40#define get_node_type(event) (((event) >> 8) & 0xFF)
47#define get_region(event) (((event) >> 16) & 0xFF) 41#define get_region(event) (((event) >> 16) & 0xFF)
48 42
43#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
44
45// From kernel/params.c
46#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \
47 int param_set_##name(const char *val, struct kernel_param *kp) \
48 { \
49 tmptype l; \
50 int ret; \
51 \
52 if (!val) return -EINVAL; \
53 ret = strtolfn(val, 0, &l); \
54 if (ret == -EINVAL || ((type)l != l)) \
55 return -EINVAL; \
56 *((type *)kp->arg) = l; \
57 return 0; \
58 } \
59 int param_get_##name(char *buffer, struct kernel_param *kp) \
60 { \
61 return sprintf(buffer, format, *((type *)kp->arg)); \
62 }
63
64#else
65
66// From kernel/params.c
67#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \
68 int param_set_##name(const char *val, const struct kernel_param *kp) \
69 { \
70 tmptype l; \
71 int ret; \
72 \
73 ret = strtolfn(val, 0, &l); \
74 if (ret < 0 || ((type)l != l)) \
75 return ret < 0 ? ret : -EINVAL; \
76 *((type *)kp->arg) = l; \
77 return 0; \
78 } \
79 int param_get_##name(char *buffer, const struct kernel_param *kp) \
80 { \
81 return scnprintf(buffer, PAGE_SIZE, format, \
82 *((type *)kp->arg)); \
83 } \
84 struct kernel_param_ops param_ops_##name = { \
85 .set = param_set_##name, \
86 .get = param_get_##name, \
87 }; \
88 EXPORT_SYMBOL(param_set_##name); \
89 EXPORT_SYMBOL(param_get_##name); \
90 EXPORT_SYMBOL(param_ops_##name)
91
92#endif
93
94STANDARD_PARAM_DEF(u64, u64, "%llu", u64, strict_strtoull);
95
96// From include/linux/moduleparam.h
97#define param_check_u64(name, p) __param_check(name, p, u64)
98
49MODULE_PARM_DESC(ccn504_addr, "CCN-504 physical base address"); 99MODULE_PARM_DESC(ccn504_addr, "CCN-504 physical base address");
50static unsigned long ccn504_addr = 0; 100static u64 ccn504_addr = 0;
51module_param(ccn504_addr, ulong, 0444); 101module_param(ccn504_addr, u64, 0444);
52 102
53static void __iomem *gator_events_ccn504_base; 103static void __iomem *gator_events_ccn504_base;
104static bool gator_events_ccn504_global_enabled;
54static unsigned long gator_events_ccn504_enabled[CNTMAX]; 105static unsigned long gator_events_ccn504_enabled[CNTMAX];
55static unsigned long gator_events_ccn504_event[CNTMAX]; 106static unsigned long gator_events_ccn504_event[CNTMAX];
56static unsigned long gator_events_ccn504_key[CNTMAX]; 107static unsigned long gator_events_ccn504_key[CNTMAX];
57static int gator_events_ccn504_buffer[2*CNTMAX]; 108static int gator_events_ccn504_buffer[2*CNTMAX];
109static int gator_events_ccn504_prev[CNTMAX];
58 110
59static void gator_events_ccn504_create_shutdown(void) 111static void gator_events_ccn504_create_shutdown(void)
60{ 112{
@@ -96,7 +148,6 @@ static void gator_events_ccn504_set_dt_config(int xp_node_id, int event_num, int
96 148
97 dt_config = readl(gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG); 149 dt_config = readl(gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG);
98 dt_config |= (value + event_num) << (4*event_num); 150 dt_config |= (value + event_num) << (4*event_num);
99 //printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, dt_config, (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG);
100 writel(dt_config, gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG); 151 writel(dt_config, gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG);
101} 152}
102 153
@@ -104,6 +155,20 @@ static int gator_events_ccn504_start(void)
104{ 155{
105 int i; 156 int i;
106 157
158 gator_events_ccn504_global_enabled = 0;
159 for (i = 0; i < CNTMAX; ++i) {
160 if (gator_events_ccn504_enabled[i]) {
161 gator_events_ccn504_global_enabled = 1;
162 break;
163 }
164 }
165
166 if (!gator_events_ccn504_global_enabled) {
167 return 0;
168 }
169
170 memset(&gator_events_ccn504_prev, 0x80, sizeof(gator_events_ccn504_prev));
171
107 // Disable INTREQ on overflow 172 // Disable INTREQ on overflow
108 // [6] ovfl_intr_en = 0 173 // [6] ovfl_intr_en = 0
109 // perhaps set to 1? 174 // perhaps set to 1?
@@ -112,9 +177,22 @@ static int gator_events_ccn504_start(void)
112 // [4:1] cntcfg = 0 177 // [4:1] cntcfg = 0
113 // Enable PMU features 178 // Enable PMU features
114 // [0] pmu_en = 1 179 // [0] pmu_en = 1
115 //printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, 0x1, REGION_DEBUG*REGION_SIZE + PMCR);
116 writel(0x1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMCR); 180 writel(0x1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMCR);
117 181
182 // Configure the XPs
183 for (i = 0; i < NUM_XPS; ++i) {
184 int dt_control;
185
186 // Pass on all events
187 writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG);
188
189 // Enable PMU capability
190 // [0] dt_enable = 1
191 dt_control = readl(gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL);
192 dt_control |= 0x1;
193 writel(dt_control, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL);
194 }
195
118 // Assume no other pmu_event_sel registers are set 196 // Assume no other pmu_event_sel registers are set
119 197
120 // cycle counter does not need to be enabled 198 // cycle counter does not need to be enabled
@@ -134,15 +212,14 @@ static int gator_events_ccn504_start(void)
134 pmu_event_id = get_pmu_event_id(gator_events_ccn504_event[i]); 212 pmu_event_id = get_pmu_event_id(gator_events_ccn504_event[i]);
135 node_type = get_node_type(gator_events_ccn504_event[i]); 213 node_type = get_node_type(gator_events_ccn504_event[i]);
136 region = get_region(gator_events_ccn504_event[i]); 214 region = get_region(gator_events_ccn504_event[i]);
137 //printk(KERN_ERR "%s(%s:%i) pmu_event_id: %x node_type: %x region: %x\n", __FUNCTION__, __FILE__, __LINE__, pmu_event_id, node_type, region);
138 215
139 // Verify the node_type 216 // Verify the node_type
140 oly_id_whole = readl(gator_events_ccn504_base + region*REGION_SIZE + OLY_ID); 217 oly_id_whole = readl(gator_events_ccn504_base + region*REGION_SIZE + OLY_ID);
141 oly_id = oly_id_whole & 0x1F; 218 oly_id = oly_id_whole & 0x1F;
142 node_id = (oly_id_whole >> 8) & 0x7F; 219 node_id = (oly_id_whole >> 8) & 0x7F;
143 if ((oly_id != node_type) || 220 if ((oly_id != node_type) ||
144 ((node_type == 0x16) && ((oly_id == 0x14) || (oly_id == 0x15) || (oly_id == 0x16) || (oly_id == 0x18) || (oly_id == 0x19) || (oly_id == 0x1A)))) { 221 ((node_type == 0x16) && ((oly_id != 0x14) && (oly_id != 0x15) && (oly_id != 0x16) && (oly_id != 0x18) && (oly_id != 0x19) && (oly_id != 0x1A)))) {
145 printk(KERN_ERR "%s(%s:%i) oly_id is %x expected %x\n", __FUNCTION__, __FILE__, __LINE__, oly_id, node_type); 222 printk(KERN_ERR "gator: oly_id is 0x%x expected 0x%x\n", oly_id, node_type);
146 return -1; 223 return -1;
147 } 224 }
148 225
@@ -160,7 +237,6 @@ static int gator_events_ccn504_start(void)
160 gator_events_ccn504_set_dt_config(node_id/2, i, (node_id & 1) == 0 ? 0x8 : 0xC); 237 gator_events_ccn504_set_dt_config(node_id/2, i, (node_id & 1) == 0 ? 0x8 : 0xC);
161 break; 238 break;
162 } 239 }
163 //printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, pmu_event_sel, region*REGION_SIZE + PMU_EVENT_SEL);
164 writel(pmu_event_sel, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL); 240 writel(pmu_event_sel, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL);
165 } 241 }
166 242
@@ -171,21 +247,25 @@ static void gator_events_ccn504_stop(void)
171{ 247{
172 int i; 248 int i;
173 249
250 if (!gator_events_ccn504_global_enabled) {
251 return;
252 }
253
174 // cycle counter does not need to be disabled 254 // cycle counter does not need to be disabled
175 for (i = 0; i < CCNT; ++i) { 255 for (i = 0; i < CCNT; ++i) {
176 int node_type;
177 int region; 256 int region;
178 257
179 node_type = get_node_type(gator_events_ccn504_event[i]); 258 if (!gator_events_ccn504_enabled[i]) {
259 continue;
260 }
261
180 region = get_region(gator_events_ccn504_event[i]); 262 region = get_region(gator_events_ccn504_event[i]);
181 263
182 //printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, 0, region*REGION_SIZE + PMU_EVENT_SEL);
183 writel(0, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL); 264 writel(0, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL);
184 } 265 }
185 266
186 // Clear dt_config 267 // Clear dt_config
187 for (i = 0; i < 11; ++i) { 268 for (i = 0; i < NUM_XPS; ++i) {
188 //printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, 0, (REGION_XP + i)*REGION_SIZE + DT_CONFIG);
189 writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG); 269 writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG);
190 } 270 }
191} 271}
@@ -194,27 +274,20 @@ static int gator_events_ccn504_read(int **buffer)
194{ 274{
195 int i; 275 int i;
196 int len = 0; 276 int len = 0;
277 int value;
197 278
198 if (!on_primary_core()) { 279 if (!on_primary_core() || !gator_events_ccn504_global_enabled) {
199 return 0; 280 return 0;
200 } 281 }
201 282
202 // Verify the pmsr register is zero 283 // Verify the pmsr register is zero
203 //i = 0; 284 while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) != 0);
204 while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) != 0) {
205 //++i;
206 }
207 //printk(KERN_ERR "%s(%s:%i) %i\n", __FUNCTION__, __FILE__, __LINE__, i);
208 285
209 // Request a PMU snapshot 286 // Request a PMU snapshot
210 writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_REQ); 287 writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_REQ);
211 288
212 // Wait for the snapshot 289 // Wait for the snapshot
213 //i = 0; 290 while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) == 0);
214 while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) == 0) {
215 //++i;
216 }
217 //printk(KERN_ERR "%s(%s:%i) %i\n", __FUNCTION__, __FILE__, __LINE__, i);
218 291
219 // Read the shadow registers 292 // Read the shadow registers
220 for (i = 0; i < CNTMAX; ++i) { 293 for (i = 0; i < CNTMAX; ++i) {
@@ -222,8 +295,12 @@ static int gator_events_ccn504_read(int **buffer)
222 continue; 295 continue;
223 } 296 }
224 297
225 gator_events_ccn504_buffer[len++] = gator_events_ccn504_key[i]; 298 value = readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + (i == CCNT ? PMCCNTRSR : PMEVCNTSR0 + 8*i));
226 gator_events_ccn504_buffer[len++] = readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + (i == CCNT ? PMCCNTRSR : PMEVCNTSR0 + 8*i)); 299 if (gator_events_ccn504_prev[i] != 0x80808080) {
300 gator_events_ccn504_buffer[len++] = gator_events_ccn504_key[i];
301 gator_events_ccn504_buffer[len++] = value - gator_events_ccn504_prev[i];
302 }
303 gator_events_ccn504_prev[i] = value;
227 304
228 // Are the counters registers cleared when read? Is that what the cntr_rst bit on the pmcr register does? 305 // Are the counters registers cleared when read? Is that what the cntr_rst bit on the pmcr register does?
229 } 306 }
@@ -231,18 +308,10 @@ static int gator_events_ccn504_read(int **buffer)
231 // Clear the PMU snapshot status 308 // Clear the PMU snapshot status
232 writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_CLR); 309 writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_CLR);
233 310
234 return len; 311 if (buffer)
235} 312 *buffer = gator_events_ccn504_buffer;
236
237static void __maybe_unused gator_events_ccn504_enumerate(int pos, int size)
238{
239 int i;
240 u32 oly_id;
241 313
242 for (i = pos; i < pos + size; ++i) { 314 return len;
243 oly_id = readl(gator_events_ccn504_base + i*REGION_SIZE + OLY_ID);
244 printk(KERN_ERR "%s(%s:%i) %i %08x\n", __FUNCTION__, __FILE__, __LINE__, i, oly_id);
245 }
246} 315}
247 316
248static struct gator_interface gator_events_ccn504_interface = { 317static struct gator_interface gator_events_ccn504_interface = {
@@ -263,36 +332,9 @@ int gator_events_ccn504_init(void)
263 332
264 gator_events_ccn504_base = ioremap(ccn504_addr, NUM_REGIONS*REGION_SIZE); 333 gator_events_ccn504_base = ioremap(ccn504_addr, NUM_REGIONS*REGION_SIZE);
265 if (gator_events_ccn504_base == NULL) { 334 if (gator_events_ccn504_base == NULL) {
266 printk(KERN_ERR "%s(%s:%i) ioremap returned NULL\n", __FUNCTION__, __FILE__, __LINE__); 335 printk(KERN_ERR "gator: ioremap returned NULL\n");
267 return -1; 336 return -1;
268 } 337 }
269 //printk(KERN_ERR "%s(%s:%i)\n", __FUNCTION__, __FILE__, __LINE__);
270
271 // Test - can memory be read
272 {
273 //gator_events_ccn504_enumerate(0, NUM_REGIONS);
274
275#if 0
276 // DT
277 gator_events_ccn504_enumerate(1, 1);
278 // HN-F
279 gator_events_ccn504_enumerate(32, 8);
280 // XP
281 gator_events_ccn504_enumerate(64, 11);
282 // RN-I
283 gator_events_ccn504_enumerate(128, 1);
284 gator_events_ccn504_enumerate(130, 1);
285 gator_events_ccn504_enumerate(134, 1);
286 gator_events_ccn504_enumerate(140, 1);
287 gator_events_ccn504_enumerate(144, 1);
288 gator_events_ccn504_enumerate(148, 1);
289 // SBAS
290 gator_events_ccn504_enumerate(129, 1);
291 gator_events_ccn504_enumerate(137, 1);
292 gator_events_ccn504_enumerate(139, 1);
293 gator_events_ccn504_enumerate(147, 1);
294#endif
295 }
296 338
297 for (i = 0; i < CNTMAX; ++i) { 339 for (i = 0; i < CNTMAX; ++i) {
298 gator_events_ccn504_enabled[i] = 0; 340 gator_events_ccn504_enabled[i] = 0;
@@ -302,5 +344,3 @@ int gator_events_ccn504_init(void)
302 344
303 return gator_events_install(&gator_events_ccn504_interface); 345 return gator_events_install(&gator_events_ccn504_interface);
304} 346}
305
306gator_events_init(gator_events_ccn504_init);
diff --git a/driver/gator_events_irq.c b/driver/gator_events_irq.c
index b4df7fa..b11879a 100644
--- a/driver/gator_events_irq.c
+++ b/driver/gator_events_irq.c
@@ -163,5 +163,3 @@ int gator_events_irq_init(void)
163 163
164 return gator_events_install(&gator_events_irq_interface); 164 return gator_events_install(&gator_events_irq_interface);
165} 165}
166
167gator_events_init(gator_events_irq_init);
diff --git a/driver/gator_events_l2c-310.c b/driver/gator_events_l2c-310.c
index 21aa4a2..ee521af 100644
--- a/driver/gator_events_l2c-310.c
+++ b/driver/gator_events_l2c-310.c
@@ -206,5 +206,3 @@ int gator_events_l2c310_init(void)
206 206
207 return gator_events_install(&gator_events_l2c310_interface); 207 return gator_events_install(&gator_events_l2c310_interface);
208} 208}
209
210gator_events_init(gator_events_l2c310_init);
diff --git a/driver/gator_events_mali_4xx.c b/driver/gator_events_mali_4xx.c
index dd275f7..6719c1e 100644
--- a/driver/gator_events_mali_4xx.c
+++ b/driver/gator_events_mali_4xx.c
@@ -415,25 +415,12 @@ static void mali_counter_initialize(void)
415 int i; 415 int i;
416 int core_id; 416 int core_id;
417 417
418 mali_osk_fb_control_set_type *mali_set_fb_event;
419 mali_profiling_control_type *mali_control; 418 mali_profiling_control_type *mali_control;
420 419
421 init_counters(COUNTER_L2_0_C0, COUNTER_L2_0_C0 + (2 * n_l2_cores) - 1); 420 init_counters(COUNTER_L2_0_C0, COUNTER_L2_0_C0 + (2 * n_l2_cores) - 1);
422 init_counters(COUNTER_VP_0_C0, COUNTER_VP_0_C0 + (2 * n_vp_cores) - 1); 421 init_counters(COUNTER_VP_0_C0, COUNTER_VP_0_C0 + (2 * n_vp_cores) - 1);
423 init_counters(COUNTER_FP_0_C0, COUNTER_FP_0_C0 + (2 * n_fp_cores) - 1); 422 init_counters(COUNTER_FP_0_C0, COUNTER_FP_0_C0 + (2 * n_fp_cores) - 1);
424 423
425 mali_set_fb_event = symbol_get(_mali_osk_fb_control_set);
426
427 if (mali_set_fb_event) {
428 pr_debug("gator: mali online _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
429
430 mali_set_fb_event(0, (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0));
431
432 symbol_put(_mali_osk_fb_control_set);
433 } else {
434 printk("gator: mali online _mali_osk_fb_control_set symbol not found\n");
435 }
436
437 /* Generic control interface for Mali DDK. */ 424 /* Generic control interface for Mali DDK. */
438 mali_control = symbol_get(_mali_profiling_control); 425 mali_control = symbol_get(_mali_profiling_control);
439 if (mali_control) { 426 if (mali_control) {
@@ -491,7 +478,6 @@ static void mali_counter_initialize(void)
491static void mali_counter_deinitialize(void) 478static void mali_counter_deinitialize(void)
492{ 479{
493 mali_profiling_set_event_type *mali_set_hw_event; 480 mali_profiling_set_event_type *mali_set_hw_event;
494 mali_osk_fb_control_set_type *mali_set_fb_event;
495 mali_profiling_control_type *mali_control; 481 mali_profiling_control_type *mali_control;
496 482
497 mali_set_hw_event = symbol_get(_mali_profiling_set_event); 483 mali_set_hw_event = symbol_get(_mali_profiling_set_event);
@@ -509,23 +495,11 @@ static void mali_counter_deinitialize(void)
509 printk("gator: mali offline _mali_profiling_set_event symbol not found\n"); 495 printk("gator: mali offline _mali_profiling_set_event symbol not found\n");
510 } 496 }
511 497
512 mali_set_fb_event = symbol_get(_mali_osk_fb_control_set);
513
514 if (mali_set_fb_event) {
515 pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
516
517 mali_set_fb_event(0, 0);
518
519 symbol_put(_mali_osk_fb_control_set);
520 } else {
521 printk("gator: mali offline _mali_osk_fb_control_set symbol not found\n");
522 }
523
524 /* Generic control interface for Mali DDK. */ 498 /* Generic control interface for Mali DDK. */
525 mali_control = symbol_get(_mali_profiling_control); 499 mali_control = symbol_get(_mali_profiling_control);
526 500
527 if (mali_control) { 501 if (mali_control) {
528 pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_set_fb_event); 502 pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_control);
529 503
530 /* Reset the DDK state - disable counter collection */ 504 /* Reset the DDK state - disable counter collection */
531 mali_control(SW_COUNTER_ENABLE, 0); 505 mali_control(SW_COUNTER_ENABLE, 0);
@@ -747,5 +721,3 @@ int gator_events_mali_init(void)
747 721
748 return gator_events_install(&gator_events_mali_interface); 722 return gator_events_install(&gator_events_mali_interface);
749} 723}
750
751gator_events_init(gator_events_mali_init);
diff --git a/driver/gator_events_mali_common.c b/driver/gator_events_mali_common.c
index 5a98b37..466ca16 100644
--- a/driver/gator_events_mali_common.c
+++ b/driver/gator_events_mali_common.c
@@ -28,7 +28,7 @@ extern const char *gator_mali_get_mali_name(void)
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, unsigned long *event)
32{ 32{
33 int err; 33 int err;
34 char buf[255]; 34 char buf[255];
@@ -56,6 +56,13 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even
56 pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf); 56 pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf);
57 return -1; 57 return -1;
58 } 58 }
59 if (event != NULL) {
60 err = gatorfs_create_ulong(sb, dir, "event", event);
61 if (err != 0) {
62 pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf);
63 return -1;
64 }
65 }
59 } 66 }
60 67
61 return 0; 68 return 0;
diff --git a/driver/gator_events_mali_common.h b/driver/gator_events_mali_common.h
index d67ee2d..509f9b6 100644
--- a/driver/gator_events_mali_common.h
+++ b/driver/gator_events_mali_common.h
@@ -43,7 +43,6 @@ typedef struct {
43 * Mali-4xx 43 * Mali-4xx
44 */ 44 */
45typedef int mali_profiling_set_event_type(unsigned int, int); 45typedef int mali_profiling_set_event_type(unsigned int, int);
46typedef void mali_osk_fb_control_set_type(unsigned int, unsigned int);
47typedef void mali_profiling_control_type(unsigned int, unsigned int); 46typedef void mali_profiling_control_type(unsigned int, unsigned int);
48typedef void mali_profiling_get_counters_type(unsigned int *, unsigned int *, unsigned int *, unsigned int *); 47typedef void mali_profiling_get_counters_type(unsigned int *, unsigned int *, unsigned int *, unsigned int *);
49 48
@@ -51,7 +50,6 @@ typedef void mali_profiling_get_counters_type(unsigned int *, unsigned int *, un
51 * Driver entry points for functions called directly by gator. 50 * Driver entry points for functions called directly by gator.
52 */ 51 */
53extern int _mali_profiling_set_event(unsigned int, int); 52extern int _mali_profiling_set_event(unsigned int, int);
54extern void _mali_osk_fb_control_set(unsigned int, unsigned int);
55extern void _mali_profiling_control(unsigned int, unsigned int); 53extern void _mali_profiling_control(unsigned int, unsigned int);
56extern void _mali_profiling_get_counters(unsigned int *, unsigned int *, unsigned int *, unsigned int *); 54extern void _mali_profiling_get_counters(unsigned int *, unsigned int *, unsigned int *, unsigned int *);
57 55
@@ -75,7 +73,7 @@ extern const char *gator_mali_get_mali_name(void);
75 * 73 *
76 * @return 0 if entry point was created, non-zero if not. 74 * @return 0 if entry point was created, non-zero if not.
77 */ 75 */
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); 76extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter, unsigned long *event);
79 77
80/** 78/**
81 * Initializes the counter array. 79 * Initializes the counter array.
diff --git a/driver/gator_events_mali_t6xx.c b/driver/gator_events_mali_t6xx.c
index 2576a99..7bf7d6a 100644
--- a/driver/gator_events_mali_t6xx.c
+++ b/driver/gator_events_mali_t6xx.c
@@ -109,12 +109,14 @@ enum {
109#define NUMBER_OF_SOFTWARE_COUNTERS (sizeof(software_counter_names) / sizeof(software_counter_names[0])) 109#define NUMBER_OF_SOFTWARE_COUNTERS (sizeof(software_counter_names) / sizeof(software_counter_names[0]))
110#define FIRST_ACCUMULATOR (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS) 110#define FIRST_ACCUMULATOR (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS)
111#define NUMBER_OF_ACCUMULATORS (sizeof(accumulators_names) / sizeof(accumulators_names[0])) 111#define NUMBER_OF_ACCUMULATORS (sizeof(accumulators_names) / sizeof(accumulators_names[0]))
112#define NUMBER_OF_EVENTS (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS) 112#define FILMSTRIP (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS)
113#define NUMBER_OF_EVENTS (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS + 1)
113 114
114/* 115/*
115 * gatorfs variables for counter enable state 116 * gatorfs variables for counter enable state
116 */ 117 */
117static mali_counter counters[NUMBER_OF_EVENTS]; 118static mali_counter counters[NUMBER_OF_EVENTS];
119static unsigned long filmstrip_event;
118 120
119/* An array used to return the data we recorded 121/* An array used to return the data we recorded
120 * as key,value pairs hence the *2 122 * as key,value pairs hence the *2
@@ -285,28 +287,37 @@ static int create_files(struct super_block *sb, struct dentry *root)
285 */ 287 */
286 int counter_index = 0; 288 int counter_index = 0;
287 const char *mali_name = gator_mali_get_mali_name(); 289 const char *mali_name = gator_mali_get_mali_name();
290 mali_profiling_control_type *mali_control;
288 291
289 for (event = FIRST_TIMELINE_EVENT; event < FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS; event++) { 292 for (event = FIRST_TIMELINE_EVENT; event < FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS; event++) {
290 if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event]) != 0) { 293 if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event], NULL) != 0) {
291 return -1; 294 return -1;
292 } 295 }
293 counter_index++; 296 counter_index++;
294 } 297 }
295 counter_index = 0; 298 counter_index = 0;
296 for (event = FIRST_SOFTWARE_COUNTER; event < FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS; event++) { 299 for (event = FIRST_SOFTWARE_COUNTER; event < FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS; event++) {
297 if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event]) != 0) { 300 if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event], NULL) != 0) {
298 return -1; 301 return -1;
299 } 302 }
300 counter_index++; 303 counter_index++;
301 } 304 }
302 counter_index = 0; 305 counter_index = 0;
303 for (event = FIRST_ACCUMULATOR; event < FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS; event++) { 306 for (event = FIRST_ACCUMULATOR; event < FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS; event++) {
304 if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event]) != 0) { 307 if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event], NULL) != 0) {
305 return -1; 308 return -1;
306 } 309 }
307 counter_index++; 310 counter_index++;
308 } 311 }
309 312
313 mali_control = symbol_get(_mali_profiling_control);
314 if (mali_control) {
315 if (gator_mali_create_file_system(mali_name, "Filmstrip_cnt0", sb, root, &counters[FILMSTRIP], &filmstrip_event) != 0) {
316 return -1;
317 }
318 symbol_put(_mali_profiling_control);
319 }
320
310 return 0; 321 return 0;
311} 322}
312 323
@@ -350,6 +361,7 @@ static int register_tracepoints(void)
350static int start(void) 361static int start(void)
351{ 362{
352 unsigned int cnt; 363 unsigned int cnt;
364 mali_profiling_control_type *mali_control;
353 365
354 /* Clean all data for the next capture */ 366 /* Clean all data for the next capture */
355 for (cnt = 0; cnt < NUMBER_OF_TIMELINE_EVENTS; cnt++) { 367 for (cnt = 0; cnt < NUMBER_OF_TIMELINE_EVENTS; cnt++) {
@@ -370,6 +382,30 @@ static int start(void)
370 return -1; 382 return -1;
371 } 383 }
372 384
385 /* Generic control interface for Mali DDK. */
386 mali_control = symbol_get(_mali_profiling_control);
387 if (mali_control) {
388 /* The event attribute in the XML file keeps the actual frame rate. */
389 unsigned int enabled = counters[FILMSTRIP].enabled ? 1 : 0;
390 unsigned int rate = filmstrip_event & 0xff;
391 unsigned int resize_factor = (filmstrip_event >> 8) & 0xff;
392
393 pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control);
394
395#define FBDUMP_CONTROL_ENABLE (1)
396#define FBDUMP_CONTROL_RATE (2)
397#define FBDUMP_CONTROL_RESIZE_FACTOR (4)
398 mali_control(FBDUMP_CONTROL_ENABLE, enabled);
399 mali_control(FBDUMP_CONTROL_RATE, rate);
400 mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor);
401
402 pr_debug("gator: sent mali_control enabled=%d, rate=%d, resize_factor=%d\n", enabled, rate, resize_factor);
403
404 symbol_put(_mali_profiling_control);
405 } else {
406 printk("gator: mali online _mali_profiling_control symbol not found\n");
407 }
408
373 /* 409 /*
374 * Set the first timestamp for calculating the sample interval. The first interval could be quite long, 410 * Set the first timestamp for calculating the sample interval. The first interval could be quite long,
375 * since it will be the time between 'start' and the first 'read'. 411 * since it will be the time between 'start' and the first 'read'.
@@ -382,6 +418,8 @@ static int start(void)
382 418
383static void stop(void) 419static void stop(void)
384{ 420{
421 mali_profiling_control_type *mali_control;
422
385 pr_debug("gator: Mali-T6xx: stop\n"); 423 pr_debug("gator: Mali-T6xx: stop\n");
386 424
387 /* 425 /*
@@ -402,6 +440,18 @@ static void stop(void)
402 440
403 GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change); 441 GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change);
404 pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint deactivated\n"); 442 pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint deactivated\n");
443
444 /* Generic control interface for Mali DDK. */
445 mali_control = symbol_get(_mali_profiling_control);
446 if (mali_control) {
447 pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_control);
448
449 mali_control(FBDUMP_CONTROL_ENABLE, 0);
450
451 symbol_put(_mali_profiling_control);
452 } else {
453 printk("gator: mali offline _mali_profiling_control symbol not found\n");
454 }
405} 455}
406 456
407static int read(int **buffer) 457static int read(int **buffer)
@@ -508,5 +558,3 @@ extern int gator_events_mali_t6xx_init(void)
508 558
509 return gator_events_install(&gator_events_mali_t6xx_interface); 559 return gator_events_install(&gator_events_mali_t6xx_interface);
510} 560}
511
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 f557350..e406991 100644
--- a/driver/gator_events_mali_t6xx_hw.c
+++ b/driver/gator_events_mali_t6xx_hw.c
@@ -63,6 +63,8 @@ static kbase_instr_hwcnt_disable_type *kbase_instr_hwcnt_disable_symbol;
63static kbase_va_free_type *kbase_va_free_symbol; 63static kbase_va_free_type *kbase_va_free_symbol;
64static kbase_destroy_context_type *kbase_destroy_context_symbol; 64static kbase_destroy_context_type *kbase_destroy_context_symbol;
65 65
66static long shader_present_low = 0;
67
66/** The interval between reads, in ns. 68/** The interval between reads, in ns.
67 * 69 *
68 * Earlier we introduced 70 * Earlier we introduced
@@ -496,6 +498,7 @@ static int start(void)
496 mali_error err; 498 mali_error err;
497 int cnt; 499 int cnt;
498 u16 bitmask[] = { 0, 0, 0, 0 }; 500 u16 bitmask[] = { 0, 0, 0, 0 };
501 unsigned long long shadersPresent = 0;
499 502
500 /* Setup HW counters */ 503 /* Setup HW counters */
501 num_hardware_counters_enabled = 0; 504 num_hardware_counters_enabled = 0;
@@ -539,6 +542,11 @@ static int start(void)
539 goto out; 542 goto out;
540 } 543 }
541 544
545
546 /* See if we can get the number of shader cores */
547 shadersPresent = kbdevice->shader_present_bitmap;
548 shader_present_low = (unsigned long)shadersPresent;
549
542 /* 550 /*
543 * The amount of memory needed to store the dump (bytes) 551 * The amount of memory needed to store the dump (bytes)
544 * DUMP_SIZE = number of core groups 552 * DUMP_SIZE = number of core groups
@@ -679,21 +687,41 @@ static int read(int **buffer)
679 kbase_device_busy = false; 687 kbase_device_busy = false;
680 688
681 if (success == MALI_TRUE) { 689 if (success == MALI_TRUE) {
690 /* Cycle through hardware counters and accumulate totals */
682 for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) { 691 for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) {
683 const mali_counter *counter = &counters[cnt]; 692 const mali_counter *counter = &counters[cnt];
684 if (counter->enabled) { 693 if (counter->enabled) {
685 const int block = GET_HW_BLOCK(cnt); 694 const int block = GET_HW_BLOCK(cnt);
686 const int counter_offset = GET_COUNTER_OFFSET(cnt); 695 const int counter_offset = GET_COUNTER_OFFSET(cnt);
687 const u32 *counter_block = (u32 *) ((uintptr_t)kernel_dump_buffer + vithar_blocks[block]);
688 const u32 *counter_address = counter_block + counter_offset;
689 696
690 value = *counter_address; 697 const char* block_base_address = (char*)kernel_dump_buffer + vithar_blocks[block];
691 698
699 /* If counter belongs to shader block need to take into account all cores */
692 if (block == SHADER_BLOCK) { 700 if (block == SHADER_BLOCK) {
693 /* (counter_address + 0x000) has already been accounted-for above. */ 701 int i = 0;
694 value += *(counter_address + 0x100); 702 int shader_core_count = 0;
695 value += *(counter_address + 0x200); 703 value = 0;
696 value += *(counter_address + 0x300); 704
705 for (i = 0; i < 4; i++) {
706 if ((shader_present_low >> i) & 1) {
707 value += *((u32*) (block_base_address + (0x100 * i)) + counter_offset);
708 shader_core_count++;
709 }
710 }
711
712 for (i = 0; i < 4; i++) {
713 if((shader_present_low >> (i+4)) & 1) {
714 value += *((u32*)(block_base_address + (0x100 * i) + 0x800) + counter_offset);
715 shader_core_count++;
716 }
717 }
718
719 /* Need to total by number of cores to produce an average */
720 if (shader_core_count != 0) {
721 value /= shader_core_count;
722 }
723 } else {
724 value = *((u32*)block_base_address + counter_offset);
697 } 725 }
698 726
699 counter_dump[len++] = counter->key; 727 counter_dump[len++] = counter->key;
@@ -727,7 +755,7 @@ static int create_files(struct super_block *sb, struct dentry *root)
727 const char *mali_name = gator_mali_get_mali_name(); 755 const char *mali_name = gator_mali_get_mali_name();
728 756
729 for (event = 0; event < NUMBER_OF_HARDWARE_COUNTERS; event++) { 757 for (event = 0; event < NUMBER_OF_HARDWARE_COUNTERS; event++) {
730 if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event]) != 0) 758 if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event], NULL) != 0)
731 return -1; 759 return -1;
732 counter_index++; 760 counter_index++;
733 } 761 }
@@ -754,5 +782,3 @@ int gator_events_mali_t6xx_hw_init(void)
754 782
755 return gator_events_install(&gator_events_mali_t6xx_interface); 783 return gator_events_install(&gator_events_mali_t6xx_interface);
756} 784}
757
758gator_events_init(gator_events_mali_t6xx_hw_init);
diff --git a/driver/gator_events_meminfo.c b/driver/gator_events_meminfo.c
index c1e360d..451290d 100644
--- a/driver/gator_events_meminfo.c
+++ b/driver/gator_events_meminfo.c
@@ -8,27 +8,62 @@
8 */ 8 */
9 9
10#include "gator.h" 10#include "gator.h"
11
12#include <linux/hardirq.h>
13#include <linux/kthread.h>
14#include <linux/sched.h>
15#include <linux/semaphore.h>
11#include <linux/workqueue.h> 16#include <linux/workqueue.h>
12#include <trace/events/kmem.h> 17#include <trace/events/kmem.h>
13#include <linux/hardirq.h>
14 18
15#define MEMINFO_MEMFREE 0 19enum {
16#define MEMINFO_MEMUSED 1 20 MEMINFO_MEMFREE,
17#define MEMINFO_BUFFERRAM 2 21 MEMINFO_MEMUSED,
18#define MEMINFO_TOTAL 3 22 MEMINFO_BUFFERRAM,
23 MEMINFO_TOTAL,
24};
25
26enum {
27 PROC_SIZE,
28 PROC_SHARE,
29 PROC_TEXT,
30 PROC_DATA,
31 PROC_COUNT,
32};
33
34static const char * const meminfo_names[] = {
35 "Linux_meminfo_memfree",
36 "Linux_meminfo_memused",
37 "Linux_meminfo_bufferram",
38};
39
40static const char * const proc_names[] = {
41 "Linux_proc_statm_size",
42 "Linux_proc_statm_share",
43 "Linux_proc_statm_text",
44 "Linux_proc_statm_data",
45};
19 46
20static ulong meminfo_global_enabled; 47static bool meminfo_global_enabled;
21static ulong meminfo_enabled[MEMINFO_TOTAL]; 48static ulong meminfo_enabled[MEMINFO_TOTAL];
22static ulong meminfo_key[MEMINFO_TOTAL]; 49static ulong meminfo_keys[MEMINFO_TOTAL];
23static unsigned long long meminfo_buffer[MEMINFO_TOTAL * 2]; 50static long long meminfo_buffer[2 * (MEMINFO_TOTAL + 2)];
24static int meminfo_length = 0; 51static int meminfo_length = 0;
25static unsigned int mem_event = 0;
26static bool new_data_avail; 52static bool new_data_avail;
27 53
28static void wq_sched_handler(struct work_struct *wsptr); 54static bool proc_global_enabled;
29DECLARE_WORK(work, wq_sched_handler); 55static ulong proc_enabled[PROC_COUNT];
30static struct timer_list meminfo_wake_up_timer; 56static ulong proc_keys[PROC_COUNT];
31static void meminfo_wake_up_handler(unsigned long unused_data); 57static DEFINE_PER_CPU(long long, proc_buffer[2 * (PROC_COUNT + 3)]);
58
59static int gator_meminfo_func(void *data);
60static bool gator_meminfo_run;
61// Initialize semaphore unlocked to initialize memory values
62#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
63static DECLARE_MUTEX(gator_meminfo_sem);
64#else
65static DEFINE_SEMAPHORE(gator_meminfo_sem);
66#endif
32 67
33#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) 68#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
34GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order)) 69GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order))
@@ -36,7 +71,7 @@ GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int
36GATOR_DEFINE_PROBE(mm_page_free, TP_PROTO(struct page *page, unsigned int order)) 71GATOR_DEFINE_PROBE(mm_page_free, TP_PROTO(struct page *page, unsigned int order))
37#endif 72#endif
38{ 73{
39 mem_event++; 74 up(&gator_meminfo_sem);
40} 75}
41 76
42#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) 77#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
@@ -45,12 +80,12 @@ GATOR_DEFINE_PROBE(mm_pagevec_free, TP_PROTO(struct page *page, int cold))
45GATOR_DEFINE_PROBE(mm_page_free_batched, TP_PROTO(struct page *page, int cold)) 80GATOR_DEFINE_PROBE(mm_page_free_batched, TP_PROTO(struct page *page, int cold))
46#endif 81#endif
47{ 82{
48 mem_event++; 83 up(&gator_meminfo_sem);
49} 84}
50 85
51GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype)) 86GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype))
52{ 87{
53 mem_event++; 88 up(&gator_meminfo_sem);
54} 89}
55 90
56static int gator_events_meminfo_create_files(struct super_block *sb, struct dentry *root) 91static int gator_events_meminfo_create_files(struct super_block *sb, struct dentry *root)
@@ -59,24 +94,21 @@ static int gator_events_meminfo_create_files(struct super_block *sb, struct dent
59 int i; 94 int i;
60 95
61 for (i = 0; i < MEMINFO_TOTAL; i++) { 96 for (i = 0; i < MEMINFO_TOTAL; i++) {
62 switch (i) { 97 dir = gatorfs_mkdir(sb, root, meminfo_names[i]);
63 case MEMINFO_MEMFREE: 98 if (!dir) {
64 dir = gatorfs_mkdir(sb, root, "Linux_meminfo_memfree");
65 break;
66 case MEMINFO_MEMUSED:
67 dir = gatorfs_mkdir(sb, root, "Linux_meminfo_memused");
68 break;
69 case MEMINFO_BUFFERRAM:
70 dir = gatorfs_mkdir(sb, root, "Linux_meminfo_bufferram");
71 break;
72 default:
73 return -1; 99 return -1;
74 } 100 }
101 gatorfs_create_ulong(sb, dir, "enabled", &meminfo_enabled[i]);
102 gatorfs_create_ro_ulong(sb, dir, "key", &meminfo_keys[i]);
103 }
104
105 for (i = 0; i < PROC_COUNT; ++i) {
106 dir = gatorfs_mkdir(sb, root, proc_names[i]);
75 if (!dir) { 107 if (!dir) {
76 return -1; 108 return -1;
77 } 109 }
78 gatorfs_create_ulong(sb, dir, "enabled", &meminfo_enabled[i]); 110 gatorfs_create_ulong(sb, dir, "enabled", &proc_enabled[i]);
79 gatorfs_create_ro_ulong(sb, dir, "key", &meminfo_key[i]); 111 gatorfs_create_ro_ulong(sb, dir, "key", &proc_keys[i]);
80 } 112 }
81 113
82 return 0; 114 return 0;
@@ -86,13 +118,26 @@ static int gator_events_meminfo_start(void)
86{ 118{
87 int i; 119 int i;
88 120
89 new_data_avail = true; 121 new_data_avail = false;
122 meminfo_global_enabled = 0;
90 for (i = 0; i < MEMINFO_TOTAL; i++) { 123 for (i = 0; i < MEMINFO_TOTAL; i++) {
91 if (meminfo_enabled[i]) { 124 if (meminfo_enabled[i]) {
92 meminfo_global_enabled = 1; 125 meminfo_global_enabled = 1;
126 break;
93 } 127 }
94 } 128 }
95 129
130 proc_global_enabled = 0;
131 for (i = 0; i < PROC_COUNT; ++i) {
132 if (proc_enabled[i]) {
133 proc_global_enabled = 1;
134 break;
135 }
136 }
137 if (meminfo_enabled[MEMINFO_MEMUSED]) {
138 proc_global_enabled = 1;
139 }
140
96 if (meminfo_global_enabled == 0) 141 if (meminfo_global_enabled == 0)
97 return 0; 142 return 0;
98 143
@@ -111,9 +156,16 @@ static int gator_events_meminfo_start(void)
111 if (GATOR_REGISTER_TRACE(mm_page_alloc)) 156 if (GATOR_REGISTER_TRACE(mm_page_alloc))
112 goto mm_page_alloc_exit; 157 goto mm_page_alloc_exit;
113 158
114 setup_timer(&meminfo_wake_up_timer, meminfo_wake_up_handler, 0); 159 // Start worker thread
160 gator_meminfo_run = true;
161 // Since the mutex starts unlocked, memory values will be initialized
162 if (IS_ERR(kthread_run(gator_meminfo_func, NULL, "gator_meminfo")))
163 goto kthread_run_exit;
164
115 return 0; 165 return 0;
116 166
167kthread_run_exit:
168 GATOR_UNREGISTER_TRACE(mm_page_alloc);
117mm_page_alloc_exit: 169mm_page_alloc_exit:
118#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) 170#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
119 GATOR_UNREGISTER_TRACE(mm_pagevec_free); 171 GATOR_UNREGISTER_TRACE(mm_pagevec_free);
@@ -132,8 +184,6 @@ mm_page_free_exit:
132 184
133static void gator_events_meminfo_stop(void) 185static void gator_events_meminfo_stop(void)
134{ 186{
135 int i;
136
137 if (meminfo_global_enabled) { 187 if (meminfo_global_enabled) {
138#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) 188#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
139 GATOR_UNREGISTER_TRACE(mm_page_free_direct); 189 GATOR_UNREGISTER_TRACE(mm_page_free_direct);
@@ -144,68 +194,75 @@ static void gator_events_meminfo_stop(void)
144#endif 194#endif
145 GATOR_UNREGISTER_TRACE(mm_page_alloc); 195 GATOR_UNREGISTER_TRACE(mm_page_alloc);
146 196
147 del_timer_sync(&meminfo_wake_up_timer); 197 // Stop worker thread
148 } 198 gator_meminfo_run = false;
149 199 up(&gator_meminfo_sem);
150 meminfo_global_enabled = 0;
151 for (i = 0; i < MEMINFO_TOTAL; i++) {
152 meminfo_enabled[i] = 0;
153 } 200 }
154} 201}
155 202
156// Must be run in process context as the kernel function si_meminfo() can sleep 203// Must be run in process context as the kernel function si_meminfo() can sleep
157static void wq_sched_handler(struct work_struct *wsptr) 204static int gator_meminfo_func(void *data)
158{ 205{
159 struct sysinfo info; 206 struct sysinfo info;
160 int i, len; 207 int i, len;
161 unsigned long long value; 208 unsigned long long value;
162 209
163 meminfo_length = len = 0; 210 for (;;) {
211 if (down_killable(&gator_meminfo_sem)) {
212 break;
213 }
164 214
165 si_meminfo(&info); 215 // Eat up any pending events
166 for (i = 0; i < MEMINFO_TOTAL; i++) { 216 while (!down_trylock(&gator_meminfo_sem));
167 if (meminfo_enabled[i]) { 217
168 switch (i) { 218 if (!gator_meminfo_run) {
169 case MEMINFO_MEMFREE: 219 break;
170 value = info.freeram * PAGE_SIZE; 220 }
171 break; 221
172 case MEMINFO_MEMUSED: 222 meminfo_length = len = 0;
173 value = (info.totalram - info.freeram) * PAGE_SIZE; 223
174 break; 224 si_meminfo(&info);
175 case MEMINFO_BUFFERRAM: 225 for (i = 0; i < MEMINFO_TOTAL; i++) {
176 value = info.bufferram * PAGE_SIZE; 226 if (meminfo_enabled[i]) {
177 break; 227 switch (i) {
178 default: 228 case MEMINFO_MEMFREE:
179 value = 0; 229 value = info.freeram * PAGE_SIZE;
180 break; 230 break;
231 case MEMINFO_MEMUSED:
232 // pid -1 means system wide
233 meminfo_buffer[len++] = 1;
234 meminfo_buffer[len++] = -1;
235 // Emit value
236 meminfo_buffer[len++] = meminfo_keys[MEMINFO_MEMUSED];
237 meminfo_buffer[len++] = (info.totalram - info.freeram) * PAGE_SIZE;
238 // Clear pid
239 meminfo_buffer[len++] = 1;
240 meminfo_buffer[len++] = 0;
241 continue;
242 case MEMINFO_BUFFERRAM:
243 value = info.bufferram * PAGE_SIZE;
244 break;
245 default:
246 value = 0;
247 break;
248 }
249 meminfo_buffer[len++] = meminfo_keys[i];
250 meminfo_buffer[len++] = value;
181 } 251 }
182 meminfo_buffer[len++] = (unsigned long long)meminfo_key[i];
183 meminfo_buffer[len++] = value;
184 } 252 }
185 }
186 253
187 meminfo_length = len; 254 meminfo_length = len;
188 new_data_avail = true; 255 new_data_avail = true;
189} 256 }
190 257
191static void meminfo_wake_up_handler(unsigned long unused_data) 258 return 0;
192{
193 // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
194 schedule_work(&work);
195} 259}
196 260
197static int gator_events_meminfo_read(long long **buffer) 261static int gator_events_meminfo_read(long long **buffer)
198{ 262{
199 static unsigned int last_mem_event = 0;
200
201 if (!on_primary_core() || !meminfo_global_enabled) 263 if (!on_primary_core() || !meminfo_global_enabled)
202 return 0; 264 return 0;
203 265
204 if (last_mem_event != mem_event) {
205 last_mem_event = mem_event;
206 mod_timer(&meminfo_wake_up_timer, jiffies + 1);
207 }
208
209 if (!new_data_avail) 266 if (!new_data_avail)
210 return 0; 267 return 0;
211 268
@@ -217,11 +274,97 @@ static int gator_events_meminfo_read(long long **buffer)
217 return meminfo_length; 274 return meminfo_length;
218} 275}
219 276
277static int gator_events_meminfo_read_proc(long long **buffer, struct task_struct *task)
278{
279 struct mm_struct *mm;
280 u64 share = 0;
281 int i;
282 long long value;
283 int len = 0;
284 int cpu = get_physical_cpu();
285 long long *buf = per_cpu(proc_buffer, cpu);
286
287 if (!proc_global_enabled) {
288 return 0;
289 }
290
291 // Collect the memory stats of the process instead of the thread
292 if (task->group_leader != NULL) {
293 task = task->group_leader;
294 }
295
296 // get_task_mm/mmput is not needed in this context because the task and it's mm are required as part of the sched_switch
297 mm = task->mm;
298 if (mm == NULL) {
299 return 0;
300 }
301
302 // Derived from task_statm in fs/proc/task_mmu.c
303 if (meminfo_enabled[MEMINFO_MEMUSED] || proc_enabled[PROC_SHARE]) {
304 share = get_mm_counter(mm,
305#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 32)
306 file_rss
307#else
308 MM_FILEPAGES
309#endif
310 );
311 }
312
313 // key of 1 indicates a pid
314 buf[len++] = 1;
315 buf[len++] = task->pid;
316
317 for (i = 0; i < PROC_COUNT; ++i) {
318 if (proc_enabled[i]) {
319 switch (i) {
320 case PROC_SIZE:
321 value = mm->total_vm;
322 break;
323 case PROC_SHARE:
324 value = share;
325 break;
326 case PROC_TEXT:
327 value = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> PAGE_SHIFT;
328 break;
329 case PROC_DATA:
330 value = mm->total_vm - mm->shared_vm;
331 break;
332 }
333
334 buf[len++] = proc_keys[i];
335 buf[len++] = value * PAGE_SIZE;
336 }
337 }
338
339 if (meminfo_enabled[MEMINFO_MEMUSED]) {
340 value = share + get_mm_counter(mm,
341#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 32)
342 anon_rss
343#else
344 MM_ANONPAGES
345#endif
346 );
347 // Send resident for this pid
348 buf[len++] = meminfo_keys[MEMINFO_MEMUSED];
349 buf[len++] = value * PAGE_SIZE;
350 }
351
352 // Clear pid
353 buf[len++] = 1;
354 buf[len++] = 0;
355
356 if (buffer)
357 *buffer = buf;
358
359 return len;
360}
361
220static struct gator_interface gator_events_meminfo_interface = { 362static struct gator_interface gator_events_meminfo_interface = {
221 .create_files = gator_events_meminfo_create_files, 363 .create_files = gator_events_meminfo_create_files,
222 .start = gator_events_meminfo_start, 364 .start = gator_events_meminfo_start,
223 .stop = gator_events_meminfo_stop, 365 .stop = gator_events_meminfo_stop,
224 .read64 = gator_events_meminfo_read, 366 .read64 = gator_events_meminfo_read,
367 .read_proc = gator_events_meminfo_read_proc,
225}; 368};
226 369
227int gator_events_meminfo_init(void) 370int gator_events_meminfo_init(void)
@@ -231,10 +374,14 @@ int gator_events_meminfo_init(void)
231 meminfo_global_enabled = 0; 374 meminfo_global_enabled = 0;
232 for (i = 0; i < MEMINFO_TOTAL; i++) { 375 for (i = 0; i < MEMINFO_TOTAL; i++) {
233 meminfo_enabled[i] = 0; 376 meminfo_enabled[i] = 0;
234 meminfo_key[i] = gator_events_get_key(); 377 meminfo_keys[i] = gator_events_get_key();
378 }
379
380 proc_global_enabled = 0;
381 for (i = 0; i < PROC_COUNT; ++i) {
382 proc_enabled[i] = 0;
383 proc_keys[i] = gator_events_get_key();
235 } 384 }
236 385
237 return gator_events_install(&gator_events_meminfo_interface); 386 return gator_events_install(&gator_events_meminfo_interface);
238} 387}
239
240gator_events_init(gator_events_meminfo_init);
diff --git a/driver/gator_events_mmaped.c b/driver/gator_events_mmapped.c
index f7670f6..f055e48 100644
--- a/driver/gator_events_mmaped.c
+++ b/driver/gator_events_mmapped.c
@@ -11,12 +11,18 @@
11 * To add them to the events.xml, create an events-mmap.xml with the 11 * To add them to the events.xml, create an events-mmap.xml with the
12 * following contents and rebuild gatord: 12 * following contents and rebuild gatord:
13 * 13 *
14 * <counter_set name="mmaped_cnt" count="3"/> 14 * <counter_set name="mmapped_cnt" count="3"/>
15 * <category name="mmaped" counter_set="mmaped_cnt" per_cpu="no"> 15 * <category name="mmapped" counter_set="mmapped_cnt" per_cpu="no">
16 * <event event="0x0" title="Simulated1" name="Sine" display="maximum" average_selection="yes" description="Sort-of-sine"/> 16 * <event event="0x0" title="Simulated1" name="Sine" display="maximum" average_selection="yes" description="Sort-of-sine"/>
17 * <event event="0x1" title="Simulated2" name="Triangle" display="maximum" average_selection="yes" description="Triangular wave"/> 17 * <event event="0x1" title="Simulated2" name="Triangle" display="maximum" average_selection="yes" description="Triangular wave"/>
18 * <event event="0x2" title="Simulated3" name="PWM" display="maximum" average_selection="yes" description="PWM Signal"/> 18 * <event event="0x2" title="Simulated3" name="PWM" display="maximum" average_selection="yes" description="PWM Signal"/>
19 * </category> 19 * </category>
20 *
21 * When adding custom events, be sure do the following
22 * - add any needed .c files to the gator driver Makefile
23 * - call gator_events_install in the events init function
24 * - add the init function to GATOR_EVENTS_LIST in gator_main.c
25 * - add a new events-*.xml file to the gator daemon and rebuild
20 */ 26 */
21 27
22#include <linux/init.h> 28#include <linux/init.h>
@@ -25,79 +31,71 @@
25 31
26#include "gator.h" 32#include "gator.h"
27 33
28#define MMAPED_COUNTERS_NUM 3 34#define MMAPPED_COUNTERS_NUM 3
35
36static int mmapped_global_enabled;
29 37
30static struct { 38static struct {
31 unsigned long enabled; 39 unsigned long enabled;
32 unsigned long event; 40 unsigned long event;
33 unsigned long key; 41 unsigned long key;
34} mmaped_counters[MMAPED_COUNTERS_NUM]; 42} mmapped_counters[MMAPPED_COUNTERS_NUM];
35 43
36static int mmaped_buffer[MMAPED_COUNTERS_NUM * 2]; 44static int mmapped_buffer[MMAPPED_COUNTERS_NUM * 2];
37 45
38#ifdef TODO
39static void __iomem *mmaped_base;
40#endif
41
42#ifndef TODO
43static s64 prev_time; 46static s64 prev_time;
44#endif
45 47
46/* Adds mmaped_cntX directories and enabled, event, and key files to /dev/gator/events */ 48/* Adds mmapped_cntX directories and enabled, event, and key files to /dev/gator/events */
47static int gator_events_mmaped_create_files(struct super_block *sb, 49static int gator_events_mmapped_create_files(struct super_block *sb,
48 struct dentry *root) 50 struct dentry *root)
49{ 51{
50 int i; 52 int i;
51 53
52 for (i = 0; i < MMAPED_COUNTERS_NUM; i++) { 54 for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) {
53 char buf[16]; 55 char buf[16];
54 struct dentry *dir; 56 struct dentry *dir;
55 57
56 snprintf(buf, sizeof(buf), "mmaped_cnt%d", i); 58 snprintf(buf, sizeof(buf), "mmapped_cnt%d", i);
57 dir = gatorfs_mkdir(sb, root, buf); 59 dir = gatorfs_mkdir(sb, root, buf);
58 if (WARN_ON(!dir)) 60 if (WARN_ON(!dir))
59 return -1; 61 return -1;
60 gatorfs_create_ulong(sb, dir, "enabled", 62 gatorfs_create_ulong(sb, dir, "enabled",
61 &mmaped_counters[i].enabled); 63 &mmapped_counters[i].enabled);
62 gatorfs_create_ulong(sb, dir, "event", 64 gatorfs_create_ulong(sb, dir, "event",
63 &mmaped_counters[i].event); 65 &mmapped_counters[i].event);
64 gatorfs_create_ro_ulong(sb, dir, "key", 66 gatorfs_create_ro_ulong(sb, dir, "key",
65 &mmaped_counters[i].key); 67 &mmapped_counters[i].key);
66 } 68 }
67 69
68 return 0; 70 return 0;
69} 71}
70 72
71static int gator_events_mmaped_start(void) 73static int gator_events_mmapped_start(void)
72{ 74{
73#ifdef TODO 75 int i;
74 for (i = 0; i < MMAPED_COUNTERS_NUM; i++)
75 writel(mmaped_counters[i].event,
76 mmaped_base + COUNTERS_CONFIG_OFFSET[i]);
77
78 writel(ENABLED, COUNTERS_CONTROL_OFFSET);
79#endif
80
81#ifndef TODO
82 struct timespec ts; 76 struct timespec ts;
77
83 getnstimeofday(&ts); 78 getnstimeofday(&ts);
84 prev_time = timespec_to_ns(&ts); 79 prev_time = timespec_to_ns(&ts);
85#endif 80
81 mmapped_global_enabled = 0;
82 for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) {
83 if (mmapped_counters[i].enabled) {
84 mmapped_global_enabled = 1;
85 break;
86 }
87 }
86 88
87 return 0; 89 return 0;
88} 90}
89 91
90static void gator_events_mmaped_stop(void) 92static void gator_events_mmapped_stop(void)
91{ 93{
92#ifdef TODO
93 writel(DISABLED, COUNTERS_CONTROL_OFFSET);
94#endif
95} 94}
96 95
97#ifndef TODO
98/* This function "simulates" counters, generating values of fancy 96/* This function "simulates" counters, generating values of fancy
99 * functions like sine or triangle... */ 97 * functions like sine or triangle... */
100static int mmaped_simulate(int counter, int delta_in_us) 98static int mmapped_simulate(int counter, int delta_in_us)
101{ 99{
102 int result = 0; 100 int result = 0;
103 101
@@ -157,73 +155,55 @@ static int mmaped_simulate(int counter, int delta_in_us)
157 155
158 return result; 156 return result;
159} 157}
160#endif
161 158
162static int gator_events_mmaped_read(int **buffer) 159static int gator_events_mmapped_read(int **buffer)
163{ 160{
164 int i; 161 int i;
165 int len = 0; 162 int len = 0;
166#ifndef TODO
167 int delta_in_us; 163 int delta_in_us;
168 struct timespec ts; 164 struct timespec ts;
169 s64 time; 165 s64 time;
170#endif
171 166
172 /* System wide counters - read from one core only */ 167 /* System wide counters - read from one core only */
173 if (!on_primary_core()) 168 if (!on_primary_core() || !mmapped_global_enabled)
174 return 0; 169 return 0;
175 170
176#ifndef TODO
177 getnstimeofday(&ts); 171 getnstimeofday(&ts);
178 time = timespec_to_ns(&ts); 172 time = timespec_to_ns(&ts);
179 delta_in_us = (int)(time - prev_time) / 1000; 173 delta_in_us = (int)(time - prev_time) / 1000;
180 prev_time = time; 174 prev_time = time;
181#endif 175
182 176 for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) {
183 for (i = 0; i < MMAPED_COUNTERS_NUM; i++) { 177 if (mmapped_counters[i].enabled) {
184 if (mmaped_counters[i].enabled) { 178 mmapped_buffer[len++] = mmapped_counters[i].key;
185 mmaped_buffer[len++] = mmaped_counters[i].key; 179 mmapped_buffer[len++] =
186#ifdef TODO 180 mmapped_simulate(mmapped_counters[i].event,
187 mmaped_buffer[len++] =
188 readl(mmaped_base + COUNTERS_VALUE_OFFSET[i]);
189#else
190 mmaped_buffer[len++] =
191 mmaped_simulate(mmaped_counters[i].event,
192 delta_in_us); 181 delta_in_us);
193#endif
194 } 182 }
195 } 183 }
196 184
197 if (buffer) 185 if (buffer)
198 *buffer = mmaped_buffer; 186 *buffer = mmapped_buffer;
199 187
200 return len; 188 return len;
201} 189}
202 190
203static struct gator_interface gator_events_mmaped_interface = { 191static struct gator_interface gator_events_mmapped_interface = {
204 .create_files = gator_events_mmaped_create_files, 192 .create_files = gator_events_mmapped_create_files,
205 .start = gator_events_mmaped_start, 193 .start = gator_events_mmapped_start,
206 .stop = gator_events_mmaped_stop, 194 .stop = gator_events_mmapped_stop,
207 .read = gator_events_mmaped_read, 195 .read = gator_events_mmapped_read,
208}; 196};
209 197
210/* Must not be static! */ 198/* Must not be static! */
211int __init gator_events_mmaped_init(void) 199int __init gator_events_mmapped_init(void)
212{ 200{
213 int i; 201 int i;
214 202
215#ifdef TODO 203 for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) {
216 mmaped_base = ioremap(COUNTERS_PHYS_ADDR, SZ_4K); 204 mmapped_counters[i].enabled = 0;
217 if (!mmaped_base) 205 mmapped_counters[i].key = gator_events_get_key();
218 return -ENOMEM;
219#endif
220
221 for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
222 mmaped_counters[i].enabled = 0;
223 mmaped_counters[i].key = gator_events_get_key();
224 } 206 }
225 207
226 return gator_events_install(&gator_events_mmaped_interface); 208 return gator_events_install(&gator_events_mmapped_interface);
227} 209}
228
229gator_events_init(gator_events_mmaped_init);
diff --git a/driver/gator_events_net.c b/driver/gator_events_net.c
index 80cdee4..9c8d3a4 100644
--- a/driver/gator_events_net.c
+++ b/driver/gator_events_net.c
@@ -73,6 +73,8 @@ static void calculate_delta(int *rx, int *tx)
73 73
74static int gator_events_net_create_files(struct super_block *sb, struct dentry *root) 74static int gator_events_net_create_files(struct super_block *sb, struct dentry *root)
75{ 75{
76 // Network counters are not currently supported in RT-Preempt full because mod_timer is used
77#ifndef CONFIG_PREEMPT_RT_FULL
76 struct dentry *dir; 78 struct dentry *dir;
77 79
78 dir = gatorfs_mkdir(sb, root, "Linux_net_rx"); 80 dir = gatorfs_mkdir(sb, root, "Linux_net_rx");
@@ -88,6 +90,7 @@ static int gator_events_net_create_files(struct super_block *sb, struct dentry *
88 } 90 }
89 gatorfs_create_ulong(sb, dir, "enabled", &nettx_enabled); 91 gatorfs_create_ulong(sb, dir, "enabled", &nettx_enabled);
90 gatorfs_create_ro_ulong(sb, dir, "key", &nettx_key); 92 gatorfs_create_ro_ulong(sb, dir, "key", &nettx_key);
93#endif
91 94
92 return 0; 95 return 0;
93} 96}
@@ -167,5 +170,3 @@ int gator_events_net_init(void)
167 170
168 return gator_events_install(&gator_events_net_interface); 171 return gator_events_install(&gator_events_net_interface);
169} 172}
170
171gator_events_init(gator_events_net_init);
diff --git a/driver/gator_events_perf_pmu.c b/driver/gator_events_perf_pmu.c
index 53b2d0a..d472df9 100644
--- a/driver/gator_events_perf_pmu.c
+++ b/driver/gator_events_perf_pmu.c
@@ -6,13 +6,18 @@
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8 8
9#include <linux/slab.h>
10#include <linux/perf_event.h>
11#include "gator.h" 9#include "gator.h"
12 10
13// gator_events_armvX.c is used for Linux 2.6.x 11// gator_events_armvX.c is used for Linux 2.6.x
14#if GATOR_PERF_PMU_SUPPORT 12#if GATOR_PERF_PMU_SUPPORT
15 13
14#include <linux/io.h>
15#ifdef CONFIG_OF
16#include <linux/of_address.h>
17#endif
18#include <linux/perf_event.h>
19#include <linux/slab.h>
20
16extern bool event_based_sampling; 21extern bool event_based_sampling;
17 22
18// Maximum number of per-core counters - currently reserves enough space for two full hardware PMUs for big.LITTLE 23// Maximum number of per-core counters - currently reserves enough space for two full hardware PMUs for big.LITTLE
@@ -22,6 +27,9 @@ extern bool event_based_sampling;
22// + 1 for the cci-400 cycles counter 27// + 1 for the cci-400 cycles counter
23#define UCCNT (CCI_400 + 1) 28#define UCCNT (CCI_400 + 1)
24 29
30// Default to 0 if unable to probe the revision which was the previous behavior
31#define DEFAULT_CCI_REVISION 0
32
25// A gator_attr is needed for every counter 33// A gator_attr is needed for every counter
26struct gator_attr { 34struct gator_attr {
27 // Set once in gator_events_perf_pmu_*_init - the name of the event in the gatorfs 35 // Set once in gator_events_perf_pmu_*_init - the name of the event in the gatorfs
@@ -404,17 +412,81 @@ static void __attr_init(struct gator_attr *const attr)
404 attr->key = gator_events_get_key(); 412 attr->key = gator_events_get_key();
405} 413}
406 414
415#ifdef CONFIG_OF
416
417static const struct of_device_id arm_cci_matches[] = {
418 {.compatible = "arm,cci-400" },
419 {},
420};
421
422static int probe_cci_revision(void)
423{
424 struct device_node *np;
425 struct resource res;
426 void __iomem *cci_ctrl_base;
427 int rev;
428 int ret = DEFAULT_CCI_REVISION;
429
430 np = of_find_matching_node(NULL, arm_cci_matches);
431 if (!np) {
432 return ret;
433 }
434
435 if (of_address_to_resource(np, 0, &res)) {
436 goto node_put;
437 }
438
439 cci_ctrl_base = ioremap(res.start, resource_size(&res));
440
441 rev = (readl_relaxed(cci_ctrl_base + 0xfe8) >> 4) & 0xf;
442
443 if (rev <= 4) {
444 ret = 0;
445 } else if (rev <= 6) {
446 ret = 1;
447 }
448
449 iounmap(cci_ctrl_base);
450
451 node_put:
452 of_node_put(np);
453
454 return ret;
455}
456
457#else
458
459static int probe_cci_revision(void)
460{
461 return DEFAULT_CCI_REVISION;
462}
463
464#endif
465
407static void gator_events_perf_pmu_cci_init(const int type) 466static void gator_events_perf_pmu_cci_init(const int type)
408{ 467{
409 int cnt; 468 int cnt;
469 const char *cci_name;
470
471 switch (probe_cci_revision()) {
472 case 0:
473 cci_name = "cci-400";
474 break;
475 case 1:
476 cci_name = "cci-400-r1";
477 break;
478 default:
479 pr_debug("gator: unrecognized cci-400 revision\n");
480 return;
481 }
410 482
411 strncpy(uc_attrs[uc_attr_count].name, "cci-400_ccnt", sizeof(uc_attrs[uc_attr_count].name)); 483 snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", cci_name);
412 uc_attrs[uc_attr_count].type = type; 484 uc_attrs[uc_attr_count].type = type;
413 ++uc_attr_count; 485 ++uc_attr_count;
414 486
415 for (cnt = 0; cnt < CCI_400; ++cnt, ++uc_attr_count) { 487 for (cnt = 0; cnt < CCI_400; ++cnt, ++uc_attr_count) {
416 struct gator_attr *const attr = &uc_attrs[uc_attr_count]; 488 struct gator_attr *const attr = &uc_attrs[uc_attr_count];
417 snprintf(attr->name, sizeof(attr->name), "cci-400_cnt%d", cnt); 489 snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", cci_name, cnt);
418 attr->type = type; 490 attr->type = type;
419 } 491 }
420} 492}
@@ -477,7 +549,7 @@ int gator_events_perf_pmu_init(void)
477 } 549 }
478 550
479 if (pe->pmu != NULL && type == pe->pmu->type) { 551 if (pe->pmu != NULL && type == pe->pmu->type) {
480 if (strcmp("CCI", pe->pmu->name) == 0) { 552 if (strcmp("CCI", pe->pmu->name) == 0 || strcmp("CCI_400", pe->pmu->name) == 0) {
481 gator_events_perf_pmu_cci_init(type); 553 gator_events_perf_pmu_cci_init(type);
482 } else if ((gator_cpu = gator_find_cpu_by_pmu_name(pe->pmu->name)) != NULL) { 554 } else if ((gator_cpu = gator_find_cpu_by_pmu_name(pe->pmu->name)) != NULL) {
483 found_cpu = true; 555 found_cpu = true;
@@ -512,5 +584,4 @@ int gator_events_perf_pmu_init(void)
512 return gator_events_install(&gator_events_perf_pmu_interface); 584 return gator_events_install(&gator_events_perf_pmu_interface);
513} 585}
514 586
515gator_events_init(gator_events_perf_pmu_init);
516#endif 587#endif
diff --git a/driver/gator_events_sched.c b/driver/gator_events_sched.c
index 461a051..29f4e39 100644
--- a/driver/gator_events_sched.c
+++ b/driver/gator_events_sched.c
@@ -111,5 +111,3 @@ 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
115gator_events_init(gator_events_sched_init);
diff --git a/driver/gator_events_scorpion.c b/driver/gator_events_scorpion.c
index aaf306a..c91db12 100644
--- a/driver/gator_events_scorpion.c
+++ b/driver/gator_events_scorpion.c
@@ -666,11 +666,4 @@ int gator_events_scorpion_init(void)
666 return gator_events_install(&gator_events_scorpion_interface); 666 return gator_events_install(&gator_events_scorpion_interface);
667} 667}
668 668
669gator_events_init(gator_events_scorpion_init);
670
671#else
672int gator_events_scorpion_init(void)
673{
674 return -1;
675}
676#endif 669#endif
diff --git a/driver/gator_main.c b/driver/gator_main.c
index ead7eae..9773ae2 100644
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
@@ -8,7 +8,8 @@
8 */ 8 */
9 9
10// This version must match the gator daemon version 10// This version must match the gator daemon version
11static unsigned long gator_protocol_version = 16; 11#define PROTOCOL_VERSION 17
12static unsigned long gator_protocol_version = PROTOCOL_VERSION;
12 13
13#include <linux/slab.h> 14#include <linux/slab.h>
14#include <linux/cpu.h> 15#include <linux/cpu.h>
@@ -22,16 +23,20 @@ static unsigned long gator_protocol_version = 16;
22#include <linux/module.h> 23#include <linux/module.h>
23#include <linux/perf_event.h> 24#include <linux/perf_event.h>
24#include <linux/utsname.h> 25#include <linux/utsname.h>
26#include <linux/kthread.h>
25#include <asm/stacktrace.h> 27#include <asm/stacktrace.h>
26#include <asm/uaccess.h> 28#include <asm/uaccess.h>
27 29
28#include "gator.h" 30#include "gator.h"
29#include "gator_events.h"
30 31
31#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) 32#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
32#error kernels prior to 2.6.32 are not supported 33#error kernels prior to 2.6.32 are not supported
33#endif 34#endif
34 35
36#if defined(MODULE) && !defined(CONFIG_MODULES)
37#error Cannot build a module against a kernel that does not support modules. To resolve, either rebuild the kernel to support modules or build gator as part of the kernel.
38#endif
39
35#if !defined(CONFIG_GENERIC_TRACER) && !defined(CONFIG_TRACING) 40#if !defined(CONFIG_GENERIC_TRACER) && !defined(CONFIG_TRACING)
36#error gator requires the kernel to have CONFIG_GENERIC_TRACER or CONFIG_TRACING defined 41#error gator requires the kernel to have CONFIG_GENERIC_TRACER or CONFIG_TRACING defined
37#endif 42#endif
@@ -44,17 +49,15 @@ static unsigned long gator_protocol_version = 16;
44#error gator requires the kernel to have CONFIG_HIGH_RES_TIMERS defined to support PC sampling 49#error gator requires the kernel to have CONFIG_HIGH_RES_TIMERS defined to support PC sampling
45#endif 50#endif
46 51
47#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) /* Because CONFIG_LOCAL_TIMERS was removed in 3.12 */ 52#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && defined(__arm__) && defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
48#if defined(__arm__) && defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
49#error gator requires the kernel to have CONFIG_LOCAL_TIMERS defined on SMP systems 53#error gator requires the kernel to have CONFIG_LOCAL_TIMERS defined on SMP systems
50#endif 54#endif
51#endif
52 55
53#if (GATOR_PERF_SUPPORT) && (!(GATOR_PERF_PMU_SUPPORT)) 56#if (GATOR_PERF_SUPPORT) && (!(GATOR_PERF_PMU_SUPPORT))
54#ifndef CONFIG_PERF_EVENTS 57#ifndef CONFIG_PERF_EVENTS
55#warning gator requires the kernel to have CONFIG_PERF_EVENTS defined to support pmu hardware counters 58#error gator requires the kernel to have CONFIG_PERF_EVENTS defined to support pmu hardware counters
56#elif !defined CONFIG_HW_PERF_EVENTS 59#elif !defined CONFIG_HW_PERF_EVENTS
57#warning gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters 60#error gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters
58#endif 61#endif
59#endif 62#endif
60 63
@@ -89,6 +92,7 @@ static unsigned long gator_protocol_version = 16;
89#define MESSAGE_COOKIE 1 92#define MESSAGE_COOKIE 1
90#define MESSAGE_THREAD_NAME 2 93#define MESSAGE_THREAD_NAME 2
91#define HRTIMER_CORE_NAME 3 94#define HRTIMER_CORE_NAME 3
95#define MESSAGE_LINK 4
92 96
93#define MESSAGE_GPU_START 1 97#define MESSAGE_GPU_START 1
94#define MESSAGE_GPU_STOP 2 98#define MESSAGE_GPU_STOP 2
@@ -138,6 +142,7 @@ static u64 gator_live_rate;
138 142
139static unsigned long gator_started; 143static unsigned long gator_started;
140static u64 gator_monotonic_started; 144static u64 gator_monotonic_started;
145static u64 gator_hibernate_time;
141static unsigned long gator_buffer_opened; 146static unsigned long gator_buffer_opened;
142static unsigned long gator_timer_count; 147static unsigned long gator_timer_count;
143static unsigned long gator_response_type; 148static unsigned long gator_response_type;
@@ -149,6 +154,8 @@ bool event_based_sampling;
149static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait); 154static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
150static DECLARE_WAIT_QUEUE_HEAD(gator_annotate_wait); 155static DECLARE_WAIT_QUEUE_HEAD(gator_annotate_wait);
151static struct timer_list gator_buffer_wake_up_timer; 156static struct timer_list gator_buffer_wake_up_timer;
157static bool gator_buffer_wake_stop;
158static struct task_struct *gator_buffer_wake_thread;
152static LIST_HEAD(gator_events); 159static LIST_HEAD(gator_events);
153 160
154static DEFINE_PER_CPU(u64, last_timestamp); 161static DEFINE_PER_CPU(u64, last_timestamp);
@@ -191,6 +198,34 @@ static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer);
191// The time after which the buffer should be committed for live display 198// The time after which the buffer should be committed for live display
192static DEFINE_PER_CPU(u64, gator_buffer_commit_time); 199static DEFINE_PER_CPU(u64, gator_buffer_commit_time);
193 200
201// List of all gator events - new events must be added to this list
202#define GATOR_EVENTS_LIST \
203 GATOR_EVENT(gator_events_armv6_init) \
204 GATOR_EVENT(gator_events_armv7_init) \
205 GATOR_EVENT(gator_events_block_init) \
206 GATOR_EVENT(gator_events_ccn504_init) \
207 GATOR_EVENT(gator_events_irq_init) \
208 GATOR_EVENT(gator_events_l2c310_init) \
209 GATOR_EVENT(gator_events_mali_init) \
210 GATOR_EVENT(gator_events_mali_t6xx_hw_init) \
211 GATOR_EVENT(gator_events_mali_t6xx_init) \
212 GATOR_EVENT(gator_events_meminfo_init) \
213 GATOR_EVENT(gator_events_mmapped_init) \
214 GATOR_EVENT(gator_events_net_init) \
215 GATOR_EVENT(gator_events_perf_pmu_init) \
216 GATOR_EVENT(gator_events_sched_init) \
217 GATOR_EVENT(gator_events_scorpion_init) \
218
219#define GATOR_EVENT(EVENT_INIT) __weak int EVENT_INIT(void);
220GATOR_EVENTS_LIST
221#undef GATOR_EVENT
222
223static int (*gator_events_list[])(void) = {
224#define GATOR_EVENT(EVENT_INIT) EVENT_INIT,
225GATOR_EVENTS_LIST
226#undef GATOR_EVENT
227};
228
194/****************************************************************************** 229/******************************************************************************
195 * Application Includes 230 * Application Includes
196 ******************************************************************************/ 231 ******************************************************************************/
@@ -394,6 +429,21 @@ static void gator_buffer_wake_up(unsigned long data)
394 wake_up(&gator_buffer_wait); 429 wake_up(&gator_buffer_wait);
395} 430}
396 431
432static int gator_buffer_wake_func(void *data)
433{
434 while (!gator_buffer_wake_stop) {
435 set_current_state(TASK_INTERRUPTIBLE);
436 schedule();
437 if (gator_buffer_wake_stop) {
438 break;
439 }
440
441 gator_buffer_wake_up(0);
442 }
443
444 return 0;
445}
446
397/****************************************************************************** 447/******************************************************************************
398 * Commit interface 448 * Commit interface
399 ******************************************************************************/ 449 ******************************************************************************/
@@ -519,7 +569,14 @@ static void gator_commit_buffer(int cpu, int buftype, u64 time)
519 marshal_frame(cpu, buftype); 569 marshal_frame(cpu, buftype);
520 570
521 // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater 571 // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
522 mod_timer(&gator_buffer_wake_up_timer, jiffies + 1); 572 if (per_cpu(in_scheduler_context, cpu)) {
573#ifndef CONFIG_PREEMPT_RT_FULL
574 // mod_timer can not be used in interrupt context in RT-Preempt full
575 mod_timer(&gator_buffer_wake_up_timer, jiffies + 1);
576#endif
577 } else {
578 wake_up_process(gator_buffer_wake_thread);
579 }
523} 580}
524 581
525static void buffer_check(int cpu, int buftype, u64 time) 582static void buffer_check(int cpu, int buftype, u64 time)
@@ -592,8 +649,13 @@ void gator_backtrace_handler(struct pt_regs *const regs)
592 649
593 // Collect counters 650 // Collect counters
594 if (!per_cpu(collecting, cpu)) { 651 if (!per_cpu(collecting, cpu)) {
595 collect_counters(time); 652 collect_counters(time, NULL);
596 } 653 }
654
655 // No buffer flushing occurs during sched switch for RT-Preempt full. The block counter frame will be flushed by collect_counters, but the sched buffer needs to be explicitly flushed
656#ifdef CONFIG_PREEMPT_RT_FULL
657 buffer_check(cpu, SCHED_TRACE_BUF, time);
658#endif
597} 659}
598 660
599static int gator_running; 661static int gator_running;
@@ -817,6 +879,7 @@ static struct notifier_block __refdata gator_hotcpu_notifier = {
817static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy) 879static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy)
818{ 880{
819 int cpu; 881 int cpu;
882 struct timespec ts;
820 883
821 switch (event) { 884 switch (event) {
822 case PM_HIBERNATION_PREPARE: 885 case PM_HIBERNATION_PREPARE:
@@ -827,9 +890,20 @@ static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void
827 for_each_online_cpu(cpu) { 890 for_each_online_cpu(cpu) {
828 gator_timer_offline_dispatch(lcpu_to_pcpu(cpu), false); 891 gator_timer_offline_dispatch(lcpu_to_pcpu(cpu), false);
829 } 892 }
893
894 // Record the wallclock hibernate time
895 getnstimeofday(&ts);
896 gator_hibernate_time = timespec_to_ns(&ts) - gator_get_time();
830 break; 897 break;
831 case PM_POST_HIBERNATION: 898 case PM_POST_HIBERNATION:
832 case PM_POST_SUSPEND: 899 case PM_POST_SUSPEND:
900 // Adjust gator_monotonic_started for the time spent sleeping, as gator_get_time does not account for it
901 if (gator_hibernate_time > 0) {
902 getnstimeofday(&ts);
903 gator_monotonic_started += gator_hibernate_time + gator_get_time() - timespec_to_ns(&ts);
904 gator_hibernate_time = 0;
905 }
906
833 for_each_online_cpu(cpu) { 907 for_each_online_cpu(cpu) {
834 gator_timer_online_dispatch(lcpu_to_pcpu(cpu), false); 908 gator_timer_online_dispatch(lcpu_to_pcpu(cpu), false);
835 } 909 }
@@ -904,8 +978,10 @@ int gator_events_install(struct gator_interface *interface)
904 978
905int gator_events_get_key(void) 979int gator_events_get_key(void)
906{ 980{
907 // key of zero is reserved as a timestamp 981 // key 0 is reserved as a timestamp
908 static int key = 1; 982 // key 1 is reserved as the marker for thread specific counters
983 // Odd keys are assigned by the driver, even keys by the daemon
984 static int key = 3;
909 985
910 const int ret = key; 986 const int ret = key;
911 key += 2; 987 key += 2;
@@ -918,7 +994,7 @@ static int gator_init(void)
918 994
919 calc_first_cluster_size(); 995 calc_first_cluster_size();
920 996
921 // events sources (gator_events.h, generated by gator_events.sh) 997 // events sources
922 for (i = 0; i < ARRAY_SIZE(gator_events_list); i++) 998 for (i = 0; i < ARRAY_SIZE(gator_events_list); i++)
923 if (gator_events_list[i]) 999 if (gator_events_list[i])
924 gator_events_list[i](); 1000 gator_events_list[i]();
@@ -943,6 +1019,11 @@ static int gator_start(void)
943 unsigned long cpu, i; 1019 unsigned long cpu, i;
944 struct gator_interface *gi; 1020 struct gator_interface *gi;
945 1021
1022 gator_buffer_wake_stop = false;
1023 if (IS_ERR(gator_buffer_wake_thread = kthread_run(gator_buffer_wake_func, NULL, "gator_bwake"))) {
1024 goto bwake_failure;
1025 }
1026
946 if (gator_migrate_start()) 1027 if (gator_migrate_start())
947 goto migrate_failure; 1028 goto migrate_failure;
948 1029
@@ -1013,6 +1094,9 @@ cookies_failure:
1013events_failure: 1094events_failure:
1014 gator_migrate_stop(); 1095 gator_migrate_stop();
1015migrate_failure: 1096migrate_failure:
1097 gator_buffer_wake_stop = true;
1098 wake_up_process(gator_buffer_wake_thread);
1099bwake_failure:
1016 1100
1017 return -1; 1101 return -1;
1018} 1102}
@@ -1036,6 +1120,9 @@ static void gator_stop(void)
1036 gi->stop(); 1120 gi->stop();
1037 1121
1038 gator_migrate_stop(); 1122 gator_migrate_stop();
1123
1124 gator_buffer_wake_stop = true;
1125 wake_up_process(gator_buffer_wake_thread);
1039} 1126}
1040 1127
1041/****************************************************************************** 1128/******************************************************************************
@@ -1440,3 +1527,6 @@ module_exit(gator_module_exit);
1440MODULE_LICENSE("GPL"); 1527MODULE_LICENSE("GPL");
1441MODULE_AUTHOR("ARM Ltd"); 1528MODULE_AUTHOR("ARM Ltd");
1442MODULE_DESCRIPTION("Gator system profiler"); 1529MODULE_DESCRIPTION("Gator system profiler");
1530#define STRIFY2(ARG) #ARG
1531#define STRIFY(ARG) STRIFY2(ARG)
1532MODULE_VERSION(STRIFY(PROTOCOL_VERSION));
diff --git a/driver/gator_marshaling.c b/driver/gator_marshaling.c
index 3282de8..af80ff6 100644
--- a/driver/gator_marshaling.c
+++ b/driver/gator_marshaling.c
@@ -89,6 +89,25 @@ static void marshal_thread_name(int pid, char *name)
89 local_irq_restore(flags); 89 local_irq_restore(flags);
90} 90}
91 91
92static void marshal_link(int cookie, int tgid, int pid)
93{
94 unsigned long cpu = get_physical_cpu(), flags;
95 u64 time;
96
97 local_irq_save(flags);
98 time = gator_get_time();
99 if (buffer_check_space(cpu, NAME_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
100 gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_LINK);
101 gator_buffer_write_packed_int64(cpu, NAME_BUF, time);
102 gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
103 gator_buffer_write_packed_int(cpu, NAME_BUF, tgid);
104 gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
105 }
106 // Check and commit; commit is set to occur once buffer is 3/4 full
107 buffer_check(cpu, NAME_BUF, time);
108 local_irq_restore(flags);
109}
110
92static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel, u64 time) 111static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel, u64 time)
93{ 112{
94 int cpu = get_physical_cpu(); 113 int cpu = get_physical_cpu();
diff --git a/driver/gator_trace_gpu.c b/driver/gator_trace_gpu.c
index 12623c4..be135b4 100644
--- a/driver/gator_trace_gpu.c
+++ b/driver/gator_trace_gpu.c
@@ -85,7 +85,7 @@ static void mali_gpu_stop(int unit, int core)
85 int count; 85 int count;
86 int last_tgid = 0; 86 int last_tgid = 0;
87 int last_pid = 0; 87 int last_pid = 0;
88 int last_job_id = 0; 88 //int last_job_id = 0;
89 89
90 spin_lock(&mali_gpu_jobs_lock); 90 spin_lock(&mali_gpu_jobs_lock);
91 if (mali_gpu_jobs[unit][core].count == 0) { 91 if (mali_gpu_jobs[unit][core].count == 0) {
@@ -97,7 +97,7 @@ static void mali_gpu_stop(int unit, int core)
97 if (count) { 97 if (count) {
98 last_tgid = mali_gpu_jobs[unit][core].last_tgid; 98 last_tgid = mali_gpu_jobs[unit][core].last_tgid;
99 last_pid = mali_gpu_jobs[unit][core].last_pid; 99 last_pid = mali_gpu_jobs[unit][core].last_pid;
100 last_job_id = mali_gpu_jobs[unit][core].last_job_id; 100 //last_job_id = mali_gpu_jobs[unit][core].last_job_id;
101 } 101 }
102 spin_unlock(&mali_gpu_jobs_lock); 102 spin_unlock(&mali_gpu_jobs_lock);
103 103
@@ -242,7 +242,7 @@ int gator_trace_gpu_start(void)
242 * Absence of gpu trace points is not an error 242 * Absence of gpu trace points is not an error
243 */ 243 */
244 244
245 memset(&mali_gpu_jobs, sizeof(mali_gpu_jobs), 0); 245 memset(&mali_gpu_jobs, 0, sizeof(mali_gpu_jobs));
246 gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0; 246 gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
247 247
248#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx) 248#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
diff --git a/driver/gator_trace_sched.c b/driver/gator_trace_sched.c
index e98815e..332b3f6 100644
--- a/driver/gator_trace_sched.c
+++ b/driver/gator_trace_sched.c
@@ -22,6 +22,7 @@ enum {
22 22
23static DEFINE_PER_CPU(uint64_t *, taskname_keys); 23static DEFINE_PER_CPU(uint64_t *, taskname_keys);
24static DEFINE_PER_CPU(int, collecting); 24static DEFINE_PER_CPU(int, collecting);
25static DEFINE_PER_CPU(bool, in_scheduler_context);
25 26
26// this array is never read as the cpu wait charts are derived counters 27// this array is never read as the cpu wait charts are derived counters
27// the files are needed, nonetheless, to show that these counters are available 28// the files are needed, nonetheless, to show that these counters are available
@@ -89,7 +90,7 @@ void emit_pid_name(struct task_struct *task)
89 } 90 }
90} 91}
91 92
92static void collect_counters(u64 time) 93static void collect_counters(u64 time, struct task_struct *task)
93{ 94{
94 int *buffer, len, cpu = get_physical_cpu(); 95 int *buffer, len, cpu = get_physical_cpu();
95 long long *buffer64; 96 long long *buffer64;
@@ -104,17 +105,26 @@ static void collect_counters(u64 time)
104 len = gi->read64(&buffer64); 105 len = gi->read64(&buffer64);
105 marshal_event64(len, buffer64); 106 marshal_event64(len, buffer64);
106 } 107 }
108 if (gi->read_proc && task != NULL) {
109 len = gi->read_proc(&buffer64, task);
110 marshal_event64(len, buffer64);
111 }
107 } 112 }
108 // Only check after writing all counters so that time and corresponding counters appear in the same frame 113 // Only check after writing all counters so that time and corresponding counters appear in the same frame
109 buffer_check(cpu, BLOCK_COUNTER_BUF, time); 114 buffer_check(cpu, BLOCK_COUNTER_BUF, time);
110 115
111 // Commit buffers on timeout 116 // Commit buffers on timeout
112 if (gator_live_rate > 0 && time >= per_cpu(gator_buffer_commit_time, cpu)) { 117 if (gator_live_rate > 0 && time >= per_cpu(gator_buffer_commit_time, cpu)) {
113 static const int buftypes[] = { COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF }; 118 static const int buftypes[] = { NAME_BUF, COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF };
119 unsigned long flags;
114 int i; 120 int i;
121
122 local_irq_save(flags);
115 for (i = 0; i < ARRAY_SIZE(buftypes); ++i) { 123 for (i = 0; i < ARRAY_SIZE(buftypes); ++i) {
116 gator_commit_buffer(cpu, buftypes[i], time); 124 gator_commit_buffer(cpu, buftypes[i], time);
117 } 125 }
126 local_irq_restore(flags);
127
118 // Try to preemptively flush the annotate buffer to reduce the chance of the buffer being full 128 // Try to preemptively flush the annotate buffer to reduce the chance of the buffer being full
119 if (on_primary_core() && spin_trylock(&annotate_lock)) { 129 if (on_primary_core() && spin_trylock(&annotate_lock)) {
120 gator_commit_buffer(0, ANNOTATE_BUF, time); 130 gator_commit_buffer(0, ANNOTATE_BUF, time);
@@ -151,6 +161,8 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_
151 int state; 161 int state;
152 int cpu = get_physical_cpu(); 162 int cpu = get_physical_cpu();
153 163
164 per_cpu(in_scheduler_context, cpu) = true;
165
154 // do as much work as possible before disabling interrupts 166 // do as much work as possible before disabling interrupts
155 cookie = get_exec_cookie(cpu, next); 167 cookie = get_exec_cookie(cpu, next);
156 emit_pid_name(next); 168 emit_pid_name(next);
@@ -163,10 +175,12 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_
163 } 175 }
164 176
165 per_cpu(collecting, cpu) = 1; 177 per_cpu(collecting, cpu) = 1;
166 collect_counters(gator_get_time()); 178 collect_counters(gator_get_time(), prev);
167 per_cpu(collecting, cpu) = 0; 179 per_cpu(collecting, cpu) = 0;
168 180
169 marshal_sched_trace_switch(next->tgid, next->pid, cookie, state); 181 marshal_sched_trace_switch(next->tgid, next->pid, cookie, state);
182
183 per_cpu(in_scheduler_context, cpu) = false;
170} 184}
171 185
172GATOR_DEFINE_PROBE(sched_process_free, TP_PROTO(struct task_struct *p)) 186GATOR_DEFINE_PROBE(sched_process_free, TP_PROTO(struct task_struct *p))
diff --git a/driver/mali/mali_mjollnir_profiling_gator_api.h b/driver/mali/mali_mjollnir_profiling_gator_api.h
index 3db4543..347a4fe 100644
--- a/driver/mali/mali_mjollnir_profiling_gator_api.h
+++ b/driver/mali/mali_mjollnir_profiling_gator_api.h
@@ -1,11 +1,10 @@
1/* 1/**
2 * This confidential and proprietary software may be used only as 2 * Copyright (C) ARM Limited 2013. All rights reserved.
3 * authorised by a licensing agreement from ARM Limited 3 *
4 * (C) COPYRIGHT 2013 ARM Limited 4 * This program is free software; you can redistribute it and/or modify
5 * ALL RIGHTS RESERVED 5 * it under the terms of the GNU General Public License version 2 as
6 * The entire notice above must be reproduced on all authorised 6 * published by the Free Software Foundation.
7 * copies and copies may only be made to the extent permitted 7 *
8 * by a licensing agreement from ARM Limited.
9 */ 8 */
10 9
11#ifndef __MALI_MJOLLNIR_PROFILING_GATOR_API_H__ 10#ifndef __MALI_MJOLLNIR_PROFILING_GATOR_API_H__
diff --git a/driver/mali/mali_utgard_profiling_gator_api.h b/driver/mali/mali_utgard_profiling_gator_api.h
index c02a1a4..559647a 100644
--- a/driver/mali/mali_utgard_profiling_gator_api.h
+++ b/driver/mali/mali_utgard_profiling_gator_api.h
@@ -1,11 +1,10 @@
1/* 1/**
2 * This confidential and proprietary software may be used only as 2 * Copyright (C) ARM Limited 2013. All rights reserved.
3 * authorised by a licensing agreement from ARM Limited 3 *
4 * (C) COPYRIGHT 2013 ARM Limited 4 * This program is free software; you can redistribute it and/or modify
5 * ALL RIGHTS RESERVED 5 * it under the terms of the GNU General Public License version 2 as
6 * The entire notice above must be reproduced on all authorised 6 * published by the Free Software Foundation.
7 * copies and copies may only be made to the extent permitted 7 *
8 * by a licensing agreement from ARM Limited.
9 */ 8 */
10 9
11#ifndef __MALI_UTGARD_PROFILING_GATOR_API_H__ 10#ifndef __MALI_UTGARD_PROFILING_GATOR_API_H__
diff --git a/driver/mali_t6xx.mk b/driver/mali_t6xx.mk
index 2cc6411..1a98c1c 100644
--- a/driver/mali_t6xx.mk
+++ b/driver/mali_t6xx.mk
@@ -9,16 +9,17 @@ EXTRA_CFLAGS += -DMALI_USE_UMP=1 \
9 -DMALI_BACKEND_KERNEL=1 \ 9 -DMALI_BACKEND_KERNEL=1 \
10 -DMALI_NO_MALI=0 10 -DMALI_NO_MALI=0
11 11
12KBASE_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase 12DDK_DIR ?= .
13OSK_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase/osk 13KBASE_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase
14UMP_DIR = $(DDK_DIR)/kernel/include/linux 14OSK_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase/osk
15UMP_DIR = $(DDK_DIR)/include/linux
15 16
16# Include directories in the DDK 17# Include directories in the DDK
17EXTRA_CFLAGS += -I$(DDK_DIR) \ 18EXTRA_CFLAGS += -I$(KBASE_DIR)/ \
18 -I$(KBASE_DIR)/.. \ 19 -I$(KBASE_DIR)/.. \
19 -I$(OSK_DIR)/.. \ 20 -I$(OSK_DIR)/.. \
20 -I$(UMP_DIR)/.. \ 21 -I$(UMP_DIR)/.. \
21 -I$(DDK_DIR)/kernel/include \ 22 -I$(DDK_DIR)/include \
22 -I$(KBASE_DIR)/osk/src/linux/include \ 23 -I$(KBASE_DIR)/osk/src/linux/include \
23 -I$(KBASE_DIR)/platform_dummy \ 24 -I$(KBASE_DIR)/platform_dummy \
24 -I$(KBASE_DIR)/src 25 -I$(KBASE_DIR)/src