diff options
author | Jon Medhurst | 2013-12-18 08:45:18 -0600 |
---|---|---|
committer | Jon Medhurst | 2013-12-18 08:45:18 -0600 |
commit | c3fc2b13fd58f1f5db521a062f0bbf782874383c (patch) | |
tree | 76c3c628d80d00aba867dafecbf6fe39813d1500 | |
parent | 6f4705753bf6ede126239aa56eb518dfc4397b11 (diff) | |
download | arm-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>
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 | ||
196 | bool 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 | |||
196 | void Buffer::event (const int32_t key, const int32_t value) { | 207 | void 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 | ||
89 | static void* durationThread(void* pVoid) { | 89 | static 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 | ||
105 | static void* stopThread(void* pVoid) { | 105 | static 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 | ||
142 | void* countersThread(void* pVoid) { | 142 | static 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 | ||
195 | static void* senderThread(void* pVoid) { | 195 | static 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: | |||
39 | private: | 39 | private: |
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 | ||
68 | HwmonCounter::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) { | 72 | HwmonCounter::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 | ||
128 | void OlySocket::createServerSocket(int port) { | 129 | void 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 | ||
141 | int getEventKey() { | 141 | int 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 | ||
22 | struct ImageLinkList { | 22 | struct ImageLinkList { |
@@ -62,6 +62,10 @@ public: | |||
62 | 62 | ||
63 | private: | 63 | private: |
64 | void readCpuInfo(); | 64 | void readCpuInfo(); |
65 | |||
66 | // Intentionally unimplemented | ||
67 | SessionData(const SessionData &); | ||
68 | SessionData &operator=(const SessionData &); | ||
65 | }; | 69 | }; |
66 | 70 | ||
67 | extern SessionData* gSessionData; | 71 | extern 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 |
8 | CFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors | 8 | CFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors |
9 | CXXFLAGS += -fno-rtti | 9 | CXXFLAGS += -fno-rtti -Wextra # -Weffc++ |
10 | ifeq ($(WERROR),1) | 10 | ifeq ($(WERROR),1) |
11 | CFLAGS += -Werror | 11 | CFLAGS += -Werror |
12 | endif | 12 | endif |
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 |
96 | static void child_exit(int signum) { | 96 | static 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 | ||
107 | static int udpPort(int port) { | 107 | static 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 |
389 | int main(int argc, char** argv, char* envp[]) { | 394 | int 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 | ||
6 | obj-m := gator.o | 6 | CONFIG_GATOR ?= m |
7 | obj-$(CONFIG_GATOR) := gator.o | ||
7 | 8 | ||
8 | gator-y := gator_main.o \ | 9 | gator-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 \ | |
16 | gator-y += gator_events_mmaped.o | ||
17 | 17 | ||
18 | # Convert the old GATOR_WITH_MALI_SUPPORT to the new kernel flags | ||
18 | ifneq ($(GATOR_WITH_MALI_SUPPORT),) | 19 | ifneq ($(GATOR_WITH_MALI_SUPPORT),) |
19 | ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_T6xx) | 20 | CONFIG_GATOR_WITH_MALI_SUPPORT := y |
20 | gator-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 |
22 | include $(M)/mali_t6xx.mk | 23 | CONFIG_GATOR_MALI_T6XX := y |
23 | else | 24 | else |
24 | gator-y += gator_events_mali_4xx.o | 25 | CONFIG_GATOR_MALI_4XXMP := y |
25 | endif | 26 | CONFIG_GATOR_MALI_T6XX := n |
26 | gator-y += gator_events_mali_common.o | 27 | endif |
27 | EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT) | 28 | EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT) |
28 | ifneq ($(GATOR_MALI_INTERFACE_STYLE),) | 29 | ifneq ($(GATOR_MALI_INTERFACE_STYLE),) |
29 | EXTRA_CFLAGS += -DGATOR_MALI_INTERFACE_STYLE=$(GATOR_MALI_INTERFACE_STYLE) | 30 | EXTRA_CFLAGS += -DGATOR_MALI_INTERFACE_STYLE=$(GATOR_MALI_INTERFACE_STYLE) |
31 | endif | ||
30 | endif | 32 | endif |
33 | |||
34 | ifeq ($(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 | ||
31 | endif | 49 | endif |
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 | ||
43 | gator-$(CONFIG_ARM64) += gator_events_ccn-504.o | 61 | gator-$(CONFIG_ARM64) += gator_events_ccn-504.o |
44 | 62 | ||
45 | $(obj)/gator_main.o: gator_events.h | ||
46 | |||
47 | clean-files := gator_events.h | ||
48 | |||
49 | chk_events.h = : | ||
50 | quiet_chk_events.h = echo ' CHK $@' | ||
51 | silent_chk_events.h = : | ||
52 | gator_events.h: FORCE | ||
53 | @$($(quiet)chk_events.h) | ||
54 | $(Q)cd $(obj) ; $(CONFIG_SHELL) $(obj)/gator_events.sh $@ | ||
55 | |||
56 | else | 63 | else |
57 | 64 | ||
58 | all: | 65 | all: |
@@ -63,7 +70,7 @@ all: | |||
63 | $(error) | 70 | $(error) |
64 | 71 | ||
65 | clean: | 72 | clean: |
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 | ||
69 | endif | 76 | endif |
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 | |||
123 | int gator_events_install(struct gator_interface *interface); | 119 | int gator_events_install(struct gator_interface *interface); |
124 | int gator_events_get_key(void); | 120 | int gator_events_get_key(void); |
125 | u32 gator_cpuid(void); | 121 | u32 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 | ||
32 | static void marshal_u16(char *buf, u16 val) { | ||
33 | buf[0] = val & 0xff; | ||
34 | buf[1] = (val >> 8) & 0xff; | ||
35 | } | ||
36 | |||
37 | static 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 | |||
32 | void gator_annotate_channel(int channel, const char *str) | 44 | void 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 | ||
49 | void gator_annotate_channel_color(int channel, int color, const char *str) | 65 | void 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 | ||
71 | void gator_annotate_channel_end(int channel) | 87 | void 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 | ||
77 | EXPORT_SYMBOL(gator_annotate_channel_end); | 97 | EXPORT_SYMBOL(gator_annotate_channel_end); |
@@ -85,14 +105,14 @@ EXPORT_SYMBOL(gator_annotate_end); | |||
85 | 105 | ||
86 | void gator_annotate_name_channel(int channel, int group, const char* str) | 106 | void 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 | ||
101 | void gator_annotate_name_group(int group, const char* str) | 121 | void 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 | ||
111 | void gator_annotate_visual(const char *data, unsigned int length, const char *str) | 135 | void 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 | ||
123 | void gator_annotate_marker(void) | 152 | void 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 | ||
129 | EXPORT_SYMBOL(gator_annotate_marker); | 161 | EXPORT_SYMBOL(gator_annotate_marker); |
130 | 162 | ||
131 | void gator_annotate_marker_str(const char *str) | 163 | void 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 | ||
141 | void gator_annotate_marker_color(int color) | 176 | void 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 | ||
147 | EXPORT_SYMBOL(gator_annotate_marker_color); | 186 | EXPORT_SYMBOL(gator_annotate_marker_color); |
148 | 187 | ||
149 | void gator_annotate_marker_color_str(int color, const char *str) | 188 | void 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 | ||
138 | MODULE_PARM_DESC(kernel_stack_unwinding, "Allow kernel stack unwinding."); | ||
139 | bool kernel_stack_unwinding = 0; | ||
140 | module_param(kernel_stack_unwinding, bool, 0644); | ||
141 | #endif | ||
142 | |||
135 | static void kernel_backtrace(int cpu, struct pt_regs *const regs) | 143 | static 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 | ||
14 | static uint32_t *gator_crc32_table; | 15 | static uint32_t *gator_crc32_table; |
@@ -22,7 +23,7 @@ static DEFINE_PER_CPU(int, translate_buffer_read); | |||
22 | static DEFINE_PER_CPU(int, translate_buffer_write); | 23 | static DEFINE_PER_CPU(int, translate_buffer_write); |
23 | static DEFINE_PER_CPU(void **, translate_buffer); | 24 | static DEFINE_PER_CPU(void **, translate_buffer); |
24 | 25 | ||
25 | static inline uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq); | 26 | static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq); |
26 | static void wq_cookie_handler(struct work_struct *unused); | 27 | static void wq_cookie_handler(struct work_struct *unused); |
27 | DECLARE_WORK(cookie_work, wq_cookie_handler); | 28 | DECLARE_WORK(cookie_work, wq_cookie_handler); |
28 | static struct timer_list app_process_wake_up_timer; | 29 | static 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 | ||
110 | static void translate_buffer_write_ptr(int cpu, void *x) | 112 | static 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 | ||
116 | static void *translate_buffer_read_ptr(int cpu) | 119 | static 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 | ||
228 | static inline uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq) | 235 | static 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 | |||
3 | EVENTS=`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 | |||
19 | cmp -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 | ||
237 | gator_events_init(gator_events_armv6_init); | ||
238 | |||
239 | #else | ||
240 | int 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 | ||
312 | gator_events_init(gator_events_armv7_init); | ||
313 | |||
314 | #else | ||
315 | int 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 | |||
155 | gator_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 | |||
94 | STANDARD_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 | |||
49 | MODULE_PARM_DESC(ccn504_addr, "CCN-504 physical base address"); | 99 | MODULE_PARM_DESC(ccn504_addr, "CCN-504 physical base address"); |
50 | static unsigned long ccn504_addr = 0; | 100 | static u64 ccn504_addr = 0; |
51 | module_param(ccn504_addr, ulong, 0444); | 101 | module_param(ccn504_addr, u64, 0444); |
52 | 102 | ||
53 | static void __iomem *gator_events_ccn504_base; | 103 | static void __iomem *gator_events_ccn504_base; |
104 | static bool gator_events_ccn504_global_enabled; | ||
54 | static unsigned long gator_events_ccn504_enabled[CNTMAX]; | 105 | static unsigned long gator_events_ccn504_enabled[CNTMAX]; |
55 | static unsigned long gator_events_ccn504_event[CNTMAX]; | 106 | static unsigned long gator_events_ccn504_event[CNTMAX]; |
56 | static unsigned long gator_events_ccn504_key[CNTMAX]; | 107 | static unsigned long gator_events_ccn504_key[CNTMAX]; |
57 | static int gator_events_ccn504_buffer[2*CNTMAX]; | 108 | static int gator_events_ccn504_buffer[2*CNTMAX]; |
109 | static int gator_events_ccn504_prev[CNTMAX]; | ||
58 | 110 | ||
59 | static void gator_events_ccn504_create_shutdown(void) | 111 | static 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 | |||
237 | static 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 | ||
248 | static struct gator_interface gator_events_ccn504_interface = { | 317 | static 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 | |||
306 | gator_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 | |||
167 | gator_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 | |||
210 | gator_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) | |||
491 | static void mali_counter_deinitialize(void) | 478 | static 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 | |||
751 | gator_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 | ||
31 | extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter) | 31 | extern 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 | */ |
45 | typedef int mali_profiling_set_event_type(unsigned int, int); | 45 | typedef int mali_profiling_set_event_type(unsigned int, int); |
46 | typedef void mali_osk_fb_control_set_type(unsigned int, unsigned int); | ||
47 | typedef void mali_profiling_control_type(unsigned int, unsigned int); | 46 | typedef void mali_profiling_control_type(unsigned int, unsigned int); |
48 | typedef void mali_profiling_get_counters_type(unsigned int *, unsigned int *, unsigned int *, unsigned int *); | 47 | typedef 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 | */ |
53 | extern int _mali_profiling_set_event(unsigned int, int); | 52 | extern int _mali_profiling_set_event(unsigned int, int); |
54 | extern void _mali_osk_fb_control_set(unsigned int, unsigned int); | ||
55 | extern void _mali_profiling_control(unsigned int, unsigned int); | 53 | extern void _mali_profiling_control(unsigned int, unsigned int); |
56 | extern void _mali_profiling_get_counters(unsigned int *, unsigned int *, unsigned int *, unsigned int *); | 54 | extern 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 | */ |
78 | extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter); | 76 | extern 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 | */ |
117 | static mali_counter counters[NUMBER_OF_EVENTS]; | 118 | static mali_counter counters[NUMBER_OF_EVENTS]; |
119 | static 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) | |||
350 | static int start(void) | 361 | static 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 | ||
383 | static void stop(void) | 419 | static 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 | ||
407 | static int read(int **buffer) | 457 | static 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 | |||
512 | gator_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; | |||
63 | static kbase_va_free_type *kbase_va_free_symbol; | 63 | static kbase_va_free_type *kbase_va_free_symbol; |
64 | static kbase_destroy_context_type *kbase_destroy_context_symbol; | 64 | static kbase_destroy_context_type *kbase_destroy_context_symbol; |
65 | 65 | ||
66 | static 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 | |||
758 | gator_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 | 19 | enum { |
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 | |||
26 | enum { | ||
27 | PROC_SIZE, | ||
28 | PROC_SHARE, | ||
29 | PROC_TEXT, | ||
30 | PROC_DATA, | ||
31 | PROC_COUNT, | ||
32 | }; | ||
33 | |||
34 | static const char * const meminfo_names[] = { | ||
35 | "Linux_meminfo_memfree", | ||
36 | "Linux_meminfo_memused", | ||
37 | "Linux_meminfo_bufferram", | ||
38 | }; | ||
39 | |||
40 | static 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 | ||
20 | static ulong meminfo_global_enabled; | 47 | static bool meminfo_global_enabled; |
21 | static ulong meminfo_enabled[MEMINFO_TOTAL]; | 48 | static ulong meminfo_enabled[MEMINFO_TOTAL]; |
22 | static ulong meminfo_key[MEMINFO_TOTAL]; | 49 | static ulong meminfo_keys[MEMINFO_TOTAL]; |
23 | static unsigned long long meminfo_buffer[MEMINFO_TOTAL * 2]; | 50 | static long long meminfo_buffer[2 * (MEMINFO_TOTAL + 2)]; |
24 | static int meminfo_length = 0; | 51 | static int meminfo_length = 0; |
25 | static unsigned int mem_event = 0; | ||
26 | static bool new_data_avail; | 52 | static bool new_data_avail; |
27 | 53 | ||
28 | static void wq_sched_handler(struct work_struct *wsptr); | 54 | static bool proc_global_enabled; |
29 | DECLARE_WORK(work, wq_sched_handler); | 55 | static ulong proc_enabled[PROC_COUNT]; |
30 | static struct timer_list meminfo_wake_up_timer; | 56 | static ulong proc_keys[PROC_COUNT]; |
31 | static void meminfo_wake_up_handler(unsigned long unused_data); | 57 | static DEFINE_PER_CPU(long long, proc_buffer[2 * (PROC_COUNT + 3)]); |
58 | |||
59 | static int gator_meminfo_func(void *data); | ||
60 | static bool gator_meminfo_run; | ||
61 | // Initialize semaphore unlocked to initialize memory values | ||
62 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) | ||
63 | static DECLARE_MUTEX(gator_meminfo_sem); | ||
64 | #else | ||
65 | static 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) |
34 | GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order)) | 69 | GATOR_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 | |||
36 | GATOR_DEFINE_PROBE(mm_page_free, TP_PROTO(struct page *page, unsigned int order)) | 71 | GATOR_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)) | |||
45 | GATOR_DEFINE_PROBE(mm_page_free_batched, TP_PROTO(struct page *page, int cold)) | 80 | GATOR_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 | ||
51 | GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype)) | 86 | GATOR_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 | ||
56 | static int gator_events_meminfo_create_files(struct super_block *sb, struct dentry *root) | 91 | static 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 | ||
167 | kthread_run_exit: | ||
168 | GATOR_UNREGISTER_TRACE(mm_page_alloc); | ||
117 | mm_page_alloc_exit: | 169 | mm_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 | ||
133 | static void gator_events_meminfo_stop(void) | 185 | static 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 |
157 | static void wq_sched_handler(struct work_struct *wsptr) | 204 | static 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 | ||
191 | static 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 | ||
197 | static int gator_events_meminfo_read(long long **buffer) | 261 | static 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 | ||
277 | static 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 | |||
220 | static struct gator_interface gator_events_meminfo_interface = { | 362 | static 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 | ||
227 | int gator_events_meminfo_init(void) | 370 | int 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 | |||
240 | gator_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 | |||
36 | static int mmapped_global_enabled; | ||
29 | 37 | ||
30 | static struct { | 38 | static 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 | ||
36 | static int mmaped_buffer[MMAPED_COUNTERS_NUM * 2]; | 44 | static int mmapped_buffer[MMAPPED_COUNTERS_NUM * 2]; |
37 | 45 | ||
38 | #ifdef TODO | ||
39 | static void __iomem *mmaped_base; | ||
40 | #endif | ||
41 | |||
42 | #ifndef TODO | ||
43 | static s64 prev_time; | 46 | static 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 */ |
47 | static int gator_events_mmaped_create_files(struct super_block *sb, | 49 | static 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 | ||
71 | static int gator_events_mmaped_start(void) | 73 | static 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 | ||
90 | static void gator_events_mmaped_stop(void) | 92 | static 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... */ |
100 | static int mmaped_simulate(int counter, int delta_in_us) | 98 | static 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 | ||
162 | static int gator_events_mmaped_read(int **buffer) | 159 | static 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 | ||
203 | static struct gator_interface gator_events_mmaped_interface = { | 191 | static 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! */ |
211 | int __init gator_events_mmaped_init(void) | 199 | int __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 | |||
229 | gator_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 | ||
74 | static int gator_events_net_create_files(struct super_block *sb, struct dentry *root) | 74 | static 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 | |||
171 | gator_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 | |||
16 | extern bool event_based_sampling; | 21 | extern 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 |
26 | struct gator_attr { | 34 | struct 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 | |||
417 | static const struct of_device_id arm_cci_matches[] = { | ||
418 | {.compatible = "arm,cci-400" }, | ||
419 | {}, | ||
420 | }; | ||
421 | |||
422 | static 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 | |||
459 | static int probe_cci_revision(void) | ||
460 | { | ||
461 | return DEFAULT_CCI_REVISION; | ||
462 | } | ||
463 | |||
464 | #endif | ||
465 | |||
407 | static void gator_events_perf_pmu_cci_init(const int type) | 466 | static 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 | ||
515 | gator_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 | |||
115 | gator_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 | ||
669 | gator_events_init(gator_events_scorpion_init); | ||
670 | |||
671 | #else | ||
672 | int 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 |
11 | static unsigned long gator_protocol_version = 16; | 11 | #define PROTOCOL_VERSION 17 |
12 | static 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 | ||
139 | static unsigned long gator_started; | 143 | static unsigned long gator_started; |
140 | static u64 gator_monotonic_started; | 144 | static u64 gator_monotonic_started; |
145 | static u64 gator_hibernate_time; | ||
141 | static unsigned long gator_buffer_opened; | 146 | static unsigned long gator_buffer_opened; |
142 | static unsigned long gator_timer_count; | 147 | static unsigned long gator_timer_count; |
143 | static unsigned long gator_response_type; | 148 | static unsigned long gator_response_type; |
@@ -149,6 +154,8 @@ bool event_based_sampling; | |||
149 | static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait); | 154 | static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait); |
150 | static DECLARE_WAIT_QUEUE_HEAD(gator_annotate_wait); | 155 | static DECLARE_WAIT_QUEUE_HEAD(gator_annotate_wait); |
151 | static struct timer_list gator_buffer_wake_up_timer; | 156 | static struct timer_list gator_buffer_wake_up_timer; |
157 | static bool gator_buffer_wake_stop; | ||
158 | static struct task_struct *gator_buffer_wake_thread; | ||
152 | static LIST_HEAD(gator_events); | 159 | static LIST_HEAD(gator_events); |
153 | 160 | ||
154 | static DEFINE_PER_CPU(u64, last_timestamp); | 161 | static 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 |
192 | static DEFINE_PER_CPU(u64, gator_buffer_commit_time); | 199 | static 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); | ||
220 | GATOR_EVENTS_LIST | ||
221 | #undef GATOR_EVENT | ||
222 | |||
223 | static int (*gator_events_list[])(void) = { | ||
224 | #define GATOR_EVENT(EVENT_INIT) EVENT_INIT, | ||
225 | GATOR_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 | ||
432 | static 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 | ||
525 | static void buffer_check(int cpu, int buftype, u64 time) | 582 | static 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 | ||
599 | static int gator_running; | 661 | static int gator_running; |
@@ -817,6 +879,7 @@ static struct notifier_block __refdata gator_hotcpu_notifier = { | |||
817 | static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy) | 879 | static 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 | ||
905 | int gator_events_get_key(void) | 979 | int 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: | |||
1013 | events_failure: | 1094 | events_failure: |
1014 | gator_migrate_stop(); | 1095 | gator_migrate_stop(); |
1015 | migrate_failure: | 1096 | migrate_failure: |
1097 | gator_buffer_wake_stop = true; | ||
1098 | wake_up_process(gator_buffer_wake_thread); | ||
1099 | bwake_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); | |||
1440 | MODULE_LICENSE("GPL"); | 1527 | MODULE_LICENSE("GPL"); |
1441 | MODULE_AUTHOR("ARM Ltd"); | 1528 | MODULE_AUTHOR("ARM Ltd"); |
1442 | MODULE_DESCRIPTION("Gator system profiler"); | 1529 | MODULE_DESCRIPTION("Gator system profiler"); |
1530 | #define STRIFY2(ARG) #ARG | ||
1531 | #define STRIFY(ARG) STRIFY2(ARG) | ||
1532 | MODULE_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 | ||
92 | static 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 | |||
92 | static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel, u64 time) | 111 | static 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 | ||
23 | static DEFINE_PER_CPU(uint64_t *, taskname_keys); | 23 | static DEFINE_PER_CPU(uint64_t *, taskname_keys); |
24 | static DEFINE_PER_CPU(int, collecting); | 24 | static DEFINE_PER_CPU(int, collecting); |
25 | static 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 | ||
92 | static void collect_counters(u64 time) | 93 | static 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 | ||
172 | GATOR_DEFINE_PROBE(sched_process_free, TP_PROTO(struct task_struct *p)) | 186 | GATOR_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 | ||
12 | KBASE_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase | 12 | DDK_DIR ?= . |
13 | OSK_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase/osk | 13 | KBASE_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase |
14 | UMP_DIR = $(DDK_DIR)/kernel/include/linux | 14 | OSK_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase/osk |
15 | UMP_DIR = $(DDK_DIR)/include/linux | ||
15 | 16 | ||
16 | # Include directories in the DDK | 17 | # Include directories in the DDK |
17 | EXTRA_CFLAGS += -I$(DDK_DIR) \ | 18 | EXTRA_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 |