aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README_Streamline.txt51
-rw-r--r--daemon/Android.mk6
-rw-r--r--daemon/Application.mk1
-rw-r--r--daemon/Buffer.cpp36
-rw-r--r--daemon/Buffer.h11
-rw-r--r--daemon/CapturedXML.cpp11
-rw-r--r--daemon/CapturedXML.h2
-rw-r--r--daemon/Child.cpp45
-rw-r--r--daemon/Child.h2
-rw-r--r--daemon/ConfigurationXML.cpp10
-rw-r--r--daemon/Counter.h4
-rw-r--r--daemon/DriverSource.cpp53
-rw-r--r--daemon/DriverSource.h5
-rw-r--r--daemon/EventsXML.cpp16
-rw-r--r--daemon/EventsXML.h5
-rw-r--r--daemon/ExternalSource.cpp177
-rw-r--r--daemon/ExternalSource.h11
-rw-r--r--daemon/FSDriver.cpp212
-rw-r--r--daemon/FSDriver.h44
-rw-r--r--daemon/Fifo.h2
-rw-r--r--daemon/Hwmon.cpp16
-rw-r--r--daemon/KMod.cpp11
-rw-r--r--daemon/LocalCapture.h2
-rw-r--r--daemon/Logging.h2
-rw-r--r--daemon/Makefile8
-rw-r--r--daemon/Makefile_aarch649
-rw-r--r--daemon/MaliVideoDriver.cpp253
-rw-r--r--daemon/MaliVideoDriver.h50
-rw-r--r--daemon/Monitor.cpp11
-rw-r--r--daemon/Monitor.h1
-rw-r--r--daemon/OlySocket.cpp77
-rw-r--r--daemon/OlySocket.h14
-rw-r--r--daemon/PerfDriver.cpp92
-rw-r--r--daemon/PerfDriver.h6
-rw-r--r--daemon/PerfGroup.cpp28
-rw-r--r--daemon/PerfGroup.h2
-rw-r--r--daemon/PerfSource.cpp14
-rw-r--r--daemon/Proc.cpp106
-rw-r--r--daemon/Proc.h2
-rw-r--r--daemon/Sender.h2
-rw-r--r--daemon/SessionData.cpp55
-rw-r--r--daemon/SessionData.h17
-rw-r--r--daemon/SessionXML.cpp8
-rw-r--r--daemon/StreamlineSetup.cpp2
-rw-r--r--daemon/StreamlineSetup.h4
-rw-r--r--daemon/UEvent.cpp3
-rw-r--r--daemon/UserSpaceSource.cpp14
-rw-r--r--daemon/UserSpaceSource.h2
-rw-r--r--daemon/c++.cpp40
-rw-r--r--daemon/common.mk16
-rw-r--r--daemon/defaults.xml5
-rw-r--r--daemon/escape.c2
-rw-r--r--daemon/events-CCI-400.xml21
-rw-r--r--daemon/events-CCN-504.xml9
-rw-r--r--daemon/events-Cortex-A53.xml84
-rw-r--r--daemon/events-Cortex-A57.xml84
-rw-r--r--daemon/events-Filesystem.xml11
-rw-r--r--daemon/events-L2C-310.xml30
-rw-r--r--daemon/events-Linux.xml5
-rw-r--r--daemon/events-Mali-4xx.xml126
-rw-r--r--daemon/events-Mali-T6xx.xml26
-rw-r--r--daemon/events-Mali-T6xx_hw.xml33
-rw-r--r--daemon/events-Mali-V500.xml29
-rw-r--r--daemon/main.cpp260
-rw-r--r--driver/Makefile15
-rw-r--r--driver/gator.h16
-rw-r--r--driver/gator_backtrace.c2
-rw-r--r--driver/gator_buffer.c6
-rw-r--r--driver/gator_events_armv7.c4
-rw-r--r--driver/gator_events_block.c12
-rw-r--r--driver/gator_events_mali_4xx.c144
-rw-r--r--driver/gator_events_mali_common.c36
-rw-r--r--driver/gator_events_mali_common.h20
-rw-r--r--driver/gator_events_mali_t6xx.c5
-rw-r--r--driver/gator_events_mali_t6xx_hw.c183
-rw-r--r--driver/gator_events_mmapped.c26
-rw-r--r--driver/gator_events_perf_pmu.c6
-rw-r--r--driver/gator_events_scorpion.c4
-rw-r--r--driver/gator_events_threads.c115
-rw-r--r--driver/gator_iks.c2
-rw-r--r--driver/gator_main.c126
-rw-r--r--driver/gator_marshaling.c101
-rw-r--r--driver/gator_trace_gpu.c178
-rw-r--r--driver/gator_trace_gpu.h79
-rw-r--r--driver/gator_trace_power.c4
-rw-r--r--driver/gator_trace_sched.c85
-rw-r--r--driver/mali/mali_dd_gator_api.h40
-rw-r--r--driver/mali_t6xx.mk4
88 files changed, 2347 insertions, 1162 deletions
diff --git a/README_Streamline.txt b/README_Streamline.txt
index df3f923..54791c0 100644
--- a/README_Streamline.txt
+++ b/README_Streamline.txt
@@ -2,7 +2,7 @@
*** Purpose ***
Instructions on setting up ARM Streamline on the target.
-The gator driver and gator daemon are required to run on the ARM Linux target in order for ARM Streamline to operate. A new early access feature allows the gator daemon can run without the gator driver by using userspace APIs with reduced functionality when using Linux 3.12 or later.
+The gator driver and gator daemon are required to run on the ARM Linux target in order for ARM Streamline to operate. A new early access feature allows the gator daemon can run without the gator driver by using userspace APIs with reduced functionality when using Linux 3.4 or later.
The driver should be built as a module and the daemon must run with root permissions on the target.
*** Introduction ***
@@ -14,7 +14,7 @@ A Linux development environment with cross compiling tools is most likely requir
-First, check if the kernel has the proper configuration options (see below). Profiling cannot occur using a kernel that is not configured properly, a new kernel must be created. See if /proc/config.gz exists on the target.
-Second, given a properly configured kernel, check if the filesystem contains the kernel source/headers, which can be used to re-create the gator driver. These files may be located in different areas, but common locations are /lib/modules/ and /usr/src.
-If the kernel is not properly configured or sources/headers are not available, the developer is on their own and kernel creation is beyond the scope of this document. Note: It is possible for a module to work when compiled against a similar kernel source code, though this is not guaranteed to work due to differences in kernel structures, exported symbols and incompatible configuration parameters.
- -If the target is running Linux 3.12 or later the kernel driver is not required and userspace APIs will be used instead.
+ -If the target is running Linux 3.4 or later the kernel driver is not required and userspace APIs will be used instead.
*** Kernel configuration ***
@@ -59,8 +59,7 @@ If a device tree is used it must include the pmu bindings, see Documentation/dev
*** Building the gator module ***
To create the gator.ko module,
- cd /path/to/gator/driver-src
- tar xzf gator-driver.tar.gz
+ tar xzf /path/to/DS-5/arm/gator/driver-src/gator-driver.tar.gz
cd gator-driver
make -C <kernel_build_dir> M=`pwd` ARCH=arm CROSS_COMPILE=<...> modules
for example when using the linaro-toolchain-binaries
@@ -78,10 +77,14 @@ Edit Kconfig in the kernel drivers folder and add this before the last endmenu
source "drivers/gator/Kconfig"
You can now select gator when using menuconfig while configuring the kernel and rebuild as directed
+*** Use the prebuilt gator daemon ***
+
+A prebuilt gator daemon is provided at /path/to/DS-5/arm/gator/gatord. This gator daemon should work in most cases so building the gator daemon is only required if the prebuilt gator daemon doesn't work.
+To improve portablility gatord is statically compiled against musl libc from http://www.musl-libc.org/releases/musl-1.0.2.tar.gz instead of glibc. The gator daemon will work correctly with either glibc or musl.
+
*** Building the gator daemon ***
-cd /path/to/gator/daemon-src
-tar -xzf gator-daemon.tar.gz (may need to issue with 'sudo')
+tar -xzf /path/to/DS-5/arm/gator/daemon-src/gator-daemon.tar.gz
For Linux targets,
cd gator-daemon
make CROSS_COMPILE=<...> # For ARMv7 targets
@@ -105,7 +108,7 @@ gator.ko must be located in the same directory as gatord on the target or the lo
With root privileges, run the daemon
sudo ./gatord &
Note: gatord requires libstdc++.so.6 which is usually supplied by the Linux distribution on the target. A copy of libstdc++.so.6 is available in the DS-5 Linux example distribution.
-If gator.ko is not loaded and is not in the same directory as gatord when using Linux 3.12 or later, gatord can run without gator.ko by using userspace APIs. Not all features are supported by userspace gator. If /dev/gator/version does not exist after starting gatord it is running userspace gator.
+If gator.ko is not loaded and is not in the same directory as gatord when using Linux 3.4 or later, gatord can run without gator.ko by using userspace APIs. Not all features are supported by userspace gator. If /dev/gator/version does not exist after starting gatord it is running userspace gator.
*** Customizing the l2c-310 Counter ***
@@ -123,7 +126,7 @@ CCN-504 is disabled by default. To enable CCN-504, insmod gator module with the
Recommended compiler settings:
"-g": Debug information, such as line numbers, needed for best analysis results.
"-fno-inline": Speed improvement when processing the image files and most accurate analysis results.
- "-fno-omit-frame-pointer": ARM EABI frame pointers (Code Sourcery cross compiler) allow recording of the call stack with each sample taken when in ARM state (i.e. not -mthumb).
+ "-fno-omit-frame-pointer": ARM EABI frame pointers allow recording of the call stack with each sample taken when in ARM state (i.e. not -mthumb).
"-marm": This option is required if your compiler is configured with --with-mode=thumb, otherwise call stack unwinding will not work.
*** Hardfloat EABI ***
@@ -132,6 +135,35 @@ To compile for non-hardfloat targets it is necessary to add options '-marm -marc
The armv5t_mtx filesystem is provided as part of the "DS-5 Linux Example Distribution" package which can be downloaded from the DS-5 Downloads page.
Attempting to run an incompatible binary often results in the confusing error message "No such file or directory" when clearly the file exists.
+*** Mali GPU ***
+
+Streamline supports Mali-400, 450, T6xx, and T7xx series GPUs with hardware activity charts, hardware & software counters and an optional 'film strip' showing periodic framebuffer snapshots. Support is chosen at build time and only one type of GPU (and version of driver) is supported at once. For best results build gator in-tree at .../drivers/gator and use the menuconfig options. Details of what these mean or how to build out of tree below.
+
+Mali-4xx:
+ ___To add Mali-4xx support to gator___
+ GATOR_WITH_MALI_SUPPORT=MALI_4xx # Set by CONFIG_GATOR_MALI_4XXMP
+ CONFIG_GATOR_MALI_PATH=".../path/to/Mali_DDK_kernel_files/src/devicedrv/mali" # gator source needs to #include "linux/mali_linux_trace.h"
+ GATOR_MALI_INTERFACE_STYLE=<3|4> # 3=Mali-400 DDK >= r3p0-04rel0 and < r3p2-01rel3
+ # 4=Mali-400 DDK >= r3p2-01rel3
+ # (default of 4 set in gator-driver/gator_events_mali_4xx.c)
+ ___To add the corresponding support to Mali___
+ Userspace needs MALI_TIMELINE_PROFILING_ENABLED=1 MALI_FRAMEBUFFER_DUMP_ENABLED=1 MALI_SW_COUNTERS_ENABLED=1
+ Kernel driver needs USING_PROFILING=1 # Sets CONFIG_MALI400_PROFILING=y
+ See the DDK integration guide for more details (the above are the default in later driver versions)
+
+Mali-T6xx/T7xx:
+ ___To add Mali-T6xx support to gator___
+ GATOR_WITH_MALI_SUPPORT=MALI_T6xx # Set by CONFIG_GATOR_MALI_T6XX
+ DDK_DIR=".../path/to/Mali_DDK_kernel_files" # gator source needs access to headers under .../kernel/drivers/gpu/arm/...
+ # (default of . suitable for in-tree builds)
+ ___To add the corresponding support to Mali___
+ Userspace (scons) needs gator=1
+ Kernel driver needs CONFIG_MALI_GATOR_SUPPORT=y
+ See the DDK integration guide for more details
+
+*** Polling /dev, /sys and /proc files ***
+Gator supports reading arbitrary /dev, /sys and /proc files 10 times a second. It will either interpret the file contents as a number or use a POSIX extended regex to extract the number, see events-Filesystem.xml for examples.
+
*** Bugs ***
There is a bug in some Linux kernels where perf misidentifies the CPU type. To see if you are affected by this, run ls /sys/bus/event_source/devices/ and verify the listed processor type matches what is expected. For example, an A9 should show the following.
@@ -139,7 +171,7 @@ There is a bug in some Linux kernels where perf misidentifies the CPU type. To s
ARMv7_Cortex_A9 breakpoint software tracepoint
To work around the issue try upgrading to a later kernel or comment out the gator_events_perf_pmu_cpu_init(gator_cpu, type); call in gator_events_perf_pmu.c
-There is a bug in some Linux kernels where an Oops may occurs when using userspace gator and a core is offlined. The fix was merged into mainline in 3.14-rc5, see http://git.kernel.org/tip/e3703f8cdfcf39c25c4338c3ad8e68891cca3731, and as been backported to older kernels.
+There is a bug in some Linux kernels where an Oops may occur when using userspace gator and a core is offlined. The fix was merged into mainline in 3.14-rc5, see http://git.kernel.org/tip/e3703f8cdfcf39c25c4338c3ad8e68891cca3731, and as been backported to older kernels.
If you see this error when using SELinux, ex: Android 4.4 or later
# ./gatord
@@ -172,3 +204,4 @@ update-rc.d rungator.sh defaults
*** GPL License ***
For license information, please see the file LICENSE after unzipping driver-src/gator-driver.tar.gz.
+The prebuilt gatord uses musl from http://www.musl-libc.org/releases/musl-1.0.2.tar.gz for musl license information see the COPYRIGHT file in the musl tar file.
diff --git a/daemon/Android.mk b/daemon/Android.mk
index 045d028..44c069c 100644
--- a/daemon/Android.mk
+++ b/daemon/Android.mk
@@ -3,7 +3,7 @@ include $(CLEAR_VARS)
XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h)
-LOCAL_CFLAGS += -Wall -O3 -mthumb-interwork -fno-exceptions -DETCDIR=\"/etc\" -Ilibsensors
+LOCAL_CFLAGS += -Wall -O3 -mthumb-interwork -fno-exceptions -pthread -DETCDIR=\"/etc\" -Ilibsensors
LOCAL_SRC_FILES := \
Buffer.cpp \
@@ -15,12 +15,14 @@ LOCAL_SRC_FILES := \
DynBuf.cpp \
EventsXML.cpp \
ExternalSource.cpp \
+ FSDriver.cpp \
Fifo.cpp \
Hwmon.cpp \
KMod.cpp \
LocalCapture.cpp \
Logging.cpp \
main.cpp \
+ MaliVideoDriver.cpp \
Monitor.cpp \
OlySocket.cpp \
OlyUtility.cpp \
@@ -55,7 +57,7 @@ LOCAL_SRC_FILES := \
mxml/mxml-set.c \
mxml/mxml-string.c
-LOCAL_C_INCLUDES := $(LOCAL_PATH)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_MODULE := gatord
LOCAL_MODULE_TAGS := optional
diff --git a/daemon/Application.mk b/daemon/Application.mk
new file mode 100644
index 0000000..631ba54
--- /dev/null
+++ b/daemon/Application.mk
@@ -0,0 +1 @@
+APP_PLATFORM := android-8
diff --git a/daemon/Buffer.cpp b/daemon/Buffer.cpp
index 93557da..dd19f7f 100644
--- a/daemon/Buffer.cpp
+++ b/daemon/Buffer.cpp
@@ -15,11 +15,12 @@
#define mask (mSize - 1)
enum {
- CODE_PEA = 1,
- CODE_KEYS = 2,
- CODE_FORMAT = 3,
- CODE_MAPS = 4,
- CODE_COMM = 5,
+ CODE_PEA = 1,
+ CODE_KEYS = 2,
+ CODE_FORMAT = 3,
+ CODE_MAPS = 4,
+ CODE_COMM = 5,
+ CODE_KEYS_OLD = 6,
};
// Summary Frame Messages
@@ -167,7 +168,7 @@ void Buffer::check(const uint64_t time) {
}
}
-void Buffer::packInt(int32_t x) {
+void Buffer::packInt(char *const buf, const int size, int &writePos, int32_t x) {
int packedBytes = 0;
int more = true;
while (more) {
@@ -181,11 +182,15 @@ void Buffer::packInt(int32_t x) {
b |= 0x80;
}
- mBuf[(mWritePos + packedBytes) & mask] = b;
+ buf[(writePos + packedBytes) & /*mask*/(size - 1)] = b;
packedBytes++;
}
- mWritePos = (mWritePos + packedBytes) & mask;
+ writePos = (writePos + packedBytes) & /*mask*/(size - 1);
+}
+
+void Buffer::packInt(int32_t x) {
+ packInt(mBuf, mSize, mWritePos, x);
}
void Buffer::packInt64(int64_t x) {
@@ -320,6 +325,21 @@ void Buffer::keys(const int count, const __u64 *const ids, const int *const keys
check(1);
}
+void Buffer::keysOld(const int keyCount, const int *const keys, const int bytes, const char *const buf) {
+ if (checkSpace((2 + keyCount) * MAXSIZE_PACK32 + bytes)) {
+ packInt(CODE_KEYS_OLD);
+ packInt(keyCount);
+ for (int i = 0; i < keyCount; ++i) {
+ packInt(keys[i]);
+ }
+ writeBytes(buf, bytes);
+ } else {
+ logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
+ handleException();
+ }
+ check(1);
+}
+
void Buffer::format(const int length, const char *const format) {
if (checkSpace(MAXSIZE_PACK32 + length + 1)) {
packInt(CODE_FORMAT);
diff --git a/daemon/Buffer.h b/daemon/Buffer.h
index 5023777..2de1b97 100644
--- a/daemon/Buffer.h
+++ b/daemon/Buffer.h
@@ -54,6 +54,7 @@ public:
// Perf Attrs messages
void pea(const struct perf_event_attr *const pea, int key);
void keys(const int count, const __u64 *const ids, const int *const keys);
+ void keysOld(const int keyCount, const int *const keys, const int bytes, const char *const buf);
void format(const int length, const char *const format);
void maps(const int pid, const int tid, const char *const maps);
void comm(const int pid, const int tid, const char *const image, const char *const comm);
@@ -64,6 +65,11 @@ public:
// Prefer a new member to using these functions if possible
char *getWritePos() { return mBuf + mWritePos; }
void advanceWrite(int bytes) { mWritePos = (mWritePos + bytes) & /*mask*/(mSize - 1); }
+ static void packInt(char *const buf, const int size, int &writePos, int32_t x);
+ void packInt(int32_t x);
+ void packInt64(int64_t x);
+ void writeBytes(const void *const data, size_t count);
+ void writeString(const char *const str);
static void writeLEInt(unsigned char *buf, int v) {
buf[0] = (v >> 0) & 0xFF;
@@ -76,11 +82,6 @@ private:
bool commitReady() const;
bool checkSpace(int bytes);
- void packInt(int32_t x);
- void packInt64(int64_t x);
- void writeBytes(const void *const data, size_t count);
- void writeString(const char *const str);
-
const int32_t mCore;
const int32_t mBufType;
const int mSize;
diff --git a/daemon/CapturedXML.cpp b/daemon/CapturedXML.cpp
index cf79b72..4a11415 100644
--- a/daemon/CapturedXML.cpp
+++ b/daemon/CapturedXML.cpp
@@ -33,7 +33,7 @@ mxml_node_t* CapturedXML::getTree(bool includeTime) {
captured = mxmlNewElement(xml, "captured");
mxmlElementSetAttr(captured, "version", "1");
if (gSessionData->perf.isSetup()) {
- mxmlElementSetAttr(captured, "type", "Perf");
+ mxmlElementSetAttr(captured, "type", "Perf");
}
mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION);
if (includeTime) { // Send the following only after the capture is complete
@@ -66,10 +66,15 @@ mxml_node_t* CapturedXML::getTree(bool includeTime) {
mxml_node_t *const node = mxmlNewElement(counters, "counter");
mxmlElementSetAttrf(node, "key", "0x%x", counter.getKey());
mxmlElementSetAttr(node, "type", counter.getType());
- mxmlElementSetAttrf(node, "event", "0x%x", counter.getEvent());
+ if (counter.getEvent() != -1) {
+ mxmlElementSetAttrf(node, "event", "0x%x", counter.getEvent());
+ }
if (counter.getCount() > 0) {
mxmlElementSetAttrf(node, "count", "%d", counter.getCount());
}
+ if (counter.getCores() > 0) {
+ mxmlElementSetAttrf(node, "cores", "%d", counter.getCores());
+ }
}
}
@@ -89,7 +94,7 @@ void CapturedXML::write(char* path) {
// Set full path
snprintf(file, PATH_MAX, "%s/captured.xml", path);
-
+
char* xml = getXML(true);
if (util->writeToDisk(file, xml) < 0) {
logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
diff --git a/daemon/CapturedXML.h b/daemon/CapturedXML.h
index efc1e52..ed08c44 100644
--- a/daemon/CapturedXML.h
+++ b/daemon/CapturedXML.h
@@ -23,4 +23,4 @@ private:
const char * mxmlWhitespaceCB(mxml_node_t *node, int where);
-#endif //__CAPTURED_XML_H__
+#endif //__CAPTURED_XML_H__
diff --git a/daemon/Child.cpp b/daemon/Child.cpp
index ca33561..1901ecc 100644
--- a/daemon/Child.cpp
+++ b/daemon/Child.cpp
@@ -26,13 +26,13 @@
#include "Driver.h"
#include "PerfSource.h"
#include "DriverSource.h"
-#include "UserSpaceSource.h"
#include "ExternalSource.h"
+#include "UserSpaceSource.h"
static sem_t haltPipeline, senderThreadStarted, startProfile, senderSem; // Shared by Child and spawned threads
static Source *primarySource = NULL;
-static Source *userSpaceSource = NULL;
static Source *externalSource = NULL;
+static Source *userSpaceSource = NULL;
static Sender* sender = NULL; // Shared by Child.cpp and spawned threads
Child* child = NULL; // shared by Child.cpp and main.cpp
@@ -147,16 +147,16 @@ static void *senderThread(void *) {
prctl(PR_SET_NAME, (unsigned long)&"gatord-sender", 0, 0, 0);
sem_wait(&haltPipeline);
- while (!primarySource->isDone() || (userSpaceSource != NULL && !userSpaceSource->isDone()) || (externalSource != NULL && !externalSource->isDone())) {
+ while (!primarySource->isDone() ||
+ !externalSource->isDone() ||
+ (userSpaceSource != NULL && !userSpaceSource->isDone())) {
sem_wait(&senderSem);
primarySource->write(sender);
+ externalSource->write(sender);
if (userSpaceSource != NULL) {
userSpaceSource->write(sender);
}
- if (externalSource != NULL) {
- externalSource->write(sender);
- }
}
// write end-of-capture sequence
@@ -202,6 +202,10 @@ void Child::initialization() {
void Child::endSession() {
gSessionData->mSessionIsActive = false;
primarySource->interrupt();
+ externalSource->interrupt();
+ if (userSpaceSource != NULL) {
+ userSpaceSource->interrupt();
+ }
sem_post(&haltPipeline);
}
@@ -227,9 +231,9 @@ void Child::run() {
// Set up the driver; must be done after gSessionData->mPerfCounterType[] is populated
if (!gSessionData->perf.isSetup()) {
- primarySource = new DriverSource(&senderSem, &startProfile);
+ primarySource = new DriverSource(&senderSem, &startProfile);
} else {
- primarySource = new PerfSource(&senderSem, &startProfile);
+ primarySource = new PerfSource(&senderSem, &startProfile);
}
// Initialize all drivers
@@ -280,11 +284,18 @@ void Child::run() {
thread_creation_success = false;
} else if (socket && pthread_create(&stopThreadID, NULL, stopThread, NULL)) {
thread_creation_success = false;
- } else if (pthread_create(&senderThreadID, NULL, senderThread, NULL)){
+ } else if (pthread_create(&senderThreadID, NULL, senderThread, NULL)) {
thread_creation_success = false;
}
- if (gSessionData->hwmon.countersEnabled()) {
+ externalSource = new ExternalSource(&senderSem);
+ if (!externalSource->prepare()) {
+ logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
+ handleException();
+ }
+ externalSource->start();
+
+ if (gSessionData->hwmon.countersEnabled() || gSessionData->fsDriver.countersEnabled()) {
userSpaceSource = new UserSpaceSource(&senderSem);
if (!userSpaceSource->prepare()) {
logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
@@ -292,14 +303,6 @@ void Child::run() {
}
userSpaceSource->start();
}
- if (access("/tmp/gator", F_OK) == 0) {
- externalSource = new ExternalSource(&senderSem);
- if (!externalSource->prepare()) {
- logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
- handleException();
- }
- externalSource->start();
- }
if (!thread_creation_success) {
logg->logError(__FILE__, __LINE__, "Failed to create gator threads");
@@ -312,12 +315,10 @@ void Child::run() {
// Start profiling
primarySource->run();
- if (externalSource != NULL) {
- externalSource->join();
- }
if (userSpaceSource != NULL) {
userSpaceSource->join();
}
+ externalSource->join();
// Wait for the other threads to exit
pthread_join(senderThreadID, NULL);
@@ -337,8 +338,8 @@ void Child::run() {
logg->logMessage("Profiling ended.");
- delete externalSource;
delete userSpaceSource;
+ delete externalSource;
delete primarySource;
delete sender;
delete localCapture;
diff --git a/daemon/Child.h b/daemon/Child.h
index 9e206d7..a306a77 100644
--- a/daemon/Child.h
+++ b/daemon/Child.h
@@ -30,4 +30,4 @@ private:
Child &operator=(const Child &);
};
-#endif //__CHILD_H__
+#endif //__CHILD_H__
diff --git a/daemon/ConfigurationXML.cpp b/daemon/ConfigurationXML.cpp
index fd479f2..6590dd3 100644
--- a/daemon/ConfigurationXML.cpp
+++ b/daemon/ConfigurationXML.cpp
@@ -21,12 +21,13 @@ static const char* ATTR_COUNTER = "counter";
static const char* ATTR_REVISION = "revision";
static const char* ATTR_EVENT = "event";
static const char* ATTR_COUNT = "count";
+static const char* ATTR_CORES = "cores";
ConfigurationXML::ConfigurationXML() {
const char * configuration_xml;
unsigned int configuration_xml_len;
getDefaultConfigurationXml(configuration_xml, configuration_xml_len);
-
+
char path[PATH_MAX];
getPath(path);
@@ -53,7 +54,7 @@ ConfigurationXML::ConfigurationXML() {
break;
}
-
+
validate();
}
@@ -82,7 +83,7 @@ int ConfigurationXML::parse(const char* configurationXML) {
node = mxmlGetFirstChild(tree);
while (node && mxmlGetType(node) != MXML_ELEMENT)
node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
-
+
ret = configurationsTag(node);
node = mxmlGetFirstChild(node);
@@ -127,7 +128,7 @@ void ConfigurationXML::validate(void) {
#define CONFIGURATION_REVISION 3
int ConfigurationXML::configurationsTag(mxml_node_t *node) {
const char* revision_string;
-
+
revision_string = mxmlElementGetAttr(node, ATTR_REVISION);
if (!revision_string) {
return 1; //revision issue;
@@ -158,6 +159,7 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) {
if (mxmlElementGetAttr(node, ATTR_COUNTER)) counter.setType(mxmlElementGetAttr(node, ATTR_COUNTER));
if (mxmlElementGetAttr(node, ATTR_EVENT)) counter.setEvent(strtol(mxmlElementGetAttr(node, ATTR_EVENT), NULL, 16));
if (mxmlElementGetAttr(node, ATTR_COUNT)) counter.setCount(strtol(mxmlElementGetAttr(node, ATTR_COUNT), NULL, 10));
+ if (mxmlElementGetAttr(node, ATTR_CORES)) counter.setCores(strtol(mxmlElementGetAttr(node, ATTR_CORES), NULL, 10));
if (counter.getCount() > 0) {
gSessionData->mIsEBS = true;
}
diff --git a/daemon/Counter.h b/daemon/Counter.h
index 6891745..5202aa0 100644
--- a/daemon/Counter.h
+++ b/daemon/Counter.h
@@ -27,6 +27,7 @@ public:
mEnabled = false;
mEvent = -1;
mCount = 0;
+ mCores = -1;
mKey = 0;
mDriver = NULL;
}
@@ -35,6 +36,7 @@ public:
void setEnabled(const bool enabled) { mEnabled = enabled; }
void setEvent(const int event) { mEvent = event; }
void setCount(const int count) { mCount = count; }
+ void setCores(const int cores) { mCores = cores; }
void setKey(const int key) { mKey = key; }
void setDriver(Driver *const driver) { mDriver = driver; }
@@ -42,6 +44,7 @@ public:
bool isEnabled() const { return mEnabled; }
int getEvent() const { return mEvent; }
int getCount() const { return mCount; }
+ int getCores() const { return mCores; }
int getKey() const { return mKey; }
Driver *getDriver() const { return mDriver; }
@@ -54,6 +57,7 @@ private:
bool mEnabled;
int mEvent;
int mCount;
+ int mCores;
int mKey;
Driver *mDriver;
};
diff --git a/daemon/DriverSource.cpp b/daemon/DriverSource.cpp
index f78ec6b..11d3095 100644
--- a/daemon/DriverSource.cpp
+++ b/daemon/DriverSource.cpp
@@ -12,19 +12,24 @@
#include <fcntl.h>
#include <inttypes.h>
+#include <sys/prctl.h>
#include <unistd.h>
+#include "Buffer.h"
#include "Child.h"
+#include "DynBuf.h"
#include "Fifo.h"
#include "Logging.h"
+#include "Proc.h"
#include "Sender.h"
#include "SessionData.h"
extern Child *child;
-DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mFifo(NULL), mSenderSem(senderSem), mStartProfile(startProfile), mBufferSize(0), mBufferFD(0), mLength(1) {
+DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL), mFifo(NULL), mSenderSem(senderSem), mStartProfile(startProfile), mBufferSize(0), mBufferFD(0), mLength(1) {
int driver_version = 0;
+ mBuffer = new Buffer(0, FRAME_PERF_ATTRS, 4*1024*1024, senderSem);
if (readIntDriver("/dev/gator/version", &driver_version) == -1) {
logg->logError(__FILE__, __LINE__, "Error reading gator driver version");
handleException();
@@ -43,7 +48,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mFifo(NULL),
handleException();
} else {
// Release version mismatch
- logg->logError(__FILE__, __LINE__,
+ logg->logError(__FILE__, __LINE__,
"gator driver version \"%d\" is different than gator daemon version \"%d\".\n"
">> Please upgrade the driver and daemon to the latest versions.", driver_version, PROTOCOL_VERSION);
handleException();
@@ -87,6 +92,28 @@ bool DriverSource::prepare() {
return true;
}
+void DriverSource::bootstrapThread() {
+ prctl(PR_SET_NAME, (unsigned long)&"gatord-bootstrap", 0, 0, 0);
+
+ DynBuf printb;
+ DynBuf b1;
+ DynBuf b2;
+ DynBuf b3;
+
+ if (!readProc(mBuffer, false, &printb, &b1, &b2, &b3)) {
+ logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__);
+ handleException();
+ }
+
+ mBuffer->commit(1);
+ mBuffer->setDone();
+}
+
+void *DriverSource::bootstrapThreadStatic(void *arg) {
+ static_cast<DriverSource *>(arg)->bootstrapThread();
+ return NULL;
+}
+
void DriverSource::run() {
// Get the initial pointer to the collect buffer
char *collectBuffer = mFifo->start();
@@ -138,6 +165,12 @@ void DriverSource::run() {
sem_post(mStartProfile);
+ pthread_t bootstrapThreadID;
+ if (pthread_create(&bootstrapThreadID, NULL, bootstrapThreadStatic, this) != 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to start the gator_bootstrap thread");
+ handleException();
+ }
+
// Collect Data
do {
// This command will stall until data is received from the driver
@@ -164,6 +197,8 @@ void DriverSource::run() {
} while (bytesCollected > 0);
logg->logMessage("Exit collect data loop");
+
+ pthread_join(bootstrapThreadID, NULL);
}
void DriverSource::interrupt() {
@@ -174,7 +209,7 @@ void DriverSource::interrupt() {
}
bool DriverSource::isDone() {
- return mLength <= 0;
+ return mLength <= 0 && (mBuffer == NULL || mBuffer->isDone());
}
void DriverSource::write(Sender *sender) {
@@ -182,6 +217,16 @@ void DriverSource::write(Sender *sender) {
if (data != NULL) {
sender->writeData(data, mLength, RESPONSE_APC_DATA);
mFifo->release();
+ // Assume the summary packet is in the first block received from the driver
+ gSessionData->mSentSummary = true;
+ }
+ if (mBuffer != NULL && !mBuffer->isDone()) {
+ mBuffer->write(sender);
+ if (mBuffer->isDone()) {
+ Buffer *buf = mBuffer;
+ mBuffer = NULL;
+ delete buf;
+ }
}
}
@@ -227,7 +272,7 @@ int DriverSource::readInt64Driver(const char *fullpath, int64_t *value) {
char *endptr;
errno = 0;
*value = strtoll(data, &endptr, 10);
- if (errno != 0 || *endptr != '\n') {
+ if (errno != 0 || (*endptr != '\n' && *endptr != '\0')) {
logg->logMessage("Invalid value in file %s", fullpath);
return -1;
}
diff --git a/daemon/DriverSource.h b/daemon/DriverSource.h
index dcf1078..ec27b08 100644
--- a/daemon/DriverSource.h
+++ b/daemon/DriverSource.h
@@ -14,6 +14,7 @@
#include "Source.h"
+class Buffer;
class Fifo;
class DriverSource : public Source {
@@ -37,6 +38,10 @@ public:
static int writeReadDriver(const char *path, int64_t *value);
private:
+ static void *bootstrapThreadStatic(void *arg);
+ void bootstrapThread();
+
+ Buffer *mBuffer;
Fifo *mFifo;
sem_t *const mSenderSem;
sem_t *const mStartProfile;
diff --git a/daemon/EventsXML.cpp b/daemon/EventsXML.cpp
index a07a046..cf0192e 100644
--- a/daemon/EventsXML.cpp
+++ b/daemon/EventsXML.cpp
@@ -13,7 +13,7 @@
#include "OlyUtility.h"
#include "SessionData.h"
-char* EventsXML::getXML() {
+mxml_node_t *EventsXML::getTree() {
#include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len
char path[PATH_MAX];
mxml_node_t *xml;
@@ -38,6 +38,12 @@ char* EventsXML::getXML() {
xml = mxmlLoadString(NULL, (const char *)events_xml, MXML_NO_CALLBACK);
}
+ return xml;
+}
+
+char *EventsXML::getXML() {
+ mxml_node_t *xml = getTree();
+
// Add dynamic events from the drivers
mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND);
if (!events) {
@@ -48,19 +54,19 @@ char* EventsXML::getXML() {
driver->writeEvents(events);
}
- char* string = mxmlSaveAllocString(xml, mxmlWhitespaceCB);
+ char *string = mxmlSaveAllocString(xml, mxmlWhitespaceCB);
mxmlDelete(xml);
return string;
}
-void EventsXML::write(const char* path) {
+void EventsXML::write(const char *path) {
char file[PATH_MAX];
// Set full path
snprintf(file, PATH_MAX, "%s/events.xml", path);
-
- char* buf = getXML();
+
+ char *buf = getXML();
if (util->writeToDisk(file, buf) < 0) {
logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
handleException();
diff --git a/daemon/EventsXML.h b/daemon/EventsXML.h
index 6cd1560..ff7a02f 100644
--- a/daemon/EventsXML.h
+++ b/daemon/EventsXML.h
@@ -9,9 +9,12 @@
#ifndef EVENTS_XML
#define EVENTS_XML
+#include "mxml/mxml.h"
+
class EventsXML {
public:
- char* getXML();
+ mxml_node_t *getTree();
+ char *getXML();
void write(const char* path);
};
diff --git a/daemon/ExternalSource.cpp b/daemon/ExternalSource.cpp
index fe5824b..b6ec301 100644
--- a/daemon/ExternalSource.cpp
+++ b/daemon/ExternalSource.cpp
@@ -8,41 +8,195 @@
#include "ExternalSource.h"
+#include <fcntl.h>
#include <sys/prctl.h>
+#include <unistd.h>
#include "Logging.h"
#include "OlySocket.h"
#include "SessionData.h"
-ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 1024, senderSem), mSock("/tmp/gator") {
+static const char MALI_VIDEO[] = "\0mali-video";
+static const char MALI_VIDEO_STARTUP[] = "\0mali-video-startup";
+static const char MALI_VIDEO_V1[] = "MALI_VIDEO 1\n";
+
+static bool setNonblock(const int fd) {
+ int flags;
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags < 0) {
+ logg->logMessage("fcntl getfl failed");
+ return false;
+ }
+
+ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) {
+ logg->logMessage("fcntl setfl failed");
+ return false;
+ }
+
+ return true;
+}
+
+ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 128*1024, senderSem), mMonitor(), mMveStartupUds(MALI_VIDEO_STARTUP, sizeof(MALI_VIDEO_STARTUP)), mInterruptFd(-1), mMveUds(-1) {
+ sem_init(&mBufferSem, 0, 0);
}
ExternalSource::~ExternalSource() {
}
+void ExternalSource::waitFor(const uint64_t currTime, const int bytes) {
+ while (mBuffer.bytesAvailable() <= bytes) {
+ mBuffer.check(currTime);
+ sem_wait(&mBufferSem);
+ }
+}
+
+void ExternalSource::configureConnection(const int fd, const char *const handshake, size_t size) {
+ if (!setNonblock(fd)) {
+ logg->logError(__FILE__, __LINE__, "Unable to set nonblock on fh");
+ handleException();
+ }
+
+ if (!mMonitor.add(fd)) {
+ logg->logError(__FILE__, __LINE__, "Unable to add fh to monitor");
+ handleException();
+ }
+
+ // Write the handshake to the circular buffer
+ waitFor(1, Buffer::MAXSIZE_PACK32 + 4 + size - 1);
+ mBuffer.packInt(fd);
+ mBuffer.writeLEInt((unsigned char *)mBuffer.getWritePos(), size - 1);
+ mBuffer.advanceWrite(4);
+ mBuffer.writeBytes(handshake, size - 1);
+}
+
+bool ExternalSource::connectMve() {
+ if (!gSessionData->maliVideo.countersEnabled()) {
+ return true;
+ }
+
+ mMveUds = OlySocket::connect(MALI_VIDEO, sizeof(MALI_VIDEO));
+ if (mMveUds < 0) {
+ return false;
+ }
+
+ if (!gSessionData->maliVideo.start(mMveUds)) {
+ return false;
+ }
+
+ configureConnection(mMveUds, MALI_VIDEO_V1, sizeof(MALI_VIDEO_V1));
+
+ return true;
+}
+
bool ExternalSource::prepare() {
+ if (!mMonitor.init() || !setNonblock(mMveStartupUds.getFd()) || !mMonitor.add(mMveStartupUds.getFd())) {
+ return false;
+ }
+
+ connectMve();
+
return true;
}
void ExternalSource::run() {
- prctl(PR_SET_NAME, (unsigned long)&"gatord-uds", 0, 0, 0);
+ int pipefd[2];
+
+ prctl(PR_SET_NAME, (unsigned long)&"gatord-external", 0, 0, 0);
+
+ if (pipe(pipefd) != 0) {
+ logg->logError(__FILE__, __LINE__, "pipe failed");
+ handleException();
+ }
+ mInterruptFd = pipefd[1];
+
+ if (!mMonitor.add(pipefd[0])) {
+ logg->logError(__FILE__, __LINE__, "Monitor::add failed");
+ handleException();
+ }
while (gSessionData->mSessionIsActive) {
- // Will be aborted when the socket is closed at the end of the capture
- int length = mSock.receive(mBuffer.getWritePos(), mBuffer.contiguousSpaceAvailable());
- if (length <= 0) {
- break;
+ struct epoll_event events[16];
+ // Clear any pending sem posts
+ while (sem_trywait(&mBufferSem) == 0);
+ int ready = mMonitor.wait(events, ARRAY_LENGTH(events), -1);
+ if (ready < 0) {
+ logg->logError(__FILE__, __LINE__, "Monitor::wait failed");
+ handleException();
}
- mBuffer.advanceWrite(length);
- mBuffer.check(0);
+ const uint64_t currTime = getTime();
+
+ for (int i = 0; i < ready; ++i) {
+ const int fd = events[i].data.fd;
+ if (fd == mMveStartupUds.getFd()) {
+ // Mali Video Engine says it's alive
+ int client = mMveStartupUds.acceptConnection();
+ // Don't read from this connection, establish a new connection to Mali-V500
+ close(client);
+ if (!connectMve()) {
+ logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali video connection");
+ handleException();
+ }
+ } else if (fd == pipefd[0]) {
+ // Means interrupt has been called and mSessionIsActive should be reread
+ } else {
+ while (true) {
+ waitFor(currTime, Buffer::MAXSIZE_PACK32 + 4);
+
+ mBuffer.packInt(fd);
+ char *const bytesPos = mBuffer.getWritePos();
+ mBuffer.advanceWrite(4);
+ const int contiguous = mBuffer.contiguousSpaceAvailable();
+ const int bytes = read(fd, mBuffer.getWritePos(), contiguous);
+ if (bytes < 0) {
+ if (errno == EAGAIN) {
+ // Nothing left to read, and Buffer convention dictates that writePos can't go backwards
+ mBuffer.writeLEInt((unsigned char *)bytesPos, 0);
+ break;
+ }
+ // Something else failed, close the socket
+ mBuffer.writeLEInt((unsigned char *)bytesPos, -1);
+ close(fd);
+ break;
+ } else if (bytes == 0) {
+ // The other side is closed
+ mBuffer.writeLEInt((unsigned char *)bytesPos, -1);
+ close(fd);
+ break;
+ }
+
+ mBuffer.writeLEInt((unsigned char *)bytesPos, bytes);
+ mBuffer.advanceWrite(bytes);
+
+ // Short reads also mean nothing is left to read
+ if (bytes < contiguous) {
+ break;
+ }
+ }
+ }
+ }
+
+ // Only call mBufferCheck once per iteration
+ mBuffer.check(currTime);
}
mBuffer.setDone();
+
+ mInterruptFd = -1;
+ close(pipefd[0]);
+ close(pipefd[1]);
}
void ExternalSource::interrupt() {
- // Do nothing
+ if (mInterruptFd >= 0) {
+ int8_t c = 0;
+ // Write to the pipe to wake the monitor which will cause mSessionIsActive to be reread
+ if (::write(mInterruptFd, &c, sizeof(c)) != sizeof(c)) {
+ logg->logError(__FILE__, __LINE__, "write failed");
+ handleException();
+ }
+ }
}
bool ExternalSource::isDone() {
@@ -50,7 +204,12 @@ bool ExternalSource::isDone() {
}
void ExternalSource::write(Sender *sender) {
+ // Don't send external data until the summary packet is sent so that monotonic delta is available
+ if (!gSessionData->mSentSummary) {
+ return;
+ }
if (!mBuffer.isDone()) {
mBuffer.write(sender);
+ sem_post(&mBufferSem);
}
}
diff --git a/daemon/ExternalSource.h b/daemon/ExternalSource.h
index 2052bdf..2e7ed27 100644
--- a/daemon/ExternalSource.h
+++ b/daemon/ExternalSource.h
@@ -12,6 +12,7 @@
#include <semaphore.h>
#include "Buffer.h"
+#include "Monitor.h"
#include "OlySocket.h"
#include "Source.h"
@@ -29,8 +30,16 @@ public:
void write(Sender *sender);
private:
+ void waitFor(const uint64_t currTime, const int bytes);
+ void configureConnection(const int fd, const char *const handshake, size_t size);
+ bool connectMve();
+
+ sem_t mBufferSem;
Buffer mBuffer;
- OlySocket mSock;
+ Monitor mMonitor;
+ OlyServerSocket mMveStartupUds;
+ int mInterruptFd;
+ int mMveUds;
// Intentionally unimplemented
ExternalSource(const ExternalSource &);
diff --git a/daemon/FSDriver.cpp b/daemon/FSDriver.cpp
new file mode 100644
index 0000000..40c8df1
--- /dev/null
+++ b/daemon/FSDriver.cpp
@@ -0,0 +1,212 @@
+/**
+ * Copyright (C) ARM Limited 2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "FSDriver.h"
+
+#include <fcntl.h>
+#include <regex.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "Buffer.h"
+#include "Counter.h"
+#include "DriverSource.h"
+#include "Logging.h"
+#include "SessionData.h"
+
+class FSCounter {
+public:
+ FSCounter(FSCounter *next, char *name, const char *regex);
+ ~FSCounter();
+
+ FSCounter *getNext() const { return next; }
+ int getKey() const { return key; }
+ bool isEnabled() const { return enabled; }
+ void setEnabled(const bool enabled) { this->enabled = enabled; }
+ const char *getName() const { return name; }
+ int64_t read();
+
+private:
+ FSCounter *const next;
+ regex_t reg;
+ char *name;
+ const int key;
+ int enabled : 1,
+ useRegex : 1;
+
+ // Intentionally unimplemented
+ FSCounter(const FSCounter &);
+ FSCounter &operator=(const FSCounter &);
+};
+
+FSCounter::FSCounter(FSCounter *next, char *name, const char *regex) : next(next), name(name), key(getEventKey()), enabled(false), useRegex(regex != NULL) {
+ if (useRegex) {
+ int result = regcomp(&reg, regex, REG_EXTENDED);
+ if (result != 0) {
+ char buf[128];
+ regerror(result, &reg, buf, sizeof(buf));
+ logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf);
+ handleException();
+ }
+ }
+}
+
+FSCounter::~FSCounter() {
+ free(name);
+ if (useRegex) {
+ regfree(&reg);
+ }
+}
+
+int64_t FSCounter::read() {
+ int64_t value;
+ if (useRegex) {
+ char buf[4096];
+ size_t pos = 0;
+ const int fd = open(name, O_RDONLY);
+ if (fd < 0) {
+ goto fail;
+ }
+ while (pos < sizeof(buf) - 1) {
+ const ssize_t bytes = ::read(fd, buf + pos, sizeof(buf) - pos - 1);
+ if (bytes < 0) {
+ goto fail;
+ } else if (bytes == 0) {
+ break;
+ }
+ pos += bytes;
+ }
+ close(fd);
+ buf[pos] = '\0';
+
+ regmatch_t match[2];
+ int result = regexec(&reg, buf, 2, match, 0);
+ if (result != 0) {
+ regerror(result, &reg, buf, sizeof(buf));
+ logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, buf);
+ handleException();
+ }
+
+ if (match[1].rm_so < 0) {
+ logg->logError(__FILE__, __LINE__, "Parsing %s failed", name);
+ handleException();
+ }
+ char *endptr;
+ errno = 0;
+ value = strtoll(buf + match[1].rm_so, &endptr, 0);
+ if (errno != 0) {
+ logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, strerror(errno));
+ handleException();
+ }
+ } else {
+ if (DriverSource::readInt64Driver(name, &value) != 0) {
+ goto fail;
+ }
+ }
+ return value;
+
+ fail:
+ logg->logError(__FILE__, __LINE__, "Unable to read %s", name);
+ handleException();
+}
+
+FSDriver::FSDriver() : counters(NULL) {
+}
+
+FSDriver::~FSDriver() {
+ while (counters != NULL) {
+ FSCounter * counter = counters;
+ counters = counter->getNext();
+ delete counter;
+ }
+}
+
+void FSDriver::setup(mxml_node_t *const xml) {
+ // fs driver does not currently work with perf
+ if (gSessionData->perf.isSetup()) {
+ return;
+ }
+
+ mxml_node_t *node = xml;
+ while (true) {
+ node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ break;
+ }
+ const char *counter = mxmlElementGetAttr(node, "counter");
+ if ((counter != NULL) && (counter[0] == '/')) {
+ const char *regex = mxmlElementGetAttr(node, "regex");
+ counters = new FSCounter(counters, strdup(counter), regex);
+ }
+ }
+}
+
+FSCounter *FSDriver::findCounter(const Counter &counter) const {
+ for (FSCounter * fsCounter = counters; fsCounter != NULL; fsCounter = fsCounter->getNext()) {
+ if (strcmp(fsCounter->getName(), counter.getType()) == 0) {
+ return fsCounter;
+ }
+ }
+
+ return NULL;
+}
+
+bool FSDriver::claimCounter(const Counter &counter) const {
+ return findCounter(counter) != NULL;
+}
+
+bool FSDriver::countersEnabled() const {
+ for (FSCounter *counter = counters; counter != NULL; counter = counter->getNext()) {
+ if (counter->isEnabled()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void FSDriver::resetCounters() {
+ for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
+ counter->setEnabled(false);
+ }
+}
+
+void FSDriver::setupCounter(Counter &counter) {
+ FSCounter *const fsCounter = findCounter(counter);
+ if (fsCounter == NULL) {
+ counter.setEnabled(false);
+ return;
+ }
+ fsCounter->setEnabled(true);
+ counter.setKey(fsCounter->getKey());
+}
+
+int FSDriver::writeCounters(mxml_node_t *root) const {
+ int count = 0;
+ for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
+ if (access(counter->getName(), R_OK) == 0) {
+ mxml_node_t *node = mxmlNewElement(root, "counter");
+ mxmlElementSetAttr(node, "name", counter->getName());
+ ++count;
+ }
+ }
+
+ return count;
+}
+
+void FSDriver::start() {
+}
+
+void FSDriver::read(Buffer * const buffer) {
+ for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
+ if (!counter->isEnabled()) {
+ continue;
+ }
+ buffer->event(counter->getKey(), counter->read());
+ }
+}
diff --git a/daemon/FSDriver.h b/daemon/FSDriver.h
new file mode 100644
index 0000000..ef39553
--- /dev/null
+++ b/daemon/FSDriver.h
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) ARM Limited 2014. 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 FSDRIVER_H
+#define FSDRIVER_H
+
+#include "Driver.h"
+
+class Buffer;
+class FSCounter;
+
+class FSDriver : public Driver {
+public:
+ FSDriver();
+ ~FSDriver();
+
+ void setup(mxml_node_t *const xml);
+
+ bool claimCounter(const Counter &counter) const;
+ bool countersEnabled() const;
+ void resetCounters();
+ void setupCounter(Counter &counter);
+
+ int writeCounters(mxml_node_t *root) const;
+
+ void start();
+ void read(Buffer * buffer);
+
+private:
+ FSCounter *findCounter(const Counter &counter) const;
+
+ FSCounter *counters;
+
+ // Intentionally unimplemented
+ FSDriver(const FSDriver &);
+ FSDriver &operator=(const FSDriver &);
+};
+
+#endif // FSDRIVER_H
diff --git a/daemon/Fifo.h b/daemon/Fifo.h
index 7dd7426..bdda3f5 100644
--- a/daemon/Fifo.h
+++ b/daemon/Fifo.h
@@ -45,4 +45,4 @@ private:
Fifo &operator=(const Fifo &);
};
-#endif //__FIFO_H__
+#endif //__FIFO_H__
diff --git a/daemon/Hwmon.cpp b/daemon/Hwmon.cpp
index 778f307..e444247 100644
--- a/daemon/Hwmon.cpp
+++ b/daemon/Hwmon.cpp
@@ -28,6 +28,7 @@ public:
const char *getTitle() const { return title; }
bool isDuplicate() const { return duplicate; }
const char *getDisplay() const { return display; }
+ const char *getCounterClass() const { return counter_class; }
const char *getUnit() const { return unit; }
int getModifier() const { return modifier; }
@@ -58,6 +59,7 @@ private:
char *label;
const char *title;
const char *display;
+ const char *counter_class;
const char *unit;
int modifier;
double previous_value;
@@ -87,7 +89,8 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
case SENSORS_FEATURE_IN:
title = "Voltage";
input = SENSORS_SUBFEATURE_IN_INPUT;
- display = "average";
+ display = "maximum";
+ counter_class = "absolute";
unit = "V";
modifier = 1000;
monotonic = false;
@@ -96,6 +99,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
title = "Fan";
input = SENSORS_SUBFEATURE_FAN_INPUT;
display = "average";
+ counter_class = "absolute";
unit = "RPM";
modifier = 1;
monotonic = false;
@@ -104,6 +108,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
title = "Temperature";
input = SENSORS_SUBFEATURE_TEMP_INPUT;
display = "maximum";
+ counter_class = "absolute";
unit = "°C";
modifier = 1000;
monotonic = false;
@@ -111,7 +116,8 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
case SENSORS_FEATURE_POWER:
title = "Power";
input = SENSORS_SUBFEATURE_POWER_INPUT;
- display = "average";
+ display = "maximum";
+ counter_class = "absolute";
unit = "W";
modifier = 1000000;
monotonic = false;
@@ -120,6 +126,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
title = "Energy";
input = SENSORS_SUBFEATURE_ENERGY_INPUT;
display = "accumulate";
+ counter_class = "delta";
unit = "J";
modifier = 1000000;
monotonic = true;
@@ -127,7 +134,8 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
case SENSORS_FEATURE_CURR:
title = "Current";
input = SENSORS_SUBFEATURE_CURR_INPUT;
- display = "average";
+ display = "maximum";
+ counter_class = "absolute";
unit = "A";
modifier = 1000;
monotonic = false;
@@ -136,6 +144,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
title = "Humidity";
input = SENSORS_SUBFEATURE_HUMIDITY_INPUT;
display = "average";
+ counter_class = "absolute";
unit = "%";
modifier = 1000;
monotonic = false;
@@ -311,6 +320,7 @@ void Hwmon::writeEvents(mxml_node_t *root) const {
mxmlElementSetAttr(node, "name", counter->getLabel());
}
mxmlElementSetAttr(node, "display", counter->getDisplay());
+ mxmlElementSetAttr(node, "class", counter->getCounterClass());
mxmlElementSetAttr(node, "units", counter->getUnit());
if (counter->getModifier() != 1) {
mxmlElementSetAttrf(node, "modifier", "%d", counter->getModifier());
diff --git a/daemon/KMod.cpp b/daemon/KMod.cpp
index 9300002..73e123d 100644
--- a/daemon/KMod.cpp
+++ b/daemon/KMod.cpp
@@ -58,10 +58,15 @@ void KMod::setupCounter(Counter &counter) {
return;
}
+ int value = 0;
snprintf(text, sizeof(text), "%s/key", base);
- int key = 0;
- DriverSource::readIntDriver(text, &key);
- counter.setKey(key);
+ DriverSource::readIntDriver(text, &value);
+ counter.setKey(value);
+
+ snprintf(text, sizeof(text), "%s/cores", base);
+ if (DriverSource::readIntDriver(text, &value) == 0) {
+ counter.setCores(value);
+ }
snprintf(text, sizeof(text), "%s/event", base);
DriverSource::writeDriver(text, counter.getEvent());
diff --git a/daemon/LocalCapture.h b/daemon/LocalCapture.h
index aadecce..b1e7219 100644
--- a/daemon/LocalCapture.h
+++ b/daemon/LocalCapture.h
@@ -23,4 +23,4 @@ private:
int removeDirAndAllContents(char* path);
};
-#endif //__LOCAL_CAPTURE_H__
+#endif //__LOCAL_CAPTURE_H__
diff --git a/daemon/Logging.h b/daemon/Logging.h
index 6ae3280..4934bb0 100644
--- a/daemon/Logging.h
+++ b/daemon/Logging.h
@@ -33,4 +33,4 @@ extern Logging* logg;
extern void handleException() __attribute__ ((noreturn));
-#endif //__LOGGING_H__
+#endif //__LOGGING_H__
diff --git a/daemon/Makefile b/daemon/Makefile
index 24ee940..2ed49fd 100644
--- a/daemon/Makefile
+++ b/daemon/Makefile
@@ -8,14 +8,14 @@
# targets run 'make SOFTFLOAT=1 SYSROOT=/path/to/sysroot', see
# README_Streamline.txt for more details
-CPP = $(CROSS_COMPILE)g++
-GCC = $(CROSS_COMPILE)gcc
+CC = $(CROSS_COMPILE)gcc
+CXX = $(CROSS_COMPILE)g++
# -mthumb-interwork is required for interworking to ARM or Thumb stdlibc
-CFLAGS += -mthumb-interwork
+CPPFLAGS += -mthumb-interwork
ifeq ($(SOFTFLOAT),1)
- CFLAGS += -marm -march=armv4t -mfloat-abi=soft
+ CPPFLAGS += -marm -march=armv4t -mfloat-abi=soft
LDFLAGS += -marm -march=armv4t -mfloat-abi=soft
endif
ifneq ($(SYSROOT),)
diff --git a/daemon/Makefile_aarch64 b/daemon/Makefile_aarch64
index 10b4b4a..efd1fa0 100644
--- a/daemon/Makefile_aarch64
+++ b/daemon/Makefile_aarch64
@@ -4,12 +4,9 @@
#
# Uncomment and define CROSS_COMPILE if it is not already defined
-# CROSS_COMPILE=/path/to/cross-compiler/arm-linux-gnueabihf-
-# NOTE: This toolchain uses the hardfloat abi by default. For non-hardfloat
-# targets it is necessary to add options
-# '-marm -march=armv4t -mfloat-abi=soft'.
+# CROSS_COMPILE=/path/to/cross-compiler/aarch64-linux-gnu-
-CPP = $(CROSS_COMPILE)g++
-GCC = $(CROSS_COMPILE)gcc
+CC = $(CROSS_COMPILE)gcc
+CXX = $(CROSS_COMPILE)g++
include common.mk
diff --git a/daemon/MaliVideoDriver.cpp b/daemon/MaliVideoDriver.cpp
new file mode 100644
index 0000000..18b413b
--- /dev/null
+++ b/daemon/MaliVideoDriver.cpp
@@ -0,0 +1,253 @@
+/**
+ * Copyright (C) ARM Limited 2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "MaliVideoDriver.h"
+
+#include <unistd.h>
+
+#include "Buffer.h"
+#include "Counter.h"
+#include "Logging.h"
+#include "SessionData.h"
+
+// From instr/src/mve_instr_comm_protocol.h
+typedef enum mve_instr_configuration_type {
+ MVE_INSTR_RAW = 1 << 0,
+ MVE_INSTR_COUNTERS = 1 << 1,
+ MVE_INSTR_EVENTS = 1 << 2,
+ MVE_INSTR_ACTIVITIES = 1 << 3,
+
+ // Raw always pushed regardless
+ MVE_INSTR_PULL = 1 << 12,
+ // Raw always unpacked regardless
+ MVE_INSTR_PACKED_COMM = 1 << 13,
+ // Don’t send ACKt response
+ MVE_INSTR_NO_AUTO_ACK = 1 << 14,
+} mve_instr_configuration_type_t;
+
+static const char COUNTER[] = "ARM_Mali-V500_cnt";
+static const char EVENT[] = "ARM_Mali-V500_evn";
+static const char ACTIVITY[] = "ARM_Mali-V500_act";
+
+class MaliVideoCounter {
+public:
+ MaliVideoCounter(MaliVideoCounter *next, const char *name, const MaliVideoCounterType type, const int id) : mNext(next), mName(name), mType(type), mId(id), mKey(getEventKey()), mEnabled(false) {
+ }
+
+ ~MaliVideoCounter() {
+ delete mName;
+ }
+
+ MaliVideoCounter *getNext() const { return mNext; }
+ const char *getName() const { return mName; }
+ MaliVideoCounterType getType() const { return mType; }
+ int getId() const { return mId; }
+ int getKey() const { return mKey; }
+ bool isEnabled() const { return mEnabled; }
+ void setEnabled(const bool enabled) { mEnabled = enabled; }
+
+private:
+ MaliVideoCounter *const mNext;
+ const char *const mName;
+ const MaliVideoCounterType mType;
+ // Mali Video id
+ const int mId;
+ // Streamline key
+ const int mKey;
+ bool mEnabled;
+};
+
+MaliVideoDriver::MaliVideoDriver() : mCounters(NULL), mActivityCount(0) {
+}
+
+MaliVideoDriver::~MaliVideoDriver() {
+ while (mCounters != NULL) {
+ MaliVideoCounter *counter = mCounters;
+ mCounters = counter->getNext();
+ delete counter;
+ }
+}
+
+void MaliVideoDriver::setup(mxml_node_t *const xml) {
+ // hwmon does not currently work with perf
+ if (gSessionData->perf.isSetup()) {
+ return;
+ }
+
+ mxml_node_t *node = xml;
+ while (true) {
+ node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ break;
+ }
+ const char *counter = mxmlElementGetAttr(node, "counter");
+ if (counter == NULL) {
+ // Ignore
+ } else if (strncmp(counter, COUNTER, sizeof(COUNTER) - 1) == 0) {
+ const int i = strtol(counter + sizeof(COUNTER) - 1, NULL, 10);
+ mCounters = new MaliVideoCounter(mCounters, strdup(counter), MVCT_COUNTER, i);
+ } else if (strncmp(counter, EVENT, sizeof(EVENT) - 1) == 0) {
+ const int i = strtol(counter + sizeof(EVENT) - 1, NULL, 10);
+ mCounters = new MaliVideoCounter(mCounters, strdup(counter), MVCT_EVENT, i);
+ } else if (strcmp(counter, ACTIVITY) == 0) {
+ mCounters = new MaliVideoCounter(mCounters, strdup(ACTIVITY), MVCT_ACTIVITY, 0);
+ mActivityCount = 0;
+ while (true) {
+ char buf[32];
+ snprintf(buf, sizeof(buf), "activity%i", mActivityCount + 1);
+ if (mxmlElementGetAttr(node, buf) == NULL) {
+ break;
+ }
+ ++mActivityCount;
+ }
+ }
+ }
+}
+
+MaliVideoCounter *MaliVideoDriver::findCounter(const Counter &counter) const {
+ for (MaliVideoCounter *maliVideoCounter = mCounters; maliVideoCounter != NULL; maliVideoCounter = maliVideoCounter->getNext()) {
+ if (strcmp(maliVideoCounter->getName(), counter.getType()) == 0) {
+ return maliVideoCounter;
+ }
+ }
+
+ return NULL;
+}
+
+bool MaliVideoDriver::claimCounter(const Counter &counter) const {
+ return findCounter(counter) != NULL;
+}
+
+bool MaliVideoDriver::countersEnabled() const {
+ for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
+ if (counter->isEnabled()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void MaliVideoDriver::resetCounters() {
+ for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
+ counter->setEnabled(false);
+ }
+}
+
+void MaliVideoDriver::setupCounter(Counter &counter) {
+ MaliVideoCounter *const maliVideoCounter = findCounter(counter);
+ if (maliVideoCounter == NULL) {
+ counter.setEnabled(false);
+ return;
+ }
+ maliVideoCounter->setEnabled(true);
+ counter.setKey(maliVideoCounter->getKey());
+}
+
+int MaliVideoDriver::writeCounters(mxml_node_t *root) const {
+ if (access("/dev/mv500", F_OK) != 0) {
+ return 0;
+ }
+
+ int count = 0;
+ for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
+ mxml_node_t *node = mxmlNewElement(root, "counter");
+ mxmlElementSetAttr(node, "name", counter->getName());
+ ++count;
+ }
+
+ return count;
+}
+
+void MaliVideoDriver::marshalEnable(const MaliVideoCounterType type, char *const buf, const size_t bufsize, int &pos) {
+ // size
+ int numEnabled = 0;
+ for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
+ if (counter->isEnabled() && (counter->getType() == type)) {
+ ++numEnabled;
+ }
+ }
+ Buffer::packInt(buf, bufsize, pos, numEnabled*sizeof(uint32_t));
+ for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
+ if (counter->isEnabled() && (counter->getType() == type)) {
+ Buffer::packInt(buf, bufsize, pos, counter->getId());
+ }
+ }
+}
+
+bool MaliVideoDriver::start(const int mveUds) {
+ char buf[256];
+ int pos = 0;
+
+ // code - MVE_INSTR_STARTUP
+ buf[pos++] = 'C';
+ buf[pos++] = 'L';
+ buf[pos++] = 'N';
+ buf[pos++] = 'T';
+ // size
+ Buffer::packInt(buf, sizeof(buf), pos, sizeof(uint32_t));
+ // client_version_number
+ Buffer::packInt(buf, sizeof(buf), pos, 1);
+
+ // code - MVE_INSTR_CONFIGURE
+ buf[pos++] = 'C';
+ buf[pos++] = 'N';
+ buf[pos++] = 'F';
+ buf[pos++] = 'G';
+ // size
+ Buffer::packInt(buf, sizeof(buf), pos, 5*sizeof(uint32_t));
+ // configuration
+ Buffer::packInt(buf, sizeof(buf), pos, MVE_INSTR_COUNTERS | MVE_INSTR_EVENTS | MVE_INSTR_ACTIVITIES | MVE_INSTR_PACKED_COMM);
+ // communication_protocol_version
+ Buffer::packInt(buf, sizeof(buf), pos, 1);
+ // data_protocol_version
+ Buffer::packInt(buf, sizeof(buf), pos, 1);
+ // sample_rate - convert samples/second to ms/sample
+ Buffer::packInt(buf, sizeof(buf), pos, 1000/gSessionData->mSampleRate);
+ // live_rate - convert ns/flush to ms/flush
+ Buffer::packInt(buf, sizeof(buf), pos, gSessionData->mLiveRate/1000000);
+
+ // code - MVE_INSTR_ENABLE_COUNTERS
+ buf[pos++] = 'C';
+ buf[pos++] = 'F';
+ buf[pos++] = 'G';
+ buf[pos++] = 'c';
+ marshalEnable(MVCT_COUNTER, buf, sizeof(buf), pos);
+
+ // code - MVE_INSTR_ENABLE_EVENTS
+ buf[pos++] = 'C';
+ buf[pos++] = 'F';
+ buf[pos++] = 'G';
+ buf[pos++] = 'e';
+ marshalEnable(MVCT_EVENT, buf, sizeof(buf), pos);
+
+ /*
+ // code - MVE_INSTR_ENABLE_ACTIVITIES
+ buf[pos++] = 'C';
+ buf[pos++] = 'F';
+ buf[pos++] = 'G';
+ buf[pos++] = 'a';
+ // size
+ Buffer::packInt(buf, sizeof(buf), pos, mActivityCount*sizeof(uint32_t));
+ for (int i = 0; i < mActivityCount; ++i) {
+ // activity_id
+ Buffer::packInt(buf, sizeof(buf), pos, i);
+ }
+ */
+
+ int written = 0;
+ while (written < pos) {
+ size_t bytes = ::write(mveUds, buf + written, pos - written);
+ if (bytes <= 0) {
+ logg->logMessage("%s(%s:%i): write failed", __FUNCTION__, __FILE__, __LINE__);
+ return false;
+ }
+ written += bytes;
+ }
+
+ return true;
+}
diff --git a/daemon/MaliVideoDriver.h b/daemon/MaliVideoDriver.h
new file mode 100644
index 0000000..00cb808
--- /dev/null
+++ b/daemon/MaliVideoDriver.h
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) ARM Limited 2014. 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 MALIVIDEODRIVER_H
+#define MALIVIDEODRIVER_H
+
+#include "Driver.h"
+
+class MaliVideoCounter;
+
+enum MaliVideoCounterType {
+ MVCT_COUNTER,
+ MVCT_EVENT,
+ MVCT_ACTIVITY,
+};
+
+class MaliVideoDriver : public Driver {
+public:
+ MaliVideoDriver();
+ ~MaliVideoDriver();
+
+ void setup(mxml_node_t *const xml);
+
+ bool claimCounter(const Counter &counter) const;
+ bool countersEnabled() const;
+ void resetCounters();
+ void setupCounter(Counter &counter);
+
+ int writeCounters(mxml_node_t *root) const;
+
+ bool start(const int mveUds);
+
+private:
+ MaliVideoCounter *findCounter(const Counter &counter) const;
+ void marshalEnable(const MaliVideoCounterType type, char *const buf, const size_t bufsize, int &pos);
+
+ MaliVideoCounter *mCounters;
+ int mActivityCount;
+
+ // Intentionally unimplemented
+ MaliVideoDriver(const MaliVideoDriver &);
+ MaliVideoDriver &operator=(const MaliVideoDriver &);
+};
+
+#endif // MALIVIDEODRIVER_H
diff --git a/daemon/Monitor.cpp b/daemon/Monitor.cpp
index 90d5c47..b34a15f 100644
--- a/daemon/Monitor.cpp
+++ b/daemon/Monitor.cpp
@@ -18,8 +18,15 @@ Monitor::Monitor() : mFd(-1) {
}
Monitor::~Monitor() {
- if (mFd >= -1) {
- close(mFd);
+ if (mFd >= 0) {
+ ::close(mFd);
+ }
+}
+
+void Monitor::close() {
+ if (mFd >= 0) {
+ ::close(mFd);
+ mFd = -1;
}
}
diff --git a/daemon/Monitor.h b/daemon/Monitor.h
index 6e268b6..7194e0e 100644
--- a/daemon/Monitor.h
+++ b/daemon/Monitor.h
@@ -16,6 +16,7 @@ public:
Monitor();
~Monitor();
+ void close();
bool init();
bool add(const int fd);
int wait(struct epoll_event *const events, int maxevents, int timeout);
diff --git a/daemon/OlySocket.cpp b/daemon/OlySocket.cpp
index 26e4768..28774e3 100644
--- a/daemon/OlySocket.cpp
+++ b/daemon/OlySocket.cpp
@@ -9,6 +9,7 @@
#include "OlySocket.h"
#include <stdio.h>
+#include <string.h>
#ifdef WIN32
#include <Winsock2.h>
#include <ws2tcpip.h>
@@ -43,16 +44,18 @@ OlyServerSocket::OlyServerSocket(int port) {
createServerSocket(port);
}
-OlySocket::OlySocket(int port, const char* host) {
- createClientSocket(host, port);
-}
-
OlySocket::OlySocket(int socketID) : mSocketID(socketID) {
}
#ifndef WIN32
-OlyServerSocket::OlyServerSocket(const char* path) {
+#define MIN(A, B) ({ \
+ const __typeof__(A) __a = A; \
+ const __typeof__(B) __b = B; \
+ __a > __b ? __b : __a; \
+})
+
+OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize) {
// Create socket
mFDServer = socket(PF_UNIX, SOCK_STREAM, 0);
if (mFDServer < 0) {
@@ -60,13 +63,11 @@ OlyServerSocket::OlyServerSocket(const char* path) {
handleException();
}
- unlink(path);
-
// Create sockaddr_in structure, ensuring non-populated fields are zero
struct sockaddr_un sockaddr;
memset((void*)&sockaddr, 0, sizeof(sockaddr));
sockaddr.sun_family = AF_UNIX;
- strncpy(sockaddr.sun_path, path, sizeof(sockaddr.sun_path) - 1);
+ memcpy(sockaddr.sun_path, path, MIN(pathSize, sizeof(sockaddr.sun_path)));
sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0';
// Bind the socket to an address
@@ -82,24 +83,25 @@ OlyServerSocket::OlyServerSocket(const char* path) {
}
}
-OlySocket::OlySocket(const char* path) {
- mSocketID = socket(PF_UNIX, SOCK_STREAM, 0);
- if (mSocketID < 0) {
- return;
+int OlySocket::connect(const char* path, const size_t pathSize) {
+ int fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ return -1;
}
// Create sockaddr_in structure, ensuring non-populated fields are zero
struct sockaddr_un sockaddr;
memset((void*)&sockaddr, 0, sizeof(sockaddr));
sockaddr.sun_family = AF_UNIX;
- strncpy(sockaddr.sun_path, path, sizeof(sockaddr.sun_path) - 1);
+ memcpy(sockaddr.sun_path, path, MIN(pathSize, sizeof(sockaddr.sun_path)));
sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0';
- if (connect(mSocketID, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
- close(mSocketID);
- mSocketID = -1;
- return;
+ if (::connect(fd, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
+ close(fd);
+ return -1;
}
+
+ return fd;
}
#endif
@@ -137,47 +139,6 @@ void OlyServerSocket::closeServerSocket() {
mFDServer = 0;
}
-void OlySocket::createClientSocket(const char* hostname, int portno) {
-#ifdef WIN32
- // TODO: Implement for Windows
-#else
- char buf[32];
- struct addrinfo hints, *res, *res0;
-
- snprintf(buf, sizeof(buf), "%d", portno);
- mSocketID = -1;
- memset((void*)&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
-
- if (getaddrinfo(hostname, buf, &hints, &res0)) {
- logg->logError(__FILE__, __LINE__, "Client socket failed to get address info for %s", hostname);
- handleException();
- }
- for (res=res0; res!=NULL; res = res->ai_next) {
- if ( res->ai_family != PF_INET || res->ai_socktype != SOCK_STREAM ) {
- continue;
- }
- mSocketID = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (mSocketID < 0) {
- continue;
- }
- if (connect(mSocketID, res->ai_addr, res->ai_addrlen) < 0) {
- close(mSocketID);
- mSocketID = -1;
- }
- if (mSocketID > 0) {
- break;
- }
- }
- freeaddrinfo(res0);
- if (mSocketID <= 0) {
- logg->logError(__FILE__, __LINE__, "Could not connect to client socket. Ensure ARM Streamline is running.");
- handleException();
- }
-#endif
-}
-
void OlyServerSocket::createServerSocket(int port) {
int family = AF_INET6;
diff --git a/daemon/OlySocket.h b/daemon/OlySocket.h
index eab786b..20c67cc 100644
--- a/daemon/OlySocket.h
+++ b/daemon/OlySocket.h
@@ -9,13 +9,15 @@
#ifndef __OLY_SOCKET_H__
#define __OLY_SOCKET_H__
+#include <stddef.h>
+
class OlySocket {
public:
- OlySocket(int port, const char* hostname);
- OlySocket(int socketID);
#ifndef WIN32
- OlySocket(const char* path);
+ static int connect(const char* path, const size_t pathSize);
#endif
+
+ OlySocket(int socketID);
~OlySocket();
void closeSocket();
@@ -29,21 +31,21 @@ public:
private:
int mSocketID;
-
- void createClientSocket(const char* hostname, int port);
};
class OlyServerSocket {
public:
OlyServerSocket(int port);
#ifndef WIN32
- OlyServerSocket(const char* path);
+ OlyServerSocket(const char* path, const size_t pathSize);
#endif
~OlyServerSocket();
int acceptConnection();
void closeServerSocket();
+ int getFd() { return mFDServer; }
+
private:
int mFDServer;
diff --git a/daemon/PerfDriver.cpp b/daemon/PerfDriver.cpp
index 8e25c22..ac97a07 100644
--- a/daemon/PerfDriver.cpp
+++ b/daemon/PerfDriver.cpp
@@ -11,6 +11,7 @@
#include <dirent.h>
#include <sys/utsname.h>
#include <time.h>
+#include <unistd.h>
#include "Buffer.h"
#include "Config.h"
@@ -30,7 +31,7 @@
struct gator_cpu {
const int cpuid;
// Human readable name
- const char core_name[32];
+ const char *const core_name;
// gatorfs event and Perf PMU name
const char *const pmnc_name;
const int pmnc_counters;
@@ -62,9 +63,20 @@ static const struct gator_cpu gator_cpus[] = {
static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-";
static const char NEW_PMU_PREFIX[] = "ARMv7_Cortex_";
+struct uncore_counter {
+ // gatorfs event and Perf PMU name
+ const char *const name;
+ const int count;
+};
+
+static const struct uncore_counter uncore_counters[] = {
+ { "CCI_400", 4 },
+ { "CCI_400-r1", 4 },
+};
+
class PerfCounter {
public:
- PerfCounter(PerfCounter *next, const char *name, uint32_t type, uint64_t config) : mNext(next), mName(name), mType(type), mCount(0), mKey(getEventKey()), mConfig(config), mEnabled(false) {}
+ PerfCounter(PerfCounter *next, const char *name, uint32_t type, uint64_t config, bool perCpu) : mNext(next), mName(name), mType(type), mCount(0), mKey(getEventKey()), mConfig(config), mEnabled(false), mPerCpu(perCpu) {}
~PerfCounter() {
delete [] mName;
}
@@ -79,6 +91,7 @@ public:
void setConfig(const uint64_t config) { mConfig = config; }
bool isEnabled() const { return mEnabled; }
void setEnabled(const bool enabled) { mEnabled = enabled; }
+ bool isPerCpu() const { return mPerCpu; }
private:
PerfCounter *const mNext;
@@ -87,10 +100,11 @@ private:
int mCount;
const int mKey;
uint64_t mConfig;
- bool mEnabled;
+ int mEnabled : 1,
+ mPerCpu : 1;
};
-PerfDriver::PerfDriver() : mCounters(NULL), mIsSetup(false) {
+PerfDriver::PerfDriver() : mCounters(NULL), mIsSetup(false), mLegacySupport(false) {
}
PerfDriver::~PerfDriver() {
@@ -105,13 +119,27 @@ void PerfDriver::addCpuCounters(const char *const counterName, const int type, c
int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1;
char *name = new char[len];
snprintf(name, len, "%s_ccnt", counterName);
- mCounters = new PerfCounter(mCounters, name, type, -1);
+ mCounters = new PerfCounter(mCounters, name, type, -1, true);
for (int j = 0; j < numCounters; ++j) {
len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1;
name = new char[len];
snprintf(name, len, "%s_cnt%d", counterName, j);
- mCounters = new PerfCounter(mCounters, name, type, -1);
+ mCounters = new PerfCounter(mCounters, name, type, -1, true);
+ }
+}
+
+void PerfDriver::addUncoreCounters(const char *const counterName, const int type, const int numCounters) {
+ int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1;
+ char *name = new char[len];
+ snprintf(name, len, "%s_ccnt", counterName);
+ mCounters = new PerfCounter(mCounters, name, type, -1, false);
+
+ for (int j = 0; j < numCounters; ++j) {
+ len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1;
+ name = new char[len];
+ snprintf(name, len, "%s_cnt%d", counterName, j);
+ mCounters = new PerfCounter(mCounters, name, type, -1, false);
}
}
@@ -139,10 +167,16 @@ bool PerfDriver::setup() {
}
}
- if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0)) {
+ if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 4, 0)) {
logg->logMessage("%s(%s:%i): Unsupported kernel version", __FUNCTION__, __FILE__, __LINE__);
return false;
}
+ mLegacySupport = KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0);
+
+ if (access(EVENTS_PATH, R_OK) != 0) {
+ logg->logMessage("%s(%s:%i): " EVENTS_PATH " does not exist, is CONFIG_TRACING enabled?", __FUNCTION__, __FILE__, __LINE__);
+ return false;
+ }
// Add supported PMUs
bool foundCpu = false;
@@ -174,6 +208,21 @@ bool PerfDriver::setup() {
foundCpu = true;
addCpuCounters(gator_cpus[i].pmnc_name, type, gator_cpus[i].pmnc_counters);
}
+
+ for (int i = 0; i < ARRAY_LENGTH(uncore_counters); ++i) {
+ if (strcmp(dirent->d_name, uncore_counters[i].name) != 0) {
+ continue;
+ }
+
+ int type;
+ char buf[256];
+ snprintf(buf, sizeof(buf), PERF_DEVICES "/%s/type", dirent->d_name);
+ if (DriverSource::readIntDriver(buf, &type) != 0) {
+ continue;
+ }
+
+ addUncoreCounters(uncore_counters[i].name, type, uncore_counters[i].count);
+ }
}
closedir(dir);
@@ -203,12 +252,12 @@ bool PerfDriver::setup() {
id = getTracepointId("irq/softirq_exit", &printb);
if (id >= 0) {
- mCounters = new PerfCounter(mCounters, "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id);
+ mCounters = new PerfCounter(mCounters, "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id, true);
}
id = getTracepointId("irq/irq_handler_exit", &printb);
if (id >= 0) {
- mCounters = new PerfCounter(mCounters, "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id);
+ mCounters = new PerfCounter(mCounters, "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id, true);
}
//Linux_block_rq_wr
@@ -218,7 +267,7 @@ bool PerfDriver::setup() {
id = getTracepointId(SCHED_SWITCH, &printb);
if (id >= 0) {
- mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id);
+ mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, true);
}
//Linux_meminfo_memused
@@ -227,7 +276,7 @@ bool PerfDriver::setup() {
//Linux_power_cpu_freq
//Linux_power_cpu_idle
- mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1);
+ mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1, false);
//Linux_cpu_wait_io
@@ -252,15 +301,16 @@ bool PerfDriver::summary(Buffer *const buffer) {
}
const int64_t timestamp = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec;
- if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
- logg->logMessage("%s(%s:%i): clock_gettime failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- const int64_t uptime = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec;
+ const int64_t uptime = getTime();
buffer->summary(timestamp, uptime, 0, buf);
for (int i = 0; i < gSessionData->mCores; ++i) {
+ // Don't send information on a cpu we know nothing about
+ if (gSessionData->mCpuIds[i] == -1) {
+ continue;
+ }
+
int j;
for (j = 0; j < ARRAY_LENGTH(gator_cpus); ++j) {
if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) {
@@ -270,7 +320,11 @@ bool PerfDriver::summary(Buffer *const buffer) {
if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) {
buffer->coreName(i, gSessionData->mCpuIds[i], gator_cpus[j].core_name);
} else {
- snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[i]);
+ if (gSessionData->mCpuIds[i] == -1) {
+ snprintf(buf, sizeof(buf), "Unknown");
+ } else {
+ snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[i]);
+ }
buffer->coreName(i, gSessionData->mCpuIds[i], buf);
}
}
@@ -326,10 +380,10 @@ int PerfDriver::writeCounters(mxml_node_t *root) const {
return count;
}
-bool PerfDriver::enable(PerfGroup *group, Buffer *const buffer) const {
+bool PerfDriver::enable(PerfGroup *const group, Buffer *const buffer) const {
for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
if (counter->isEnabled() && (counter->getType() != TYPE_DERIVED)) {
- if (!group->add(buffer, counter->getKey(), counter->getType(), counter->getConfig(), counter->getCount(), 0, 0)) {
+ if (!group->add(buffer, counter->getKey(), counter->getType(), counter->getConfig(), counter->getCount(), counter->getCount() > 0 ? PERF_SAMPLE_TID | PERF_SAMPLE_IP : 0, counter->isPerCpu() ? PERF_GROUP_PER_CPU : 0)) {
logg->logMessage("%s(%s:%i): PerfGroup::add failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
diff --git a/daemon/PerfDriver.h b/daemon/PerfDriver.h
index 3181b74..2cae575 100644
--- a/daemon/PerfDriver.h
+++ b/daemon/PerfDriver.h
@@ -27,6 +27,8 @@ public:
PerfDriver();
~PerfDriver();
+ bool getLegacySupport() const { return mLegacySupport; }
+
bool setup();
bool summary(Buffer *const buffer);
bool isSetup() const { return mIsSetup; }
@@ -37,16 +39,18 @@ public:
int writeCounters(mxml_node_t *root) const;
- bool enable(PerfGroup *group, Buffer *const buffer) const;
+ bool enable(PerfGroup *const group, Buffer *const buffer) const;
static long long getTracepointId(const char *const name, DynBuf *const printb);
private:
PerfCounter *findCounter(const Counter &counter) const;
void addCpuCounters(const char *const counterName, const int type, const int numCounters);
+ void addUncoreCounters(const char *const counterName, const int type, const int numCounters);
PerfCounter *mCounters;
bool mIsSetup;
+ bool mLegacySupport;
// Intentionally undefined
PerfDriver(const PerfDriver &);
diff --git a/daemon/PerfGroup.cpp b/daemon/PerfGroup.cpp
index faf5fca..2a0239f 100644
--- a/daemon/PerfGroup.cpp
+++ b/daemon/PerfGroup.cpp
@@ -23,7 +23,9 @@
#define DEFAULT_PEA_ARGS(pea, additionalSampleType) \
pea.size = sizeof(pea); \
/* Emit time, read_format below, group leader id, and raw tracepoint info */ \
- pea.sample_type = PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_IDENTIFIER | additionalSampleType; \
+ pea.sample_type = (gSessionData->perf.getLegacySupport() \
+ ? PERF_SAMPLE_TID | PERF_SAMPLE_IP | PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_ID \
+ : PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_IDENTIFIER ) | additionalSampleType; \
/* Emit emit value in group format */ \
pea.read_format = PERF_FORMAT_ID | PERF_FORMAT_GROUP; \
/* start out disabled */ \
@@ -39,6 +41,7 @@ static int sys_perf_event_open(struct perf_event_attr *const attr, const pid_t p
PerfGroup::PerfGroup(PerfBuffer *const pb) : mPb(pb) {
memset(&mAttrs, 0, sizeof(mAttrs));
+ memset(&mPerCpu, 0, sizeof(mPerCpu));
memset(&mKeys, -1, sizeof(mKeys));
memset(&mFds, -1, sizeof(mFds));
}
@@ -75,6 +78,7 @@ bool PerfGroup::add(Buffer *const buffer, const int key, const __u32 type, const
mAttrs[i].freq = (flags & PERF_GROUP_FREQ ? 1 : 0);
mAttrs[i].task = (flags & PERF_GROUP_TASK ? 1 : 0);
mAttrs[i].sample_id_all = (flags & PERF_GROUP_SAMPLE_ID_ALL ? 1 : 0);
+ mPerCpu[i] = (flags & PERF_GROUP_PER_CPU);
mKeys[i] = key;
@@ -91,13 +95,17 @@ bool PerfGroup::prepareCPU(const int cpu) {
continue;
}
+ if ((cpu != 0) && !mPerCpu[i]) {
+ continue;
+ }
+
const int offset = i * gSessionData->mCores;
if (mFds[cpu + offset] >= 0) {
logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__);
return false;
}
- logg->logMessage("%s(%s:%i): perf_event_open cpu: %i type: %lli config: %lli sample: %lli sample_type: %lli", __FUNCTION__, __FILE__, __LINE__, cpu, (long long)mAttrs[i].type, (long long)mAttrs[i].config, (long long)mAttrs[i].sample_period, (long long)mAttrs[i].sample_type);
+ logg->logMessage("%s(%s:%i): perf_event_open cpu: %i type: %lli config: %lli sample: %lli sample_type: 0x%llx pinned: %i mmap: %i comm: %i freq: %i task: %i sample_id_all: %i", __FUNCTION__, __FILE__, __LINE__, cpu, (long long)mAttrs[i].type, (long long)mAttrs[i].config, (long long)mAttrs[i].sample_period, (long long)mAttrs[i].sample_type, mAttrs[i].pinned, mAttrs[i].mmap, mAttrs[i].comm, mAttrs[i].freq, mAttrs[i].task, mAttrs[i].sample_id_all);
mFds[cpu + offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, i == 0 ? -1 : mFds[cpu], i == 0 ? 0 : PERF_FLAG_FD_OUTPUT);
if (mFds[cpu + offset] < 0) {
logg->logMessage("%s(%s:%i): failed %s", __FUNCTION__, __FILE__, __LINE__, strerror(errno));
@@ -125,7 +133,9 @@ int PerfGroup::onlineCPU(const int cpu, const bool start, Buffer *const buffer,
}
coreKeys[idCount] = mKeys[i];
- if (ioctl(fd, PERF_EVENT_IOC_ID, &ids[idCount]) != 0) {
+ if (!gSessionData->perf.getLegacySupport() && ioctl(fd, PERF_EVENT_IOC_ID, &ids[idCount]) != 0 &&
+ // Workaround for running 32-bit gatord on 64-bit systems, kernel patch in the works
+ ioctl(fd, (PERF_EVENT_IOC_ID & ~IOCSIZE_MASK) | (8 << _IOC_SIZESHIFT), &ids[idCount]) != 0) {
logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
@@ -137,7 +147,17 @@ int PerfGroup::onlineCPU(const int cpu, const bool start, Buffer *const buffer,
return false;
}
- buffer->keys(idCount, ids, coreKeys);
+ if (!gSessionData->perf.getLegacySupport()) {
+ buffer->keys(idCount, ids, coreKeys);
+ } else {
+ char buf[1024];
+ ssize_t bytes = read(mFds[cpu], buf, sizeof(buf));
+ if (bytes < 0) {
+ logg->logMessage("read failed");
+ return false;
+ }
+ buffer->keysOld(idCount, coreKeys, bytes, buf);
+ }
if (start) {
for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
diff --git a/daemon/PerfGroup.h b/daemon/PerfGroup.h
index af496d4..3f1e2bb 100644
--- a/daemon/PerfGroup.h
+++ b/daemon/PerfGroup.h
@@ -24,6 +24,7 @@ enum PerfGroupFlags {
PERF_GROUP_FREQ = 1 << 2,
PERF_GROUP_TASK = 1 << 3,
PERF_GROUP_SAMPLE_ID_ALL = 1 << 4,
+ PERF_GROUP_PER_CPU = 1 << 5,
};
class PerfGroup {
@@ -43,6 +44,7 @@ public:
private:
// +1 for the group leader
struct perf_event_attr mAttrs[MAX_PERFORMANCE_COUNTERS + 1];
+ bool mPerCpu[MAX_PERFORMANCE_COUNTERS + 1];
int mKeys[MAX_PERFORMANCE_COUNTERS + 1];
int mFds[NR_CPUS * (MAX_PERFORMANCE_COUNTERS + 1)];
PerfBuffer *const mPb;
diff --git a/daemon/PerfSource.cpp b/daemon/PerfSource.cpp
index 1f1cb19..ecfaa66 100644
--- a/daemon/PerfSource.cpp
+++ b/daemon/PerfSource.cpp
@@ -37,7 +37,7 @@ static bool sendTracepointFormat(Buffer *const buffer, const char *const name, D
return true;
}
-PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAME_SUMMARY, 1024, senderSem), mBuffer(0, FRAME_PERF_ATTRS, 1024*1024, senderSem), mCountersBuf(), mCountersGroup(&mCountersBuf), mMonitor(), mUEvent(), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false) {
+PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAME_SUMMARY, 1024, senderSem), mBuffer(0, FRAME_PERF_ATTRS, 4*1024*1024, senderSem), mCountersBuf(), mCountersGroup(&mCountersBuf), mMonitor(), mUEvent(), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false) {
long l = sysconf(_SC_PAGE_SIZE);
if (l < 0) {
logg->logError(__FILE__, __LINE__, "Unable to obtain the page size");
@@ -74,6 +74,9 @@ bool PerfSource::prepare() {
DynBuf b3;
long long schedSwitchId;
+ // Reread cpuinfo since cores may have changed since startup
+ gSessionData->readCpuInfo();
+
if (0
|| !mMonitor.init()
|| !mUEvent.init()
@@ -83,14 +86,14 @@ bool PerfSource::prepare() {
|| !sendTracepointFormat(&mBuffer, SCHED_SWITCH, &printb, &b1)
// Only want RAW but not IP on sched_switch and don't want TID on SAMPLE_ID
- || !mCountersGroup.add(&mBuffer, 100/**/, PERF_TYPE_TRACEPOINT, schedSwitchId, 1, PERF_SAMPLE_RAW, PERF_GROUP_MMAP | PERF_GROUP_COMM | PERF_GROUP_TASK | PERF_GROUP_SAMPLE_ID_ALL)
+ || !mCountersGroup.add(&mBuffer, 100/**/, PERF_TYPE_TRACEPOINT, schedSwitchId, 1, PERF_SAMPLE_RAW, PERF_GROUP_MMAP | PERF_GROUP_COMM | PERF_GROUP_TASK | PERF_GROUP_SAMPLE_ID_ALL | PERF_GROUP_PER_CPU)
// Only want TID and IP but not RAW on timer
- || (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && !mCountersGroup.add(&mBuffer, 99/**/, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP, 0))
+ || (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && !mCountersGroup.add(&mBuffer, 99/**/, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP, PERF_GROUP_PER_CPU))
|| !gSessionData->perf.enable(&mCountersGroup, &mBuffer)
|| 0) {
- logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.12 or later?", __FUNCTION__, __FILE__, __LINE__);
+ logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.4 or later?", __FUNCTION__, __FILE__, __LINE__);
return false;
}
@@ -134,7 +137,7 @@ bool PerfSource::prepare() {
return false;
}
- if (!readProc(&mBuffer, &printb, &b1, &b2, &b3)) {
+ if (!readProc(&mBuffer, true, &printb, &b1, &b2, &b3)) {
logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
@@ -260,6 +263,7 @@ bool PerfSource::isDone () {
void PerfSource::write (Sender *sender) {
if (!mSummary.isDone()) {
mSummary.write(sender);
+ gSessionData->mSentSummary = true;
}
if (!mBuffer.isDone()) {
mBuffer.write(sender);
diff --git a/daemon/Proc.cpp b/daemon/Proc.cpp
index e0b9e22..9f01770 100644
--- a/daemon/Proc.cpp
+++ b/daemon/Proc.cpp
@@ -57,14 +57,57 @@ static bool readProcStat(ProcStat *const ps, const char *const pathname, DynBuf
return true;
}
-static bool readProcTask(Buffer *const buffer, const int pid, const char *const image, DynBuf *const printb, DynBuf *const b) {
+static const char *readProcExe(DynBuf *const printb, const int pid, const int tid, DynBuf *const b) {
+ if (tid == -1 ? !printb->printf("/proc/%i/exe", pid)
+ : !printb->printf("/proc/%i/task/%i/exe", pid, tid)) {
+ logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+ return NULL;
+ }
+
+ const int err = b->readlink(printb->getBuf());
+ const char *image;
+ if (err == 0) {
+ image = strrchr(b->getBuf(), '/');
+ if (image == NULL) {
+ image = b->getBuf();
+ } else {
+ ++image;
+ }
+ } else if (err == -ENOENT) {
+ // readlink /proc/[pid]/exe returns ENOENT for kernel threads
+ image = "\0";
+ } else {
+ logg->logMessage("%s(%s:%i): DynBuf::readlink failed", __FUNCTION__, __FILE__, __LINE__);
+ return NULL;
+ }
+
+ // Android apps are run by app_process but the cmdline is changed to reference the actual app name
+ if (strcmp(image, "app_process") != 0) {
+ return image;
+ }
+
+ if (tid == -1 ? !printb->printf("/proc/%i/cmdline", pid)
+ : !printb->printf("/proc/%i/task/%i/cmdline", pid, tid)) {
+ logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+ return NULL;
+ }
+
+ if (!b->read(printb->getBuf())) {
+ logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the thread exited", __FUNCTION__, __FILE__, __LINE__);
+ return NULL;
+ }
+
+ return b->getBuf();
+}
+
+static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) {
bool result = false;
- if (!b->printf("/proc/%i/task", pid)) {
+ if (!b1->printf("/proc/%i/task", pid)) {
logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
return result;
}
- DIR *task = opendir(b->getBuf());
+ DIR *task = opendir(b1->getBuf());
if (task == NULL) {
logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__);
return result;
@@ -84,11 +127,17 @@ static bool readProcTask(Buffer *const buffer, const int pid, const char *const
goto fail;
}
ProcStat ps;
- if (!readProcStat(&ps, printb->getBuf(), b)) {
+ if (!readProcStat(&ps, printb->getBuf(), b1)) {
logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__);
goto fail;
}
+ const char *const image = readProcExe(printb, pid, tid, b2);
+ if (image == NULL) {
+ logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__);
+ goto fail;
+ }
+
buffer->comm(pid, tid, image, ps.comm);
}
@@ -100,7 +149,7 @@ static bool readProcTask(Buffer *const buffer, const int pid, const char *const
return result;
}
-bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) {
+bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) {
bool result = false;
DIR *proc = opendir("/proc");
@@ -128,42 +177,29 @@ bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynB
goto fail;
}
- if (!printb->printf("/proc/%i/exe", pid)) {
- logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
- const int err = b1->readlink(printb->getBuf());
- const char *image;
- if (err == 0) {
- image = strrchr(b1->getBuf(), '/');
- if (image == NULL) {
- image = b1->getBuf();
- } else {
- ++image;
+ if (sendMaps) {
+ if (!printb->printf("/proc/%i/maps", pid)) {
+ logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+ goto fail;
+ }
+ if (!b2->read(printb->getBuf())) {
+ logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__);
+ // This is not a fatal error - the process just doesn't exist any more
+ continue;
}
- } else if (err == -ENOENT) {
- // readlink /proc/[pid]/exe returns ENOENT for kernel threads
- image = "\0";
- } else {
- logg->logMessage("%s(%s:%i): DynBuf::readlink failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
- if (!printb->printf("/proc/%i/maps", pid)) {
- logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
+ buffer->maps(pid, pid, b2->getBuf());
}
- if (!b2->read(printb->getBuf())) {
- logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__);
- // This is not a fatal error - the process just doesn't exist any more
- continue;
- }
-
- buffer->maps(pid, pid, b2->getBuf());
if (ps.numThreads <= 1) {
+ const char *const image = readProcExe(printb, pid, -1, b1);
+ if (image == NULL) {
+ logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__);
+ goto fail;
+ }
+
buffer->comm(pid, pid, image, ps.comm);
} else {
- if (!readProcTask(buffer, pid, image, printb, b3)) {
+ if (!readProcTask(buffer, pid, printb, b1, b3)) {
logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__);
goto fail;
}
diff --git a/daemon/Proc.h b/daemon/Proc.h
index 057b610..31c2eec 100644
--- a/daemon/Proc.h
+++ b/daemon/Proc.h
@@ -12,6 +12,6 @@
class Buffer;
class DynBuf;
-bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3);
+bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3);
#endif // PROC_H
diff --git a/daemon/Sender.h b/daemon/Sender.h
index 4c359db..33b6cc3 100644
--- a/daemon/Sender.h
+++ b/daemon/Sender.h
@@ -39,4 +39,4 @@ private:
Sender &operator=(const Sender &);
};
-#endif //__SENDER_H__
+#endif //__SENDER_H__
diff --git a/daemon/SessionData.cpp b/daemon/SessionData.cpp
index c169299..14d995f 100644
--- a/daemon/SessionData.cpp
+++ b/daemon/SessionData.cpp
@@ -9,6 +9,7 @@
#include "SessionData.h"
#include <string.h>
+#include <sys/mman.h>
#include "SessionXML.h"
#include "Logging.h"
@@ -27,6 +28,15 @@ void SessionData::initialize() {
mSessionIsActive = false;
mLocalCapture = false;
mOneShot = false;
+ mSentSummary = false;
+ const size_t cpuIdSize = sizeof(int)*NR_CPUS;
+ // Share mCpuIds across all instances of gatord
+ mCpuIds = (int *)mmap(NULL, cpuIdSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ if (mCpuIds == MAP_FAILED) {
+ logg->logError(__FILE__, __LINE__, "Unable to mmap shared memory for cpuids");
+ handleException();
+ }
+ memset(mCpuIds, -1, cpuIdSize);
readCpuInfo();
mConfigurationXMLPath = NULL;
mSessionXMLPath = NULL;
@@ -91,10 +101,9 @@ void SessionData::parseSessionXML(char* xmlString) {
void SessionData::readCpuInfo() {
char temp[256]; // arbitrarily large amount
strcpy(mCoreName, "unknown");
- memset(&mCpuIds, -1, sizeof(mCpuIds));
mMaxCpuId = -1;
- FILE* f = fopen("/proc/cpuinfo", "r");
+ FILE* f = fopen("/proc/cpuinfo", "r");
if (f == NULL) {
logg->logMessage("Error opening /proc/cpuinfo\n"
"The core name in the captured xml file will be 'unknown'.");
@@ -102,10 +111,18 @@ void SessionData::readCpuInfo() {
}
bool foundCoreName = false;
- int processor = 0;
+ int processor = -1;
while (fgets(temp, sizeof(temp), f)) {
- if (strlen(temp) > 0) {
- temp[strlen(temp) - 1] = 0; // Replace the line feed with a null
+ const size_t len = strlen(temp);
+
+ if (len == 1) {
+ // New section, clear the processor. Streamline will not know the cpus if the pre Linux 3.8 format of cpuinfo is encountered but also that no incorrect information will be transmitted.
+ processor = -1;
+ continue;
+ }
+
+ if (len > 0) {
+ temp[len - 1] = '\0'; // Replace the line feed with a null
}
const bool foundHardware = strstr(temp, "Hardware") != 0;
@@ -127,10 +144,15 @@ void SessionData::readCpuInfo() {
}
if (foundCPUPart) {
- mCpuIds[processor] = strtol(position, NULL, 0);
+ const int cpuId = strtol(position, NULL, 0);
// If this does not have the full topology in /proc/cpuinfo, mCpuIds[0] may not have the 1 CPU part emitted - this guarantees it's in mMaxCpuId
- if (mCpuIds[processor] > mMaxCpuId) {
- mMaxCpuId = mCpuIds[processor];
+ if (cpuId > mMaxCpuId) {
+ mMaxCpuId = cpuId;
+ }
+ if (processor >= NR_CPUS) {
+ logg->logMessage("Too many processors, please increase NR_CPUS");
+ } else if (processor >= 0) {
+ mCpuIds[processor] = cpuId;
}
}
@@ -142,10 +164,23 @@ void SessionData::readCpuInfo() {
if (!foundCoreName) {
logg->logMessage("Could not determine core name from /proc/cpuinfo\n"
- "The core name in the captured xml file will be 'unknown'.");
+ "The core name in the captured xml file will be 'unknown'.");
}
fclose(f);
- }
+}
+
+uint64_t getTime() {
+ struct timespec ts;
+#ifndef CLOCK_MONOTONIC_RAW
+ // Android doesn't have this defined but it was added in Linux 2.6.28
+#define CLOCK_MONOTONIC_RAW 4
+#endif
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
+ logg->logError(__FILE__, __LINE__, "Failed to get uptime");
+ handleException();
+ }
+ return (NS_PER_S*ts.tv_sec + ts.tv_nsec);
+}
int getEventKey() {
// key 0 is reserved as a timestamp
diff --git a/daemon/SessionData.h b/daemon/SessionData.h
index ea34240..835082d 100644
--- a/daemon/SessionData.h
+++ b/daemon/SessionData.h
@@ -13,12 +13,16 @@
#include "Config.h"
#include "Counter.h"
+#include "FSDriver.h"
#include "Hwmon.h"
+#include "MaliVideoDriver.h"
#include "PerfDriver.h"
-#define PROTOCOL_VERSION 18
+#define PROTOCOL_VERSION 19
#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions
+#define NS_PER_S ((uint64_t)1000000000)
+
struct ImageLinkList {
char* path;
struct ImageLinkList *next;
@@ -32,9 +36,12 @@ public:
~SessionData();
void initialize();
void parseSessionXML(char* xmlString);
+ void readCpuInfo();
Hwmon hwmon;
+ FSDriver fsDriver;
PerfDriver perf;
+ MaliVideoDriver maliVideo;
char mCoreName[MAX_STRING_LEN];
struct ImageLinkList *mImages;
@@ -49,7 +56,8 @@ public:
bool mLocalCapture;
bool mOneShot; // halt processing of the driver data until profiling is complete or the buffer is filled
bool mIsEBS;
-
+ bool mSentSummary;
+
int mBacktraceDepth;
int mTotalBufferSize; // number of MB to use for the entire collection buffer
int mSampleRate;
@@ -57,7 +65,7 @@ public:
int mDuration;
int mCores;
int mPageSize;
- int mCpuIds[NR_CPUS];
+ int *mCpuIds;
int mMaxCpuId;
// PMU Counters
@@ -65,8 +73,6 @@ public:
Counter mCounters[MAX_PERFORMANCE_COUNTERS];
private:
- void readCpuInfo();
-
// Intentionally unimplemented
SessionData(const SessionData &);
SessionData &operator=(const SessionData &);
@@ -74,6 +80,7 @@ private:
extern SessionData* gSessionData;
+uint64_t getTime();
int getEventKey();
#endif // SESSION_DATA_H
diff --git a/daemon/SessionXML.cpp b/daemon/SessionXML.cpp
index 55b2f92..8cdc940 100644
--- a/daemon/SessionXML.cpp
+++ b/daemon/SessionXML.cpp
@@ -17,15 +17,15 @@
#include "SessionData.h"
static const char* TAG_SESSION = "session";
-static const char* TAG_IMAGE = "image";
+static const char* TAG_IMAGE = "image";
-static const char* ATTR_VERSION = "version";
+static const char* ATTR_VERSION = "version";
static const char* ATTR_CALL_STACK_UNWINDING = "call_stack_unwinding";
static const char* ATTR_BUFFER_MODE = "buffer_mode";
-static const char* ATTR_SAMPLE_RATE = "sample_rate";
+static const char* ATTR_SAMPLE_RATE = "sample_rate";
static const char* ATTR_DURATION = "duration";
static const char* ATTR_PATH = "path";
-static const char* ATTR_LIVE_RATE = "live_rate";
+static const char* ATTR_LIVE_RATE = "live_rate";
SessionXML::SessionXML(const char *str) {
parameters.buffer_mode[0] = 0;
diff --git a/daemon/StreamlineSetup.cpp b/daemon/StreamlineSetup.cpp
index caa665e..2b61eae 100644
--- a/daemon/StreamlineSetup.cpp
+++ b/daemon/StreamlineSetup.cpp
@@ -266,7 +266,7 @@ void StreamlineSetup::writeConfiguration(char* xml) {
{ ConfigurationXML configuration; }
if (gSessionData->mCounterOverflow > 0) {
- logg->logError(__FILE__, __LINE__, "Only %i performance counters counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow);
+ logg->logError(__FILE__, __LINE__, "Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow);
handleException();
}
}
diff --git a/daemon/StreamlineSetup.h b/daemon/StreamlineSetup.h
index 74bb197..b380f46 100644
--- a/daemon/StreamlineSetup.h
+++ b/daemon/StreamlineSetup.h
@@ -21,7 +21,7 @@ enum {
COMMAND_APC_START = 2,
COMMAND_APC_STOP = 3,
COMMAND_DISCONNECT = 4,
- COMMAND_PING = 5
+ COMMAND_PING = 5
};
class StreamlineSetup {
@@ -47,4 +47,4 @@ private:
StreamlineSetup &operator=(const StreamlineSetup &);
};
-#endif //__STREAMLINE_SETUP_H__
+#endif //__STREAMLINE_SETUP_H__
diff --git a/daemon/UEvent.cpp b/daemon/UEvent.cpp
index 282e965..54d4575 100644
--- a/daemon/UEvent.cpp
+++ b/daemon/UEvent.cpp
@@ -8,11 +8,12 @@
#include "UEvent.h"
-#include <linux/netlink.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
+#include <linux/netlink.h>
+
#include "Logging.h"
static const char EMPTY[] = "";
diff --git a/daemon/UserSpaceSource.cpp b/daemon/UserSpaceSource.cpp
index debe696..8c328e0 100644
--- a/daemon/UserSpaceSource.cpp
+++ b/daemon/UserSpaceSource.cpp
@@ -16,7 +16,6 @@
#include "Logging.h"
#include "SessionData.h"
-#define NS_PER_S ((uint64_t)1000000000)
#define NS_PER_US 1000
extern Child *child;
@@ -35,6 +34,7 @@ void UserSpaceSource::run() {
prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0);
gSessionData->hwmon.start();
+ gSessionData->fsDriver.start();
int64_t monotonic_started = 0;
while (monotonic_started <= 0) {
@@ -48,16 +48,7 @@ void UserSpaceSource::run() {
uint64_t next_time = 0;
while (gSessionData->mSessionIsActive) {
- struct timespec ts;
-#ifndef CLOCK_MONOTONIC_RAW
- // Android doesn't have this defined but it was added in Linux 2.6.28
-#define CLOCK_MONOTONIC_RAW 4
-#endif
- if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
- logg->logError(__FILE__, __LINE__, "Failed to get uptime");
- handleException();
- }
- const uint64_t curr_time = (NS_PER_S*ts.tv_sec + ts.tv_nsec) - monotonic_started;
+ const uint64_t curr_time = getTime() - monotonic_started;
// Sample ten times a second ignoring gSessionData->mSampleRate
next_time += NS_PER_S/10;//gSessionData->mSampleRate;
if (next_time < curr_time) {
@@ -67,6 +58,7 @@ void UserSpaceSource::run() {
if (mBuffer.eventHeader(curr_time)) {
gSessionData->hwmon.read(&mBuffer);
+ gSessionData->fsDriver.read(&mBuffer);
// Only check after writing all counters so that time and corresponding counters appear in the same frame
mBuffer.check(curr_time);
}
diff --git a/daemon/UserSpaceSource.h b/daemon/UserSpaceSource.h
index fb5889d..9b36660 100644
--- a/daemon/UserSpaceSource.h
+++ b/daemon/UserSpaceSource.h
@@ -14,7 +14,7 @@
#include "Buffer.h"
#include "Source.h"
-// User space counters - currently just hwmon
+// User space counters
class UserSpaceSource : public Source {
public:
UserSpaceSource(sem_t *senderSem);
diff --git a/daemon/c++.cpp b/daemon/c++.cpp
new file mode 100644
index 0000000..6041e5e
--- /dev/null
+++ b/daemon/c++.cpp
@@ -0,0 +1,40 @@
+/**
+ * Minimal set of C++ functions so that libstdc++ is not required
+ *
+ * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void operator delete(void *ptr) {
+ if (ptr != NULL) {
+ free(ptr);
+ }
+}
+
+void operator delete[](void *ptr) {
+ operator delete(ptr);
+}
+
+void *operator new(size_t size) {
+ void *ptr = malloc(size == 0 ? 1 : size);
+ if (ptr == NULL) {
+ abort();
+ }
+ return ptr;
+}
+
+void *operator new[](size_t size) {
+ return operator new(size);
+}
+
+extern "C"
+void __cxa_pure_virtual() {
+ printf("pure virtual method called\n");
+ abort();
+}
diff --git a/daemon/common.mk b/daemon/common.mk
index d9dc146..769a92e 100644
--- a/daemon/common.mk
+++ b/daemon/common.mk
@@ -5,16 +5,17 @@
# -Werror treats warnings as errors
# -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
+CPPFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors
CXXFLAGS += -fno-rtti -Wextra # -Weffc++
ifeq ($(WERROR),1)
- CFLAGS += -Werror
+ CPPFLAGS += -Werror
endif
# -s strips the binary of debug info
LDFLAGS += -s
+LDLIBS += -lrt -lm -pthread
TARGET = gatord
C_SRC = $(wildcard mxml/*.c) $(wildcard libsensors/*.c)
-CPP_SRC = $(wildcard *.cpp)
+CXX_SRC = $(wildcard *.cpp)
all: $(TARGET)
@@ -35,14 +36,15 @@ libsensors/conf-parse.c: ;
./escape $< > $@
%.o: %.c
- $(GCC) -c $(CFLAGS) -o $@ $<
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
%.o: %.cpp
- $(CPP) -c $(CFLAGS) $(CXXFLAGS) -o $@ $<
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
-$(TARGET): $(CPP_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o)
- $(CPP) $(LDFLAGS) -o $@ $^ -lrt -pthread
+$(TARGET): $(CXX_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o)
+ $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
+# Intentionally ignore CC as a native binary is required
escape: escape.c
gcc $^ -o $@
diff --git a/daemon/defaults.xml b/daemon/defaults.xml
index 5bf096c..39a0f65 100644
--- a/daemon/defaults.xml
+++ b/daemon/defaults.xml
@@ -58,5 +58,10 @@
<configuration counter="Linux_meminfo_memused"/>
<configuration counter="Linux_meminfo_memfree"/>
<configuration counter="Linux_power_cpu_freq"/>
+ <configuration counter="ARM_Mali-4xx_fragment"/>
+ <configuration counter="ARM_Mali-4xx_vertex"/>
+ <configuration counter="ARM_Mali-T6xx_fragment" cores="1"/>
+ <configuration counter="ARM_Mali-T6xx_vertex" cores="1"/>
+ <configuration counter="ARM_Mali-T6xx_opencl" cores="1"/>
<configuration counter="L2C-310_cnt0" event="0x1"/>
</configurations>
diff --git a/daemon/escape.c b/daemon/escape.c
index c54aa1c..2b0863a 100644
--- a/daemon/escape.c
+++ b/daemon/escape.c
@@ -6,7 +6,7 @@
* published by the Free Software Foundation.
*/
-/*
+/*
* The Makefile in the daemon folder builds and executes 'escape'
* 'escape' creates configuration_xml.h from configuration.xml and events_xml.h from events-*.xml
* these genereated xml files are then #included and built as part of the gatord binary
diff --git a/daemon/events-CCI-400.xml b/daemon/events-CCI-400.xml
index 4fa7711..20002ef 100644
--- a/daemon/events-CCI-400.xml
+++ b/daemon/events-CCI-400.xml
@@ -1,7 +1,6 @@
- <counter_set name="cci-400_cnt" count="4"/>
- <category name="CCI-400" counter_set="cci-400_cnt" per_cpu="no" supports_event_based_sampling="yes">
- <event counter="cci-400_ccnt" event="0xff" title="CCI-400 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
-
+ <counter_set name="CCI_400_cnt" count="4"/>
+ <category name="CCI-400" counter_set="CCI_400_cnt" per_cpu="no" supports_event_based_sampling="yes">
+ <event counter="CCI_400_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"/>
@@ -9,7 +8,6 @@
<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"/>
@@ -30,13 +28,11 @@
<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"/>
-
<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="0x14" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/>
<event event="0x15" option_set="Master" title="CCI-400" name="Read stall: address hazard" description="Read request stall cycle because of an address hazard"/>
<event event="0x16" option_set="Master" title="CCI-400" name="Read stall: ID hazard" description="Read request stall cycle because of an ID hazard"/>
@@ -45,11 +41,9 @@
<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"/>
-
+ <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"/>
@@ -57,7 +51,6 @@
<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"/>
@@ -79,13 +72,11 @@
<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"/>
diff --git a/daemon/events-CCN-504.xml b/daemon/events-CCN-504.xml
index cfabf65..6ef3e64 100644
--- a/daemon/events-CCN-504.xml
+++ b/daemon/events-CCN-504.xml
@@ -1,7 +1,6 @@
<counter_set name="CCN-504_cnt" count="4"/>
<category name="CCN-504" counter_set="CCN-504_cnt">
<event counter="CCN-504_ccnt" title="CCN-504 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
-
<option_set name="XP_Region">
<option event_delta="0x400000" name="XP 0" description="Crosspoint 0"/>
<option event_delta="0x410000" name="XP 1" description="Crosspoint 1"/>
@@ -15,7 +14,6 @@
<option event_delta="0x490000" name="XP 9" description="Crosspoint 9"/>
<option event_delta="0x4A0000" name="XP 10" description="Crosspoint 10"/>
</option_set>
-
<event event="0x0801" option_set="XP_Region" title="CCN-504" name="Bus 0: REQ: H-bit" description="Bus 0: REQ: Set H-bit, signaled when this XP sets the H-bit."/>
<event event="0x0802" option_set="XP_Region" title="CCN-504" name="Bus 0: REQ: S-bit" description="Bus 0: REQ: Set S-bit, signaled when this XP sets the S-bit."/>
<event event="0x0803" option_set="XP_Region" title="CCN-504" name="Bus 0: REQ: P-Cnt" description="Bus 0: REQ: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/>
@@ -56,7 +54,6 @@
<event event="0x087A" option_set="XP_Region" title="CCN-504" name="Bus 1: DATB: S-bit" description="Bus 1: DATB: Set S-bit, signaled when this XP sets the S-bit."/>
<event event="0x087B" option_set="XP_Region" title="CCN-504" name="Bus 1: DATB: P-Cnt" description="Bus 1: DATB: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/>
<event event="0x087C" option_set="XP_Region" title="CCN-504" name="Bus 1: DATB: TknV" description="Bus 1: DATB: No TknV, signaled when this XP transmits a valid packet."/>
-
<option_set name="HN-F_Region">
<option event_delta="0x200000" name="HN-F 3" description="Fully-coherent Home Node 3"/>
<option event_delta="0x210000" name="HN-F 5" description="Fully-coherent Home Node 5"/>
@@ -67,7 +64,6 @@
<option event_delta="0x260000" name="HN-F 17" description="Fully-coherent Home Node 17"/>
<option event_delta="0x270000" name="HN-F 18" description="Fully-coherent Home Node 18"/>
</option_set>
-
<event event="0x0401" option_set="HN-F_Region" title="CCN-504" name="Cache Miss" description="Counts the total cache misses. This is the first time lookup result, and is high priority."/>
<event event="0x0402" option_set="HN-F_Region" title="CCN-504" name="L3 SF Cache Access" description="Counts the number of cache accesses. This is the first time access, and is high priority."/>
<event event="0x0403" option_set="HN-F_Region" title="CCN-504" name="Cache Fill" description="Counts the total allocations in the HN L3 cache, and all cache line allocations to the L3 cache."/>
@@ -82,7 +78,6 @@
<event event="0x040C" option_set="HN-F_Region" title="CCN-504" name="MC Retries" description="Counts the number of transactions retried by the memory controller."/>
<event event="0x040D" option_set="HN-F_Region" title="CCN-504" name="MC Reqs" description="Counts the number of requests to the memory controller."/>
<event event="0x040E" option_set="HN-F_Region" title="CCN-504" name="QOS HH Retry" description="Counts the number of times a highest-priority QoS class was retried at the HN-F."/>
-
<option_set name="RN-I_Region">
<option event_delta="0x800000" name="RN-I 0" description="I/O-coherent Requesting Node 0"/>
<option event_delta="0x820000" name="RN-I 2" description="I/O-coherent Requesting Node 2"/>
@@ -91,7 +86,6 @@
<option event_delta="0x900000" name="RN-I 16" description="I/O-coherent Requesting Node 16"/>
<option event_delta="0x940000" name="RN-I 20" description="I/O-coherent Requesting Node 20"/>
</option_set>
-
<event event="0x1601" option_set="RN-I_Region" title="CCN-504" name="S0 RDataBeats" description="S0 RDataBeats."/>
<event event="0x1602" option_set="RN-I_Region" title="CCN-504" name="S1 RDataBeats" description="S1 RDataBeats."/>
<event event="0x1603" option_set="RN-I_Region" title="CCN-504" name="S2 RDataBeats" description="S2 RDataBeats."/>
@@ -102,14 +96,12 @@
<event event="0x1608" option_set="RN-I_Region" title="CCN-504" name="RRT full" description="RRT full."/>
<event event="0x1609" option_set="RN-I_Region" title="CCN-504" name="WRT full" description="WRT full."/>
<event event="0x160A" option_set="RN-I_Region" title="CCN-504" name="Replayed TXREQ Flits" description="Replayed TXREQ Flits."/>
-
<option_set name="SBAS_Region">
<option event_delta="0x810000" name="SBAS 1" description="ACE master to CHI protocol bridge 1"/>
<option event_delta="0x890000" name="SBAS 9" description="ACE master to CHI protocol bridge 9"/>
<option event_delta="0x8B0000" name="SBAS 11" description="ACE master to CHI protocol bridge 11"/>
<option event_delta="0x930000" name="SBAS 19" description="ACE master to CHI protocol bridge 19"/>
</option_set>
-
<event event="0x1001" option_set="SBAS_Region" title="CCN-504" name="S0 RDataBeats" description="S0 RDataBeats."/>
<event event="0x1004" option_set="SBAS_Region" title="CCN-504" name="RXDAT Flits received" description="RXDAT Flits received."/>
<event event="0x1005" option_set="SBAS_Region" title="CCN-504" name="TXDAT Flits sent" description="TXDAT Flits sent."/>
@@ -118,5 +110,4 @@
<event event="0x1008" option_set="SBAS_Region" title="CCN-504" name="RRT full" description="RRT full."/>
<event event="0x1009" option_set="SBAS_Region" title="CCN-504" name="WRT full" description="WRT full."/>
<event event="0x100A" option_set="SBAS_Region" title="CCN-504" name="Replayed TXREQ Flits" description="Replayed TXREQ Flits."/>
-
</category>
diff --git a/daemon/events-Cortex-A53.xml b/daemon/events-Cortex-A53.xml
index 577dcd9..5ba1790 100644
--- a/daemon/events-Cortex-A53.xml
+++ b/daemon/events-Cortex-A53.xml
@@ -1,171 +1,87 @@
<counter_set name="ARM_Cortex-A53_cnt" count="6"/>
<category name="Cortex-A53" counter_set="ARM_Cortex-A53_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <!-- 0x11 CPU_CYCLES - Cycle -->
<event counter="ARM_Cortex-A53_ccnt" event="0x11" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <!-- 0x00 SW_INCR - Instruction architecturally executed (condition check pass) - Software increment -->
<event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
- <!-- 0x01 L1I_CACHE_REFILL - Level 1 instruction cache refill -->
<event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <!-- 0x02 L1I_TLB_REFILL - Level 1 instruction TLB refill -->
<event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <!-- 0x03 L1D_CACHE_REFILL - Level 1 data cache refill -->
<event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <!-- 0x04 L1D_CACHE - Level 1 data cache access -->
<event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
- <!-- 0x05 L1D_TLB_REFILL - Level 1 data TLB refill -->
<event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <!-- 0x08 INST_RETIRED - Instruction architecturally executed -->
<event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
- <!-- 0x09 EXC_TAKEN - Exception taken -->
<event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
- <!-- 0x0A EXC_RETURN - Instruction architecturally executed (condition check pass) - Exception return -->
<event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
- <!-- 0x0B CID_WRITE_RETIRED - Instruction architecturally executed (condition check pass) - Write to CONTEXTIDR -->
<event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
- <!-- 0x10 BR_MIS_PRED - Mispredicted or not predicted branch speculatively executed -->
<event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <!-- 0x12 BR_PRED - Predictable branch speculatively executed -->
<event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- <!-- 0x13 MEM_ACCESS - Data memory access -->
<event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
- <!-- 0x14 L1I_CACHE - Level 1 instruction cache access -->
<event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/>
- <!-- 0x15 L1D_CACHE_WB - Level 1 data cache Write-Back -->
<event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
- <!-- 0x16 L2D_CACHE - Level 2 data cache access -->
<event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
- <!-- 0x17 L2D_CACHE_REFILL - Level 2 data cache refill -->
<event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
- <!-- 0x18 L2D_CACHE_WB - Level 2 data cache Write-Back -->
<event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
- <!-- 0x19 BUS_ACCESS - Bus access -->
<event event="0x19" title="Bus" name="Access" description="Bus access"/>
- <!-- 0x1A MEMORY_ERROR - Local memory error -->
<event event="0x1A" title="Memory" name="Error" description="Local memory error"/>
- <!-- 0x1B INST_SPEC - Operation speculatively executed -->
<event event="0x1B" title="Instruction" name="Speculative" description="Operation speculatively executed"/>
- <!-- 0x1C TTBR_WRITE_RETIRED - Instruction architecturally executed (condition check pass) - Write to translation table base -->
<event event="0x1C" title="Memory" name="Translation table" description="Instruction architecturally executed (condition check pass) - Write to translation table base"/>
- <!-- 0x1D BUS_CYCLES - Bus cycle -->
<event event="0x1D" title="Bus" name="Cycle" description="Bus cycle"/>
- <!-- 0x1E CHAIN - Odd performance counter chain mode -->
<event event="0x1E" title="Counter chain" name="Odd Performance" description="Odd performance counter chain mode"/>
- <!-- 0x40 L1D_CACHE_LD - Level 1 data cache access - Read -->
<event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
- <!-- 0x41 L1D_CACHE_ST - Level 1 data cache access - Write -->
<event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
- <!-- 0x42 L1D_CACHE_REFILL_LD - Level 1 data cache refill - Read -->
<event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/>
- <!-- 0x43 L1D_CACHE_REFILL_ST - Level 1 data cache refill - Write -->
<event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill - Write"/>
- <!-- 0x46 L1D_CACHE_WB_VICTIM - Level 1 data cache Write-back - Victim -->
<event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-back - Victim"/>
- <!-- 0x47 L1D_CACHE_WB_CLEAN - Level 1 data cache Write-back - Cleaning and coherency -->
<event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-back - Cleaning and coherency"/>
- <!-- 0x48 L1D_CACHE_INVAL - Level 1 data cache invalidate -->
<event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/>
- <!-- 0x4C L1D_TLB_REFILL_LD - Level 1 data TLB refill - Read -->
<event event="0x4C" title="Cache" name="L1 data refill read" description="Level 1 data TLB refill - Read"/>
- <!-- 0x4D L1D_TLB_REFILL_ST - Level 1 data TLB refill - Write -->
<event event="0x4D" title="Cache" name="L1 data refill write" description="Level 1 data TLB refill - Write"/>
- <!-- 0x50 L2D_CACHE_LD - Level 2 data cache access - Read -->
<event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
- <!-- 0x51 L2D_CACHE_ST - Level 2 data cache access - Write -->
<event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
- <!-- 0x52 L2D_CACHE_REFILL_LD - Level 2 data cache refill - Read -->
<event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/>
- <!-- 0x53 L2D_CACHE_REFILL_ST - Level 2 data cache refill - Write -->
<event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill - Write"/>
- <!-- 0x56 L2D_CACHE_WB_VICTIM - Level 2 data cache Write-back - Victim -->
<event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-back - Victim"/>
- <!-- 0x57 L2D_CACHE_WB_CLEAN - Level 2 data cache Write-back - Cleaning and coherency -->
<event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-back - Cleaning and coherency"/>
- <!-- 0x58 L2D_CACHE_INVAL - Level 2 data cache invalidate -->
<event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/>
- <!-- 0x60 BUS_ACCESS_LD - Bus access - Read -->
<event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
- <!-- 0x61 BUS_ACCESS_ST - Bus access - Write -->
<event event="0x61" title="Bus" name="Write" description="Bus access - Write"/>
- <!-- 0x62 BUS_ACCESS_SHARED - Bus access - Normal -->
<event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/>
- <!-- 0x63 BUS_ACCESS_NOT_SHARED - Bus access - Not normal -->
<event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/>
- <!-- 0x64 BUS_ACCESS_NORMAL - Bus access - Normal -->
<event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/>
- <!-- 0x65 BUS_ACCESS_PERIPH - Bus access - Peripheral -->
<event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/>
- <!-- 0x66 MEM_ACCESS_LD - Data memory access - Read -->
<event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/>
- <!-- 0x67 MEM_ACCESS_ST - Data memory access - Write -->
<event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/>
- <!-- 0x68 UNALIGNED_LD_SPEC - Unaligned access - Read -->
<event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/>
- <!-- 0x69 UNALIGNED_ST_SPEC - Unaligned access - Write -->
<event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/>
- <!-- 0x6A UNALIGNED_LDST_SPEC - Unaligned access -->
<event event="0x6A" title="Memory" name="Unaligned" description="Unaligned access"/>
- <!-- 0x6C LDREX_SPEC - Exclusive operation speculatively executed - LDREX -->
<event event="0x6C" title="Intrinsic" name="LDREX" description="Exclusive operation speculatively executed - LDREX"/>
- <!-- 0x6D STREX_PASS_SPEC - Exclusive instruction speculatively executed - STREX pass -->
<event event="0x6D" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/>
- <!-- 0x6E STREX_FAIL_SPEC - Exclusive operation speculatively executed - STREX fail -->
<event event="0x6E" title="Intrinsic" name="STREX fail" description="Exclusive operation speculatively executed - STREX fail"/>
- <!-- 0x70 LD_SPEC - Operation speculatively executed - Load -->
<event event="0x70" title="Instruction" name="Load" description="Operation speculatively executed - Load"/>
- <!-- 0x71 ST_SPEC - Operation speculatively executed - Store -->
<event event="0x71" title="Instruction" name="Store" description="Operation speculatively executed - Store"/>
- <!-- 0x72 LDST_SPEC - Operation speculatively executed - Load or store -->
<event event="0x72" title="Instruction" name="Load/Store" description="Operation speculatively executed - Load or store"/>
- <!-- 0x73 DP_SPEC - Operation speculatively executed - Integer data processing -->
<event event="0x73" title="Instruction" name="Integer" description="Operation speculatively executed - Integer data processing"/>
- <!-- 0x74 ASE_SPEC - Operation speculatively executed - Advanced SIMD -->
<event event="0x74" title="Instruction" name="Advanced SIMD" description="Operation speculatively executed - Advanced SIMD"/>
- <!-- 0x75 VFP_SPEC - Operation speculatively executed - VFP -->
<event event="0x75" title="Instruction" name="VFP" description="Operation speculatively executed - VFP"/>
- <!-- 0x76 PC_WRITE_SPEC - Operation speculatively executed - Software change of the PC -->
<event event="0x76" title="Instruction" name="Software change" description="Operation speculatively executed - Software change of the PC"/>
- <!-- 0x77 CRYPTO_SPEC - Operation speculatively executed, crypto data processing -->
<event event="0x77" title="Instruction" name="Crypto" description="Operation speculatively executed, crypto data processing"/>
- <!-- 0x78 BR_IMMED_SPEC - Branch speculatively executed - Immediate branch -->
<event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
- <!-- 0x79 BR_RETURN_SPEC - Branch speculatively executed - Procedure return -->
<event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
- <!-- 0x7A BR_INDIRECT_SPEC - Branch speculatively executed - Indirect branch -->
<event event="0x7A" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
- <!-- 0x7C ISB_SPEC - Barrier speculatively executed - ISB -->
<event event="0x7C" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
- <!-- 0x7D DSB_SPEC - Barrier speculatively executed - DSB -->
<event event="0x7D" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
- <!-- 0x7E DMB_SPEC - Barrier speculatively executed - DMB -->
<event event="0x7E" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
- <!-- 0x81 EXC_UNDEF - Exception taken, other synchronous -->
<event event="0x81" title="Exception" name="Undefined" description="Exception taken, other synchronous"/>
- <!-- 0x82 EXC_SVC - Exception taken, Supervisor Call -->
<event event="0x82" title="Exception" name="Supervisor" description="Exception taken, Supervisor Call"/>
- <!-- 0x83 EXC_PABORT - Exception taken, Instruction Abort -->
<event event="0x83" title="Exception" name="Instruction abort" description="Exception taken, Instruction Abort"/>
- <!-- 0x84 EXC_DABORT - Exception taken, Data Abort or SError -->
<event event="0x84" title="Exception" name="Data abort" description="Exception taken, Data Abort or SError"/>
- <!-- 0x86 EXC_IRQ - Exception taken, IRQ -->
<event event="0x86" title="Interrupts" name="IRQ" description="Exception taken, IRQ"/>
- <!-- 0x87 EXC_FIQ - Exception taken, FIQ -->
<event event="0x87" title="Interrupts" name="FIQ" description="Exception taken, FIQ"/>
- <!-- 0x88 EXC_SMC - Exception taken, Secure Monitor Call -->
<event event="0x88" title="Exception" name="Secure monitor call" description="Exception taken, Secure Monitor Call"/>
- <!-- 0x8A EXC_HVC - Exception taken, Hypervisor Call -->
<event event="0x8A" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/>
- <!-- 0x8B EXC_TRAP_PABORT - Exception taken, Instruction Abort not taken locally -->
<event event="0x8B" title="Exception" name="Instruction abort non-local" description="Exception taken, Instruction Abort not taken locally"/>
- <!-- 0x8C EXC_TRAP_DABORT - Exception taken, Data Abort or SError not taken locally -->
<event event="0x8C" title="Exception" name="Data abort non-local" description="Exception taken, Data Abort or SError not taken locally"/>
- <!-- 0x8D EXC_TRAP_OTHER - Exception taken - Other traps not taken locally -->
<event event="0x8D" title="Exception" name="Other non-local" description="Exception taken - Other traps not taken locally"/>
- <!-- 0x8E EXC_TRAP_IRQ - Exception taken, IRQ not taken locally -->
<event event="0x8E" title="Exception" name="IRQ non-local" description="Exception taken, IRQ not taken locally"/>
- <!-- 0x8F EXC_TRAP_FIQ - Exception taken, FIQ not taken locally -->
<event event="0x8F" title="Exception" name="FIQ non-local" description="Exception taken, FIQ not taken locally"/>
- <!-- 0x90 RC_LD_SPEC - Release consistency instruction speculatively executed - Load Acquire -->
<event event="0x90" title="Release Consistency" name="Load" description="Release consistency instruction speculatively executed - Load Acquire"/>
- <!-- 0x91 RC_ST_SPEC - Release consistency instruction speculatively executed - Store Release -->
<event event="0x91" title="Release Consistency" name="Store" description="Release consistency instruction speculatively executed - Store Release"/>
</category>
diff --git a/daemon/events-Cortex-A57.xml b/daemon/events-Cortex-A57.xml
index b7178c0..fbe96c2 100644
--- a/daemon/events-Cortex-A57.xml
+++ b/daemon/events-Cortex-A57.xml
@@ -1,171 +1,87 @@
<counter_set name="ARM_Cortex-A57_cnt" count="6"/>
<category name="Cortex-A57" counter_set="ARM_Cortex-A57_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <!-- 0x11 CPU_CYCLES - Cycle -->
<event counter="ARM_Cortex-A57_ccnt" event="0x11" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <!-- 0x00 SW_INCR - Instruction architecturally executed (condition check pass) - Software increment -->
<event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
- <!-- 0x01 L1I_CACHE_REFILL - Level 1 instruction cache refill -->
<event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <!-- 0x02 L1I_TLB_REFILL - Level 1 instruction TLB refill -->
<event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <!-- 0x03 L1D_CACHE_REFILL - Level 1 data cache refill -->
<event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <!-- 0x04 L1D_CACHE - Level 1 data cache access -->
<event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
- <!-- 0x05 L1D_TLB_REFILL - Level 1 data TLB refill -->
<event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <!-- 0x08 INST_RETIRED - Instruction architecturally executed -->
<event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
- <!-- 0x09 EXC_TAKEN - Exception taken -->
<event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
- <!-- 0x0A EXC_RETURN - Instruction architecturally executed (condition check pass) - Exception return -->
<event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
- <!-- 0x0B CID_WRITE_RETIRED - Instruction architecturally executed (condition check pass) - Write to CONTEXTIDR -->
<event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
- <!-- 0x10 BR_MIS_PRED - Mispredicted or not predicted branch speculatively executed -->
<event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <!-- 0x12 BR_PRED - Predictable branch speculatively executed -->
<event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- <!-- 0x13 MEM_ACCESS - Data memory access -->
<event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
- <!-- 0x14 L1I_CACHE - Level 1 instruction cache access -->
<event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/>
- <!-- 0x15 L1D_CACHE_WB - Level 1 data cache Write-Back -->
<event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
- <!-- 0x16 L2D_CACHE - Level 2 data cache access -->
<event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
- <!-- 0x17 L2D_CACHE_REFILL - Level 2 data cache refill -->
<event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
- <!-- 0x18 L2D_CACHE_WB - Level 2 data cache Write-Back -->
<event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
- <!-- 0x19 BUS_ACCESS - Bus access -->
<event event="0x19" title="Bus" name="Access" description="Bus access"/>
- <!-- 0x1A MEMORY_ERROR - Local memory error -->
<event event="0x1A" title="Memory" name="Error" description="Local memory error"/>
- <!-- 0x1B INST_SPEC - Operation speculatively executed -->
<event event="0x1B" title="Instruction" name="Speculative" description="Operation speculatively executed"/>
- <!-- 0x1C TTBR_WRITE_RETIRED - Instruction architecturally executed (condition check pass) - Write to translation table base -->
<event event="0x1C" title="Memory" name="Translation table" description="Instruction architecturally executed (condition check pass) - Write to translation table base"/>
- <!-- 0x1D BUS_CYCLES - Bus cycle -->
<event event="0x1D" title="Bus" name="Cycle" description="Bus cycle"/>
- <!-- 0x1E CHAIN - Odd performance counter chain mode -->
<event event="0x1E" title="Counter chain" name="Odd Performance" description="Odd performance counter chain mode"/>
- <!-- 0x40 L1D_CACHE_LD - Level 1 data cache access - Read -->
<event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
- <!-- 0x41 L1D_CACHE_ST - Level 1 data cache access - Write -->
<event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
- <!-- 0x42 L1D_CACHE_REFILL_LD - Level 1 data cache refill - Read -->
<event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/>
- <!-- 0x43 L1D_CACHE_REFILL_ST - Level 1 data cache refill - Write -->
<event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill - Write"/>
- <!-- 0x46 L1D_CACHE_WB_VICTIM - Level 1 data cache Write-back - Victim -->
<event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-back - Victim"/>
- <!-- 0x47 L1D_CACHE_WB_CLEAN - Level 1 data cache Write-back - Cleaning and coherency -->
<event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-back - Cleaning and coherency"/>
- <!-- 0x48 L1D_CACHE_INVAL - Level 1 data cache invalidate -->
<event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/>
- <!-- 0x4C L1D_TLB_REFILL_LD - Level 1 data TLB refill - Read -->
<event event="0x4C" title="Cache" name="L1 data refill read" description="Level 1 data TLB refill - Read"/>
- <!-- 0x4D L1D_TLB_REFILL_ST - Level 1 data TLB refill - Write -->
<event event="0x4D" title="Cache" name="L1 data refill write" description="Level 1 data TLB refill - Write"/>
- <!-- 0x50 L2D_CACHE_LD - Level 2 data cache access - Read -->
<event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
- <!-- 0x51 L2D_CACHE_ST - Level 2 data cache access - Write -->
<event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
- <!-- 0x52 L2D_CACHE_REFILL_LD - Level 2 data cache refill - Read -->
<event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/>
- <!-- 0x53 L2D_CACHE_REFILL_ST - Level 2 data cache refill - Write -->
<event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill - Write"/>
- <!-- 0x56 L2D_CACHE_WB_VICTIM - Level 2 data cache Write-back - Victim -->
<event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-back - Victim"/>
- <!-- 0x57 L2D_CACHE_WB_CLEAN - Level 2 data cache Write-back - Cleaning and coherency -->
<event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-back - Cleaning and coherency"/>
- <!-- 0x58 L2D_CACHE_INVAL - Level 2 data cache invalidate -->
<event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/>
- <!-- 0x60 BUS_ACCESS_LD - Bus access - Read -->
<event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
- <!-- 0x61 BUS_ACCESS_ST - Bus access - Write -->
<event event="0x61" title="Bus" name="Write" description="Bus access - Write"/>
- <!-- 0x62 BUS_ACCESS_SHARED - Bus access - Normal -->
<event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/>
- <!-- 0x63 BUS_ACCESS_NOT_SHARED - Bus access - Not normal -->
<event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/>
- <!-- 0x64 BUS_ACCESS_NORMAL - Bus access - Normal -->
<event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/>
- <!-- 0x65 BUS_ACCESS_PERIPH - Bus access - Peripheral -->
<event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/>
- <!-- 0x66 MEM_ACCESS_LD - Data memory access - Read -->
<event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/>
- <!-- 0x67 MEM_ACCESS_ST - Data memory access - Write -->
<event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/>
- <!-- 0x68 UNALIGNED_LD_SPEC - Unaligned access - Read -->
<event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/>
- <!-- 0x69 UNALIGNED_ST_SPEC - Unaligned access - Write -->
<event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/>
- <!-- 0x6A UNALIGNED_LDST_SPEC - Unaligned access -->
<event event="0x6A" title="Memory" name="Unaligned" description="Unaligned access"/>
- <!-- 0x6C LDREX_SPEC - Exclusive operation speculatively executed - LDREX -->
<event event="0x6C" title="Intrinsic" name="LDREX" description="Exclusive operation speculatively executed - LDREX"/>
- <!-- 0x6D STREX_PASS_SPEC - Exclusive instruction speculatively executed - STREX pass -->
<event event="0x6D" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/>
- <!-- 0x6E STREX_FAIL_SPEC - Exclusive operation speculatively executed - STREX fail -->
<event event="0x6E" title="Intrinsic" name="STREX fail" description="Exclusive operation speculatively executed - STREX fail"/>
- <!-- 0x70 LD_SPEC - Operation speculatively executed - Load -->
<event event="0x70" title="Instruction" name="Load" description="Operation speculatively executed - Load"/>
- <!-- 0x71 ST_SPEC - Operation speculatively executed - Store -->
<event event="0x71" title="Instruction" name="Store" description="Operation speculatively executed - Store"/>
- <!-- 0x72 LDST_SPEC - Operation speculatively executed - Load or store -->
<event event="0x72" title="Instruction" name="Load/Store" description="Operation speculatively executed - Load or store"/>
- <!-- 0x73 DP_SPEC - Operation speculatively executed - Integer data processing -->
<event event="0x73" title="Instruction" name="Integer" description="Operation speculatively executed - Integer data processing"/>
- <!-- 0x74 ASE_SPEC - Operation speculatively executed - Advanced SIMD -->
<event event="0x74" title="Instruction" name="Advanced SIMD" description="Operation speculatively executed - Advanced SIMD"/>
- <!-- 0x75 VFP_SPEC - Operation speculatively executed - VFP -->
<event event="0x75" title="Instruction" name="VFP" description="Operation speculatively executed - VFP"/>
- <!-- 0x76 PC_WRITE_SPEC - Operation speculatively executed - Software change of the PC -->
<event event="0x76" title="Instruction" name="Software change" description="Operation speculatively executed - Software change of the PC"/>
- <!-- 0x77 CRYPTO_SPEC - Operation speculatively executed, crypto data processing -->
<event event="0x77" title="Instruction" name="Crypto" description="Operation speculatively executed, crypto data processing"/>
- <!-- 0x78 BR_IMMED_SPEC - Branch speculatively executed - Immediate branch -->
<event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
- <!-- 0x79 BR_RETURN_SPEC - Branch speculatively executed - Procedure return -->
<event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
- <!-- 0x7A BR_INDIRECT_SPEC - Branch speculatively executed - Indirect branch -->
<event event="0x7A" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
- <!-- 0x7C ISB_SPEC - Barrier speculatively executed - ISB -->
<event event="0x7C" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
- <!-- 0x7D DSB_SPEC - Barrier speculatively executed - DSB -->
<event event="0x7D" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
- <!-- 0x7E DMB_SPEC - Barrier speculatively executed - DMB -->
<event event="0x7E" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
- <!-- 0x81 EXC_UNDEF - Exception taken, other synchronous -->
<event event="0x81" title="Exception" name="Undefined" description="Exception taken, other synchronous"/>
- <!-- 0x82 EXC_SVC - Exception taken, Supervisor Call -->
<event event="0x82" title="Exception" name="Supervisor" description="Exception taken, Supervisor Call"/>
- <!-- 0x83 EXC_PABORT - Exception taken, Instruction Abort -->
<event event="0x83" title="Exception" name="Instruction abort" description="Exception taken, Instruction Abort"/>
- <!-- 0x84 EXC_DABORT - Exception taken, Data Abort or SError -->
<event event="0x84" title="Exception" name="Data abort" description="Exception taken, Data Abort or SError"/>
- <!-- 0x86 EXC_IRQ - Exception taken, IRQ -->
<event event="0x86" title="Interrupts" name="IRQ" description="Exception taken, IRQ"/>
- <!-- 0x87 EXC_FIQ - Exception taken, FIQ -->
<event event="0x87" title="Interrupts" name="FIQ" description="Exception taken, FIQ"/>
- <!-- 0x88 EXC_SMC - Exception taken, Secure Monitor Call -->
<event event="0x88" title="Exception" name="Secure monitor call" description="Exception taken, Secure Monitor Call"/>
- <!-- 0x8A EXC_HVC - Exception taken, Hypervisor Call -->
<event event="0x8A" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/>
- <!-- 0x8B EXC_TRAP_PABORT - Exception taken, Instruction Abort not taken locally -->
<event event="0x8B" title="Exception" name="Instruction abort non-local" description="Exception taken, Instruction Abort not taken locally"/>
- <!-- 0x8C EXC_TRAP_DABORT - Exception taken, Data Abort or SError not taken locally -->
<event event="0x8C" title="Exception" name="Data abort non-local" description="Exception taken, Data Abort or SError not taken locally"/>
- <!-- 0x8D EXC_TRAP_OTHER - Exception taken - Other traps not taken locally -->
<event event="0x8D" title="Exception" name="Other non-local" description="Exception taken - Other traps not taken locally"/>
- <!-- 0x8E EXC_TRAP_IRQ - Exception taken, IRQ not taken locally -->
<event event="0x8E" title="Exception" name="IRQ non-local" description="Exception taken, IRQ not taken locally"/>
- <!-- 0x8F EXC_TRAP_FIQ - Exception taken, FIQ not taken locally -->
<event event="0x8F" title="Exception" name="FIQ non-local" description="Exception taken, FIQ not taken locally"/>
- <!-- 0x90 RC_LD_SPEC - Release consistency instruction speculatively executed - Load Acquire -->
<event event="0x90" title="Release Consistency" name="Load" description="Release consistency instruction speculatively executed - Load Acquire"/>
- <!-- 0x91 RC_ST_SPEC - Release consistency instruction speculatively executed - Store Release -->
<event event="0x91" title="Release Consistency" name="Store" description="Release consistency instruction speculatively executed - Store Release"/>
</category>
diff --git a/daemon/events-Filesystem.xml b/daemon/events-Filesystem.xml
new file mode 100644
index 0000000..5feeb90
--- /dev/null
+++ b/daemon/events-Filesystem.xml
@@ -0,0 +1,11 @@
+ <category name="Filesystem">
+ <!-- counter attributes must be unique -->
+ <!-- regex item in () is the value shown -->
+ <!-- these counters are not compatible with userspace gator, i.e. gator.ko must be loaded -->
+ <!--
+ <event counter="/sys/devices/system/cpu/cpu1/online" title="online" name="cpu 1" class="absolute" description="If cpu 1 is online"/>
+ <event counter="/proc/self/loginuid" title="loginuid" name="loginuid" class="absolute" description="loginuid"/>
+ <event counter="/proc/self/stat" title="stat" name="rss" class="absolute" regex="-?[0-9]+ \(.*\) . -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ (-?[0-9]+)" units="pages" description="resident set size"/>
+ <event counter="/proc/stat" title="proc-stat" name="processes" class="absolute" regex="processes ([0-9]+)" description="Number of processes and threads created"/>
+ -->
+ </category>
diff --git a/daemon/events-L2C-310.xml b/daemon/events-L2C-310.xml
index 4da4d1d..923fb90 100644
--- a/daemon/events-L2C-310.xml
+++ b/daemon/events-L2C-310.xml
@@ -1,18 +1,18 @@
<counter_set name="L2C-310_cnt" count="2"/>
<category name="L2C-310" counter_set="L2C-310_cnt" per_cpu="no">
- <event event="0x1" title="L2 Cache" name="CO" description="Eviction, CastOUT, of a line from the L2 cache"/>
- <event event="0x2" title="L2 Cache" name="DRH" description="Data read hit"/>
- <event event="0x3" title="L2 Cache" name="DRREQ" description="Data read request"/>
- <event event="0x4" title="L2 Cache" name="DWHIT" description="Data write hit"/>
- <event event="0x5" title="L2 Cache" name="DWREQ" description="Data write request"/>
- <event event="0x6" title="L2 Cache" name="DWTREQ" description="Data write request with write-through attribute"/>
- <event event="0x7" title="L2 Cache" name="IRHIT" description="Instruction read hit"/>
- <event event="0x8" title="L2 Cache" name="IRREQ" description="Instruction read request"/>
- <event event="0x9" title="L2 Cache" name="WA" description="Write allocate"/>
- <event event="0xa" title="L2 Cache" name="IPFALLOC" description="Allocation of a prefetch generated by L2C-310 into the L2 cache"/>
- <event event="0xb" title="L2 Cache" name="EPFHIT" description="Prefetch hint hits in the L2 cache"/>
- <event event="0xc" title="L2 Cache" name="EPFALLOC" description="Prefetch hint allocated into the L2 cache"/>
- <event event="0xd" title="L2 Cache" name="SRRCVD" description="Speculative read received"/>
- <event event="0xe" title="L2 Cache" name="SRCONF" description="Speculative read confirmed"/>
- <event event="0xf" title="L2 Cache" name="EPFRCVD" description="Prefetch hint received"/>
+ <event event="0x1" title="L2 Cache" name="CastOUT" description="Eviction, CastOUT, of a line from the L2 cache"/>
+ <event event="0x2" title="L2 Cache" name="Data Read Hit" description="Data read hit in the L2 cache"/>
+ <event event="0x3" title="L2 Cache" name="Data Read Request" description="Data read lookup to the L2 cache. Subsequently results in a hit or miss"/>
+ <event event="0x4" title="L2 Cache" name="Data Write Hit" description="Data write hit in the L2 cache"/>
+ <event event="0x5" title="L2 Cache" name="Data Write Request" description="Data write lookup to the L2 cache. Subsequently results in a hit or miss"/>
+ <event event="0x6" title="L2 Cache" name="Data Write-Through Request" description="Data write lookup to the L2 cache with Write-Through attribute. Subsequently results in a hit or miss"/>
+ <event event="0x7" title="L2 Cache" name="Instruction Read Hit" description="Instruction read hit in the L2 cache"/>
+ <event event="0x8" title="L2 Cache" name="Instruction Read Request" description="Instruction read lookup to the L2 cache. Subsequently results in a hit or miss"/>
+ <event event="0x9" title="L2 Cache" name="Write Allocate Miss" description="Allocation into the L2 cache caused by a write, with Write-Allocate attribute, miss"/>
+ <event event="0xa" title="L2 Cache" name="Internal Prefetch Allocate" description="Allocation of a prefetch generated by L2C-310 into the L2 cache"/>
+ <event event="0xb" title="L2 Cache" name="Prefitch Hit" description="Prefetch hint hits in the L2 cache"/>
+ <event event="0xc" title="L2 Cache" name="Prefitch Allocate" description="Prefetch hint allocated into the L2 cache"/>
+ <event event="0xd" title="L2 Cache" name="Speculative Read Received" description="Speculative read received"/>
+ <event event="0xe" title="L2 Cache" name="Speculative Read Confirmed" description="Speculative read confirmed"/>
+ <event event="0xf" title="L2 Cache" name="Prefetch Hint Received" description="Prefetch hint received"/>
</category>
diff --git a/daemon/events-Linux.xml b/daemon/events-Linux.xml
index 4d677e1..c306dd6 100644
--- a/daemon/events-Linux.xml
+++ b/daemon/events-Linux.xml
@@ -11,7 +11,6 @@
<event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" class="absolute" units="B" description="Memory used by OS disk buffers"/>
<event counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" class="absolute" 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" class="absolute" 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" class="activity" 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" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" description="Thread waiting on I/O resource"/>
+ <event counter="Linux_cpu_wait_contention" title="CPU Contention" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" color="0x003c96fb" description="Thread waiting on contended resource"/>
+ <event counter="Linux_cpu_wait_io" title="CPU I/O" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" color="0x00b30000" description="Thread waiting on I/O resource"/>
</category>
-
diff --git a/daemon/events-Mali-4xx.xml b/daemon/events-Mali-4xx.xml
index 5a71386..0a95dfe 100644
--- a/daemon/events-Mali-4xx.xml
+++ b/daemon/events-Mali-4xx.xml
@@ -1,34 +1,33 @@
<counter_set name="ARM_Mali-4xx_VP_0_cnt" count="2"/>
<counter_set name="ARM_Mali-4xx_SW_cnt" count="0"/>
- <counter_set name="ARM_Mali-4xx_Filmstrip_cnt" count="1"/>
- <category name="Mali-4xx-VP" counter_set="ARM_Mali-4xx_VP_0_cnt" per_cpu="no">
- <event event="0x01" title="Mali GPU Vertex Processor" name="Active cycles" description="Number of cycles per frame the MaliGP2 was active."/>
- <event event="0x02" title="Mali GPU Vertex Processor" name="Active cycles, vertex shader" description="Number of cycles per frame the vertex shader unit was active."/>
- <event event="0x03" title="Mali GPU Vertex Processor" name="Active cycles, vertex storer" description="Number of cycles per frame the vertex storer unit was active."/>
- <event event="0x04" title="Mali GPU Vertex Processor" name="Active cycles, vertex loader" description="Number of cycles per frame the vertex loader unit was active."/>
- <event event="0x05" title="Mali GPU Vertex Processor" name="Cycles vertex loader waiting for vertex shader" description="Number of cycles per frame the vertex loader was idle while waiting on the vertex shader."/>
- <event event="0x06" title="Mali GPU Vertex Processor" name="Words read, system bus" description="Total number of 64 bit words read by the GP2 from the system bus per frame."/>
- <event event="0x07" title="Mali GPU Vertex Processor" name="Words written, system bus" description="Total number of 64 bit words written by the GP2 to the system bus per frame."/>
- <event event="0x08" title="Mali GPU Vertex Processor" name="Read bursts, system bus" description="Number of read bursts by the GP2 from the system bus per frame."/>
- <event event="0x09" title="Mali GPU Vertex Processor" name="Write bursts, system bus" description="Number of write bursts from the MaliGP2 to the system bus per frame."/>
- <event event="0x0a" title="Mali GPU Vertex Processor" name="Vertices processed" description="Number of vertices processed by the MaliGP2 per frame."/>
- <event event="0x0b" title="Mali GPU Vertex Processor" name="Vertices fetched" description="Number of vertices fetched by the MaliGP2 per frame."/>
- <event event="0x0c" title="Mali GPU Vertex Processor" name="Primitives fetched" description="Number of graphics primitives fetched by the MaliGP2 per frame."/>
- <event event="0x0e" title="Mali GPU Vertex Processor" name="Primitives culled" description="Number of graphics primitives discarded per frame, because they were seen from the back or were offscreen."/>
- <event event="0x0f" title="Mali GPU Vertex Processor" name="Commands written to tiles" description="Number of commands (8 Bytes, mainly primitives) written by GP2 to the PP input data structure per frame."/>
- <event event="0x10" title="Mali GPU Vertex Processor" name="Memory blocks allocated" description="Number of overflow data blocks needed for outputting the PP input data structure per frame ."/>
- <event event="0x13" title="Mali GPU Vertex Processor" name="Vertex loader cache misses" description="Number of cache misses for the vertex shader's vertex input unit per frame."/>
- <event event="0x16" title="Mali GPU Vertex Processor" name="Active cycles, vertex shader command processor" description="Number of cycles per frame the GP2 vertex shader command processor was active. This includes time waiting for semaphores."/>
- <event event="0x17" title="Mali GPU Vertex Processor" name="Active cycles, PLBU command processor" description="Number of cycles per frame the MaliGP2 PLBU command processor was active. This includes time waiting for semaphores."/>
- <event event="0x18" title="Mali GPU Vertex Processor" name="MaliGP2 PLBU cycles per frame" description="Number of cycles per frame the MaliGP2 PLBU output unit was active. This includes time spent waiting on the bus."/>
- <event event="0x19" title="Mali GPU Vertex Processor" name="Active cycles, PLBU geometry processing" description="Number of cycles per frame the MaliGP2 PLBU was active, excepting final data output. In other words: active cycles through the prepare list commands. This includes time spent waiting on the bus."/>
- <event event="0x1b" title="Mali GPU Vertex Processor" name="Active cycles, PLBU primitive assembly" description="Number of active cycles per frame spent by the MaliGP2 PLBU doing primitive assembly. This does not include scissoring or final output. This includes time spent waiting on the bus."/>
- <event event="0x1c" title="Mali GPU Vertex Processor" name="Active cycles, PLBU vertex fetcher" description="Number of active cycles per frame spent by the MaliGP2 PLBU fetching vertex data. This includes time spent waiting on the bus."/>
- <event event="0x1e" title="Mali GPU Vertex Processor" name="Active cycles, Bounding-box and command generator" description="Number of active cycles per frame spent by the MaliGP2 PLBU setting up bounding boxes and commands (mainly graphics primitives). This includes time spent waiting on the bus."/>
- <event event="0x20" title="Mali GPU Vertex Processor" name="Active cycles, Scissor tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over tiles to perform scissoring. This includes time spent waiting on the bus."/>
- <event event="0x21" title="Mali GPU Vertex Processor" name="Active cycles, PLBU tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over the tiles in the bounding box generating commands (mainly graphics primitives). This includes time spent waiting on the bus."/>
+ <category name="Mali Vertex Processor" counter_set="ARM_Mali-4xx_VP_0_cnt" per_cpu="no">
+ <event event="0x01" title="Mali-4xx VP" name="Active cycles" description="Number of cycles per frame the MaliGP2 was active."/>
+ <event event="0x02" title="Mali-4xx VP" name="Active cycles, vertex shader" description="Number of cycles per frame the vertex shader unit was active."/>
+ <event event="0x03" title="Mali-4xx VP" name="Active cycles, vertex storer" description="Number of cycles per frame the vertex storer unit was active."/>
+ <event event="0x04" title="Mali-4xx VP" name="Active cycles, vertex loader" description="Number of cycles per frame the vertex loader unit was active."/>
+ <event event="0x05" title="Mali-4xx VP" name="Cycles vertex loader waiting for vertex shader" description="Number of cycles per frame the vertex loader was idle while waiting on the vertex shader."/>
+ <event event="0x06" title="Mali-4xx VP" name="Words read, system bus" description="Total number of 64 bit words read by the GP2 from the system bus per frame."/>
+ <event event="0x07" title="Mali-4xx VP" name="Words written, system bus" description="Total number of 64 bit words written by the GP2 to the system bus per frame."/>
+ <event event="0x08" title="Mali-4xx VP" name="Read bursts, system bus" description="Number of read bursts by the GP2 from the system bus per frame."/>
+ <event event="0x09" title="Mali-4xx VP" name="Write bursts, system bus" description="Number of write bursts from the MaliGP2 to the system bus per frame."/>
+ <event event="0x0a" title="Mali-4xx VP" name="Vertices processed" description="Number of vertices processed by the MaliGP2 per frame."/>
+ <event event="0x0b" title="Mali-4xx VP" name="Vertices fetched" description="Number of vertices fetched by the MaliGP2 per frame."/>
+ <event event="0x0c" title="Mali-4xx VP" name="Primitives fetched" description="Number of graphics primitives fetched by the MaliGP2 per frame."/>
+ <event event="0x0e" title="Mali-4xx VP" name="Primitives culled" description="Number of graphics primitives discarded per frame, because they were seen from the back or were offscreen."/>
+ <event event="0x0f" title="Mali-4xx VP" name="Commands written to tiles" description="Number of commands (8 Bytes, mainly primitives) written by GP2 to the PP input data structure per frame."/>
+ <event event="0x10" title="Mali-4xx VP" name="Memory blocks allocated" description="Number of overflow data blocks needed for outputting the PP input data structure per frame ."/>
+ <event event="0x13" title="Mali-4xx VP" name="Vertex loader cache misses" description="Number of cache misses for the vertex shader's vertex input unit per frame."/>
+ <event event="0x16" title="Mali-4xx VP" name="Active cycles, vertex shader command processor" description="Number of cycles per frame the GP2 vertex shader command processor was active. This includes time waiting for semaphores."/>
+ <event event="0x17" title="Mali-4xx VP" name="Active cycles, PLBU command processor" description="Number of cycles per frame the MaliGP2 PLBU command processor was active. This includes time waiting for semaphores."/>
+ <event event="0x18" title="Mali-4xx VP" name="Active Cycles, PLBU list writer" description="Number of cycles per frame the MaliGP2 PLBU output unit was active. This includes time spent waiting on the bus."/>
+ <event event="0x19" title="Mali-4xx VP" name="Active cycles, PLBU geometry processing" description="Number of cycles per frame the MaliGP2 PLBU was active, excepting final data output. In other words: active cycles through the prepare list commands. This includes time spent waiting on the bus."/>
+ <event event="0x1b" title="Mali-4xx VP" name="Active cycles, PLBU primitive assembly" description="Number of active cycles per frame spent by the MaliGP2 PLBU doing primitive assembly. This does not include scissoring or final output. This includes time spent waiting on the bus."/>
+ <event event="0x1c" title="Mali-4xx VP" name="Active cycles, PLBU vertex fetcher" description="Number of active cycles per frame spent by the MaliGP2 PLBU fetching vertex data. This includes time spent waiting on the bus."/>
+ <event event="0x1e" title="Mali-4xx VP" name="Active cycles, Bounding-box and command generator" description="Number of active cycles per frame spent by the MaliGP2 PLBU setting up bounding boxes and commands (mainly graphics primitives). This includes time spent waiting on the bus."/>
+ <event event="0x20" title="Mali-4xx VP" name="Active cycles, Scissor tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over tiles to perform scissoring. This includes time spent waiting on the bus."/>
+ <event event="0x21" title="Mali-4xx VP" name="Active cycles, PLBU tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over the tiles in the bounding box generating commands (mainly graphics primitives). This includes time spent waiting on the bus."/>
</category>
- <category name="Mali GPU Fragment Processor" per_cpu="no">
+ <category name="Mali Fragment Processor" per_cpu="no">
<counter_set name="ARM_Mali-4xx_FP_0_cnt" title="Mali-4xx FP0" description="Mali GPU Fragment Processor 0" count="2"/>
<counter_set name="ARM_Mali-4xx_FP_1_cnt" title="Mali-4xx FP1" description="Mali GPU Fragment Processor 1" count="2"/>
<counter_set name="ARM_Mali-4xx_FP_2_cnt" title="Mali-4xx FP2" description="Mali GPU Fragment Processor 2" count="2"/>
@@ -37,7 +36,6 @@
<counter_set name="ARM_Mali-4xx_FP_5_cnt" title="Mali-4xx FP5" description="Mali GPU Fragment Processor 5" count="2"/>
<counter_set name="ARM_Mali-4xx_FP_6_cnt" title="Mali-4xx FP6" description="Mali GPU Fragment Processor 6" count="2"/>
<counter_set name="ARM_Mali-4xx_FP_7_cnt" title="Mali-4xx FP7" description="Mali GPU Fragment Processor 7" count="2"/>
-
<event event="0x00" title="Mali-4xx FP" name="Active clock cycles" description="Active clock cycles, between polygon start and IRQ."/>
<event event="0x02" title="Mali-4xx FP" name="Total bus reads" description="Total number of 64-bit words read from the bus."/>
<event event="0x03" title="Mali-4xx FP" name="Total bus writes" description="Total number of 64-bit words written to the bus."/>
@@ -96,11 +94,10 @@
<event event="0x3c" title="Mali-4xx FP" name="Program cache hit count" description="Number of hits in the program cache."/>
<event event="0x3d" title="Mali-4xx FP" name="Program cache miss count" description="Number of misses in the program cache."/>
</category>
- <counter_set name="ARM_Mali-4xx_L2_0_cnt" title="Mali-4xx L2 0" description="Mali GPU L2 Cache Core 0" count="2"/>
- <category name="Mali-4xx-L2_0" counter_set="ARM_Mali-4xx_L2_0_cnt" per_cpu="no">
+ <counter_set name="ARM_Mali-4xx_L2_0_cnt" title="Mali-4xx L2" description="Mali GPU L2 Cache Core 0" count="2"/>
+ <category name="Mali-4xx L2" counter_set="ARM_Mali-4xx_L2_0_cnt" per_cpu="no">
<event event="0x01" title="Mali L2 Cache" name="Total clock cycles" description="Total clock cycles"/>
<event event="0x02" title="Mali L2 Cache" name="Active clock cycles" description="Active clock cycles"/>
-
<option_set name="All">
<option event_delta="0x08" name="Master" description="Master"/>
<option event_delta="0x10" name="All slaves" description="All slaves"/>
@@ -110,7 +107,6 @@
<option event_delta="0x50" name="Slave 3" description="Slave 3"/>
<option event_delta="0x60" name="Slave 4" description="Slave 4"/>
</option_set>
-
<option_set name="Slaves">
<option event_delta="0x10" name="All slaves" description="All slaves"/>
<option event_delta="0x20" name="Slave 0" description="Slave 0"/>
@@ -119,7 +115,6 @@
<option event_delta="0x50" name="Slave 3" description="Slave 3"/>
<option event_delta="0x60" name="Slave 4" description="Slave 4"/>
</option_set>
-
<event event="0x00" option_set="All" title="Mali L2 Cache" name="Read transactions" description="Read transactions"/>
<event event="0x01" option_set="All" title="Mali L2 Cache" name="Write transactions" description="Write transactions"/>
<event event="0x02" option_set="All" title="Mali L2 Cache" name="Words read" description="Words read"/>
@@ -131,10 +126,9 @@
<event event="0x08" option_set="Slaves" title="Mali L2 Cache" name="Cacheable read transactions" description="Cacheable read transactions"/>
</category>
<counter_set name="ARM_Mali-4xx_L2_1_cnt" title="Mali-4xx L2 1" description="Mali GPU L2 Cache Core 1" count="2"/>
- <category name="Mali-4xx-L2_1" counter_set="ARM_Mali-4xx_L2_1_cnt" per_cpu="no">
- <event event="0x01" title="Mali L2 Cache" name="Total clock cycles" description="Total clock cycles"/>
- <event event="0x02" title="Mali L2 Cache" name="Active clock cycles" description="Active clock cycles"/>
-
+ <category name="Mali-4xx L2_1" counter_set="ARM_Mali-4xx_L2_1_cnt" per_cpu="no">
+ <event event="0x01" title="Mali L2 Cache 1" name="Total clock cycles" description="Total clock cycles"/>
+ <event event="0x02" title="Mali L2 Cache 1" name="Active clock cycles" description="Active clock cycles"/>
<option_set name="All">
<option event_delta="0x08" name="Master" description="Master"/>
<option event_delta="0x10" name="All slaves" description="All slaves"/>
@@ -144,7 +138,6 @@
<option event_delta="0x50" name="Slave 3" description="Slave 3"/>
<option event_delta="0x60" name="Slave 4" description="Slave 4"/>
</option_set>
-
<option_set name="Slaves">
<option event_delta="0x10" name="All slaves" description="All slaves"/>
<option event_delta="0x20" name="Slave 0" description="Slave 0"/>
@@ -153,22 +146,20 @@
<option event_delta="0x50" name="Slave 3" description="Slave 3"/>
<option event_delta="0x60" name="Slave 4" description="Slave 4"/>
</option_set>
-
- <event event="0x00" option_set="All" title="Mali L2 Cache" name="Read transactions" description="Read transactions"/>
- <event event="0x01" option_set="All" title="Mali L2 Cache" name="Write transactions" description="Write transactions"/>
- <event event="0x02" option_set="All" title="Mali L2 Cache" name="Words read" description="Words read"/>
- <event event="0x03" option_set="All" title="Mali L2 Cache" name="Words written" description="Words written"/>
- <event event="0x04" option_set="Slaves" title="Mali L2 Cache" name="Read hits" description="Read hits"/>
- <event event="0x05" option_set="Slaves" title="Mali L2 Cache" name="Read misses" description="Read misses"/>
- <event event="0x06" option_set="Slaves" title="Mali L2 Cache" name="Write invalidates" description="Write invalidates"/>
- <event event="0x07" option_set="Slaves" title="Mali L2 Cache" name="Read invalidates" description="Read invalidates"/>
- <event event="0x08" option_set="Slaves" title="Mali L2 Cache" name="Cacheable read transactions" description="Cacheable read transactions"/>
+ <event event="0x00" option_set="All" title="Mali L2 Cache 1" name="Read transactions" description="Read transactions"/>
+ <event event="0x01" option_set="All" title="Mali L2 Cache 1" name="Write transactions" description="Write transactions"/>
+ <event event="0x02" option_set="All" title="Mali L2 Cache 1" name="Words read" description="Words read"/>
+ <event event="0x03" option_set="All" title="Mali L2 Cache 1" name="Words written" description="Words written"/>
+ <event event="0x04" option_set="Slaves" title="Mali L2 Cache 1" name="Read hits" description="Read hits"/>
+ <event event="0x05" option_set="Slaves" title="Mali L2 Cache 1" name="Read misses" description="Read misses"/>
+ <event event="0x06" option_set="Slaves" title="Mali L2 Cache 1" name="Write invalidates" description="Write invalidates"/>
+ <event event="0x07" option_set="Slaves" title="Mali L2 Cache 1" name="Read invalidates" description="Read invalidates"/>
+ <event event="0x08" option_set="Slaves" title="Mali L2 Cache 1" name="Cacheable read transactions" description="Cacheable read transactions"/>
</category>
<counter_set name="ARM_Mali-4xx_L2_2_cnt" title="Mali-4xx L2 2" description="Mali GPU L2 Cache Core 2" count="2"/>
- <category name="Mali-4xx-L2_2" counter_set="ARM_Mali-4xx_L2_2_cnt" per_cpu="no">
- <event event="0x01" title="Mali L2 Cache" name="Total clock cycles" description="Total clock cycles"/>
- <event event="0x02" title="Mali L2 Cache" name="Active clock cycles" description="Active clock cycles"/>
-
+ <category name="Mali-4xx L2_2" counter_set="ARM_Mali-4xx_L2_2_cnt" per_cpu="no">
+ <event event="0x01" title="Mali L2 Cache 2" name="Total clock cycles" description="Total clock cycles"/>
+ <event event="0x02" title="Mali L2 Cache 2" name="Active clock cycles" description="Active clock cycles"/>
<option_set name="All">
<option event_delta="0x08" name="Master" description="Master"/>
<option event_delta="0x10" name="All slaves" description="All slaves"/>
@@ -178,7 +169,6 @@
<option event_delta="0x50" name="Slave 3" description="Slave 3"/>
<option event_delta="0x60" name="Slave 4" description="Slave 4"/>
</option_set>
-
<option_set name="Slaves">
<option event_delta="0x10" name="All slaves" description="All slaves"/>
<option event_delta="0x20" name="Slave 0" description="Slave 0"/>
@@ -187,18 +177,18 @@
<option event_delta="0x50" name="Slave 3" description="Slave 3"/>
<option event_delta="0x60" name="Slave 4" description="Slave 4"/>
</option_set>
-
- <event event="0x00" option_set="All" title="Mali L2 Cache" name="Read transactions" description="Read transactions"/>
- <event event="0x01" option_set="All" title="Mali L2 Cache" name="Write transactions" description="Write transactions"/>
- <event event="0x02" option_set="All" title="Mali L2 Cache" name="Words read" description="Words read"/>
- <event event="0x03" option_set="All" title="Mali L2 Cache" name="Words written" description="Words written"/>
- <event event="0x04" option_set="Slaves" title="Mali L2 Cache" name="Read hits" description="Read hits"/>
- <event event="0x05" option_set="Slaves" title="Mali L2 Cache" name="Read misses" description="Read misses"/>
- <event event="0x06" option_set="Slaves" title="Mali L2 Cache" name="Write invalidates" description="Write invalidates"/>
- <event event="0x07" option_set="Slaves" title="Mali L2 Cache" name="Read invalidates" description="Read invalidates"/>
- <event event="0x08" option_set="Slaves" title="Mali L2 Cache" name="Cacheable read transactions" description="Cacheable read transactions"/>
+ <event event="0x00" option_set="All" title="Mali L2 Cache 2" name="Read transactions" description="Read transactions"/>
+ <event event="0x01" option_set="All" title="Mali L2 Cache 2" name="Write transactions" description="Write transactions"/>
+ <event event="0x02" option_set="All" title="Mali L2 Cache 2" name="Words read" description="Words read"/>
+ <event event="0x03" option_set="All" title="Mali L2 Cache 2" name="Words written" description="Words written"/>
+ <event event="0x04" option_set="Slaves" title="Mali L2 Cache 2" name="Read hits" description="Read hits"/>
+ <event event="0x05" option_set="Slaves" title="Mali L2 Cache 2" name="Read misses" description="Read misses"/>
+ <event event="0x06" option_set="Slaves" title="Mali L2 Cache 2" name="Write invalidates" description="Write invalidates"/>
+ <event event="0x07" option_set="Slaves" title="Mali L2 Cache 2" name="Read invalidates" description="Read invalidates"/>
+ <event event="0x08" option_set="Slaves" title="Mali L2 Cache 2" name="Cacheable read transactions" description="Cacheable read transactions"/>
</category>
- <category name="ARM Mali-4xx Filmstrip" counter_set="ARM_Mali-4xx_Filmstrip_cnt" per_cpu="no">
+ <counter_set name="ARM_Mali-4xx_Filmstrip_cnt" count="1"/>
+ <category name="Mali-4xx Filmstrip" counter_set="ARM_Mali-4xx_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"/>
@@ -212,7 +202,11 @@
<category name="ARM_Mali-4xx_Frequency" per_cpu="no">
<event counter="ARM_Mali-4xx_Frequency" title="Mali GPU Frequency" name="Frequency" display="average" average_selection="yes" units="MHz" description="GPU core frequency."/>
</category>
- <category name="Mali-4xx-SW" counter_set="ARM_Mali-4xx_SW_cnt" per_cpu="no">
+ <category name="Mali-4xx Activity" counter_set="ARM_Mali-4xx_Activity_cnt">
+ <event counter="ARM_Mali-4xx_fragment" title="GPU Fragment" name="Activity" class="activity" activity1="Activity" activity_color1="0x00006fcc" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" description="GPU Fragment Activity"/>
+ <event counter="ARM_Mali-4xx_vertex" title="GPU Vertex" name="Activity" class="activity" activity1="Activity" activity_color1="0x00eda000" rendering_type="bar" average_selection="yes" percentage="yes" description="GPU Vertex Activity"/>
+ </category>
+ <category name="Mali-4xx Software Counters" counter_set="ARM_Mali-4xx_SW_cnt" per_cpu="no">
<!-- EGL Counters -->
<event counter="ARM_Mali-4xx_SW_0" title="Mali EGL Software Counters" name="Blit Time" description="Time spent blitting the framebuffer from video memory to framebuffer."/>
<!-- glDrawElements Counters -->
diff --git a/daemon/events-Mali-T6xx.xml b/daemon/events-Mali-T6xx.xml
index ec9ca00..5e89797 100644
--- a/daemon/events-Mali-T6xx.xml
+++ b/daemon/events-Mali-T6xx.xml
@@ -1,9 +1,7 @@
-
- <category name="Mali-T6xx-SW-counters" per_cpu="no">
+ <category name="Mali-T6xx Software Counters" per_cpu="no">
<event counter="ARM_Mali-T6xx_TOTAL_ALLOC_PAGES" title="Mali Total Alloc Pages" name="Total number of allocated pages" description="Mali total number of allocated pages."/>
</category>
-
- <category name="Mali-T6xx-PMShader" per_cpu="no">
+ <category name="Mali-T6xx PM Shader" per_cpu="no">
<event counter="ARM_Mali-T6xx_PM_SHADER_0" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 0" description="Mali PM Shader: PM Shader Core 0."/>
<event counter="ARM_Mali-T6xx_PM_SHADER_1" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 1" description="Mali PM Shader: PM Shader Core 1."/>
<event counter="ARM_Mali-T6xx_PM_SHADER_2" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 2" description="Mali PM Shader: PM Shader Core 2."/>
@@ -13,32 +11,27 @@
<event counter="ARM_Mali-T6xx_PM_SHADER_6" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 6" description="Mali PM Shader: PM Shader Core 6."/>
<event counter="ARM_Mali-T6xx_PM_SHADER_7" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 7" description="Mali PM Shader: PM Shader Core 7."/>
</category>
-
- <category name="Mali-T6xx-PMTiler" per_cpu="no">
+ <category name="Mali-T6xx PM Tiler" per_cpu="no">
<event counter="ARM_Mali-T6xx_PM_TILER_0" display="average" average_selection="yes" percentage="yes" title="Mali PM Tiler" name="PM Tiler Core 0" description="Mali PM Tiler: PM Tiler Core 0."/>
</category>
-
- <category name="Mali-T6xx-PML2" per_cpu="no">
+ <category name="Mali-T6xx PM L2" per_cpu="no">
<event counter="ARM_Mali-T6xx_PM_L2_0" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 0" description="Mali PM L2: PM L2 Core 0."/>
<event counter="ARM_Mali-T6xx_PM_L2_1" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 1" description="Mali PM L2: PM L2 Core 1."/>
</category>
-
- <category name="Mali-T6xx-MMU_AS" per_cpu="no">
+ <category name="Mali-T6xx MMU Address Space" per_cpu="no">
<event counter="ARM_Mali-T6xx_MMU_AS_0" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 0" description="Mali MMU Address Space 0 usage."/>
<event counter="ARM_Mali-T6xx_MMU_AS_1" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 1" description="Mali MMU Address Space 1 usage."/>
<event counter="ARM_Mali-T6xx_MMU_AS_2" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 2" description="Mali MMU Address Space 2 usage."/>
<event counter="ARM_Mali-T6xx_MMU_AS_3" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 3" description="Mali MMU Address Space 3 usage."/>
</category>
-
- <category name="Mali-T6xx-MMU_page_fault" per_cpu="no">
+ <category name="Mali-T6xx MMU Page Fault" per_cpu="no">
<event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_0" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 0" description="Reports the number of newly allocated pages after a MMU page fault in address space 0."/>
<event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_1" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 1" description="Reports the number of newly allocated pages after a MMU page fault in address space 1."/>
<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">
+ <category name="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"/>
@@ -46,3 +39,8 @@
</option_set>
<event event="0x0400" option_set="fs" title="ARM Mali-T6xx" name="Filmstrip" description="Scaled framebuffer"/>
</category>
+ <category name="Mali-T6xx Activity" per_cpu="no">
+ <event counter="ARM_Mali-T6xx_fragment" title="GPU Fragment" name="Activity" class="activity" activity1="Activity" activity_color1="0x00006fcc" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 0 Activity"/>
+ <event counter="ARM_Mali-T6xx_vertex" title="GPU Vertex-Tiling-Compute" name="Activity" class="activity" activity1="Activity" activity_color1="0x00eda000" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 1 Activity"/>
+ <event counter="ARM_Mali-T6xx_opencl" title="GPU Vertex-Compute" name="Activity" class="activity" activity1="Activity" activity_color1="0x00ef022f" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 2 Activity"/>
+ </category>
diff --git a/daemon/events-Mali-T6xx_hw.xml b/daemon/events-Mali-T6xx_hw.xml
index 03566cb..df27962 100644
--- a/daemon/events-Mali-T6xx_hw.xml
+++ b/daemon/events-Mali-T6xx_hw.xml
@@ -1,35 +1,27 @@
-
- <category name="Mali-T6xx-JobManager" per_cpu="no">
-
+ <category name="Mali-T6xx Job Manager" per_cpu="no">
<event counter="ARM_Mali-T6xx_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles the GPU was active"/>
<event counter="ARM_Mali-T6xx_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles the GPU had a pending interrupt"/>
<event counter="ARM_Mali-T6xx_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) was active"/>
<event counter="ARM_Mali-T6xx_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) was active"/>
<event counter="ARM_Mali-T6xx_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) was active"/>
-
<event counter="ARM_Mali-T6xx_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
<event counter="ARM_Mali-T6xx_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
<event counter="ARM_Mali-T6xx_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
<event counter="ARM_Mali-T6xx_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
<event counter="ARM_Mali-T6xx_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
<event counter="ARM_Mali-T6xx_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
-
</category>
-
- <category name="Mali-T6xx-Tiler" per_cpu="no">
-
+ <category name="Mali-T6xx Tiler" per_cpu="no">
<event counter="ARM_Mali-T6xx_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
<event counter="ARM_Mali-T6xx_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
<event counter="ARM_Mali-T6xx_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
<event counter="ARM_Mali-T6xx_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
<event counter="ARM_Mali-T6xx_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
-
<event counter="ARM_Mali-T6xx_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
<event counter="ARM_Mali-T6xx_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
<event counter="ARM_Mali-T6xx_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
<event counter="ARM_Mali-T6xx_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
<event counter="ARM_Mali-T6xx_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
-
<event counter="ARM_Mali-T6xx_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
<event counter="ARM_Mali-T6xx_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
<event counter="ARM_Mali-T6xx_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
@@ -38,7 +30,6 @@
<event counter="ARM_Mali-T6xx_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
<event counter="ARM_Mali-T6xx_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
<event counter="ARM_Mali-T6xx_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
-
<event counter="ARM_Mali-T6xx_COMMAND_1" title="Mali Tiler Commands" name="Prims in 1 command" description="Number of primitives producing 1 command"/>
<event counter="ARM_Mali-T6xx_COMMAND_2" title="Mali Tiler Commands" name="Prims in 2 command" description="Number of primitives producing 2 commands"/>
<event counter="ARM_Mali-T6xx_COMMAND_3" title="Mali Tiler Commands" name="Prims in 3 command" description="Number of primitives producing 3 commands"/>
@@ -48,48 +39,36 @@
<event counter="ARM_Mali-T6xx_COMMAND_8_15" title="Mali Tiler Commands" name="Prims in 8-15 commands" description="Number of primitives producing 8-15 commands"/>
<event counter="ARM_Mali-T6xx_COMMAND_16_63" title="Mali Tiler Commands" name="Prims in 16-63 commands" description="Number of primitives producing 16-63 commands"/>
<event counter="ARM_Mali-T6xx_COMMAND_64" title="Mali Tiler Commands" name="Prims in &gt;= 64 commands" description="Number of primitives producing &gt;= 64 commands"/>
-
</category>
-
- <category name="Mali-T6xx-ShaderCore" per_cpu="no">
-
+ <category name="Mali-T6xx Shader Core" per_cpu="no">
<event counter="ARM_Mali-T6xx_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles the Tripipe was active"/>
<event counter="ARM_Mali-T6xx_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
<event counter="ARM_Mali-T6xx_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
<event counter="ARM_Mali-T6xx_FRAG_CYCLE_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
-
<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_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"/>
<event counter="ARM_Mali-T6xx_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
-
<event counter="ARM_Mali-T6xx_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
<event counter="ARM_Mali-T6xx_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
<event counter="ARM_Mali-T6xx_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
-
<event counter="ARM_Mali-T6xx_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
<event counter="ARM_Mali-T6xx_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
-
<event counter="ARM_Mali-T6xx_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
-
<event counter="ARM_Mali-T6xx_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
<event counter="ARM_Mali-T6xx_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
-
<event counter="ARM_Mali-T6xx_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
<event counter="ARM_Mali-T6xx_TEX_THREADS" title="Mali Texture Pipe" name="T instruction issues" description="Number of instructions issused to the T-pipe, including restarts"/>
<event counter="ARM_Mali-T6xx_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
-
<event counter="ARM_Mali-T6xx_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
<event counter="ARM_Mali-T6xx_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
<event counter="ARM_Mali-T6xx_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
@@ -99,11 +78,8 @@
<event counter="ARM_Mali-T6xx_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
<event counter="ARM_Mali-T6xx_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
<event counter="ARM_Mali-T6xx_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
-
</category>
-
- <category name="Mali-T6xx-L2AndMMU" per_cpu="no">
-
+ <category name="Mali-T6xx L2 and MMU" per_cpu="no">
<event counter="ARM_Mali-T6xx_L2_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
<event counter="ARM_Mali-T6xx_L2_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
<event counter="ARM_Mali-T6xx_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
@@ -112,5 +88,4 @@
<event counter="ARM_Mali-T6xx_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
<event counter="ARM_Mali-T6xx_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
<event counter="ARM_Mali-T6xx_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
-
</category>
diff --git a/daemon/events-Mali-V500.xml b/daemon/events-Mali-V500.xml
new file mode 100644
index 0000000..d2751e7
--- /dev/null
+++ b/daemon/events-Mali-V500.xml
@@ -0,0 +1,29 @@
+ <category name="Mali-V500">
+ <event counter="ARM_Mali-V500_cnt0" title="Mali Video Engine" name="Samples" class="absolute" description="The number of times we have taken a sample"/>
+ <event counter="ARM_Mali-V500_cnt1" title="Mali Video Engine" name="Queued input-buffers" class="absolute" description="The number of input-buffers that has been queued for consumption by the MVE"/>
+ <event counter="ARM_Mali-V500_cnt2" title="Mali Video Engine" name="Consumed input-buffers" class="absolute" description="The number of input-buffers that has been consumed by the MVE and returned to the application"/>
+ <event counter="ARM_Mali-V500_cnt3" title="Mali Video Engine" name="Queued output-buffers" class="absolute" description="The number of output-buffers that has been queued for usage by the MVE"/>
+ <event counter="ARM_Mali-V500_cnt4" title="Mali Video Engine" name="Consumed output-buffers" class="absolute" description="The number of output-buffers that has been consumed by the MVE and returned to the application"/>
+ <event counter="ARM_Mali-V500_cnt5" title="Mali Video Engine" name="Created Sessions" class="absolute" description="The number of created sessions throughout the lifetime of the process"/>
+ <event counter="ARM_Mali-V500_cnt6" title="Mali Video Engine" name="Active Sessions" description="The number of currently existing sessions"/>
+ <event counter="ARM_Mali-V500_cnt7" title="Mali Video Engine" name="Processed Frames" class="absolute" description="The number of processed frames. A processed frame is one where the encode or decode is complete for that particular frame. Frames can be processed out of order so this is not the same as the number of output-buffers returned"/>
+ <event counter="ARM_Mali-V500_cnt8" title="Mali Video Engine" name="Input Flushes Requested" class="absolute" description="The number of requested flushes of the input queue"/>
+ <event counter="ARM_Mali-V500_cnt9" title="Mali Video Engine" name="Input Flushes Complete" class="absolute" description="The number of completed flushes of the input queue"/>
+ <event counter="ARM_Mali-V500_cnt10" title="Mali Video Engine" name="Output Flushes Requested" class="absolute" description="The number of requested flushes of the output queue"/>
+ <event counter="ARM_Mali-V500_cnt11" title="Mali Video Engine" name="Output Flushes Complete" class="absolute" description="The number of completed flushes of the output queue"/>
+ <event counter="ARM_Mali-V500_cnt12" title="Mali Video Engine" name="Queued Output Buffers (current)" description="The number of output-buffers that are currently queued for usage by the MVE"/>
+ <event counter="ARM_Mali-V500_cnt13" title="Mali Video Engine" name="Queued Input Buffers (current)" description="The number of input-buffers that are currently queued for consumption by the MVE"/>
+ <event counter="ARM_Mali-V500_cnt14" title="Mali Video Engine" name="Output Queue Flushes" description="The number of pending flushes for the MVE output-queue"/>
+ <event counter="ARM_Mali-V500_cnt15" title="Mali Video Engine" name="Input Queue Flushes" description="The number of pending flushes for the MVE input-queue"/>
+ <event counter="ARM_Mali-V500_cnt16" title="Mali Video Engine" name="Errors encountered" class="absolute" description="The number of errors encountered"/>
+ <event counter="ARM_Mali-V500_cnt17" title="Mali Video Engine" name="Bits consumed" class="absolute" description="The number of bits consumed during decode"/>
+ <event counter="ARM_Mali-V500_cnt18" title="Mali Video Engine" name="AFBC bandwidth" class="absolute" description="The amount of AFBC-encoded bytes read or written"/>
+ <event counter="ARM_Mali-V500_cnt19" title="Mali Video Engine" name="Bandwidth (read)" class="absolute" description="The amount of bytes read over the AXI bus"/>
+ <event counter="ARM_Mali-V500_cnt20" title="Mali Video Engine" name="Bandwidth (write)" class="absolute" description="The amount of bytes written over the AXI bus"/>
+ <event counter="ARM_Mali-V500_evn0" title="Mali Video Engine" name="Session created" description="Generated when a session has been created"/>
+ <event counter="ARM_Mali-V500_evn1" title="Mali Video Engine" name="Session destroyed" description="Generated when a session has been destroyed"/>
+ <event counter="ARM_Mali-V500_evn2" title="Mali Video Engine" name="Frame Processed" description="Generated when the MVE has finished processing a frame"/>
+ <event counter="ARM_Mali-V500_evn3" title="Mali Video Engine" name="Output buffer received" description="Generated when an an output buffer is returned to us from the MVE"/>
+ <event counter="ARM_Mali-V500_evn4" title="Mali Video Engine" name="Input buffer received" description="Generated when we an input buffer is returned to us from the MVE"/>
+ <!--event counter="ARM_Mali-V500_act" title="VPU" name="Activity" class="activity" activity1="Parsed" activity_color1="0x000000ff" activity2="Piped" activity_color2="0x0000ff00" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" cores="8" description="Mali-V500 Activity"/-->
+ </category>
diff --git a/daemon/main.cpp b/daemon/main.cpp
index 1275aef..2998c70 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -20,8 +20,10 @@
#include <unistd.h>
#include "Child.h"
+#include "EventsXML.h"
#include "KMod.h"
#include "Logging.h"
+#include "Monitor.h"
#include "OlySocket.h"
#include "OlyUtility.h"
#include "SessionData.h"
@@ -31,8 +33,9 @@
extern Child* child;
static int shutdownFilesystem();
static pthread_mutex_t numSessions_mutex;
-static int numSessions = 0;
static OlyServerSocket* sock = NULL;
+static Monitor monitor;
+static int numSessions = 0;
static bool driverRunningAtStart = false;
static bool driverMountedAtStart = false;
@@ -102,42 +105,8 @@ static void child_exit(int) {
}
}
-static int udpPort(int port) {
- int s;
- struct sockaddr_in6 sockaddr;
- int on;
- int family = AF_INET6;
-
- s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
- if (s == -1) {
- family = AF_INET;
- s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (s == -1) {
- logg->logError(__FILE__, __LINE__, "socket failed");
- handleException();
- }
- }
-
- on = 1;
- if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) != 0) {
- logg->logError(__FILE__, __LINE__, "setsockopt failed");
- handleException();
- }
-
- memset((void*)&sockaddr, 0, sizeof(sockaddr));
- 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();
- }
-
- return s;
-}
-
-#define UDP_ANS_PORT 30000
-#define UDP_REQ_PORT 30001
+static const int UDP_ANS_PORT = 30000;
+static const int UDP_REQ_PORT = 30001;
typedef struct {
char rviHeader[8];
@@ -149,50 +118,102 @@ typedef struct {
uint32_t ipAddress;
uint32_t defaultGateway;
uint32_t subnetMask;
- uint32_t activeConnections;
+ uint32_t activeConnections;
} RVIConfigureInfo;
static const char DST_REQ[] = { 'D', 'S', 'T', '_', 'R', 'E', 'Q', ' ', 0, 0, 0, 0x64 };
-static void* answerThread(void* pVoid) {
- prctl(PR_SET_NAME, (unsigned long)&"gatord-discover", 0, 0, 0);
- const struct cmdline_t * const cmdline = (struct cmdline_t *)pVoid;
- RVIConfigureInfo dstAns;
- int req = udpPort(UDP_REQ_PORT);
- int ans = udpPort(UDP_ANS_PORT);
-
- // Format the answer buffer
- memset(&dstAns, 0, sizeof(dstAns));
- memcpy(dstAns.rviHeader, "STR_ANS ", sizeof(dstAns.rviHeader));
- if (gethostname(dstAns.dhcpName, sizeof(dstAns.dhcpName) - 1) != 0) {
- logg->logError(__FILE__, __LINE__, "gethostname failed");
- handleException();
+class UdpListener {
+public:
+ UdpListener() : mDstAns(), mReq(-1), mAns(-1) {}
+
+ void setup(int port) {
+ mReq = udpPort(UDP_REQ_PORT);
+ mAns = udpPort(UDP_ANS_PORT);
+
+ // Format the answer buffer
+ memset(&mDstAns, 0, sizeof(mDstAns));
+ memcpy(mDstAns.rviHeader, "STR_ANS ", sizeof(mDstAns.rviHeader));
+ if (gethostname(mDstAns.dhcpName, sizeof(mDstAns.dhcpName) - 1) != 0) {
+ logg->logError(__FILE__, __LINE__, "gethostname failed");
+ handleException();
+ }
+ // Subvert the defaultGateway field for the port number
+ if (port != DEFAULT_PORT) {
+ mDstAns.defaultGateway = port;
+ }
+ // Subvert the subnetMask field for the protocol version
+ mDstAns.subnetMask = PROTOCOL_VERSION;
}
- // Subvert the defaultGateway field for the port number
- if (cmdline->port != DEFAULT_PORT) {
- dstAns.defaultGateway = cmdline->port;
+
+ int getReq() const {
+ return mReq;
}
- // Subvert the subnetMask field for the protocol version
- dstAns.subnetMask = PROTOCOL_VERSION;
- for (;;) {
+ void handle() {
char buf[128];
struct sockaddr_in6 sockaddr;
socklen_t addrlen;
int read;
addrlen = sizeof(sockaddr);
- read = recvfrom(req, &buf, sizeof(buf), 0, (struct sockaddr *)&sockaddr, &addrlen);
+ read = recvfrom(mReq, &buf, sizeof(buf), 0, (struct sockaddr *)&sockaddr, &addrlen);
if (read < 0) {
logg->logError(__FILE__, __LINE__, "recvfrom failed");
handleException();
} else if ((read == 12) && (memcmp(buf, DST_REQ, sizeof(DST_REQ)) == 0)) {
- if (sendto(ans, &dstAns, sizeof(dstAns), 0, (struct sockaddr *)&sockaddr, addrlen) != sizeof(dstAns)) {
+ if (sendto(mAns, &mDstAns, sizeof(mDstAns), 0, (struct sockaddr *)&sockaddr, addrlen) != sizeof(mDstAns)) {
logg->logError(__FILE__, __LINE__, "sendto failed");
handleException();
}
}
}
-}
+
+ void close() {
+ ::close(mReq);
+ ::close(mAns);
+ }
+
+private:
+ int udpPort(int port) {
+ int s;
+ struct sockaddr_in6 sockaddr;
+ int on;
+ int family = AF_INET6;
+
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s == -1) {
+ family = AF_INET;
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (s == -1) {
+ logg->logError(__FILE__, __LINE__, "socket failed");
+ handleException();
+ }
+ }
+
+ on = 1;
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) != 0) {
+ logg->logError(__FILE__, __LINE__, "setsockopt failed");
+ handleException();
+ }
+
+ memset((void*)&sockaddr, 0, sizeof(sockaddr));
+ 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();
+ }
+
+ return s;
+ }
+
+ RVIConfigureInfo mDstAns;
+ int mReq;
+ int mAns;
+};
+
+static UdpListener udpListener;
// retval: -1 = failure; 0 = was already mounted; 1 = successfully mounted
static int mountGatorFS() {
@@ -218,7 +239,7 @@ static bool init_module (const char * const location) {
if (fstat(fd, &st) == 0) {
void * const p = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (p != MAP_FAILED) {
- if (syscall(__NR_init_module, p, st.st_size, "") == 0) {
+ if (syscall(__NR_init_module, p, (unsigned long)st.st_size, "") == 0) {
ret = true;
}
munmap(p, st.st_size);
@@ -264,8 +285,14 @@ static bool setupFilesystem(char* module) {
}
if (access(location, F_OK) == -1) {
- // The gator kernel is not already loaded and unable to locate gator.ko
- return false;
+ if (module == NULL) {
+ // The gator kernel is not already loaded and unable to locate gator.ko in the default location
+ return false;
+ } else {
+ // gator location specified on the command line but it was not found
+ logg->logError(__FILE__, __LINE__, "gator module not found at %s", location);
+ handleException();
+ }
}
// Load driver
@@ -380,6 +407,45 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
return cmdline;
}
+void handleClient() {
+ OlySocket client(sock->acceptConnection());
+
+ int pid = fork();
+ if (pid < 0) {
+ // Error
+ logg->logError(__FILE__, __LINE__, "Fork process failed. Please power cycle the target device if this error persists.");
+ } else if (pid == 0) {
+ // Child
+ sock->closeServerSocket();
+ udpListener.close();
+ monitor.close();
+ child = new Child(&client, numSessions + 1);
+ child->run();
+ delete child;
+ exit(0);
+ } else {
+ // Parent
+ client.closeSocket();
+
+ pthread_mutex_lock(&numSessions_mutex);
+ numSessions++;
+ pthread_mutex_unlock(&numSessions_mutex);
+
+ // Maximum number of connections is 2
+ int wait = 0;
+ while (numSessions > 1) {
+ // Throttle until one of the children exits before continuing to accept another socket connection
+ logg->logMessage("%d sessions active!", numSessions);
+ if (wait++ >= 10) { // Wait no more than 10 seconds
+ // Kill last created child
+ kill(pid, SIGALRM);
+ break;
+ }
+ sleep(1);
+ }
+ }
+}
+
// Gator data flow: collector -> collector fifo -> sender
int main(int argc, char** argv) {
// Ensure proper signal handling by making gatord the process group leader
@@ -420,16 +486,23 @@ int main(int argc, char** argv) {
logg->logMessage("Unable to setup gatorfs, trying perf");
if (!gSessionData->perf.setup()) {
logg->logError(__FILE__, __LINE__,
- "Unable to locate gator.ko driver:\n"
- " >>> gator.ko should be co-located with gatord in the same directory\n"
- " >>> OR insmod gator.ko prior to launching gatord\n"
- " >>> OR specify the location of gator.ko on the command line\n"
- " >>> OR run Linux 3.12 or later with perf support to collect data via userspace only");
+ "Unable to locate gator.ko driver:\n"
+ " >>> gator.ko should be co-located with gatord in the same directory\n"
+ " >>> OR insmod gator.ko prior to launching gatord\n"
+ " >>> OR specify the location of gator.ko on the command line\n"
+ " >>> OR run Linux 3.4 or later with perf (CONFIG_PERF_EVENTS and CONFIG_HW_PERF_EVENTS) and tracing (CONFIG_TRACING) support to collect data via userspace only");
handleException();
}
}
gSessionData->hwmon.setup();
+ {
+ EventsXML eventsXML;
+ mxml_node_t *xml = eventsXML.getTree();
+ gSessionData->fsDriver.setup(xml);
+ gSessionData->maliVideo.setup(xml);
+ mxmlDelete(xml);
+ }
// Handle child exit codes
signal(SIGCHLD, child_exit);
@@ -444,47 +517,26 @@ int main(int argc, char** argv) {
child->run();
delete child;
} else {
- pthread_t answerThreadID;
- if (pthread_create(&answerThreadID, NULL, answerThread, &cmdline)) {
- logg->logError(__FILE__, __LINE__, "Failed to create answer thread");
+ sock = new OlyServerSocket(cmdline.port);
+ udpListener.setup(cmdline.port);
+ if (!monitor.init() || !monitor.add(sock->getFd()) || !monitor.add(udpListener.getReq())) {
+ logg->logError(__FILE__, __LINE__, "Monitor setup failed");
handleException();
}
- sock = new OlyServerSocket(cmdline.port);
// Forever loop, can be exited via a signal or exception
while (1) {
+ struct epoll_event events[2];
logg->logMessage("Waiting on connection...");
- OlySocket client(sock->acceptConnection());
-
- int pid = fork();
- if (pid < 0) {
- // Error
- logg->logError(__FILE__, __LINE__, "Fork process failed. Please power cycle the target device if this error persists.");
- } else if (pid == 0) {
- // Child
- sock->closeServerSocket();
- child = new Child(&client, numSessions + 1);
- child->run();
- delete child;
- exit(0);
- } else {
- // Parent
- client.closeSocket();
-
- pthread_mutex_lock(&numSessions_mutex);
- numSessions++;
- pthread_mutex_unlock(&numSessions_mutex);
-
- // Maximum number of connections is 2
- int wait = 0;
- while (numSessions > 1) {
- // Throttle until one of the children exits before continuing to accept another socket connection
- logg->logMessage("%d sessions active!", numSessions);
- if (wait++ >= 10) { // Wait no more than 10 seconds
- // Kill last created child
- kill(pid, SIGALRM);
- break;
- }
- sleep(1);
+ int ready = monitor.wait(events, ARRAY_LENGTH(events), -1);
+ if (ready < 0) {
+ logg->logError(__FILE__, __LINE__, "Monitor::wait failed");
+ handleException();
+ }
+ for (int i = 0; i < ready; ++i) {
+ if (events[i].data.fd == sock->getFd()) {
+ handleClient();
+ } else if (events[i].data.fd == udpListener.getReq()) {
+ udpListener.handle();
}
}
}
diff --git a/driver/Makefile b/driver/Makefile
index 3dc9d05..2f86823 100644
--- a/driver/Makefile
+++ b/driver/Makefile
@@ -7,13 +7,14 @@ CONFIG_GATOR ?= m
obj-$(CONFIG_GATOR) := gator.o
gator-y := gator_main.o \
- gator_events_irq.o \
- gator_events_sched.o \
- gator_events_net.o \
gator_events_block.o \
+ gator_events_irq.o \
gator_events_meminfo.o \
- gator_events_perf_pmu.o \
gator_events_mmapped.o \
+ gator_events_net.o \
+ gator_events_perf_pmu.o \
+ gator_events_sched.o \
+ gator_events_threads.o \
# Convert the old GATOR_WITH_MALI_SUPPORT to the new kernel flags
ifneq ($(GATOR_WITH_MALI_SUPPORT),)
@@ -48,10 +49,14 @@ ifeq ($(CONFIG_GATOR_WITH_MALI_SUPPORT),y)
ccflags-$(CONFIG_GATOR_MALI_T6XX) += -DMALI_SUPPORT=MALI_T6xx
endif
-# GATOR_TEST controls whether to include (=1) or exclude (=0) test code.
+# GATOR_TEST controls whether to include (=1) or exclude (=0) test code.
GATOR_TEST ?= 0
EXTRA_CFLAGS += -DGATOR_TEST=$(GATOR_TEST)
+# Should the original or new block_rq_complete API be used?
+OLD_BLOCK_RQ_COMPLETE := $(shell grep -A3 block_rq_complete include/trace/events/block.h | grep nr_bytes > /dev/null; echo $$?)
+EXTRA_CFLAGS += -DOLD_BLOCK_RQ_COMPLETE=$(OLD_BLOCK_RQ_COMPLETE)
+
gator-$(CONFIG_ARM) += gator_events_armv6.o \
gator_events_armv7.o \
gator_events_ccn-504.o \
diff --git a/driver/gator.h b/driver/gator.h
index 586cd9e..5ad0254 100644
--- a/driver/gator.h
+++ b/driver/gator.h
@@ -42,6 +42,10 @@
#define AARCH64 0xd0f
#define OTHER 0xfff
+// gpu enums
+#define MALI_4xx 1
+#define MALI_T6xx 2
+
#define MAXSIZE_CORE_NAME 32
struct gator_cpu {
@@ -82,13 +86,21 @@ int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root,
register_trace_##probe_name(probe_##probe_name)
# define GATOR_UNREGISTER_TRACE(probe_name) \
unregister_trace_##probe_name(probe_##probe_name)
-#else
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)
# define GATOR_DEFINE_PROBE(probe_name, proto) \
static void probe_##probe_name(void *data, PARAMS(proto))
# define GATOR_REGISTER_TRACE(probe_name) \
register_trace_##probe_name(probe_##probe_name, NULL)
# define GATOR_UNREGISTER_TRACE(probe_name) \
unregister_trace_##probe_name(probe_##probe_name, NULL)
+#else
+# define GATOR_DEFINE_PROBE(probe_name, proto) \
+ extern struct tracepoint *gator_tracepoint_##probe_name; \
+ static void probe_##probe_name(void *data, PARAMS(proto))
+# define GATOR_REGISTER_TRACE(probe_name) \
+ tracepoint_probe_register(gator_tracepoint_##probe_name, probe_##probe_name, NULL)
+# define GATOR_UNREGISTER_TRACE(probe_name) \
+ tracepoint_probe_unregister(gator_tracepoint_##probe_name, probe_##probe_name, NULL)
#endif
/******************************************************************************
@@ -115,6 +127,8 @@ u32 gator_cpuid(void);
void gator_backtrace_handler(struct pt_regs *const regs);
+void gator_marshal_activity_switch(int core, int key, int activity, int pid);
+
#if !GATOR_IKS_SUPPORT
#define get_physical_cpu() smp_processor_id()
diff --git a/driver/gator_backtrace.c b/driver/gator_backtrace.c
index 9f305cf..e03c165 100644
--- a/driver/gator_backtrace.c
+++ b/driver/gator_backtrace.c
@@ -178,7 +178,7 @@ static void kernel_backtrace(int cpu, struct pt_regs *const regs)
marshal_backtrace(PC_REG & ~1, NO_COOKIE, 1);
#endif
}
-
+
static void gator_add_sample(int cpu, struct pt_regs *const regs, u64 time)
{
bool in_kernel;
diff --git a/driver/gator_buffer.c b/driver/gator_buffer.c
index eba22df..dfbc97d 100644
--- a/driver/gator_buffer.c
+++ b/driver/gator_buffer.c
@@ -37,12 +37,12 @@ static void marshal_frame(int cpu, int buftype)
case SCHED_TRACE_BUF:
frame = FRAME_SCHED_TRACE;
break;
- case GPU_TRACE_BUF:
- frame = FRAME_GPU_TRACE;
- break;
case IDLE_BUF:
frame = FRAME_IDLE;
break;
+ case ACTIVITY_BUF:
+ frame = FRAME_ACTIVITY;
+ break;
default:
frame = -1;
break;
diff --git a/driver/gator_events_armv7.c b/driver/gator_events_armv7.c
index 153119b..bd8a9ba 100644
--- a/driver/gator_events_armv7.c
+++ b/driver/gator_events_armv7.c
@@ -27,9 +27,9 @@
// ccnt reg
#define CCNT_REG (1 << 31)
-#define CCNT 0
+#define CCNT 0
#define CNT0 1
-#define CNTMAX (6+1)
+#define CNTMAX (6+1)
static const char *pmnc_name;
static int pmnc_counters;
diff --git a/driver/gator_events_block.c b/driver/gator_events_block.c
index b2bc414..03eed4f 100644
--- a/driver/gator_events_block.c
+++ b/driver/gator_events_block.c
@@ -28,15 +28,25 @@ static ulong block_rq_rd_key;
static atomic_t blockCnt[BLOCK_TOTAL];
static int blockGet[BLOCK_TOTAL * 4];
+// Tracepoint changed in 3.15 backported to older kernels. The Makefile tries to autodetect the correct value, but if it fails change the #if below
+#if OLD_BLOCK_RQ_COMPLETE
GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct request *rq))
+#else
+GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct request *rq, unsigned int nr_bytes))
+#endif
{
- int write, size;
+ int write;
+ unsigned int size;
if (!rq)
return;
write = rq->cmd_flags & EVENTWRITE;
+#if OLD_BLOCK_RQ_COMPLETE
size = rq->resid_len;
+#else
+ size = nr_bytes;
+#endif
if (!size)
return;
diff --git a/driver/gator_events_mali_4xx.c b/driver/gator_events_mali_4xx.c
index 85d4764..9e1c706 100644
--- a/driver/gator_events_mali_4xx.c
+++ b/driver/gator_events_mali_4xx.c
@@ -18,17 +18,27 @@
#include "gator_events_mali_4xx.h"
/*
- * There are (currently) four different variants of the comms between gator and Mali:
- * 1 (deprecated): No software counter support
- * 2 (deprecated): Tracepoint called for each separate s/w counter value as it appears
- * 3 (default): Single tracepoint for all s/w counters in a bundle.
- * Interface style 3 is the default if no other is specified. 1 and 2 will be eliminated when
- * existing Mali DDKs are upgraded.
- * 4. As above, but for the Utgard (Mali-450) driver.
- */
+* There have been four different variants of the comms between gator and Mali depending on driver version:
+* # | DDK vsn range | Support | Notes
+*
+* 1 | (obsolete) | No software counter support | Obsolete patches
+* 2 | (obsolete) | Tracepoint called for each separate s/w counter value as it appears | Obsolete patches
+* 3 | r3p0-04rel0 - r3p2-01rel2 | Single tracepoint for all s/w counters in a bundle. |
+* 4 | r3p2-01rel3 - date | As above but with extensions for MP devices (Mali-450) | At least r4p0-00rel1
+*/
#if !defined(GATOR_MALI_INTERFACE_STYLE)
-#define GATOR_MALI_INTERFACE_STYLE (3)
+#define GATOR_MALI_INTERFACE_STYLE (4)
+#endif
+
+#if GATOR_MALI_INTERFACE_STYLE == 1
+#error GATOR_MALI_INTERFACE_STYLE 1 is obsolete
+#elif GATOR_MALI_INTERFACE_STYLE == 2
+#error GATOR_MALI_INTERFACE_STYLE 2 is obsolete
+#elif GATOR_MALI_INTERFACE_STYLE >= 3
+// Valid GATOR_MALI_INTERFACE_STYLE
+#else
+#error Unknown GATOR_MALI_INTERFACE_STYLE option.
#endif
#if GATOR_MALI_INTERFACE_STYLE < 4
@@ -44,6 +54,8 @@
#error MALI_SUPPORT set to an invalid device code: expecting MALI_4xx
#endif
+static const char mali_name[] = "Mali-4xx";
+
/* gatorfs variables for counter enable state,
* the event the counter should count and the
* 'key' (a unique id set by gatord and returned
@@ -63,6 +75,7 @@ static u32 *counter_address[NUMBER_OF_EVENTS];
*/
static unsigned long counter_dump[NUMBER_OF_EVENTS * 2];
static unsigned long counter_prev[NUMBER_OF_EVENTS];
+static bool prev_set[NUMBER_OF_EVENTS];
/* Note whether tracepoints have been registered */
static int trace_registered;
@@ -76,18 +89,11 @@ static unsigned int n_vp_cores = MAX_NUM_VP_CORES;
static unsigned int n_l2_cores = MAX_NUM_L2_CACHE_CORES;
static unsigned int n_fp_cores = MAX_NUM_FP_CORES;
-/**
- * Calculate the difference and handle the overflow.
- */
-static u32 get_difference(u32 start, u32 end)
-{
- if (start - end >= 0) {
- return start - end;
- }
-
- // Mali counters are unsigned 32 bit values that wrap.
- return (4294967295u - end) + start;
-}
+extern mali_counter mali_activity[2];
+static const char* const mali_activity_names[] = {
+ "fragment",
+ "vertex",
+};
/**
* Returns non-zero if the given counter ID is an activity counter.
@@ -112,40 +118,6 @@ static inline int is_hw_counter(unsigned int event_id)
typedef void _mali_profiling_get_mali_version_type(struct _mali_profiling_mali_version *values);
typedef u32 _mali_profiling_get_l2_counters_type(_mali_profiling_l2_counter_values *values);
-#if GATOR_MALI_INTERFACE_STYLE == 2
-/**
- * Returns non-zero if the given counter ID is a software counter.
- */
-static inline int is_sw_counter(unsigned int event_id)
-{
- return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER);
-}
-#endif
-
-#if GATOR_MALI_INTERFACE_STYLE == 2
-/*
- * The Mali DDK uses s64 types to contain software counter values, but gator
- * can only use a maximum of 32 bits. This function scales a software counter
- * to an appropriate range.
- */
-static u32 scale_sw_counter_value(unsigned int event_id, signed long long value)
-{
- u32 scaled_value;
-
- switch (event_id) {
- case COUNTER_GLES_UPLOAD_TEXTURE_TIME:
- case COUNTER_GLES_UPLOAD_VBO_TIME:
- scaled_value = (u32)div_s64(value, 1000000);
- break;
- default:
- scaled_value = (u32)value;
- break;
- }
-
- return scaled_value;
-}
-#endif
-
/* Probe for continuously sampled counter */
#if 0 //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING
GATOR_DEFINE_PROBE(mali_sample_address, TP_PROTO(unsigned int event_id, u32 *addr))
@@ -172,16 +144,6 @@ GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int
}
}
-#if GATOR_MALI_INTERFACE_STYLE == 2
-GATOR_DEFINE_PROBE(mali_sw_counter, TP_PROTO(unsigned int event_id, signed long long value))
-{
- if (is_sw_counter(event_id)) {
- counter_data[event_id] = scale_sw_counter_value(event_id, value);
- }
-}
-#endif /* GATOR_MALI_INTERFACE_STYLE == 2 */
-
-#if GATOR_MALI_INTERFACE_STYLE >= 3
GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surface_id, unsigned int *counters))
{
u32 i;
@@ -193,7 +155,6 @@ GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surfac
}
}
}
-#endif /* GATOR_MALI_INTERFACE_STYLE >= 3 */
/**
* Create a single filesystem entry for a specified event.
@@ -254,6 +215,7 @@ static void initialise_version_info(void)
symbol_put(_mali_profiling_get_mali_version);
} else {
printk("gator: mali online _mali_profiling_get_mali_version symbol not found\n");
+ printk("gator: check your Mali DDK version versus the GATOR_MALI_INTERFACE_STYLE setting\n");
}
}
#endif
@@ -261,7 +223,6 @@ static void initialise_version_info(void)
static int create_files(struct super_block *sb, struct dentry *root)
{
int event;
- const char *mali_name = gator_mali_get_mali_name();
char buf[40];
int core_id;
@@ -278,6 +239,14 @@ static int create_files(struct super_block *sb, struct dentry *root)
initialise_version_info();
#endif
+ mali_activity[0].cores = n_fp_cores;
+ mali_activity[1].cores = n_vp_cores;
+ for (event = 0; event < ARRAY_SIZE(mali_activity); event++) {
+ if (gator_mali_create_file_system(mali_name, mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) {
+ return -1;
+ }
+ }
+
/* Vertex processor counters */
for (core_id = 0; core_id < n_vp_cores; core_id++) {
int activity_counter_id = ACTIVITY_VP_0;
@@ -413,7 +382,6 @@ static void init_counters(unsigned int from_counter, unsigned int to_counter)
static void mali_counter_initialize(void)
{
int i;
- int core_id;
mali_profiling_control_type *mali_control;
@@ -463,15 +431,10 @@ static void mali_counter_initialize(void)
n_l2_cores = 0;
}
- for (core_id = 0; core_id < n_l2_cores; core_id++) {
- int counter_id = COUNTER_L2_0_C0 + (2 * core_id);
- counter_prev[counter_id] = 0;
- counter_prev[counter_id + 1] = 0;
- }
-
/* Clear counters in the start */
for (i = 0; i < NUMBER_OF_EVENTS; i++) {
counter_data[i] = 0;
+ prev_set[i] = false;
}
}
@@ -528,23 +491,11 @@ static int start(void)
return -1;
}
-#if GATOR_MALI_INTERFACE_STYLE == 1
- /* None. */
-#elif GATOR_MALI_INTERFACE_STYLE == 2
- /* For patched Mali driver. */
- if (GATOR_REGISTER_TRACE(mali_sw_counter)) {
- printk("gator: mali_sw_counter tracepoint failed to activate\n");
- return -1;
- }
-#elif GATOR_MALI_INTERFACE_STYLE >= 3
/* For Mali drivers with built-in support. */
if (GATOR_REGISTER_TRACE(mali_sw_counters)) {
printk("gator: mali_sw_counters tracepoint failed to activate\n");
return -1;
}
-#else
-#error Unknown GATOR_MALI_INTERFACE_STYLE option.
-#endif
trace_registered = 1;
@@ -561,17 +512,8 @@ static void stop(void)
if (trace_registered) {
GATOR_UNREGISTER_TRACE(mali_hw_counter);
-#if GATOR_MALI_INTERFACE_STYLE == 1
- /* None. */
-#elif GATOR_MALI_INTERFACE_STYLE == 2
- /* For patched Mali driver. */
- GATOR_UNREGISTER_TRACE(mali_sw_counter);
-#elif GATOR_MALI_INTERFACE_STYLE >= 3
/* For Mali drivers with built-in support. */
GATOR_UNREGISTER_TRACE(mali_sw_counters);
-#else
-#error Unknown GATOR_MALI_INTERFACE_STYLE option.
-#endif
pr_debug("gator: mali timeline tracepoint deactivated\n");
@@ -636,21 +578,23 @@ static int read(int **buffer)
per_core = &cache_values.cores[cache_id];
- if (counter_enabled[counter_id_0]) {
+ if (counter_enabled[counter_id_0] && prev_set[counter_id_0]) {
// Calculate and save src0's counter val0
counter_dump[len++] = counter_key[counter_id_0];
- counter_dump[len++] = get_difference(per_core->value0, counter_prev[counter_id_0]);
+ counter_dump[len++] = per_core->value0 - counter_prev[counter_id_0];
}
- if (counter_enabled[counter_id_1]) {
+ if (counter_enabled[counter_id_1] && prev_set[counter_id_1]) {
// Calculate and save src1's counter val1
counter_dump[len++] = counter_key[counter_id_1];
- counter_dump[len++] = get_difference(per_core->value1, counter_prev[counter_id_1]);
+ counter_dump[len++] = per_core->value1 - counter_prev[counter_id_1];
}
// Save the previous values for the counters.
counter_prev[counter_id_0] = per_core->value0;
+ prev_set[counter_id_0] = true;
counter_prev[counter_id_1] = per_core->value1;
+ prev_set[counter_id_1] = true;
}
}
@@ -709,6 +653,8 @@ int gator_events_mali_init(void)
pr_debug("gator: mali init\n");
+ gator_mali_initialise_counters(mali_activity, ARRAY_SIZE(mali_activity));
+
for (cnt = 0; cnt < NUMBER_OF_EVENTS; cnt++) {
counter_enabled[cnt] = 0;
counter_event[cnt] = 0;
diff --git a/driver/gator_events_mali_common.c b/driver/gator_events_mali_common.c
index dc58dcf..4f2cce4 100644
--- a/driver/gator_events_mali_common.c
+++ b/driver/gator_events_mali_common.c
@@ -8,26 +8,6 @@
*/
#include "gator_events_mali_common.h"
-static u32 gator_mali_get_id(void)
-{
- return MALI_SUPPORT;
-}
-
-extern const char *gator_mali_get_mali_name(void)
-{
- u32 id = gator_mali_get_id();
-
- switch (id) {
- case MALI_T6xx:
- return "Mali-T6xx";
- case MALI_4xx:
- return "Mali-4xx";
- default:
- pr_debug("gator: Mali-T6xx: unknown Mali ID (%d)\n", id);
- return "Mali-Unknown";
- }
-}
-
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;
@@ -42,24 +22,31 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even
dir = gatorfs_mkdir(sb, root, buf);
if (dir == NULL) {
- pr_debug("gator: Mali-T6xx: error creating file system for: %s (%s)", event_name, buf);
+ pr_debug("gator: %s: error creating file system for: %s (%s)", mali_name, event_name, buf);
return -1;
}
err = gatorfs_create_ulong(sb, dir, "enabled", &counter->enabled);
if (err != 0) {
- pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ulong for: %s (%s)", event_name, buf);
+ pr_debug("gator: %s: error calling gatorfs_create_ulong for: %s (%s)", mali_name, event_name, buf);
return -1;
}
err = gatorfs_create_ro_ulong(sb, dir, "key", &counter->key);
if (err != 0) {
- pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf);
+ pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf);
return -1;
}
+ if (counter->cores != -1) {
+ err = gatorfs_create_ro_ulong(sb, dir, "cores", &counter->cores);
+ if (err != 0) {
+ pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, 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);
+ pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf);
return -1;
}
}
@@ -77,5 +64,6 @@ extern void gator_mali_initialise_counters(mali_counter counters[], unsigned int
counter->key = gator_events_get_key();
counter->enabled = 0;
+ counter->cores = -1;
}
}
diff --git a/driver/gator_events_mali_common.h b/driver/gator_events_mali_common.h
index 41c2a3c..91d871b 100644
--- a/driver/gator_events_mali_common.h
+++ b/driver/gator_events_mali_common.h
@@ -18,10 +18,6 @@
#include <linux/slab.h>
#include <asm/io.h>
-/* Device codes for each known GPU */
-#define MALI_4xx (0x0b07)
-#define MALI_T6xx (0x0056)
-
/* Ensure that MALI_SUPPORT has been defined to something. */
#ifndef MALI_SUPPORT
#error MALI_SUPPORT not defined!
@@ -35,8 +31,12 @@
* Runtime state information for a counter.
*/
typedef struct {
- unsigned long key; /* 'key' (a unique id set by gatord and returned by gator.ko) */
- unsigned long enabled; /* counter enable state */
+ // 'key' (a unique id set by gatord and returned by gator.ko)
+ unsigned long key;
+ // counter enable state
+ unsigned long enabled;
+ // for activity counters, the number of cores, otherwise -1
+ unsigned long cores;
} mali_counter;
/*
@@ -54,17 +54,9 @@ extern void _mali_profiling_control(unsigned int, unsigned int);
extern void _mali_profiling_get_counters(unsigned int *, unsigned int *, unsigned int *, unsigned int *);
/**
- * Returns a name which identifies the GPU type (eg Mali-4xx, Mali-T6xx).
- *
- * @return The name as a constant string.
- */
-extern const char *gator_mali_get_mali_name(void);
-
-/**
* Creates a filesystem entry under /dev/gator relating to the specified event name and key, and
* associate the key/enable values with this entry point.
*
- * @param mali_name A name related to the type of GPU, obtained from a call to gator_mali_get_mali_name()
* @param event_name The name of the event.
* @param sb Linux super block
* @param root Directory under which the entry will be created.
diff --git a/driver/gator_events_mali_t6xx.c b/driver/gator_events_mali_t6xx.c
index 76f14ee..e56ba84 100644
--- a/driver/gator_events_mali_t6xx.c
+++ b/driver/gator_events_mali_t6xx.c
@@ -32,6 +32,8 @@
#error MALI_SUPPORT set to an invalid device code: expecting MALI_T6xx
#endif
+static const char mali_name[] = "Mali-T6xx";
+
/* Counters for Mali-T6xx:
*
* - Timeline events
@@ -292,7 +294,6 @@ static int create_files(struct super_block *sb, struct dentry *root)
* Create the filesystem for all events
*/
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++) {
@@ -317,7 +318,7 @@ static int create_files(struct super_block *sb, struct dentry *root)
}
mali_control = symbol_get(_mali_profiling_control);
- if (mali_control) {
+ if (mali_control) {
if (gator_mali_create_file_system(mali_name, "Filmstrip_cnt0", sb, root, &counters[FILMSTRIP], &filmstrip_event) != 0) {
return -1;
}
diff --git a/driver/gator_events_mali_t6xx_hw.c b/driver/gator_events_mali_t6xx_hw.c
index dfbc91f..3a072bb 100644
--- a/driver/gator_events_mali_t6xx_hw.c
+++ b/driver/gator_events_mali_t6xx_hw.c
@@ -16,7 +16,10 @@
#include <asm/io.h>
/* Mali T6xx DDK includes */
-#ifdef MALI_DIR_MIDGARD
+#if defined(MALI_SIMPLE_API)
+/* Header with wrapper functions to kbase structures and functions */
+#include "mali/mali_dd_gator_api.h"
+#elif defined(MALI_DIR_MIDGARD)
/* New DDK Directory structure with kernel/drivers/gpu/arm/midgard*/
#include "mali_linux_trace.h"
#include "mali_kbase.h"
@@ -28,37 +31,49 @@
#include "kbase/src/linux/mali_kbase_mem_linux.h"
#endif
-#include "gator_events_mali_common.h"
-
/* If API version is not specified then assume API version 1. */
#ifndef MALI_DDK_GATOR_API_VERSION
#define MALI_DDK_GATOR_API_VERSION 1
#endif
-#if (MALI_DDK_GATOR_API_VERSION != 1) && (MALI_DDK_GATOR_API_VERSION != 2)
-#error MALI_DDK_GATOR_API_VERSION is invalid (must be 1 for r1/r2 DDK, or 2 for r3 DDK).
+#if (MALI_DDK_GATOR_API_VERSION != 1) && (MALI_DDK_GATOR_API_VERSION != 2) && (MALI_DDK_GATOR_API_VERSION != 3)
+#error MALI_DDK_GATOR_API_VERSION is invalid (must be 1 for r1/r2 DDK, or 2 for r3 DDK, or 3 for r? DDK).
#endif
+#include "gator_events_mali_common.h"
+
/*
* Mali-T6xx
*/
+#if MALI_DDK_GATOR_API_VERSION == 3
+typedef uint32_t kbase_dd_instr_hwcnt_dump_irq_type(struct mali_dd_hwcnt_handles *);
+typedef uint32_t kbase_dd_instr_hwcnt_dump_complete_type(struct mali_dd_hwcnt_handles *, uint32_t *);
+typedef struct mali_dd_hwcnt_handles* mali_dd_hwcnt_init_type(struct mali_dd_hwcnt_info *);
+typedef void mali_dd_hwcnt_clear_type(struct mali_dd_hwcnt_info *, struct mali_dd_hwcnt_handles *);
+
+static kbase_dd_instr_hwcnt_dump_irq_type *kbase_dd_instr_hwcnt_dump_irq_symbol;
+static kbase_dd_instr_hwcnt_dump_complete_type *kbase_dd_instr_hwcnt_dump_complete_symbol;
+static mali_dd_hwcnt_init_type *mali_dd_hwcnt_init_symbol;
+static mali_dd_hwcnt_clear_type *mali_dd_hwcnt_clear_symbol;
+
+#else
typedef struct kbase_device *kbase_find_device_type(int);
-typedef kbase_context *kbase_create_context_type(kbase_device *);
-typedef void kbase_destroy_context_type(kbase_context *);
+typedef struct kbase_context *kbase_create_context_type(struct kbase_device *);
+typedef void kbase_destroy_context_type(struct kbase_context *);
#if MALI_DDK_GATOR_API_VERSION == 1
-typedef void *kbase_va_alloc_type(kbase_context *, u32);
-typedef void kbase_va_free_type(kbase_context *, void *);
+typedef void *kbase_va_alloc_type(struct kbase_context *, u32);
+typedef void kbase_va_free_type(struct kbase_context *, void *);
#elif MALI_DDK_GATOR_API_VERSION == 2
-typedef void *kbase_va_alloc_type(kbase_context *, u32, kbase_hwc_dma_mapping * handle);
-typedef void kbase_va_free_type(kbase_context *, kbase_hwc_dma_mapping * handle);
+typedef void *kbase_va_alloc_type(struct kbase_context *, u32, kbase_hwc_dma_mapping * handle);
+typedef void kbase_va_free_type(struct kbase_context *, kbase_hwc_dma_mapping * handle);
#endif
-typedef mali_error kbase_instr_hwcnt_enable_type(kbase_context *, kbase_uk_hwcnt_setup *);
-typedef mali_error kbase_instr_hwcnt_disable_type(kbase_context *);
-typedef mali_error kbase_instr_hwcnt_clear_type(kbase_context *);
-typedef mali_error kbase_instr_hwcnt_dump_irq_type(kbase_context *);
-typedef mali_bool kbase_instr_hwcnt_dump_complete_type(kbase_context *, mali_bool *);
+typedef mali_error kbase_instr_hwcnt_enable_type(struct kbase_context *, struct kbase_uk_hwcnt_setup *);
+typedef mali_error kbase_instr_hwcnt_disable_type(struct kbase_context *);
+typedef mali_error kbase_instr_hwcnt_clear_type(struct kbase_context *);
+typedef mali_error kbase_instr_hwcnt_dump_irq_type(struct kbase_context *);
+typedef mali_bool kbase_instr_hwcnt_dump_complete_type(struct kbase_context *, mali_bool *);
static kbase_find_device_type *kbase_find_device_symbol;
static kbase_create_context_type *kbase_create_context_symbol;
@@ -70,6 +85,7 @@ static kbase_instr_hwcnt_dump_complete_type *kbase_instr_hwcnt_dump_complete_sym
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;
+#endif
static long shader_present_low = 0;
@@ -99,6 +115,8 @@ enum {
MMU_BLOCK
};
+static const char mali_name[] = "Mali-T6xx";
+
/* Counters for Mali-T6xx:
*
* - HW counters, 4 blocks
@@ -381,6 +399,14 @@ static const char *const hardware_counter_names[] = {
#define GET_HW_BLOCK(c) (((c) >> 6) & 0x3)
#define GET_COUNTER_OFFSET(c) ((c) & 0x3f)
+#if MALI_DDK_GATOR_API_VERSION == 3
+/* Opaque handles for kbase_context and kbase_hwc_dma_mapping */
+static struct mali_dd_hwcnt_handles *handles;
+
+/* Information about hardware counters */
+static struct mali_dd_hwcnt_info *in_out_info;
+
+#else
/* Memory to dump hardware counters into */
static void *kernel_dump_buffer;
@@ -390,14 +416,9 @@ kbase_hwc_dma_mapping kernel_dump_buffer_handle;
#endif
/* kbase context and device */
-static kbase_context *kbcontext = NULL;
+static struct kbase_context *kbcontext = NULL;
static struct kbase_device *kbdevice = NULL;
-
-/*
- * The following function has no external prototype in older DDK revisions. When the DDK
- * is updated then this should be removed.
- */
-struct kbase_device *kbase_find_device(int minor);
+#endif
static volatile bool kbase_device_busy = false;
static unsigned int num_hardware_counters_enabled;
@@ -412,6 +433,13 @@ static mali_counter counters[NUMBER_OF_HARDWARE_COUNTERS];
*/
static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2];
+extern mali_counter mali_activity[3];
+static const char* const mali_activity_names[] = {
+ "fragment",
+ "vertex",
+ "opencl",
+};
+
#define SYMBOL_GET(FUNCTION, ERROR_COUNT) \
if(FUNCTION ## _symbol) \
{ \
@@ -431,8 +459,8 @@ static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2];
#define SYMBOL_CLEANUP(FUNCTION) \
if(FUNCTION ## _symbol) \
{ \
- symbol_put(FUNCTION); \
- FUNCTION ## _symbol = NULL; \
+ symbol_put(FUNCTION); \
+ FUNCTION ## _symbol = NULL; \
}
/**
@@ -442,6 +470,12 @@ static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2];
static int init_symbols(void)
{
int error_count = 0;
+#if MALI_DDK_GATOR_API_VERSION == 3
+ SYMBOL_GET(kbase_dd_instr_hwcnt_dump_irq, error_count);
+ SYMBOL_GET(kbase_dd_instr_hwcnt_dump_complete, error_count);
+ SYMBOL_GET(mali_dd_hwcnt_init, error_count);
+ SYMBOL_GET(mali_dd_hwcnt_clear, error_count);
+#else
SYMBOL_GET(kbase_find_device, error_count);
SYMBOL_GET(kbase_create_context, error_count);
SYMBOL_GET(kbase_va_alloc, error_count);
@@ -452,6 +486,7 @@ static int init_symbols(void)
SYMBOL_GET(kbase_instr_hwcnt_disable, error_count);
SYMBOL_GET(kbase_va_free, error_count);
SYMBOL_GET(kbase_destroy_context, error_count);
+#endif
return error_count;
}
@@ -461,6 +496,12 @@ static int init_symbols(void)
*/
static void clean_symbols(void)
{
+#if MALI_DDK_GATOR_API_VERSION == 3
+ SYMBOL_CLEANUP(kbase_dd_instr_hwcnt_dump_irq);
+ SYMBOL_CLEANUP(kbase_dd_instr_hwcnt_dump_complete);
+ SYMBOL_CLEANUP(mali_dd_hwcnt_init);
+ SYMBOL_CLEANUP(mali_dd_hwcnt_clear);
+#else
SYMBOL_CLEANUP(kbase_find_device);
SYMBOL_CLEANUP(kbase_create_context);
SYMBOL_CLEANUP(kbase_va_alloc);
@@ -471,6 +512,7 @@ static void clean_symbols(void)
SYMBOL_CLEANUP(kbase_instr_hwcnt_disable);
SYMBOL_CLEANUP(kbase_va_free);
SYMBOL_CLEANUP(kbase_destroy_context);
+#endif
}
/**
@@ -502,11 +544,13 @@ static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time
static int start(void)
{
- kbase_uk_hwcnt_setup setup;
+#if MALI_DDK_GATOR_API_VERSION < 3
+ struct kbase_uk_hwcnt_setup setup;
+ unsigned long long shadersPresent = 0;
+ u16 bitmask[] = { 0, 0, 0, 0 };
mali_error err;
+#endif
int cnt;
- u16 bitmask[] = { 0, 0, 0, 0 };
- unsigned long long shadersPresent = 0;
/* Setup HW counters */
num_hardware_counters_enabled = 0;
@@ -515,18 +559,52 @@ static int start(void)
pr_debug("Unexpected number of hardware counters defined: expecting 256, got %d\n", NUMBER_OF_HARDWARE_COUNTERS);
}
+#if MALI_DDK_GATOR_API_VERSION == 3
+ /* Declare and initialise mali_dd_hwcnt_info structure */
+ in_out_info = kmalloc(sizeof(struct mali_dd_hwcnt_info), GFP_KERNEL);
+ for (cnt = 0; cnt < 4; cnt++){
+ in_out_info->bitmask[cnt] = 0;
+ }
+#endif
/* Calculate enable bitmasks based on counters_enabled array */
for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) {
const mali_counter *counter = &counters[cnt];
if (counter->enabled) {
int block = GET_HW_BLOCK(cnt);
int enable_bit = GET_COUNTER_OFFSET(cnt) / 4;
+#if MALI_DDK_GATOR_API_VERSION == 3
+ in_out_info->bitmask[block] |= (1 << enable_bit);
+#else
bitmask[block] |= (1 << enable_bit);
+#endif
pr_debug("gator: Mali-T6xx: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt);
num_hardware_counters_enabled++;
}
}
+#if MALI_DDK_GATOR_API_VERSION == 3
+ /* Create a kbase context for HW counters */
+ if (num_hardware_counters_enabled > 0) {
+ if (init_symbols() > 0) {
+ clean_symbols();
+ /* No Mali driver code entrypoints found - not a fault. */
+ return 0;
+ }
+
+ handles = mali_dd_hwcnt_init_symbol(in_out_info);
+
+ if(handles == NULL) {
+ goto out;
+ }
+
+ /* See if we can get the number of shader cores */
+ shader_present_low = (unsigned long)in_out_info->shader_present_bitmap;
+
+ kbase_device_busy = false;
+ }
+
+ return 0;
+#else
/* Create a kbase context for HW counters */
if (num_hardware_counters_enabled > 0) {
if (init_symbols() > 0) {
@@ -606,6 +684,7 @@ free_buffer:
destroy_context:
kbase_destroy_context_symbol(kbcontext);
+#endif
out:
clean_symbols();
@@ -615,7 +694,11 @@ out:
static void stop(void)
{
unsigned int cnt;
- kbase_context *temp_kbcontext;
+#if MALI_DDK_GATOR_API_VERSION == 3
+ struct mali_dd_hwcnt_handles *temp_hand;
+#else
+ struct kbase_context *temp_kbcontext;
+#endif
pr_debug("gator: Mali-T6xx: stop\n");
@@ -625,6 +708,20 @@ static void stop(void)
}
/* Destroy the context for HW counters */
+#if MALI_DDK_GATOR_API_VERSION == 3
+ if (num_hardware_counters_enabled > 0 && handles != NULL) {
+ /*
+ * Set the global variable to NULL before destroying it, because
+ * other function will check this before using it.
+ */
+ temp_hand = handles;
+ handles = NULL;
+
+ mali_dd_hwcnt_clear_symbol(in_out_info, temp_hand);
+
+ kfree(in_out_info);
+
+#else
if (num_hardware_counters_enabled > 0 && kbcontext != NULL) {
/*
* Set the global variable to NULL before destroying it, because
@@ -642,6 +739,7 @@ static void stop(void)
#endif
kbase_destroy_context_symbol(temp_kbcontext);
+#endif
pr_debug("gator: Mali-T6xx: hardware counters stopped\n");
@@ -654,7 +752,7 @@ static int read(int **buffer)
int cnt;
int len = 0;
u32 value = 0;
- mali_bool success;
+ uint32_t success;
struct timespec current_time;
static u32 prev_time_s = 0;
@@ -686,12 +784,21 @@ static int read(int **buffer)
0x500 /* VITHAR_MEMORY_SYSTEM, Block 3 */
};
+#if MALI_DDK_GATOR_API_VERSION == 3
+ if (!handles) {
+ return -1;
+ }
+
+ /* Mali symbols can be called safely since a kbcontext is valid */
+ if (kbase_dd_instr_hwcnt_dump_complete_symbol(handles, &success) == MALI_TRUE) {
+#else
if (!kbcontext) {
return -1;
}
/* Mali symbols can be called safely since a kbcontext is valid */
if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE) {
+#endif
kbase_device_busy = false;
if (success == MALI_TRUE) {
@@ -702,7 +809,11 @@ static int read(int **buffer)
const int block = GET_HW_BLOCK(cnt);
const int counter_offset = GET_COUNTER_OFFSET(cnt);
+#if MALI_DDK_GATOR_API_VERSION == 3
+ const char* block_base_address = (char*)in_out_info->kernel_dump_buffer + vithar_blocks[block];
+#else
const char* block_base_address = (char*)kernel_dump_buffer + vithar_blocks[block];
+#endif
/* If counter belongs to shader block need to take into account all cores */
if (block == SHADER_BLOCK) {
@@ -741,7 +852,11 @@ static int read(int **buffer)
if (!kbase_device_busy) {
kbase_device_busy = true;
+#if MALI_DDK_GATOR_API_VERSION == 3
+ kbase_dd_instr_hwcnt_dump_irq_symbol(handles);
+#else
kbase_instr_hwcnt_dump_irq_symbol(kbcontext);
+#endif
}
}
@@ -760,7 +875,12 @@ static int create_files(struct super_block *sb, struct dentry *root)
* Create the filesystem for all events
*/
int counter_index = 0;
- const char *mali_name = gator_mali_get_mali_name();
+
+ for (event = 0; event < ARRAY_SIZE(mali_activity); event++) {
+ if (gator_mali_create_file_system(mali_name, mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) {
+ return -1;
+ }
+ }
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], NULL) != 0)
@@ -786,6 +906,7 @@ int gator_events_mali_t6xx_hw_init(void)
test_all_is_read_scheduled();
#endif
+ gator_mali_initialise_counters(mali_activity, ARRAY_SIZE(mali_activity));
gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS);
return gator_events_install(&gator_events_mali_t6xx_interface);
diff --git a/driver/gator_events_mmapped.c b/driver/gator_events_mmapped.c
index 3b248ec..5bc01c4 100644
--- a/driver/gator_events_mmapped.c
+++ b/driver/gator_events_mmapped.c
@@ -8,21 +8,25 @@
* published by the Free Software Foundation.
*
* Similar entries to those below must be present in the events.xml file.
- * To add them to the events.xml, create an events-mmap.xml with the
+ * To add them to the events.xml, create an events-mmap.xml with the
* following contents and rebuild gatord:
*
- * <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 name="mmapped">
+ * <event counter="mmapped_cnt0" title="Simulated1" name="Sine" display="maximum" class="absolute" description="Sort-of-sine"/>
+ * <event counter="mmapped_cnt1" title="Simulated2" name="Triangle" display="maximum" class="absolute" description="Triangular wave"/>
+ * <event counter="mmapped_cnt2" title="Simulated3" name="PWM" display="maximum" class="absolute" description="PWM Signal"/>
* </category>
*
- * When adding custom events, be sure do the following
+ * When adding custom events, be sure to 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
+ *
+ * Troubleshooting:
+ * - verify the new events are part of events.xml, which is created when building the daemon
+ * - verify the new events exist at /dev/gator/events/ once gatord is launched
+ * - verify the counter name in the XML matches the name at /dev/gator/events
*/
#include <linux/init.h>
@@ -37,7 +41,6 @@ static int mmapped_global_enabled;
static struct {
unsigned long enabled;
- unsigned long event;
unsigned long key;
} mmapped_counters[MMAPPED_COUNTERS_NUM];
@@ -47,7 +50,7 @@ static s64 prev_time;
/* 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)
+ struct dentry *root)
{
int i;
@@ -61,8 +64,6 @@ static int gator_events_mmapped_create_files(struct super_block *sb,
return -1;
gatorfs_create_ulong(sb, dir, "enabled",
&mmapped_counters[i].enabled);
- gatorfs_create_ulong(sb, dir, "event",
- &mmapped_counters[i].event);
gatorfs_create_ro_ulong(sb, dir, "key",
&mmapped_counters[i].key);
}
@@ -177,8 +178,7 @@ static int gator_events_mmapped_read(int **buffer)
if (mmapped_counters[i].enabled) {
mmapped_buffer[len++] = mmapped_counters[i].key;
mmapped_buffer[len++] =
- mmapped_simulate(mmapped_counters[i].event,
- delta_in_us);
+ mmapped_simulate(i, delta_in_us);
}
}
diff --git a/driver/gator_events_perf_pmu.c b/driver/gator_events_perf_pmu.c
index 8b2d67a..06bbad5 100644
--- a/driver/gator_events_perf_pmu.c
+++ b/driver/gator_events_perf_pmu.c
@@ -470,10 +470,10 @@ static void gator_events_perf_pmu_cci_init(const int type)
switch (probe_cci_revision()) {
case 0:
- cci_name = "cci-400";
+ cci_name = "CCI_400";
break;
case 1:
- cci_name = "cci-400-r1";
+ cci_name = "CCI_400-r1";
break;
default:
pr_debug("gator: unrecognized cci-400 revision\n");
@@ -549,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 || strcmp("CCI_400", pe->pmu->name) == 0) {
+ if (strcmp("CCI", pe->pmu->name) == 0 || strcmp("CCI_400", pe->pmu->name) == 0 || strcmp("CCI_400-r1", 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;
diff --git a/driver/gator_events_scorpion.c b/driver/gator_events_scorpion.c
index 8ca251a..2e5be8d 100644
--- a/driver/gator_events_scorpion.c
+++ b/driver/gator_events_scorpion.c
@@ -26,9 +26,9 @@ static int pmnc_counters;
// ccnt reg
#define CCNT_REG (1 << 31)
-#define CCNT 0
+#define CCNT 0
#define CNT0 1
-#define CNTMAX (4+1)
+#define CNTMAX (4+1)
static unsigned long pmnc_enabled[CNTMAX];
static unsigned long pmnc_event[CNTMAX];
diff --git a/driver/gator_events_threads.c b/driver/gator_events_threads.c
new file mode 100644
index 0000000..9de8586
--- /dev/null
+++ b/driver/gator_events_threads.c
@@ -0,0 +1,115 @@
+/*
+ * Sample activity provider
+ *
+ * Copyright (C) ARM Limited 2014. 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.
+ *
+ * See gator_events_mmapped.c for additional directions and
+ * troubleshooting.
+ *
+ * For this sample to work these entries must be present in the
+ * events.xml file. So create an events-threads.xml in the gator
+ * daemon source directory with the following contents and rebuild
+ * gatord:
+ *
+ * <category name="threads">
+ * <event counter="Linux_threads" title="Linux" name="Threads" class="activity" activity1="odd" activity_color1="0x000000ff" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" description="Linux syscall activity"/>
+ * </category>
+ */
+
+#include <trace/events/sched.h>
+
+#include "gator.h"
+
+static ulong threads_enabled;
+static ulong threads_key;
+static ulong threads_cores;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
+GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next))
+#else
+GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_struct *next))
+#endif
+{
+ int cpu = get_physical_cpu();
+ int pid = next->pid;
+ if (pid == 0) {
+ // idle
+ gator_marshal_activity_switch(cpu, threads_key, 0, 0);
+ } else if (pid & 1) {
+ // odd
+ gator_marshal_activity_switch(cpu, threads_key, 1, pid);
+ } else {
+ // even
+ //gator_marshal_activity_switch(cpu, threads_key, 2, current->pid);
+ // Multiple activities are not yet supported so emit idle
+ gator_marshal_activity_switch(cpu, threads_key, 0, 0);
+ }
+}
+
+// Adds Linux_threads directory and enabled, key, and cores files to /dev/gator/events
+static int gator_events_threads_create_files(struct super_block *sb, struct dentry *root)
+{
+ struct dentry *dir;
+
+ dir = gatorfs_mkdir(sb, root, "Linux_threads");
+ if (!dir) {
+ return -1;
+ }
+ gatorfs_create_ulong(sb, dir, "enabled", &threads_enabled);
+ gatorfs_create_ro_ulong(sb, dir, "key", &threads_key);
+ // Number of cores associated with this activity
+ gatorfs_create_ro_ulong(sb, dir, "cores", &threads_cores);
+
+ return 0;
+}
+
+static int gator_events_threads_start(void)
+{
+ int cpu;
+
+ if (threads_enabled) {
+ preempt_disable();
+ for (cpu = 0; cpu < nr_cpu_ids; ++cpu) {
+ gator_marshal_activity_switch(cpu, threads_key, 0, 0);
+ }
+ preempt_enable();
+
+ if (GATOR_REGISTER_TRACE(sched_switch)) {
+ goto fail_sched_switch;
+ }
+ }
+
+ return 0;
+
+fail_sched_switch:
+ return -1;
+}
+
+static void gator_events_threads_stop(void)
+{
+ if (threads_enabled) {
+ GATOR_UNREGISTER_TRACE(sched_switch);
+ }
+
+ threads_enabled = 0;
+}
+
+static struct gator_interface gator_events_threads_interface = {
+ .create_files = gator_events_threads_create_files,
+ .start = gator_events_threads_start,
+ .stop = gator_events_threads_stop,
+};
+
+// Must not be static. Ensure that this init function is added to GATOR_EVENTS_LIST in gator_main.c
+int __init gator_events_threads_init(void)
+{
+ threads_enabled = 0;
+ threads_key = gator_events_get_key();
+ threads_cores = nr_cpu_ids;
+
+ return gator_events_install(&gator_events_threads_interface);
+}
diff --git a/driver/gator_iks.c b/driver/gator_iks.c
index e90dfcc..9180b87 100644
--- a/driver/gator_iks.c
+++ b/driver/gator_iks.c
@@ -150,7 +150,7 @@ static void gator_send_iks_core_names(void)
preempt_disable();
for (cpu = 0; cpu < nr_cpu_ids; ++cpu) {
if (mpidr_cpus[cpu] != NULL) {
- gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid, mpidr_cpus[cpu]);
+ gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid);
}
}
preempt_enable();
diff --git a/driver/gator_main.c b/driver/gator_main.c
index e67f7c5..0d867f2 100644
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
@@ -8,7 +8,7 @@
*/
// This version must match the gator daemon version
-#define PROTOCOL_VERSION 18
+#define PROTOCOL_VERSION 19
static unsigned long gator_protocol_version = PROTOCOL_VERSION;
#include <linux/slab.h>
@@ -71,8 +71,8 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION;
#define BLOCK_COUNTER_BUFFER_SIZE (128*1024)
#define ANNOTATE_BUFFER_SIZE (128*1024) // annotate counters have the core as part of the data and the core value in the frame header may be discarded
#define SCHED_TRACE_BUFFER_SIZE (128*1024)
-#define GPU_TRACE_BUFFER_SIZE (64*1024) // gpu trace counters have the core as part of the data and the core value in the frame header may be discarded
#define IDLE_BUFFER_SIZE (32*1024) // idle counters have the core as part of the data and the core value in the frame header may be discarded
+#define ACTIVITY_BUFFER_SIZE (128*1024)
#define NO_COOKIE 0U
#define UNRESOLVED_COOKIE ~0U
@@ -84,8 +84,8 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION;
#define FRAME_BLOCK_COUNTER 5
#define FRAME_ANNOTATE 6
#define FRAME_SCHED_TRACE 7
-#define FRAME_GPU_TRACE 8
#define FRAME_IDLE 9
+#define FRAME_ACTIVITY 13
#define MESSAGE_END_BACKTRACE 1
@@ -94,14 +94,9 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION;
#define MESSAGE_THREAD_NAME 2
#define MESSAGE_LINK 4
-// GPU Trace Frame Messages
-#define MESSAGE_GPU_START 1
-#define MESSAGE_GPU_STOP 2
-
// Scheduler Trace Frame Messages
#define MESSAGE_SCHED_SWITCH 1
#define MESSAGE_SCHED_EXIT 2
-#define MESSAGE_SCHED_START 3
// Idle Frame Messages
#define MESSAGE_IDLE_ENTER 1
@@ -111,6 +106,10 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION;
#define MESSAGE_SUMMARY 1
#define MESSAGE_CORE_NAME 3
+// Activity Frame Messages
+#define MESSAGE_SWITCH 2
+#define MESSAGE_EXIT 3
+
#define MAXSIZE_PACK32 5
#define MAXSIZE_PACK64 10
@@ -132,8 +131,8 @@ enum {
BLOCK_COUNTER_BUF,
ANNOTATE_BUF,
SCHED_TRACE_BUF,
- GPU_TRACE_BUF,
IDLE_BUF,
+ ACTIVITY_BUF,
NUM_GATOR_BUFS
};
@@ -175,6 +174,7 @@ static DEFINE_PER_CPU(u64, last_timestamp);
static bool printed_monotonic_warning;
+static u32 gator_cpuids[NR_CPUS];
static bool sent_core_name[NR_CPUS];
static DEFINE_PER_CPU(bool, in_scheduler_context);
@@ -226,6 +226,7 @@ static DEFINE_PER_CPU(u64, gator_buffer_commit_time);
GATOR_EVENT(gator_events_perf_pmu_init) \
GATOR_EVENT(gator_events_sched_init) \
GATOR_EVENT(gator_events_scorpion_init) \
+ GATOR_EVENT(gator_events_threads_init) \
#define GATOR_EVENT(EVENT_INIT) __weak int EVENT_INIT(void);
GATOR_EVENTS_LIST
@@ -570,25 +571,37 @@ static void gator_timer_stop(void)
}
}
-#if defined(__arm__) || defined(__aarch64__)
-static void gator_send_core_name(int cpu, const u32 cpuid, const struct gator_cpu *const gator_cpu)
+static void gator_send_core_name(const int cpu, const u32 cpuid)
{
- const char *core_name = NULL;
- char core_name_buf[32];
+#if defined(__arm__) || defined(__aarch64__)
+ if (!sent_core_name[cpu] || (cpuid != gator_cpuids[cpu])) {
+ const struct gator_cpu *const gator_cpu = gator_find_cpu_by_cpuid(cpuid);
+ const char *core_name = NULL;
+ char core_name_buf[32];
- if (!sent_core_name[cpu]) {
+ // Save off this cpuid
+ gator_cpuids[cpu] = cpuid;
if (gator_cpu != NULL) {
core_name = gator_cpu->core_name;
} else {
- snprintf(core_name_buf, sizeof(core_name_buf), "Unknown (0x%.3x)", cpuid);
+ if (cpuid == -1) {
+ snprintf(core_name_buf, sizeof(core_name_buf), "Unknown");
+ } else {
+ snprintf(core_name_buf, sizeof(core_name_buf), "Unknown (0x%.3x)", cpuid);
+ }
core_name = core_name_buf;
}
marshal_core_name(cpu, cpuid, core_name);
sent_core_name[cpu] = true;
}
-}
#endif
+}
+
+static void gator_read_cpuid(void * arg)
+{
+ gator_cpuids[get_physical_cpu()] = gator_cpuid();
+}
// This function runs in interrupt context and on the appropriate core
static void gator_timer_online(void *migrate)
@@ -598,6 +611,9 @@ static void gator_timer_online(void *migrate)
int *buffer;
u64 time;
+ // Send what is currently running on this core
+ marshal_sched_trace_switch(current->pid, 0);
+
gator_trace_power_online();
// online any events and output counters
@@ -617,12 +633,7 @@ static void gator_timer_online(void *migrate)
gator_hrtimer_online();
}
-#if defined(__arm__) || defined(__aarch64__)
- if (!sent_core_name[cpu]) {
- const u32 cpuid = gator_cpuid();
- gator_send_core_name(cpu, cpuid, gator_find_cpu_by_cpuid(cpuid));
- }
-#endif
+ gator_send_core_name(cpu, gator_cpuid());
}
// This function runs in interrupt context and may be running on a core other than core 'cpu'
@@ -658,6 +669,13 @@ static int gator_timer_start(unsigned long sample_rate)
if (gator_hrtimer_init(sample_rate, gator_timer_interrupt) == -1)
return -1;
+ // Send off the previously saved cpuids
+ for_each_present_cpu(cpu) {
+ preempt_disable();
+ gator_send_core_name(cpu, gator_cpuids[cpu]);
+ preempt_enable();
+ }
+
gator_send_iks_core_names();
for_each_online_cpu(cpu) {
gator_timer_online_dispatch(lcpu_to_pcpu(cpu), false);
@@ -1009,12 +1027,12 @@ static int gator_op_setup(void)
gator_buffer_size[SCHED_TRACE_BUF] = SCHED_TRACE_BUFFER_SIZE;
gator_buffer_mask[SCHED_TRACE_BUF] = SCHED_TRACE_BUFFER_SIZE - 1;
- gator_buffer_size[GPU_TRACE_BUF] = GPU_TRACE_BUFFER_SIZE;
- gator_buffer_mask[GPU_TRACE_BUF] = GPU_TRACE_BUFFER_SIZE - 1;
-
gator_buffer_size[IDLE_BUF] = IDLE_BUFFER_SIZE;
gator_buffer_mask[IDLE_BUF] = IDLE_BUFFER_SIZE - 1;
+ gator_buffer_size[ACTIVITY_BUF] = ACTIVITY_BUFFER_SIZE;
+ gator_buffer_mask[ACTIVITY_BUF] = ACTIVITY_BUFFER_SIZE - 1;
+
// Initialize percpu per buffer variables
for (i = 0; i < NUM_GATOR_BUFS; i++) {
// Verify buffers are a power of 2
@@ -1349,8 +1367,62 @@ static void gator_op_create_files(struct super_block *sb, struct dentry *root)
/******************************************************************************
* Module
******************************************************************************/
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+
+#define GATOR_TRACEPOINTS \
+ GATOR_HANDLE_TRACEPOINT(block_rq_complete); \
+ GATOR_HANDLE_TRACEPOINT(cpu_frequency); \
+ GATOR_HANDLE_TRACEPOINT(cpu_idle); \
+ GATOR_HANDLE_TRACEPOINT(cpu_migrate_begin); \
+ GATOR_HANDLE_TRACEPOINT(cpu_migrate_current); \
+ GATOR_HANDLE_TRACEPOINT(cpu_migrate_finish); \
+ GATOR_HANDLE_TRACEPOINT(irq_handler_exit); \
+ GATOR_HANDLE_TRACEPOINT(mali_hw_counter); \
+ GATOR_HANDLE_TRACEPOINT(mali_job_slots_event); \
+ GATOR_HANDLE_TRACEPOINT(mali_mmu_as_in_use); \
+ GATOR_HANDLE_TRACEPOINT(mali_mmu_as_released); \
+ GATOR_HANDLE_TRACEPOINT(mali_page_fault_insert_pages); \
+ GATOR_HANDLE_TRACEPOINT(mali_pm_status); \
+ GATOR_HANDLE_TRACEPOINT(mali_sw_counter); \
+ GATOR_HANDLE_TRACEPOINT(mali_sw_counters); \
+ GATOR_HANDLE_TRACEPOINT(mali_timeline_event); \
+ GATOR_HANDLE_TRACEPOINT(mali_total_alloc_pages_change); \
+ GATOR_HANDLE_TRACEPOINT(mm_page_alloc); \
+ GATOR_HANDLE_TRACEPOINT(mm_page_free); \
+ GATOR_HANDLE_TRACEPOINT(mm_page_free_batched); \
+ GATOR_HANDLE_TRACEPOINT(sched_process_exec); \
+ GATOR_HANDLE_TRACEPOINT(sched_process_fork); \
+ GATOR_HANDLE_TRACEPOINT(sched_process_free); \
+ GATOR_HANDLE_TRACEPOINT(sched_switch); \
+ GATOR_HANDLE_TRACEPOINT(softirq_exit); \
+
+#define GATOR_HANDLE_TRACEPOINT(probe_name) \
+ struct tracepoint *gator_tracepoint_##probe_name
+GATOR_TRACEPOINTS;
+#undef GATOR_HANDLE_TRACEPOINT
+
+static void gator_fct(struct tracepoint *tp, void *priv)
+{
+#define GATOR_HANDLE_TRACEPOINT(probe_name) \
+ if (strcmp(tp->name, #probe_name) == 0) { \
+ gator_tracepoint_##probe_name = tp; \
+ return; \
+ }
+GATOR_TRACEPOINTS;
+#undef GATOR_HANDLE_TRACEPOINT
+}
+
+#else
+
+#define for_each_kernel_tracepoint(fct, priv)
+
+#endif
+
static int __init gator_module_init(void)
{
+ for_each_kernel_tracepoint(gator_fct, NULL);
+
if (gatorfs_register()) {
return -1;
}
@@ -1362,6 +1434,10 @@ static int __init gator_module_init(void)
setup_timer(&gator_buffer_wake_up_timer, gator_buffer_wake_up, 0);
+ // Initialize the list of cpuids
+ memset(gator_cpuids, -1, sizeof(gator_cpuids));
+ on_each_cpu(gator_read_cpuid, NULL, 1);
+
return 0;
}
diff --git a/driver/gator_marshaling.c b/driver/gator_marshaling.c
index fd413ad..97b4ae6 100644
--- a/driver/gator_marshaling.c
+++ b/driver/gator_marshaling.c
@@ -231,75 +231,28 @@ static void marshal_event_single(int core, int key, int value)
// Check and commit; commit is set to occur once buffer is 3/4 full
buffer_check(cpu, COUNTER_BUF, time);
}
-#endif
-static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid)
+static void marshal_event_single64(int core, int key, long long value)
{
- unsigned long cpu = get_physical_cpu(), flags;
- u64 time;
-
- if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
- return;
-
- local_irq_save(flags);
- time = gator_get_time();
- if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
- gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_START);
- gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, time);
- gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
- gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
- gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, tgid);
- gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, pid);
- }
- local_irq_restore(flags);
- // Check and commit; commit is set to occur once buffer is 3/4 full
- buffer_check(cpu, GPU_TRACE_BUF, time);
-}
-
-static void marshal_sched_gpu_stop(int unit, int core)
-{
- unsigned long cpu = get_physical_cpu(), flags;
- u64 time;
-
- if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
- return;
-
- local_irq_save(flags);
- time = gator_get_time();
- if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
- gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_STOP);
- gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, time);
- gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
- gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
- }
- local_irq_restore(flags);
- // Check and commit; commit is set to occur once buffer is 3/4 full
- buffer_check(cpu, GPU_TRACE_BUF, time);
-}
-
-static void marshal_sched_trace_start(int tgid, int pid, int cookie)
-{
- unsigned long cpu = get_physical_cpu(), flags;
+ unsigned long flags, cpu;
u64 time;
- if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
- return;
-
local_irq_save(flags);
+ cpu = get_physical_cpu();
time = gator_get_time();
- if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
- gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_START);
- gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, time);
- gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid);
- gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
- gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie);
+ if (buffer_check_space(cpu, COUNTER_BUF, 2 * MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int64(cpu, COUNTER_BUF, time);
+ gator_buffer_write_packed_int(cpu, COUNTER_BUF, core);
+ gator_buffer_write_packed_int(cpu, COUNTER_BUF, key);
+ gator_buffer_write_packed_int64(cpu, COUNTER_BUF, value);
}
local_irq_restore(flags);
// Check and commit; commit is set to occur once buffer is 3/4 full
- buffer_check(cpu, SCHED_TRACE_BUF, time);
+ buffer_check(cpu, COUNTER_BUF, time);
}
+#endif
-static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state)
+static void marshal_sched_trace_switch(int pid, int state)
{
unsigned long cpu = get_physical_cpu(), flags;
u64 time;
@@ -312,9 +265,7 @@ static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state)
if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_SWITCH);
gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, time);
- gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid);
gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
- gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie);
gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state);
}
local_irq_restore(flags);
@@ -379,3 +330,33 @@ static void marshal_core_name(const int core, const int cpuid, const char *name)
gator_commit_buffer(cpu, SUMMARY_BUF, gator_get_time());
}
#endif
+
+static void marshal_activity_switch(int core, int key, int activity, int pid, int state)
+{
+ unsigned long cpu = get_physical_cpu(), flags;
+ u64 time;
+
+ if (!per_cpu(gator_buffer, cpu)[ACTIVITY_BUF])
+ return;
+
+ local_irq_save(flags);
+ time = gator_get_time();
+ if (buffer_check_space(cpu, ACTIVITY_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, MESSAGE_SWITCH);
+ gator_buffer_write_packed_int64(cpu, ACTIVITY_BUF, time);
+ gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, core);
+ gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, key);
+ gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, activity);
+ gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, pid);
+ gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, state);
+ }
+ local_irq_restore(flags);
+ // Check and commit; commit is set to occur once buffer is 3/4 full
+ buffer_check(cpu, ACTIVITY_BUF, time);
+}
+
+void gator_marshal_activity_switch(int core, int key, int activity, int pid)
+{
+ // state is reserved for cpu use only
+ marshal_activity_switch(core, key, activity, pid, 0);
+}
diff --git a/driver/gator_trace_gpu.c b/driver/gator_trace_gpu.c
index 6332098..a8b9e7d 100644
--- a/driver/gator_trace_gpu.c
+++ b/driver/gator_trace_gpu.c
@@ -23,8 +23,6 @@
#endif
#endif
-#include "gator_trace_gpu.h"
-
/*
* Taken from MALI_PROFILING_EVENT_TYPE_* items in Mali DDK.
*/
@@ -37,7 +35,6 @@
/* Note whether tracepoints have been registered */
static int mali_timeline_trace_registered;
static int mali_job_slots_trace_registered;
-static int gpu_trace_registered;
enum {
GPU_UNIT_NONE = 0,
@@ -47,19 +44,19 @@ enum {
NUMBER_OF_GPU_UNITS
};
-#define MALI_4xx (0x0b07)
-#define MALI_T6xx (0x0056)
+#if defined(MALI_SUPPORT)
-struct mali_gpu_job {
+struct mali_activity {
+ int core;
+ int key;
int count;
- int last_tgid;
+ int last_activity;
int last_pid;
- int last_job_id;
};
#define NUMBER_OF_GPU_CORES 16
-static struct mali_gpu_job mali_gpu_jobs[NUMBER_OF_GPU_UNITS][NUMBER_OF_GPU_CORES];
-static DEFINE_SPINLOCK(mali_gpu_jobs_lock);
+static struct mali_activity mali_activities[NUMBER_OF_GPU_UNITS*NUMBER_OF_GPU_CORES];
+static DEFINE_SPINLOCK(mali_activities_lock);
/* Only one event should be running on a unit and core at a time (ie, a start
* event can only be followed by a stop and vice versa), but because the kernel
@@ -67,53 +64,97 @@ static DEFINE_SPINLOCK(mali_gpu_jobs_lock);
* start1, start2, stop1, stop2. Change it back into start1, stop1, start2,
* stop2 by queueing up start2 and releasing it when stop1 is received.
*/
-static void mali_gpu_enqueue(int unit, int core, int tgid, int pid, int job_id)
+
+static int mali_activity_index(int core, int key)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mali_activities); ++i) {
+ if ((mali_activities[i].core == core) && (mali_activities[i].key == key)) {
+ break;
+ }
+ if ((mali_activities[i].core == 0) && (mali_activities[i].key == 0)) {
+ mali_activities[i].core = core;
+ mali_activities[i].key = key;
+ break;
+ }
+ }
+ BUG_ON(i >= ARRAY_SIZE(mali_activities));
+
+ return i;
+}
+
+static void mali_activity_enqueue(int core, int key, int activity, int pid)
{
+ int i;
int count;
- spin_lock(&mali_gpu_jobs_lock);
- count = mali_gpu_jobs[unit][core].count;
+ spin_lock(&mali_activities_lock);
+ i = mali_activity_index(core, key);
+
+ count = mali_activities[i].count;
BUG_ON(count < 0);
- ++mali_gpu_jobs[unit][core].count;
+ ++mali_activities[i].count;
if (count) {
- mali_gpu_jobs[unit][core].last_tgid = tgid;
- mali_gpu_jobs[unit][core].last_pid = pid;
- mali_gpu_jobs[unit][core].last_job_id = job_id;
+ mali_activities[i].last_activity = activity;
+ mali_activities[i].last_pid = pid;
}
- spin_unlock(&mali_gpu_jobs_lock);
+ spin_unlock(&mali_activities_lock);
if (!count) {
- marshal_sched_gpu_start(unit, core, tgid, pid/*, job_id*/);
+ gator_marshal_activity_switch(core, key, activity, pid);
}
}
-static void mali_gpu_stop(int unit, int core)
+static void mali_activity_stop(int core, int key)
{
+ int i;
int count;
- int last_tgid = 0;
+ int last_activity = 0;
int last_pid = 0;
- //int last_job_id = 0;
- spin_lock(&mali_gpu_jobs_lock);
- if (mali_gpu_jobs[unit][core].count == 0) {
- spin_unlock(&mali_gpu_jobs_lock);
+ spin_lock(&mali_activities_lock);
+ i = mali_activity_index(core, key);
+
+ if (mali_activities[i].count == 0) {
+ spin_unlock(&mali_activities_lock);
return;
}
- --mali_gpu_jobs[unit][core].count;
- count = mali_gpu_jobs[unit][core].count;
+ --mali_activities[i].count;
+ count = mali_activities[i].count;
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_activity = mali_activities[i].last_activity;
+ last_pid = mali_activities[i].last_pid;
}
- spin_unlock(&mali_gpu_jobs_lock);
+ spin_unlock(&mali_activities_lock);
- marshal_sched_gpu_stop(unit, core);
+ gator_marshal_activity_switch(core, key, 0, 0);
if (count) {
- marshal_sched_gpu_start(unit, core, last_tgid, last_pid/*, last_job_id*/);
+ gator_marshal_activity_switch(core, key, last_activity, last_pid);
}
}
+void mali_activity_clear(mali_counter mali_activity[], size_t mali_activity_size)
+{
+ int activity;
+ int cores;
+ int core;
+
+ for (activity = 0; activity < mali_activity_size; ++activity) {
+ cores = mali_activity[activity].cores;
+ if (cores < 0) {
+ cores = 1;
+ }
+ for (core = 0; core < cores; ++core) {
+ if (mali_activity[activity].enabled) {
+ gator_marshal_activity_switch(core, mali_activity[activity].key, 0, 0);
+ }
+ }
+ }
+}
+
+#endif
+
#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
#include "gator_events_mali_4xx.h"
@@ -142,6 +183,8 @@ enum {
EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1,
};
+mali_counter mali_activity[2];
+
GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned int d2, unsigned int d3, unsigned int d4))
{
unsigned int component, state;
@@ -154,18 +197,26 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned
case EVENT_TYPE_START:
if (component == EVENT_CHANNEL_VP0) {
/* tgid = d0; pid = d1; */
- mali_gpu_enqueue(GPU_UNIT_VP, 0, d0, d1, 0);
+ if (mali_activity[1].enabled) {
+ mali_activity_enqueue(0, mali_activity[1].key, 1, d1);
+ }
} else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
/* tgid = d0; pid = d1; */
- mali_gpu_enqueue(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, d0, d1, 0);
+ if (mali_activity[0].enabled) {
+ mali_activity_enqueue(component - EVENT_CHANNEL_FP0, mali_activity[0].key, 1, d1);
+ }
}
break;
case EVENT_TYPE_STOP:
if (component == EVENT_CHANNEL_VP0) {
- mali_gpu_stop(GPU_UNIT_VP, 0);
+ if (mali_activity[1].enabled) {
+ mali_activity_stop(0, mali_activity[1].key);
+ }
} else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
- mali_gpu_stop(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0);
+ if (mali_activity[0].enabled) {
+ mali_activity_stop(component - EVENT_CHANNEL_FP0, mali_activity[0].key);
+ }
}
break;
@@ -186,6 +237,9 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned
#endif
#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
+
+mali_counter mali_activity[3];
+
#if defined(MALI_JOB_SLOTS_EVENT_CHANGED)
GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid, unsigned char job_id))
#else
@@ -217,31 +271,21 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne
if (unit != GPU_UNIT_NONE) {
switch (state) {
case EVENT_TYPE_START:
- mali_gpu_enqueue(unit, 0, tgid, (pid != 0 ? pid : tgid), job_id);
+ if (mali_activity[component].enabled) {
+ mali_activity_enqueue(0, mali_activity[component].key, 1, (pid != 0 ? pid : tgid));
+ }
break;
case EVENT_TYPE_STOP:
- mali_gpu_stop(unit, 0);
+ default: // Some jobs can be soft-stopped, so ensure that this terminates the activity trace.
+ if (mali_activity[component].enabled) {
+ mali_activity_stop(0, mali_activity[component].key);
+ }
break;
- default:
- /*
- * Some jobs can be soft-stopped, so ensure that this terminates the activity trace.
- */
- mali_gpu_stop(unit, 0);
}
}
}
#endif
-GATOR_DEFINE_PROBE(gpu_activity_start, TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p))
-{
- mali_gpu_enqueue(gpu_unit, gpu_core, (int)p->tgid, (int)p->pid, 0);
-}
-
-GATOR_DEFINE_PROBE(gpu_activity_stop, TP_PROTO(int gpu_unit, int gpu_core))
-{
- mali_gpu_stop(gpu_unit, gpu_core);
-}
-
static int gator_trace_gpu_start(void)
{
/*
@@ -249,32 +293,25 @@ static int gator_trace_gpu_start(void)
* Absence of gpu trace points is not an error
*/
- 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)
+ memset(&mali_activities, 0, sizeof(mali_activities));
+#endif
+ mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
+ mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity));
if (!GATOR_REGISTER_TRACE(mali_timeline_event)) {
mali_timeline_trace_registered = 1;
}
#endif
#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
+ mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity));
if (!GATOR_REGISTER_TRACE(mali_job_slots_event)) {
mali_job_slots_trace_registered = 1;
}
#endif
- if (!mali_timeline_trace_registered) {
- if (GATOR_REGISTER_TRACE(gpu_activity_start)) {
- return 0;
- }
- if (GATOR_REGISTER_TRACE(gpu_activity_stop)) {
- GATOR_UNREGISTER_TRACE(gpu_activity_start);
- return 0;
- }
- gpu_trace_registered = 1;
- }
-
return 0;
}
@@ -292,10 +329,5 @@ static void gator_trace_gpu_stop(void)
}
#endif
- if (gpu_trace_registered) {
- GATOR_UNREGISTER_TRACE(gpu_activity_stop);
- GATOR_UNREGISTER_TRACE(gpu_activity_start);
- }
-
- gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
+ mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
}
diff --git a/driver/gator_trace_gpu.h b/driver/gator_trace_gpu.h
deleted file mode 100644
index 5113d45..0000000
--- a/driver/gator_trace_gpu.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2010-2014. 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.
- */
-
-#undef TRACE_GPU
-#define TRACE_GPU gpu
-
-#if !defined(_TRACE_GPU_H)
-#define _TRACE_GPU_H
-
-#include <linux/tracepoint.h>
-
-/*
- * UNIT - the GPU processor type
- * 1 = Vertex Processor
- * 2 = Fragment Processor
- *
- * CORE - the GPU processor core number
- * this is not the CPU core number
- */
-
-/*
- * Tracepoint for calling GPU unit start activity on core
- */
-TRACE_EVENT(gpu_activity_start,
-
- TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p),
-
- TP_ARGS(gpu_unit, gpu_core, p),
-
- TP_STRUCT__entry(
- __field(int, gpu_unit)
- __field(int, gpu_core)
- __array(char, comm, TASK_COMM_LEN)
- __field(pid_t, pid)
- ),
-
- TP_fast_assign(
- __entry->gpu_unit = gpu_unit;
- __entry->gpu_core = gpu_core;
- memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
- __entry->pid = p->pid;
- ),
-
- TP_printk("unit=%d core=%d comm=%s pid=%d",
- __entry->gpu_unit, __entry->gpu_core, __entry->comm,
- __entry->pid)
- );
-
-/*
- * Tracepoint for calling GPU unit stop activity on core
- */
-TRACE_EVENT(gpu_activity_stop,
-
- TP_PROTO(int gpu_unit, int gpu_core),
-
- TP_ARGS(gpu_unit, gpu_core),
-
- TP_STRUCT__entry(
- __field(int, gpu_unit)
- __field(int, gpu_core)
- ),
-
- TP_fast_assign(
- __entry->gpu_unit = gpu_unit;
- __entry->gpu_core = gpu_core;
- ),
-
- TP_printk("unit=%d core=%d", __entry->gpu_unit, __entry->gpu_core)
- );
-
-#endif /* _TRACE_GPU_H */
-
-/* This part must be outside protection */
-#include <trace/define_trace.h>
diff --git a/driver/gator_trace_power.c b/driver/gator_trace_power.c
index 1895bb9..f2754b1 100644
--- a/driver/gator_trace_power.c
+++ b/driver/gator_trace_power.c
@@ -75,7 +75,7 @@ static int gator_trace_power_create_files(struct super_block *sb, struct dentry
GATOR_DEFINE_PROBE(cpu_frequency, TP_PROTO(unsigned int frequency, unsigned int cpu))
{
cpu = lcpu_to_pcpu(cpu);
- marshal_event_single(cpu, power_cpu_key[POWER_CPU_FREQ], frequency * 1000);
+ marshal_event_single64(cpu, power_cpu_key[POWER_CPU_FREQ], frequency * 1000L);
}
GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu))
@@ -109,7 +109,7 @@ static void gator_trace_power_online(void)
int pcpu = get_physical_cpu();
int lcpu = get_logical_cpu();
if (power_cpu_enabled[POWER_CPU_FREQ]) {
- marshal_event_single(pcpu, power_cpu_key[POWER_CPU_FREQ], cpufreq_quick_get(lcpu) * 1000);
+ marshal_event_single64(pcpu, power_cpu_key[POWER_CPU_FREQ], cpufreq_quick_get(lcpu) * 1000L);
}
}
diff --git a/driver/gator_trace_sched.c b/driver/gator_trace_sched.c
index 52990e9..6550086 100644
--- a/driver/gator_trace_sched.c
+++ b/driver/gator_trace_sched.c
@@ -114,7 +114,7 @@ static void collect_counters(u64 time, struct task_struct *task)
// Commit buffers on timeout
if (gator_live_rate > 0 && time >= per_cpu(gator_buffer_commit_time, cpu)) {
- static const int buftypes[] = { NAME_BUF, COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF };
+ static const int buftypes[] = { NAME_BUF, COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF, ACTIVITY_BUF };
int i;
for (i = 0; i < ARRAY_SIZE(buftypes); ++i) {
@@ -137,35 +137,44 @@ static void collect_counters(u64 time, struct task_struct *task)
// special case used during a suspend of the system
static void trace_sched_insert_idle(void)
{
- marshal_sched_trace_switch(0, 0, 0, 0);
+ marshal_sched_trace_switch(0, 0);
}
-GATOR_DEFINE_PROBE(sched_process_fork, TP_PROTO(struct task_struct *parent, struct task_struct *child))
+static void gator_trace_emit_link(struct task_struct *p)
{
int cookie;
int cpu = get_physical_cpu();
- cookie = get_exec_cookie(cpu, child);
- emit_pid_name(child);
+ cookie = get_exec_cookie(cpu, p);
+ emit_pid_name(p);
- marshal_sched_trace_start(child->tgid, child->pid, cookie);
+ marshal_link(cookie, p->tgid, p->pid);
}
+GATOR_DEFINE_PROBE(sched_process_fork, TP_PROTO(struct task_struct *parent, struct task_struct *child))
+{
+ gator_trace_emit_link(child);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+GATOR_DEFINE_PROBE(sched_process_exec, TP_PROTO(struct task_struct *p, pid_t old_pid, struct linux_binprm *bprm))
+{
+ gator_trace_emit_link(p);
+}
+#endif
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next))
#else
GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_struct *next))
#endif
{
- int cookie;
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);
if (prev->state == TASK_RUNNING) {
state = STATE_CONTENTION;
} else if (prev->in_iowait) {
@@ -178,7 +187,10 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_
collect_counters(gator_get_time(), prev);
per_cpu(collecting, cpu) = 0;
- marshal_sched_trace_switch(next->tgid, next->pid, cookie, state);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
+ gator_trace_emit_link(next);
+#endif
+ marshal_sched_trace_switch(next->pid, state);
per_cpu(in_scheduler_context, cpu) = false;
}
@@ -199,6 +211,10 @@ static int register_scheduler_tracepoints(void)
// register tracepoints
if (GATOR_REGISTER_TRACE(sched_process_fork))
goto fail_sched_process_fork;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+ if (GATOR_REGISTER_TRACE(sched_process_exec))
+ goto fail_sched_process_exec;
+#endif
if (GATOR_REGISTER_TRACE(sched_switch))
goto fail_sched_switch;
if (GATOR_REGISTER_TRACE(sched_process_free))
@@ -216,15 +232,42 @@ fail_sched_process_free:
GATOR_UNREGISTER_TRACE(sched_switch);
fail_sched_switch:
GATOR_UNREGISTER_TRACE(sched_process_fork);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+fail_sched_process_exec:
+ GATOR_UNREGISTER_TRACE(sched_process_exec);
+#endif
fail_sched_process_fork:
pr_err("gator: tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n");
return -1;
}
+static void unregister_scheduler_tracepoints(void)
+{
+ GATOR_UNREGISTER_TRACE(sched_process_fork);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+ GATOR_UNREGISTER_TRACE(sched_process_exec);
+#endif
+ GATOR_UNREGISTER_TRACE(sched_switch);
+ GATOR_UNREGISTER_TRACE(sched_process_free);
+ pr_debug("gator: unregistered tracepoints\n");
+}
+
+static void gator_trace_sched_stop(void)
+{
+ int cpu;
+
+ unregister_scheduler_tracepoints();
+
+ for_each_present_cpu(cpu) {
+ kfree(per_cpu(taskname_keys, cpu));
+ }
+}
+
static int gator_trace_sched_start(void)
{
int cpu, size;
+ int ret;
for_each_present_cpu(cpu) {
size = TASK_MAP_ENTRIES * TASK_MAX_COLLISIONS * sizeof(uint64_t);
@@ -234,7 +277,9 @@ static int gator_trace_sched_start(void)
memset(per_cpu(taskname_keys, cpu), 0, size);
}
- return register_scheduler_tracepoints();
+ ret = register_scheduler_tracepoints();
+
+ return ret;
}
static void gator_trace_sched_offline(void)
@@ -242,24 +287,6 @@ static void gator_trace_sched_offline(void)
trace_sched_insert_idle();
}
-static void unregister_scheduler_tracepoints(void)
-{
- GATOR_UNREGISTER_TRACE(sched_process_fork);
- GATOR_UNREGISTER_TRACE(sched_switch);
- GATOR_UNREGISTER_TRACE(sched_process_free);
- pr_debug("gator: unregistered tracepoints\n");
-}
-
-static void gator_trace_sched_stop(void)
-{
- int cpu;
- unregister_scheduler_tracepoints();
-
- for_each_present_cpu(cpu) {
- kfree(per_cpu(taskname_keys, cpu));
- }
-}
-
static void gator_trace_sched_init(void)
{
int i;
diff --git a/driver/mali/mali_dd_gator_api.h b/driver/mali/mali_dd_gator_api.h
new file mode 100644
index 0000000..104b34f
--- /dev/null
+++ b/driver/mali/mali_dd_gator_api.h
@@ -0,0 +1,40 @@
+#if !defined(MALI_DDK_GATOR_API_VERSION)
+ #define MALI_DDK_GATOR_API_VERSION 3
+#endif
+#if !defined(MALI_TRUE)
+ #define MALI_TRUE ((unsigned int)1)
+#endif
+
+#if !defined(MALI_FALSE)
+ #define MALI_FALSE ((unsigned int)0)
+#endif
+
+struct mali_dd_hwcnt_info {
+
+ /* Passed from Gator to kbase */
+ //u32 in_mali_dd_hwcnt_version;
+ unsigned short int bitmask[4];
+
+ /* Passed from kbase to Gator */
+
+ /* ptr to counter dump memory */
+ void *kernel_dump_buffer;
+
+ /* size of counter dump memory */
+ unsigned int size;
+
+ unsigned int gpu_id;
+
+ unsigned int nr_cores;
+
+ unsigned int nr_core_groups;
+
+ /* The cached present bitmaps - these are the same as the corresponding hardware registers*/
+ unsigned long int shader_present_bitmap;
+};
+
+struct mali_dd_hwcnt_handles;
+extern struct mali_dd_hwcnt_handles* mali_dd_hwcnt_init(struct mali_dd_hwcnt_info *in_out_info);
+extern void mali_dd_hwcnt_clear(struct mali_dd_hwcnt_info *in_out_info, struct mali_dd_hwcnt_handles *opaque_handles);
+extern unsigned int kbase_dd_instr_hwcnt_dump_complete(struct mali_dd_hwcnt_handles *opaque_handles, unsigned int * const success);
+extern unsigned int kbase_dd_instr_hwcnt_dump_irq(struct mali_dd_hwcnt_handles *opaque_handles);
diff --git a/driver/mali_t6xx.mk b/driver/mali_t6xx.mk
index 059d47a..fa7571d 100644
--- a/driver/mali_t6xx.mk
+++ b/driver/mali_t6xx.mk
@@ -21,6 +21,10 @@ OSK_DIR = $(DDK_DIR)/drivers/gpu/arm/midgard/osk
EXTRA_CFLAGS += -DMALI_DIR_MIDGARD=1
endif
+ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/midgard/mali_dd_gator_api.h),)
+EXTRA_CFLAGS += -DMALI_SIMPLE_API=1
+endif
+
UMP_DIR = $(DDK_DIR)/include/linux
# Include directories in the DDK