gator: Version 5.17
authorJon Medhurst <tixy@linaro.org>
Wed, 18 Dec 2013 14:45:18 +0000 (14:45 +0000)
committerJon Medhurst <tixy@linaro.org>
Wed, 18 Dec 2013 14:45:18 +0000 (14:45 +0000)
Signed-off-by: Jon Medhurst <tixy@linaro.org>
51 files changed:
daemon/Buffer.cpp
daemon/Buffer.h
daemon/Child.cpp
daemon/Child.h
daemon/ConfigurationXML.h
daemon/Driver.h
daemon/Fifo.h
daemon/Hwmon.cpp
daemon/Hwmon.h
daemon/OlySocket.cpp
daemon/Sender.h
daemon/SessionData.cpp
daemon/SessionData.h
daemon/SessionXML.h
daemon/StreamlineSetup.h
daemon/common.mk
daemon/events-CCI-400.xml
daemon/events-Linux.xml
daemon/events-Mali-T6xx.xml
daemon/events-Mali-T6xx_hw.xml
daemon/main.cpp
driver/Makefile
driver/gator.h
driver/gator_annotate_kernel.c
driver/gator_backtrace.c
driver/gator_cookies.c
driver/gator_events.sh [deleted file]
driver/gator_events_armv6.c
driver/gator_events_armv7.c
driver/gator_events_block.c
driver/gator_events_ccn-504.c
driver/gator_events_irq.c
driver/gator_events_l2c-310.c
driver/gator_events_mali_4xx.c
driver/gator_events_mali_common.c
driver/gator_events_mali_common.h
driver/gator_events_mali_t6xx.c
driver/gator_events_mali_t6xx_hw.c
driver/gator_events_meminfo.c
driver/gator_events_mmapped.c [moved from driver/gator_events_mmaped.c with 56% similarity]
driver/gator_events_net.c
driver/gator_events_perf_pmu.c
driver/gator_events_sched.c
driver/gator_events_scorpion.c
driver/gator_main.c
driver/gator_marshaling.c
driver/gator_trace_gpu.c
driver/gator_trace_sched.c
driver/mali/mali_mjollnir_profiling_gator_api.h
driver/mali/mali_utgard_profiling_gator_api.h
driver/mali_t6xx.mk

index c7abbf3a18208034a1d47c4191edccac2fd0501f..090a71553277b6ab74073552c106a627688b2588 100644 (file)
@@ -193,6 +193,17 @@ bool Buffer::eventHeader (const uint64_t curr_time) {
        return retval;
 }
 
+bool Buffer::eventTid (const int tid) {
+       bool retval = false;
+       if (checkSpace(2*MAXSIZE_PACK32)) {
+               packInt(1);     // key of 1 indicates a tid
+               packInt(tid);
+               retval = true;
+       }
+
+       return retval;
+}
+
 void Buffer::event (const int32_t key, const int32_t value) {
        if (checkSpace(2 * MAXSIZE_PACK32)) {
                packInt(key);
index f820cfd851e32399a4108511bf0b81180a17ada0..b3c8d78cf758af6cffbacd0a8e5e43bee2e4c5b2 100644 (file)
@@ -32,6 +32,7 @@ public:
        void frame ();
 
        bool eventHeader (uint64_t curr_time);
+       bool eventTid (int tid);
        void event (int32_t key, int32_t value);
        void event64 (int64_t key, int64_t value);
 
@@ -56,6 +57,10 @@ private:
        char *const buf;
        uint64_t commitTime;
        sem_t *const readerSem;
+
+       // Intentionally unimplemented
+       Buffer(const Buffer &);
+       Buffer &operator=(const Buffer &);
 };
 
 #endif // BUFFER_H
index c0540762698fc3c87eaa7fc2443eb39a3ad16600..9ee2ef8afb9d582225cb0823151758138e9b119c 100644 (file)
@@ -86,7 +86,7 @@ static void child_handler(int signum) {
        }
 }
 
