summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Medhurst2014-08-01 07:32:58 -0500
committerJon Medhurst2014-08-01 07:33:21 -0500
commitbc8a84cf0b138a2951679581453da7bd93003db6 (patch)
treeb94eb00f90c24063053d99bea588fbbd493076ef
parentba783f1443773505231ac2808c9a3716c3c2f3ae (diff)
downloadarm-ds5-gator-DS-5.19.tar.gz
arm-ds5-gator-DS-5.19.tar.xz
arm-ds5-gator-DS-5.19.zip
gator: Version 5.19DS-5.19-tiDS-5.19
Signed-off-by: Jon Medhurst <tixy@linaro.org> On branch master Changes not staged for commit: modified: README_Streamline.txt no changes added to commit (use "git add" and/or "git commit -a") Signed-off-by: Jon Medhurst <tixy@linaro.org>
-rwxr-xr-xREADME_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.cpp6
-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.h6
-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.c77
-rw-r--r--driver/gator_marshaling.c101
-rw-r--r--driver/gator_trace_gpu.c142
-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
87 files changed, 2281 insertions, 1057 deletions
diff --git a/README_Streamline.txt b/README_Streamline.txt
index df3f923..54791c0 100755
--- a/README_Streamline.txt
+++ b/README_Streamline.txt
@@ -2,7 +2,7 @@
2*** Purpose *** 2*** Purpose ***
3 3
4Instructions on setting up ARM Streamline on the target. 4Instructions on setting up ARM Streamline on the target.
5The 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. 5The 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.
6The driver should be built as a module and the daemon must run with root permissions on the target. 6The driver should be built as a module and the daemon must run with root permissions on the target.
7 7
8*** Introduction *** 8*** Introduction ***
@@ -14,7 +14,7 @@ A Linux development environment with cross compiling tools is most likely requir
14 -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. 14 -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.
15 -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. 15 -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.
16 -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. 16 -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.
17 -If the target is running Linux 3.12 or later the kernel driver is not required and userspace APIs will be used instead. 17 -If the target is running Linux 3.4 or later the kernel driver is not required and userspace APIs will be used instead.
18 18
19*** Kernel configuration *** 19*** Kernel configuration ***
20 20
@@ -59,8 +59,7 @@ If a device tree is used it must include the pmu bindings, see Documentation/dev
59*** Building the gator module *** 59*** Building the gator module ***
60 60
61To create the gator.ko module, 61To create the gator.ko module,
62 cd /path/to/gator/driver-src 62 tar xzf /path/to/DS-5/arm/gator/driver-src/gator-driver.tar.gz
63 tar xzf gator-driver.tar.gz
64 cd gator-driver 63 cd gator-driver
65 make -C <kernel_build_dir> M=`pwd` ARCH=arm CROSS_COMPILE=<...> modules 64 make -C <kernel_build_dir> M=`pwd` ARCH=arm CROSS_COMPILE=<...> modules
66for example when using the linaro-toolchain-binaries 65for 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
78 source "drivers/gator/Kconfig" 77 source "drivers/gator/Kconfig"
79You can now select gator when using menuconfig while configuring the kernel and rebuild as directed 78You can now select gator when using menuconfig while configuring the kernel and rebuild as directed
80 79
80*** Use the prebuilt gator daemon ***
81
82A 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.
83To 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.
84
81*** Building the gator daemon *** 85*** Building the gator daemon ***
82 86
83cd /path/to/gator/daemon-src 87tar -xzf /path/to/DS-5/arm/gator/daemon-src/gator-daemon.tar.gz
84tar -xzf gator-daemon.tar.gz (may need to issue with 'sudo')
85For Linux targets, 88For Linux targets,
86 cd gator-daemon 89 cd gator-daemon
87 make CROSS_COMPILE=<...> # For ARMv7 targets 90 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
105With root privileges, run the daemon 108With root privileges, run the daemon
106 sudo ./gatord & 109 sudo ./gatord &
107Note: 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. 110Note: 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.
108If 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. 111If 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.
109 112
110*** Customizing the l2c-310 Counter *** 113*** Customizing the l2c-310 Counter ***
111 114
@@ -123,7 +126,7 @@ CCN-504 is disabled by default. To enable CCN-504, insmod gator module with the
123Recommended compiler settings: 126Recommended compiler settings:
124 "-g": Debug information, such as line numbers, needed for best analysis results. 127 "-g": Debug information, such as line numbers, needed for best analysis results.
125 "-fno-inline": Speed improvement when processing the image files and most accurate analysis results. 128 "-fno-inline": Speed improvement when processing the image files and most accurate analysis results.
126 "-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). 129 "-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).
127 "-marm": This option is required if your compiler is configured with --with-mode=thumb, otherwise call stack unwinding will not work. 130 "-marm": This option is required if your compiler is configured with --with-mode=thumb, otherwise call stack unwinding will not work.
128 131
129*** Hardfloat EABI *** 132*** Hardfloat EABI ***
@@ -132,6 +135,35 @@ To compile for non-hardfloat targets it is necessary to add options '-marm -marc
132The 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. 135The 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.
133Attempting to run an incompatible binary often results in the confusing error message "No such file or directory" when clearly the file exists. 136Attempting to run an incompatible binary often results in the confusing error message "No such file or directory" when clearly the file exists.
134 137
138*** Mali GPU ***
139
140Streamline 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.
141
142Mali-4xx:
143 ___To add Mali-4xx support to gator___
144 GATOR_WITH_MALI_SUPPORT=MALI_4xx # Set by CONFIG_GATOR_MALI_4XXMP
145 CONFIG_GATOR_MALI_PATH=".../path/to/Mali_DDK_kernel_files/src/devicedrv/mali" # gator source needs to #include "linux/mali_linux_trace.h"
146 GATOR_MALI_INTERFACE_STYLE=<3|4> # 3=Mali-400 DDK >= r3p0-04rel0 and < r3p2-01rel3
147 # 4=Mali-400 DDK >= r3p2-01rel3
148 # (default of 4 set in gator-driver/gator_events_mali_4xx.c)
149 ___To add the corresponding support to Mali___
150 Userspace needs MALI_TIMELINE_PROFILING_ENABLED=1 MALI_FRAMEBUFFER_DUMP_ENABLED=1 MALI_SW_COUNTERS_ENABLED=1
151 Kernel driver needs USING_PROFILING=1 # Sets CONFIG_MALI400_PROFILING=y
152 See the DDK integration guide for more details (the above are the default in later driver versions)
153
154Mali-T6xx/T7xx:
155 ___To add Mali-T6xx support to gator___
156 GATOR_WITH_MALI_SUPPORT=MALI_T6xx # Set by CONFIG_GATOR_MALI_T6XX
157 DDK_DIR=".../path/to/Mali_DDK_kernel_files" # gator source needs access to headers under .../kernel/drivers/gpu/arm/...
158 # (default of . suitable for in-tree builds)
159 ___To add the corresponding support to Mali___
160 Userspace (scons) needs gator=1
161 Kernel driver needs CONFIG_MALI_GATOR_SUPPORT=y
162 See the DDK integration guide for more details
163
164*** Polling /dev, /sys and /proc files ***
165Gator 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.
166
135*** Bugs *** 167*** Bugs ***
136 168
137There 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. 169There 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
139 ARMv7_Cortex_A9 breakpoint software tracepoint 171 ARMv7_Cortex_A9 breakpoint software tracepoint
140To 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 172To 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
141 173
142There 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. 174There 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.
143 175
144If you see this error when using SELinux, ex: Android 4.4 or later 176If you see this error when using SELinux, ex: Android 4.4 or later
145 # ./gatord 177 # ./gatord
@@ -172,3 +204,4 @@ update-rc.d rungator.sh defaults
172*** GPL License *** 204*** GPL License ***
173 205
174For license information, please see the file LICENSE after unzipping driver-src/gator-driver.tar.gz. 206For license information, please see the file LICENSE after unzipping driver-src/gator-driver.tar.gz.
207The 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)
3 3
4XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h) 4XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h)
5 5
6LOCAL_CFLAGS += -Wall -O3 -mthumb-interwork -fno-exceptions -DETCDIR=\"/etc\" -Ilibsensors 6LOCAL_CFLAGS += -Wall -O3 -mthumb-interwork -fno-exceptions -pthread -DETCDIR=\"/etc\" -Ilibsensors
7 7
8LOCAL_SRC_FILES := \ 8LOCAL_SRC_FILES := \
9 Buffer.cpp \ 9 Buffer.cpp \
@@ -15,12 +15,14 @@ LOCAL_SRC_FILES := \
15 DynBuf.cpp \ 15 DynBuf.cpp \
16 EventsXML.cpp \ 16 EventsXML.cpp \
17 ExternalSource.cpp \ 17 ExternalSource.cpp \
18 FSDriver.cpp \
18 Fifo.cpp \ 19 Fifo.cpp \
19 Hwmon.cpp \ 20 Hwmon.cpp \
20 KMod.cpp \ 21 KMod.cpp \
21 LocalCapture.cpp \ 22 LocalCapture.cpp \
22 Logging.cpp \ 23 Logging.cpp \
23 main.cpp \ 24 main.cpp \
25 MaliVideoDriver.cpp \
24 Monitor.cpp \ 26 Monitor.cpp \
25 OlySocket.cpp \ 27 OlySocket.cpp \
26 OlyUtility.cpp \ 28 OlyUtility.cpp \
@@ -55,7 +57,7 @@ LOCAL_SRC_FILES := \
55 mxml/mxml-set.c \ 57 mxml/mxml-set.c \
56 mxml/mxml-string.c 58 mxml/mxml-string.c
57 59
58LOCAL_C_INCLUDES := $(LOCAL_PATH) 60LOCAL_C_INCLUDES := $(LOCAL_PATH)
59 61
60LOCAL_MODULE := gatord 62LOCAL_MODULE := gatord
61LOCAL_MODULE_TAGS := optional 63LOCAL_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 @@
15#define mask (mSize - 1) 15#define mask (mSize - 1)
16 16
17enum { 17enum {
18 CODE_PEA = 1, 18 CODE_PEA = 1,
19 CODE_KEYS = 2, 19 CODE_KEYS = 2,
20 CODE_FORMAT = 3, 20 CODE_FORMAT = 3,
21 CODE_MAPS = 4, 21 CODE_MAPS = 4,
22 CODE_COMM = 5, 22 CODE_COMM = 5,
23 CODE_KEYS_OLD = 6,
23}; 24};
24 25
25// Summary Frame Messages 26// Summary Frame Messages
@@ -167,7 +168,7 @@ void Buffer::check(const uint64_t time) {
167 } 168 }
168} 169}
169 170
170void Buffer::packInt(int32_t x) { 171void Buffer::packInt(char *const buf, const int size, int &writePos, int32_t x) {
171 int packedBytes = 0; 172 int packedBytes = 0;
172 int more = true; 173 int more = true;
173 while (more) { 174 while (more) {
@@ -181,11 +182,15 @@ void Buffer::packInt(int32_t x) {
181 b |= 0x80; 182 b |= 0x80;
182 } 183 }
183 184
184 mBuf[(mWritePos + packedBytes) & mask] = b; 185 buf[(writePos + packedBytes) & /*mask*/(size - 1)] = b;
185 packedBytes++; 186 packedBytes++;
186 } 187 }
187 188
188 mWritePos = (mWritePos + packedBytes) & mask; 189 writePos = (writePos + packedBytes) & /*mask*/(size - 1);
190}
191
192void Buffer::packInt(int32_t x) {
193 packInt(mBuf, mSize, mWritePos, x);
189} 194}
190 195
191void Buffer::packInt64(int64_t x) { 196void Buffer::packInt64(int64_t x) {
@@ -320,6 +325,21 @@ void Buffer::keys(const int count, const __u64 *const ids, const int *const keys
320 check(1); 325 check(1);
321} 326}
322 327
328void Buffer::keysOld(const int keyCount, const int *const keys, const int bytes, const char *const buf) {
329 if (checkSpace((2 + keyCount) * MAXSIZE_PACK32 + bytes)) {
330 packInt(CODE_KEYS_OLD);
331 packInt(keyCount);
332 for (int i = 0; i < keyCount; ++i) {
333 packInt(keys[i]);
334 }
335 writeBytes(buf, bytes);
336 } else {
337 logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
338 handleException();
339 }
340 check(1);
341}
342
323void Buffer::format(const int length, const char *const format) { 343void Buffer::format(const int length, const char *const format) {
324 if (checkSpace(MAXSIZE_PACK32 + length + 1)) { 344 if (checkSpace(MAXSIZE_PACK32 + length + 1)) {
325 packInt(CODE_FORMAT); 345 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:
54 // Perf Attrs messages 54 // Perf Attrs messages
55 void pea(const struct perf_event_attr *const pea, int key); 55 void pea(const struct perf_event_attr *const pea, int key);
56 void keys(const int count, const __u64 *const ids, const int *const keys); 56 void keys(const int count, const __u64 *const ids, const int *const keys);
57 void keysOld(const int keyCount, const int *const keys, const int bytes, const char *const buf);
57 void format(const int length, const char *const format); 58 void format(const int length, const char *const format);
58 void maps(const int pid, const int tid, const char *const maps); 59 void maps(const int pid, const int tid, const char *const maps);
59 void comm(const int pid, const int tid, const char *const image, const char *const comm); 60 void comm(const int pid, const int tid, const char *const image, const char *const comm);
@@ -64,6 +65,11 @@ public:
64 // Prefer a new member to using these functions if possible 65 // Prefer a new member to using these functions if possible
65 char *getWritePos() { return mBuf + mWritePos; } 66 char *getWritePos() { return mBuf + mWritePos; }
66 void advanceWrite(int bytes) { mWritePos = (mWritePos + bytes) & /*mask*/(mSize - 1); } 67 void advanceWrite(int bytes) { mWritePos = (mWritePos + bytes) & /*mask*/(mSize - 1); }
68 static void packInt(char *const buf, const int size, int &writePos, int32_t x);
69 void packInt(int32_t x);
70 void packInt64(int64_t x);
71 void writeBytes(const void *const data, size_t count);
72 void writeString(const char *const str);
67 73
68 static void writeLEInt(unsigned char *buf, int v) { 74 static void writeLEInt(unsigned char *buf, int v) {
69 buf[0] = (v >> 0) & 0xFF; 75 buf[0] = (v >> 0) & 0xFF;
@@ -76,11 +82,6 @@ private:
76 bool commitReady() const; 82 bool commitReady() const;
77 bool checkSpace(int bytes); 83 bool checkSpace(int bytes);
78 84
79 void packInt(int32_t x);
80 void packInt64(int64_t x);
81 void writeBytes(const void *const data, size_t count);
82 void writeString(const char *const str);
83
84 const int32_t mCore; 85 const int32_t mCore;
85 const int32_t mBufType; 86 const int32_t mBufType;
86 const int mSize; 87 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) {
33 captured = mxmlNewElement(xml, "captured"); 33 captured = mxmlNewElement(xml, "captured");
34 mxmlElementSetAttr(captured, "version", "1"); 34 mxmlElementSetAttr(captured, "version", "1");
35 if (gSessionData->perf.isSetup()) { 35 if (gSessionData->perf.isSetup()) {
36 mxmlElementSetAttr(captured, "type", "Perf"); 36 mxmlElementSetAttr(captured, "type", "Perf");
37 } 37 }
38 mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION); 38 mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION);
39 if (includeTime) { // Send the following only after the capture is complete 39 if (includeTime) { // Send the following only after the capture is complete
@@ -66,10 +66,15 @@ mxml_node_t* CapturedXML::getTree(bool includeTime) {
66 mxml_node_t *const node = mxmlNewElement(counters, "counter"); 66 mxml_node_t *const node = mxmlNewElement(counters, "counter");
67 mxmlElementSetAttrf(node, "key", "0x%x", counter.getKey()); 67 mxmlElementSetAttrf(node, "key", "0x%x", counter.getKey());
68 mxmlElementSetAttr(node, "type", counter.getType()); 68 mxmlElementSetAttr(node, "type", counter.getType());
69 mxmlElementSetAttrf(node, "event", "0x%x", counter.getEvent()); 69 if (counter.getEvent() != -1) {
70 mxmlElementSetAttrf(node, "event", "0x%x", counter.getEvent());
71 }
70 if (counter.getCount() > 0) { 72 if (counter.getCount() > 0) {
71 mxmlElementSetAttrf(node, "count", "%d", counter.getCount()); 73 mxmlElementSetAttrf(node, "count", "%d", counter.getCount());
72 } 74 }
75 if (counter.getCores() > 0) {
76 mxmlElementSetAttrf(node, "cores", "%d", counter.getCores());
77 }
73 } 78 }
74 } 79 }
75 80
@@ -89,7 +94,7 @@ void CapturedXML::write(char* path) {
89 94
90 // Set full path 95 // Set full path
91 snprintf(file, PATH_MAX, "%s/captured.xml", path); 96 snprintf(file, PATH_MAX, "%s/captured.xml", path);
92 97
93 char* xml = getXML(true); 98 char* xml = getXML(true);
94 if (util->writeToDisk(file, xml) < 0) { 99 if (util->writeToDisk(file, xml) < 0) {
95 logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); 100 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:
23 23
24const char * mxmlWhitespaceCB(mxml_node_t *node, int where); 24const char * mxmlWhitespaceCB(mxml_node_t *node, int where);
25 25
26#endif //__CAPTURED_XML_H__ 26#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 @@
26#include "Driver.h" 26#include "Driver.h"
27#include "PerfSource.h" 27#include "PerfSource.h"
28#include "DriverSource.h" 28#include "DriverSource.h"
29#include "UserSpaceSource.h"
30#include "ExternalSource.h" 29#include "ExternalSource.h"
30#include "UserSpaceSource.h"
31 31
32static sem_t haltPipeline, senderThreadStarted, startProfile, senderSem; // Shared by Child and spawned threads 32static sem_t haltPipeline, senderThreadStarted, startProfile, senderSem; // Shared by Child and spawned threads
33static Source *primarySource = NULL; 33static Source *primarySource = NULL;
34static Source *userSpaceSource = NULL;
35static Source *externalSource = NULL; 34static Source *externalSource = NULL;
35static Source *userSpaceSource = NULL;
36static Sender* sender = NULL; // Shared by Child.cpp and spawned threads 36static Sender* sender = NULL; // Shared by Child.cpp and spawned threads
37Child* child = NULL; // shared by Child.cpp and main.cpp 37Child* child = NULL; // shared by Child.cpp and main.cpp
38 38
@@ -147,16 +147,16 @@ static void *senderThread(void *) {
147 prctl(PR_SET_NAME, (unsigned long)&"gatord-sender", 0, 0, 0); 147 prctl(PR_SET_NAME, (unsigned long)&"gatord-sender", 0, 0, 0);
148 sem_wait(&haltPipeline); 148 sem_wait(&haltPipeline);
149 149
150 while (!primarySource->isDone() || (userSpaceSource != NULL && !userSpaceSource->isDone()) || (externalSource != NULL && !externalSource->isDone())) { 150 while (!primarySource->isDone() ||
151 !externalSource->isDone() ||
152 (userSpaceSource != NULL && !userSpaceSource->isDone())) {
151 sem_wait(&senderSem); 153 sem_wait(&senderSem);
152 154
153 primarySource->write(sender); 155 primarySource->write(sender);
156 externalSource->write(sender);
154 if (userSpaceSource != NULL) { 157 if (userSpaceSource != NULL) {
155 userSpaceSource->write(sender); 158 userSpaceSource->write(sender);
156 } 159 }
157 if (externalSource != NULL) {
158 externalSource->write(sender);
159 }
160 } 160 }
161 161
162 // write end-of-capture sequence 162 // write end-of-capture sequence
@@ -202,6 +202,10 @@ void Child::initialization() {
202void Child::endSession() { 202void Child::endSession() {
203 gSessionData->mSessionIsActive = false; 203 gSessionData->mSessionIsActive = false;
204 primarySource->interrupt(); 204 primarySource->interrupt();
205 externalSource->interrupt();
206 if (userSpaceSource != NULL) {
207 userSpaceSource->interrupt();
208 }
205 sem_post(&haltPipeline); 209 sem_post(&haltPipeline);
206} 210}
207 211
@@ -227,9 +231,9 @@ void Child::run() {
227 231
228 // Set up the driver; must be done after gSessionData->mPerfCounterType[] is populated 232 // Set up the driver; must be done after gSessionData->mPerfCounterType[] is populated
229 if (!gSessionData->perf.isSetup()) { 233 if (!gSessionData->perf.isSetup()) {
230 primarySource = new DriverSource(&senderSem, &startProfile); 234 primarySource = new DriverSource(&senderSem, &startProfile);
231 } else { 235 } else {
232 primarySource = new PerfSource(&senderSem, &startProfile); 236 primarySource = new PerfSource(&senderSem, &startProfile);
233 } 237 }
234 238
235 // Initialize all drivers 239 // Initialize all drivers
@@ -280,11 +284,18 @@ void Child::run() {
280 thread_creation_success = false; 284 thread_creation_success = false;
281 } else if (socket && pthread_create(&stopThreadID, NULL, stopThread, NULL)) { 285 } else if (socket && pthread_create(&stopThreadID, NULL, stopThread, NULL)) {
282 thread_creation_success = false; 286 thread_creation_success = false;
283 } else if (pthread_create(&senderThreadID, NULL, senderThread, NULL)){ 287 } else if (pthread_create(&senderThreadID, NULL, senderThread, NULL)) {
284 thread_creation_success = false; 288 thread_creation_success = false;
285 } 289 }
286 290
287 if (gSessionData->hwmon.countersEnabled()) { 291 externalSource = new ExternalSource(&senderSem);
292 if (!externalSource->prepare()) {
293 logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
294 handleException();
295 }
296 externalSource->start();
297
298 if (gSessionData->hwmon.countersEnabled() || gSessionData->fsDriver.countersEnabled()) {
288 userSpaceSource = new UserSpaceSource(&senderSem); 299 userSpaceSource = new UserSpaceSource(&senderSem);
289 if (!userSpaceSource->prepare()) { 300 if (!userSpaceSource->prepare()) {
290 logg->logError(__FILE__, __LINE__, "Unable to prepare for capture"); 301 logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
@@ -292,14 +303,6 @@ void Child::run() {
292 } 303 }
293 userSpaceSource->start(); 304 userSpaceSource->start();
294 } 305 }
295 if (access("/tmp/gator", F_OK) == 0) {
296 externalSource = new ExternalSource(&senderSem);
297 if (!externalSource->prepare()) {
298 logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
299 handleException();
300 }
301 externalSource->start();
302 }
303 306
304 if (!thread_creation_success) { 307 if (!thread_creation_success) {
305 logg->logError(__FILE__, __LINE__, "Failed to create gator threads"); 308 logg->logError(__FILE__, __LINE__, "Failed to create gator threads");
@@ -312,12 +315,10 @@ void Child::run() {
312 // Start profiling 315 // Start profiling
313 primarySource->run(); 316 primarySource->run();
314 317
315 if (externalSource != NULL) {
316 externalSource->join();
317 }
318 if (userSpaceSource != NULL) { 318 if (userSpaceSource != NULL) {
319 userSpaceSource->join(); 319 userSpaceSource->join();
320 } 320 }
321 externalSource->join();
321 322
322 // Wait for the other threads to exit 323 // Wait for the other threads to exit
323 pthread_join(senderThreadID, NULL); 324 pthread_join(senderThreadID, NULL);
@@ -337,8 +338,8 @@ void Child::run() {
337 338
338 logg->logMessage("Profiling ended."); 339 logg->logMessage("Profiling ended.");
339 340
340 delete externalSource;
341 delete userSpaceSource; 341 delete userSpaceSource;
342 delete externalSource;
342 delete primarySource; 343 delete primarySource;
343 delete sender; 344 delete sender;
344 delete localCapture; 345 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:
30 Child &operator=(const Child &); 30 Child &operator=(const Child &);
31}; 31};
32 32
33#endif //__CHILD_H__ 33#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";
21static const char* ATTR_REVISION = "revision"; 21static const char* ATTR_REVISION = "revision";
22static const char* ATTR_EVENT = "event"; 22static const char* ATTR_EVENT = "event";
23static const char* ATTR_COUNT = "count"; 23static const char* ATTR_COUNT = "count";
24static const char* ATTR_CORES = "cores";
24 25
25ConfigurationXML::ConfigurationXML() { 26ConfigurationXML::ConfigurationXML() {
26 const char * configuration_xml; 27 const char * configuration_xml;
27 unsigned int configuration_xml_len; 28 unsigned int configuration_xml_len;
28 getDefaultConfigurationXml(configuration_xml, configuration_xml_len); 29 getDefaultConfigurationXml(configuration_xml, configuration_xml_len);
29 30
30 char path[PATH_MAX]; 31 char path[PATH_MAX];
31 32
32 getPath(path); 33 getPath(path);
@@ -53,7 +54,7 @@ ConfigurationXML::ConfigurationXML() {
53 54
54 break; 55 break;
55 } 56 }
56 57
57 validate(); 58 validate();
58} 59}
59 60
@@ -82,7 +83,7 @@ int ConfigurationXML::parse(const char* configurationXML) {
82 node = mxmlGetFirstChild(tree); 83 node = mxmlGetFirstChild(tree);
83 while (node && mxmlGetType(node) != MXML_ELEMENT) 84 while (node && mxmlGetType(node) != MXML_ELEMENT)
84 node = mxmlWalkNext(node, tree, MXML_NO_DESCEND); 85 node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
85 86
86 ret = configurationsTag(node); 87 ret = configurationsTag(node);
87 88
88 node = mxmlGetFirstChild(node); 89 node = mxmlGetFirstChild(node);
@@ -127,7 +128,7 @@ void ConfigurationXML::validate(void) {
127#define CONFIGURATION_REVISION 3 128#define CONFIGURATION_REVISION 3
128int ConfigurationXML::configurationsTag(mxml_node_t *node) { 129int ConfigurationXML::configurationsTag(mxml_node_t *node) {
129 const char* revision_string; 130 const char* revision_string;
130 131
131 revision_string = mxmlElementGetAttr(node, ATTR_REVISION); 132 revision_string = mxmlElementGetAttr(node, ATTR_REVISION);
132 if (!revision_string) { 133 if (!revision_string) {
133 return 1; //revision issue; 134 return 1; //revision issue;
@@ -158,6 +159,7 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) {
158 if (mxmlElementGetAttr(node, ATTR_COUNTER)) counter.setType(mxmlElementGetAttr(node, ATTR_COUNTER)); 159 if (mxmlElementGetAttr(node, ATTR_COUNTER)) counter.setType(mxmlElementGetAttr(node, ATTR_COUNTER));
159 if (mxmlElementGetAttr(node, ATTR_EVENT)) counter.setEvent(strtol(mxmlElementGetAttr(node, ATTR_EVENT), NULL, 16)); 160 if (mxmlElementGetAttr(node, ATTR_EVENT)) counter.setEvent(strtol(mxmlElementGetAttr(node, ATTR_EVENT), NULL, 16));
160 if (mxmlElementGetAttr(node, ATTR_COUNT)) counter.setCount(strtol(mxmlElementGetAttr(node, ATTR_COUNT), NULL, 10)); 161 if (mxmlElementGetAttr(node, ATTR_COUNT)) counter.setCount(strtol(mxmlElementGetAttr(node, ATTR_COUNT), NULL, 10));
162 if (mxmlElementGetAttr(node, ATTR_CORES)) counter.setCores(strtol(mxmlElementGetAttr(node, ATTR_CORES), NULL, 10));
161 if (counter.getCount() > 0) { 163 if (counter.getCount() > 0) {
162 gSessionData->mIsEBS = true; 164 gSessionData->mIsEBS = true;
163 } 165 }
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:
27 mEnabled = false; 27 mEnabled = false;
28 mEvent = -1; 28 mEvent = -1;
29 mCount = 0; 29 mCount = 0;
30 mCores = -1;
30 mKey = 0; 31 mKey = 0;
31 mDriver = NULL; 32 mDriver = NULL;
32 } 33 }
@@ -35,6 +36,7 @@ public:
35 void setEnabled(const bool enabled) { mEnabled = enabled; } 36 void setEnabled(const bool enabled) { mEnabled = enabled; }
36 void setEvent(const int event) { mEvent = event; } 37 void setEvent(const int event) { mEvent = event; }
37 void setCount(const int count) { mCount = count; } 38 void setCount(const int count) { mCount = count; }
39 void setCores(const int cores) { mCores = cores; }
38 void setKey(const int key) { mKey = key; } 40 void setKey(const int key) { mKey = key; }
39 void setDriver(Driver *const driver) { mDriver = driver; } 41 void setDriver(Driver *const driver) { mDriver = driver; }
40 42
@@ -42,6 +44,7 @@ public:
42 bool isEnabled() const { return mEnabled; } 44 bool isEnabled() const { return mEnabled; }
43 int getEvent() const { return mEvent; } 45 int getEvent() const { return mEvent; }
44 int getCount() const { return mCount; } 46 int getCount() const { return mCount; }
47 int getCores() const { return mCores; }
45 int getKey() const { return mKey; } 48 int getKey() const { return mKey; }
46 Driver *getDriver() const { return mDriver; } 49 Driver *getDriver() const { return mDriver; }
47 50
@@ -54,6 +57,7 @@ private:
54 bool mEnabled; 57 bool mEnabled;
55 int mEvent; 58 int mEvent;
56 int mCount; 59 int mCount;
60 int mCores;
57 int mKey; 61 int mKey;
58 Driver *mDriver; 62 Driver *mDriver;
59}; 63};
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 @@
12 12
13#include <fcntl.h> 13#include <fcntl.h>
14#include <inttypes.h> 14#include <inttypes.h>
15#include <sys/prctl.h>
15#include <unistd.h> 16#include <unistd.h>
16 17
18#include "Buffer.h"
17#include "Child.h" 19#include "Child.h"
20#include "DynBuf.h"
18#include "Fifo.h" 21#include "Fifo.h"
19#include "Logging.h" 22#include "Logging.h"
23#include "Proc.h"
20#include "Sender.h" 24#include "Sender.h"
21#include "SessionData.h" 25#include "SessionData.h"
22 26
23extern Child *child; 27extern Child *child;
24 28
25DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mFifo(NULL), mSenderSem(senderSem), mStartProfile(startProfile), mBufferSize(0), mBufferFD(0), mLength(1) { 29DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL), mFifo(NULL), mSenderSem(senderSem), mStartProfile(startProfile), mBufferSize(0), mBufferFD(0), mLength(1) {
26 int driver_version = 0; 30 int driver_version = 0;
27 31
32 mBuffer = new Buffer(0, FRAME_PERF_ATTRS, 4*1024*1024, senderSem);
28 if (readIntDriver("/dev/gator/version", &driver_version) == -1) { 33 if (readIntDriver("/dev/gator/version", &driver_version) == -1) {
29 logg->logError(__FILE__, __LINE__, "Error reading gator driver version"); 34 logg->logError(__FILE__, __LINE__, "Error reading gator driver version");
30 handleException(); 35 handleException();
@@ -43,7 +48,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mFifo(NULL),
43 handleException(); 48 handleException();
44 } else { 49 } else {
45 // Release version mismatch 50 // Release version mismatch
46 logg->logError(__FILE__, __LINE__, 51 logg->logError(__FILE__, __LINE__,
47 "gator driver version \"%d\" is different than gator daemon version \"%d\".\n" 52 "gator driver version \"%d\" is different than gator daemon version \"%d\".\n"
48 ">> Please upgrade the driver and daemon to the latest versions.", driver_version, PROTOCOL_VERSION); 53 ">> Please upgrade the driver and daemon to the latest versions.", driver_version, PROTOCOL_VERSION);
49 handleException(); 54 handleException();
@@ -87,6 +92,28 @@ bool DriverSource::prepare() {
87 return true; 92 return true;
88} 93}
89 94
95void DriverSource::bootstrapThread() {
96 prctl(PR_SET_NAME, (unsigned long)&"gatord-bootstrap", 0, 0, 0);
97
98 DynBuf printb;
99 DynBuf b1;
100 DynBuf b2;
101 DynBuf b3;
102
103 if (!readProc(mBuffer, false, &printb, &b1, &b2, &b3)) {
104 logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__);
105 handleException();
106 }
107
108 mBuffer->commit(1);
109 mBuffer->setDone();
110}
111
112void *DriverSource::bootstrapThreadStatic(void *arg) {
113 static_cast<DriverSource *>(arg)->bootstrapThread();
114 return NULL;
115}
116
90void DriverSource::run() { 117void DriverSource::run() {
91 // Get the initial pointer to the collect buffer 118 // Get the initial pointer to the collect buffer
92 char *collectBuffer = mFifo->start(); 119 char *collectBuffer = mFifo->start();
@@ -138,6 +165,12 @@ void DriverSource::run() {
138 165
139 sem_post(mStartProfile); 166 sem_post(mStartProfile);
140 167
168 pthread_t bootstrapThreadID;
169 if (pthread_create(&bootstrapThreadID, NULL, bootstrapThreadStatic, this) != 0) {
170 logg->logError(__FILE__, __LINE__, "Unable to start the gator_bootstrap thread");
171 handleException();
172 }
173
141 // Collect Data 174 // Collect Data
142 do { 175 do {
143 // This command will stall until data is received from the driver 176 // This command will stall until data is received from the driver
@@ -164,6 +197,8 @@ void DriverSource::run() {
164 } while (bytesCollected > 0); 197 } while (bytesCollected > 0);
165 198
166 logg->logMessage("Exit collect data loop"); 199 logg->logMessage("Exit collect data loop");
200
201 pthread_join(bootstrapThreadID, NULL);
167} 202}
168 203
169void DriverSource::interrupt() { 204void DriverSource::interrupt() {
@@ -174,7 +209,7 @@ void DriverSource::interrupt() {
174} 209}
175 210
176bool DriverSource::isDone() { 211bool DriverSource::isDone() {
177 return mLength <= 0; 212 return mLength <= 0 && (mBuffer == NULL || mBuffer->isDone());
178} 213}
179 214
180void DriverSource::write(Sender *sender) { 215void DriverSource::write(Sender *sender) {
@@ -182,6 +217,16 @@ void DriverSource::write(Sender *sender) {
182 if (data != NULL) { 217 if (data != NULL) {
183 sender->writeData(data, mLength, RESPONSE_APC_DATA); 218 sender->writeData(data, mLength, RESPONSE_APC_DATA);
184 mFifo->release(); 219 mFifo->release();
220 // Assume the summary packet is in the first block received from the driver
221 gSessionData->mSentSummary = true;
222 }
223 if (mBuffer != NULL && !mBuffer->isDone()) {
224 mBuffer->write(sender);
225 if (mBuffer->isDone()) {
226 Buffer *buf = mBuffer;
227 mBuffer = NULL;
228 delete buf;
229 }
185 } 230 }
186} 231}
187 232
@@ -227,7 +272,7 @@ int DriverSource::readInt64Driver(const char *fullpath, int64_t *value) {
227 char *endptr; 272 char *endptr;
228 errno = 0; 273 errno = 0;
229 *value = strtoll(data, &endptr, 10); 274 *value = strtoll(data, &endptr, 10);
230 if (errno != 0 || *endptr != '\n') { 275 if (errno != 0 || (*endptr != '\n' && *endptr != '\0')) {
231 logg->logMessage("Invalid value in file %s", fullpath); 276 logg->logMessage("Invalid value in file %s", fullpath);
232 return -1; 277 return -1;
233 } 278 }
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 @@
14 14
15#include "Source.h" 15#include "Source.h"
16 16
17class Buffer;
17class Fifo; 18class Fifo;
18 19
19class DriverSource : public Source { 20class DriverSource : public Source {
@@ -37,6 +38,10 @@ public:
37 static int writeReadDriver(const char *path, int64_t *value); 38 static int writeReadDriver(const char *path, int64_t *value);
38 39
39private: 40private:
41 static void *bootstrapThreadStatic(void *arg);
42 void bootstrapThread();
43
44 Buffer *mBuffer;
40 Fifo *mFifo; 45 Fifo *mFifo;
41 sem_t *const mSenderSem; 46 sem_t *const mSenderSem;
42 sem_t *const mStartProfile; 47 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 @@
13#include "OlyUtility.h" 13#include "OlyUtility.h"
14#include "SessionData.h" 14#include "SessionData.h"
15 15
16char* EventsXML::getXML() { 16mxml_node_t *EventsXML::getTree() {
17#include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len 17#include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len
18 char path[PATH_MAX]; 18 char path[PATH_MAX];
19 mxml_node_t *xml; 19 mxml_node_t *xml;
@@ -38,6 +38,12 @@ char* EventsXML::getXML() {
38 xml = mxmlLoadString(NULL, (const char *)events_xml, MXML_NO_CALLBACK); 38 xml = mxmlLoadString(NULL, (const char *)events_xml, MXML_NO_CALLBACK);
39 } 39 }
40 40
41 return xml;
42}
43
44char *EventsXML::getXML() {
45 mxml_node_t *xml = getTree();
46
41 // Add dynamic events from the drivers 47 // Add dynamic events from the drivers
42 mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND); 48 mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND);
43 if (!events) { 49 if (!events) {
@@ -48,19 +54,19 @@ char* EventsXML::getXML() {
48 driver->writeEvents(events); 54 driver->writeEvents(events);
49 } 55 }
50 56
51 char* string = mxmlSaveAllocString(xml, mxmlWhitespaceCB); 57 char *string = mxmlSaveAllocString(xml, mxmlWhitespaceCB);
52 mxmlDelete(xml); 58 mxmlDelete(xml);
53 59
54 return string; 60 return string;
55} 61}
56 62
57void EventsXML::write(const char* path) { 63void EventsXML::write(const char *path) {
58 char file[PATH_MAX]; 64 char file[PATH_MAX];
59 65
60 // Set full path 66 // Set full path
61 snprintf(file, PATH_MAX, "%s/events.xml", path); 67 snprintf(file, PATH_MAX, "%s/events.xml", path);
62 68
63 char* buf = getXML(); 69 char *buf = getXML();
64 if (util->writeToDisk(file, buf) < 0) { 70 if (util->writeToDisk(file, buf) < 0) {
65 logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); 71 logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
66 handleException(); 72 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 @@
9#ifndef EVENTS_XML 9#ifndef EVENTS_XML
10#define EVENTS_XML 10#define EVENTS_XML
11 11
12#include "mxml/mxml.h"
13
12class EventsXML { 14class EventsXML {
13public: 15public:
14 char* getXML(); 16 mxml_node_t *getTree();
17 char *getXML();
15 void write(const char* path); 18 void write(const char* path);
16}; 19};
17 20
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 @@
8 8
9#include "ExternalSource.h" 9#include "ExternalSource.h"
10 10
11#include <fcntl.h>
11#include <sys/prctl.h> 12#include <sys/prctl.h>
13#include <unistd.h>
12 14
13#include "Logging.h" 15#include "Logging.h"
14#include "OlySocket.h" 16#include "OlySocket.h"
15#include "SessionData.h" 17#include "SessionData.h"
16 18
17ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 1024, senderSem), mSock("/tmp/gator") { 19static const char MALI_VIDEO[] = "\0mali-video";
20static const char MALI_VIDEO_STARTUP[] = "\0mali-video-startup";
21static const char MALI_VIDEO_V1[] = "MALI_VIDEO 1\n";
22
23static bool setNonblock(const int fd) {
24 int flags;
25
26 flags = fcntl(fd, F_GETFL);
27 if (flags < 0) {
28 logg->logMessage("fcntl getfl failed");
29 return false;
30 }
31
32 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) {
33 logg->logMessage("fcntl setfl failed");
34 return false;
35 }
36
37 return true;
38}
39
40ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 128*1024, senderSem), mMonitor(), mMveStartupUds(MALI_VIDEO_STARTUP, sizeof(MALI_VIDEO_STARTUP)), mInterruptFd(-1), mMveUds(-1) {
41 sem_init(&mBufferSem, 0, 0);
18} 42}
19 43
20ExternalSource::~ExternalSource() { 44ExternalSource::~ExternalSource() {
21} 45}
22 46
47void ExternalSource::waitFor(const uint64_t currTime, const int bytes) {
48 while (mBuffer.bytesAvailable() <= bytes) {
49 mBuffer.check(currTime);
50 sem_wait(&mBufferSem);
51 }
52}
53
54void ExternalSource::configureConnection(const int fd, const char *const handshake, size_t size) {
55 if (!setNonblock(fd)) {
56 logg->logError(__FILE__, __LINE__, "Unable to set nonblock on fh");
57 handleException();
58 }
59
60 if (!mMonitor.add(fd)) {
61 logg->logError(__FILE__, __LINE__, "Unable to add fh to monitor");
62 handleException();
63 }
64
65 // Write the handshake to the circular buffer
66 waitFor(1, Buffer::MAXSIZE_PACK32 + 4 + size - 1);
67 mBuffer.packInt(fd);
68 mBuffer.writeLEInt((unsigned char *)mBuffer.getWritePos(), size - 1);
69 mBuffer.advanceWrite(4);
70 mBuffer.writeBytes(handshake, size - 1);
71}
72
73bool ExternalSource::connectMve() {
74 if (!gSessionData->maliVideo.countersEnabled()) {
75 return true;
76 }
77
78 mMveUds = OlySocket::connect(MALI_VIDEO, sizeof(MALI_VIDEO));
79 if (mMveUds < 0) {
80 return false;
81 }
82
83 if (!gSessionData->maliVideo.start(mMveUds)) {
84 return false;
85 }
86
87 configureConnection(mMveUds, MALI_VIDEO_V1, sizeof(MALI_VIDEO_V1));
88
89 return true;
90}
91
23bool ExternalSource::prepare() { 92bool ExternalSource::prepare() {
93 if (!mMonitor.init() || !setNonblock(mMveStartupUds.getFd()) || !mMonitor.add(mMveStartupUds.getFd())) {
94 return false;
95 }
96
97 connectMve();
98
24 return true; 99 return true;
25} 100}
26 101
27void ExternalSource::run() { 102void ExternalSource::run() {
28 prctl(PR_SET_NAME, (unsigned long)&"gatord-uds", 0, 0, 0); 103 int pipefd[2];
104
105 prctl(PR_SET_NAME, (unsigned long)&"gatord-external", 0, 0, 0);
106
107 if (pipe(pipefd) != 0) {
108 logg->logError(__FILE__, __LINE__, "pipe failed");
109 handleException();
110 }
111 mInterruptFd = pipefd[1];
112
113 if (!mMonitor.add(pipefd[0])) {
114 logg->logError(__FILE__, __LINE__, "Monitor::add failed");
115 handleException();
116 }
29 117
30 while (gSessionData->mSessionIsActive) { 118 while (gSessionData->mSessionIsActive) {
31 // Will be aborted when the socket is closed at the end of the capture 119 struct epoll_event events[16];
32 int length = mSock.receive(mBuffer.getWritePos(), mBuffer.contiguousSpaceAvailable()); 120 // Clear any pending sem posts
33 if (length <= 0) { 121 while (sem_trywait(&mBufferSem) == 0);
34 break; 122 int ready = mMonitor.wait(events, ARRAY_LENGTH(events), -1);
123 if (ready < 0) {
124 logg->logError(__FILE__, __LINE__, "Monitor::wait failed");
125 handleException();
35 } 126 }
36 127
37 mBuffer.advanceWrite(length); 128 const uint64_t currTime = getTime();
38 mBuffer.check(0); 129
130 for (int i = 0; i < ready; ++i) {
131 const int fd = events[i].data.fd;
132 if (fd == mMveStartupUds.getFd()) {
133 // Mali Video Engine says it's alive
134 int client = mMveStartupUds.acceptConnection();
135 // Don't read from this connection, establish a new connection to Mali-V500
136 close(client);
137 if (!connectMve()) {
138 logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali video connection");
139 handleException();
140 }
141 } else if (fd == pipefd[0]) {
142 // Means interrupt has been called and mSessionIsActive should be reread
143 } else {
144 while (true) {
145 waitFor(currTime, Buffer::MAXSIZE_PACK32 + 4);
146
147 mBuffer.packInt(fd);
148 char *const bytesPos = mBuffer.getWritePos();
149 mBuffer.advanceWrite(4);
150 const int contiguous = mBuffer.contiguousSpaceAvailable();
151 const int bytes = read(fd, mBuffer.getWritePos(), contiguous);
152 if (bytes < 0) {
153 if (errno == EAGAIN) {
154 // Nothing left to read, and Buffer convention dictates that writePos can't go backwards
155 mBuffer.writeLEInt((unsigned char *)bytesPos, 0);
156 break;
157 }
158 // Something else failed, close the socket
159 mBuffer.writeLEInt((unsigned char *)bytesPos, -1);
160 close(fd);
161 break;
162 } else if (bytes == 0) {
163 // The other side is closed
164 mBuffer.writeLEInt((unsigned char *)bytesPos, -1);
165 close(fd);
166 break;
167 }
168
169 mBuffer.writeLEInt((unsigned char *)bytesPos, bytes);
170 mBuffer.advanceWrite(bytes);
171
172 // Short reads also mean nothing is left to read
173 if (bytes < contiguous) {
174 break;
175 }
176 }
177 }
178 }
179
180 // Only call mBufferCheck once per iteration
181 mBuffer.check(currTime);
39 } 182 }
40 183
41 mBuffer.setDone(); 184 mBuffer.setDone();
185
186 mInterruptFd = -1;
187 close(pipefd[0]);
188 close(pipefd[1]);
42} 189}
43 190
44void ExternalSource::interrupt() { 191void ExternalSource::interrupt() {
45 // Do nothing 192 if (mInterruptFd >= 0) {
193 int8_t c = 0;
194 // Write to the pipe to wake the monitor which will cause mSessionIsActive to be reread
195 if (::write(mInterruptFd, &c, sizeof(c)) != sizeof(c)) {
196 logg->logError(__FILE__, __LINE__, "write failed");
197 handleException();
198 }
199 }
46} 200}
47 201
48bool ExternalSource::isDone() { 202bool ExternalSource::isDone() {
@@ -50,7 +204,12 @@ bool ExternalSource::isDone() {
50} 204}
51 205
52void ExternalSource::write(Sender *sender) { 206void ExternalSource::write(Sender *sender) {
207 // Don't send external data until the summary packet is sent so that monotonic delta is available
208 if (!gSessionData->mSentSummary) {
209 return;
210 }
53 if (!mBuffer.isDone()) { 211 if (!mBuffer.isDone()) {
54 mBuffer.write(sender); 212 mBuffer.write(sender);
213 sem_post(&mBufferSem);
55 } 214 }
56} 215}
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 @@
12#include <semaphore.h> 12#include <semaphore.h>
13 13
14#include "Buffer.h" 14#include "Buffer.h"
15#include "Monitor.h"
15#include "OlySocket.h" 16#include "OlySocket.h"
16#include "Source.h" 17#include "Source.h"
17 18
@@ -29,8 +30,16 @@ public:
29 void write(Sender *sender); 30 void write(Sender *sender);
30 31
31private: 32private:
33 void waitFor(const uint64_t currTime, const int bytes);
34 void configureConnection(const int fd, const char *const handshake, size_t size);
35 bool connectMve();
36
37 sem_t mBufferSem;
32 Buffer mBuffer; 38 Buffer mBuffer;
33 OlySocket mSock; 39 Monitor mMonitor;
40 OlyServerSocket mMveStartupUds;
41 int mInterruptFd;
42 int mMveUds;
34 43
35 // Intentionally unimplemented 44 // Intentionally unimplemented
36 ExternalSource(const ExternalSource &); 45 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 @@
1/**
2 * Copyright (C) ARM Limited 2014. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include "FSDriver.h"
10
11#include <fcntl.h>
12#include <regex.h>
13#include <sys/stat.h>
14#include <sys/types.h>
15#include <unistd.h>
16
17#include "Buffer.h"
18#include "Counter.h"
19#include "DriverSource.h"
20#include "Logging.h"
21#include "SessionData.h"
22
23class FSCounter {
24public:
25 FSCounter(FSCounter *next, char *name, const char *regex);
26 ~FSCounter();
27
28 FSCounter *getNext() const { return next; }
29 int getKey() const { return key; }
30 bool isEnabled() const { return enabled; }
31 void setEnabled(const bool enabled) { this->enabled = enabled; }
32 const char *getName() const { return name; }
33 int64_t read();
34
35private:
36 FSCounter *const next;
37 regex_t reg;
38 char *name;
39 const int key;
40 int enabled : 1,
41 useRegex : 1;
42
43 // Intentionally unimplemented
44 FSCounter(const FSCounter &);
45 FSCounter &operator=(const FSCounter &);
46};
47
48FSCounter::FSCounter(FSCounter *next, char *name, const char *regex) : next(next), name(name), key(getEventKey()), enabled(false), useRegex(regex != NULL) {
49 if (useRegex) {
50 int result = regcomp(&reg, regex, REG_EXTENDED);
51 if (result != 0) {
52 char buf[128];
53 regerror(result, &reg, buf, sizeof(buf));
54 logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf);
55 handleException();
56 }
57 }
58}
59
60FSCounter::~FSCounter() {
61 free(name);
62 if (useRegex) {
63 regfree(&reg);
64 }
65}
66
67int64_t FSCounter::read() {
68 int64_t value;
69 if (useRegex) {
70 char buf[4096];
71 size_t pos = 0;
72 const int fd = open(name, O_RDONLY);
73 if (fd < 0) {
74 goto fail;
75 }
76 while (pos < sizeof(buf) - 1) {
77 const ssize_t bytes = ::read(fd, buf + pos, sizeof(buf) - pos - 1);
78 if (bytes < 0) {
79 goto fail;
80 } else if (bytes == 0) {
81 break;
82 }
83 pos += bytes;
84 }
85 close(fd);
86 buf[pos] = '\0';
87
88 regmatch_t match[2];
89 int result = regexec(&reg, buf, 2, match, 0);
90 if (result != 0) {
91 regerror(result, &reg, buf, sizeof(buf));
92 logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, buf);
93 handleException();
94 }
95
96 if (match[1].rm_so < 0) {
97 logg->logError(__FILE__, __LINE__, "Parsing %s failed", name);
98 handleException();
99 }
100 char *endptr;
101 errno = 0;
102 value = strtoll(buf + match[1].rm_so, &endptr, 0);
103 if (errno != 0) {
104 logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, strerror(errno));
105 handleException();
106 }
107 } else {
108 if (DriverSource::readInt64Driver(name, &value) != 0) {
109 goto fail;
110 }
111 }
112 return value;
113
114 fail:
115 logg->logError(__FILE__, __LINE__, "Unable to read %s", name);
116 handleException();
117}
118
119FSDriver::FSDriver() : counters(NULL) {
120}
121
122FSDriver::~FSDriver() {
123 while (counters != NULL) {
124 FSCounter * counter = counters;
125 counters = counter->getNext();
126 delete counter;
127 }
128}
129
130void FSDriver::setup(mxml_node_t *const xml) {
131 // fs driver does not currently work with perf
132 if (gSessionData->perf.isSetup()) {
133 return;
134 }
135
136 mxml_node_t *node = xml;
137 while (true) {
138 node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
139 if (node == NULL) {
140 break;
141 }
142 const char *counter = mxmlElementGetAttr(node, "counter");
143 if ((counter != NULL) && (counter[0] == '/')) {
144 const char *regex = mxmlElementGetAttr(node, "regex");
145 counters = new FSCounter(counters, strdup(counter), regex);
146 }
147 }
148}
149
150FSCounter *FSDriver::findCounter(const Counter &counter) const {
151 for (FSCounter * fsCounter = counters; fsCounter != NULL; fsCounter = fsCounter->getNext()) {
152 if (strcmp(fsCounter->getName(), counter.getType()) == 0) {
153 return fsCounter;
154 }
155 }
156
157 return NULL;
158}
159
160bool FSDriver::claimCounter(const Counter &counter) const {
161 return findCounter(counter) != NULL;
162}
163
164bool FSDriver::countersEnabled() const {
165 for (FSCounter *counter = counters; counter != NULL; counter = counter->getNext()) {
166 if (counter->isEnabled()) {
167 return true;
168 }
169 }
170 return false;
171}
172
173void FSDriver::resetCounters() {
174 for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
175 counter->setEnabled(false);
176 }
177}
178
179void FSDriver::setupCounter(Counter &counter) {
180 FSCounter *const fsCounter = findCounter(counter);
181 if (fsCounter == NULL) {
182 counter.setEnabled(false);
183 return;
184 }
185 fsCounter->setEnabled(true);
186 counter.setKey(fsCounter->getKey());
187}
188
189int FSDriver::writeCounters(mxml_node_t *root) const {
190 int count = 0;
191 for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
192 if (access(counter->getName(), R_OK) == 0) {
193 mxml_node_t *node = mxmlNewElement(root, "counter");
194 mxmlElementSetAttr(node, "name", counter->getName());
195 ++count;
196 }
197 }
198
199 return count;
200}
201
202void FSDriver::start() {
203}
204
205void FSDriver::read(Buffer * const buffer) {
206 for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
207 if (!counter->isEnabled()) {
208 continue;
209 }
210 buffer->event(counter->getKey(), counter->read());
211 }
212}
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 @@
1/**
2 * Copyright (C) ARM Limited 2014. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef FSDRIVER_H
10#define FSDRIVER_H
11
12#include "Driver.h"
13
14class Buffer;
15class FSCounter;
16
17class FSDriver : public Driver {
18public:
19 FSDriver();
20 ~FSDriver();
21
22 void setup(mxml_node_t *const xml);
23
24 bool claimCounter(const Counter &counter) const;
25 bool countersEnabled() const;
26 void resetCounters();
27 void setupCounter(Counter &counter);
28
29 int writeCounters(mxml_node_t *root) const;
30
31 void start();
32 void read(Buffer * buffer);
33
34private:
35 FSCounter *findCounter(const Counter &counter) const;
36
37 FSCounter *counters;
38
39 // Intentionally unimplemented
40 FSDriver(const FSDriver &);
41 FSDriver &operator=(const FSDriver &);
42};
43
44#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:
45 Fifo &operator=(const Fifo &); 45 Fifo &operator=(const Fifo &);
46}; 46};
47 47
48#endif //__FIFO_H__ 48#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:
28 const char *getTitle() const { return title; } 28 const char *getTitle() const { return title; }
29 bool isDuplicate() const { return duplicate; } 29 bool isDuplicate() const { return duplicate; }
30 const char *getDisplay() const { return display; } 30 const char *getDisplay() const { return display; }
31 const char *getCounterClass() const { return counter_class; }
31 const char *getUnit() const { return unit; } 32 const char *getUnit() const { return unit; }
32 int getModifier() const { return modifier; } 33 int getModifier() const { return modifier; }
33 34
@@ -58,6 +59,7 @@ private:
58 char *label; 59 char *label;
59 const char *title; 60 const char *title;
60 const char *display; 61 const char *display;
62 const char *counter_class;
61 const char *unit; 63 const char *unit;
62 int modifier; 64 int modifier;
63 double previous_value; 65 double previous_value;
@@ -87,7 +89,8 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
87 case SENSORS_FEATURE_IN: 89 case SENSORS_FEATURE_IN:
88 title = "Voltage"; 90 title = "Voltage";
89 input = SENSORS_SUBFEATURE_IN_INPUT; 91 input = SENSORS_SUBFEATURE_IN_INPUT;
90 display = "average"; 92 display = "maximum";
93 counter_class = "absolute";
91 unit = "V"; 94 unit = "V";
92 modifier = 1000; 95 modifier = 1000;
93 monotonic = false; 96 monotonic = false;
@@ -96,6 +99,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
96 title = "Fan"; 99 title = "Fan";
97 input = SENSORS_SUBFEATURE_FAN_INPUT; 100 input = SENSORS_SUBFEATURE_FAN_INPUT;
98 display = "average"; 101 display = "average";
102 counter_class = "absolute";
99 unit = "RPM"; 103 unit = "RPM";
100 modifier = 1; 104 modifier = 1;
101 monotonic = false; 105 monotonic = false;
@@ -104,6 +108,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
104 title = "Temperature"; 108 title = "Temperature";
105 input = SENSORS_SUBFEATURE_TEMP_INPUT; 109 input = SENSORS_SUBFEATURE_TEMP_INPUT;
106 display = "maximum"; 110 display = "maximum";
111 counter_class = "absolute";
107 unit = "°C"; 112 unit = "°C";
108 modifier = 1000; 113 modifier = 1000;
109 monotonic = false; 114 monotonic = false;
@@ -111,7 +116,8 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
111 case SENSORS_FEATURE_POWER: 116 case SENSORS_FEATURE_POWER:
112 title = "Power"; 117 title = "Power";
113 input = SENSORS_SUBFEATURE_POWER_INPUT; 118 input = SENSORS_SUBFEATURE_POWER_INPUT;
114 display = "average"; 119 display = "maximum";
120 counter_class = "absolute";
115 unit = "W"; 121 unit = "W";
116 modifier = 1000000; 122 modifier = 1000000;
117 monotonic = false; 123 monotonic = false;
@@ -120,6 +126,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
120 title = "Energy"; 126 title = "Energy";
121 input = SENSORS_SUBFEATURE_ENERGY_INPUT; 127 input = SENSORS_SUBFEATURE_ENERGY_INPUT;
122 display = "accumulate"; 128 display = "accumulate";
129 counter_class = "delta";
123 unit = "J"; 130 unit = "J";
124 modifier = 1000000; 131 modifier = 1000000;
125 monotonic = true; 132 monotonic = true;
@@ -127,7 +134,8 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
127 case SENSORS_FEATURE_CURR: 134 case SENSORS_FEATURE_CURR:
128 title = "Current"; 135 title = "Current";
129 input = SENSORS_SUBFEATURE_CURR_INPUT; 136 input = SENSORS_SUBFEATURE_CURR_INPUT;
130 display = "average"; 137 display = "maximum";
138 counter_class = "absolute";
131 unit = "A"; 139 unit = "A";
132 modifier = 1000; 140 modifier = 1000;
133 monotonic = false; 141 monotonic = false;
@@ -136,6 +144,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
136 title = "Humidity"; 144 title = "Humidity";
137 input = SENSORS_SUBFEATURE_HUMIDITY_INPUT; 145 input = SENSORS_SUBFEATURE_HUMIDITY_INPUT;
138 display = "average"; 146 display = "average";
147 counter_class = "absolute";
139 unit = "%"; 148 unit = "%";
140 modifier = 1000; 149 modifier = 1000;
141 monotonic = false; 150 monotonic = false;
@@ -311,6 +320,7 @@ void Hwmon::writeEvents(mxml_node_t *root) const {
311 mxmlElementSetAttr(node, "name", counter->getLabel()); 320 mxmlElementSetAttr(node, "name", counter->getLabel());
312 } 321 }
313 mxmlElementSetAttr(node, "display", counter->getDisplay()); 322 mxmlElementSetAttr(node, "display", counter->getDisplay());
323 mxmlElementSetAttr(node, "class", counter->getCounterClass());
314 mxmlElementSetAttr(node, "units", counter->getUnit()); 324 mxmlElementSetAttr(node, "units", counter->getUnit());
315 if (counter->getModifier() != 1) { 325 if (counter->getModifier() != 1) {
316 mxmlElementSetAttrf(node, "modifier", "%d", counter->getModifier()); 326 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) {
58 return; 58 return;
59 } 59 }
60 60
61 int value = 0;
61 snprintf(text, sizeof(text), "%s/key", base); 62 snprintf(text, sizeof(text), "%s/key", base);
62 int key = 0; 63 DriverSource::readIntDriver(text, &value);
63 DriverSource::readIntDriver(text, &key); 64 counter.setKey(value);
64 counter.setKey(key); 65
66 snprintf(text, sizeof(text), "%s/cores", base);
67 if (DriverSource::readIntDriver(text, &value) == 0) {
68 counter.setCores(value);
69 }
65 70
66 snprintf(text, sizeof(text), "%s/event", base); 71 snprintf(text, sizeof(text), "%s/event", base);
67 DriverSource::writeDriver(text, counter.getEvent()); 72 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:
23 int removeDirAndAllContents(char* path); 23 int removeDirAndAllContents(char* path);
24}; 24};
25 25
26#endif //__LOCAL_CAPTURE_H__ 26#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;
33 33
34extern void handleException() __attribute__ ((noreturn)); 34extern void handleException() __attribute__ ((noreturn));
35 35
36#endif //__LOGGING_H__ 36#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 @@
8# targets run 'make SOFTFLOAT=1 SYSROOT=/path/to/sysroot', see 8# targets run 'make SOFTFLOAT=1 SYSROOT=/path/to/sysroot', see
9# README_Streamline.txt for more details 9# README_Streamline.txt for more details
10 10
11CPP = $(CROSS_COMPILE)g++ 11CC = $(CROSS_COMPILE)gcc
12GCC = $(CROSS_COMPILE)gcc 12CXX = $(CROSS_COMPILE)g++
13 13
14# -mthumb-interwork is required for interworking to ARM or Thumb stdlibc 14# -mthumb-interwork is required for interworking to ARM or Thumb stdlibc
15CFLAGS += -mthumb-interwork 15CPPFLAGS += -mthumb-interwork
16 16
17ifeq ($(SOFTFLOAT),1) 17ifeq ($(SOFTFLOAT),1)
18 CFLAGS += -marm -march=armv4t -mfloat-abi=soft 18 CPPFLAGS += -marm -march=armv4t -mfloat-abi=soft
19 LDFLAGS += -marm -march=armv4t -mfloat-abi=soft 19 LDFLAGS += -marm -march=armv4t -mfloat-abi=soft
20endif 20endif
21ifneq ($(SYSROOT),) 21ifneq ($(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 @@
4# 4#
5 5
6# Uncomment and define CROSS_COMPILE if it is not already defined 6# Uncomment and define CROSS_COMPILE if it is not already defined
7# CROSS_COMPILE=/path/to/cross-compiler/arm-linux-gnueabihf- 7# CROSS_COMPILE=/path/to/cross-compiler/aarch64-linux-gnu-
8# NOTE: This toolchain uses the hardfloat abi by default. For non-hardfloat
9# targets it is necessary to add options
10# '-marm -march=armv4t -mfloat-abi=soft'.
11 8
12CPP = $(CROSS_COMPILE)g++ 9CC = $(CROSS_COMPILE)gcc
13GCC = $(CROSS_COMPILE)gcc 10CXX = $(CROSS_COMPILE)g++
14 11
15include common.mk 12include 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 @@
1/**
2 * Copyright (C) ARM Limited 2014. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include "MaliVideoDriver.h"
10
11#include <unistd.h>
12
13#include "Buffer.h"
14#include "Counter.h"
15#include "Logging.h"
16#include "SessionData.h"
17
18// From instr/src/mve_instr_comm_protocol.h
19typedef enum mve_instr_configuration_type {
20 MVE_INSTR_RAW = 1 << 0,
21 MVE_INSTR_COUNTERS = 1 << 1,
22 MVE_INSTR_EVENTS = 1 << 2,
23 MVE_INSTR_ACTIVITIES = 1 << 3,
24
25 // Raw always pushed regardless
26 MVE_INSTR_PULL = 1 << 12,
27 // Raw always unpacked regardless
28 MVE_INSTR_PACKED_COMM = 1 << 13,
29 // Don’t send ACKt response
30 MVE_INSTR_NO_AUTO_ACK = 1 << 14,
31} mve_instr_configuration_type_t;
32
33static const char COUNTER[] = "ARM_Mali-V500_cnt";
34static const char EVENT[] = "ARM_Mali-V500_evn";
35static const char ACTIVITY[] = "ARM_Mali-V500_act";
36
37class MaliVideoCounter {
38public:
39 MaliVideoCounter(MaliVideoCounter *next, const char *name, const MaliVideoCounterType type, const int id) : mNext(next), mName(name), mType(type), mId(id), mKey(getEventKey()), mEnabled(false) {
40 }
41
42 ~MaliVideoCounter() {
43 delete mName;
44 }
45
46 MaliVideoCounter *getNext() const { return mNext; }
47 const char *getName() const { return mName; }
48 MaliVideoCounterType getType() const { return mType; }
49 int getId() const { return mId; }
50 int getKey() const { return mKey; }
51 bool isEnabled() const { return mEnabled; }
52 void setEnabled(const bool enabled) { mEnabled = enabled; }
53
54private:
55 MaliVideoCounter *const mNext;
56 const char *const mName;
57 const MaliVideoCounterType mType;
58 // Mali Video id
59 const int mId;
60 // Streamline key
61 const int mKey;
62 bool mEnabled;
63};
64
65MaliVideoDriver::MaliVideoDriver() : mCounters(NULL), mActivityCount(0) {
66}
67
68MaliVideoDriver::~MaliVideoDriver() {
69 while (mCounters != NULL) {
70 MaliVideoCounter *counter = mCounters;
71 mCounters = counter->getNext();
72 delete counter;
73 }
74}
75
76void MaliVideoDriver::setup(mxml_node_t *const xml) {
77 // hwmon does not currently work with perf
78 if (gSessionData->perf.isSetup()) {
79 return;
80 }
81
82 mxml_node_t *node = xml;
83 while (true) {
84 node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
85 if (node == NULL) {
86 break;
87 }
88 const char *counter = mxmlElementGetAttr(node, "counter");
89 if (counter == NULL) {
90 // Ignore
91 } else if (strncmp(counter, COUNTER, sizeof(COUNTER) - 1) == 0) {
92 const int i = strtol(counter + sizeof(COUNTER) - 1, NULL, 10);
93 mCounters = new MaliVideoCounter(mCounters, strdup(counter), MVCT_COUNTER, i);
94 } else if (strncmp(counter, EVENT, sizeof(EVENT) - 1) == 0) {
95 const int i = strtol(counter + sizeof(EVENT) - 1, NULL, 10);
96 mCounters = new MaliVideoCounter(mCounters, strdup(counter), MVCT_EVENT, i);
97 } else if (strcmp(counter, ACTIVITY) == 0) {
98 mCounters = new MaliVideoCounter(mCounters, strdup(ACTIVITY), MVCT_ACTIVITY, 0);
99 mActivityCount = 0;
100 while (true) {
101 char buf[32];
102 snprintf(buf, sizeof(buf), "activity%i", mActivityCount + 1);
103 if (mxmlElementGetAttr(node, buf) == NULL) {
104 break;
105 }
106 ++mActivityCount;
107 }
108 }
109 }
110}
111
112MaliVideoCounter *MaliVideoDriver::findCounter(const Counter &counter) const {
113 for (MaliVideoCounter *maliVideoCounter = mCounters; maliVideoCounter != NULL; maliVideoCounter = maliVideoCounter->getNext()) {
114 if (strcmp(maliVideoCounter->getName(), counter.getType()) == 0) {
115 return maliVideoCounter;
116 }
117 }
118
119 return NULL;
120}
121
122bool MaliVideoDriver::claimCounter(const Counter &counter) const {
123 return findCounter(counter) != NULL;
124}
125
126bool MaliVideoDriver::countersEnabled() const {
127 for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
128 if (counter->isEnabled()) {
129 return true;
130 }
131 }
132 return false;
133}
134
135void MaliVideoDriver::resetCounters() {
136 for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
137 counter->setEnabled(false);
138 }
139}
140
141void MaliVideoDriver::setupCounter(Counter &counter) {
142 MaliVideoCounter *const maliVideoCounter = findCounter(counter);
143 if (maliVideoCounter == NULL) {
144 counter.setEnabled(false);
145 return;
146 }
147 maliVideoCounter->setEnabled(true);
148 counter.setKey(maliVideoCounter->getKey());
149}
150
151int MaliVideoDriver::writeCounters(mxml_node_t *root) const {
152 if (access("/dev/mv500", F_OK) != 0) {
153 return 0;
154 }
155
156 int count = 0;
157 for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
158 mxml_node_t *node = mxmlNewElement(root, "counter");
159 mxmlElementSetAttr(node, "name", counter->getName());
160 ++count;
161 }
162
163 return count;
164}
165
166void MaliVideoDriver::marshalEnable(const MaliVideoCounterType type, char *const buf, const size_t bufsize, int &pos) {
167 // size
168 int numEnabled = 0;
169 for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
170 if (counter->isEnabled() && (counter->getType() == type)) {
171 ++numEnabled;
172 }
173 }
174 Buffer::packInt(buf, bufsize, pos, numEnabled*sizeof(uint32_t));
175 for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
176 if (counter->isEnabled() && (counter->getType() == type)) {
177 Buffer::packInt(buf, bufsize, pos, counter->getId());
178 }
179 }
180}
181
182bool MaliVideoDriver::start(const int mveUds) {
183 char buf[256];
184 int pos = 0;
185
186 // code - MVE_INSTR_STARTUP
187 buf[pos++] = 'C';
188 buf[pos++] = 'L';
189 buf[pos++] = 'N';
190 buf[pos++] = 'T';
191 // size
192 Buffer::packInt(buf, sizeof(buf), pos, sizeof(uint32_t));
193 // client_version_number
194 Buffer::packInt(buf, sizeof(buf), pos, 1);
195
196 // code - MVE_INSTR_CONFIGURE
197 buf[pos++] = 'C';
198 buf[pos++] = 'N';
199 buf[pos++] = 'F';
200 buf[pos++] = 'G';
201 // size
202 Buffer::packInt(buf, sizeof(buf), pos, 5*sizeof(uint32_t));
203 // configuration
204 Buffer::packInt(buf, sizeof(buf), pos, MVE_INSTR_COUNTERS | MVE_INSTR_EVENTS | MVE_INSTR_ACTIVITIES | MVE_INSTR_PACKED_COMM);
205 // communication_protocol_version
206 Buffer::packInt(buf, sizeof(buf), pos, 1);
207 // data_protocol_version
208 Buffer::packInt(buf, sizeof(buf), pos, 1);
209 // sample_rate - convert samples/second to ms/sample
210 Buffer::packInt(buf, sizeof(buf), pos, 1000/gSessionData->mSampleRate);
211 // live_rate - convert ns/flush to ms/flush
212 Buffer::packInt(buf, sizeof(buf), pos, gSessionData->mLiveRate/1000000);
213
214 // code - MVE_INSTR_ENABLE_COUNTERS
215 buf[pos++] = 'C';
216 buf[pos++] = 'F';
217 buf[pos++] = 'G';
218 buf[pos++] = 'c';
219 marshalEnable(MVCT_COUNTER, buf, sizeof(buf), pos);
220
221 // code - MVE_INSTR_ENABLE_EVENTS
222 buf[pos++] = 'C';
223 buf[pos++] = 'F';
224 buf[pos++] = 'G';
225 buf[pos++] = 'e';
226 marshalEnable(MVCT_EVENT, buf, sizeof(buf), pos);
227
228 /*
229 // code - MVE_INSTR_ENABLE_ACTIVITIES
230 buf[pos++] = 'C';
231 buf[pos++] = 'F';
232 buf[pos++] = 'G';
233 buf[pos++] = 'a';
234 // size
235 Buffer::packInt(buf, sizeof(buf), pos, mActivityCount*sizeof(uint32_t));
236 for (int i = 0; i < mActivityCount; ++i) {
237 // activity_id
238 Buffer::packInt(buf, sizeof(buf), pos, i);
239 }
240 */
241
242 int written = 0;
243 while (written < pos) {
244 size_t bytes = ::write(mveUds, buf + written, pos - written);
245 if (bytes <= 0) {
246 logg->logMessage("%s(%s:%i): write failed", __FUNCTION__, __FILE__, __LINE__);
247 return false;
248 }
249 written += bytes;
250 }
251
252 return true;
253}
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 @@
1/**
2 * Copyright (C) ARM Limited 2014. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef MALIVIDEODRIVER_H
10#define MALIVIDEODRIVER_H
11
12#include "Driver.h"
13
14class MaliVideoCounter;
15
16enum MaliVideoCounterType {
17 MVCT_COUNTER,
18 MVCT_EVENT,
19 MVCT_ACTIVITY,
20};
21
22class MaliVideoDriver : public Driver {
23public:
24 MaliVideoDriver();
25 ~MaliVideoDriver();
26
27 void setup(mxml_node_t *const xml);
28
29 bool claimCounter(const Counter &counter) const;
30 bool countersEnabled() const;
31 void resetCounters();
32 void setupCounter(Counter &counter);
33
34 int writeCounters(mxml_node_t *root) const;
35
36 bool start(const int mveUds);
37
38private:
39 MaliVideoCounter *findCounter(const Counter &counter) const;
40 void marshalEnable(const MaliVideoCounterType type, char *const buf, const size_t bufsize, int &pos);
41
42 MaliVideoCounter *mCounters;
43 int mActivityCount;
44
45 // Intentionally unimplemented
46 MaliVideoDriver(const MaliVideoDriver &);
47 MaliVideoDriver &operator=(const MaliVideoDriver &);
48};
49
50#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) {
18} 18}
19 19
20Monitor::~Monitor() { 20Monitor::~Monitor() {
21 if (mFd >= -1) { 21 if (mFd >= 0) {
22 close(mFd); 22 ::close(mFd);
23 }
24}
25
26void Monitor::close() {
27 if (mFd >= 0) {
28 ::close(mFd);
29 mFd = -1;
23 } 30 }
24} 31}
25 32
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:
16 Monitor(); 16 Monitor();
17 ~Monitor(); 17 ~Monitor();
18 18
19 void close();
19 bool init(); 20 bool init();
20 bool add(const int fd); 21 bool add(const int fd);
21 int wait(struct epoll_event *const events, int maxevents, int timeout); 22 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 @@
9#include "OlySocket.h" 9#include "OlySocket.h"
10 10
11#include <stdio.h> 11#include <stdio.h>
12#include <string.h>
12#ifdef WIN32 13#ifdef WIN32
13#include <Winsock2.h> 14#include <Winsock2.h>
14#include <ws2tcpip.h> 15#include <ws2tcpip.h>
@@ -43,16 +44,18 @@ OlyServerSocket::OlyServerSocket(int port) {
43 createServerSocket(port); 44 createServerSocket(port);
44} 45}
45 46
46OlySocket::OlySocket(int port, const char* host) {
47 createClientSocket(host, port);
48}
49
50OlySocket::OlySocket(int socketID) : mSocketID(socketID) { 47OlySocket::OlySocket(int socketID) : mSocketID(socketID) {
51} 48}
52 49
53#ifndef WIN32 50#ifndef WIN32
54 51
55OlyServerSocket::OlyServerSocket(const char* path) { 52#define MIN(A, B) ({ \
53 const __typeof__(A) __a = A; \
54 const __typeof__(B) __b = B; \
55 __a > __b ? __b : __a; \
56})
57
58OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize) {
56 // Create socket 59 // Create socket
57 mFDServer = socket(PF_UNIX, SOCK_STREAM, 0); 60 mFDServer = socket(PF_UNIX, SOCK_STREAM, 0);
58 if (mFDServer < 0) { 61 if (mFDServer < 0) {
@@ -60,13 +63,11 @@ OlyServerSocket::OlyServerSocket(const char* path) {
60 handleException(); 63 handleException();
61 } 64 }
62 65
63 unlink(path);
64
65 // Create sockaddr_in structure, ensuring non-populated fields are zero 66 // Create sockaddr_in structure, ensuring non-populated fields are zero
66 struct sockaddr_un sockaddr; 67 struct sockaddr_un sockaddr;
67 memset((void*)&sockaddr, 0, sizeof(sockaddr)); 68 memset((void*)&sockaddr, 0, sizeof(sockaddr));
68 sockaddr.sun_family = AF_UNIX; 69 sockaddr.sun_family = AF_UNIX;
69 strncpy(sockaddr.sun_path, path, sizeof(sockaddr.sun_path) - 1); 70 memcpy(sockaddr.sun_path, path, MIN(pathSize, sizeof(sockaddr.sun_path)));
70 sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0'; 71 sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0';
71 72
72 // Bind the socket to an address 73 // Bind the socket to an address
@@ -82,24 +83,25 @@ OlyServerSocket::OlyServerSocket(const char* path) {
82 } 83 }
83} 84}
84 85
85OlySocket::OlySocket(const char* path) { 86int OlySocket::connect(const char* path, const size_t pathSize) {
86 mSocketID = socket(PF_UNIX, SOCK_STREAM, 0); 87 int fd = socket(PF_UNIX, SOCK_STREAM, 0);
87 if (mSocketID < 0) { 88 if (fd < 0) {
88 return; 89 return -1;
89 } 90 }
90 91
91 // Create sockaddr_in structure, ensuring non-populated fields are zero 92 // Create sockaddr_in structure, ensuring non-populated fields are zero
92 struct sockaddr_un sockaddr; 93 struct sockaddr_un sockaddr;
93 memset((void*)&sockaddr, 0, sizeof(sockaddr)); 94 memset((void*)&sockaddr, 0, sizeof(sockaddr));
94 sockaddr.sun_family = AF_UNIX; 95 sockaddr.sun_family = AF_UNIX;
95 strncpy(sockaddr.sun_path, path, sizeof(sockaddr.sun_path) - 1); 96 memcpy(sockaddr.sun_path, path, MIN(pathSize, sizeof(sockaddr.sun_path)));
96 sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0'; 97 sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0';
97 98
98 if (connect(mSocketID, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) { 99 if (::connect(fd, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
99 close(mSocketID); 100 close(fd);
100 mSocketID = -1; 101 return -1;
101 return;
102 } 102 }
103
104 return fd;
103} 105}
104 106
105#endif 107#endif
@@ -137,47 +139,6 @@ void OlyServerSocket::closeServerSocket() {
137 mFDServer = 0; 139 mFDServer = 0;
138} 140}
139 141
140void OlySocket::createClientSocket(const char* hostname, int portno) {
141#ifdef WIN32
142 // TODO: Implement for Windows
143#else
144 char buf[32];
145 struct addrinfo hints, *res, *res0;
146
147 snprintf(buf, sizeof(buf), "%d", portno);
148 mSocketID = -1;
149 memset((void*)&hints, 0, sizeof(hints));
150 hints.ai_family = PF_UNSPEC;
151 hints.ai_socktype = SOCK_STREAM;
152
153 if (getaddrinfo(hostname, buf, &hints, &res0)) {
154 logg->logError(__FILE__, __LINE__, "Client socket failed to get address info for %s", hostname);
155 handleException();
156 }
157 for (res=res0; res!=NULL; res = res->ai_next) {
158 if ( res->ai_family != PF_INET || res->ai_socktype != SOCK_STREAM ) {
159 continue;
160 }
161 mSocketID = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
162 if (mSocketID < 0) {
163 continue;
164 }
165 if (connect(mSocketID, res->ai_addr, res->ai_addrlen) < 0) {
166 close(mSocketID);
167 mSocketID = -1;
168 }
169 if (mSocketID > 0) {
170 break;
171 }
172 }
173 freeaddrinfo(res0);
174 if (mSocketID <= 0) {
175 logg->logError(__FILE__, __LINE__, "Could not connect to client socket. Ensure ARM Streamline is running.");
176 handleException();
177 }
178#endif
179}
180
181void OlyServerSocket::createServerSocket(int port) { 142void OlyServerSocket::createServerSocket(int port) {
182 int family = AF_INET6; 143 int family = AF_INET6;
183 144
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 @@
9#ifndef __OLY_SOCKET_H__ 9#ifndef __OLY_SOCKET_H__
10#define __OLY_SOCKET_H__ 10#define __OLY_SOCKET_H__
11 11
12#include <stddef.h>
13
12class OlySocket { 14class OlySocket {
13public: 15public:
14 OlySocket(int port, const char* hostname);
15 OlySocket(int socketID);
16#ifndef WIN32 16#ifndef WIN32
17 OlySocket(const char* path); 17 static int connect(const char* path, const size_t pathSize);
18#endif 18#endif
19
20 OlySocket(int socketID);
19 ~OlySocket(); 21 ~OlySocket();
20 22
21 void closeSocket(); 23 void closeSocket();
@@ -29,21 +31,21 @@ public:
29 31
30private: 32private:
31 int mSocketID; 33 int mSocketID;
32
33 void createClientSocket(const char* hostname, int port);
34}; 34};
35 35
36class OlyServerSocket { 36class OlyServerSocket {
37public: 37public:
38 OlyServerSocket(int port); 38 OlyServerSocket(int port);
39#ifndef WIN32 39#ifndef WIN32
40 OlyServerSocket(const char* path); 40 OlyServerSocket(const char* path, const size_t pathSize);
41#endif 41#endif
42 ~OlyServerSocket(); 42 ~OlyServerSocket();
43 43
44 int acceptConnection(); 44 int acceptConnection();
45 void closeServerSocket(); 45 void closeServerSocket();
46 46
47 int getFd() { return mFDServer; }
48
47private: 49private:
48 int mFDServer; 50 int mFDServer;
49 51
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 @@
11#include <dirent.h> 11#include <dirent.h>
12#include <sys/utsname.h> 12#include <sys/utsname.h>
13#include <time.h> 13#include <time.h>
14#include <unistd.h>
14 15
15#include "Buffer.h" 16#include "Buffer.h"
16#include "Config.h" 17#include "Config.h"
@@ -30,7 +31,7 @@
30struct gator_cpu { 31struct gator_cpu {
31 const int cpuid; 32 const int cpuid;
32 // Human readable name 33 // Human readable name
33 const char core_name[32]; 34 const char *const core_name;
34 // gatorfs event and Perf PMU name 35 // gatorfs event and Perf PMU name
35 const char *const pmnc_name; 36 const char *const pmnc_name;
36 const int pmnc_counters; 37 const int pmnc_counters;
@@ -62,9 +63,20 @@ static const struct gator_cpu gator_cpus[] = {
62static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-"; 63static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-";
63static const char NEW_PMU_PREFIX[] = "ARMv7_Cortex_"; 64static const char NEW_PMU_PREFIX[] = "ARMv7_Cortex_";
64 65
66struct uncore_counter {
67 // gatorfs event and Perf PMU name
68 const char *const name;
69 const int count;
70};
71
72static const struct uncore_counter uncore_counters[] = {
73 { "CCI_400", 4 },
74 { "CCI_400-r1", 4 },
75};
76
65class PerfCounter { 77class PerfCounter {
66public: 78public:
67 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) {} 79 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) {}
68 ~PerfCounter() { 80 ~PerfCounter() {
69 delete [] mName; 81 delete [] mName;
70 } 82 }
@@ -79,6 +91,7 @@ public:
79 void setConfig(const uint64_t config) { mConfig = config; } 91 void setConfig(const uint64_t config) { mConfig = config; }
80 bool isEnabled() const { return mEnabled; } 92 bool isEnabled() const { return mEnabled; }
81 void setEnabled(const bool enabled) { mEnabled = enabled; } 93 void setEnabled(const bool enabled) { mEnabled = enabled; }
94 bool isPerCpu() const { return mPerCpu; }
82 95
83private: 96private:
84 PerfCounter *const mNext; 97 PerfCounter *const mNext;
@@ -87,10 +100,11 @@ private:
87 int mCount; 100 int mCount;
88 const int mKey; 101 const int mKey;
89 uint64_t mConfig; 102 uint64_t mConfig;
90 bool mEnabled; 103 int mEnabled : 1,
104 mPerCpu : 1;
91}; 105};
92 106
93PerfDriver::PerfDriver() : mCounters(NULL), mIsSetup(false) { 107PerfDriver::PerfDriver() : mCounters(NULL), mIsSetup(false), mLegacySupport(false) {
94} 108}
95 109
96PerfDriver::~PerfDriver() { 110PerfDriver::~PerfDriver() {
@@ -105,13 +119,27 @@ void PerfDriver::addCpuCounters(const char *const counterName, const int type, c
105 int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1; 119 int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1;
106 char *name = new char[len]; 120 char *name = new char[len];
107 snprintf(name, len, "%s_ccnt", counterName); 121 snprintf(name, len, "%s_ccnt", counterName);
108 mCounters = new PerfCounter(mCounters, name, type, -1); 122 mCounters = new PerfCounter(mCounters, name, type, -1, true);
109 123
110 for (int j = 0; j < numCounters; ++j) { 124 for (int j = 0; j < numCounters; ++j) {
111 len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1; 125 len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1;
112 name = new char[len]; 126 name = new char[len];
113 snprintf(name, len, "%s_cnt%d", counterName, j); 127 snprintf(name, len, "%s_cnt%d", counterName, j);
114 mCounters = new PerfCounter(mCounters, name, type, -1); 128 mCounters = new PerfCounter(mCounters, name, type, -1, true);
129 }
130}
131
132void PerfDriver::addUncoreCounters(const char *const counterName, const int type, const int numCounters) {
133 int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1;
134 char *name = new char[len];
135 snprintf(name, len, "%s_ccnt", counterName);
136 mCounters = new PerfCounter(mCounters, name, type, -1, false);
137
138 for (int j = 0; j < numCounters; ++j) {
139 len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1;
140 name = new char[len];
141 snprintf(name, len, "%s_cnt%d", counterName, j);
142 mCounters = new PerfCounter(mCounters, name, type, -1, false);
115 } 143 }
116} 144}
117 145
@@ -139,10 +167,16 @@ bool PerfDriver::setup() {
139 } 167 }
140 } 168 }
141 169
142 if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0)) { 170 if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 4, 0)) {
143 logg->logMessage("%s(%s:%i): Unsupported kernel version", __FUNCTION__, __FILE__, __LINE__); 171 logg->logMessage("%s(%s:%i): Unsupported kernel version", __FUNCTION__, __FILE__, __LINE__);
144 return false; 172 return false;
145 } 173 }
174 mLegacySupport = KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0);
175
176 if (access(EVENTS_PATH, R_OK) != 0) {
177 logg->logMessage("%s(%s:%i): " EVENTS_PATH " does not exist, is CONFIG_TRACING enabled?", __FUNCTION__, __FILE__, __LINE__);
178 return false;
179 }
146 180
147 // Add supported PMUs 181 // Add supported PMUs
148 bool foundCpu = false; 182 bool foundCpu = false;
@@ -174,6 +208,21 @@ bool PerfDriver::setup() {
174 foundCpu = true; 208 foundCpu = true;
175 addCpuCounters(gator_cpus[i].pmnc_name, type, gator_cpus[i].pmnc_counters); 209 addCpuCounters(gator_cpus[i].pmnc_name, type, gator_cpus[i].pmnc_counters);
176 } 210 }
211
212 for (int i = 0; i < ARRAY_LENGTH(uncore_counters); ++i) {
213 if (strcmp(dirent->d_name, uncore_counters[i].name) != 0) {
214 continue;
215 }
216
217 int type;
218 char buf[256];
219 snprintf(buf, sizeof(buf), PERF_DEVICES "/%s/type", dirent->d_name);
220 if (DriverSource::readIntDriver(buf, &type) != 0) {
221 continue;
222 }
223
224 addUncoreCounters(uncore_counters[i].name, type, uncore_counters[i].count);
225 }
177 } 226 }
178 closedir(dir); 227 closedir(dir);
179 228
@@ -203,12 +252,12 @@ bool PerfDriver::setup() {
203 252
204 id = getTracepointId("irq/softirq_exit", &printb); 253 id = getTracepointId("irq/softirq_exit", &printb);
205 if (id >= 0) { 254 if (id >= 0) {
206 mCounters = new PerfCounter(mCounters, "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id); 255 mCounters = new PerfCounter(mCounters, "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id, true);
207 } 256 }
208 257
209 id = getTracepointId("irq/irq_handler_exit", &printb); 258 id = getTracepointId("irq/irq_handler_exit", &printb);
210 if (id >= 0) { 259 if (id >= 0) {
211 mCounters = new PerfCounter(mCounters, "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id); 260 mCounters = new PerfCounter(mCounters, "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id, true);
212 } 261 }
213 262
214 //Linux_block_rq_wr 263 //Linux_block_rq_wr
@@ -218,7 +267,7 @@ bool PerfDriver::setup() {
218 267
219 id = getTracepointId(SCHED_SWITCH, &printb); 268 id = getTracepointId(SCHED_SWITCH, &printb);
220 if (id >= 0) { 269 if (id >= 0) {
221 mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id); 270 mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, true);
222 } 271 }
223 272
224 //Linux_meminfo_memused 273 //Linux_meminfo_memused
@@ -227,7 +276,7 @@ bool PerfDriver::setup() {
227 //Linux_power_cpu_freq 276 //Linux_power_cpu_freq
228 //Linux_power_cpu_idle 277 //Linux_power_cpu_idle
229 278
230 mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1); 279 mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1, false);
231 280
232 //Linux_cpu_wait_io 281 //Linux_cpu_wait_io
233 282
@@ -252,15 +301,16 @@ bool PerfDriver::summary(Buffer *const buffer) {
252 } 301 }
253 const int64_t timestamp = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec; 302 const int64_t timestamp = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec;
254 303
255 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { 304 const int64_t uptime = getTime();
256 logg->logMessage("%s(%s:%i): clock_gettime failed", __FUNCTION__, __FILE__, __LINE__);
257 return false;
258 }
259 const int64_t uptime = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec;
260 305
261 buffer->summary(timestamp, uptime, 0, buf); 306 buffer->summary(timestamp, uptime, 0, buf);
262 307
263 for (int i = 0; i < gSessionData->mCores; ++i) { 308 for (int i = 0; i < gSessionData->mCores; ++i) {
309 // Don't send information on a cpu we know nothing about
310 if (gSessionData->mCpuIds[i] == -1) {
311 continue;
312 }
313
264 int j; 314 int j;
265 for (j = 0; j < ARRAY_LENGTH(gator_cpus); ++j) { 315 for (j = 0; j < ARRAY_LENGTH(gator_cpus); ++j) {
266 if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) { 316 if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) {
@@ -270,7 +320,11 @@ bool PerfDriver::summary(Buffer *const buffer) {
270 if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) { 320 if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) {
271 buffer->coreName(i, gSessionData->mCpuIds[i], gator_cpus[j].core_name); 321 buffer->coreName(i, gSessionData->mCpuIds[i], gator_cpus[j].core_name);
272 } else { 322 } else {
273 snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[i]); 323 if (gSessionData->mCpuIds[i] == -1) {
324 snprintf(buf, sizeof(buf), "Unknown");
325 } else {
326 snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[i]);
327 }
274 buffer->coreName(i, gSessionData->mCpuIds[i], buf); 328 buffer->coreName(i, gSessionData->mCpuIds[i], buf);
275 } 329 }
276 } 330 }
@@ -326,10 +380,10 @@ int PerfDriver::writeCounters(mxml_node_t *root) const {
326 return count; 380 return count;
327} 381}
328 382
329bool PerfDriver::enable(PerfGroup *group, Buffer *const buffer) const { 383bool PerfDriver::enable(PerfGroup *const group, Buffer *const buffer) const {
330 for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { 384 for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
331 if (counter->isEnabled() && (counter->getType() != TYPE_DERIVED)) { 385 if (counter->isEnabled() && (counter->getType() != TYPE_DERIVED)) {
332 if (!group->add(buffer, counter->getKey(), counter->getType(), counter->getConfig(), counter->getCount(), 0, 0)) { 386 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)) {
333 logg->logMessage("%s(%s:%i): PerfGroup::add failed", __FUNCTION__, __FILE__, __LINE__); 387 logg->logMessage("%s(%s:%i): PerfGroup::add failed", __FUNCTION__, __FILE__, __LINE__);
334 return false; 388 return false;
335 } 389 }
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:
27 PerfDriver(); 27 PerfDriver();
28 ~PerfDriver(); 28 ~PerfDriver();
29 29
30 bool getLegacySupport() const { return mLegacySupport; }
31
30 bool setup(); 32 bool setup();
31 bool summary(Buffer *const buffer); 33 bool summary(Buffer *const buffer);
32 bool isSetup() const { return mIsSetup; } 34 bool isSetup() const { return mIsSetup; }
@@ -37,16 +39,18 @@ public:
37 39
38 int writeCounters(mxml_node_t *root) const; 40 int writeCounters(mxml_node_t *root) const;
39 41
40 bool enable(PerfGroup *group, Buffer *const buffer) const; 42 bool enable(PerfGroup *const group, Buffer *const buffer) const;
41 43
42 static long long getTracepointId(const char *const name, DynBuf *const printb); 44 static long long getTracepointId(const char *const name, DynBuf *const printb);
43 45
44private: 46private:
45 PerfCounter *findCounter(const Counter &counter) const; 47 PerfCounter *findCounter(const Counter &counter) const;
46 void addCpuCounters(const char *const counterName, const int type, const int numCounters); 48 void addCpuCounters(const char *const counterName, const int type, const int numCounters);
49 void addUncoreCounters(const char *const counterName, const int type, const int numCounters);
47 50
48 PerfCounter *mCounters; 51 PerfCounter *mCounters;
49 bool mIsSetup; 52 bool mIsSetup;
53 bool mLegacySupport;
50 54
51 // Intentionally undefined 55 // Intentionally undefined
52 PerfDriver(const PerfDriver &); 56 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 @@
23#define DEFAULT_PEA_ARGS(pea, additionalSampleType) \ 23#define DEFAULT_PEA_ARGS(pea, additionalSampleType) \
24 pea.size = sizeof(pea); \ 24 pea.size = sizeof(pea); \
25 /* Emit time, read_format below, group leader id, and raw tracepoint info */ \ 25 /* Emit time, read_format below, group leader id, and raw tracepoint info */ \
26 pea.sample_type = PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_IDENTIFIER | additionalSampleType; \ 26 pea.sample_type = (gSessionData->perf.getLegacySupport() \
27 ? PERF_SAMPLE_TID | PERF_SAMPLE_IP | PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_ID \
28 : PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_IDENTIFIER ) | additionalSampleType; \
27 /* Emit emit value in group format */ \ 29 /* Emit emit value in group format */ \
28 pea.read_format = PERF_FORMAT_ID | PERF_FORMAT_GROUP; \ 30 pea.read_format = PERF_FORMAT_ID | PERF_FORMAT_GROUP; \
29 /* start out disabled */ \ 31 /* start out disabled */ \
@@ -39,6 +41,7 @@ static int sys_perf_event_open(struct perf_event_attr *const attr, const pid_t p
39 41
40PerfGroup::PerfGroup(PerfBuffer *const pb) : mPb(pb) { 42PerfGroup::PerfGroup(PerfBuffer *const pb) : mPb(pb) {
41 memset(&mAttrs, 0, sizeof(mAttrs)); 43 memset(&mAttrs, 0, sizeof(mAttrs));
44 memset(&mPerCpu, 0, sizeof(mPerCpu));
42 memset(&mKeys, -1, sizeof(mKeys)); 45 memset(&mKeys, -1, sizeof(mKeys));
43 memset(&mFds, -1, sizeof(mFds)); 46 memset(&mFds, -1, sizeof(mFds));
44} 47}
@@ -75,6 +78,7 @@ bool PerfGroup::add(Buffer *const buffer, const int key, const __u32 type, const
75 mAttrs[i].freq = (flags & PERF_GROUP_FREQ ? 1 : 0); 78 mAttrs[i].freq = (flags & PERF_GROUP_FREQ ? 1 : 0);
76 mAttrs[i].task = (flags & PERF_GROUP_TASK ? 1 : 0); 79 mAttrs[i].task = (flags & PERF_GROUP_TASK ? 1 : 0);
77 mAttrs[i].sample_id_all = (flags & PERF_GROUP_SAMPLE_ID_ALL ? 1 : 0); 80 mAttrs[i].sample_id_all = (flags & PERF_GROUP_SAMPLE_ID_ALL ? 1 : 0);
81 mPerCpu[i] = (flags & PERF_GROUP_PER_CPU);
78 82
79 mKeys[i] = key; 83 mKeys[i] = key;
80 84
@@ -91,13 +95,17 @@ bool PerfGroup::prepareCPU(const int cpu) {
91 continue; 95 continue;
92 } 96 }
93 97
98 if ((cpu != 0) && !mPerCpu[i]) {
99 continue;
100 }
101
94 const int offset = i * gSessionData->mCores; 102 const int offset = i * gSessionData->mCores;
95 if (mFds[cpu + offset] >= 0) { 103 if (mFds[cpu + offset] >= 0) {
96 logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__); 104 logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__);
97 return false; 105 return false;
98 } 106 }
99 107
100 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); 108 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);
101 mFds[cpu + offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, i == 0 ? -1 : mFds[cpu], i == 0 ? 0 : PERF_FLAG_FD_OUTPUT); 109 mFds[cpu + offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, i == 0 ? -1 : mFds[cpu], i == 0 ? 0 : PERF_FLAG_FD_OUTPUT);
102 if (mFds[cpu + offset] < 0) { 110 if (mFds[cpu + offset] < 0) {
103 logg->logMessage("%s(%s:%i): failed %s", __FUNCTION__, __FILE__, __LINE__, strerror(errno)); 111 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,
125 } 133 }
126 134
127 coreKeys[idCount] = mKeys[i]; 135 coreKeys[idCount] = mKeys[i];
128 if (ioctl(fd, PERF_EVENT_IOC_ID, &ids[idCount]) != 0) { 136 if (!gSessionData->perf.getLegacySupport() && ioctl(fd, PERF_EVENT_IOC_ID, &ids[idCount]) != 0 &&
137 // Workaround for running 32-bit gatord on 64-bit systems, kernel patch in the works
138 ioctl(fd, (PERF_EVENT_IOC_ID & ~IOCSIZE_MASK) | (8 << _IOC_SIZESHIFT), &ids[idCount]) != 0) {
129 logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__); 139 logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
130 return false; 140 return false;
131 } 141 }
@@ -137,7 +147,17 @@ int PerfGroup::onlineCPU(const int cpu, const bool start, Buffer *const buffer,
137 return false; 147 return false;
138 } 148 }
139 149
140 buffer->keys(idCount, ids, coreKeys); 150 if (!gSessionData->perf.getLegacySupport()) {
151 buffer->keys(idCount, ids, coreKeys);
152 } else {
153 char buf[1024];
154 ssize_t bytes = read(mFds[cpu], buf, sizeof(buf));
155 if (bytes < 0) {
156 logg->logMessage("read failed");
157 return false;
158 }
159 buffer->keysOld(idCount, coreKeys, bytes, buf);
160 }
141 161
142 if (start) { 162 if (start) {
143 for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) { 163 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 {
24 PERF_GROUP_FREQ = 1 << 2, 24 PERF_GROUP_FREQ = 1 << 2,
25 PERF_GROUP_TASK = 1 << 3, 25 PERF_GROUP_TASK = 1 << 3,
26 PERF_GROUP_SAMPLE_ID_ALL = 1 << 4, 26 PERF_GROUP_SAMPLE_ID_ALL = 1 << 4,
27 PERF_GROUP_PER_CPU = 1 << 5,
27}; 28};
28 29
29class PerfGroup { 30class PerfGroup {
@@ -43,6 +44,7 @@ public:
43private: 44private:
44 // +1 for the group leader 45 // +1 for the group leader
45 struct perf_event_attr mAttrs[MAX_PERFORMANCE_COUNTERS + 1]; 46 struct perf_event_attr mAttrs[MAX_PERFORMANCE_COUNTERS + 1];
47 bool mPerCpu[MAX_PERFORMANCE_COUNTERS + 1];
46 int mKeys[MAX_PERFORMANCE_COUNTERS + 1]; 48 int mKeys[MAX_PERFORMANCE_COUNTERS + 1];
47 int mFds[NR_CPUS * (MAX_PERFORMANCE_COUNTERS + 1)]; 49 int mFds[NR_CPUS * (MAX_PERFORMANCE_COUNTERS + 1)];
48 PerfBuffer *const mPb; 50 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
37 return true; 37 return true;
38} 38}
39 39
40PerfSource::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) { 40PerfSource::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) {
41 long l = sysconf(_SC_PAGE_SIZE); 41 long l = sysconf(_SC_PAGE_SIZE);
42 if (l < 0) { 42 if (l < 0) {
43 logg->logError(__FILE__, __LINE__, "Unable to obtain the page size"); 43 logg->logError(__FILE__, __LINE__, "Unable to obtain the page size");
@@ -74,6 +74,9 @@ bool PerfSource::prepare() {
74 DynBuf b3; 74 DynBuf b3;
75 long long schedSwitchId; 75 long long schedSwitchId;
76 76
77 // Reread cpuinfo since cores may have changed since startup
78 gSessionData->readCpuInfo();
79
77 if (0 80 if (0
78 || !mMonitor.init() 81 || !mMonitor.init()
79 || !mUEvent.init() 82 || !mUEvent.init()
@@ -83,14 +86,14 @@ bool PerfSource::prepare() {
83 || !sendTracepointFormat(&mBuffer, SCHED_SWITCH, &printb, &b1) 86 || !sendTracepointFormat(&mBuffer, SCHED_SWITCH, &printb, &b1)
84 87
85 // Only want RAW but not IP on sched_switch and don't want TID on SAMPLE_ID 88 // Only want RAW but not IP on sched_switch and don't want TID on SAMPLE_ID
86 || !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) 89 || !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)
87 90
88 // Only want TID and IP but not RAW on timer 91 // Only want TID and IP but not RAW on timer
89 || (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)) 92 || (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))
90 93
91 || !gSessionData->perf.enable(&mCountersGroup, &mBuffer) 94 || !gSessionData->perf.enable(&mCountersGroup, &mBuffer)
92 || 0) { 95 || 0) {
93 logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.12 or later?", __FUNCTION__, __FILE__, __LINE__); 96 logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.4 or later?", __FUNCTION__, __FILE__, __LINE__);
94 return false; 97 return false;
95 } 98 }
96 99
@@ -134,7 +137,7 @@ bool PerfSource::prepare() {
134 return false; 137 return false;
135 } 138 }
136 139
137 if (!readProc(&mBuffer, &printb, &b1, &b2, &b3)) { 140 if (!readProc(&mBuffer, true, &printb, &b1, &b2, &b3)) {
138 logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__); 141 logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__);
139 return false; 142 return false;
140 } 143 }
@@ -260,6 +263,7 @@ bool PerfSource::isDone () {
260void PerfSource::write (Sender *sender) { 263void PerfSource::write (Sender *sender) {
261 if (!mSummary.isDone()) { 264 if (!mSummary.isDone()) {
262 mSummary.write(sender); 265 mSummary.write(sender);
266 gSessionData->mSentSummary = true;
263 } 267 }
264 if (!mBuffer.isDone()) { 268 if (!mBuffer.isDone()) {
265 mBuffer.write(sender); 269 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
57 return true; 57 return true;
58} 58}
59 59
60static bool readProcTask(Buffer *const buffer, const int pid, const char *const image, DynBuf *const printb, DynBuf *const b) { 60static const char *readProcExe(DynBuf *const printb, const int pid, const int tid, DynBuf *const b) {
61 if (tid == -1 ? !printb->printf("/proc/%i/exe", pid)
62 : !printb->printf("/proc/%i/task/%i/exe", pid, tid)) {
63 logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
64 return NULL;
65 }
66
67 const int err = b->readlink(printb->getBuf());
68 const char *image;
69 if (err == 0) {
70 image = strrchr(b->getBuf(), '/');
71 if (image == NULL) {
72 image = b->getBuf();
73 } else {
74 ++image;
75 }
76 } else if (err == -ENOENT) {
77 // readlink /proc/[pid]/exe returns ENOENT for kernel threads
78 image = "\0";
79 } else {
80 logg->logMessage("%s(%s:%i): DynBuf::readlink failed", __FUNCTION__, __FILE__, __LINE__);
81 return NULL;
82 }
83
84 // Android apps are run by app_process but the cmdline is changed to reference the actual app name
85 if (strcmp(image, "app_process") != 0) {
86 return image;
87 }
88
89 if (tid == -1 ? !printb->printf("/proc/%i/cmdline", pid)
90 : !printb->printf("/proc/%i/task/%i/cmdline", pid, tid)) {
91 logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
92 return NULL;
93 }
94
95 if (!b->read(printb->getBuf())) {
96 logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the thread exited", __FUNCTION__, __FILE__, __LINE__);
97 return NULL;
98 }
99
100 return b->getBuf();
101}
102
103static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) {
61 bool result = false; 104 bool result = false;
62 105
63 if (!b->printf("/proc/%i/task", pid)) { 106 if (!b1->printf("/proc/%i/task", pid)) {
64 logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); 107 logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
65 return result; 108 return result;
66 } 109 }
67 DIR *task = opendir(b->getBuf()); 110 DIR *task = opendir(b1->getBuf());
68 if (task == NULL) { 111 if (task == NULL) {
69 logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__); 112 logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__);
70 return result; 113 return result;
@@ -84,11 +127,17 @@ static bool readProcTask(Buffer *const buffer, const int pid, const char *const
84 goto fail; 127 goto fail;
85 } 128 }
86 ProcStat ps; 129 ProcStat ps;
87 if (!readProcStat(&ps, printb->getBuf(), b)) { 130 if (!readProcStat(&ps, printb->getBuf(), b1)) {
88 logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__); 131 logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__);
89 goto fail; 132 goto fail;
90 } 133 }
91 134
135 const char *const image = readProcExe(printb, pid, tid, b2);
136 if (image == NULL) {
137 logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__);
138 goto fail;
139 }
140
92 buffer->comm(pid, tid, image, ps.comm); 141 buffer->comm(pid, tid, image, ps.comm);
93 } 142 }
94 143
@@ -100,7 +149,7 @@ static bool readProcTask(Buffer *const buffer, const int pid, const char *const
100 return result; 149 return result;
101} 150}
102 151
103bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) { 152bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) {
104 bool result = false; 153 bool result = false;
105 154
106 DIR *proc = opendir("/proc"); 155 DIR *proc = opendir("/proc");
@@ -128,42 +177,29 @@ bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynB
128 goto fail; 177 goto fail;
129 } 178 }
130 179
131 if (!printb->printf("/proc/%i/exe", pid)) { 180 if (sendMaps) {
132 logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); 181 if (!printb->printf("/proc/%i/maps", pid)) {
133 goto fail; 182 logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
134 } 183 goto fail;
135 const int err = b1->readlink(printb->getBuf()); 184 }
136 const char *image; 185 if (!b2->read(printb->getBuf())) {
137 if (err == 0) { 186 logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__);
138 image = strrchr(b1->getBuf(), '/'); 187 // This is not a fatal error - the process just doesn't exist any more
139 if (image == NULL) { 188 continue;
140 image = b1->getBuf();
141 } else {
142 ++image;
143 } 189 }
144 } else if (err == -ENOENT) {
145 // readlink /proc/[pid]/exe returns ENOENT for kernel threads
146 image = "\0";
147 } else {
148 logg->logMessage("%s(%s:%i): DynBuf::readlink failed", __FUNCTION__, __FILE__, __LINE__);
149 goto fail;
150 }
151 190
152 if (!printb->printf("/proc/%i/maps", pid)) { 191 buffer->maps(pid, pid, b2->getBuf());
153 logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
154 goto fail;
155 } 192 }
156 if (!b2->read(printb->getBuf())) {
157 logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__);
158 // This is not a fatal error - the process just doesn't exist any more
159 continue;
160 }
161
162 buffer->maps(pid, pid, b2->getBuf());
163 if (ps.numThreads <= 1) { 193 if (ps.numThreads <= 1) {
194 const char *const image = readProcExe(printb, pid, -1, b1);
195 if (image == NULL) {
196 logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__);
197 goto fail;
198 }
199
164 buffer->comm(pid, pid, image, ps.comm); 200 buffer->comm(pid, pid, image, ps.comm);
165 } else { 201 } else {
166 if (!readProcTask(buffer, pid, image, printb, b3)) { 202 if (!readProcTask(buffer, pid, printb, b1, b3)) {
167 logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__); 203 logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__);
168 goto fail; 204 goto fail;
169 } 205 }
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 @@
12class Buffer; 12class Buffer;
13class DynBuf; 13class DynBuf;
14 14
15bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3); 15bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3);
16 16
17#endif // PROC_H 17#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:
39 Sender &operator=(const Sender &); 39 Sender &operator=(const Sender &);
40}; 40};
41 41
42#endif //__SENDER_H__ 42#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 @@
9#include "SessionData.h" 9#include "SessionData.h"
10 10
11#include <string.h> 11#include <string.h>
12#include <sys/mman.h>
12 13
13#include "SessionXML.h" 14#include "SessionXML.h"
14#include "Logging.h" 15#include "Logging.h"
@@ -27,6 +28,15 @@ void SessionData::initialize() {
27 mSessionIsActive = false; 28 mSessionIsActive = false;
28 mLocalCapture = false; 29 mLocalCapture = false;
29 mOneShot = false; 30 mOneShot = false;
31 mSentSummary = false;
32 const size_t cpuIdSize = sizeof(int)*NR_CPUS;
33 // Share mCpuIds across all instances of gatord
34 mCpuIds = (int *)mmap(NULL, cpuIdSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
35 if (mCpuIds == MAP_FAILED) {
36 logg->logError(__FILE__, __LINE__, "Unable to mmap shared memory for cpuids");
37 handleException();
38 }
39 memset(mCpuIds, -1, cpuIdSize);
30 readCpuInfo(); 40 readCpuInfo();
31 mConfigurationXMLPath = NULL; 41 mConfigurationXMLPath = NULL;
32 mSessionXMLPath = NULL; 42 mSessionXMLPath = NULL;
@@ -91,10 +101,9 @@ void SessionData::parseSessionXML(char* xmlString) {
91void SessionData::readCpuInfo() { 101void SessionData::readCpuInfo() {
92 char temp[256]; // arbitrarily large amount 102 char temp[256]; // arbitrarily large amount
93 strcpy(mCoreName, "unknown"); 103 strcpy(mCoreName, "unknown");
94 memset(&mCpuIds, -1, sizeof(mCpuIds));
95 mMaxCpuId = -1; 104 mMaxCpuId = -1;
96 105
97 FILE* f = fopen("/proc/cpuinfo", "r"); 106 FILE* f = fopen("/proc/cpuinfo", "r");
98 if (f == NULL) { 107 if (f == NULL) {
99 logg->logMessage("Error opening /proc/cpuinfo\n" 108 logg->logMessage("Error opening /proc/cpuinfo\n"
100 "The core name in the captured xml file will be 'unknown'."); 109 "The core name in the captured xml file will be 'unknown'.");
@@ -102,10 +111,18 @@ void SessionData::readCpuInfo() {
102 } 111 }
103 112
104 bool foundCoreName = false; 113 bool foundCoreName = false;
105 int processor = 0; 114 int processor = -1;
106 while (fgets(temp, sizeof(temp), f)) { 115 while (fgets(temp, sizeof(temp), f)) {
107 if (strlen(temp) > 0) { 116 const size_t len = strlen(temp);
108 temp[strlen(temp) - 1] = 0; // Replace the line feed with a null 117
118 if (len == 1) {
119 // 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.
120 processor = -1;
121 continue;
122 }
123
124 if (len > 0) {
125 temp[len - 1] = '\0'; // Replace the line feed with a null
109 } 126 }
110 127
111 const bool foundHardware = strstr(temp, "Hardware") != 0; 128 const bool foundHardware = strstr(temp, "Hardware") != 0;
@@ -127,10 +144,15 @@ void SessionData::readCpuInfo() {
127 } 144 }
128 145
129 if (foundCPUPart) { 146 if (foundCPUPart) {
130 mCpuIds[processor] = strtol(position, NULL, 0); 147 const int cpuId = strtol(position, NULL, 0);
131 // 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 148 // 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
132 if (mCpuIds[processor] > mMaxCpuId) { 149 if (cpuId > mMaxCpuId) {
133 mMaxCpuId = mCpuIds[processor]; 150 mMaxCpuId = cpuId;
151 }
152 if (processor >= NR_CPUS) {
153 logg->logMessage("Too many processors, please increase NR_CPUS");
154 } else if (processor >= 0) {
155 mCpuIds[processor] = cpuId;
134 } 156 }
135 } 157 }
136 158
@@ -142,10 +164,23 @@ void SessionData::readCpuInfo() {
142 164
143 if (!foundCoreName) { 165 if (!foundCoreName) {
144 logg->logMessage("Could not determine core name from /proc/cpuinfo\n" 166 logg->logMessage("Could not determine core name from /proc/cpuinfo\n"
145 "The core name in the captured xml file will be 'unknown'."); 167 "The core name in the captured xml file will be 'unknown'.");
146 } 168 }
147 fclose(f); 169 fclose(f);
148 } 170}
171
172uint64_t getTime() {
173 struct timespec ts;
174#ifndef CLOCK_MONOTONIC_RAW
175 // Android doesn't have this defined but it was added in Linux 2.6.28
176#define CLOCK_MONOTONIC_RAW 4
177#endif
178 if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
179 logg->logError(__FILE__, __LINE__, "Failed to get uptime");
180 handleException();
181 }
182 return (NS_PER_S*ts.tv_sec + ts.tv_nsec);
183}
149 184
150int getEventKey() { 185int getEventKey() {
151 // key 0 is reserved as a timestamp 186 // 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 @@
13 13
14#include "Config.h" 14#include "Config.h"
15#include "Counter.h" 15#include "Counter.h"
16#include "FSDriver.h"
16#include "Hwmon.h" 17#include "Hwmon.h"
18#include "MaliVideoDriver.h"
17#include "PerfDriver.h" 19#include "PerfDriver.h"
18 20
19#define PROTOCOL_VERSION 18 21#define PROTOCOL_VERSION 19
20#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions 22#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions
21 23
24#define NS_PER_S ((uint64_t)1000000000)
25
22struct ImageLinkList { 26struct ImageLinkList {
23 char* path; 27 char* path;
24 struct ImageLinkList *next; 28 struct ImageLinkList *next;
@@ -32,9 +36,12 @@ public:
32 ~SessionData(); 36 ~SessionData();
33 void initialize(); 37 void initialize();
34 void parseSessionXML(char* xmlString); 38 void parseSessionXML(char* xmlString);
39 void readCpuInfo();
35 40
36 Hwmon hwmon; 41 Hwmon hwmon;
42 FSDriver fsDriver;
37 PerfDriver perf; 43 PerfDriver perf;
44 MaliVideoDriver maliVideo;
38 45
39 char mCoreName[MAX_STRING_LEN]; 46 char mCoreName[MAX_STRING_LEN];
40 struct ImageLinkList *mImages; 47 struct ImageLinkList *mImages;
@@ -49,7 +56,8 @@ public:
49 bool mLocalCapture; 56 bool mLocalCapture;
50 bool mOneShot; // halt processing of the driver data until profiling is complete or the buffer is filled 57 bool mOneShot; // halt processing of the driver data until profiling is complete or the buffer is filled
51 bool mIsEBS; 58 bool mIsEBS;
52 59 bool mSentSummary;
60
53 int mBacktraceDepth; 61 int mBacktraceDepth;
54 int mTotalBufferSize; // number of MB to use for the entire collection buffer 62 int mTotalBufferSize; // number of MB to use for the entire collection buffer
55 int mSampleRate; 63 int mSampleRate;
@@ -57,7 +65,7 @@ public:
57 int mDuration; 65 int mDuration;
58 int mCores; 66 int mCores;
59 int mPageSize; 67 int mPageSize;
60 int mCpuIds[NR_CPUS]; 68 int *mCpuIds;
61 int mMaxCpuId; 69 int mMaxCpuId;
62 70
63 // PMU Counters 71 // PMU Counters
@@ -65,8 +73,6 @@ public:
65 Counter mCounters[MAX_PERFORMANCE_COUNTERS]; 73 Counter mCounters[MAX_PERFORMANCE_COUNTERS];
66 74
67private: 75private:
68 void readCpuInfo();
69
70 // Intentionally unimplemented 76 // Intentionally unimplemented
71 SessionData(const SessionData &); 77 SessionData(const SessionData &);
72 SessionData &operator=(const SessionData &); 78 SessionData &operator=(const SessionData &);
@@ -74,6 +80,7 @@ private:
74 80
75extern SessionData* gSessionData; 81extern SessionData* gSessionData;
76 82
83uint64_t getTime();
77int getEventKey(); 84int getEventKey();
78 85
79#endif // SESSION_DATA_H 86#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 @@
17#include "SessionData.h" 17#include "SessionData.h"
18 18
19static const char* TAG_SESSION = "session"; 19static const char* TAG_SESSION = "session";
20static const char* TAG_IMAGE = "image"; 20static const char* TAG_IMAGE = "image";
21 21
22static const char* ATTR_VERSION = "version"; 22static const char* ATTR_VERSION = "version";
23static const char* ATTR_CALL_STACK_UNWINDING = "call_stack_unwinding"; 23static const char* ATTR_CALL_STACK_UNWINDING = "call_stack_unwinding";
24static const char* ATTR_BUFFER_MODE = "buffer_mode"; 24static const char* ATTR_BUFFER_MODE = "buffer_mode";
25static const char* ATTR_SAMPLE_RATE = "sample_rate"; 25static const char* ATTR_SAMPLE_RATE = "sample_rate";
26static const char* ATTR_DURATION = "duration"; 26static const char* ATTR_DURATION = "duration";
27static const char* ATTR_PATH = "path"; 27static const char* ATTR_PATH = "path";
28static const char* ATTR_LIVE_RATE = "live_rate"; 28static const char* ATTR_LIVE_RATE = "live_rate";
29 29
30SessionXML::SessionXML(const char *str) { 30SessionXML::SessionXML(const char *str) {
31 parameters.buffer_mode[0] = 0; 31 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) {
266 { ConfigurationXML configuration; } 266 { ConfigurationXML configuration; }
267 267
268 if (gSessionData->mCounterOverflow > 0) { 268 if (gSessionData->mCounterOverflow > 0) {
269 logg->logError(__FILE__, __LINE__, "Only %i performance counters counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow); 269 logg->logError(__FILE__, __LINE__, "Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow);
270 handleException(); 270 handleException();
271 } 271 }
272} 272}
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 {
21 COMMAND_APC_START = 2, 21 COMMAND_APC_START = 2,
22 COMMAND_APC_STOP = 3, 22 COMMAND_APC_STOP = 3,
23 COMMAND_DISCONNECT = 4, 23 COMMAND_DISCONNECT = 4,
24 COMMAND_PING = 5 24 COMMAND_PING = 5
25}; 25};
26 26
27class StreamlineSetup { 27class StreamlineSetup {
@@ -47,4 +47,4 @@ private:
47 StreamlineSetup &operator=(const StreamlineSetup &); 47 StreamlineSetup &operator=(const StreamlineSetup &);
48}; 48};
49 49
50#endif //__STREAMLINE_SETUP_H__ 50#endif //__STREAMLINE_SETUP_H__
diff --git a/daemon/UEvent.cpp b/daemon/UEvent.cpp
index d977cd0..54d4575 100644
--- a/daemon/UEvent.cpp
+++ b/daemon/UEvent.cpp
@@ -8,12 +8,12 @@
8 8
9#include "UEvent.h" 9#include "UEvent.h"
10 10
11#include <sys/socket.h>
12#include <linux/netlink.h>
13#include <string.h> 11#include <string.h>
14 12#include <sys/socket.h>
15#include <unistd.h> 13#include <unistd.h>
16 14
15#include <linux/netlink.h>
16
17#include "Logging.h" 17#include "Logging.h"
18 18
19static const char EMPTY[] = ""; 19static 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 @@
16#include "Logging.h" 16#include "Logging.h"
17#include "SessionData.h" 17#include "SessionData.h"
18 18
19#define NS_PER_S ((uint64_t)1000000000)
20#define NS_PER_US 1000 19#define NS_PER_US 1000
21 20
22extern Child *child; 21extern Child *child;
@@ -35,6 +34,7 @@ void UserSpaceSource::run() {
35 prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0); 34 prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0);
36 35
37 gSessionData->hwmon.start(); 36 gSessionData->hwmon.start();
37 gSessionData->fsDriver.start();
38 38
39 int64_t monotonic_started = 0; 39 int64_t monotonic_started = 0;
40 while (monotonic_started <= 0) { 40 while (monotonic_started <= 0) {
@@ -48,16 +48,7 @@ void UserSpaceSource::run() {
48 48
49 uint64_t next_time = 0; 49 uint64_t next_time = 0;
50 while (gSessionData->mSessionIsActive) { 50 while (gSessionData->mSessionIsActive) {
51 struct timespec ts; 51 const uint64_t curr_time = getTime() - monotonic_started;
52#ifndef CLOCK_MONOTONIC_RAW
53 // Android doesn't have this defined but it was added in Linux 2.6.28
54#define CLOCK_MONOTONIC_RAW 4
55#endif
56 if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
57 logg->logError(__FILE__, __LINE__, "Failed to get uptime");
58 handleException();
59 }
60 const uint64_t curr_time = (NS_PER_S*ts.tv_sec + ts.tv_nsec) - monotonic_started;
61 // Sample ten times a second ignoring gSessionData->mSampleRate 52 // Sample ten times a second ignoring gSessionData->mSampleRate
62 next_time += NS_PER_S/10;//gSessionData->mSampleRate; 53 next_time += NS_PER_S/10;//gSessionData->mSampleRate;
63 if (next_time < curr_time) { 54 if (next_time < curr_time) {
@@ -67,6 +58,7 @@ void UserSpaceSource::run() {
67 58
68 if (mBuffer.eventHeader(curr_time)) { 59 if (mBuffer.eventHeader(curr_time)) {
69 gSessionData->hwmon.read(&mBuffer); 60 gSessionData->hwmon.read(&mBuffer);
61 gSessionData->fsDriver.read(&mBuffer);
70 // Only check after writing all counters so that time and corresponding counters appear in the same frame 62 // Only check after writing all counters so that time and corresponding counters appear in the same frame
71 mBuffer.check(curr_time); 63 mBuffer.check(curr_time);
72 } 64 }
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 @@
14#include "Buffer.h" 14#include "Buffer.h"
15#include "Source.h" 15#include "Source.h"
16 16
17// User space counters - currently just hwmon 17// User space counters
18class UserSpaceSource : public Source { 18class UserSpaceSource : public Source {
19public: 19public:
20 UserSpaceSource(sem_t *senderSem); 20 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 @@
1/**
2 * Minimal set of C++ functions so that libstdc++ is not required
3 *
4 * Copyright (C) ARM Limited 2010-2014. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13
14void operator delete(void *ptr) {
15 if (ptr != NULL) {
16 free(ptr);
17 }
18}
19
20void operator delete[](void *ptr) {
21 operator delete(ptr);
22}
23
24void *operator new(size_t size) {
25 void *ptr = malloc(size == 0 ? 1 : size);
26 if (ptr == NULL) {
27 abort();
28 }
29 return ptr;
30}
31
32void *operator new[](size_t size) {
33 return operator new(size);
34}
35
36extern "C"
37void __cxa_pure_virtual() {
38 printf("pure virtual method called\n");
39 abort();
40}
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 @@
5# -Werror treats warnings as errors 5# -Werror treats warnings as errors
6# -std=c++0x is the planned new c++ standard 6# -std=c++0x is the planned new c++ standard
7# -std=c++98 is the 1998 c++ standard 7# -std=c++98 is the 1998 c++ standard
8CFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors 8CPPFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors
9CXXFLAGS += -fno-rtti -Wextra # -Weffc++ 9CXXFLAGS += -fno-rtti -Wextra # -Weffc++
10ifeq ($(WERROR),1) 10ifeq ($(WERROR),1)
11 CFLAGS += -Werror 11 CPPFLAGS += -Werror
12endif 12endif
13# -s strips the binary of debug info 13# -s strips the binary of debug info
14LDFLAGS += -s 14LDFLAGS += -s
15LDLIBS += -lrt -lm -pthread
15TARGET = gatord 16TARGET = gatord
16C_SRC = $(wildcard mxml/*.c) $(wildcard libsensors/*.c) 17C_SRC = $(wildcard mxml/*.c) $(wildcard libsensors/*.c)
17CPP_SRC = $(wildcard *.cpp) 18CXX_SRC = $(wildcard *.cpp)
18 19
19all: $(TARGET) 20all: $(TARGET)
20 21
@@ -35,14 +36,15 @@ libsensors/conf-parse.c: ;
35 ./escape $< > $@ 36 ./escape $< > $@
36 37
37%.o: %.c 38%.o: %.c
38 $(GCC) -c $(CFLAGS) -o $@ $< 39 $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
39 40
40%.o: %.cpp 41%.o: %.cpp
41 $(CPP) -c $(CFLAGS) $(CXXFLAGS) -o $@ $< 42 $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
42 43
43$(TARGET): $(CPP_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o) 44$(TARGET): $(CXX_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o)
44 $(CPP) $(LDFLAGS) -o $@ $^ -lrt -pthread 45 $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
45 46
47# Intentionally ignore CC as a native binary is required
46escape: escape.c 48escape: escape.c
47 gcc $^ -o $@ 49 gcc $^ -o $@
48 50
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 @@
58 <configuration counter="Linux_meminfo_memused"/> 58 <configuration counter="Linux_meminfo_memused"/>
59 <configuration counter="Linux_meminfo_memfree"/> 59 <configuration counter="Linux_meminfo_memfree"/>
60 <configuration counter="Linux_power_cpu_freq"/> 60 <configuration counter="Linux_power_cpu_freq"/>
61 <configuration counter="ARM_Mali-4xx_fragment"/>
62 <configuration counter="ARM_Mali-4xx_vertex"/>
63 <configuration counter="ARM_Mali-T6xx_fragment" cores="1"/>
64 <configuration counter="ARM_Mali-T6xx_vertex" cores="1"/>
65 <configuration counter="ARM_Mali-T6xx_opencl" cores="1"/>
61 <configuration counter="L2C-310_cnt0" event="0x1"/> 66 <configuration counter="L2C-310_cnt0" event="0x1"/>
62</configurations> 67</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 @@
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8 8
9/* 9/*
10 * The Makefile in the daemon folder builds and executes 'escape' 10 * The Makefile in the daemon folder builds and executes 'escape'
11 * 'escape' creates configuration_xml.h from configuration.xml and events_xml.h from events-*.xml 11 * 'escape' creates configuration_xml.h from configuration.xml and events_xml.h from events-*.xml
12 * these genereated xml files are then #included and built as part of the gatord binary 12 * 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 @@
1 <counter_set name="cci-400_cnt" count="4"/> 1 <counter_set name="CCI_400_cnt" count="4"/>
2 <category name="CCI-400" counter_set="cci-400_cnt" per_cpu="no" supports_event_based_sampling="yes"> 2 <category name="CCI-400" counter_set="CCI_400_cnt" per_cpu="no" supports_event_based_sampling="yes">
3 <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"/> 3 <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"/>
4
5 <option_set name="Slave"> 4 <option_set name="Slave">
6 <option event_delta="0x00" name="S0" description="Slave interface 0"/> 5 <option event_delta="0x00" name="S0" description="Slave interface 0"/>
7 <option event_delta="0x20" name="S1" description="Slave interface 1"/> 6 <option event_delta="0x20" name="S1" description="Slave interface 1"/>
@@ -9,7 +8,6 @@
9 <option event_delta="0x60" name="S3" description="Slave interface 3"/> 8 <option event_delta="0x60" name="S3" description="Slave interface 3"/>
10 <option event_delta="0x80" name="S4" description="Slave interface 4"/> 9 <option event_delta="0x80" name="S4" description="Slave interface 4"/>
11 </option_set> 10 </option_set>
12
13 <event event="0x00" option_set="Slave" title="CCI-400" name="Read: any" description="Read request handshake: any"/> 11 <event event="0x00" option_set="Slave" title="CCI-400" name="Read: any" description="Read request handshake: any"/>
14 <event event="0x01" option_set="Slave" title="CCI-400" name="Read: transaction" description="Read request handshake: device transaction"/> 12 <event event="0x01" option_set="Slave" title="CCI-400" name="Read: transaction" description="Read request handshake: device transaction"/>
15 <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"/> 13 <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 @@
30 <event event="0x11" option_set="Slave" title="CCI-400" name="Write: WriteLineUnique" description="Write request handshake: WriteLineUnique"/> 28 <event event="0x11" option_set="Slave" title="CCI-400" name="Write: WriteLineUnique" description="Write request handshake: WriteLineUnique"/>
31 <event event="0x12" option_set="Slave" title="CCI-400" name="Write: Evict" description="Write request handshake: Evict"/> 29 <event event="0x12" option_set="Slave" title="CCI-400" name="Write: Evict" description="Write request handshake: Evict"/>
32 <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"/> 30 <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"/>
33
34 <option_set name="Master"> 31 <option_set name="Master">
35 <option event_delta="0xa0" name="M0" description="Master interface 0"/> 32 <option event_delta="0xa0" name="M0" description="Master interface 0"/>
36 <option event_delta="0xc0" name="M1" description="Master interface 1"/> 33 <option event_delta="0xc0" name="M1" description="Master interface 1"/>
37 <option event_delta="0xe0" name="M2" description="Master interface 2"/> 34 <option event_delta="0xe0" name="M2" description="Master interface 2"/>
38 </option_set> 35 </option_set>
39
40 <event event="0x14" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/> 36 <event event="0x14" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/>
41 <event event="0x15" option_set="Master" title="CCI-400" name="Read stall: address hazard" description="Read request stall cycle because of an address hazard"/> 37 <event event="0x15" option_set="Master" title="CCI-400" name="Read stall: address hazard" description="Read request stall cycle because of an address hazard"/>
42 <event event="0x16" option_set="Master" title="CCI-400" name="Read stall: ID hazard" description="Read request stall cycle because of an ID hazard"/> 38 <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 @@
45 <event event="0x19" option_set="Master" title="CCI-400" name="Write stall: barrier hazard" description="Write request stall cycle because of a barrier hazard"/> 41 <event event="0x19" option_set="Master" title="CCI-400" name="Write stall: barrier hazard" description="Write request stall cycle because of a barrier hazard"/>
46 <event event="0x1a" option_set="Master" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase MIx_W_MAX to avoid this stall. See the CoreLink CCI-400 Cache Coherent Interconnect Integration Manual"/> 42 <event event="0x1a" option_set="Master" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase MIx_W_MAX to avoid this stall. See the CoreLink CCI-400 Cache Coherent Interconnect Integration Manual"/>
47 </category> 43 </category>
48 44 <counter_set name="CCI_400-r1_cnt" count="4"/>
49 <counter_set name="cci-400-r1_cnt" count="4"/> 45 <category name="CCI-400" counter_set="CCI_400-r1_cnt" per_cpu="no" supports_event_based_sampling="yes">
50 <category name="CCI-400" counter_set="cci-400-r1_cnt" per_cpu="no" supports_event_based_sampling="yes"> 46 <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"/>
51 <event counter="cci-400-r1_ccnt" event="0xff" title="CCI-400 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
52
53 <option_set name="Slave"> 47 <option_set name="Slave">
54 <option event_delta="0x00" name="S0" description="Slave interface 0"/> 48 <option event_delta="0x00" name="S0" description="Slave interface 0"/>
55 <option event_delta="0x20" name="S1" description="Slave interface 1"/> 49 <option event_delta="0x20" name="S1" description="Slave interface 1"/>
@@ -57,7 +51,6 @@
57 <option event_delta="0x60" name="S3" description="Slave interface 3"/> 51 <option event_delta="0x60" name="S3" description="Slave interface 3"/>
58 <option event_delta="0x80" name="S4" description="Slave interface 4"/> 52 <option event_delta="0x80" name="S4" description="Slave interface 4"/>
59 </option_set> 53 </option_set>
60
61 <event event="0x00" option_set="Slave" title="CCI-400" name="Read: any" description="Read request handshake: any"/> 54 <event event="0x00" option_set="Slave" title="CCI-400" name="Read: any" description="Read request handshake: any"/>
62 <event event="0x01" option_set="Slave" title="CCI-400" name="Read: transaction" description="Read request handshake: device transaction"/> 55 <event event="0x01" option_set="Slave" title="CCI-400" name="Read: transaction" description="Read request handshake: device transaction"/>
63 <event event="0x02" option_set="Slave" title="CCI-400" name="Read: normal" description="Read request handshake: normal, non-shareable or system-shareable, but not barrier or cache maintenance operation"/> 56 <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 @@
79 <event event="0x12" option_set="Slave" title="CCI-400" name="Write: Evict" description="Write request handshake: Evict"/> 72 <event event="0x12" option_set="Slave" title="CCI-400" name="Write: Evict" description="Write request handshake: Evict"/>
80 <event event="0x13" option_set="Slave" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase SIx_W_MAX to avoid this stall"/> 73 <event event="0x13" option_set="Slave" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase SIx_W_MAX to avoid this stall"/>
81 <event event="0x14" option_set="Slave" title="CCI-400" name="Read stall: slave hazard" description="Read request stall cycle because of a slave interface ID hazard"/> 74 <event event="0x14" option_set="Slave" title="CCI-400" name="Read stall: slave hazard" description="Read request stall cycle because of a slave interface ID hazard"/>
82
83 <option_set name="Master"> 75 <option_set name="Master">
84 <option event_delta="0xa0" name="M0" description="Master interface 0"/> 76 <option event_delta="0xa0" name="M0" description="Master interface 0"/>
85 <option event_delta="0xc0" name="M1" description="Master interface 1"/> 77 <option event_delta="0xc0" name="M1" description="Master interface 1"/>
86 <option event_delta="0xe0" name="M2" description="Master interface 2"/> 78 <option event_delta="0xe0" name="M2" description="Master interface 2"/>
87 </option_set> 79 </option_set>
88
89 <event event="0x00" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/> 80 <event event="0x00" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/>
90 <event event="0x01" option_set="Master" title="CCI-400" name="Read stall: address hazard" description="Stall cycle because of an address hazard. A read or write invalidation is stalled because of an outstanding transaction to an overlapping address"/> 81 <event event="0x01" option_set="Master" title="CCI-400" name="Read stall: address hazard" description="Stall cycle because of an address hazard. A read or write invalidation is stalled because of an outstanding transaction to an overlapping address"/>
91 <event event="0x02" option_set="Master" title="CCI-400" name="Read stall: ID hazard" description="Read request stall cycle because of a master interface ID hazard"/> 82 <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 @@
1 <counter_set name="CCN-504_cnt" count="4"/> 1 <counter_set name="CCN-504_cnt" count="4"/>
2 <category name="CCN-504" counter_set="CCN-504_cnt"> 2 <category name="CCN-504" counter_set="CCN-504_cnt">
3 <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"/> 3 <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"/>
4
5 <option_set name="XP_Region"> 4 <option_set name="XP_Region">
6 <option event_delta="0x400000" name="XP 0" description="Crosspoint 0"/> 5 <option event_delta="0x400000" name="XP 0" description="Crosspoint 0"/>
7 <option event_delta="0x410000" name="XP 1" description="Crosspoint 1"/> 6 <option event_delta="0x410000" name="XP 1" description="Crosspoint 1"/>
@@ -15,7 +14,6 @@
15 <option event_delta="0x490000" name="XP 9" description="Crosspoint 9"/> 14 <option event_delta="0x490000" name="XP 9" description="Crosspoint 9"/>
16 <option event_delta="0x4A0000" name="XP 10" description="Crosspoint 10"/> 15 <option event_delta="0x4A0000" name="XP 10" description="Crosspoint 10"/>
17 </option_set> 16 </option_set>
18
19 <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."/> 17 <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."/>
20 <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."/> 18 <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."/>
21 <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."/> 19 <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 @@
56 <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."/> 54 <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."/>
57 <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."/> 55 <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."/>
58 <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."/> 56 <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."/>
59
60 <option_set name="HN-F_Region"> 57 <option_set name="HN-F_Region">
61 <option event_delta="0x200000" name="HN-F 3" description="Fully-coherent Home Node 3"/> 58 <option event_delta="0x200000" name="HN-F 3" description="Fully-coherent Home Node 3"/>
62 <option event_delta="0x210000" name="HN-F 5" description="Fully-coherent Home Node 5"/> 59 <option event_delta="0x210000" name="HN-F 5" description="Fully-coherent Home Node 5"/>
@@ -67,7 +64,6 @@
67 <option event_delta="0x260000" name="HN-F 17" description="Fully-coherent Home Node 17"/> 64 <option event_delta="0x260000" name="HN-F 17" description="Fully-coherent Home Node 17"/>
68 <option event_delta="0x270000" name="HN-F 18" description="Fully-coherent Home Node 18"/> 65 <option event_delta="0x270000" name="HN-F 18" description="Fully-coherent Home Node 18"/>
69 </option_set> 66 </option_set>
70
71 <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."/> 67 <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."/>
72 <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."/> 68 <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."/>
73 <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."/> 69 <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 @@
82 <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."/> 78 <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."/>
83 <event event="0x040D" option_set="HN-F_Region" title="CCN-504" name="MC Reqs" description="Counts the number of requests to the memory controller."/> 79 <event event="0x040D" option_set="HN-F_Region" title="CCN-504" name="MC Reqs" description="Counts the number of requests to the memory controller."/>
84 <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."/> 80 <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."/>
85
86 <option_set name="RN-I_Region"> 81 <option_set name="RN-I_Region">
87 <option event_delta="0x800000" name="RN-I 0" description="I/O-coherent Requesting Node 0"/> 82 <option event_delta="0x800000" name="RN-I 0" description="I/O-coherent Requesting Node 0"/>
88 <option event_delta="0x820000" name="RN-I 2" description="I/O-coherent Requesting Node 2"/> 83 <option event_delta="0x820000" name="RN-I 2" description="I/O-coherent Requesting Node 2"/>
@@ -91,7 +86,6 @@
91 <option event_delta="0x900000" name="RN-I 16" description="I/O-coherent Requesting Node 16"/> 86 <option event_delta="0x900000" name="RN-I 16" description="I/O-coherent Requesting Node 16"/>
92 <option event_delta="0x940000" name="RN-I 20" description="I/O-coherent Requesting Node 20"/> 87 <option event_delta="0x940000" name="RN-I 20" description="I/O-coherent Requesting Node 20"/>
93 </option_set> 88 </option_set>
94
95 <event event="0x1601" option_set="RN-I_Region" title="CCN-504" name="S0 RDataBeats" description="S0 RDataBeats."/> 89 <event event="0x1601" option_set="RN-I_Region" title="CCN-504" name="S0 RDataBeats" description="S0 RDataBeats."/>
96 <event event="0x1602" option_set="RN-I_Region" title="CCN-504" name="S1 RDataBeats" description="S1 RDataBeats."/> 90 <event event="0x1602" option_set="RN-I_Region" title="CCN-504" name="S1 RDataBeats" description="S1 RDataBeats."/>
97 <event event="0x1603" option_set="RN-I_Region" title="CCN-504" name="S2 RDataBeats" description="S2 RDataBeats."/> 91 <event event="0x1603" option_set="RN-I_Region" title="CCN-504" name="S2 RDataBeats" description="S2 RDataBeats."/>
@@ -102,14 +96,12 @@
102 <event event="0x1608" option_set="RN-I_Region" title="CCN-504" name="RRT full" description="RRT full."/> 96 <event event="0x1608" option_set="RN-I_Region" title="CCN-504" name="RRT full" description="RRT full."/>
103 <event event="0x1609" option_set="RN-I_Region" title="CCN-504" name="WRT full" description="WRT full."/> 97 <event event="0x1609" option_set="RN-I_Region" title="CCN-504" name="WRT full" description="WRT full."/>
104 <event event="0x160A" option_set="RN-I_Region" title="CCN-504" name="Replayed TXREQ Flits" description="Replayed TXREQ Flits."/> 98 <event event="0x160A" option_set="RN-I_Region" title="CCN-504" name="Replayed TXREQ Flits" description="Replayed TXREQ Flits."/>
105
106 <option_set name="SBAS_Region"> 99 <option_set name="SBAS_Region">
107 <option event_delta="0x810000" name="SBAS 1" description="ACE master to CHI protocol bridge 1"/> 100 <option event_delta="0x810000" name="SBAS 1" description="ACE master to CHI protocol bridge 1"/>
108 <option event_delta="0x890000" name="SBAS 9" description="ACE master to CHI protocol bridge 9"/> 101 <option event_delta="0x890000" name="SBAS 9" description="ACE master to CHI protocol bridge 9"/>
109 <option event_delta="0x8B0000" name="SBAS 11" description="ACE master to CHI protocol bridge 11"/> 102 <option event_delta="0x8B0000" name="SBAS 11" description="ACE master to CHI protocol bridge 11"/>
110 <option event_delta="0x930000" name="SBAS 19" description="ACE master to CHI protocol bridge 19"/> 103 <option event_delta="0x930000" name="SBAS 19" description="ACE master to CHI protocol bridge 19"/>
111 </option_set> 104 </option_set>
112
113 <event event="0x1001" option_set="SBAS_Region" title="CCN-504" name="S0 RDataBeats" description="S0 RDataBeats."/> 105 <event event="0x1001" option_set="SBAS_Region" title="CCN-504" name="S0 RDataBeats" description="S0 RDataBeats."/>
114 <event event="0x1004" option_set="SBAS_Region" title="CCN-504" name="RXDAT Flits received" description="RXDAT Flits received."/> 106 <event event="0x1004" option_set="SBAS_Region" title="CCN-504" name="RXDAT Flits received" description="RXDAT Flits received."/>
115 <event event="0x1005" option_set="SBAS_Region" title="CCN-504" name="TXDAT Flits sent" description="TXDAT Flits sent."/> 107 <event event="0x1005" option_set="SBAS_Region" title="CCN-504" name="TXDAT Flits sent" description="TXDAT Flits sent."/>
@@ -118,5 +110,4 @@
118 <event event="0x1008" option_set="SBAS_Region" title="CCN-504" name="RRT full" description="RRT full."/> 110 <event event="0x1008" option_set="SBAS_Region" title="CCN-504" name="RRT full" description="RRT full."/>
119 <event event="0x1009" option_set="SBAS_Region" title="CCN-504" name="WRT full" description="WRT full."/> 111 <event event="0x1009" option_set="SBAS_Region" title="CCN-504" name="WRT full" description="WRT full."/>
120 <event event="0x100A" option_set="SBAS_Region" title="CCN-504" name="Replayed TXREQ Flits" description="Replayed TXREQ Flits."/> 112 <event event="0x100A" option_set="SBAS_Region" title="CCN-504" name="Replayed TXREQ Flits" description="Replayed TXREQ Flits."/>
121
122 </category> 113 </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 @@
1 <counter_set name="ARM_Cortex-A53_cnt" count="6"/> 1 <counter_set name="ARM_Cortex-A53_cnt" count="6"/>
2 <category name="Cortex-A53" counter_set="ARM_Cortex-A53_cnt" per_cpu="yes" supports_event_based_sampling="yes"> 2 <category name="Cortex-A53" counter_set="ARM_Cortex-A53_cnt" per_cpu="yes" supports_event_based_sampling="yes">
3 <!-- 0x11 CPU_CYCLES - Cycle -->
4 <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"/> 3 <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"/>
5 <!-- 0x00 SW_INCR - Instruction architecturally executed (condition check pass) - Software increment -->
6 <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/> 4 <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
7 <!-- 0x01 L1I_CACHE_REFILL - Level 1 instruction cache refill -->
8 <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"/> 5 <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"/>
9 <!-- 0x02 L1I_TLB_REFILL - Level 1 instruction TLB refill -->
10 <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"/> 6 <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"/>
11 <!-- 0x03 L1D_CACHE_REFILL - Level 1 data cache refill -->
12 <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"/> 7 <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"/>
13 <!-- 0x04 L1D_CACHE - Level 1 data cache access -->
14 <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"/> 8 <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"/>
15 <!-- 0x05 L1D_TLB_REFILL - Level 1 data TLB refill -->
16 <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"/> 9 <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"/>
17 <!-- 0x08 INST_RETIRED - Instruction architecturally executed -->
18 <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/> 10 <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
19 <!-- 0x09 EXC_TAKEN - Exception taken -->
20 <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/> 11 <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
21 <!-- 0x0A EXC_RETURN - Instruction architecturally executed (condition check pass) - Exception return -->
22 <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/> 12 <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
23 <!-- 0x0B CID_WRITE_RETIRED - Instruction architecturally executed (condition check pass) - Write to CONTEXTIDR -->
24 <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/> 13 <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
25 <!-- 0x10 BR_MIS_PRED - Mispredicted or not predicted branch speculatively executed -->
26 <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/> 14 <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
27 <!-- 0x12 BR_PRED - Predictable branch speculatively executed -->
28 <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"/> 15 <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"/>
29 <!-- 0x13 MEM_ACCESS - Data memory access -->
30 <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/> 16 <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
31 <!-- 0x14 L1I_CACHE - Level 1 instruction cache access -->
32 <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/> 17 <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/>
33 <!-- 0x15 L1D_CACHE_WB - Level 1 data cache Write-Back -->
34 <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/> 18 <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
35 <!-- 0x16 L2D_CACHE - Level 2 data cache access -->
36 <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/> 19 <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
37 <!-- 0x17 L2D_CACHE_REFILL - Level 2 data cache refill -->
38 <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/> 20 <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
39 <!-- 0x18 L2D_CACHE_WB - Level 2 data cache Write-Back -->
40 <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/> 21 <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
41 <!-- 0x19 BUS_ACCESS - Bus access -->
42 <event event="0x19" title="Bus" name="Access" description="Bus access"/> 22 <event event="0x19" title="Bus" name="Access" description="Bus access"/>
43 <!-- 0x1A MEMORY_ERROR - Local memory error -->
44 <event event="0x1A" title="Memory" name="Error" description="Local memory error"/> 23 <event event="0x1A" title="Memory" name="Error" description="Local memory error"/>
45 <!-- 0x1B INST_SPEC - Operation speculatively executed -->
46 <event event="0x1B" title="Instruction" name="Speculative" description="Operation speculatively executed"/> 24 <event event="0x1B" title="Instruction" name="Speculative" description="Operation speculatively executed"/>
47 <!-- 0x1C TTBR_WRITE_RETIRED - Instruction architecturally executed (condition check pass) - Write to translation table base -->
48 <event event="0x1C" title="Memory" name="Translation table" description="Instruction architecturally executed (condition check pass) - Write to translation table base"/> 25 <event event="0x1C" title="Memory" name="Translation table" description="Instruction architecturally executed (condition check pass) - Write to translation table base"/>
49 <!-- 0x1D BUS_CYCLES - Bus cycle -->
50 <event event="0x1D" title="Bus" name="Cycle" description="Bus cycle"/> 26 <event event="0x1D" title="Bus" name="Cycle" description="Bus cycle"/>
51 <!-- 0x1E CHAIN - Odd performance counter chain mode -->
52 <event event="0x1E" title="Counter chain" name="Odd Performance" description="Odd performance counter chain mode"/> 27 <event event="0x1E" title="Counter chain" name="Odd Performance" description="Odd performance counter chain mode"/>
53 <!-- 0x40 L1D_CACHE_LD - Level 1 data cache access - Read -->
54 <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/> 28 <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
55 <!-- 0x41 L1D_CACHE_ST - Level 1 data cache access - Write -->
56 <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/> 29 <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
57 <!-- 0x42 L1D_CACHE_REFILL_LD - Level 1 data cache refill - Read -->
58 <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/> 30 <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/>
59 <!-- 0x43 L1D_CACHE_REFILL_ST - Level 1 data cache refill - Write -->
60 <event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill - Write"/> 31 <event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill - Write"/>
61 <!-- 0x46 L1D_CACHE_WB_VICTIM - Level 1 data cache Write-back - Victim -->
62 <event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-back - Victim"/> 32 <event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-back - Victim"/>
63 <!-- 0x47 L1D_CACHE_WB_CLEAN - Level 1 data cache Write-back - Cleaning and coherency -->
64 <event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-back - Cleaning and coherency"/> 33 <event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-back - Cleaning and coherency"/>
65 <!-- 0x48 L1D_CACHE_INVAL - Level 1 data cache invalidate -->
66 <event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/> 34 <event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/>
67 <!-- 0x4C L1D_TLB_REFILL_LD - Level 1 data TLB refill - Read -->
68 <event event="0x4C" title="Cache" name="L1 data refill read" description="Level 1 data TLB refill - Read"/> 35 <event event="0x4C" title="Cache" name="L1 data refill read" description="Level 1 data TLB refill - Read"/>
69 <!-- 0x4D L1D_TLB_REFILL_ST - Level 1 data TLB refill - Write -->
70 <event event="0x4D" title="Cache" name="L1 data refill write" description="Level 1 data TLB refill - Write"/> 36 <event event="0x4D" title="Cache" name="L1 data refill write" description="Level 1 data TLB refill - Write"/>
71 <!-- 0x50 L2D_CACHE_LD - Level 2 data cache access - Read -->
72 <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/> 37 <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
73 <!-- 0x51 L2D_CACHE_ST - Level 2 data cache access - Write -->
74 <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/> 38 <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
75 <!-- 0x52 L2D_CACHE_REFILL_LD - Level 2 data cache refill - Read -->
76 <event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/> 39 <event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/>
77 <!-- 0x53 L2D_CACHE_REFILL_ST - Level 2 data cache refill - Write -->
78 <event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill - Write"/> 40 <event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill - Write"/>
79 <!-- 0x56 L2D_CACHE_WB_VICTIM - Level 2 data cache Write-back - Victim -->
80 <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-back - Victim"/> 41 <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-back - Victim"/>
81 <!-- 0x57 L2D_CACHE_WB_CLEAN - Level 2 data cache Write-back - Cleaning and coherency -->
82 <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-back - Cleaning and coherency"/> 42 <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-back - Cleaning and coherency"/>
83 <!-- 0x58 L2D_CACHE_INVAL - Level 2 data cache invalidate -->
84 <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/> 43 <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/>
85 <!-- 0x60 BUS_ACCESS_LD - Bus access - Read -->
86 <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/> 44 <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
87 <!-- 0x61 BUS_ACCESS_ST - Bus access - Write -->
88 <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/> 45 <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/>
89 <!-- 0x62 BUS_ACCESS_SHARED - Bus access - Normal -->
90 <event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/> 46 <event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/>
91 <!-- 0x63 BUS_ACCESS_NOT_SHARED - Bus access - Not normal -->
92 <event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/> 47 <event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/>
93 <!-- 0x64 BUS_ACCESS_NORMAL - Bus access - Normal -->
94 <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/> 48 <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/>
95 <!-- 0x65 BUS_ACCESS_PERIPH - Bus access - Peripheral -->
96