-static void* durationThread(void* pVoid) {
+static void *durationThread(void *) {
        prctl(PR_SET_NAME, (unsigned long)&"gatord-duration", 0, 0, 0);
        sem_wait(&startProfile);
        if (gSessionData->mSessionIsActive) {
@@ -102,7 +102,7 @@ static void* durationThread(void* pVoid) {
        return 0;
 }
 
-static void* stopThread(void* pVoid) {
+static void *stopThread(void *) {
        OlySocket* socket = child->socket;
 
        prctl(PR_SET_NAME, (unsigned long)&"gatord-stopper", 0, 0, 0);
@@ -139,7 +139,7 @@ static void* stopThread(void* pVoid) {
        return 0;
 }
 
-void* countersThread(void* pVoid) {
+static void *countersThread(void *) {
        prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0);
 
        gSessionData->hwmon.start();
@@ -192,7 +192,7 @@ void* countersThread(void* pVoid) {
        return NULL;
 }
 
-static void* senderThread(void* pVoid) {
+static void *senderThread(void *) {
        int length = 1;
        char* data;
        char end_sequence[] = {RESPONSE_APC_DATA, 0, 0, 0, 0};
@@ -340,7 +340,8 @@ void Child::run() {
                thread_creation_success = false;
        }
 
-       if (gSessionData->hwmon.countersEnabled()) {
+       bool startcountersThread = gSessionData->hwmon.countersEnabled();
+       if (startcountersThread) {
                if (pthread_create(&countersThreadID, NULL, countersThread, this)) {
                        thread_creation_success = false;
                }
@@ -378,7 +379,7 @@ void Child::run() {
        } while (bytesCollected > 0);
        logg->logMessage("Exit collect data loop");
 
-       if (gSessionData->hwmon.countersEnabled()) {
+       if (startcountersThread) {
                pthread_join(countersThreadID, NULL);
        }
 
index e39d18276407b4498e2dfe3309a8ae8955bc7739..0330e9d780276c1228e95c3eabcae708dedb8390 100644 (file)
@@ -26,6 +26,10 @@ private:
        int mNumConnections;
 
        void initialization();
+
+       // Intentionally unimplemented
+       Child(const Child &);
+       Child &operator=(const Child &);
 };
 
 #endif         //__CHILD_H__
index eba7dc4bac460eb7674603ab2b0c120c6f28299b..5650f487b990a45f16e047bc16c0ca573bc4986f 100644 (file)
@@ -29,6 +29,10 @@ private:
        int parse(const char* xmlFile);
        int configurationsTag(mxml_node_t *node);
        void configurationTag(mxml_node_t *node);
+
+       // Intentionally unimplemented
+       ConfigurationXML(const ConfigurationXML &);
+       ConfigurationXML &operator=(const ConfigurationXML &);
 };
 
 #endif // COUNTERS_H
index dd1dc27d1cdbde0b7d90424a22febdf5104e9b22..f3a932f852cb089a9cb970a8b5a10fdf6e21da5c 100644 (file)
@@ -29,7 +29,7 @@ public:
        // Emits available counters
        virtual void writeCounters(mxml_node_t *root) const = 0;
        // Emits possible dynamically generated events/counters
-       virtual void writeEvents(mxml_node_t *root) const {}
+       virtual void writeEvents(mxml_node_t *) const {}
 
        Driver *getNext() const { return next; }
 
@@ -39,6 +39,10 @@ protected:
 private:
        static Driver *head;
        Driver *next;
+
+       // Intentionally unimplemented
+       Driver(const Driver &);
+       Driver &operator=(const Driver &);
 };
 
 #endif // DRIVER_H
index ada42b9fb5848f37eabdf34b66e0710cbc3f77f7..d25cd68825614a621eab87089fb877669d9ef7d3 100644 (file)
@@ -39,6 +39,10 @@ private:
   sem_t* mReaderSem;
   char*        mBuffer;
   bool mEnd;
+
+  // Intentionally unimplemented
+  Fifo(const Fifo &);
+  Fifo &operator=(const Fifo &);
 };
 
 #endif         //__FIFO_H__
index 07925680c1f67f81e886c1426500514777f79f78..1d7c0da9cc83673eb1beba18c72518f7f9e43380 100644 (file)
@@ -63,6 +63,10 @@ private:
        double previous_value;
 
        sensors_subfeature_type input;
+
+       // Intentionally unimplemented
+       HwmonCounter(const HwmonCounter &);
+       HwmonCounter &operator=(const HwmonCounter &);
 };
 
 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) {
index 35981dc3d9ad47d66fb4fa1c9649c84e08e4890d..46bb42e898d7dee083cfe2e4f36823446de47470 100644 (file)
@@ -34,6 +34,10 @@ private:
        HwmonCounter *findCounter(const Counter &counter) const;
 
        HwmonCounter *counters;
+
+       // Intentionally unimplemented
+       Hwmon(const Hwmon &);
+       Hwmon &operator=(const Hwmon &);
 };
 
 #endif // HWMON_H
index 132510df584a05228caaab33b8fad4ce8533e4c1..ab5c3c2c89383d5b26ab916c2508134bd34629f7 100644 (file)
@@ -11,6 +11,7 @@
 #include <stdio.h>
 #ifdef WIN32
 #include <Winsock2.h>
+#include <ws2tcpip.h>
 #else
 #include <netinet/in.h>
 #include <sys/socket.h>
@@ -126,11 +127,17 @@ void OlySocket::createSingleServerConnection(int port) {
 }
 
 void OlySocket::createServerSocket(int port) {
+  int family = AF_INET6;
+
   // Create socket
-  mFDServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+  mFDServer = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
   if (mFDServer < 0) {
-    logg->logError(__FILE__, __LINE__, "Error creating server socket");
-    handleException();
+    family = AF_INET;
+    mFDServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (mFDServer < 0) {
+      logg->logError(__FILE__, __LINE__, "Error creating server socket");
+      handleException();
+    }
   }
 
   // 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) {
   }
 
   // Create sockaddr_in structure, ensuring non-populated fields are zero
-  struct sockaddr_in sockaddr;
-  memset((void*)&sockaddr, 0, sizeof(struct sockaddr_in));
-  sockaddr.sin_family = AF_INET;
-  sockaddr.sin_port   = htons(port);
-  sockaddr.sin_addr.s_addr = INADDR_ANY;
+  struct sockaddr_in6 sockaddr;
+  memset((void*)&sockaddr, 0, sizeof(sockaddr));
+  sockaddr.sin6_family = family;
+  sockaddr.sin6_port = htons(port);
+  sockaddr.sin6_addr = in6addr_any;
 
   // Bind the socket to an address
   if (bind(mFDServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
index 8f23361a5def4bbbde40a2d05ec306c5c65a23b5..b388f039bad7d33ff89e04fdf6213f55216f23dc 100644 (file)
@@ -33,6 +33,10 @@ private:
        FILE* mDataFile;
        char* mDataFileName;
        pthread_mutex_t mSendMutex;
+
+       // Intentionally unimplemented
+       Sender(const Sender &);
+       Sender &operator=(const Sender &);
 };
 
 #endif         //__SENDER_H__
index 4068d4e957f08b2fb2b4638acb4ac012cf0f91e3..cf844075401f919448e9a3e70b3a568fc3c9bb05 100644 (file)
@@ -44,13 +44,13 @@ void SessionData::parseSessionXML(char* xmlString) {
        SessionXML session(xmlString);
        session.parse();
 
-       // Set session data values
+       // Set session data values - use prime numbers just below the desired value to reduce the chance of events firing at the same time
        if (strcmp(session.parameters.sample_rate, "high") == 0) {
-               mSampleRate = 10000;
+               mSampleRate = 9973; // 10000
        } else if (strcmp(session.parameters.sample_rate, "normal") == 0) {
-               mSampleRate = 1000;
+               mSampleRate = 997; // 1000
        } else if (strcmp(session.parameters.sample_rate, "low") == 0) {
-               mSampleRate = 100;
+               mSampleRate = 97; // 100
        } else if (strcmp(session.parameters.sample_rate, "none") == 0) {
                mSampleRate = 0;
        } else {
@@ -139,7 +139,9 @@ void SessionData::readCpuInfo() {
  }
 
 int getEventKey() {
-       // Start one after the gator.ko's value of 1
+       // key 0 is reserved as a timestamp
+       // key 1 is reserved as the marker for thread specific counters
+       // Odd keys are assigned by the driver, even keys by the daemon
        static int key = 2;
 
        const int ret = key;
index e72fa5d7c5ed764dd6151baa8f23215855cb29a9..c834251527cf22334e3a06f2346c20d9f97fbd09 100644 (file)
@@ -16,7 +16,7 @@
 
 #define MAX_PERFORMANCE_COUNTERS       50
 
-#define PROTOCOL_VERSION       16
+#define PROTOCOL_VERSION       17
 #define PROTOCOL_DEV           1000    // Differentiates development versions (timestamp) from release versions
 
 struct ImageLinkList {
@@ -62,6 +62,10 @@ public:
 
 private:
        void readCpuInfo();
+
+       // Intentionally unimplemented
+       SessionData(const SessionData &);
+       SessionData &operator=(const SessionData &);
 };
 
 extern SessionData* gSessionData;
index c7e3798d69504c1b91e03c9c9c550229f3ee434b..0fb03bd6627c75bd8344a308666cfc057e55cf7d 100644 (file)
@@ -33,6 +33,10 @@ private:
        char*  mPath;
        void sessionTag(mxml_node_t *tree, mxml_node_t *node);
        void sessionImage(mxml_node_t *node);
+
+       // Intentionally unimplemented
+       SessionXML(const SessionXML &);
+       SessionXML &operator=(const SessionXML &);
 };
 
 #endif // SESSION_XML_H
index 092d956ec99fb2882abc24bd6947f72571f097ed..d6d9a6ea29919db845ec5c4777c56b28698adda1 100644 (file)
@@ -38,6 +38,10 @@ private:
        void sendDefaults();
        void sendCounters();
        void writeConfiguration(char* xml);
+
+       // Intentionally unimplemented
+       StreamlineSetup(const StreamlineSetup &);
+       StreamlineSetup &operator=(const StreamlineSetup &);
 };
 
 #endif         //__STREAMLINE_SETUP_H__
index ee2415b8825c1a37acd9892cb0f2092d1bb69d0d..031d169068817e3182ec3c3dd5e16487bb7da16f 100644 (file)
@@ -6,7 +6,7 @@
 # -std=c++0x is the planned new c++ standard
 # -std=c++98 is the 1998 c++ standard
 CFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors
-CXXFLAGS += -fno-rtti
+CXXFLAGS += -fno-rtti -Wextra # -Weffc++
 ifeq ($(WERROR),1)
        CFLAGS += -Werror
 endif
index 86db2087e1f551588822c9fdd0f10e3baebfb9c9..4fa77117d2d89e37de41a0e11c1d259133df4e3b 100644 (file)
@@ -17,7 +17,7 @@
     <event event="0x04" option_set="Slave" title="CCI-400" name="Read: cache" description="Read request handshake: cache maintenance operation, CleanInvalid, CleanShared, MakeInvalid"/>
     <event event="0x05" option_set="Slave" title="CCI-400" name="Read: memory barrier" description="Read request handshake: memory barrier"/>
     <event event="0x06" option_set="Slave" title="CCI-400" name="Read: sync barrier" description="Read request handshake: synchronization barrier"/>
-    <event event="0x07" option_set="Slave" title="CCI-400" name="Read: DVM message, no sync" description="Read request handshake: DVM message, no synchronization"/>
+    <event event="0x07" option_set="Slave" title="CCI-400" name="Read: DVM message, no sync" description="Read request handshake: DVM message, not synchronization"/>
     <event event="0x08" option_set="Slave" title="CCI-400" name="Read: DVM message, sync" description="Read request handshake: DVM message, synchronization"/>
     <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"/>
     <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"/>
     <event event="0x19" option_set="Master" title="CCI-400" name="Write stall: barrier hazard" description="Write request stall cycle because of a barrier hazard"/>
     <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"/>
   </category>
+
+  <counter_set name="cci-400-r1_cnt" count="4"/>
+  <category name="CCI-400" counter_set="cci-400-r1_cnt" per_cpu="no" supports_event_based_sampling="yes">
+    <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"/>
+
+    <option_set name="Slave">
+      <option event_delta="0x00" name="S0" description="Slave interface 0"/>
+      <option event_delta="0x20" name="S1" description="Slave interface 1"/>
+      <option event_delta="0x40" name="S2" description="Slave interface 2"/>
+      <option event_delta="0x60" name="S3" description="Slave interface 3"/>
+      <option event_delta="0x80" name="S4" description="Slave interface 4"/>
+    </option_set>
+
+    <event event="0x00" option_set="Slave" title="CCI-400" name="Read: any" description="Read request handshake: any"/>
+    <event event="0x01" option_set="Slave" title="CCI-400" name="Read: transaction" description="Read request handshake: device transaction"/>
+    <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"/>
+    <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"/>
+    <event event="0x04" option_set="Slave" title="CCI-400" name="Read: cache" description="Read request handshake: cache maintenance operation"/>
+    <event event="0x05" option_set="Slave" title="CCI-400" name="Read: memory barrier" description="Read request handshake: memory barrier"/>
+    <event event="0x06" option_set="Slave" title="CCI-400" name="Read: sync barrier" description="Read request handshake: synchronization barrier"/>
+    <event event="0x07" option_set="Slave" title="CCI-400" name="Read: DVM message, no sync" description="Read request handshake: DVM message, not synchronization"/>
+    <event event="0x08" option_set="Slave" title="CCI-400" name="Read: DVM message, sync" description="Read request handshake: DVM message, synchronization"/>
+    <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"/>
+    <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"/>
+    <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"/>
+    <event event="0x0c" option_set="Slave" title="CCI-400" name="Write: any" description="Write request handshake: any"/>
+    <event event="0x0d" option_set="Slave" title="CCI-400" name="Write: transaction" description="Write request handshake: device transaction"/>
+    <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"/>
+    <event event="0x0f" option_set="Slave" title="CCI-400" name="Write: shareable" description="Write request handshake: inner- or outer-shareable, WriteBack or WriteClean"/>
+    <event event="0x10" option_set="Slave" title="CCI-400" name="Write: WriteUnique" description="Write request handshake: WriteUnique"/>
+    <event event="0x11" option_set="Slave" title="CCI-400" name="Write: WriteLineUnique" description="Write request handshake: WriteLineUnique"/>
+    <event event="0x12" option_set="Slave" title="CCI-400" name="Write: Evict" description="Write request handshake: Evict"/>
+    <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"/>
+    <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"/>
+
+    <option_set name="Master">
+      <option event_delta="0xa0" name="M0" description="Master interface 0"/>
+      <option event_delta="0xc0" name="M1" description="Master interface 1"/>
+      <option event_delta="0xe0" name="M2" description="Master interface 2"/>
+    </option_set>
+
+    <event event="0x00" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/>
+    <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"/>
+    <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"/>
+    <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"/>
+    <event event="0x04" option_set="Master" title="CCI-400" name="Read stall: barrier hazard" description="Read request stall cycle because of a barrier hazard"/>
+    <event event="0x05" option_set="Master" title="CCI-400" name="Write stall: barrier hazard" description="Write request stall cycle because of a barrier hazard"/>
+    <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"/>
+    <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"/>
+    <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"/>
+    <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"/>
+    <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"/>
+    <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"/>
+    <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"/>
+    <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"/>
+    <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"/>
+    <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"/>
+    <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"/>
+    <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"/>
+  </category>
index 4a30ad6ec4e61da011f73b6a6a99cf477c0a38e2..31a90a1d6335e16a08bf3e37dbe2c836db3f3bfa 100644 (file)
@@ -6,11 +6,11 @@
     <event counter="Linux_net_rx" title="Network" name="Receive" units="B" description="Receive network traffic, including effect from Streamline"/>
     <event counter="Linux_net_tx" title="Network" name="Transmit" units="B" description="Transmit network traffic, including effect from Streamline"/>
     <event counter="Linux_sched_switch" title="Scheduler" name="Switch" per_cpu="yes" description="Context switch events"/>
-    <event counter="Linux_meminfo_memused" title="Memory" name="Used" display="maximum" units="B" average_selection="yes" description="Total used memory size"/>
-    <event counter="Linux_meminfo_memfree" title="Memory" name="Free" display="minimum" units="B" average_selection="yes" description="Available memory size"/>
-    <event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" display="maximum" units="B" average_selection="yes" description="Memory used by OS disk buffers"/>
-    <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"/>
-    <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"/>
+    <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."/>
+    <event counter="Linux_meminfo_memfree" title="Memory" name="Free" display="minimum" units="B" description="Available memory size"/>
+    <event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" display="maximum" units="B" description="Memory used by OS disk buffers"/>
+    <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"/>
+    <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"/>
     <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"/>
     <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"/>
   </category>
index 647e3d5b0fcf874e74c8e2b458ae71626952612c..2465238a8bda8eeff71ba566d7932230af15cd77 100644 (file)
     <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."/>
     <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."/>
   </category>
+
+  <counter_set name="ARM_Mali-T6xx_Filmstrip_cnt" count="1"/>
+  <category name="ARM Mali-T6xx Filmstrip" counter_set="ARM_Mali-T6xx_Filmstrip_cnt" per_cpu="no">
+    <option_set name="fs">
+      <option event_delta="0x3c" name="1:60" description="captures every 60th frame"/>
+      <option event_delta="0x1e" name="1:30" description="captures every 30th frame"/>
+      <option event_delta="0xa" name="1:10" description="captures every 10th frame"/>
+    </option_set>
+    <event event="0x0400" option_set="fs" title="ARM Mali-T6xx" name="Filmstrip" description="Scaled framebuffer"/>
+  </category>
index 8cfe7c3084d5ca23f09697fed5d1b0bf6ae50d07..03566cbb06abb5f9101bf80fdab4d6927b5ad893 100644 (file)
 
     <event counter="ARM_Mali-T6xx_FRAG_THREADS" title="Mali Core Threads" name="Fragment threads" description="Number of fragment threads started"/>
     <event counter="ARM_Mali-T6xx_FRAG_DUMMY_THREADS" title="Mali Core Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
-    <event counter="ARM_Mali-T6xx_COMPUTE_THREADS" title="Mali Core Threads" name="Compute threads" description="Number of vertex\compute threads started"/>
     <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"/>
     <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"/>
     <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"/>
     <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"/>
 
+    <event counter="ARM_Mali-T6xx_COMPUTE_TASKS" title="Mali Compute Threads" name="Compute tasks" description="Number of compute tasks"/>
+    <event counter="ARM_Mali-T6xx_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads started" description="Number of compute threads started"/>
+    <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"/>
+
     <event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
     <event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
     <event counter="ARM_Mali-T6xx_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
index d1b0913aa78f6c863bfda98c7f81ee54d595582f..bfd36b98766c63319b76702d0845d75cc2a92c87 100644 (file)
@@ -93,7 +93,7 @@ static void handler(int signum) {
 }
 
 // Child exit Signal Handler
-static void child_exit(int signum) {
+static void child_exit(int) {
        int status;
        int pid = wait(&status);
        if (pid != -1) {
@@ -106,13 +106,18 @@ static void child_exit(int signum) {
 
 static int udpPort(int port) {
        int s;
-       struct sockaddr_in sockaddr;
+       struct sockaddr_in6 sockaddr;
        int on;
+       int family = AF_INET6;
 
-       s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
        if (s == -1) {
-               logg->logError(__FILE__, __LINE__, "socket failed");
-               handleException();
+               family = AF_INET;
+               s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+               if (s == -1) {
+                       logg->logError(__FILE__, __LINE__, "socket failed");
+                       handleException();
+               }
        }
 
        on = 1;
@@ -122,9 +127,9 @@ static int udpPort(int port) {
        }
 
        memset((void*)&sockaddr, 0, sizeof(sockaddr));
-       sockaddr.sin_family = AF_INET;
-       sockaddr.sin_port = htons(port);
-       sockaddr.sin_addr.s_addr = INADDR_ANY;
+       sockaddr.sin6_family = family;
+       sockaddr.sin6_port = htons(port);
+       sockaddr.sin6_addr = in6addr_any;
        if (bind(s, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) {
                logg->logError(__FILE__, __LINE__, "socket failed");
                handleException();
@@ -173,7 +178,7 @@ static void* answerThread(void* pVoid) {
 
        for (;;) {
                char buf[128];
-               struct sockaddr_in sockaddr;
+               struct sockaddr_in6 sockaddr;
                socklen_t addrlen;
                int read;
                addrlen = sizeof(sockaddr);
@@ -386,7 +391,7 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
 }
 
 // Gator data flow: collector -> collector fifo -> sender
-int main(int argc, char** argv, char* envp[]) {
+int main(int argc, char** argv) {
        // Ensure proper signal handling by making gatord the process group leader
        //   e.g. it may not be the group leader when launched as 'sudo gatord'
        setsid();
index 0d4ca68701e0a40b3e5fd8371e442ca67d39171c..3dc9d059a4b409c30c193b87fd38cb4774e25953 100644 (file)
@@ -3,7 +3,8 @@ ifneq ($(KERNELRELEASE),)
 # Uncomment the following line to enable kernel stack unwinding within gator, or update gator_backtrace.c
 # EXTRA_CFLAGS +=      -DGATOR_KERNEL_STACK_UNWINDING
 
-obj-m := gator.o
+CONFIG_GATOR ?= m
+obj-$(CONFIG_GATOR) := gator.o
 
 gator-y :=     gator_main.o \
                gator_events_irq.o \
@@ -11,23 +12,40 @@ gator-y :=  gator_main.o \
                gator_events_net.o \
                gator_events_block.o \
                gator_events_meminfo.o \
-               gator_events_perf_pmu.o
-
-gator-y +=     gator_events_mmaped.o
+               gator_events_perf_pmu.o \
+               gator_events_mmapped.o \
 
+# Convert the old GATOR_WITH_MALI_SUPPORT to the new kernel flags
 ifneq ($(GATOR_WITH_MALI_SUPPORT),)
-ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_T6xx)
-gator-y +=     gator_events_mali_t6xx.o \
-               gator_events_mali_t6xx_hw.o
-include $(M)/mali_t6xx.mk
-else
-gator-y +=     gator_events_mali_4xx.o
-endif
-gator-y +=     gator_events_mali_common.o
-EXTRA_CFLAGS +=        -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT)
-ifneq ($(GATOR_MALI_INTERFACE_STYLE),)
-EXTRA_CFLAGS += -DGATOR_MALI_INTERFACE_STYLE=$(GATOR_MALI_INTERFACE_STYLE)
+  CONFIG_GATOR_WITH_MALI_SUPPORT := y
+  ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_T6xx)
+    CONFIG_GATOR_MALI_4XXMP := n
+    CONFIG_GATOR_MALI_T6XX := y
+  else
+    CONFIG_GATOR_MALI_4XXMP := y
+    CONFIG_GATOR_MALI_T6XX := n
+  endif
+  EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT)
+  ifneq ($(GATOR_MALI_INTERFACE_STYLE),)
+    EXTRA_CFLAGS += -DGATOR_MALI_INTERFACE_STYLE=$(GATOR_MALI_INTERFACE_STYLE)
+  endif
 endif
+
+ifeq ($(CONFIG_GATOR_WITH_MALI_SUPPORT),y)
+  ifeq ($(CONFIG_GATOR_MALI_T6XX),y)
+    gator-y += gator_events_mali_t6xx.o \
+               gator_events_mali_t6xx_hw.o
+    include $(src)/mali_t6xx.mk
+  else
+    gator-y += gator_events_mali_4xx.o
+  endif
+  gator-y +=   gator_events_mali_common.o
+
+  ifneq ($(CONFIG_GATOR_MALI_PATH),)
+    ccflags-y += -I$(CONFIG_GATOR_MALI_PATH)
+  endif
+  ccflags-$(CONFIG_GATOR_MALI_4XXMP) += -DMALI_SUPPORT=MALI_4xx
+  ccflags-$(CONFIG_GATOR_MALI_T6XX) += -DMALI_SUPPORT=MALI_T6xx
 endif
 
 # GATOR_TEST controls whether to include (=1) or exclude (=0) test code. 
@@ -42,17 +60,6 @@ gator-$(CONFIG_ARM) +=       gator_events_armv6.o \
 
 gator-$(CONFIG_ARM64) +=       gator_events_ccn-504.o
 
-$(obj)/gator_main.o: gator_events.h
-
-clean-files := gator_events.h
-
-       chk_events.h = :
- quiet_chk_events.h = echo '  CHK     $@'
-silent_chk_events.h = :
-gator_events.h: FORCE
-       @$($(quiet)chk_events.h)
-       $(Q)cd $(obj) ; $(CONFIG_SHELL) $(obj)/gator_events.sh $@
-
 else
 
 all:
@@ -63,7 +70,7 @@ all:
        $(error)
 
 clean:
-       rm -f *.o .*.cmd gator_events.h modules.order Module.symvers gator.ko gator.mod.c
+       rm -f *.o .*.cmd modules.order Module.symvers gator.ko gator.mod.c
        rm -rf .tmp_versions
 
 endif
index 2e122da767d83e7c05d40103809f266e974f638d..d8981ed85a6a101cbfa5aadcfda9af4f99859a54 100644 (file)
@@ -112,14 +112,10 @@ struct gator_interface {
        void (*offline_dispatch)(int cpu, bool migrate);        // called in process context but may not be running on core 'cpu'
        int (*read)(int **buffer);
        int (*read64)(long long **buffer);
+       int (*read_proc)(long long **buffer, struct task_struct *);
        struct list_head list;
 };
 
-// gator_events_init is used as a search term in gator_events.sh
-#define gator_events_init(initfn) \
-       static inline int __gator_events_init_test(void) \
-       { return initfn(); }
-
 int gator_events_install(struct gator_interface *interface);
 int gator_events_get_key(void);
 u32 gator_cpuid(void);
index 4715f64a186511f8502ce00af069d68a0c2ca195..a406e4882974ba27571d7dadb12feaf1050103e8 100644 (file)
@@ -29,11 +29,27 @@ static void kannotate_write(const char *ptr, unsigned int size)
        }
 }
 
+static void marshal_u16(char *buf, u16 val) {
+       buf[0] = val & 0xff;
+       buf[1] = (val >> 8) & 0xff;
+}
+
+static void marshal_u32(char *buf, u32 val) {
+       buf[0] = val & 0xff;
+       buf[1] = (val >> 8) & 0xff;
+       buf[2] = (val >> 16) & 0xff;
+       buf[3] = (val >> 24) & 0xff;
+}
+
 void gator_annotate_channel(int channel, const char *str)
 {
-       int str_size = strlen(str) & 0xffff;
-       long long header = ESCAPE_CODE | (STRING_ANNOTATION << 8) | (channel << 16) | ((long long)str_size << 48);
-       kannotate_write((char *)&header, sizeof(header));
+       const u16 str_size = strlen(str) & 0xffff;
+       char header[8];
+       header[0] = ESCAPE_CODE;
+       header[1] = STRING_ANNOTATION;
+       marshal_u32(header + 2, channel);
+       marshal_u16(header + 6, str_size);
+       kannotate_write(header, sizeof(header));
        kannotate_write(str, str_size);
 }
 
@@ -48,14 +64,14 @@ EXPORT_SYMBOL(gator_annotate);
 
 void gator_annotate_channel_color(int channel, int color, const char *str)
 {
-       int str_size = (strlen(str) + 4) & 0xffff;
+       const u16 str_size = (strlen(str) + 4) & 0xffff;
        char header[12];
        header[0] = ESCAPE_CODE;
        header[1] = STRING_ANNOTATION;
-       *(u32 *)(&header[2]) = channel;
-       *(u16 *)(&header[6]) = str_size;
-       *(u32 *)(&header[8]) = color;
-       kannotate_write((char *)&header, sizeof(header));
+       marshal_u32(header + 2, channel);
+       marshal_u16(header + 6, str_size);
+       marshal_u32(header + 8, color);
+       kannotate_write(header, sizeof(header));
        kannotate_write(str, str_size - 4);
 }
 
@@ -70,8 +86,12 @@ EXPORT_SYMBOL(gator_annotate_color);
 
 void gator_annotate_channel_end(int channel)
 {
-       long long header = ESCAPE_CODE | (STRING_ANNOTATION << 8) | (channel << 16);
-       kannotate_write((char *)&header, sizeof(header));
+       char header[8];
+       header[0] = ESCAPE_CODE;
+       header[1] = STRING_ANNOTATION;
+       marshal_u32(header + 2, channel);
+       marshal_u16(header + 6, 0);
+       kannotate_write(header, sizeof(header));
 }
 
 EXPORT_SYMBOL(gator_annotate_channel_end);
@@ -85,14 +105,14 @@ EXPORT_SYMBOL(gator_annotate_end);
 
 void gator_annotate_name_channel(int channel, int group, const char* str)
 {
-       int str_size = strlen(str) & 0xffff;
+       const u16 str_size = strlen(str) & 0xffff;
        char header[12];
        header[0] = ESCAPE_CODE;
        header[1] = NAME_CHANNEL_ANNOTATION;
-       *(u32 *)(&header[2]) = channel;
-       *(u32 *)(&header[6]) = group;
-       *(u16 *)(&header[10]) = str_size;
-       kannotate_write((char *)&header, sizeof(header));
+       marshal_u32(header + 2, channel);
+       marshal_u32(header + 6, group);
+       marshal_u16(header + 10, str_size);
+       kannotate_write(header, sizeof(header));
        kannotate_write(str, str_size);
 }
 
@@ -100,9 +120,13 @@ EXPORT_SYMBOL(gator_annotate_name_channel);
 
 void gator_annotate_name_group(int group, const char* str)
 {
-       int str_size = strlen(str) & 0xffff;
-       long long header = ESCAPE_CODE | (NAME_GROUP_ANNOTATION << 8) | (group << 16) | ((long long)str_size << 48);
-       kannotate_write((char *)&header, sizeof(header));
+       const u16 str_size = strlen(str) & 0xffff;
+       char header[8];
+       header[0] = ESCAPE_CODE;
+       header[1] = NAME_GROUP_ANNOTATION;
+       marshal_u32(header + 2, group);
+       marshal_u16(header + 6, str_size);
+       kannotate_write(header, sizeof(header));
        kannotate_write(str, str_size);
 }
 
@@ -110,11 +134,16 @@ EXPORT_SYMBOL(gator_annotate_name_group);
 
 void gator_annotate_visual(const char *data, unsigned int length, const char *str)
 {
-       int str_size = strlen(str) & 0xffff;
-       int visual_annotation = ESCAPE_CODE | (VISUAL_ANNOTATION << 8) | (str_size << 16);
-       kannotate_write((char *)&visual_annotation, sizeof(visual_annotation));
+       const u16 str_size = strlen(str) & 0xffff;
+       char header[4];
+       char header_length[4];
+       header[0] = ESCAPE_CODE;
+       header[1] = VISUAL_ANNOTATION;
+       marshal_u16(header + 2, str_size);
+       marshal_u32(header_length, length);
+       kannotate_write(header, sizeof(header));
        kannotate_write(str, str_size);
-       kannotate_write((char *)&length, sizeof(length));
+       kannotate_write(header_length, sizeof(header_length));
        kannotate_write(data, length);
 }
 
@@ -122,17 +151,23 @@ EXPORT_SYMBOL(gator_annotate_visual);
 
 void gator_annotate_marker(void)
 {
-       int header = ESCAPE_CODE | (MARKER_ANNOTATION << 8);
-       kannotate_write((char *)&header, sizeof(header));
+       char header[4];
+       header[0] = ESCAPE_CODE;
+       header[1] = MARKER_ANNOTATION;
+       marshal_u16(header + 2, 0);
+       kannotate_write(header, sizeof(header));
 }
 
 EXPORT_SYMBOL(gator_annotate_marker);
 
 void gator_annotate_marker_str(const char *str)
 {
-       int str_size = strlen(str) & 0xffff;
-       int header = ESCAPE_CODE | (MARKER_ANNOTATION << 8) | (str_size << 16);
-       kannotate_write((char *)&header, sizeof(header));
+       const u16 str_size = strlen(str) & 0xffff;
+       char header[4];
+       header[0] = ESCAPE_CODE;
+       header[1] = MARKER_ANNOTATION;
+       marshal_u16(header + 2, str_size);
+       kannotate_write(header, sizeof(header));
        kannotate_write(str, str_size);
 }
 
@@ -140,17 +175,25 @@ EXPORT_SYMBOL(gator_annotate_marker_str);
 
 void gator_annotate_marker_color(int color)
 {
-       long long header = (ESCAPE_CODE | (MARKER_ANNOTATION << 8) | 0x00040000 | ((long long)color << 32));
-       kannotate_write((char *)&header, sizeof(header));
+       char header[8];
+       header[0] = ESCAPE_CODE;
+       header[1] = MARKER_ANNOTATION;
+       marshal_u16(header + 2, 4);
+       marshal_u32(header + 4, color);
+       kannotate_write(header, sizeof(header));
 }
 
 EXPORT_SYMBOL(gator_annotate_marker_color);
 
 void gator_annotate_marker_color_str(int color, const char *str)
 {
-       int str_size = (strlen(str) + 4) & 0xffff;
-       long long header = ESCAPE_CODE | (MARKER_ANNOTATION << 8) | (str_size << 16) | ((long long)color << 32);
-       kannotate_write((char *)&header, sizeof(header));
+       const u16 str_size = (strlen(str) + 4) & 0xffff;
+       char header[8];
+       header[0] = ESCAPE_CODE;
+       header[1] = MARKER_ANNOTATION;
+       marshal_u16(header + 2, str_size);
+       marshal_u32(header + 4, color);
+       kannotate_write(header, sizeof(header));
        kannotate_write(str, str_size - 4);
 }
 
index 0670d6cea9bdf5cf4eebeb94ac1d47978a0e0cdc..ffacb490194cb60a7161bea3b2f7886f1b732891 100644 (file)
@@ -132,13 +132,21 @@ static int report_trace(struct stackframe *frame, void *d)
 
 // Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile
 // #define GATOR_KERNEL_STACK_UNWINDING
+
+#if (defined(__arm__) || defined(__aarch64__)) && !defined(GATOR_KERNEL_STACK_UNWINDING)
+// Disabled by default
+MODULE_PARM_DESC(kernel_stack_unwinding, "Allow kernel stack unwinding.");
+bool kernel_stack_unwinding = 0;
+module_param(kernel_stack_unwinding, bool, 0644);
+#endif
+
 static void kernel_backtrace(int cpu, struct pt_regs *const regs)
 {
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef GATOR_KERNEL_STACK_UNWINDING
        int depth = gator_backtrace_depth;
 #else
-       int depth = 1;
+       int depth = (kernel_stack_unwinding ? gator_backtrace_depth : 1);
 #endif
        struct stackframe frame;
        if (depth == 0)
index 5f98a1cc309cd9dd7d28fbd355bc3c6d784f22a8..91adfdde9be2e0246e3e173eb6ce14744704715d 100644 (file)
@@ -8,7 +8,8 @@
  */
 
 #define COOKIEMAP_ENTRIES      1024    /* must be power of 2 */
-#define TRANSLATE_SIZE         256
+#define TRANSLATE_BUFFER_SIZE 512  // must be a power of 2 - 512/4 = 128 entries
+#define TRANSLATE_TEXT_SIZE            256
 #define MAX_COLLISIONS         2
 
 static uint32_t *gator_crc32_table;
@@ -22,7 +23,7 @@ static DEFINE_PER_CPU(int, translate_buffer_read);
 static DEFINE_PER_CPU(int, translate_buffer_write);
 static DEFINE_PER_CPU(void **, translate_buffer);
 
-static inline uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq);
+static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq);
 static void wq_cookie_handler(struct work_struct *unused);
 DECLARE_WORK(cookie_work, wq_cookie_handler);
 static struct timer_list app_process_wake_up_timer;
@@ -107,11 +108,13 @@ static void cookiemap_add(uint64_t key, uint32_t value)
        values[0] = value;
 }
 
+#ifndef CONFIG_PREEMPT_RT_FULL
 static void translate_buffer_write_ptr(int cpu, void *x)
 {
        per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x;
        per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask;
 }
+#endif
 
 static void *translate_buffer_read_ptr(int cpu)
 {
@@ -124,7 +127,7 @@ static void wq_cookie_handler(struct work_struct *unused)
 {
        struct task_struct *task;
        char *text;
-       int cpu = get_physical_cpu();
+       int cpu = get_physical_cpu(), cookie;
        unsigned int commit;
 
        mutex_lock(&start_mutex);
@@ -134,7 +137,8 @@ static void wq_cookie_handler(struct work_struct *unused)
                while (per_cpu(translate_buffer_read, cpu) != commit) {
                        task = (struct task_struct *)translate_buffer_read_ptr(cpu);
                        text = (char *)translate_buffer_read_ptr(cpu);
-                       get_cookie(cpu, task, text, true);
+                       cookie = get_cookie(cpu, task, text, true);
+                       marshal_link(cookie, task->tgid, task->pid);
                }
        }
 
@@ -156,15 +160,16 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
        struct mm_struct *mm;
        struct page *page = NULL;
        struct vm_area_struct *page_vma;
-       int bytes, offset, retval = 0, ptr;
+       int bytes, offset, retval = 0;
        char *buf = per_cpu(translate_text, cpu);
 
+#ifndef CONFIG_PREEMPT_RT_FULL
        // Push work into a work queue if in atomic context as the kernel functions below might sleep
        // Rely on the in_interrupt variable rather than in_irq() or in_interrupt() kernel functions, as the value of these functions seems
        //   inconsistent during a context switch between android/linux versions
        if (!from_wq) {
                // Check if already in buffer
-               ptr = per_cpu(translate_buffer_read, cpu);
+               int ptr = per_cpu(translate_buffer_read, cpu);
                while (ptr != per_cpu(translate_buffer_write, cpu)) {
                        if (per_cpu(translate_buffer, cpu)[ptr] == (void *)task)
                                goto out;
@@ -174,9 +179,11 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
                translate_buffer_write_ptr(cpu, (void *)task);
                translate_buffer_write_ptr(cpu, (void *)*text);
 
+               // Not safe to call in RT-Preempt full in schedule switch context
                mod_timer(&app_process_wake_up_timer, jiffies + 1);
                goto out;
        }
+#endif
 
        mm = get_task_mm(task);
        if (!mm)
@@ -186,8 +193,8 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
        addr = mm->arg_start;
        len = mm->arg_end - mm->arg_start;
 
-       if (len > TRANSLATE_SIZE)
-               len = TRANSLATE_SIZE;
+       if (len > TRANSLATE_TEXT_SIZE)
+               len = TRANSLATE_TEXT_SIZE;
 
        down_read(&mm->mmap_sem);
        while (len) {
@@ -225,7 +232,7 @@ out:
        return retval;
 }
 
-static inline uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq)
+static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq)
 {
        unsigned long flags, cookie;
        uint64_t key;
@@ -312,8 +319,7 @@ static int cookies_initialize(void)
        uint32_t crc, poly;
        int i, j, cpu, size, err = 0;
 
-       int translate_buffer_size = 512;        // must be a power of 2
-       translate_buffer_mask = translate_buffer_size / sizeof(per_cpu(translate_buffer, 0)[0]) - 1;
+       translate_buffer_mask = TRANSLATE_BUFFER_SIZE / sizeof(per_cpu(translate_buffer, 0)[0]) - 1;
 
        for_each_present_cpu(cpu) {
                per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu;
@@ -334,7 +340,7 @@ static int cookies_initialize(void)
                }
                memset(per_cpu(cookie_values, cpu), 0, size);
 
-               per_cpu(translate_buffer, cpu) = (void **)kmalloc(translate_buffer_size, GFP_KERNEL);
+               per_cpu(translate_buffer, cpu) = (void **)kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL);
                if (!per_cpu(translate_buffer, cpu)) {
                        err = -ENOMEM;
                        goto cookie_setup_error;
@@ -343,7 +349,7 @@ static int cookies_initialize(void)
                per_cpu(translate_buffer_write, cpu) = 0;
                per_cpu(translate_buffer_read, cpu) = 0;
 
-               per_cpu(translate_text, cpu) = (char *)kmalloc(TRANSLATE_SIZE, GFP_KERNEL);
+               per_cpu(translate_text, cpu) = (char *)kmalloc(TRANSLATE_TEXT_SIZE, GFP_KERNEL);
                if (!per_cpu(translate_text, cpu)) {
                        err = -ENOMEM;
                        goto cookie_setup_error;
@@ -353,6 +359,10 @@ static int cookies_initialize(void)
        // build CRC32 table
        poly = 0x04c11db7;
        gator_crc32_table = (uint32_t *)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL);
+       if (!gator_crc32_table) {
+               err = -ENOMEM;
+               goto cookie_setup_error;
+       }
        for (i = 0; i < 256; i++) {
                crc = i;
                for (j = 8; j > 0; j--) {
diff --git a/driver/gator_events.sh b/driver/gator_events.sh
deleted file mode 100755 (executable)
index 5467dd6..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh
-
-EVENTS=`grep gator_events_init *.c | sed 's/.\+gator_events_init(\(.\+\)).\+/\1/'`
-
-(
-       echo /\* This file is auto generated \*/
-       echo
-       for EVENT in $EVENTS; do
-               echo __weak int $EVENT\(void\)\;
-       done
-       echo
-       echo static int \(*gator_events_list[]\)\(void\) = {
-       for EVENT in $EVENTS; do
-               echo \  $EVENT,
-       done
-       echo }\;
-) > $1.tmp
-
-cmp -s $1 $1.tmp && rm $1.tmp || mv $1.tmp $1
index 4f1bca6e2dbeb2b0a19c6b75dd60d15653ce93fc..dd7974090b821d3e9bec339a9487ff8e864e6df6 100644 (file)
@@ -234,11 +234,4 @@ int gator_events_armv6_init(void)
        return gator_events_install(&gator_events_armv6_interface);
 }
 
-gator_events_init(gator_events_armv6_init);
-
-#else
-int gator_events_armv6_init(void)
-{
-       return -1;
-}
 #endif
index 58f29566eeabdc401da5251b7adeecf8a1234246..30881c8fd3fd94443d9e9781ab5c218b33939e09 100644 (file)
@@ -309,11 +309,4 @@ int gator_events_armv7_init(void)
        return gator_events_install(&gator_events_armv7_interface);
 }
 
-gator_events_init(gator_events_armv7_init);
-
-#else
-int gator_events_armv7_init(void)
-{
-       return -1;
-}
 #endif
index 56c6a67365291c9c37b57ea477bb6926151a599a..691ef2574536e580516c9e7057401f92bee04b6f 100644 (file)
@@ -151,5 +151,3 @@ int gator_events_block_init(void)
 
        return gator_events_install(&gator_events_block_interface);
 }
-
-gator_events_init(gator_events_block_init);
index b91a9a149b90546a8133ecef8c92137da6b9a6d0..b89231967c75c75fc00bdeda5aa4fb1f9ffa9fec 100644 (file)
@@ -6,23 +6,16 @@
  * published by the Free Software Foundation.
  */
 
-/*******************************************************************************
- * WARNING: This code is an experimental implementation of the CCN-504 hardware
- * counters which has not been tested on the hardware. Commented debug
- * statements are present and can be uncommented for diagnostic purposes.
- ******************************************************************************/
-
 #include <linux/io.h>
 #include <linux/module.h>
 
 #include "gator.h"
 
-#define PERIPHBASE 0x2E000000
-
 #define NUM_REGIONS 256
 #define REGION_SIZE (64*1024)
 #define REGION_DEBUG 1
 #define REGION_XP 64
+#define NUM_XPS 11
 
 // DT (Debug) region
 #define PMEVCNTSR0    0x0150
 
 // XP region
 #define DT_CONFIG     0x0300
+#define DT_CONTROL    0x0370
 
 // Multiple
 #define PMU_EVENT_SEL 0x0600
 #define OLY_ID        0xFF00
 
 #define CCNT 4
-#define CNTMAX (4 + 1)
+#define CNTMAX (CCNT + 1)
 
 #define get_pmu_event_id(event) (((event) >> 0) & 0xFF)
 #define get_node_type(event) (((event) >> 8) & 0xFF)
 #define get_region(event) (((event) >> 16) & 0xFF)
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+
+// From kernel/params.c
+#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn)              \
+       int param_set_##name(const char *val, struct kernel_param *kp)  \
+       {                                                               \
+               tmptype l;                                              \
+               int ret;                                                \
+                                                                       \
+               if (!val) return -EINVAL;                               \
+               ret = strtolfn(val, 0, &l);                             \
+               if (ret == -EINVAL || ((type)l != l))                   \
+                       return -EINVAL;                                 \
+               *((type *)kp->arg) = l;                                 \
+               return 0;                                               \
+       }                                                               \
+       int param_get_##name(char *buffer, struct kernel_param *kp)     \
+       {                                                               \
+               return sprintf(buffer, format, *((type *)kp->arg));     \
+       }
+
+#else
+
+// From kernel/params.c
+#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn)              \
+       int param_set_##name(const char *val, const struct kernel_param *kp) \
+       {                                                               \
+               tmptype l;                                              \
+               int ret;                                                \
+                                                                       \
+               ret = strtolfn(val, 0, &l);                             \
+               if (ret < 0 || ((type)l != l))                          \
+                       return ret < 0 ? ret : -EINVAL;                 \
+               *((type *)kp->arg) = l;                                 \
+               return 0;                                               \
+       }                                                               \
+       int param_get_##name(char *buffer, const struct kernel_param *kp) \
+       {                                                               \
+               return scnprintf(buffer, PAGE_SIZE, format,             \
+                               *((type *)kp->arg));                    \
+       }                                                               \
+       struct kernel_param_ops param_ops_##name = {                    \
+               .set = param_set_##name,                                \
+               .get = param_get_##name,                                \
+       };                                                              \
+       EXPORT_SYMBOL(param_set_##name);                                \
+       EXPORT_SYMBOL(param_get_##name);                                \
+       EXPORT_SYMBOL(param_ops_##name)
+
+#endif
+
+STANDARD_PARAM_DEF(u64, u64, "%llu", u64, strict_strtoull);
+
+// From include/linux/moduleparam.h
+#define param_check_u64(name, p) __param_check(name, p, u64)
+
 MODULE_PARM_DESC(ccn504_addr, "CCN-504 physical base address");
-static unsigned long ccn504_addr = 0;
-module_param(ccn504_addr, ulong, 0444);
+static u64 ccn504_addr = 0;
+module_param(ccn504_addr, u64, 0444);
 
 static void __iomem *gator_events_ccn504_base;
+static bool gator_events_ccn504_global_enabled;
 static unsigned long gator_events_ccn504_enabled[CNTMAX];
 static unsigned long gator_events_ccn504_event[CNTMAX];
 static unsigned long gator_events_ccn504_key[CNTMAX];
 static int gator_events_ccn504_buffer[2*CNTMAX];
+static int gator_events_ccn504_prev[CNTMAX];
 
 static void gator_events_ccn504_create_shutdown(void)
 {
@@ -96,7 +148,6 @@ static void gator_events_ccn504_set_dt_config(int xp_node_id, int event_num, int
 
        dt_config = readl(gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG);
        dt_config |= (value + event_num) << (4*event_num);
-       //printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, dt_config, (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG);
        writel(dt_config, gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG);
 }
 
@@ -104,6 +155,20 @@ static int gator_events_ccn504_start(void)
 {
        int i;
 
+       gator_events_ccn504_global_enabled = 0;
+       for (i = 0; i < CNTMAX; ++i) {
+               if (gator_events_ccn504_enabled[i]) {
+                       gator_events_ccn504_global_enabled = 1;
+                       break;
+               }
+       }
+
+       if (!gator_events_ccn504_global_enabled) {
+               return 0;
+       }
+
+       memset(&gator_events_ccn504_prev, 0x80, sizeof(gator_events_ccn504_prev));
+
        // Disable INTREQ on overflow
        // [6] ovfl_intr_en = 0
        // perhaps set to 1?
@@ -112,9 +177,22 @@ static int gator_events_ccn504_start(void)
        // [4:1] cntcfg = 0
        // Enable PMU features
        // [0] pmu_en = 1
-       //printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, 0x1, REGION_DEBUG*REGION_SIZE + PMCR);
        writel(0x1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMCR);
 
+       // Configure the XPs
+       for (i = 0; i < NUM_XPS; ++i) {
+               int dt_control;
+
+               // Pass on all events
+               writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG);
+
+               // Enable PMU capability
+               // [0] dt_enable = 1
+               dt_control = readl(gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL);
+               dt_control |= 0x1;
+               writel(dt_control, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL);
+       }
+
        // Assume no other pmu_event_sel registers are set
 
        // cycle counter does not need to be enabled
@@ -134,15 +212,14 @@ static int gator_events_ccn504_start(void)
                pmu_event_id = get_pmu_event_id(gator_events_ccn504_event[i]);
                node_type = get_node_type(gator_events_ccn504_event[i]);
                region = get_region(gator_events_ccn504_event[i]);
-               //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);
 
                // Verify the node_type
                oly_id_whole = readl(gator_events_ccn504_base + region*REGION_SIZE + OLY_ID);
                oly_id = oly_id_whole & 0x1F;
                node_id = (oly_id_whole >> 8) & 0x7F;
                if ((oly_id != node_type) ||
-                               ((node_type == 0x16) && ((oly_id == 0x14) || (oly_id == 0x15) || (oly_id == 0x16) || (oly_id == 0x18) || (oly_id == 0x19) || (oly_id == 0x1A)))) {
-                       printk(KERN_ERR "%s(%s:%i) oly_id is %x expected %x\n", __FUNCTION__, __FILE__, __LINE__, oly_id, node_type);
+                               ((node_type == 0x16) && ((oly_id != 0x14) && (oly_id != 0x15) && (oly_id != 0x16) && (oly_id != 0x18) && (oly_id != 0x19) && (oly_id != 0x1A)))) {
+                       printk(KERN_ERR "gator: oly_id is 0x%x expected 0x%x\n", oly_id, node_type);
                        return -1;
                }
 
@@ -160,7 +237,6 @@ static int gator_events_ccn504_start(void)
                        gator_events_ccn504_set_dt_config(node_id/2, i, (node_id & 1) == 0 ? 0x8 : 0xC);
                        break;
                }
-               //printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, pmu_event_sel, region*REGION_SIZE + PMU_EVENT_SEL);
                writel(pmu_event_sel, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL);
        }
 
@@ -171,21 +247,25 @@ static void gator_events_ccn504_stop(void)
 {
        int i;
 
+       if (!gator_events_ccn504_global_enabled) {
+               return;
+       }
+
        // cycle counter does not need to be disabled
        for (i = 0; i < CCNT; ++i) {
-               int node_type;
                int region;
 
-               node_type = get_node_type(gator_events_ccn504_event[i]);
+               if (!gator_events_ccn504_enabled[i]) {
+                       continue;
+               }
+
                region = get_region(gator_events_ccn504_event[i]);
 
-               //printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, 0, region*REGION_SIZE + PMU_EVENT_SEL);
                writel(0, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL);
        }
 
        // Clear dt_config
-       for (i = 0; i < 11; ++i) {
-               //printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, 0, (REGION_XP + i)*REGION_SIZE + DT_CONFIG);
+       for (i = 0; i < NUM_XPS; ++i) {
                writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG);
        }
 }
@@ -194,27 +274,20 @@ static int gator_events_ccn504_read(int **buffer)
 {
        int i;
        int len = 0;
+       int value;
 
-       if (!on_primary_core()) {
+       if (!on_primary_core() || !gator_events_ccn504_global_enabled) {
                return 0;
        }
 
        // Verify the pmsr register is zero
-       //i = 0;
-       while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) != 0) {
-               //++i;
-       }
-       //printk(KERN_ERR "%s(%s:%i) %i\n", __FUNCTION__, __FILE__, __LINE__, i);
+       while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) != 0);
 
        // Request a PMU snapshot
        writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_REQ);
 
        // Wait for the snapshot
-       //i = 0;
-       while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) == 0) {
-               //++i;
-       }
-       //printk(KERN_ERR "%s(%s:%i) %i\n", __FUNCTION__, __FILE__, __LINE__, i);
+       while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) == 0);
 
        // Read the shadow registers
        for (i = 0; i < CNTMAX; ++i) {
@@ -222,8 +295,12 @@ static int gator_events_ccn504_read(int **buffer)
                        continue;
                }
 
-               gator_events_ccn504_buffer[len++] = gator_events_ccn504_key[i];
-               gator_events_ccn504_buffer[len++] = readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + (i == CCNT ? PMCCNTRSR : PMEVCNTSR0 + 8*i));
+               value = readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + (i == CCNT ? PMCCNTRSR : PMEVCNTSR0 + 8*i));
+               if (gator_events_ccn504_prev[i] != 0x80808080) {
+                       gator_events_ccn504_buffer[len++] = gator_events_ccn504_key[i];
+                       gator_events_ccn504_buffer[len++] = value - gator_events_ccn504_prev[i];
+               }
+               gator_events_ccn504_prev[i] = value;
 
                // Are the counters registers cleared when read? Is that what the cntr_rst bit on the pmcr register does?
        }
@@ -231,18 +308,10 @@ static int gator_events_ccn504_read(int **buffer)
        // Clear the PMU snapshot status
        writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_CLR);
 
-       return len;
-}
-
-static void __maybe_unused gator_events_ccn504_enumerate(int pos, int size)
-{
-       int i;
-       u32 oly_id;
+       if (buffer)
+               *buffer = gator_events_ccn504_buffer;
 
-       for (i = pos; i < pos + size; ++i) {
-               oly_id = readl(gator_events_ccn504_base + i*REGION_SIZE + OLY_ID);
-               printk(KERN_ERR "%s(%s:%i) %i %08x\n", __FUNCTION__, __FILE__, __LINE__, i, oly_id);
-       }
+       return len;
 }
 
 static struct gator_interface gator_events_ccn504_interface = {
@@ -263,36 +332,9 @@ int gator_events_ccn504_init(void)
 
        gator_events_ccn504_base = ioremap(ccn504_addr, NUM_REGIONS*REGION_SIZE);
        if (gator_events_ccn504_base == NULL) {
-               printk(KERN_ERR "%s(%s:%i) ioremap returned NULL\n", __FUNCTION__, __FILE__, __LINE__);
+               printk(KERN_ERR "gator: ioremap returned NULL\n");
                return -1;
        }
-       //printk(KERN_ERR "%s(%s:%i)\n", __FUNCTION__, __FILE__, __LINE__);
-
-       // Test - can memory be read
-       {
-               //gator_events_ccn504_enumerate(0, NUM_REGIONS);
-
-#if 0
-               // DT
-               gator_events_ccn504_enumerate(1, 1);
-               // HN-F
-               gator_events_ccn504_enumerate(32, 8);
-               // XP
-               gator_events_ccn504_enumerate(64, 11);
-               // RN-I
-               gator_events_ccn504_enumerate(128, 1);
-               gator_events_ccn504_enumerate(130, 1);
-               gator_events_ccn504_enumerate(134, 1);
-               gator_events_ccn504_enumerate(140, 1);
-               gator_events_ccn504_enumerate(144, 1);
-               gator_events_ccn504_enumerate(148, 1);
-               // SBAS
-               gator_events_ccn504_enumerate(129, 1);
-               gator_events_ccn504_enumerate(137, 1);
-               gator_events_ccn504_enumerate(139, 1);
-               gator_events_ccn504_enumerate(147, 1);
-#endif
-       }
 
        for (i = 0; i < CNTMAX; ++i) {
                gator_events_ccn504_enabled[i] = 0;
@@ -302,5 +344,3 @@ int gator_events_ccn504_init(void)
 
        return gator_events_install(&gator_events_ccn504_interface);
 }
-
-gator_events_init(gator_events_ccn504_init);
index b4df7faefff81f07070d23989b1503e6f67190d8..b11879a248f831f130a8beb8eaf976a36ef582b5 100644 (file)
@@ -163,5 +163,3 @@ int gator_events_irq_init(void)
 
        return gator_events_install(&gator_events_irq_interface);
 }
-
-gator_events_init(gator_events_irq_init);
index 21aa4a214d97c02c09a9dfdea253e0cce7e8ae0d..ee521af22517a0f9bcf6d597ddc0618298bd248d 100644 (file)
@@ -206,5 +206,3 @@ int gator_events_l2c310_init(void)
 
        return gator_events_install(&gator_events_l2c310_interface);
 }
-
-gator_events_init(gator_events_l2c310_init);
index dd275f70b700698557fb3fb74c1961c5898264ff..6719c1ec73a2e07be50b198c1928b59c9f2e5411 100644 (file)
@@ -415,25 +415,12 @@ static void mali_counter_initialize(void)
        int i;
        int core_id;
 
-       mali_osk_fb_control_set_type *mali_set_fb_event;
        mali_profiling_control_type *mali_control;
 
        init_counters(COUNTER_L2_0_C0, COUNTER_L2_0_C0 + (2 * n_l2_cores) - 1);
        init_counters(COUNTER_VP_0_C0, COUNTER_VP_0_C0 + (2 * n_vp_cores) - 1);
        init_counters(COUNTER_FP_0_C0, COUNTER_FP_0_C0 + (2 * n_fp_cores) - 1);
 
-       mali_set_fb_event = symbol_get(_mali_osk_fb_control_set);
-
-       if (mali_set_fb_event) {
-               pr_debug("gator: mali online _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
-
-               mali_set_fb_event(0, (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0));
-
-               symbol_put(_mali_osk_fb_control_set);
-       } else {
-               printk("gator: mali online _mali_osk_fb_control_set symbol not found\n");
-       }
-
        /* Generic control interface for Mali DDK. */
        mali_control = symbol_get(_mali_profiling_control);
        if (mali_control) {
@@ -491,7 +478,6 @@ static void mali_counter_initialize(void)
 static void mali_counter_deinitialize(void)
 {
        mali_profiling_set_event_type *mali_set_hw_event;
-       mali_osk_fb_control_set_type *mali_set_fb_event;
        mali_profiling_control_type *mali_control;
 
        mali_set_hw_event = symbol_get(_mali_profiling_set_event);
@@ -509,23 +495,11 @@ static void mali_counter_deinitialize(void)
                printk("gator: mali offline _mali_profiling_set_event symbol not found\n");
        }
 
-       mali_set_fb_event = symbol_get(_mali_osk_fb_control_set);
-
-       if (mali_set_fb_event) {
-               pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
-
-               mali_set_fb_event(0, 0);
-
-               symbol_put(_mali_osk_fb_control_set);
-       } else {
-               printk("gator: mali offline _mali_osk_fb_control_set symbol not found\n");
-       }
-
        /* Generic control interface for Mali DDK. */
        mali_control = symbol_get(_mali_profiling_control);
 
        if (mali_control) {
-               pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_set_fb_event);
+               pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_control);
 
                /* Reset the DDK state - disable counter collection */
                mali_control(SW_COUNTER_ENABLE, 0);
@@ -747,5 +721,3 @@ int gator_events_mali_init(void)
 
        return gator_events_install(&gator_events_mali_interface);
 }
-
-gator_events_init(gator_events_mali_init);
index 5a98b3745fc2b0cdfb499ca88731911cf5a811ba..466ca1683c7e99f2baf82fd44de8073fe70ed161 100644 (file)
@@ -28,7 +28,7 @@ extern const char *gator_mali_get_mali_name(void)
        }
 }
 
-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)
+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)
 {
        int err;
        char buf[255];
@@ -56,6 +56,13 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even
                        pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf);
                        return -1;
                }
+               if (event != NULL) {
+                       err = gatorfs_create_ulong(sb, dir, "event", event);
+                       if (err != 0) {
+                               pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf);
+                               return -1;
+                       }
+               }
        }
 
        return 0;
index d67ee2d245add6ee69e3f98f9fcb45efe68100b9..509f9b61884a3c6620d1c2520bc12ffc6384644e 100644 (file)
@@ -43,7 +43,6 @@ typedef struct {
  * Mali-4xx
  */
 typedef int mali_profiling_set_event_type(unsigned int, int);
-typedef void mali_osk_fb_control_set_type(unsigned int, unsigned int);
 typedef void mali_profiling_control_type(unsigned int, unsigned int);
 typedef void mali_profiling_get_counters_type(unsigned int *, unsigned int *, unsigned int *, unsigned int *);
 
@@ -51,7 +50,6 @@ typedef void mali_profiling_get_counters_type(unsigned int *, unsigned int *, un
  * Driver entry points for functions called directly by gator.
  */
 extern int _mali_profiling_set_event(unsigned int, int);
-extern void _mali_osk_fb_control_set(unsigned int, unsigned int);
 extern void _mali_profiling_control(unsigned int, unsigned int);
 extern void _mali_profiling_get_counters(unsigned int *, unsigned int *, unsigned int *, unsigned int *);
 
@@ -75,7 +73,7 @@ extern const char *gator_mali_get_mali_name(void);
  *
  * @return 0 if entry point was created, non-zero if not.
  */
-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);
+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);
 
 /**
  * Initializes the counter array.
index 2576a99a126a892ac8fed63df4152cd4a9e23dde..7bf7d6a6dbf9b0a09f08d61935ed297d319f6f28 100644 (file)
@@ -109,12 +109,14 @@ enum {
 #define NUMBER_OF_SOFTWARE_COUNTERS (sizeof(software_counter_names) / sizeof(software_counter_names[0]))
 #define FIRST_ACCUMULATOR (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS)
 #define NUMBER_OF_ACCUMULATORS (sizeof(accumulators_names) / sizeof(accumulators_names[0]))
-#define NUMBER_OF_EVENTS (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS)
+#define FILMSTRIP (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS)
+#define NUMBER_OF_EVENTS (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS + 1)
 
 /*
  * gatorfs variables for counter enable state
  */
 static mali_counter counters[NUMBER_OF_EVENTS];
+static unsigned long filmstrip_event;
 
 /* An array used to return the data we recorded
  * as key,value pairs hence the *2
@@ -285,28 +287,37 @@ static int create_files(struct super_block *sb, struct dentry *root)
         */
        int counter_index = 0;
        const char *mali_name = gator_mali_get_mali_name();
+       mali_profiling_control_type *mali_control;
 
        for (event = FIRST_TIMELINE_EVENT; event < FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS; event++) {
-               if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event]) != 0) {
+               if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event], NULL) != 0) {
                        return -1;
                }
                counter_index++;
        }
        counter_index = 0;
        for (event = FIRST_SOFTWARE_COUNTER; event < FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS; event++) {
-               if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event]) != 0) {
+               if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event], NULL) != 0) {
                        return -1;
                }
                counter_index++;
        }
        counter_index = 0;
        for (event = FIRST_ACCUMULATOR; event < FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS; event++) {
-               if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event]) != 0) {
+               if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event], NULL) != 0) {
                        return -1;
                }
                counter_index++;
        }
 
+       mali_control = symbol_get(_mali_profiling_control);
+       if (mali_control) {     
+               if (gator_mali_create_file_system(mali_name, "Filmstrip_cnt0", sb, root, &counters[FILMSTRIP], &filmstrip_event) != 0) {
+                       return -1;
+               }
+               symbol_put(_mali_profiling_control);
+       }
+
        return 0;
 }
 
@@ -350,6 +361,7 @@ static int register_tracepoints(void)
 static int start(void)
 {
        unsigned int cnt;
+       mali_profiling_control_type *mali_control;
 
        /* Clean all data for the next capture */
        for (cnt = 0; cnt < NUMBER_OF_TIMELINE_EVENTS; cnt++) {
@@ -370,6 +382,30 @@ static int start(void)
                return -1;
        }
 
+       /* Generic control interface for Mali DDK. */
+       mali_control = symbol_get(_mali_profiling_control);
+       if (mali_control) {
+               /* The event attribute in the XML file keeps the actual frame rate. */
+               unsigned int enabled = counters[FILMSTRIP].enabled ? 1 : 0;
+               unsigned int rate = filmstrip_event & 0xff;
+               unsigned int resize_factor = (filmstrip_event >> 8) & 0xff;
+
+               pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control);
+
+#define FBDUMP_CONTROL_ENABLE (1)
+#define FBDUMP_CONTROL_RATE (2)
+#define FBDUMP_CONTROL_RESIZE_FACTOR (4)
+               mali_control(FBDUMP_CONTROL_ENABLE, enabled);
+               mali_control(FBDUMP_CONTROL_RATE, rate);
+               mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor);
+
+               pr_debug("gator: sent mali_control enabled=%d, rate=%d, resize_factor=%d\n", enabled, rate, resize_factor);
+
+               symbol_put(_mali_profiling_control);
+       } else {
+               printk("gator: mali online _mali_profiling_control symbol not found\n");
+       }
+
        /*
         * Set the first timestamp for calculating the sample interval. The first interval could be quite long,
         * since it will be the time between 'start' and the first 'read'.
@@ -382,6 +418,8 @@ static int start(void)
 
 static void stop(void)
 {
+       mali_profiling_control_type *mali_control;
+
        pr_debug("gator: Mali-T6xx: stop\n");
 
        /*
@@ -402,6 +440,18 @@ static void stop(void)
 
        GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change);
        pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint deactivated\n");
+
+       /* Generic control interface for Mali DDK. */
+       mali_control = symbol_get(_mali_profiling_control);
+       if (mali_control) {
+               pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_control);
+
+               mali_control(FBDUMP_CONTROL_ENABLE, 0);
+
+               symbol_put(_mali_profiling_control);
+       } else {
+               printk("gator: mali offline _mali_profiling_control symbol not found\n");
+       }
 }
 
 static int read(int **buffer)
@@ -508,5 +558,3 @@ extern int gator_events_mali_t6xx_init(void)
 
        return gator_events_install(&gator_events_mali_t6xx_interface);
 }
-
-gator_events_init(gator_events_mali_t6xx_init);
index f557350eb9bca4e8dcdbf9839f2f29270f3a78a1..e406991398d997fbf1ac32303f0c9742696766a0 100644 (file)
@@ -63,6 +63,8 @@ static kbase_instr_hwcnt_disable_type *kbase_instr_hwcnt_disable_symbol;
 static kbase_va_free_type *kbase_va_free_symbol;
 static kbase_destroy_context_type *kbase_destroy_context_symbol;
 
+static long shader_present_low = 0;
+
 /** The interval between reads, in ns.
  *
  * Earlier we introduced
@@ -496,6 +498,7 @@ static int start(void)
        mali_error err;
        int cnt;
        u16 bitmask[] = { 0, 0, 0, 0 };
+       unsigned long long shadersPresent = 0;
 
        /* Setup HW counters */
        num_hardware_counters_enabled = 0;
@@ -539,6 +542,11 @@ static int start(void)
                        goto out;
                }
 
+
+               /* See if we can get the number of shader cores */
+               shadersPresent = kbdevice->shader_present_bitmap;
+               shader_present_low = (unsigned long)shadersPresent;
+
                /*
                 * The amount of memory needed to store the dump (bytes)
                 * DUMP_SIZE = number of core groups
@@ -679,21 +687,41 @@ static int read(int **buffer)
                        kbase_device_busy = false;
 
                        if (success == MALI_TRUE) {
+                               /* Cycle through hardware counters and accumulate totals */
                                for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) {
                                        const mali_counter *counter = &counters[cnt];
                                        if (counter->enabled) {
                                                const int block = GET_HW_BLOCK(cnt);
                                                const int counter_offset = GET_COUNTER_OFFSET(cnt);
-                                               const u32 *counter_block = (u32 *) ((uintptr_t)kernel_dump_buffer + vithar_blocks[block]);
-                                               const u32 *counter_address = counter_block + counter_offset;
 
-                                               value = *counter_address;
+                                               const char* block_base_address = (char*)kernel_dump_buffer + vithar_blocks[block];
 
+                                               /* If counter belongs to shader block need to take into account all cores */
                                                if (block == SHADER_BLOCK) {
-                                                       /* (counter_address + 0x000) has already been accounted-for above. */
-                                                       value += *(counter_address + 0x100);
-                                                       value += *(counter_address + 0x200);
-                                                       value += *(counter_address + 0x300);
+                                                       int i = 0;
+                                                       int shader_core_count = 0;
+                                                       value = 0;
+
+                                                       for (i = 0; i < 4; i++) {
+                                                               if ((shader_present_low >> i) & 1) {
+                                                                       value += *((u32*) (block_base_address + (0x100 * i)) + counter_offset);
+                                                                       shader_core_count++;
+                                                               }
+                                                       }
+
+                                                       for (i = 0; i < 4; i++) {
+                                                               if((shader_present_low >> (i+4)) & 1) {
+                                                                       value += *((u32*)(block_base_address + (0x100 * i) + 0x800) + counter_offset);
+                                                                       shader_core_count++;
+                                                               }
+                                                       }
+
+                                                       /* Need to total by number of cores to produce an average */
+                                                       if (shader_core_count != 0) {
+                                                               value /= shader_core_count;
+                                                       }
+                                               } else {
+                                                       value = *((u32*)block_base_address + counter_offset);
                                                }
 
                                                counter_dump[len++] = counter->key;
@@ -727,7 +755,7 @@ static int create_files(struct super_block *sb, struct dentry *root)
        const char *mali_name = gator_mali_get_mali_name();
 
        for (event = 0; event < NUMBER_OF_HARDWARE_COUNTERS; event++) {
-               if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event]) != 0)
+               if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event], NULL) != 0)
                        return -1;
                counter_index++;
        }
@@ -754,5 +782,3 @@ int gator_events_mali_t6xx_hw_init(void)
 
        return gator_events_install(&gator_events_mali_t6xx_interface);
 }
-
-gator_events_init(gator_events_mali_t6xx_hw_init);
index c1e360d12895677961b0c3068d626cc872bceb7c..451290d9af1759fa5759a985a44df303b98089e4 100644 (file)
@@ -8,27 +8,62 @@
  */
 
 #include "gator.h"
+
+#include <linux/hardirq.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/semaphore.h>
 #include <linux/workqueue.h>
 #include <trace/events/kmem.h>
-#include <linux/hardirq.h>
 
-#define MEMINFO_MEMFREE                0
-#define MEMINFO_MEMUSED                1
-#define MEMINFO_BUFFERRAM      2
-#define MEMINFO_TOTAL          3
+enum {
+       MEMINFO_MEMFREE,
+       MEMINFO_MEMUSED,
+       MEMINFO_BUFFERRAM,
+       MEMINFO_TOTAL,
+};
+
+enum {
+       PROC_SIZE,
+       PROC_SHARE,
+       PROC_TEXT,
+       PROC_DATA,
+       PROC_COUNT,
+};
+
+static const char * const meminfo_names[] = {
+       "Linux_meminfo_memfree",
+       "Linux_meminfo_memused",
+       "Linux_meminfo_bufferram",
+};
+
+static const char * const proc_names[] = {
+       "Linux_proc_statm_size",
+       "Linux_proc_statm_share",
+       "Linux_proc_statm_text",
+       "Linux_proc_statm_data",
+};
 
-static ulong meminfo_global_enabled;
+static bool meminfo_global_enabled;
 static ulong meminfo_enabled[MEMINFO_TOTAL];
-static ulong meminfo_key[MEMINFO_TOTAL];
-static unsigned long long meminfo_buffer[MEMINFO_TOTAL * 2];
+static ulong meminfo_keys[MEMINFO_TOTAL];
+static long long meminfo_buffer[2 * (MEMINFO_TOTAL + 2)];
 static int meminfo_length = 0;
-static unsigned int mem_event = 0;
 static bool new_data_avail;
 
-static void wq_sched_handler(struct work_struct *wsptr);
-DECLARE_WORK(work, wq_sched_handler);
-static struct timer_list meminfo_wake_up_timer;
-static void meminfo_wake_up_handler(unsigned long unused_data);
+static bool proc_global_enabled;
+static ulong proc_enabled[PROC_COUNT];
+static ulong proc_keys[PROC_COUNT];
+static DEFINE_PER_CPU(long long, proc_buffer[2 * (PROC_COUNT + 3)]);
+
+static int gator_meminfo_func(void *data);
+static bool gator_meminfo_run;
+// Initialize semaphore unlocked to initialize memory values
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+static DECLARE_MUTEX(gator_meminfo_sem);
+#else
+static DEFINE_SEMAPHORE(gator_meminfo_sem);
+#endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
 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
 GATOR_DEFINE_PROBE(mm_page_free, TP_PROTO(struct page *page, unsigned int order))
 #endif
 {
-       mem_event++;
+       up(&gator_meminfo_sem);
 }
 
 #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))
 GATOR_DEFINE_PROBE(mm_page_free_batched, TP_PROTO(struct page *page, int cold))
 #endif
 {
-       mem_event++;
+       up(&gator_meminfo_sem);
 }
 
 GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype))
 {
-       mem_event++;
+       up(&gator_meminfo_sem);
 }
 
 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
        int i;
 
        for (i = 0; i < MEMINFO_TOTAL; i++) {
-               switch (i) {
-               case MEMINFO_MEMFREE:
-                       dir = gatorfs_mkdir(sb, root, "Linux_meminfo_memfree");
-                       break;
-               case MEMINFO_MEMUSED:
-                       dir = gatorfs_mkdir(sb, root, "Linux_meminfo_memused");
-                       break;
-               case MEMINFO_BUFFERRAM:
-                       dir = gatorfs_mkdir(sb, root, "Linux_meminfo_bufferram");
-                       break;
-               default:
+               dir = gatorfs_mkdir(sb, root, meminfo_names[i]);
+               if (!dir) {
                        return -1;
                }
+               gatorfs_create_ulong(sb, dir, "enabled", &meminfo_enabled[i]);
+               gatorfs_create_ro_ulong(sb, dir, "key", &meminfo_keys[i]);
+       }
+
+       for (i = 0; i < PROC_COUNT; ++i) {
+               dir = gatorfs_mkdir(sb, root, proc_names[i]);
                if (!dir) {
                        return -1;
                }
-               gatorfs_create_ulong(sb, dir, "enabled", &meminfo_enabled[i]);
-               gatorfs_create_ro_ulong(sb, dir, "key", &meminfo_key[i]);
+               gatorfs_create_ulong(sb, dir, "enabled", &proc_enabled[i]);
+               gatorfs_create_ro_ulong(sb, dir, "key", &proc_keys[i]);
        }
 
        return 0;
@@ -86,13 +118,26 @@ static int gator_events_meminfo_start(void)
 {
        int i;
 
-       new_data_avail = true;
+       new_data_avail = false;
+       meminfo_global_enabled = 0;
        for (i = 0; i < MEMINFO_TOTAL; i++) {
                if (meminfo_enabled[i]) {
                        meminfo_global_enabled = 1;
+                       break;
                }
        }
 
+       proc_global_enabled = 0;
+       for (i = 0; i < PROC_COUNT; ++i) {
+               if (proc_enabled[i]) {
+                       proc_global_enabled = 1;
+                       break;
+               }
+       }
+       if (meminfo_enabled[MEMINFO_MEMUSED]) {
+               proc_global_enabled = 1;
+       }
+
        if (meminfo_global_enabled == 0)
                return 0;
 
@@ -111,9 +156,16 @@ static int gator_events_meminfo_start(void)
        if (GATOR_REGISTER_TRACE(mm_page_alloc))
                goto mm_page_alloc_exit;
 
-       setup_timer(&meminfo_wake_up_timer, meminfo_wake_up_handler, 0);
+       // Start worker thread
+       gator_meminfo_run = true;
+       // Since the mutex starts unlocked, memory values will be initialized
+       if (IS_ERR(kthread_run(gator_meminfo_func, NULL, "gator_meminfo")))
+               goto kthread_run_exit;
+
        return 0;
 
+kthread_run_exit:
+       GATOR_UNREGISTER_TRACE(mm_page_alloc);
 mm_page_alloc_exit:
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
        GATOR_UNREGISTER_TRACE(mm_pagevec_free);
@@ -132,8 +184,6 @@ mm_page_free_exit:
 
 static void gator_events_meminfo_stop(void)
 {
-       int i;
-
        if (meminfo_global_enabled) {
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
                GATOR_UNREGISTER_TRACE(mm_page_free_direct);
@@ -144,68 +194,75 @@ static void gator_events_meminfo_stop(void)
 #endif
                GATOR_UNREGISTER_TRACE(mm_page_alloc);
 
-               del_timer_sync(&meminfo_wake_up_timer);
-       }
-
-       meminfo_global_enabled = 0;
-       for (i = 0; i < MEMINFO_TOTAL; i++) {
-               meminfo_enabled[i] = 0;
+               // Stop worker thread
+               gator_meminfo_run = false;
+               up(&gator_meminfo_sem);
        }
 }
 
 // Must be run in process context as the kernel function si_meminfo() can sleep
-static void wq_sched_handler(struct work_struct *wsptr)
+static int gator_meminfo_func(void *data)
 {
        struct sysinfo info;
        int i, len;
        unsigned long long value;
 
-       meminfo_length = len = 0;
+       for (;;) {
+               if (down_killable(&gator_meminfo_sem)) {
+                       break;
+               }
 
-       si_meminfo(&info);
-       for (i = 0; i < MEMINFO_TOTAL; i++) {
-               if (meminfo_enabled[i]) {
-                       switch (i) {
-                       case MEMINFO_MEMFREE:
-                               value = info.freeram * PAGE_SIZE;
-                               break;
-                       case MEMINFO_MEMUSED:
-                               value = (info.totalram - info.freeram) * PAGE_SIZE;
-                               break;
-                       case MEMINFO_BUFFERRAM:
-                               value = info.bufferram * PAGE_SIZE;
-                               break;
-                       default:
-                               value = 0;
-                               break;
+               // Eat up any pending events
+               while (!down_trylock(&gator_meminfo_sem));
+
+               if (!gator_meminfo_run) {
+                       break;
+               }
+
+               meminfo_length = len = 0;
+
+               si_meminfo(&info);
+               for (i = 0; i < MEMINFO_TOTAL; i++) {
+                       if (meminfo_enabled[i]) {
+                               switch (i) {
+                               case MEMINFO_MEMFREE:
+                                       value = info.freeram * PAGE_SIZE;
+                                       break;
+                               case MEMINFO_MEMUSED:
+                                       // pid -1 means system wide
+                                       meminfo_buffer[len++] = 1;
+                                       meminfo_buffer[len++] = -1;
+                                       // Emit value
+                                       meminfo_buffer[len++] = meminfo_keys[MEMINFO_MEMUSED];
+                                       meminfo_buffer[len++] = (info.totalram - info.freeram) * PAGE_SIZE;
+                                       // Clear pid
+                                       meminfo_buffer[len++] = 1;
+                                       meminfo_buffer[len++] = 0;
+                                       continue;
+                               case MEMINFO_BUFFERRAM:
+                                       value = info.bufferram * PAGE_SIZE;
+                                       break;
+                               default:
+                                       value = 0;
+                                       break;
+                               }
+                               meminfo_buffer[len++] = meminfo_keys[i];
+                               meminfo_buffer[len++] = value;
                        }
-                       meminfo_buffer[len++] = (unsigned long long)meminfo_key[i];
-                       meminfo_buffer[len++] = value;
                }
-       }
 
-       meminfo_length = len;
-       new_data_avail = true;
-}
+               meminfo_length = len;
+               new_data_avail = true;
+       }
 
-static void meminfo_wake_up_handler(unsigned long unused_data)
-{
-       // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
-       schedule_work(&work);
+       return 0;
 }
 
 static int gator_events_meminfo_read(long long **buffer)
 {
-       static unsigned int last_mem_event = 0;
-
        if (!on_primary_core() || !meminfo_global_enabled)
                return 0;
 
-       if (last_mem_event != mem_event) {
-               last_mem_event = mem_event;
-               mod_timer(&meminfo_wake_up_timer, jiffies + 1);
-       }
-
        if (!new_data_avail)
                return 0;
 
@@ -217,11 +274,97 @@ static int gator_events_meminfo_read(long long **buffer)
        return meminfo_length;
 }
 
+static int gator_events_meminfo_read_proc(long long **buffer, struct task_struct *task)
+{
+       struct mm_struct *mm;
+       u64 share = 0;
+       int i;
+       long long value;
+       int len = 0;
+       int cpu = get_physical_cpu();
+       long long *buf = per_cpu(proc_buffer, cpu);
+
+       if (!proc_global_enabled) {
+               return 0;
+       }
+
+       // Collect the memory stats of the process instead of the thread
+       if (task->group_leader != NULL) {
+               task = task->group_leader;
+       }
+
+       // 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
+       mm = task->mm;
+       if (mm == NULL) {
+               return 0;
+       }
+
+       // Derived from task_statm in fs/proc/task_mmu.c
+       if (meminfo_enabled[MEMINFO_MEMUSED] || proc_enabled[PROC_SHARE]) {
+               share = get_mm_counter(mm,
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 32)
+                                                          file_rss
+#else
+                                                          MM_FILEPAGES
+#endif
+                                                          );
+       }
+
+       // key of 1 indicates a pid
+       buf[len++] = 1;
+       buf[len++] = task->pid;
+
+       for (i = 0; i < PROC_COUNT; ++i) {
+               if (proc_enabled[i]) {
+                       switch (i) {
+                       case PROC_SIZE:
+                               value = mm->total_vm;
+                               break;
+                       case PROC_SHARE:
+                               value = share;
+                               break;
+                       case PROC_TEXT:
+                               value = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> PAGE_SHIFT;
+                               break;
+                       case PROC_DATA:
+                               value = mm->total_vm - mm->shared_vm;
+                               break;
+                       }
+
+                       buf[len++] = proc_keys[i];
+                       buf[len++] = value * PAGE_SIZE;
+               }
+       }
+
+       if (meminfo_enabled[MEMINFO_MEMUSED]) {
+               value = share + get_mm_counter(mm,
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 32)
+                                                                          anon_rss
+#else
+                                                                          MM_ANONPAGES
+#endif
+                                                                          );
+               // Send resident for this pid
+               buf[len++] = meminfo_keys[MEMINFO_MEMUSED];
+               buf[len++] = value * PAGE_SIZE;
+       }
+
+       // Clear pid
+       buf[len++] = 1;
+       buf[len++] = 0;
+
+       if (buffer)
+               *buffer = buf;
+
+       return len;
+}
+
 static struct gator_interface gator_events_meminfo_interface = {
        .create_files = gator_events_meminfo_create_files,
        .start = gator_events_meminfo_start,
        .stop = gator_events_meminfo_stop,
        .read64 = gator_events_meminfo_read,
+       .read_proc = gator_events_meminfo_read_proc,
 };
 
 int gator_events_meminfo_init(void)
@@ -231,10 +374,14 @@ int gator_events_meminfo_init(void)
        meminfo_global_enabled = 0;
        for (i = 0; i < MEMINFO_TOTAL; i++) {
                meminfo_enabled[i] = 0;
-               meminfo_key[i] = gator_events_get_key();
+               meminfo_keys[i] = gator_events_get_key();
+       }
+
+       proc_global_enabled = 0;
+       for (i = 0; i < PROC_COUNT; ++i) {
+               proc_enabled[i] = 0;
+               proc_keys[i] = gator_events_get_key();
        }
 
        return gator_events_install(&gator_events_meminfo_interface);
 }
-
-gator_events_init(gator_events_meminfo_init);
similarity index 56%
rename from driver/gator_events_mmaped.c
rename to driver/gator_events_mmapped.c
index f7670f62a2580bd3220adfde265c954bd654cd6d..f055e48d317adaa1c1c9c07ceda8f2614ecfca0b 100644 (file)
  * To add them to the events.xml, create an events-mmap.xml with the 
  * following contents and rebuild gatord:
  *
- * <counter_set name="mmaped_cnt" count="3"/>
- * <category name="mmaped" counter_set="mmaped_cnt" per_cpu="no">
+ * <counter_set name="mmapped_cnt" count="3"/>
+ * <category name="mmapped" counter_set="mmapped_cnt" per_cpu="no">
  *   <event event="0x0" title="Simulated1" name="Sine" display="maximum" average_selection="yes" description="Sort-of-sine"/>
  *   <event event="0x1" title="Simulated2" name="Triangle" display="maximum" average_selection="yes" description="Triangular wave"/>
  *   <event event="0x2" title="Simulated3" name="PWM" display="maximum" average_selection="yes" description="PWM Signal"/>
  * </category>
+ *
+ * When adding custom events, be sure do the following
+ * - add any needed .c files to the gator driver Makefile
+ * - call gator_events_install in the events init function
+ * - add the init function to GATOR_EVENTS_LIST in gator_main.c
+ * - add a new events-*.xml file to the gator daemon and rebuild
  */
 
 #include <linux/init.h>
 
 #include "gator.h"
 
-#define MMAPED_COUNTERS_NUM 3
+#define MMAPPED_COUNTERS_NUM 3
+
+static int mmapped_global_enabled;
 
 static struct {
        unsigned long enabled;
        unsigned long event;
        unsigned long key;
-} mmaped_counters[MMAPED_COUNTERS_NUM];
+} mmapped_counters[MMAPPED_COUNTERS_NUM];
 
-static int mmaped_buffer[MMAPED_COUNTERS_NUM * 2];
+static int mmapped_buffer[MMAPPED_COUNTERS_NUM * 2];
 
-#ifdef TODO
-static void __iomem *mmaped_base;
-#endif
-
-#ifndef TODO
 static s64 prev_time;
-#endif
 
-/* Adds mmaped_cntX directories and enabled, event, and key files to /dev/gator/events */
-static int gator_events_mmaped_create_files(struct super_block *sb,
+/* Adds mmapped_cntX directories and enabled, event, and key files to /dev/gator/events */
+static int gator_events_mmapped_create_files(struct super_block *sb,
                                            struct dentry *root)
 {
        int i;
 
-       for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
+       for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) {
                char buf[16];
                struct dentry *dir;
 
-               snprintf(buf, sizeof(buf), "mmaped_cnt%d", i);
+               snprintf(buf, sizeof(buf), "mmapped_cnt%d", i);
                dir = gatorfs_mkdir(sb, root, buf);
                if (WARN_ON(!dir))
                        return -1;
                gatorfs_create_ulong(sb, dir, "enabled",
-                                    &mmaped_counters[i].enabled);
+                                    &mmapped_counters[i].enabled);
                gatorfs_create_ulong(sb, dir, "event",
-                                    &mmaped_counters[i].event);
+                                    &mmapped_counters[i].event);
                gatorfs_create_ro_ulong(sb, dir, "key",
-                                       &mmaped_counters[i].key);
+                                       &mmapped_counters[i].key);
        }
 
        return 0;
 }
 
-static int gator_events_mmaped_start(void)
+static int gator_events_mmapped_start(void)
 {
-#ifdef TODO
-       for (i = 0; i < MMAPED_COUNTERS_NUM; i++)
-               writel(mmaped_counters[i].event,
-                      mmaped_base + COUNTERS_CONFIG_OFFSET[i]);
-
-       writel(ENABLED, COUNTERS_CONTROL_OFFSET);
-#endif
-
-#ifndef TODO
+       int i;
        struct timespec ts;
+
        getnstimeofday(&ts);
        prev_time = timespec_to_ns(&ts);
-#endif
+
+       mmapped_global_enabled = 0;
+       for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) {
+               if (mmapped_counters[i].enabled) {
+                       mmapped_global_enabled = 1;
+                       break;
+               }
+       }
 
        return 0;
 }
 
-static void gator_events_mmaped_stop(void)
+static void gator_events_mmapped_stop(void)
 {
-#ifdef TODO
-       writel(DISABLED, COUNTERS_CONTROL_OFFSET);
-#endif
 }
 
-#ifndef TODO
 /* This function "simulates" counters, generating values of fancy
  * functions like sine or triangle... */
-static int mmaped_simulate(int counter, int delta_in_us)
+static int mmapped_simulate(int counter, int delta_in_us)
 {
        int result = 0;
 
@@ -157,73 +155,55 @@ static int mmaped_simulate(int counter, int delta_in_us)
 
        return result;
 }
-#endif
 
-static int gator_events_mmaped_read(int **buffer)
+static int gator_events_mmapped_read(int **buffer)
 {
        int i;
        int len = 0;
-#ifndef TODO
        int delta_in_us;
        struct timespec ts;
        s64 time;
-#endif
 
        /* System wide counters - read from one core only */
-       if (!on_primary_core())
+       if (!on_primary_core() || !mmapped_global_enabled)
                return 0;
 
-#ifndef TODO
        getnstimeofday(&ts);
        time = timespec_to_ns(&ts);
        delta_in_us = (int)(time - prev_time) / 1000;
        prev_time = time;
-#endif
-
-       for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
-               if (mmaped_counters[i].enabled) {
-                       mmaped_buffer[len++] = mmaped_counters[i].key;
-#ifdef TODO
-                       mmaped_buffer[len++] =
-                           readl(mmaped_base + COUNTERS_VALUE_OFFSET[i]);
-#else
-                       mmaped_buffer[len++] =
-                           mmaped_simulate(mmaped_counters[i].event,
+
+       for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) {
+               if (mmapped_counters[i].enabled) {
+                       mmapped_buffer[len++] = mmapped_counters[i].key;
+                       mmapped_buffer[len++] =
+                           mmapped_simulate(mmapped_counters[i].event,
                                            delta_in_us);
-#endif
                }
        }
 
        if (buffer)
-               *buffer = mmaped_buffer;
+               *buffer = mmapped_buffer;
 
        return len;
 }
 
-static struct gator_interface gator_events_mmaped_interface = {
-       .create_files = gator_events_mmaped_create_files,
-       .start = gator_events_mmaped_start,
-       .stop = gator_events_mmaped_stop,
-       .read = gator_events_mmaped_read,
+static struct gator_interface gator_events_mmapped_interface = {
+       .create_files = gator_events_mmapped_create_files,
+       .start = gator_events_mmapped_start,
+       .stop = gator_events_mmapped_stop,
+       .read = gator_events_mmapped_read,
 };
 
 /* Must not be static! */
-int __init gator_events_mmaped_init(void)
+int __init gator_events_mmapped_init(void)
 {
        int i;
 
-#ifdef TODO
-       mmaped_base = ioremap(COUNTERS_PHYS_ADDR, SZ_4K);
-       if (!mmaped_base)
-               return -ENOMEM;
-#endif
-
-       for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
-               mmaped_counters[i].enabled = 0;
-               mmaped_counters[i].key = gator_events_get_key();
+       for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) {
+               mmapped_counters[i].enabled = 0;
+               mmapped_counters[i].key = gator_events_get_key();
        }
 
-       return gator_events_install(&gator_events_mmaped_interface);
+       return gator_events_install(&gator_events_mmapped_interface);
 }
-
-gator_events_init(gator_events_mmaped_init);
index 80cdee41ae3d620dbec0fa0f470b7f8721e39931..9c8d3a43eaebd408ad7be01f66516ef83ddc7b8f 100644 (file)
@@ -73,6 +73,8 @@ static void calculate_delta(int *rx, int *tx)
 
 static int gator_events_net_create_files(struct super_block *sb, struct dentry *root)
 {
+       // Network counters are not currently supported in RT-Preempt full because mod_timer is used
+#ifndef CONFIG_PREEMPT_RT_FULL
        struct dentry *dir;
 
        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 *
        }
        gatorfs_create_ulong(sb, dir, "enabled", &nettx_enabled);
        gatorfs_create_ro_ulong(sb, dir, "key", &nettx_key);
+#endif
 
        return 0;
 }
@@ -167,5 +170,3 @@ int gator_events_net_init(void)
 
        return gator_events_install(&gator_events_net_interface);
 }
-
-gator_events_init(gator_events_net_init);
index 53b2d0a5afbffa55e8974c6d6ec4859b3a9957cc..d472df918ab0f88069101261e35cc777efc125b7 100644 (file)
@@ -6,13 +6,18 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/slab.h>
-#include <linux/perf_event.h>
 #include "gator.h"
 
 // gator_events_armvX.c is used for Linux 2.6.x
 #if GATOR_PERF_PMU_SUPPORT
 
+#include <linux/io.h>
+#ifdef CONFIG_OF
+#include <linux/of_address.h>
+#endif
+#include <linux/perf_event.h>
+#include <linux/slab.h>
+
 extern bool event_based_sampling;
 
 // 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;
 // + 1 for the cci-400 cycles counter
 #define UCCNT (CCI_400 + 1)
 
+// Default to 0 if unable to probe the revision which was the previous behavior
+#define DEFAULT_CCI_REVISION 0
+
 // A gator_attr is needed for every counter
 struct gator_attr {
        // 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)
        attr->key = gator_events_get_key();
 }
 
+#ifdef CONFIG_OF
+
+static const struct of_device_id arm_cci_matches[] = {
+       {.compatible = "arm,cci-400" },
+       {},
+};
+
+static int probe_cci_revision(void)
+{
+       struct device_node *np;
+       struct resource res;
+       void __iomem *cci_ctrl_base;
+       int rev;
+       int ret = DEFAULT_CCI_REVISION;
+
+       np = of_find_matching_node(NULL, arm_cci_matches);
+       if (!np) {
+               return ret;
+       }
+
+       if (of_address_to_resource(np, 0, &res)) {
+               goto node_put;
+       }
+
+       cci_ctrl_base = ioremap(res.start, resource_size(&res));
+
+       rev = (readl_relaxed(cci_ctrl_base + 0xfe8) >> 4) & 0xf;
+
+       if (rev <= 4) {
+               ret = 0;
+       } else if (rev <= 6) {
+               ret = 1;
+       }
+
+       iounmap(cci_ctrl_base);
+
+ node_put:
+       of_node_put(np);
+
+       return ret;
+}
+
+#else
+
+static int probe_cci_revision(void)
+{
+       return DEFAULT_CCI_REVISION;
+}
+
+#endif
+
 static void gator_events_perf_pmu_cci_init(const int type)
 {
        int cnt;
+       const char *cci_name;
+
+       switch (probe_cci_revision()) {
+       case 0:
+               cci_name = "cci-400";
+               break;
+       case 1:
+               cci_name = "cci-400-r1";
+               break;
+       default:
+               pr_debug("gator: unrecognized cci-400 revision\n");
+               return;
+       }
 
-       strncpy(uc_attrs[uc_attr_count].name, "cci-400_ccnt", sizeof(uc_attrs[uc_attr_count].name));
+       snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", cci_name);
        uc_attrs[uc_attr_count].type = type;
        ++uc_attr_count;
 
        for (cnt = 0; cnt < CCI_400; ++cnt, ++uc_attr_count) {
                struct gator_attr *const attr = &uc_attrs[uc_attr_count];
-               snprintf(attr->name, sizeof(attr->name), "cci-400_cnt%d", cnt);
+               snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", cci_name, cnt);
                attr->type = type;
        }
 }
@@ -477,7 +549,7 @@ int gator_events_perf_pmu_init(void)
                }
 
                if (pe->pmu != NULL && type == pe->pmu->type) {
-                       if (strcmp("CCI", pe->pmu->name) == 0) {
+                       if (strcmp("CCI", pe->pmu->name) == 0 || strcmp("CCI_400", pe->pmu->name) == 0) {
                                gator_events_perf_pmu_cci_init(type);
                        } else if ((gator_cpu = gator_find_cpu_by_pmu_name(pe->pmu->name)) != NULL) {
                                found_cpu = true;
@@ -512,5 +584,4 @@ int gator_events_perf_pmu_init(void)
        return gator_events_install(&gator_events_perf_pmu_interface);
 }
 
-gator_events_init(gator_events_perf_pmu_init);
 #endif
index 461a0511143d77ba99cb046909efe70b465ba606..29f4e39e261c4214413dbf799cc8fcd91c4fd2f7 100644 (file)
@@ -111,5 +111,3 @@ int gator_events_sched_init(void)
 
        return gator_events_install(&gator_events_sched_interface);
 }
-
-gator_events_init(gator_events_sched_init);
index aaf306a4b4c8c5cbc2b15d6ae13e6d240b50c087..c91db1219d080b62aa9585f8530a451b7c981863 100644 (file)
@@ -666,11 +666,4 @@ int gator_events_scorpion_init(void)
        return gator_events_install(&gator_events_scorpion_interface);
 }
 
-gator_events_init(gator_events_scorpion_init);
-
-#else
-int gator_events_scorpion_init(void)
-{
-       return -1;
-}
 #endif
index ead7eae4ae41f7c3a3e93e4b0c8a5d4e545aa4e0..9773ae24d6f2d5345ea0bd0946eb5b32418c0d4b 100644 (file)
@@ -8,7 +8,8 @@
  */
 
 // This version must match the gator daemon version
-static unsigned long gator_protocol_version = 16;
+#define PROTOCOL_VERSION 17
+static unsigned long gator_protocol_version = PROTOCOL_VERSION;
 
 #include <linux/slab.h>
 #include <linux/cpu.h>
@@ -22,16 +23,20 @@ static unsigned long gator_protocol_version = 16;
 #include <linux/module.h>
 #include <linux/perf_event.h>
 #include <linux/utsname.h>
+#include <linux/kthread.h>
 #include <asm/stacktrace.h>
 #include <asm/uaccess.h>
 
 #include "gator.h"
-#include "gator_events.h"
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
 #error kernels prior to 2.6.32 are not supported
 #endif
 
+#if defined(MODULE) && !defined(CONFIG_MODULES)
+#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.
+#endif
+
 #if !defined(CONFIG_GENERIC_TRACER) && !defined(CONFIG_TRACING)
 #error gator requires the kernel to have CONFIG_GENERIC_TRACER or CONFIG_TRACING defined
 #endif
@@ -44,17 +49,15 @@ static unsigned long gator_protocol_version = 16;
 #error gator requires the kernel to have CONFIG_HIGH_RES_TIMERS defined to support PC sampling
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) /* Because CONFIG_LOCAL_TIMERS was removed in 3.12 */
-#if defined(__arm__) && defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && defined(__arm__) && defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
 #error gator requires the kernel to have CONFIG_LOCAL_TIMERS defined on SMP systems
 #endif
-#endif
 
 #if (GATOR_PERF_SUPPORT) && (!(GATOR_PERF_PMU_SUPPORT))
 #ifndef CONFIG_PERF_EVENTS
-#warning gator requires the kernel to have CONFIG_PERF_EVENTS defined to support pmu hardware counters
+#error gator requires the kernel to have CONFIG_PERF_EVENTS defined to support pmu hardware counters
 #elif !defined CONFIG_HW_PERF_EVENTS
-#warning gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters
+#error gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters
 #endif
 #endif
 
@@ -89,6 +92,7 @@ static unsigned long gator_protocol_version = 16;
 #define MESSAGE_COOKIE      1
 #define MESSAGE_THREAD_NAME 2
 #define HRTIMER_CORE_NAME   3
+#define MESSAGE_LINK        4
 
 #define MESSAGE_GPU_START 1
 #define MESSAGE_GPU_STOP  2
@@ -138,6 +142,7 @@ static u64 gator_live_rate;
 
 static unsigned long gator_started;
 static u64 gator_monotonic_started;
+static u64 gator_hibernate_time;
 static unsigned long gator_buffer_opened;
 static unsigned long gator_timer_count;
 static unsigned long gator_response_type;
@@ -149,6 +154,8 @@ bool event_based_sampling;
 static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
 static DECLARE_WAIT_QUEUE_HEAD(gator_annotate_wait);
 static struct timer_list gator_buffer_wake_up_timer;
+static bool gator_buffer_wake_stop;
+static struct task_struct *gator_buffer_wake_thread;
 static LIST_HEAD(gator_events);
 
 static DEFINE_PER_CPU(u64, last_timestamp);
@@ -191,6 +198,34 @@ static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer);
 // The time after which the buffer should be committed for live display
 static DEFINE_PER_CPU(u64, gator_buffer_commit_time);
 
+// List of all gator events - new events must be added to this list
+#define GATOR_EVENTS_LIST \
+       GATOR_EVENT(gator_events_armv6_init) \
+       GATOR_EVENT(gator_events_armv7_init) \
+       GATOR_EVENT(gator_events_block_init) \
+       GATOR_EVENT(gator_events_ccn504_init) \
+       GATOR_EVENT(gator_events_irq_init) \
+       GATOR_EVENT(gator_events_l2c310_init) \
+       GATOR_EVENT(gator_events_mali_init) \
+       GATOR_EVENT(gator_events_mali_t6xx_hw_init) \
+       GATOR_EVENT(gator_events_mali_t6xx_init) \
+       GATOR_EVENT(gator_events_meminfo_init) \
+       GATOR_EVENT(gator_events_mmapped_init) \
+       GATOR_EVENT(gator_events_net_init) \
+       GATOR_EVENT(gator_events_perf_pmu_init) \
+       GATOR_EVENT(gator_events_sched_init) \
+       GATOR_EVENT(gator_events_scorpion_init) \
+
+#define GATOR_EVENT(EVENT_INIT) __weak int EVENT_INIT(void);
+GATOR_EVENTS_LIST
+#undef GATOR_EVENT
+
+static int (*gator_events_list[])(void) = {
+#define GATOR_EVENT(EVENT_INIT) EVENT_INIT,
+GATOR_EVENTS_LIST
+#undef GATOR_EVENT
+};
+
 /******************************************************************************
  * Application Includes
  ******************************************************************************/
@@ -394,6 +429,21 @@ static void gator_buffer_wake_up(unsigned long data)
        wake_up(&gator_buffer_wait);
 }
 
+static int gator_buffer_wake_func(void *data)
+{
+       while (!gator_buffer_wake_stop) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule();
+               if (gator_buffer_wake_stop) {
+                       break;
+               }
+
+               gator_buffer_wake_up(0);
+       }
+
+       return 0;
+}
+
 /******************************************************************************
  * Commit interface
  ******************************************************************************/
@@ -519,7 +569,14 @@ static void gator_commit_buffer(int cpu, int buftype, u64 time)
        marshal_frame(cpu, buftype);
 
        // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
-       mod_timer(&gator_buffer_wake_up_timer, jiffies + 1);
+       if (per_cpu(in_scheduler_context, cpu)) {
+#ifndef CONFIG_PREEMPT_RT_FULL
+               // mod_timer can not be used in interrupt context in RT-Preempt full
+               mod_timer(&gator_buffer_wake_up_timer, jiffies + 1);
+#endif
+       } else {
+               wake_up_process(gator_buffer_wake_thread);
+       }
 }
 
 static void buffer_check(int cpu, int buftype, u64 time)
@@ -592,8 +649,13 @@ void gator_backtrace_handler(struct pt_regs *const regs)
 
        // Collect counters
        if (!per_cpu(collecting, cpu)) {
-               collect_counters(time);
+               collect_counters(time, NULL);
        }
+
+       // 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
+#ifdef CONFIG_PREEMPT_RT_FULL
+       buffer_check(cpu, SCHED_TRACE_BUF, time);
+#endif
 }
 
 static int gator_running;
@@ -817,6 +879,7 @@ static struct notifier_block __refdata gator_hotcpu_notifier = {
 static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy)
 {
        int cpu;
+       struct timespec ts;
 
        switch (event) {
        case PM_HIBERNATION_PREPARE:
@@ -827,9 +890,20 @@ static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void
                for_each_online_cpu(cpu) {
                        gator_timer_offline_dispatch(lcpu_to_pcpu(cpu), false);
                }
+
+               // Record the wallclock hibernate time
+               getnstimeofday(&ts);
+               gator_hibernate_time = timespec_to_ns(&ts) - gator_get_time();
                break;
        case PM_POST_HIBERNATION:
        case PM_POST_SUSPEND:
+               // Adjust gator_monotonic_started for the time spent sleeping, as gator_get_time does not account for it
+               if (gator_hibernate_time > 0) {
+                       getnstimeofday(&ts);
+                       gator_monotonic_started += gator_hibernate_time + gator_get_time() - timespec_to_ns(&ts);
+                       gator_hibernate_time = 0;
+               }
+
                for_each_online_cpu(cpu) {
                        gator_timer_online_dispatch(lcpu_to_pcpu(cpu), false);
                }
@@ -904,8 +978,10 @@ int gator_events_install(struct gator_interface *interface)
 
 int gator_events_get_key(void)
 {
-       // key of zero is reserved as a timestamp
-       static int key = 1;
+       // key 0 is reserved as a timestamp
+       // key 1 is reserved as the marker for thread specific counters
+       // Odd keys are assigned by the driver, even keys by the daemon
+       static int key = 3;
 
        const int ret = key;
        key += 2;
@@ -918,7 +994,7 @@ static int gator_init(void)
 
        calc_first_cluster_size();
 
-       // events sources (gator_events.h, generated by gator_events.sh)
+       // events sources
        for (i = 0; i < ARRAY_SIZE(gator_events_list); i++)
                if (gator_events_list[i])
                        gator_events_list[i]();
@@ -943,6 +1019,11 @@ static int gator_start(void)
        unsigned long cpu, i;
        struct gator_interface *gi;
 
+       gator_buffer_wake_stop = false;
+       if (IS_ERR(gator_buffer_wake_thread = kthread_run(gator_buffer_wake_func, NULL, "gator_bwake"))) {
+               goto bwake_failure;
+       }
+
        if (gator_migrate_start())
                goto migrate_failure;
 
@@ -1013,6 +1094,9 @@ cookies_failure:
 events_failure:
        gator_migrate_stop();
 migrate_failure:
+       gator_buffer_wake_stop = true;
+       wake_up_process(gator_buffer_wake_thread);
+bwake_failure:
 
        return -1;
 }
@@ -1036,6 +1120,9 @@ static void gator_stop(void)
                        gi->stop();
 
        gator_migrate_stop();
+
+       gator_buffer_wake_stop = true;
+       wake_up_process(gator_buffer_wake_thread);
 }
 
 /******************************************************************************
@@ -1440,3 +1527,6 @@ module_exit(gator_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("ARM Ltd");
 MODULE_DESCRIPTION("Gator system profiler");
+#define STRIFY2(ARG) #ARG
+#define STRIFY(ARG) STRIFY2(ARG)
+MODULE_VERSION(STRIFY(PROTOCOL_VERSION));
index 3282de843f7154558b8bc604b1c903895c570283..af80ff62e712c4e423ebea24af6cc08addd2a80a 100644 (file)
@@ -89,6 +89,25 @@ static void marshal_thread_name(int pid, char *name)
        local_irq_restore(flags);
 }
 
+static void marshal_link(int cookie, int tgid, int pid)
+{
+       unsigned long cpu = get_physical_cpu(), flags;
+       u64 time;
+
+       local_irq_save(flags);
+       time = gator_get_time();
+       if (buffer_check_space(cpu, NAME_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
+               gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_LINK);
+               gator_buffer_write_packed_int64(cpu, NAME_BUF, time);
+               gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
+               gator_buffer_write_packed_int(cpu, NAME_BUF, tgid);
+               gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
+       }
+       // Check and commit; commit is set to occur once buffer is 3/4 full
+       buffer_check(cpu, NAME_BUF, time);
+       local_irq_restore(flags);
+}
+
 static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel, u64 time)
 {
        int cpu = get_physical_cpu();
index 12623c4036ee02f4b60ad63ae3025407620b64fd..be135b4aac563bbdabac6266383ca93c88054f27 100644 (file)
@@ -85,7 +85,7 @@ static void mali_gpu_stop(int unit, int core)
        int count;
        int last_tgid = 0;
        int last_pid = 0;
-       int last_job_id = 0;
+       //int last_job_id = 0;
 
        spin_lock(&mali_gpu_jobs_lock);
        if (mali_gpu_jobs[unit][core].count == 0) {
@@ -97,7 +97,7 @@ static void mali_gpu_stop(int unit, int core)
        if (count) {
                last_tgid = mali_gpu_jobs[unit][core].last_tgid;
                last_pid = mali_gpu_jobs[unit][core].last_pid;
-               last_job_id = mali_gpu_jobs[unit][core].last_job_id;
+               //last_job_id = mali_gpu_jobs[unit][core].last_job_id;
        }
        spin_unlock(&mali_gpu_jobs_lock);
 
@@ -242,7 +242,7 @@ int gator_trace_gpu_start(void)
         * Absence of gpu trace points is not an error
         */
 
-       memset(&mali_gpu_jobs, sizeof(mali_gpu_jobs), 0);
+       memset(&mali_gpu_jobs, 0, sizeof(mali_gpu_jobs));
        gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
 
 #if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
index e98815e25b9ccc5c9a5e0ca3f699dfdb04e18e9d..332b3f6ba965d99f6ab2dfc18255821028532ff2 100644 (file)
@@ -22,6 +22,7 @@ enum {
 
 static DEFINE_PER_CPU(uint64_t *, taskname_keys);
 static DEFINE_PER_CPU(int, collecting);
+static DEFINE_PER_CPU(bool, in_scheduler_context);
 
 // this array is never read as the cpu wait charts are derived counters
 // the files are needed, nonetheless, to show that these counters are available
@@ -89,7 +90,7 @@ void emit_pid_name(struct task_struct *task)
        }
 }
 
-static void collect_counters(u64 time)
+static void collect_counters(u64 time, struct task_struct *task)
 {
        int *buffer, len, cpu = get_physical_cpu();
        long long *buffer64;
@@ -104,17 +105,26 @@ static void collect_counters(u64 time)
                                len = gi->read64(&buffer64);
                                marshal_event64(len, buffer64);
                        }
+                       if (gi->read_proc && task != NULL) {
+                               len = gi->read_proc(&buffer64, task);
+                               marshal_event64(len, buffer64);
+                       }
                }
                // Only check after writing all counters so that time and corresponding counters appear in the same frame
                buffer_check(cpu, BLOCK_COUNTER_BUF, time);
 
                // Commit buffers on timeout
                if (gator_live_rate > 0 && time >= per_cpu(gator_buffer_commit_time, cpu)) {
-                       static const int buftypes[] = { COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF };
+                       static const int buftypes[] = { NAME_BUF, COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF };
+                       unsigned long flags;
                        int i;
+
+                       local_irq_save(flags);
                        for (i = 0; i < ARRAY_SIZE(buftypes); ++i) {
                                gator_commit_buffer(cpu, buftypes[i], time);
                        }
+                       local_irq_restore(flags);
+
                        // Try to preemptively flush the annotate buffer to reduce the chance of the buffer being full
                        if (on_primary_core() && spin_trylock(&annotate_lock)) {
                                gator_commit_buffer(0, ANNOTATE_BUF, time);
@@ -151,6 +161,8 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_
        int state;
        int cpu = get_physical_cpu();
 
+       per_cpu(in_scheduler_context, cpu) = true;
+
        // do as much work as possible before disabling interrupts
        cookie = get_exec_cookie(cpu, next);
        emit_pid_name(next);
@@ -163,10 +175,12 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_
        }
 
        per_cpu(collecting, cpu) = 1;
-       collect_counters(gator_get_time());
+       collect_counters(gator_get_time(), prev);
        per_cpu(collecting, cpu) = 0;
 
        marshal_sched_trace_switch(next->tgid, next->pid, cookie, state);
+
+       per_cpu(in_scheduler_context, cpu) = false;
 }
 
 GATOR_DEFINE_PROBE(sched_process_free, TP_PROTO(struct task_struct *p))
index 3db454371d59fec0304fface82f79f9c6ffdd552..347a4fe404bc8bd597d5365d9742aafa4c4c1be9 100644 (file)
@@ -1,11 +1,10 @@
-/*
- * This confidential and proprietary software may be used only as
- * authorised by a licensing agreement from ARM Limited
- * (C) COPYRIGHT 2013 ARM Limited
- * ALL RIGHTS RESERVED
- * The entire notice above must be reproduced on all authorised
- * copies and copies may only be made to the extent permitted
- * by a licensing agreement from ARM Limited.
+/**
+ * Copyright (C) ARM Limited 2013. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
  */
 
 #ifndef __MALI_MJOLLNIR_PROFILING_GATOR_API_H__
index c02a1a43efff4f0cf8630c656736de1a58ab4927..559647a76d29096980b44e8c752731e836804cee 100644 (file)
@@ -1,11 +1,10 @@
-/*
- * This confidential and proprietary software may be used only as
- * authorised by a licensing agreement from ARM Limited
- * (C) COPYRIGHT 2013 ARM Limited
- * ALL RIGHTS RESERVED
- * The entire notice above must be reproduced on all authorised
- * copies and copies may only be made to the extent permitted
- * by a licensing agreement from ARM Limited.
+/**
+ * Copyright (C) ARM Limited 2013. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
  */
 
 #ifndef __MALI_UTGARD_PROFILING_GATOR_API_H__
index 2cc64113ea2c575332ccbb5f58350db00a58617c..1a98c1c6a73fe3320b805ba41e834ad49dee9675 100644 (file)
@@ -9,16 +9,17 @@ EXTRA_CFLAGS += -DMALI_USE_UMP=1 \
                 -DMALI_BACKEND_KERNEL=1 \
                 -DMALI_NO_MALI=0
 
-KBASE_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase
-OSK_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase/osk
-UMP_DIR = $(DDK_DIR)/kernel/include/linux
+DDK_DIR ?= .
+KBASE_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase
+OSK_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase/osk
+UMP_DIR = $(DDK_DIR)/include/linux
 
 # Include directories in the DDK
-EXTRA_CFLAGS += -I$(DDK_DIR) \
+EXTRA_CFLAGS += -I$(KBASE_DIR)/ \
                 -I$(KBASE_DIR)/.. \
                 -I$(OSK_DIR)/.. \
                 -I$(UMP_DIR)/.. \
-                -I$(DDK_DIR)/kernel/include \
+                -I$(DDK_DIR)/include \
                 -I$(KBASE_DIR)/osk/src/linux/include \
                 -I$(KBASE_DIR)/platform_dummy \
                 -I$(KBASE_DIR)/src