aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew Richardson <drew.richardson@arm.com>2012-10-13 12:00:00 -0700
committerDrew Richardson <drew.richardson@arm.com>2014-12-19 15:31:23 -0800
commitb04e8aefeed42f23955e88c7aa1611e49bdf5909 (patch)
treeeeee0f97880889c93457dfe96bdc96e487864506
parent5f9955b9c65967a7a62f7860295d8ac187c9ec11 (diff)
gator: Version 5.125.12
Signed-off-by: Drew Richardson <drew.richardson@arm.com>
-rw-r--r--README_Streamline.txt68
-rw-r--r--daemon/CapturedXML.cpp26
-rw-r--r--daemon/CapturedXML.h4
-rw-r--r--daemon/Child.cpp7
-rw-r--r--daemon/Collector.cpp5
-rw-r--r--daemon/ConfigurationXML.cpp32
-rw-r--r--daemon/ConfigurationXML.h3
-rw-r--r--daemon/LocalCapture.cpp96
-rw-r--r--daemon/LocalCapture.h5
-rw-r--r--daemon/Makefile11
-rw-r--r--daemon/OlyUtility.cpp4
-rw-r--r--daemon/Sender.cpp5
-rw-r--r--daemon/Sender.h1
-rw-r--r--daemon/SessionData.cpp21
-rw-r--r--daemon/SessionData.h8
-rw-r--r--daemon/SessionXML.cpp35
-rw-r--r--daemon/SessionXML.h4
-rw-r--r--daemon/StreamlineSetup.cpp69
-rw-r--r--daemon/StreamlineSetup.h1
-rw-r--r--daemon/configuration.xml70
-rw-r--r--daemon/events-ARM11.xml8
-rw-r--r--daemon/events-ARM11MPCore.xml8
-rw-r--r--daemon/events-Cortex-A15.xml12
-rw-r--r--daemon/events-Cortex-A5.xml7
-rw-r--r--daemon/events-Cortex-A7.xml9
-rw-r--r--daemon/events-Cortex-A8.xml9
-rw-r--r--daemon/events-Cortex-A9.xml11
-rw-r--r--daemon/events-Krait-architected.xml9
-rw-r--r--daemon/events-L2C-310.xml7
-rw-r--r--daemon/events-Linux.xml6
-rw-r--r--daemon/events-Mali-400.xml53
-rw-r--r--daemon/events-Scorpion.xml9
-rw-r--r--daemon/events-ScorpionMP.xml9
-rw-r--r--daemon/main.cpp55
-rw-r--r--driver/Makefile4
-rw-r--r--driver/gator.h25
-rw-r--r--driver/gator_annotate.c39
-rw-r--r--driver/gator_annotate_kernel.c89
-rw-r--r--driver/gator_backtrace.c15
-rw-r--r--driver/gator_cookies.c52
-rw-r--r--driver/gator_ebs.c156
-rw-r--r--driver/gator_events_block.c70
-rw-r--r--driver/gator_events_mali_400.c2
-rw-r--r--driver/gator_events_mali_400.h15
-rw-r--r--driver/gator_events_mali_common.c15
-rw-r--r--driver/gator_events_mali_common.h19
-rw-r--r--driver/gator_events_mali_t6xx.c15
-rw-r--r--driver/gator_events_mali_t6xx_hw.c214
-rw-r--r--driver/gator_events_mali_t6xx_hw_test.c57
-rw-r--r--driver/gator_events_mmaped.c8
-rw-r--r--driver/gator_events_net.c4
-rw-r--r--driver/gator_events_perf_pmu.c55
-rw-r--r--driver/gator_main.c254
-rw-r--r--driver/gator_marshaling.c152
-rw-r--r--driver/gator_pack.c25
-rw-r--r--driver/gator_trace_gpu.c37
-rw-r--r--driver/gator_trace_power.c26
-rw-r--r--driver/gator_trace_sched.c17
-rw-r--r--driver/mali_t6xx.mk3
59 files changed, 1080 insertions, 975 deletions
diff --git a/README_Streamline.txt b/README_Streamline.txt
index c39b34c..f8309e1 100644
--- a/README_Streamline.txt
+++ b/README_Streamline.txt
@@ -9,37 +9,47 @@ The driver should be built as a module and the daemon must run with root permiss
A linux development environment with cross compiling tools is most likely required, depending on what is already created and provided.
-For users, the ideal environment is to be given a BSP with gatord and gator.ko already running on a properly configured kernel. In such a scenario, a development environment is not needed, root permission may or may not be needed (gatord must be executed with root permissions but can be automatically started, see below), and the user can run Streamline and profile the system without any setup.
--The ideal development environment has the kernel source code available to be rebuilt and executed on the target. This environment allows the greatest flexibility in configuring the kernel and building the gator driver module.
+-The ideal development environment has the kernel source code available to be rebuilt, usually by cross-compiling on a host machine. This environment allows the greatest flexibility in configuring the kernel and building the gator driver module.
-However, it is possible that a user/developer has a kernel but does not have the source code. In this scenario it may or may not be possible to obtain a valid profile.
- -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.
- -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.
+ -First, check if the kernel has the proper configuration options (see below). Profiling cannot occur using a kernel that is not configured properly, a new kernel must be created. See if /proc/config.gz exists on the target.
+ -Second, given a properly configured kernel, check if the filesystem contains the kernel source/headers, which can be used to re-create the gator driver. These files may be located in different areas, but common locations are /lib/modules/ and /usr/src.
-If the kernel is not properly configured or sources/headers are not available, the developer is on their own and kernel creation is beyond the scope of this document. Note: It is possible for a module to work when compiled against a similar kernel source code, though this is not guaranteed to work due to differences in kernel structures, exported symbols and incompatible configuration parameters.
-*** Preparing and building the kernel ***
+*** Kernel configuration ***
-cd into the root source dir of the linux kernel
-if your target has never been configured, choose the appropriate configuration for your target
- make ARCH=arm CROSS_COMPILE=${CROSS_TOOLS}/bin/arm-none-linux-gnueabi- <platform_defconfig>
-make ARCH=arm CROSS_COMPILE=${CROSS_TOOLS}/bin/arm-none-linux-gnueabi- menuconfig
-
-Required Kernel Changes (depending on the kernel version, the location of these configuration settings within menuconfig may be different)
+menuconfig options (depending on the kernel version, the location of these configuration settings within menuconfig may differ)
- General Setup
- - [*] Profiling Support
+ - Kernel Performance Events And Counters
+ - [*] Kernel performance events and counters (enables CONFIG_PERF_EVENTS)
+ - [*] Profiling Support (enables CONFIG_PROFILING)
+- Kernel Features
+ - [*] High Resolution Timer Support (enables CONFIG_HIGH_RES_TIMERS)
+ - [*] Use local timer interrupts (only required for SMP, enables CONFIG_LOCAL_TIMERS)
+ - [*] Enable hardware performance counter support for perf events (enables CONFIG_HW_PERF_EVENTS)
+- CPU Power Management
+ - CPU Frequency scaling
+ - [*] CPU Frequency scaling (enables CONFIG_CPU_FREQ)
- Kernel hacking
+ - [*] Mutex debugging: basic checks (optional, enables CONFIG_DEBUG_MUTEXES)
+ - [*] Compile the kernel with debug info (optional, enables CONFIG_DEBUG_INFO)
- [*] Tracers
- - [*] Trace process context switches and events
-- Kernel Features
- - [*] High Resolution Timer Support
- - [*] Use local timer interrupts (only required for SMP)
+ - [*] Trace process context switches and events (#)
-The "context switches and events" option will not be available if other trace configurations are enabled. Other trace configurations being enabled is sufficient to turn on context switches and events.
+(#) The "Trace process context switches and events" is not the only option that enables tracing (CONFIG_GENERIC_TRACER or CONFIG_TRACING) and may not be visible in menuconfig as an option if other trace configurations are enabled. Other trace configurations being enabled is sufficient to turn on tracing.
-Optional Kernel Changes (depending on the kernel version, the location of these configuration settings within menuconfig may be different)
-Note: Configurations may not be supported on all targets
-- System Type
- - [*] <SoC name> debugging peripherals (enable core performance counters on supported SoCs) /* kernels before 2.6.35 */
+The configuration options:
+CONFIG_GENERIC_TRACER or CONFIG_TRACING
+CONFIG_PROFILING
+CONFIG_HIGH_RES_TIMERS
+CONFIG_LOCAL_TIMERS (for SMP systems)
+CONFIG_PERF_EVENTS and CONFIG_HW_PERF_EVENTS (kernel versions 3.0 and greater)
+CONFIG_DEBUG_MUTEXES (optional, provides 'mutex' as a reason code when a thread stops running)
+CONFIG_DEBUG_INFO (optional, used for analyzing the kernel)
+CONFIG_CPU_FREQ (optional, provides frequency setting of the CPU)
-make -j5 ARCH=arm CROSS_COMPILE=${CROSS_TOOLS}/bin/arm-none-linux-gnueabi- uImage
+These may be verified on a running system using /proc/config.gz (if this file exists) by running 'zcat /proc/config.gz | grep <option>'. For example, confirming that CONFIG_PROFILING is enabled
+ > zcat /proc/config.gz | grep CONFIG_PROFILING
+ CONFIG_PROFILING=y
*** Checking the gator requirements ***
@@ -53,7 +63,7 @@ To create the gator.ko module,
cd gator-driver
make -C <kernel_build_dir> M=`pwd` ARCH=arm CROSS_COMPILE=<...> modules
for example
- make -C /home/username/kernel_2.6.32/ M=`pwd` ARCH=arm CROSS_COMPILE=/home/username/CodeSourcery/Sourcery_G++_Lite/bin/arm-none-linux-gnueabi- modules
+ make -C /home/username/kernel_2.6.32/ M=`pwd` ARCH=arm CROSS_COMPILE=/usr/local/DS-5/bin/arm-linux-gnueabihf- modules
If successful, a gator.ko module should be generated
*** Building the gator daemon ***
@@ -75,7 +85,7 @@ For Android targets (install the android ndk, see developer.android.com)
Load the kernel onto the target and copy gatord and gator.ko into the target's filesystem.
Ensure gatord has execute permissions
chmod +x gatord
-gator.ko must be located in the same directory as gatord on the target or the location specified with the -m option.
+gator.ko must be located in the same directory as gatord on the target or the location specified with the -m option or already insmod'ed.
With root privileges, run the daemon
sudo ./gatord &
Note: gatord requires libstdc++.so.6 which is usually supplied by the Linux distribution on the target. A copy of libstdc++.so.6 is available in the DS-5 Linux example distribution.
@@ -85,7 +95,8 @@ Note: gatord requires libstdc++.so.6 which is usually supplied by the Linux dist
Recommended compiler settings:
"-g": Debug symbols needed for best analysis results.
"-fno-inline": Speed improvement when processing the image files and most accurate analysis results.
- "-fno-omit-frame-pointer": ARM EABI frame pointers (Code Sourcery cross compiler) allow the call stack to be recorded with each sample taken when in ARM state (i.e. not -mthumb).
+ "-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).
+ "-marm": This option is required if your compiler is configured with --with-mode=thumb, otherwise call stack unwinding will not work.
*** Hardfloat EABI ***
Binary applications built for the soft or softfp ABI are not compatible on a hardfloat system. All soft/softfp applications need to be rebuilt for hardfloat. The included compiler with DS-5 supports hardfloat.
@@ -94,13 +105,9 @@ Attempting to run an incompatible binary often results in the confusing error me
*** Profiling the kernel (optional) ***
-make ARCH=arm CROSS_COMPILE=$(CROSS_TOOLS}/bin/arm-none-linux-gnueabi- menuconfig
-- Kernel Hacking
- - [*] Compile the kernel with debug info
-
-make -j5 ARCH=arm CROSS_COMPILE=${CROSS_TOOLS}/bin/arm-none-linux-gnueabi- uImage
+CONFIG_DEBUG_INFO must be enabled, see "Kernel configuration" section above.
Use vmlinux as the image for debug symbols in Streamline.
-Drivers may be profiled using this method by statically linking the driver into the kernel image or adding the module as an image.
+Drivers may be profiled using this method by statically linking the driver into the kernel image or adding the driver as an image to Streamline.
To perform kernel stack unwinding and module unwinding, edit the Makefile to enable GATOR_KERNEL_STACK_UNWINDING and rebuild gator.ko.
*** Automatically start gator on boot (optional) ***
@@ -114,3 +121,4 @@ update-rc.d rungator.sh defaults
*** GPL License ***
For license information, please see the file LICENSE after unzipping driver-src/gator-driver.tar.gz.
+
diff --git a/daemon/CapturedXML.cpp b/daemon/CapturedXML.cpp
index f02ed2a..30d984f 100644
--- a/daemon/CapturedXML.cpp
+++ b/daemon/CapturedXML.cpp
@@ -22,12 +22,12 @@ CapturedXML::CapturedXML() {
CapturedXML::~CapturedXML() {
}
-mxml_node_t* CapturedXML::getTree() {
+mxml_node_t* CapturedXML::getTree(bool includeTime) {
bool perfCounters = false;
mxml_node_t *xml;
- mxml_node_t *captured;
- mxml_node_t *target;
- mxml_node_t *counters;
+ mxml_node_t *captured;
+ mxml_node_t *target;
+ mxml_node_t *counters;
mxml_node_t *counter;
int x;
@@ -43,11 +43,10 @@ mxml_node_t* CapturedXML::getTree() {
captured = mxmlNewElement(xml, "captured");
mxmlElementSetAttr(captured, "version", "1");
mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION);
- if (gSessionData->mBytes > 0) { // Send the following only after the capture is complete
+ if (includeTime) { // Send the following only after the capture is complete
if (time(NULL) > 1267000000) { // If the time is reasonable (after Feb 23, 2010)
mxmlElementSetAttrf(captured, "created", "%lu", time(NULL)); // Valid until the year 2038
}
- mxmlElementSetAttrf(captured, "bytes", "%d", gSessionData->mBytes);
}
target = mxmlNewElement(captured, "target");
@@ -69,18 +68,9 @@ mxml_node_t* CapturedXML::getTree() {
if (gSessionData->mPerfCounterPerCPU[x]) {
mxmlElementSetAttr(counter, "per_cpu", "yes");
}
- if (strlen(gSessionData->mPerfCounterOperation[x]) > 0) {
- mxmlElementSetAttr(counter, "operation", gSessionData->mPerfCounterOperation[x]);
- }
if (gSessionData->mPerfCounterCount[x] > 0) {
mxmlElementSetAttrf(counter, "count", "%d", gSessionData->mPerfCounterCount[x]);
}
- if (gSessionData->mPerfCounterLevel[x]) {
- mxmlElementSetAttr(counter, "level", "yes");
- }
- if (strlen(gSessionData->mPerfCounterAlias[x]) > 0) {
- mxmlElementSetAttr(counter, "alias", gSessionData->mPerfCounterAlias[x]);
- }
if (strlen(gSessionData->mPerfCounterDisplay[x]) > 0) {
mxmlElementSetAttr(counter, "display", gSessionData->mPerfCounterDisplay[x]);
}
@@ -98,9 +88,9 @@ mxml_node_t* CapturedXML::getTree() {
return xml;
}
-char* CapturedXML::getXML() {
+char* CapturedXML::getXML(bool includeTime) {
char* xml_string;
- mxml_node_t *xml = getTree();
+ mxml_node_t *xml = getTree(includeTime);
xml_string = mxmlSaveAllocString(xml, mxmlWhitespaceCB);
mxmlDelete(xml);
return xml_string;
@@ -112,7 +102,7 @@ void CapturedXML::write(char* path) {
// Set full path
snprintf(file, PATH_MAX, "%s/captured.xml", path);
- char* xml = getXML();
+ char* xml = getXML(true);
if (util->writeToDisk(file, xml) < 0) {
logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
handleException();
diff --git a/daemon/CapturedXML.h b/daemon/CapturedXML.h
index 984d1f2..3f6a4de 100644
--- a/daemon/CapturedXML.h
+++ b/daemon/CapturedXML.h
@@ -16,10 +16,10 @@ class CapturedXML {
public:
CapturedXML();
~CapturedXML();
- char* getXML(); // the string should be freed by the caller
+ char* getXML(bool includeTime); // the string should be freed by the caller
void write(char* path);
private:
- mxml_node_t* getTree();
+ mxml_node_t* getTree(bool includeTime);
};
#endif //__CAPTURED_XML_H__
diff --git a/daemon/Child.cpp b/daemon/Child.cpp
index 2c7c292..b97e0db 100644
--- a/daemon/Child.cpp
+++ b/daemon/Child.cpp
@@ -102,7 +102,10 @@ void* stopThread(void* pVoid) {
prctl(PR_SET_NAME, (unsigned long)&"gatord-stopper", 0, 0, 0);
while (gSessionData->mSessionIsActive) {
// This thread will stall until the APC_STOP or PING command is received over the socket or the socket is disconnected
- if (socket->receiveNBytes(&type, sizeof(type)) > 0) {
+ const int result = socket->receiveNBytes(&type, sizeof(type));
+ if (result == -1) {
+ child->endSession();
+ } else if (result > 0) {
if ((type != COMMAND_APC_STOP) && (type != COMMAND_PING)) {
logg->logMessage("INVESTIGATE: Received unknown command type %d", type);
} else {
@@ -228,7 +231,7 @@ void Child::run() {
}
gSessionData->parseSessionXML(xmlString);
localCapture = new LocalCapture();
- localCapture->createAPCDirectory(gSessionData->mTargetPath, gSessionData->mTitle);
+ localCapture->createAPCDirectory(gSessionData->mTargetPath);
localCapture->copyImages(gSessionData->mImages);
localCapture->write(xmlString);
sender->createDataFile(gSessionData->mAPCDir);
diff --git a/daemon/Collector.cpp b/daemon/Collector.cpp
index d29cd16..25bb934 100644
--- a/daemon/Collector.cpp
+++ b/daemon/Collector.cpp
@@ -202,7 +202,10 @@ void Collector::stop() {
int Collector::collect(char* buffer) {
// Calls event_buffer_read in the driver
- int bytesRead = read(mBufferFD, buffer, mBufferSize);
+ int bytesRead;
+
+ errno = 0;
+ bytesRead = read(mBufferFD, buffer, mBufferSize);
// If read() returned due to an interrupt signal, re-read to obtain the last bit of collected data
if (bytesRead == -1 && errno == EINTR) {
diff --git a/daemon/ConfigurationXML.cpp b/daemon/ConfigurationXML.cpp
index 145ddbd..df83697 100644
--- a/daemon/ConfigurationXML.cpp
+++ b/daemon/ConfigurationXML.cpp
@@ -21,20 +21,19 @@ static const char* ATTR_REVISION = "revision";
static const char* ATTR_TITLE = "title";
static const char* ATTR_NAME = "name";
static const char* ATTR_EVENT = "event";
-static const char* ATTR_COLOR = "color";
static const char* ATTR_COUNT = "count";
-static const char* ATTR_OPERATION = "operation";
static const char* ATTR_PER_CPU = "per_cpu";
static const char* ATTR_DESCRIPTION = "description";
-static const char* ATTR_EBS = "event_based_sampling";
-static const char* ATTR_LEVEL = "level";
-static const char* ATTR_ALIAS = "alias";
+static const char* ATTR_EBS = "supports_event_based_sampling";
static const char* ATTR_DISPLAY = "display";
static const char* ATTR_UNITS = "units";
static const char* ATTR_AVERAGE_SELECTION = "average_selection";
ConfigurationXML::ConfigurationXML() {
-#include "configuration_xml.h" // defines and initializes char configuration_xml[] and int configuration_xml_len
+ const char * configuration_xml;
+ unsigned int configuration_xml_len;
+ getDefaultConfigurationXml(configuration_xml, configuration_xml_len);
+
mIndex = 0;
char* path = (char*)malloc(PATH_MAX);
@@ -61,6 +60,9 @@ ConfigurationXML::ConfigurationXML() {
gSessionData->mPerfCounterEnabled[i] = 0;
}
+ // clear counter overflow
+ gSessionData->mCounterOverflow = false;
+
int ret = parse(mConfigurationXML);
if (ret == 1) {
// remove configuration.xml on disk to use the default
@@ -151,8 +153,8 @@ int ConfigurationXML::configurationsTag(mxml_node_t *node) {
void ConfigurationXML::configurationTag(mxml_node_t *node) {
// handle all other performance counters
if (mIndex >= MAX_PERFORMANCE_COUNTERS) {
- logg->logError(__FILE__, __LINE__, "Exceeded maximum number of %d performance counters", MAX_PERFORMANCE_COUNTERS);
- handleException();
+ gSessionData->mCounterOverflow = true;
+ return;
}
// read attributes
@@ -162,12 +164,8 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) {
if (mxmlElementGetAttr(node, ATTR_DESCRIPTION)) strncpy(gSessionData->mPerfCounterDescription[mIndex], mxmlElementGetAttr(node, ATTR_DESCRIPTION), sizeof(gSessionData->mPerfCounterDescription[mIndex]));
if (mxmlElementGetAttr(node, ATTR_EVENT)) gSessionData->mPerfCounterEvent[mIndex] = strtol(mxmlElementGetAttr(node, ATTR_EVENT), NULL, 16);
if (mxmlElementGetAttr(node, ATTR_COUNT)) gSessionData->mPerfCounterCount[mIndex] = strtol(mxmlElementGetAttr(node, ATTR_COUNT), NULL, 10);
- if (mxmlElementGetAttr(node, ATTR_COLOR)) gSessionData->mPerfCounterColor[mIndex] = strtol(mxmlElementGetAttr(node, ATTR_COLOR), NULL, 16);
if (mxmlElementGetAttr(node, ATTR_PER_CPU)) gSessionData->mPerfCounterPerCPU[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_PER_CPU), false);
if (mxmlElementGetAttr(node, ATTR_EBS)) gSessionData->mPerfCounterEBSCapable[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_EBS), false);
- if (mxmlElementGetAttr(node, ATTR_OPERATION)) strncpy(gSessionData->mPerfCounterOperation[mIndex], mxmlElementGetAttr(node, ATTR_OPERATION), sizeof(gSessionData->mPerfCounterOperation[mIndex]));
- if (mxmlElementGetAttr(node, ATTR_LEVEL)) gSessionData->mPerfCounterLevel[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_LEVEL), false);
- if (mxmlElementGetAttr(node, ATTR_ALIAS)) strncpy(gSessionData->mPerfCounterAlias[mIndex], mxmlElementGetAttr(node, ATTR_ALIAS), sizeof(gSessionData->mPerfCounterAlias[mIndex]));
if (mxmlElementGetAttr(node, ATTR_DISPLAY)) strncpy(gSessionData->mPerfCounterDisplay[mIndex], mxmlElementGetAttr(node, ATTR_DISPLAY), sizeof(gSessionData->mPerfCounterDisplay[mIndex]));
if (mxmlElementGetAttr(node, ATTR_UNITS)) strncpy(gSessionData->mPerfCounterUnits[mIndex], mxmlElementGetAttr(node, ATTR_UNITS), sizeof(gSessionData->mPerfCounterUnits[mIndex]));
if (mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION)) gSessionData->mPerfCounterAverageSelection[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION), false);
@@ -178,11 +176,17 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) {
gSessionData->mPerfCounterTitle[mIndex][sizeof(gSessionData->mPerfCounterTitle[mIndex]) - 1] = 0;
gSessionData->mPerfCounterName[mIndex][sizeof(gSessionData->mPerfCounterName[mIndex]) - 1] = 0;
gSessionData->mPerfCounterDescription[mIndex][sizeof(gSessionData->mPerfCounterDescription[mIndex]) - 1] = 0;
- gSessionData->mPerfCounterOperation[mIndex][sizeof(gSessionData->mPerfCounterOperation[mIndex]) - 1] = 0;
- gSessionData->mPerfCounterAlias[mIndex][sizeof(gSessionData->mPerfCounterAlias[mIndex]) - 1] = 0;
gSessionData->mPerfCounterDisplay[mIndex][sizeof(gSessionData->mPerfCounterDisplay[mIndex]) - 1] = 0;
gSessionData->mPerfCounterUnits[mIndex][sizeof(gSessionData->mPerfCounterUnits[mIndex]) - 1] = 0;
// update counter index
mIndex++;
}
+
+void ConfigurationXML::getDefaultConfigurationXml(const char * & xml, unsigned int & len) {
+ // the first line of configuration_xml.h is "unsigned char configuration_xml", but configuration_xml needs to be const static as well
+ const static
+#include "configuration_xml.h" // defines and initializes char configuration_xml[] and int configuration_xml_len
+ xml = (const char *)configuration_xml;
+ len = configuration_xml_len;
+}
diff --git a/daemon/ConfigurationXML.h b/daemon/ConfigurationXML.h
index b48d32f..66ad587 100644
--- a/daemon/ConfigurationXML.h
+++ b/daemon/ConfigurationXML.h
@@ -13,10 +13,13 @@
class ConfigurationXML {
public:
+ static void getDefaultConfigurationXml(const char * & xml, unsigned int & len);
+
ConfigurationXML();
~ConfigurationXML();
const char* getConfigurationXML() {return mConfigurationXML;}
void validate(void);
+
private:
char* mConfigurationXML;
int mIndex;
diff --git a/daemon/LocalCapture.cpp b/daemon/LocalCapture.cpp
index 6449d03..f8cd17f 100644
--- a/daemon/LocalCapture.cpp
+++ b/daemon/LocalCapture.cpp
@@ -23,8 +23,8 @@ LocalCapture::LocalCapture() {}
LocalCapture::~LocalCapture() {}
-void LocalCapture::createAPCDirectory(char* target_path, char* name) {
- gSessionData->mAPCDir = createUniqueDirectory(target_path, ".apc", name);
+void LocalCapture::createAPCDirectory(char* target_path) {
+ gSessionData->mAPCDir = createUniqueDirectory(target_path, ".apc");
if ((removeDirAndAllContents(gSessionData->mAPCDir) != 0 || mkdir(gSessionData->mAPCDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)) {
logg->logError(__FILE__, __LINE__, "Unable to create directory %s", gSessionData->mAPCDir);
handleException();
@@ -46,17 +46,14 @@ void LocalCapture::write(char* string) {
free(file);
}
-char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* ending, char* title) {
- int i;
+char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* ending) {
char* output;
char* path = (char*)malloc(PATH_MAX);
// Ensure the path is an absolute path, i.e. starts with a slash
if (initialPath == 0 || strlen(initialPath) == 0) {
- if (getcwd(path, PATH_MAX) == 0) {
- logg->logMessage("Unable to retrive the current working directory");
- }
- strncat(path, "/@F_@N", PATH_MAX - strlen(path) - 1);
+ logg->logError(__FILE__, __LINE__, "Missing -o command line option required for a local capture.");
+ handleException();
} else if (initialPath[0] != '/') {
if (getcwd(path, PATH_MAX) == 0) {
logg->logMessage("Unable to retrive the current working directory");
@@ -68,98 +65,17 @@ char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* e
path[PATH_MAX - 1] = 0; // strncpy does not guarantee a null-terminated string
}
- // Convert to uppercase
- replaceAll(path, "@f", "@F", PATH_MAX);
- replaceAll(path, "@n", "@N", PATH_MAX);
-
- // Replace @F with the session xml title
- replaceAll(path, "@F", title, PATH_MAX);
-
// Add ending if it is not already there
if (strcmp(&path[strlen(path) - strlen(ending)], ending) != 0) {
strncat(path, ending, PATH_MAX - strlen(path) - 1);
}
- // Replace @N with a unique integer
- if (strstr(path, "@N")) {
- char* tempPath = (char*)malloc(PATH_MAX);
- for (i = 1; i < 1000; i++) {
- char number[4];
- snprintf(number, sizeof(number), "%03d", i);
- strcpy(tempPath, path);
- replaceAll(tempPath, "@N", number, PATH_MAX);
- struct stat mFileInfo;
- if (stat(tempPath, &mFileInfo) != 0) {
- // if the direcotry does not exist, break
- break;
- }
- }
-
- if (i == 1000) {
- logg->logError(__FILE__, __LINE__, "Unable to create .apc directory, please delete older directories.");
- handleException();
- }
-
- output = strdup(tempPath);
- free(tempPath);
- } else {
- output = strdup(path);
- }
+ output = strdup(path);
free(path);
return output;
}
-//Replaces all occurrences of <find> in <target> with <replace> provided enough <size> is available
-void LocalCapture::replaceAll(char* target, const char* find, const char* replace, unsigned int size) {
- char* nextOccurrence;
- unsigned int count = 0;
-
- // Duplicate the original string
- char* original = strdup(target);
- char* ptr = original;
-
- // Determine number of <find>s
- ptr = strstr(ptr, find);
- while (ptr) {
- count++;
- ptr += strlen(find);
- ptr = strstr(ptr, find);
- }
-
- // Is there enough space available
- if (strlen(target) + (strlen(replace) - strlen(find)) * count > size - 1) {
- free(original);
- return;
- }
-
- // Reset
- ptr = original;
-
- nextOccurrence = strstr(ptr, find);
- while (nextOccurrence) {
- // Move pointers to location of replace
- int length = nextOccurrence - ptr;
- target += length;
- ptr += length;
-
- // Replace <find> with <replace>
- memcpy(target, replace, strlen(replace));
-
- // Increment over <replace>/<find>
- target += strlen(replace);
- ptr += strlen(find);
-
- // Copy remainder of ptr
- strcpy(target, ptr);
-
- // Get next occurrence
- nextOccurrence = strstr(ptr, find);
- }
-
- free(original);
-}
-
int LocalCapture::removeDirAndAllContents(char* path) {
int error = 0;
struct stat mFileInfo;
diff --git a/daemon/LocalCapture.h b/daemon/LocalCapture.h
index ca37f6e..40f7883 100644
--- a/daemon/LocalCapture.h
+++ b/daemon/LocalCapture.h
@@ -17,10 +17,9 @@ public:
~LocalCapture();
void write(char* string);
void copyImages(ImageLinkList* ptr);
- void createAPCDirectory(char* target_path, char* name);
+ void createAPCDirectory(char* target_path);
private:
- char* createUniqueDirectory(const char* path, const char* ending, char* title);
- void replaceAll(char* target, const char* find, const char* replace, unsigned int size);
+ char* createUniqueDirectory(const char* path, const char* ending);
int removeDirAndAllContents(char* path);
};
diff --git a/daemon/Makefile b/daemon/Makefile
index b62a223..5562db7 100644
--- a/daemon/Makefile
+++ b/daemon/Makefile
@@ -3,7 +3,11 @@
#
# Uncomment and define CROSS_COMPILE if it is not already defined
-# CROSS_COMPILE=/path/to/cross-compiler/arm-none-linux-gnueabi-
+# CROSS_COMPILE=/path/to/cross-compiler/arm-linux-gnueabihf-
+# NOTE: This toolchain uses the hardfloat abi by default. For non-hardfloat
+# targets it is necessary to add options
+# '-marm -march=armv4t -mfloat-abi=soft'.
+
ARCH=arm
CPP=$(CROSS_COMPILE)g++
@@ -17,7 +21,10 @@ GCC=$(CROSS_COMPILE)gcc
# -std=c++0x is the planned new c++ standard
# -std=c++98 is the 1998 c++ standard
# -mthumb-interwork is required for interworking to ARM or Thumb stdlibc
-CFLAGS=-O3 -Wall -Werror -Wno-error=sequence-point -mthumb-interwork
+CFLAGS=-O3 -Wall -mthumb-interwork
+ifeq ($(WERROR),1)
+ CFLAGS += -Werror
+endif
# -s strips the binary of debug info
LDFLAGS=-s
TARGET=gatord
diff --git a/daemon/OlyUtility.cpp b/daemon/OlyUtility.cpp
index c72b0d1..adc7aba 100644
--- a/daemon/OlyUtility.cpp
+++ b/daemon/OlyUtility.cpp
@@ -24,6 +24,10 @@ OlyUtility* util = NULL;
bool OlyUtility::stringToBool(const char* string, bool defValue) {
char value[32];
+ if (string == NULL) {
+ return defValue;
+ }
+
strncpy(value, string, sizeof(value));
if (value[0] == 0) {
return defValue;
diff --git a/daemon/Sender.cpp b/daemon/Sender.cpp
index efff753..eba8343 100644
--- a/daemon/Sender.cpp
+++ b/daemon/Sender.cpp
@@ -38,8 +38,9 @@ Sender::Sender(OlySocket* socket) {
}
// Send magic sequence - must be done first, afterwhich error messages can be sent
- char magic[] = {'G', 'A', 'T', 'O', 'R', '\n'};
- mDataSocket->send(magic, sizeof(magic));
+ char magic[32];
+ snprintf(magic, 32, "GATOR %i\n", PROTOCOL_VERSION);
+ mDataSocket->send(magic, strlen(magic));
gSessionData->mWaitingOnCommand = true;
logg->logMessage("Completed magic sequence");
diff --git a/daemon/Sender.h b/daemon/Sender.h
index 98467e0..ceab343 100644
--- a/daemon/Sender.h
+++ b/daemon/Sender.h
@@ -14,7 +14,6 @@
#include "OlySocket.h"
enum {
- RESPONSE_END = 0, // unused
RESPONSE_XML = 1,
RESPONSE_APC_DATA = 3,
RESPONSE_ACK = 4,
diff --git a/daemon/SessionData.cpp b/daemon/SessionData.cpp
index a245369..5aa3f11 100644
--- a/daemon/SessionData.cpp
+++ b/daemon/SessionData.cpp
@@ -30,10 +30,10 @@ void SessionData::initialize() {
mConfigurationXMLPath = NULL;
mSessionXMLPath = NULL;
mEventsXMLPath = NULL;
+ mTargetPath = NULL;
mAPCDir = NULL;
mSampleRate = 0;
mDuration = 0;
- mBytes = 0;
mBacktraceDepth = 0;
mTotalBufferSize = 0;
mCores = 1;
@@ -48,8 +48,6 @@ void SessionData::initializeCounters() {
mPerfCounterTitle[i][0] = 0;
mPerfCounterName[i][0] = 0;
mPerfCounterDescription[i][0] = 0;
- mPerfCounterOperation[i][0] = 0;
- mPerfCounterAlias[i][0] = 0;
mPerfCounterDisplay[i][0] = 0;
mPerfCounterUnits[i][0] = 0;
mPerfCounterEnabled[i] = 0;
@@ -59,7 +57,6 @@ void SessionData::initializeCounters() {
mPerfCounterCount[i] = 0;
mPerfCounterPerCPU[i] = false;
mPerfCounterEBSCapable[i] = false;
- mPerfCounterLevel[i] = false;
mPerfCounterAverageSelection[i] = false;
}
}
@@ -68,15 +65,6 @@ void SessionData::parseSessionXML(char* xmlString) {
SessionXML session(xmlString);
session.parse();
- // Parameter error checking
- if (session.parameters.output_path == 0 && session.parameters.target_path == 0) {
- logg->logError(__FILE__, __LINE__, "No capture path (target or host) was provided.");
- handleException();
- } else if (gSessionData->mLocalCapture && session.parameters.target_path == 0) {
- logg->logError(__FILE__, __LINE__, "Missing target_path tag in session xml required for a local capture.");
- handleException();
- }
-
// Set session data values
if (strcmp(session.parameters.sample_rate, "high") == 0) {
gSessionData->mSampleRate = 10000;
@@ -84,8 +72,11 @@ void SessionData::parseSessionXML(char* xmlString) {
gSessionData->mSampleRate = 1000;
} else if (strcmp(session.parameters.sample_rate, "low") == 0) {
gSessionData->mSampleRate = 100;
- } else {
+ } else if (strcmp(session.parameters.sample_rate, "none") == 0) {
gSessionData->mSampleRate = 0;
+ } else {
+ logg->logError(__FILE__, __LINE__, "Invalid sample rate (%s) in session xml.", session.parameters.sample_rate);
+ handleException();
}
gSessionData->mBacktraceDepth = session.parameters.call_stack_unwinding == true ? 128 : 0;
gSessionData->mDuration = session.parameters.duration;
@@ -107,6 +98,4 @@ void SessionData::parseSessionXML(char* xmlString) {
}
gSessionData->mImages = session.parameters.images;
- gSessionData->mTargetPath = session.parameters.target_path;
- gSessionData->mTitle = session.parameters.title;
}
diff --git a/daemon/SessionData.h b/daemon/SessionData.h
index 6f42c07..00a71b1 100644
--- a/daemon/SessionData.h
+++ b/daemon/SessionData.h
@@ -13,7 +13,7 @@
#define MAX_STRING_LEN 80
#define MAX_DESCRIPTION_LEN 400
-#define PROTOCOL_VERSION 10
+#define PROTOCOL_VERSION 11
#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions
struct ImageLinkList {
@@ -36,7 +36,6 @@ public:
char* mEventsXMLPath;
char* mTargetPath;
char* mAPCDir;
- char* mTitle;
bool mWaitingOnCommand;
bool mSessionIsActive;
@@ -48,15 +47,13 @@ public:
int mSampleRate;
int mDuration;
int mCores;
- int mBytes;
// PMU Counters
+ bool mCounterOverflow;
char mPerfCounterType[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
char mPerfCounterTitle[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
char mPerfCounterName[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
char mPerfCounterDescription[MAX_PERFORMANCE_COUNTERS][MAX_DESCRIPTION_LEN];
- char mPerfCounterOperation[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
- char mPerfCounterAlias[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
char mPerfCounterDisplay[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
char mPerfCounterUnits[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
int mPerfCounterEnabled[MAX_PERFORMANCE_COUNTERS];
@@ -66,7 +63,6 @@ public:
int mPerfCounterKey[MAX_PERFORMANCE_COUNTERS];
bool mPerfCounterPerCPU[MAX_PERFORMANCE_COUNTERS];
bool mPerfCounterEBSCapable[MAX_PERFORMANCE_COUNTERS];
- bool mPerfCounterLevel[MAX_PERFORMANCE_COUNTERS];
bool mPerfCounterAverageSelection[MAX_PERFORMANCE_COUNTERS];
};
diff --git a/daemon/SessionXML.cpp b/daemon/SessionXML.cpp
index f1a8258..4c373d8 100644
--- a/daemon/SessionXML.cpp
+++ b/daemon/SessionXML.cpp
@@ -19,21 +19,13 @@ static const char* TAG_SESSION = "session";
static const char* TAG_IMAGE = "image";
static const char* ATTR_VERSION = "version";
-static const char* ATTR_TITLE = "title";
-static const char* ATTR_UUID = "uuid";
static const char* ATTR_CALL_STACK_UNWINDING = "call_stack_unwinding";
static const char* ATTR_BUFFER_MODE = "buffer_mode";
static const char* ATTR_SAMPLE_RATE = "sample_rate";
-static const char* ATTR_TARGET_PATH = "target_path";
-static const char* ATTR_OUTPUT_PATH = "output_path";
static const char* ATTR_DURATION = "duration";
static const char* ATTR_PATH = "path";
SessionXML::SessionXML(const char* str) {
- parameters.title = 0;
- parameters.uuid[0] = 0;
- parameters.target_path = 0;
- parameters.output_path = 0;
parameters.buffer_mode[0] = 0;
parameters.sample_rate[0] = 0;
parameters.duration = 0;
@@ -75,34 +67,7 @@ void SessionXML::sessionTag(mxml_node_t *tree, mxml_node_t *node) {
handleException();
}
- // allocate strings
- if (mxmlElementGetAttr(node, ATTR_TITLE)) {
- parameters.title = strdup(mxmlElementGetAttr(node, ATTR_TITLE)); // freed when the child process exits
- if (parameters.title == NULL) {
- logg->logError(__FILE__, __LINE__, "failed to allocate parameters.title");
- handleException();
- }
- }
- if (mxmlElementGetAttr(node, ATTR_TARGET_PATH)) {
- parameters.target_path = strdup(mxmlElementGetAttr(node, ATTR_TARGET_PATH)); // freed when the child process exits
- if (parameters.target_path == NULL) {
- logg->logError(__FILE__, __LINE__, "failed to allocate parameters.target_path");
- handleException();
- }
- }
- if (mxmlElementGetAttr(node, ATTR_OUTPUT_PATH)) {
- parameters.output_path = strdup(mxmlElementGetAttr(node, ATTR_OUTPUT_PATH)); // freed when the child process exits
- if (parameters.output_path == NULL) {
- logg->logError(__FILE__, __LINE__, "failed to allocate parameters.output_path");
- handleException();
- }
- }
-
// copy to pre-allocated strings
- if (mxmlElementGetAttr(node, ATTR_UUID)) {
- strncpy(parameters.uuid, mxmlElementGetAttr(node, ATTR_UUID), sizeof(parameters.uuid));
- parameters.uuid[sizeof(parameters.uuid) - 1] = 0; // strncpy does not guarantee a null-terminated string
- }
if (mxmlElementGetAttr(node, ATTR_BUFFER_MODE)) {
strncpy(parameters.buffer_mode, mxmlElementGetAttr(node, ATTR_BUFFER_MODE), sizeof(parameters.buffer_mode));
parameters.buffer_mode[sizeof(parameters.buffer_mode) - 1] = 0; // strncpy does not guarantee a null-terminated string
diff --git a/daemon/SessionXML.h b/daemon/SessionXML.h
index c2b5489..f7a5641 100644
--- a/daemon/SessionXML.h
+++ b/daemon/SessionXML.h
@@ -13,10 +13,6 @@
#include "SessionData.h"
struct ConfigParameters {
- char* title; // status title
- char uuid[64]; // universal unique identifier
- char* target_path; // target path of where to write to disk
- char* output_path; // host path of where to write to disk
char buffer_mode[64]; // buffer mode, "streaming", "low", "normal", "high" defines oneshot and buffer size
char sample_rate[64]; // capture mode, "high", "normal", or "low"
int duration; // length of profile in seconds
diff --git a/daemon/StreamlineSetup.cpp b/daemon/StreamlineSetup.cpp
index 53729ab..3f59eab 100644
--- a/daemon/StreamlineSetup.cpp
+++ b/daemon/StreamlineSetup.cpp
@@ -28,13 +28,13 @@ static const char* TAG_SESSION = "session";
static const char* TAG_REQUEST = "request";
static const char* TAG_CONFIGURATIONS = "configurations";
-static const char* ATTR_PROTOCOL = "protocol";
-static const char* ATTR_EVENTS = "events";
-static const char* ATTR_CONFIGURATION = "configuration";
-static const char* ATTR_COUNTERS = "counters";
-static const char* ATTR_SESSION = "session";
-static const char* ATTR_CAPTURED = "captured";
-static const char* ATTR_DEFAULTS = "defaults";
+static const char* ATTR_TYPE = "type";
+static const char* VALUE_EVENTS = "events";
+static const char* VALUE_CONFIGURATION = "configuration";
+static const char* VALUE_COUNTERS = "counters";
+static const char* VALUE_SESSION = "session";
+static const char* VALUE_CAPTURED = "captured";
+static const char* VALUE_DEFAULTS = "defaults";
StreamlineSetup::StreamlineSetup(OlySocket* s) {
bool ready = false;
@@ -81,6 +81,11 @@ StreamlineSetup::StreamlineSetup(OlySocket* s) {
free(data);
}
+
+ if (gSessionData->mCounterOverflow) {
+ logg->logError(__FILE__, __LINE__, "Exceeded maximum number of %d performance counters", MAX_PERFORMANCE_COUNTERS);
+ handleException();
+ }
}
StreamlineSetup::~StreamlineSetup() {
@@ -143,30 +148,32 @@ char* StreamlineSetup::readCommand(int* command) {
void StreamlineSetup::handleRequest(char* xml) {
mxml_node_t *tree, *node;
+ const char * attr = NULL;
tree = mxmlLoadString(NULL, xml, MXML_NO_CALLBACK);
- if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_PROTOCOL, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_PROTOCOL), false)) {
- sendProtocol();
- logg->logMessage("Sent protocol xml response");
- } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_EVENTS, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_EVENTS), false)) {
+ node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_TYPE, NULL, MXML_DESCEND_FIRST);
+ if (node) {
+ attr = mxmlElementGetAttr(node, ATTR_TYPE);
+ }
+ if (attr && strcmp(attr, VALUE_EVENTS) == 0) {
sendEvents();
logg->logMessage("Sent events xml response");
- } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_CONFIGURATION, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_CONFIGURATION), false)) {
+ } else if (attr && strcmp(attr, VALUE_CONFIGURATION) == 0) {
sendConfiguration();
logg->logMessage("Sent configuration xml response");
- } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_COUNTERS, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_COUNTERS), false)) {
+ } else if (attr && strcmp(attr, VALUE_COUNTERS) == 0) {
sendCounters();
logg->logMessage("Sent counters xml response");
- } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_SESSION, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_SESSION), false)) {
+ } else if (attr && strcmp(attr, VALUE_SESSION) == 0) {
sendData(mSessionXML, strlen(mSessionXML), RESPONSE_XML);
logg->logMessage("Sent session xml response");
- } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_CAPTURED, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_CAPTURED), false)) {
+ } else if (attr && strcmp(attr, VALUE_CAPTURED) == 0) {
CapturedXML capturedXML;
- char* capturedText = capturedXML.getXML();
+ char* capturedText = capturedXML.getXML(false);
sendData(capturedText, strlen(capturedText), RESPONSE_XML);
free(capturedText);
logg->logMessage("Sent captured xml response");
- } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_DEFAULTS, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_DEFAULTS), false)) {
+ } else if (attr && strcmp(attr, VALUE_DEFAULTS) == 0) {
sendDefaults();
logg->logMessage("Sent default configuration xml response");
} else {
@@ -215,21 +222,6 @@ void StreamlineSetup::sendData(const char* data, int length, int type) {
mSocket->send((char*)data, length);
}
-void StreamlineSetup::sendProtocol() {
- mxml_node_t *xml;
- mxml_node_t *protocol;
-
- xml = mxmlNewXML("1.0");
- protocol = mxmlNewElement(xml, "protocol");
- mxmlElementSetAttrf(protocol, "version", "%d", PROTOCOL_VERSION);
-
- char* string = mxmlSaveAllocString(xml, mxmlWhitespaceCB);
- sendString(string, RESPONSE_XML);
-
- free(string);
- mxmlDelete(xml);
-}
-
void StreamlineSetup::sendEvents() {
#include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len
char* path = (char*)malloc(PATH_MAX);;
@@ -264,10 +256,10 @@ void StreamlineSetup::sendConfiguration() {
}
void StreamlineSetup::sendDefaults() {
-#include "configuration_xml.h" // defines and initializes char configuration_xml[] and int configuration_xml_len
// Send the config built into the binary
- char* xml = (char*)configuration_xml;
- unsigned int size = configuration_xml_len;
+ const char* xml;
+ unsigned int size;
+ ConfigurationXML::getDefaultConfigurationXml(xml, size);
// Artificial size restriction
if (size > 1024*1024) {
@@ -282,7 +274,7 @@ void StreamlineSetup::sendDefaults() {
void StreamlineSetup::sendCounters() {
struct dirent *ent;
mxml_node_t *xml;
- mxml_node_t *counters;
+ mxml_node_t *counters;
mxml_node_t *counter;
// counters.xml is simply a file listing of /dev/gator/events
@@ -328,4 +320,9 @@ void StreamlineSetup::writeConfiguration(char* xml) {
// Re-populate gSessionData with the configuration, as it has now changed
new ConfigurationXML();
free(path);
+
+ if (gSessionData->mCounterOverflow) {
+ logg->logError(__FILE__, __LINE__, "Exceeded maximum number of %d performance counters", MAX_PERFORMANCE_COUNTERS);
+ handleException();
+ }
}
diff --git a/daemon/StreamlineSetup.h b/daemon/StreamlineSetup.h
index c46ae08..8086fe2 100644
--- a/daemon/StreamlineSetup.h
+++ b/daemon/StreamlineSetup.h
@@ -35,7 +35,6 @@ private:
void handleDeliver(char* xml);
void sendData(const char* data, int length, int type);
void sendString(const char* string, int type) {sendData(string, strlen(string), type);}
- void sendProtocol();
void sendEvents();
void sendConfiguration();
void sendDefaults();
diff --git a/daemon/configuration.xml b/daemon/configuration.xml
index 4875f1f..fbdef31 100644
--- a/daemon/configuration.xml
+++ b/daemon/configuration.xml
@@ -1,49 +1,45 @@
<?xml version="1.0" encoding='UTF-8'?>
-<configurations version="1" revision="1">
+<configurations revision="1">
<configuration counter="ARM_ARM11_ccnt" title="Clock" name="Cycles" per_cpu="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<configuration counter="ARM_ARM11_cnt0" event="0x7" title="Instruction" name="Executed" per_cpu="yes" description="Instructions executed"/>
<configuration counter="ARM_ARM11_cnt1" event="0xb" title="Cache" name="Data miss" per_cpu="yes" description="Data cache miss, not including Cache Operations"/>
<configuration counter="ARM_ARM11MPCore_ccnt" title="Clock" name="Cycles" per_cpu="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<configuration counter="ARM_ARM11MPCore_cnt0" event="0x08" title="Core" name="Instructions" per_cpu="yes" description="Instructions executed"/>
<configuration counter="ARM_ARM11MPCore_cnt1" event="0x0b" title="Cache" name="Data read miss" per_cpu="yes" description="Data cache miss, not including Cache Operations"/>
- <configuration counter="ARM_Cortex-A5_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="ARM_Cortex-A5_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="ARM_Cortex-A5_cnt1" event="0x1" title="Cache" name="Instruction refill" per_cpu="yes" event_based_sampling="yes" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <configuration counter="ARM_Cortex-A7_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="ARM_Cortex-A7_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="ARM_Cortex-A7_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
- <configuration counter="ARM_Cortex-A7_cnt2" event="0x16" title="Cache" name="L2 data access" per_cpu="yes" event_based_sampling="yes" description="Level 2 data cache access"/>
- <configuration counter="ARM_Cortex-A8_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="ARM_Cortex-A8_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="ARM_Cortex-A8_cnt1" event="0x44" title="Cache" name="L2 miss" per_cpu="yes" event_based_sampling="yes" description="Any cacheable miss in the L2 cache"/>
- <configuration counter="ARM_Cortex-A8_cnt2" event="0x43" title="Cache" name="L1 miss" per_cpu="yes" event_based_sampling="yes" description="Any accesses to the L2 cache"/>
- <configuration counter="ARM_Cortex-A8_cnt3" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
- <configuration counter="ARM_Cortex-A9_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="ARM_Cortex-A9_cnt0" event="0x68" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Counts the number of instructions going through the Register Renaming stage. This number is an approximate number of the total number of instructions speculatively executed, and even more approximate of the total number of instructions architecturally executed"/>
- <configuration counter="ARM_Cortex-A9_cnt1" event="0x06" title="Instruction" name="Memory read" per_cpu="yes" event_based_sampling="yes" description="Memory-reading instruction architecturally executed"/>
- <configuration counter="ARM_Cortex-A9_cnt2" event="0x07" title="Instruction" name="Memory write" per_cpu="yes" event_based_sampling="yes" description="Memory-writing instruction architecturally executed"/>
- <configuration counter="ARM_Cortex-A9_cnt3" event="0x03" title="Cache" name="Data refill" per_cpu="yes" event_based_sampling="yes" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <configuration counter="ARM_Cortex-A9_cnt4" event="0x04" title="Cache" name="Data access" per_cpu="yes" event_based_sampling="yes" 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"/>
- <configuration counter="ARM_Cortex-A15_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="ARM_Cortex-A15_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="ARM_Cortex-A15_cnt1" event="0x16" title="Cache" name="L2 data access" per_cpu="yes" event_based_sampling="yes" description="Level 2 data cache access"/>
- <configuration counter="ARM_Cortex-A15_cnt2" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
- <configuration counter="ARM_Cortex-A15_cnt3" event="0x19" title="Bus" name="Access" per_cpu="yes" event_based_sampling="yes" description=""/>
- <configuration counter="Scorpion_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="Scorpion_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="Scorpion_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
- <configuration counter="ScorpionMP_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="ScorpionMP_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="ScorpionMP_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
- <configuration counter="Krait_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
- <configuration counter="Krait_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/>
- <configuration counter="Krait_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="ARM_Cortex-A5_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A5_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A5_cnt1" event="0x1" title="Cache" name="Instruction refill" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
+ <configuration counter="ARM_Cortex-A7_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A7_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A7_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" supports_event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="ARM_Cortex-A7_cnt2" event="0x16" title="Cache" name="L2 data access" per_cpu="yes" supports_event_based_sampling="yes" description="Level 2 data cache access"/>
+ <configuration counter="ARM_Cortex-A8_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A8_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A8_cnt1" event="0x44" title="Cache" name="L2 miss" per_cpu="yes" supports_event_based_sampling="yes" description="Any cacheable miss in the L2 cache"/>
+ <configuration counter="ARM_Cortex-A8_cnt2" event="0x43" title="Cache" name="L1 miss" per_cpu="yes" supports_event_based_sampling="yes" description="Any accesses to the L2 cache"/>
+ <configuration counter="ARM_Cortex-A8_cnt3" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" supports_event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="ARM_Cortex-A9_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A9_cnt0" event="0x68" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Counts the number of instructions going through the Register Renaming stage. This number is an approximate number of the total number of instructions speculatively executed, and even more approximate of the total number of instructions architecturally executed"/>
+ <configuration counter="ARM_Cortex-A9_cnt1" event="0x06" title="Instruction" name="Memory read" per_cpu="yes" supports_event_based_sampling="yes" description="Memory-reading instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A9_cnt2" event="0x07" title="Instruction" name="Memory write" per_cpu="yes" supports_event_based_sampling="yes" description="Memory-writing instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A9_cnt3" event="0x03" title="Cache" name="Data refill" per_cpu="yes" supports_event_based_sampling="yes" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
+ <configuration counter="ARM_Cortex-A9_cnt4" event="0x04" title="Cache" name="Data access" per_cpu="yes" supports_event_based_sampling="yes" 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"/>
+ <configuration counter="ARM_Cortex-A15_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="ARM_Cortex-A15_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="ARM_Cortex-A15_cnt1" event="0x16" title="Cache" name="L2 data access" per_cpu="yes" supports_event_based_sampling="yes" description="Level 2 data cache access"/>
+ <configuration counter="ARM_Cortex-A15_cnt2" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" supports_event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="ARM_Cortex-A15_cnt3" event="0x19" title="Bus" name="Access" per_cpu="yes" supports_event_based_sampling="yes" description=""/>
+ <configuration counter="Scorpion_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="Scorpion_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="Scorpion_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" supports_event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="ScorpionMP_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="ScorpionMP_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="ScorpionMP_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" supports_event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
+ <configuration counter="Krait_ccnt" title="Clock" name="Cycles" per_cpu="yes" supports_event_based_sampling="yes" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
+ <configuration counter="Krait_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" supports_event_based_sampling="yes" description="Instruction architecturally executed"/>
+ <configuration counter="Krait_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" supports_event_based_sampling="yes" description="Branch mispredicted or not predicted"/>
<configuration counter="Linux_block_rq_wr" title="Disk IO" name="Write" units="B" description="Disk IO Bytes Written"/>
<configuration counter="Linux_block_rq_rd" title="Disk IO" name="Read" units="B" description="Disk IO Bytes Read"/>
- <configuration counter="Linux_net_rx" title="Network" name="Receive" units="B" description="Receive network traffic, including effect from Streamline"/>
- <configuration counter="Linux_net_tx" title="Network" name="Transmit" units="B" description="Transmit network traffic, including effect from Streamline"/>
- <configuration counter="Linux_cpuload_system" title="CPU Load" name="System" description="Scheduler CPU Load of System Behavior"/>
- <configuration counter="Linux_cpuload_user" title="CPU Load" name="User" description="Scheduler CPU Load of User Application"/>
<configuration counter="Linux_meminfo_memused" title="Memory" name="Used" display="maximum" units="B" average_selection="yes" description="Total used memory size"/>
<configuration counter="Linux_meminfo_memfree" title="Memory" name="Free" display="minimum" units="B" average_selection="yes" description="Available memory size"/>
<configuration counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" display="maximum" units="Hz" average_selection="yes" description="Frequency setting of the CPU"/>
diff --git a/daemon/events-ARM11.xml b/daemon/events-ARM11.xml
index d4a2914..0a5ee66 100644
--- a/daemon/events-ARM11.xml
+++ b/daemon/events-ARM11.xml
@@ -1,9 +1,5 @@
- <counter_set name="ARM_ARM11_cntX">
- <counter name="ARM_ARM11_cnt0"/>
- <counter name="ARM_ARM11_cnt1"/>
- <counter name="ARM_ARM11_cnt2"/>
- </counter_set>
- <category name="ARM11" counter_set="ARM_ARM11_cntX" per_cpu="yes">
+ <counter_set name="ARM_ARM11_cnt" count="3"/>
+ <category name="ARM11" counter_set="ARM_ARM11_cnt" per_cpu="yes">
<event counter="ARM_ARM11_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<event event="0x00" title="Cache" name="Inst miss" description="Instruction cache miss to a cacheable location, which requires a fetch from external memory"/>
<event event="0x01" title="Pipeline" name="Instruction stall" description="Stall because instruction buffer cannot deliver an instruction"/>
diff --git a/daemon/events-ARM11MPCore.xml b/daemon/events-ARM11MPCore.xml
index 7de51b0..1a9ca3f 100644
--- a/daemon/events-ARM11MPCore.xml
+++ b/daemon/events-ARM11MPCore.xml
@@ -1,9 +1,5 @@
- <counter_set name="ARM_ARM11MPCore_cntX">
- <counter name="ARM_ARM11MPCore_cnt0"/>
- <counter name="ARM_ARM11MPCore_cnt1"/>
- <counter name="ARM_ARM11MPCore_cnt2"/>
- </counter_set>
- <category name="ARM11MPCore" counter_set="ARM_ARM11MPCore_cntX" per_cpu="yes">
+ <counter_set name="ARM_ARM11MPCore_cnt" count="3"/>
+ <category name="ARM11MPCore" counter_set="ARM_ARM11MPCore_cnt" per_cpu="yes">
<event counter="ARM_ARM11MPCore_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<event event="0x00" title="Cache" name="Inst miss" description="Instruction cache miss to a cacheable location, which requires a fetch from external memory"/>
<event event="0x01" title="Pipeline" name="Instruction stall" description="Stall because instruction buffer cannot deliver an instruction"/>
diff --git a/daemon/events-Cortex-A15.xml b/daemon/events-Cortex-A15.xml
index d6222eb..0ec196f 100644
--- a/daemon/events-Cortex-A15.xml
+++ b/daemon/events-Cortex-A15.xml
@@ -1,12 +1,5 @@
- <counter_set name="ARM_Cortex-A15_cntX">
- <counter name="ARM_Cortex-A15_cnt0"/>
- <counter name="ARM_Cortex-A15_cnt1"/>
- <counter name="ARM_Cortex-A15_cnt2"/>
- <counter name="ARM_Cortex-A15_cnt3"/>
- <counter name="ARM_Cortex-A15_cnt4"/>
- <counter name="ARM_Cortex-A15_cnt5"/>
- </counter_set>
- <category name="Cortex-A15" counter_set="ARM_Cortex-A15_cntX" per_cpu="yes" event_based_sampling="yes">
+ <counter_set name="ARM_Cortex-A15_cnt" count="6"/>
+ <category name="Cortex-A15" counter_set="ARM_Cortex-A15_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="ARM_Cortex-A15_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<event event="0x00" title="Software" name="Increment" description="Software increment architecturally executed"/>
<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"/>
@@ -19,7 +12,6 @@
<event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
<event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
<event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <event event="0x11" title="Cycle" name="Cycle" description=""/>
<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"/>
<event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
<event event="0x14" title="Cache" name="L1 inst access" description="Instruction cache access"/>
diff --git a/daemon/events-Cortex-A5.xml b/daemon/events-Cortex-A5.xml
index e01492b..4a894d3 100644
--- a/daemon/events-Cortex-A5.xml
+++ b/daemon/events-Cortex-A5.xml
@@ -1,8 +1,5 @@
- <counter_set name="ARM_Cortex-A5_cntX">
- <counter name="ARM_Cortex-A5_cnt0"/>
- <counter name="ARM_Cortex-A5_cnt1"/>
- </counter_set>
- <category name="Cortex-A5" counter_set="ARM_Cortex-A5_cntX" per_cpu="yes" event_based_sampling="yes">
+ <counter_set name="ARM_Cortex-A5_cnt" count="2"/>
+ <category name="Cortex-A5" counter_set="ARM_Cortex-A5_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="ARM_Cortex-A5_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
<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"/>
diff --git a/daemon/events-Cortex-A7.xml b/daemon/events-Cortex-A7.xml
index 9ee4580..2bd4797 100644
--- a/daemon/events-Cortex-A7.xml
+++ b/daemon/events-Cortex-A7.xml
@@ -1,10 +1,5 @@
- <counter_set name="ARM_Cortex-A7_cntX">
- <counter name="ARM_Cortex-A7_cnt0"/>
- <counter name="ARM_Cortex-A7_cnt1"/>
- <counter name="ARM_Cortex-A7_cnt2"/>
- <counter name="ARM_Cortex-A7_cnt3"/>
- </counter_set>
- <category name="Cortex-A7" counter_set="ARM_Cortex-A7_cntX" per_cpu="yes" event_based_sampling="yes">
+ <counter_set name="ARM_Cortex-A7_cnt" count="4"/>
+ <category name="Cortex-A7" counter_set="ARM_Cortex-A7_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="ARM_Cortex-A7_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<event event="0x00" title="Software" name="Increment" description="Software increment architecturally executed"/>
<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"/>
diff --git a/daemon/events-Cortex-A8.xml b/daemon/events-Cortex-A8.xml
index 1981c36..fe4c69d 100644
--- a/daemon/events-Cortex-A8.xml
+++ b/daemon/events-Cortex-A8.xml
@@ -1,10 +1,5 @@
- <counter_set name="ARM_Cortex-A8_cntX">
- <counter name="ARM_Cortex-A8_cnt0"/>
- <counter name="ARM_Cortex-A8_cnt1"/>
- <counter name="ARM_Cortex-A8_cnt2"/>
- <counter name="ARM_Cortex-A8_cnt3"/>
- </counter_set>
- <category name="Cortex-A8" counter_set="ARM_Cortex-A8_cntX" per_cpu="yes" event_based_sampling="yes">
+ <counter_set name="ARM_Cortex-A8_cnt" count="4"/>
+ <category name="Cortex-A8" counter_set="ARM_Cortex-A8_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="ARM_Cortex-A8_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
<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"/>
diff --git a/daemon/events-Cortex-A9.xml b/daemon/events-Cortex-A9.xml
index faccb2f..7597f78 100644
--- a/daemon/events-Cortex-A9.xml
+++ b/daemon/events-Cortex-A9.xml
@@ -1,12 +1,5 @@
- <counter_set name="ARM_Cortex-A9_cntX">
- <counter name="ARM_Cortex-A9_cnt0"/>
- <counter name="ARM_Cortex-A9_cnt1"/>
- <counter name="ARM_Cortex-A9_cnt2"/>
- <counter name="ARM_Cortex-A9_cnt3"/>
- <counter name="ARM_Cortex-A9_cnt4"/>
- <counter name="ARM_Cortex-A9_cnt5"/>
- </counter_set>
- <category name="Cortex-A9" counter_set="ARM_Cortex-A9_cntX" per_cpu="yes" event_based_sampling="yes">
+ <counter_set name="ARM_Cortex-A9_cnt" count="6"/>
+ <category name="Cortex-A9" counter_set="ARM_Cortex-A9_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="ARM_Cortex-A9_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
<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"/>
diff --git a/daemon/events-Krait-architected.xml b/daemon/events-Krait-architected.xml
index 6f2982e..06c1901 100644
--- a/daemon/events-Krait-architected.xml
+++ b/daemon/events-Krait-architected.xml
@@ -1,10 +1,5 @@
- <counter_set name="Krait_cntX">
- <counter name="Krait_cnt0"/>
- <counter name="Krait_cnt1"/>
- <counter name="Krait_cnt2"/>
- <counter name="Krait_cnt3"/>
- </counter_set>
- <category name="Krait" counter_set="Krait_cntX" per_cpu="yes">
+ <counter_set name="Krait_cnt" count="4"/>
+ <category name="Krait" counter_set="Krait_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="Krait_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
<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"/>
diff --git a/daemon/events-L2C-310.xml b/daemon/events-L2C-310.xml
index 695b6b8..4da4d1d 100644
--- a/daemon/events-L2C-310.xml
+++ b/daemon/events-L2C-310.xml
@@ -1,8 +1,5 @@
- <counter_set name="L2C-310_cntX">
- <counter name="L2C-310_cnt0"/>
- <counter name="L2C-310_cnt1"/>
- </counter_set>
- <category name="L2C-310" counter_set="L2C-310_cntX" per_cpu="no">
+ <counter_set name="L2C-310_cnt" count="2"/>
+ <category name="L2C-310" counter_set="L2C-310_cnt" per_cpu="no">
<event event="0x1" title="L2 Cache" name="CO" description="Eviction, CastOUT, of a line from the L2 cache"/>
<event event="0x2" title="L2 Cache" name="DRH" description="Data read hit"/>
<event event="0x3" title="L2 Cache" name="DRREQ" description="Data read request"/>
diff --git a/daemon/events-Linux.xml b/daemon/events-Linux.xml
index 3f626b3..b45a122 100644
--- a/daemon/events-Linux.xml
+++ b/daemon/events-Linux.xml
@@ -1,17 +1,15 @@
<category name="Linux">
- <event counter="Linux_cpuload_user" title="CPU Load" name="User" per_cpu="yes" description="Scheduler CPU Load of User Application"/>
- <event counter="Linux_cpuload_system" title="CPU Load" name="System" per_cpu="yes" description="Scheduler CPU Load of System Behavior"/>
<event counter="Linux_irq_softirq" title="Interrupts" name="SoftIRQ" per_cpu="yes" description="Linux SoftIRQ taken"/>
<event counter="Linux_irq_irq" title="Interrupts" name="IRQ" per_cpu="yes" description="Linux IRQ taken"/>
<event counter="Linux_block_rq_wr" title="Disk IO" name="Write" units="B" description="Disk IO Bytes Written"/>
<event counter="Linux_block_rq_rd" title="Disk IO" name="Read" units="B" description="Disk IO Bytes Read"/>
<event counter="Linux_net_rx" title="Network" name="Receive" units="B" description="Receive network traffic, including effect from Streamline"/>
<event counter="Linux_net_tx" title="Network" name="Transmit" units="B" description="Transmit network traffic, including effect from Streamline"/>
- <event counter="Linux_sched_switch" title="Scheduler" name="Switch" description="Context switch events"/>
+ <event counter="Linux_sched_switch" title="Scheduler" name="Switch" per_cpu="yes" description="Context switch events"/>
<event counter="Linux_meminfo_memused" title="Memory" name="Used" display="maximum" units="B" average_selection="yes" description="Total used memory size"/>
<event counter="Linux_meminfo_memfree" title="Memory" name="Free" display="minimum" units="B" average_selection="yes" description="Available memory size"/>
<event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" display="maximum" units="B" average_selection="yes" description="Memory used by buffers"/>
<event counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" display="maximum" units="Hz" average_selection="yes" description="Frequency setting of the CPU"/>
- <event counter="Linux_power_cpu_idle" title="Power" name="Idle" per_cpu="yes" display="maximum" average_selection="yes" description="CPU Idle State, set the Sample Rate to None to prevent the hrtimer from interrupting the system"/>
+ <event counter="Linux_power_cpu_idle" title="Power" name="Idle" per_cpu="yes" display="maximum" average_selection="yes" description="CPU Idle State + 1, set the Sample Rate to None to prevent the hrtimer from interrupting the system"/>
</category>
diff --git a/daemon/events-Mali-400.xml b/daemon/events-Mali-400.xml
index cb1c6b4..6830d46 100644
--- a/daemon/events-Mali-400.xml
+++ b/daemon/events-Mali-400.xml
@@ -1,33 +1,12 @@
- <counter_set name="ARM_Mali-400_VP_cntX">
- <counter name="ARM_Mali-400_VP_cnt0"/>
- <counter name="ARM_Mali-400_VP_cnt1"/>
- </counter_set>
- <counter_set name="ARM_Mali-400_FP0_cntX">
- <counter name="ARM_Mali-400_FP0_cnt0"/>
- <counter name="ARM_Mali-400_FP0_cnt1"/>
- </counter_set>
- <counter_set name="ARM_Mali-400_FP1_cntX">
- <counter name="ARM_Mali-400_FP1_cnt0"/>
- <counter name="ARM_Mali-400_FP1_cnt1"/>
- </counter_set>
- <counter_set name="ARM_Mali-400_FP2_cntX">
- <counter name="ARM_Mali-400_FP2_cnt0"/>
- <counter name="ARM_Mali-400_FP2_cnt1"/>
- </counter_set>
- <counter_set name="ARM_Mali-400_FP3_cntX">
- <counter name="ARM_Mali-400_FP3_cnt0"/>
- <counter name="ARM_Mali-400_FP3_cnt1"/>
- </counter_set>
- <counter_set name="ARM_Mali-400_L2_cntX">
- <counter name="ARM_Mali-400_L2_cnt0"/>
- <counter name="ARM_Mali-400_L2_cnt1"/>
- </counter_set>
- <counter_set name="ARM_Mali-400_SW_cntX">
- </counter_set>
- <counter_set name="ARM_Mali-400_Filmstrip_cntX">
- <counter name="ARM_Mali-400_Filmstrip"/>
- </counter_set>
- <category name="Mali-400-VP" counter_set="ARM_Mali-400_VP_cntX" per_cpu="no">
+ <counter_set name="ARM_Mali-400_VP_cnt" count="2"/>
+ <counter_set name="ARM_Mali-400_FP0_cnt" count="2"/>
+ <counter_set name="ARM_Mali-400_FP1_cnt" count="2"/>
+ <counter_set name="ARM_Mali-400_FP2_cnt" count="2"/>
+ <counter_set name="ARM_Mali-400_FP3_cnt" count="2"/>
+ <counter_set name="ARM_Mali-400_L2_cnt" count="2"/>
+ <counter_set name="ARM_Mali-400_SW_cnt" count="0"/>
+ <counter_set name="ARM_Mali-400_Filmstrip_cnt" count="1"/>
+ <category name="Mali-400-VP" counter_set="ARM_Mali-400_VP_cnt" per_cpu="no">
<event event="0x01" title="Mali GPU Vertex Processor" name="Active cycles" description="Number of cycles per frame the MaliGP2 was active."/>
<event event="0x02" title="Mali GPU Vertex Processor" name="Active cycles, vertex shader" description="Number of cycles per frame the vertex shader unit was active."/>
<event event="0x03" title="Mali GPU Vertex Processor" name="Active cycles, vertex storer" description="Number of cycles per frame the vertex storer unit was active."/>
@@ -54,7 +33,7 @@
<event event="0x20" title="Mali GPU Vertex Processor" name="Active cycles, Scissor tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over tiles to perform scissoringi. This includes time spent waiting on the bus."/>
<event event="0x21" title="Mali GPU Vertex Processor" name="Active cycles, PLBU tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over the tiles in the bounding box generating commands (mainly graphics primitives). This includes time spent waiting on the bus."/>
</category>
- <category name="Mali-400-FP0" counter_set="ARM_Mali-400_FP0_cntX" per_cpu="no">
+ <category name="Mali-400-FP0" counter_set="ARM_Mali-400_FP0_cnt" per_cpu="no">
<event event="0x00" title="Mali GPU Fragment Processor 0" name="Active clock cycles" description="Active clock cycles, between polygon start and IRQ."/>
<event event="0x02" title="Mali GPU Fragment Processor 0" name="Total bus reads" description="Total number of 64-bit words read from the bus."/>
<event event="0x03" title="Mali GPU Fragment Processor 0" name="Total bus writes" description="Total number of 64-bit words written to the bus."/>
@@ -113,7 +92,7 @@
<event event="0x3c" title="Mali GPU Fragment Processor 0" name="Program cache hit count" description="Number of hits in the program cache."/>
<event event="0x3d" title="Mali GPU Fragment Processor 0" name="Program cache miss count" description="Number of misses in the program cache."/>
</category>
- <category name="Mali-400-FP1" counter_set="ARM_Mali-400_FP1_cntX" per_cpu="no">
+ <category name="Mali-400-FP1" counter_set="ARM_Mali-400_FP1_cnt" per_cpu="no">
<event event="0x00" title="Mali GPU Fragment Processor 1" name="Active clock cycles" description="Active clock cycles, between polygon start and IRQ."/>
<event event="0x02" title="Mali GPU Fragment Processor 1" name="Total bus reads" description="Total number of 64-bit words read from the bus."/>
<event event="0x03" title="Mali GPU Fragment Processor 1" name="Total bus writes" description="Total number of 64-bit words written to the bus."/>
@@ -172,7 +151,7 @@
<event event="0x3c" title="Mali GPU Fragment Processor 1" name="Program cache hit count" description="Number of hits in the program cache."/>
<event event="0x3d" title="Mali GPU Fragment Processor 1" name="Program cache miss count" description="Number of misses in the program cache."/>
</category>
- <category name="Mali-400-FP2" counter_set="ARM_Mali-400_FP2_cntX" per_cpu="no">
+ <category name="Mali-400-FP2" counter_set="ARM_Mali-400_FP2_cnt" per_cpu="no">
<event event="0x00" title="Mali GPU Fragment Processor 2" name="Active clock cycles" description="Active clock cycles, between polygon start and IRQ."/>
<event event="0x02" title="Mali GPU Fragment Processor 2" name="Total bus reads" description="Total number of 64-bit words read from the bus."/>
<event event="0x03" title="Mali GPU Fragment Processor 2" name="Total bus writes" description="Total number of 64-bit words written to the bus."/>
@@ -231,7 +210,7 @@
<event event="0x3c" title="Mali GPU Fragment Processor 2" name="Program cache hit count" description="Number of hits in the program cache."/>
<event event="0x3d" title="Mali GPU Fragment Processor 2" name="Program cache miss count" description="Number of misses in the program cache."/>
</category>
- <category name="Mali-400-FP3" counter_set="ARM_Mali-400_FP3_cntX" per_cpu="no">
+ <category name="Mali-400-FP3" counter_set="ARM_Mali-400_FP3_cnt" per_cpu="no">
<event event="0x00" title="Mali GPU Fragment Processor 3" name="Active clock cycles" description="Active clock cycles, between polygon start and IRQ."/>
<event event="0x02" title="Mali GPU Fragment Processor 3" name="Total bus reads" description="Total number of 64-bit words read from the bus."/>
<event event="0x03" title="Mali GPU Fragment Processor 3" name="Total bus writes" description="Total number of 64-bit words written to the bus."/>
@@ -290,7 +269,7 @@
<event event="0x3c" title="Mali GPU Fragment Processor 3" name="Program cache hit count" description="Number of hits in the program cache."/>
<event event="0x3d" title="Mali GPU Fragment Processor 3" name="Program cache miss count" description="Number of misses in the program cache."/>
</category>
- <category name="Mali-400-L2" counter_set="ARM_Mali-400_L2_cntX" per_cpu="no">
+ <category name="Mali-400-L2" counter_set="ARM_Mali-400_L2_cnt" per_cpu="no">
<event event="0x01" title="Mali L2 Cache" name="Total clock cycles" description="Total clock cycles."/>
<event event="0x02" title="Mali L2 Cache" name="Active clock cycles" description="Active clock cycles." />
<event event="0x08" title="Mali L2 Cache" name="Read transactions, master" description="Read transactions, master." />
@@ -352,7 +331,7 @@
<event event="0x67" title="Mali L2 Cache" name="Read invalidates, slave 4" description="Read invalidates, slave 4." />
<event event="0x68" title="Mali L2 Cache" name="Cacheable read transactions, slave 4" description="Cacheable read transactions, slave 4." />
</category>
- <category name="ARM_Mali-400_Filmstrip" counter_set="ARM_Mali-400_Filmstrip_cntX" per_cpu="no">
+ <category name="ARM_Mali-400_Filmstrip" counter_set="ARM_Mali-400_Filmstrip_cnt" per_cpu="no">
<event event="0x040a" title="ARM_Mali-400_Filmstrip" name="Freq 1:10" description="Scaled framebuffer captures every 10th frame." />
<event event="0x041e" title="ARM_Mali-400_Filmstrip" name="Freq 1:30" description="Scaled framebuffer captures every 30th frame." />
<event event="0x043c" title="ARM_Mali-400_Filmstrip" name="Freq 1:60" description="Scaled framebuffer captures every 60th frame." />
@@ -363,7 +342,7 @@
<category name="ARM_Mali-400_Frequency" per_cpu="no">
<event counter="ARM_Mali-400_Frequency" title="Mali GPU Frequency" name="Frequency" display="average" average_selection="yes" units="MHz" description="GPU core frequency."/>
</category>
- <category name="Mali-400-SW" counter_set="ARM_Mali-400_SW_cntX" per_cpu="no">
+ <category name="Mali-400-SW" counter_set="ARM_Mali-400_SW_cnt" per_cpu="no">
<!-- EGL Counters -->
<event counter="ARM_Mali-400_SW_17" title="Mali EGL Software Counters" name="Blit Time" description="Time spent blitting the the framebuffer from video memory to framebuffer."/>
<!-- glDrawElements Counters -->
diff --git a/daemon/events-Scorpion.xml b/daemon/events-Scorpion.xml
index 51ed937..1642e85 100644
--- a/daemon/events-Scorpion.xml
+++ b/daemon/events-Scorpion.xml
@@ -1,10 +1,5 @@
- <counter_set name="Scorpion_cntX">
- <counter name="Scorpion_cnt0"/>
- <counter name="Scorpion_cnt1"/>
- <counter name="Scorpion_cnt2"/>
- <counter name="Scorpion_cnt3"/>
- </counter_set>
- <category name="Scorpion" counter_set="Scorpion_cntX" per_cpu="yes">
+ <counter_set name="Scorpion_cnt" count="4"/>
+ <category name="Scorpion" counter_set="Scorpion_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="Scorpion_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
<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"/>
diff --git a/daemon/events-ScorpionMP.xml b/daemon/events-ScorpionMP.xml
index d3dd430..42acc64 100644
--- a/daemon/events-ScorpionMP.xml
+++ b/daemon/events-ScorpionMP.xml
@@ -1,10 +1,5 @@
- <counter_set name="ScorpionMP_cntX">
- <counter name="ScorpionMP_cnt0"/>
- <counter name="ScorpionMP_cnt1"/>
- <counter name="ScorpionMP_cnt2"/>
- <counter name="ScorpionMP_cnt3"/>
- </counter_set>
- <category name="ScorpionMP" counter_set="ScorpionMP_cntX" per_cpu="yes">
+ <counter_set name="ScorpionMP_cnt" count="4"/>
+ <category name="ScorpionMP" counter_set="ScorpionMP_cnt" per_cpu="yes" supports_event_based_sampling="yes">
<event counter="ScorpionMP_ccnt" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
<event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
<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"/>
diff --git a/daemon/main.cpp b/daemon/main.cpp
index d972913..5bc75ef 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -17,6 +17,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h>
+#include <fcntl.h>
+#include <sys/mman.h>
#include "Child.h"
#include "SessionData.h"
#include "OlySocket.h"
@@ -114,6 +116,26 @@ int mountGatorFS() {
}
}
+bool init_module (const char * const location) {
+ bool ret(false);
+ const int fd = open(location, O_RDONLY);
+ if (fd >= 0) {
+ struct stat st;
+ if (fstat(fd, &st) == 0) {
+ void * const p = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (p != MAP_FAILED) {
+ if (syscall(__NR_init_module, p, st.st_size, "") == 0) {
+ ret = true;
+ }
+ munmap(p, st.st_size);
+ }
+ }
+ close(fd);
+ }
+
+ return ret;
+}
+
int setupFilesystem(char* module) {
int retval;
@@ -162,11 +184,15 @@ int setupFilesystem(char* module) {
}
// Load driver
- snprintf(command, sizeof(command), "insmod %s >/dev/null 2>&1", location);
- if (system(command) != 0) {
- logg->logMessage("Unable to load gator.ko driver with command: %s", command);
- logg->logError(__FILE__, __LINE__, "Unable to load (insmod) gator.ko driver:\n >>> gator.ko must be built against the current kernel version & configuration\n >>> See dmesg for more details");
- handleException();
+ bool success = init_module(location);
+ if (!success) {
+ logg->logMessage("init_module failed, trying insmod");
+ snprintf(command, sizeof(command), "insmod %s >/dev/null 2>&1", location);
+ if (system(command) != 0) {
+ logg->logMessage("Unable to load gator.ko driver with command: %s", command);
+ logg->logError(__FILE__, __LINE__, "Unable to load (insmod) gator.ko driver:\n >>> gator.ko must be built against the current kernel version & configuration\n >>> See dmesg for more details");
+ handleException();
+ }
}
if (mountGatorFS() == -1) {
@@ -183,8 +209,11 @@ int shutdownFilesystem() {
umount("/dev/gator");
}
if (driverRunningAtStart == false) {
- if (system("rmmod gator >/dev/null 2>&1") != 0) {
- return -1;
+ if (syscall(__NR_delete_module, "gator", O_NONBLOCK) != 0) {
+ logg->logMessage("delete_module failed, trying rmmod");
+ if (system("rmmod gator >/dev/null 2>&1") != 0) {
+ return -1;
+ }
}
}
@@ -205,7 +234,7 @@ struct cmdline_t parseCommandLine(int argc, char** argv) {
snprintf(version_string, sizeof(version_string), "Streamline gatord development version %d", PROTOCOL_VERSION);
}
- while ((c = getopt(argc, argv, "hvp:s:c:e:m:")) != -1) {
+ while ((c = getopt(argc, argv, "hvp:s:c:e:m:o:")) != -1) {
switch(c) {
case 'c':
gSessionData->mConfigurationXMLPath = optarg;
@@ -222,6 +251,9 @@ struct cmdline_t parseCommandLine(int argc, char** argv) {
case 's':
gSessionData->mSessionXMLPath = optarg;
break;
+ case 'o':
+ gSessionData->mTargetPath = optarg;
+ break;
case 'h':
case '?':
logg->logError(__FILE__, __LINE__,
@@ -232,6 +264,7 @@ struct cmdline_t parseCommandLine(int argc, char** argv) {
"-m module path and filename of gator.ko\n"
"-p port_number port upon which the server listens; default is 8080\n"
"-s session_xml path and filename of a session xml used for local capture\n"
+ "-o apc_dir path and name of the output for a local capture\n"
"-v version information\n"
, version_string);
handleException();
@@ -249,6 +282,11 @@ struct cmdline_t parseCommandLine(int argc, char** argv) {
handleException();
}
+ if (gSessionData->mTargetPath != NULL && gSessionData->mSessionXMLPath == NULL) {
+ logg->logError(__FILE__, __LINE__, "Missing -s command line option required for a local capture.");
+ handleException();
+ }
+
if (optind < argc) {
logg->logError(__FILE__, __LINE__, "Unknown argument: %s. Use '-h' for help.", argv[optind]);
handleException();
@@ -259,6 +297,7 @@ struct cmdline_t parseCommandLine(int argc, char** argv) {
// Gator data flow: collector -> collector fifo -> sender
int main(int argc, char** argv, char* envp[]) {
+ setsid();
gSessionData = new SessionData(); // Global data class
logg = new Logging(DEBUG); // Set up global thread-safe logging
util = new OlyUtility(); // Set up global utility class
diff --git a/driver/Makefile b/driver/Makefile
index 025dd9e..d22d29d 100644
--- a/driver/Makefile
+++ b/driver/Makefile
@@ -27,6 +27,10 @@ gator-y += gator_events_mali_common.o
EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT)
endif
+# GATOR_TEST controls whether to include (=1) or exclude (=0) test code.
+GATOR_TEST ?= 0
+EXTRA_CFLAGS += -DGATOR_TEST=$(GATOR_TEST)
+
gator-$(CONFIG_ARM) += gator_events_armv6.o \
gator_events_armv7.o \
gator_events_l2c-310.o \
diff --git a/driver/gator.h b/driver/gator.h
index 6b96109..5a40e17 100644
--- a/driver/gator.h
+++ b/driver/gator.h
@@ -20,19 +20,20 @@
#define GATOR_CPU_FREQ_SUPPORT (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) && defined(CONFIG_CPU_FREQ)
// cpu ids
-#define ARM1136 0xb36
-#define ARM1156 0xb56
-#define ARM1176 0xb76
+#define ARM1136 0xb36
+#define ARM1156 0xb56
+#define ARM1176 0xb76
#define ARM11MPCORE 0xb02
-#define CORTEX_A5 0xc05
-#define CORTEX_A7 0xc07
-#define CORTEX_A8 0xc08
-#define CORTEX_A9 0xc09
-#define CORTEX_A15 0xc0f
-#define SCORPION 0x00f
-#define SCORPIONMP 0x02d
-#define KRAITSIM 0x049
+#define CORTEX_A5 0xc05
+#define CORTEX_A7 0xc07
+#define CORTEX_A8 0xc08
+#define CORTEX_A9 0xc09
+#define CORTEX_A15 0xc0f
+#define SCORPION 0x00f
+#define SCORPIONMP 0x02d
+#define KRAITSIM 0x049
#define KRAIT 0x04d
+#define AARCH64 0xd0f
/******************************************************************************
* Filesystem
@@ -97,4 +98,6 @@ int gator_events_install(struct gator_interface *interface);
int gator_events_get_key(void);
extern u32 gator_cpuid(void);
+void gator_backtrace_handler(struct pt_regs * const regs);
+
#endif // GATOR_H_
diff --git a/driver/gator_annotate.c b/driver/gator_annotate.c
index b444789..f2f0465 100644
--- a/driver/gator_annotate.c
+++ b/driver/gator_annotate.c
@@ -38,26 +38,34 @@ static int annotate_copy(struct file *file, char const __user *buf, size_t count
static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count_orig, loff_t *offset)
{
- int tid, cpu, header_size, available, contiguous, length1, length2, size, count = count_orig & 0x7fffffff;
+ int pid, cpu, header_size, available, contiguous, length1, length2, size, count = count_orig & 0x7fffffff;
- if (*offset)
+ if (*offset) {
return -EINVAL;
+ }
+
+ // Annotation is not supported in interrupt context
+ if (in_interrupt()) {
+ return -EINVAL;
+ }
+
+ // synchronize between cores and with collect_annotations
+ spin_lock(&annotate_lock);
- if (!collect_annotations)
+ if (!collect_annotations) {
// Not collecting annotations, tell the caller everything was written
- return count_orig;
+ size = count_orig;
+ goto annotate_write_out;
+ }
cpu = 0; // Annotation only uses a single per-cpu buffer as the data must be in order to the engine
- if (file == NULL) {
- tid = -1; // set the thread id to the kernel thread
+ if (current == NULL) {
+ pid = 0;
} else {
- tid = current->pid;
+ pid = current->pid;
}
- // synchronize between cores
- spin_lock(&annotate_lock);
-
// determine total size of the payload
header_size = MAXSIZE_PACK32 * 3 + MAXSIZE_PACK64;
available = buffer_bytes_available(cpu, ANNOTATE_BUF) - header_size;
@@ -71,9 +79,9 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t
}
// synchronize shared variables annotateBuf and annotatePos
- if (collect_annotations && per_cpu(gator_buffer, cpu)[ANNOTATE_BUF]) {
+ if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF]) {
gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id());
- gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, tid);
+ gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, gator_get_time());
gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, size);
@@ -118,9 +126,9 @@ static int annotate_release(struct inode *inode, struct file *file)
spin_lock(&annotate_lock);
if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF] && buffer_check_space(cpu, ANNOTATE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
- uint32_t tid = current->pid;
+ uint32_t pid = current->pid;
gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id());
- gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, tid);
+ gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); // time
gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); // size
}
@@ -148,5 +156,8 @@ static int gator_annotate_start(void)
static void gator_annotate_stop(void)
{
+ // the spinlock here will ensure that when this function exits, we are not in the middle of an annotation
+ spin_lock(&annotate_lock);
collect_annotations = false;
+ spin_unlock(&annotate_lock);
}
diff --git a/driver/gator_annotate_kernel.c b/driver/gator_annotate_kernel.c
index ffab087..bc68fa8 100644
--- a/driver/gator_annotate_kernel.c
+++ b/driver/gator_annotate_kernel.c
@@ -7,50 +7,83 @@
*
*/
-static void kannotate_write(char* ptr, unsigned int size)
+#define ESCAPE_CODE 0x1c
+#define STRING_ANNOTATION 0x03
+#define VISUAL_ANNOTATION 0x04
+#define MARKER_ANNOTATION 0x05
+
+static void kannotate_write(const char* ptr, unsigned int size)
{
int retval;
int pos = 0;
loff_t offset = 0;
while (pos < size) {
- retval = annotate_write(NULL, &ptr[pos], size - pos, &offset);
- if (retval < 0) {
- printk(KERN_WARNING "gator: kannotate_write failed with return value %d\n", retval);
- return;
- }
- pos += retval;
+ retval = annotate_write(NULL, &ptr[pos], size - pos, &offset);
+ if (retval < 0) {
+ printk(KERN_WARNING "gator: kannotate_write failed with return value %d\n", retval);
+ return;
+ }
+ pos += retval;
}
}
+static void gator_annotate_code(char code)
+{
+ int header = ESCAPE_CODE | (code << 8);
+ kannotate_write((char*)&header, sizeof(header));
+}
+
+static void gator_annotate_code_str(char code, const char* string)
+{
+ int str_size = strlen(string) & 0xffff;
+ int header = ESCAPE_CODE | (code << 8) | (str_size << 16);
+ kannotate_write((char*)&header, sizeof(header));
+ kannotate_write(string, str_size);
+}
+
+static void gator_annotate_code_color(char code, int color)
+{
+ long long header = (ESCAPE_CODE | (code << 8) | 0x00040000 | ((long long)color << 32));
+ kannotate_write((char*)&header, sizeof(header));
+}
+
+static void gator_annotate_code_color_str(char code, int color, const char* string)
+{
+ int str_size = (strlen(string) + 4) & 0xffff;
+ long long header = ESCAPE_CODE | (code << 8) | (str_size << 16) | ((long long)color << 32);
+ kannotate_write((char*)&header, sizeof(header));
+ kannotate_write(string, str_size - 4);
+}
+
// String annotation
-void gator_annotate(char* string)
+void gator_annotate(const char* string)
{
- kannotate_write(string, strlen(string) + 1);
+ gator_annotate_code_str(STRING_ANNOTATION, string);
}
EXPORT_SYMBOL(gator_annotate);
// String annotation with color
-void gator_annotate_color(int color, char* string)
+void gator_annotate_color(int color, const char* string)
{
- kannotate_write((char*)&color, sizeof(color));
- kannotate_write(string, strlen(string) + 1);
+ gator_annotate_code_color_str(STRING_ANNOTATION, color, string);
}
EXPORT_SYMBOL(gator_annotate_color);
// Terminate an annotation
void gator_annotate_end(void)
{
- char nul = 0;
- kannotate_write(&nul, sizeof(nul));
+ gator_annotate_code(STRING_ANNOTATION);
}
EXPORT_SYMBOL(gator_annotate_end);
// Image annotation with optional string
-void gator_annotate_visual(char* data, unsigned int length, char* string)
+void gator_annotate_visual(const char* data, unsigned int length, const char* string)
{
- long long visual_annotation = 0x011c | (strlen(string) << 16) | ((long long)length << 32);
- kannotate_write((char*)&visual_annotation, 8);
- kannotate_write(string, strlen(string));
+ int str_size = strlen(string) & 0xffff;
+ int visual_annotation = ESCAPE_CODE | (VISUAL_ANNOTATION << 8) | (str_size << 16);
+ kannotate_write((char*)&visual_annotation, sizeof(visual_annotation));
+ kannotate_write(string, str_size);
+ kannotate_write((char*)&length, sizeof(length));
kannotate_write(data, length);
}
EXPORT_SYMBOL(gator_annotate_visual);
@@ -58,33 +91,27 @@ EXPORT_SYMBOL(gator_annotate_visual);
// Marker annotation
void gator_annotate_marker(void)
{
- int marker_annotation = 0x00021c;
- kannotate_write((char*)&marker_annotation, 3);
+ gator_annotate_code(MARKER_ANNOTATION);
}
EXPORT_SYMBOL(gator_annotate_marker);
// Marker annotation with a string
-void gator_annotate_marker_str(char* string)
+void gator_annotate_marker_str(const char* string)
{
- int marker_annotation = 0x021c;
- kannotate_write((char*)&marker_annotation, 2);
- kannotate_write(string, strlen(string) + 1);
+ gator_annotate_code_str(MARKER_ANNOTATION, string);
}
EXPORT_SYMBOL(gator_annotate_marker_str);
// Marker annotation with a color
void gator_annotate_marker_color(int color)
{
- long long marker_annotation = (0x021c | ((long long)color << 16)) & 0x0000ffffffffffffLL;
- kannotate_write((char*)&marker_annotation, 7);
+ gator_annotate_code_color(MARKER_ANNOTATION, color);
}
EXPORT_SYMBOL(gator_annotate_marker_color);
-// Marker annotationw ith a string and color
-void gator_annotate_marker_color_str(int color, char* string)
+// Marker annotation with a string and color
+void gator_annotate_marker_color_str(int color, const char* string)
{
- long long marker_annotation = 0x021c | ((long long)color << 16);
- kannotate_write((char*)&marker_annotation, 6);
- kannotate_write(string, strlen(string) + 1);
+ gator_annotate_code_color_str(MARKER_ANNOTATION, color, string);
}
EXPORT_SYMBOL(gator_annotate_marker_color_str);
diff --git a/driver/gator_backtrace.c b/driver/gator_backtrace.c
index 50783d6..2173d8a 100644
--- a/driver/gator_backtrace.c
+++ b/driver/gator_backtrace.c
@@ -15,7 +15,7 @@ struct frame_tail_eabi {
unsigned long lr;
};
-static void arm_backtrace_eabi(int cpu, int buftype, struct pt_regs * const regs, unsigned int depth)
+static void arm_backtrace_eabi(int cpu, struct pt_regs * const regs, unsigned int depth)
{
#if defined(__arm__)
struct frame_tail_eabi *tail;
@@ -32,7 +32,7 @@ static void arm_backtrace_eabi(int cpu, int buftype, struct pt_regs * const regs
}
/* entry preamble may not have executed */
- gator_add_trace(cpu, buftype, lr);
+ gator_add_trace(cpu, lr);
/* check tail is valid */
if (fp == 0 || fp < sp) {
@@ -50,7 +50,7 @@ static void arm_backtrace_eabi(int cpu, int buftype, struct pt_regs * const regs
ptrtail = &buftail;
lr = ptrtail[0].lr;
- gator_add_trace(cpu, buftype, lr);
+ gator_add_trace(cpu, lr);
/* frame pointers should progress back up the stack, towards higher addresses */
next = (struct frame_tail_eabi *)(lr - 4);
@@ -69,16 +69,16 @@ static void arm_backtrace_eabi(int cpu, int buftype, struct pt_regs * const regs
}
#if defined(__arm__)
-static DEFINE_PER_CPU(int, backtrace_buffer);
static int report_trace(struct stackframe *frame, void *d)
{
struct module *mod;
- unsigned int *depth = d, addr = frame->pc, cookie = NO_COOKIE, cpu = smp_processor_id();
+ unsigned int *depth = d, cookie = NO_COOKIE, cpu = smp_processor_id();
+ unsigned long addr = frame->pc;
if (*depth) {
mod = __module_address(addr);
if (mod) {
- cookie = get_cookie(cpu, per_cpu(backtrace_buffer, cpu), current, NULL, mod, true);
+ cookie = get_cookie(cpu, current, NULL, mod, true);
addr = addr - (unsigned long)mod->module_core;
}
marshal_backtrace(addr & ~1, cookie);
@@ -91,7 +91,7 @@ static int report_trace(struct stackframe *frame, void *d)
// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile
// #define GATOR_KERNEL_STACK_UNWINDING
-static void kernel_backtrace(int cpu, int buftype, struct pt_regs * const regs)
+static void kernel_backtrace(int cpu, struct pt_regs * const regs)
{
#if defined(__arm__)
#ifdef GATOR_KERNEL_STACK_UNWINDING
@@ -106,7 +106,6 @@ static void kernel_backtrace(int cpu, int buftype, struct pt_regs * const regs)
frame.sp = regs->ARM_sp;
frame.lr = regs->ARM_lr;
frame.pc = regs->ARM_pc;
- per_cpu(backtrace_buffer, cpu) = buftype;
walk_stackframe(&frame, report_trace, &depth);
#else
marshal_backtrace(PC_REG & ~1, NO_COOKIE);
diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c
index d7d8e84..b2ed686 100644
--- a/driver/gator_cookies.c
+++ b/driver/gator_cookies.c
@@ -12,7 +12,7 @@
#define MAX_COLLISIONS 2
static uint32_t *gator_crc32_table;
-static uint32_t translate_buffer_mask;
+static unsigned int translate_buffer_mask;
static DEFINE_PER_CPU(char *, translate_text);
static DEFINE_PER_CPU(uint32_t, cookie_next_key);
@@ -20,9 +20,9 @@ static DEFINE_PER_CPU(uint64_t *, cookie_keys);
static DEFINE_PER_CPU(uint32_t *, cookie_values);
static DEFINE_PER_CPU(int, translate_buffer_read);
static DEFINE_PER_CPU(int, translate_buffer_write);
-static DEFINE_PER_CPU(unsigned int *, translate_buffer);
+static DEFINE_PER_CPU(void * *, translate_buffer);
-static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt);
+static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt);
static void wq_cookie_handler(struct work_struct *unused);
DECLARE_WORK(cookie_work, wq_cookie_handler);
static struct timer_list app_process_wake_up_timer;
@@ -40,16 +40,16 @@ static uint32_t cookiemap_code(uint64_t value64) {
static uint32_t gator_chksum_crc32(char *data)
{
- register unsigned long crc;
- unsigned char *block = data;
- int i, length = strlen(data);
+ register unsigned long crc;
+ unsigned char *block = data;
+ int i, length = strlen(data);
- crc = 0xFFFFFFFF;
- for (i = 0; i < length; i++) {
- crc = ((crc >> 8) & 0x00FFFFFF) ^ gator_crc32_table[(crc ^ *block++) & 0xFF];
- }
+ crc = 0xFFFFFFFF;
+ for (i = 0; i < length; i++) {
+ crc = ((crc >> 8) & 0x00FFFFFF) ^ gator_crc32_table[(crc ^ *block++) & 0xFF];
+ }
- return (crc ^ 0xFFFFFFFF);
+ return (crc ^ 0xFFFFFFFF);
}
/*
@@ -104,15 +104,15 @@ static void cookiemap_add(uint64_t key, uint32_t value) {
values[0] = value;
}
-static void translate_buffer_write_int(int cpu, unsigned int x)
+static void translate_buffer_write_ptr(int cpu, void * x)
{
per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x;
per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask;
}
-static unsigned int translate_buffer_read_int(int cpu)
+static void * translate_buffer_read_ptr(int cpu)
{
- unsigned int value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++];
+ void * value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++];
per_cpu(translate_buffer_read, cpu) &= translate_buffer_mask;
return value;
}
@@ -129,9 +129,9 @@ static void wq_cookie_handler(struct work_struct *unused)
if (gator_started != 0) {
commit = per_cpu(translate_buffer_write, cpu);
while (per_cpu(translate_buffer_read, cpu) != commit) {
- task = (struct task_struct *)translate_buffer_read_int(cpu);
- vma = (struct vm_area_struct *)translate_buffer_read_int(cpu);
- cookie = get_cookie(cpu, BACKTRACE_BUF, task, vma, NULL, false);
+ task = (struct task_struct *)translate_buffer_read_ptr(cpu);
+ vma = (struct vm_area_struct *)translate_buffer_read_ptr(cpu);
+ cookie = get_cookie(cpu, task, vma, NULL, false);
}
}
@@ -163,13 +163,13 @@ static int translate_app_process(char** text, int cpu, struct task_struct * task
// Check if already in buffer
ptr = per_cpu(translate_buffer_read, cpu);
while (ptr != per_cpu(translate_buffer_write, cpu)) {
- if (per_cpu(translate_buffer, cpu)[ptr] == (int)task)
+ if (per_cpu(translate_buffer, cpu)[ptr] == (void *)task)
goto out;
ptr = (ptr + 2) & translate_buffer_mask;
}
- translate_buffer_write_int(cpu, (unsigned int)task);
- translate_buffer_write_int(cpu, (unsigned int)vma);
+ translate_buffer_write_ptr(cpu, (void *)task);
+ translate_buffer_write_ptr(cpu, (void *)vma);
mod_timer(&app_process_wake_up_timer, jiffies + 1);
goto out;
@@ -222,7 +222,7 @@ out:
return retval;
}
-static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt)
+static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt)
{
unsigned long flags, cookie;
struct path *path;
@@ -271,7 +271,7 @@ static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task
return cookie;
}
-static int get_exec_cookie(int cpu, int buftype, struct task_struct *task)
+static int get_exec_cookie(int cpu, struct task_struct *task)
{
unsigned long cookie = NO_COOKIE;
struct mm_struct *mm = task->mm;
@@ -286,14 +286,14 @@ static int get_exec_cookie(int cpu, int buftype, struct task_struct *task)
continue;
if (!(vma->vm_flags & VM_EXECUTABLE))
continue;
- cookie = get_cookie(cpu, buftype, task, vma, NULL, true);
+ cookie = get_cookie(cpu, task, vma, NULL, true);
break;
}
return cookie;
}
-static unsigned long get_address_cookie(int cpu, int buftype, struct task_struct *task, unsigned long addr, off_t *offset)
+static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsigned long addr, off_t *offset)
{
unsigned long cookie = NO_COOKIE;
struct mm_struct *mm = task->mm;
@@ -307,7 +307,7 @@ static unsigned long get_address_cookie(int cpu, int buftype, struct task_struct
continue;
if (vma->vm_file) {
- cookie = get_cookie(cpu, buftype, task, vma, NULL, true);
+ cookie = get_cookie(cpu, task, vma, NULL, true);
*offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start;
} else {
/* must be an anonymous map */
@@ -350,7 +350,7 @@ static int cookies_initialize(void)
}
memset(per_cpu(cookie_values, cpu), 0, size);
- per_cpu(translate_buffer, cpu) = (unsigned int *)kmalloc(translate_buffer_size, GFP_KERNEL);
+ per_cpu(translate_buffer, cpu) = (void * *)kmalloc(translate_buffer_size, GFP_KERNEL);
if (!per_cpu(translate_buffer, cpu)) {
err = -ENOMEM;
goto cookie_setup_error;
diff --git a/driver/gator_ebs.c b/driver/gator_ebs.c
deleted file mode 100644
index 6abdfa4..0000000
--- a/driver/gator_ebs.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2012. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#if defined(__arm__) && (GATOR_PERF_PMU_SUPPORT)
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-
-#include <asm/pmu.h>
-
-static DEFINE_MUTEX(perf_mutex);
-
-extern int pmnc_counters;
-extern int ccnt;
-extern unsigned long pmnc_enabled[];
-extern unsigned long pmnc_event[];
-extern unsigned long pmnc_count[];
-extern unsigned long pmnc_key[];
-
-static DEFINE_PER_CPU(struct perf_event_attr *, pevent_attr);
-static DEFINE_PER_CPU(int, key);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
-static void ebs_overflow_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs)
-#else
-static void ebs_overflow_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
-#endif
-{
- int cpu = smp_processor_id();
-
- if (event != per_cpu(pevent_ebs, cpu))
- return;
-
- // Output backtrace
- gator_add_sample(cpu, BACKTRACE_BUF, regs);
-
- // Collect counters
- collect_counters();
-}
-
-static void gator_event_sampling_online_dispatch(int cpu)
-{
- struct perf_event * ev;
-
- if (!event_based_sampling)
- return;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
- ev = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu), cpu, 0, ebs_overflow_handler);
-#else
- ev = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu), cpu, 0, ebs_overflow_handler, 0);
-#endif
-
- if (IS_ERR(ev)) {
- pr_err("gator: unable to start event-based-sampling");
- return;
- }
-
- if (ev->state != PERF_EVENT_STATE_ACTIVE) {
- pr_err("gator: unable to start event-based-sampling");
- perf_event_release_kernel(ev);
- return;
- }
-
- ev->pmu->read(ev);
- per_cpu(pevent_ebs, cpu) = ev;
-}
-
-static void gator_event_sampling_offline_dispatch(int cpu)
-{
- struct perf_event * pe = NULL;
-
- mutex_lock(&perf_mutex);
- if (per_cpu(pevent_ebs, cpu)) {
- pe = per_cpu(pevent_ebs, cpu);
- per_cpu(pevent_ebs, cpu) = NULL;
- }
- mutex_unlock(&perf_mutex);
-
- if (pe) {
- perf_event_release_kernel(pe);
- }
-}
-
-static int gator_event_sampling_start(void)
-{
- int cnt, event = 0, count = 0, ebs_key = 0, cpu;
-
- for_each_present_cpu(cpu) {
- per_cpu(pevent_ebs, cpu) = NULL;
- per_cpu(pevent_attr, cpu) = NULL;
- }
-
- event_based_sampling = false;
- for (cnt = 0; cnt < pmnc_counters; cnt++) {
- if (pmnc_count[cnt] > 0) {
- event_based_sampling = true;
- event = pmnc_event[cnt];
- count = pmnc_count[cnt];
- ebs_key = pmnc_key[cnt];
- break;
- }
- }
-
- if (!event_based_sampling)
- return 0;
-
- for_each_present_cpu(cpu) {
- u32 size = sizeof(struct perf_event_attr);
- per_cpu(pevent_attr, cpu) = kmalloc(size, GFP_KERNEL);
- if (!per_cpu(pevent_attr, cpu))
- return -1;
-
- memset(per_cpu(pevent_attr, cpu), 0, size);
- per_cpu(pevent_attr, cpu)->type = PERF_TYPE_RAW;
- per_cpu(pevent_attr, cpu)->size = size;
- per_cpu(pevent_attr, cpu)->config = event;
- per_cpu(pevent_attr, cpu)->sample_period = count;
- per_cpu(pevent_attr, cpu)->pinned = 1;
-
- // handle special case for ccnt
- if (cnt == ccnt) {
- per_cpu(pevent_attr, cpu)->type = PERF_TYPE_HARDWARE;
- per_cpu(pevent_attr, cpu)->config = PERF_COUNT_HW_CPU_CYCLES;
- }
-
- per_cpu(key, cpu) = ebs_key;
- }
-
- return 0;
-}
-
-static void gator_event_sampling_stop(void)
-{
- int cpu;
-
- for_each_present_cpu(cpu) {
- if (per_cpu(pevent_attr, cpu)) {
- kfree(per_cpu(pevent_attr, cpu));
- per_cpu(pevent_attr, cpu) = NULL;
- }
- }
-}
-
-#else
-static void gator_event_sampling_online_dispatch(int cpu) {}
-static void gator_event_sampling_offline_dispatch(int cpu) {}
-static int gator_event_sampling_start(void) {return 0;}
-static void gator_event_sampling_stop(void) {}
-#endif
diff --git a/driver/gator_events_block.c b/driver/gator_events_block.c
index a8b8114..b18c3ca 100644
--- a/driver/gator_events_block.c
+++ b/driver/gator_events_block.c
@@ -25,15 +25,13 @@ static ulong block_rq_wr_enabled;
static ulong block_rq_rd_enabled;
static ulong block_rq_wr_key;
static ulong block_rq_rd_key;
-static DEFINE_PER_CPU(int[BLOCK_TOTAL], blockCnt);
-static DEFINE_PER_CPU(int[BLOCK_TOTAL * 4], blockGet);
-static DEFINE_PER_CPU(bool, new_data_avail);
+static atomic_t blockCnt[BLOCK_TOTAL];
+static int blockGet[BLOCK_TOTAL * 4];
GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct request *rq))
{
unsigned long flags;
int write, size;
- int cpu = smp_processor_id();
if (!rq)
return;
@@ -47,13 +45,16 @@ GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct r
// disable interrupts to synchronize with gator_events_block_read()
// spinlocks not needed since percpu buffers are used
local_irq_save(flags);
- if (write)
- per_cpu(blockCnt, cpu)[BLOCK_RQ_WR] += size;
- else
- per_cpu(blockCnt, cpu)[BLOCK_RQ_RD] += size;
+ if (write) {
+ if (block_rq_wr_enabled) {
+ atomic_add(size, &blockCnt[BLOCK_RQ_WR]);
+ }
+ } else {
+ if (block_rq_rd_enabled) {
+ atomic_add(size, &blockCnt[BLOCK_RQ_RD]);
+ }
+ }
local_irq_restore(flags);
-
- per_cpu(new_data_avail, cpu) = true;
}
static int gator_events_block_create_files(struct super_block *sb, struct dentry *root)
@@ -81,11 +82,6 @@ static int gator_events_block_create_files(struct super_block *sb, struct dentry
static int gator_events_block_start(void)
{
- int cpu;
-
- for_each_present_cpu(cpu)
- per_cpu(new_data_avail, cpu) = true;
-
// register tracepoints
if (block_rq_wr_enabled || block_rq_rd_enabled)
if (GATOR_REGISTER_TRACE(block_rq_complete))
@@ -113,44 +109,32 @@ static void gator_events_block_stop(void)
static int gator_events_block_read(int **buffer)
{
- unsigned long flags;
- int len, value, cpu, data = 0;
- cpu = smp_processor_id();
+ int len, value, data = 0;
- if (per_cpu(new_data_avail, cpu) == false)
+ if (smp_processor_id() != 0) {
return 0;
-
- per_cpu(new_data_avail, cpu) = false;
+ }
len = 0;
- if (block_rq_wr_enabled) {
- local_irq_save(flags);
- value = per_cpu(blockCnt, cpu)[BLOCK_RQ_WR];
- per_cpu(blockCnt, cpu)[BLOCK_RQ_WR] = 0;
- local_irq_restore(flags);
- per_cpu(blockGet, cpu)[len++] = block_rq_wr_key;
- per_cpu(blockGet, cpu)[len++] = 0; // indicates to Streamline that value bytes were written now, not since the last message
- per_cpu(blockGet, cpu)[len++] = block_rq_wr_key;
- per_cpu(blockGet, cpu)[len++] = value;
+ if (block_rq_wr_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_WR])) > 0) {
+ atomic_sub(value, &blockCnt[BLOCK_RQ_WR]);
+ blockGet[len++] = block_rq_wr_key;
+ blockGet[len++] = 0; // indicates to Streamline that value bytes were written now, not since the last message
+ blockGet[len++] = block_rq_wr_key;
+ blockGet[len++] = value;
data += value;
}
- if (block_rq_rd_enabled) {
- local_irq_save(flags);
- value = per_cpu(blockCnt, cpu)[BLOCK_RQ_RD];
- per_cpu(blockCnt, cpu)[BLOCK_RQ_RD] = 0;
- local_irq_restore(flags);
- per_cpu(blockGet, cpu)[len++] = block_rq_rd_key;
- per_cpu(blockGet, cpu)[len++] = 0; // indicates to Streamline that value bytes were read now, not since the last message
- per_cpu(blockGet, cpu)[len++] = block_rq_rd_key;
- per_cpu(blockGet, cpu)[len++] = value;
+ if (block_rq_rd_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_RD])) > 0) {
+ atomic_sub(value, &blockCnt[BLOCK_RQ_RD]);
+ blockGet[len++] = block_rq_rd_key;
+ blockGet[len++] = 0; // indicates to Streamline that value bytes were read now, not since the last message
+ blockGet[len++] = block_rq_rd_key;
+ blockGet[len++] = value;
data += value;
}
- if (data != 0)
- per_cpu(new_data_avail, cpu) = true;
-
if (buffer)
- *buffer = per_cpu(blockGet, cpu);
+ *buffer = blockGet;
return len;
}
diff --git a/driver/gator_events_mali_400.c b/driver/gator_events_mali_400.c
index ef4cc58..65eeb4f 100644
--- a/driver/gator_events_mali_400.c
+++ b/driver/gator_events_mali_400.c
@@ -385,7 +385,7 @@ static int create_files(struct super_block *sb, struct dentry *root) {
switch(event) {
case COUNTER_FILMSTRIP:
- snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip", mali_name);
+ snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip_cnt0", mali_name);
break;
case COUNTER_FREQUENCY:
diff --git a/driver/gator_events_mali_400.h b/driver/gator_events_mali_400.h
index b784ae9..a09757e 100644
--- a/driver/gator_events_mali_400.h
+++ b/driver/gator_events_mali_400.h
@@ -1,11 +1,10 @@
-/*
- * This confidential and proprietary software may be used only as
- * authorised by a licensing agreement from ARM Limited
- * (C) COPYRIGHT 2011-2012 ARM Limited
- * ALL RIGHTS RESERVED
- * The entire notice above must be reproduced on all authorised
- * copies and copies may only be made to the extent permitted
- * by a licensing agreement from ARM Limited.
+/**
+ * Copyright (C) ARM Limited 2011-2012. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
*/
/*
diff --git a/driver/gator_events_mali_common.c b/driver/gator_events_mali_common.c
index 2dd9ad6..62e441c 100644
--- a/driver/gator_events_mali_common.c
+++ b/driver/gator_events_mali_common.c
@@ -1,11 +1,10 @@
-/*
- * This confidential and proprietary software may be used only as
- * authorised by a licensing agreement from ARM Limited
- * (C) COPYRIGHT 2011-2012 ARM Limited
- * ALL RIGHTS RESERVED
- * The entire notice above must be reproduced on all authorised
- * copies and copies may only be made to the extent permitted
- * by a licensing agreement from ARM Limited.
+/**
+ * Copyright (C) ARM Limited 2012. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
*/
#include "gator_events_mali_common.h"
diff --git a/driver/gator_events_mali_common.h b/driver/gator_events_mali_common.h
index cb851d5..2c9457f 100644
--- a/driver/gator_events_mali_common.h
+++ b/driver/gator_events_mali_common.h
@@ -1,12 +1,12 @@
-/*
- * This confidential and proprietary software may be used only as
- * authorised by a licensing agreement from ARM Limited
- * (C) COPYRIGHT 2011-2012 ARM Limited
- * ALL RIGHTS RESERVED
- * The entire notice above must be reproduced on all authorised
- * copies and copies may only be made to the extent permitted
- * by a licensing agreement from ARM Limited.
+/**
+ * Copyright (C) ARM Limited 2012. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
*/
+
#if !defined(GATOR_EVENTS_MALI_COMMON_H)
#define GATOR_EVENTS_MALI_COMMON_H
@@ -39,6 +39,9 @@ typedef struct {
unsigned long enabled; /* counter enable state */
} mali_counter;
+/*
+ * Mali-400
+ */
typedef void mali_profiling_set_event_type(unsigned int, unsigned int);
typedef void mali_osk_fb_control_set_type(unsigned int, unsigned int);
typedef void mali_profiling_control_type(unsigned int, unsigned int);
diff --git a/driver/gator_events_mali_t6xx.c b/driver/gator_events_mali_t6xx.c
index 79af764..f8f868e 100644
--- a/driver/gator_events_mali_t6xx.c
+++ b/driver/gator_events_mali_t6xx.c
@@ -1,11 +1,10 @@
-/*
- * This confidential and proprietary software may be used only as
- * authorised by a licensing agreement from ARM Limited
- * (C) COPYRIGHT 2011 ARM Limited
- * ALL RIGHTS RESERVED
- * The entire notice above must be reproduced on all authorised
- * copies and copies may only be made to the extent permitted
- * by a licensing agreement from ARM Limited.
+/**
+ * Copyright (C) ARM Limited 2011-2012. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
*/
#include "gator.h"
diff --git a/driver/gator_events_mali_t6xx_hw.c b/driver/gator_events_mali_t6xx_hw.c
index 12ffebc..d4945c7 100644
--- a/driver/gator_events_mali_t6xx_hw.c
+++ b/driver/gator_events_mali_t6xx_hw.c
@@ -1,11 +1,10 @@
-/*
- * This confidential and proprietary software may be used only as
- * authorised by a licensing agreement from ARM Limited
- * (C) COPYRIGHT 2011-2012 ARM Limited
- * ALL RIGHTS RESERVED
- * The entire notice above must be reproduced on all authorised
- * copies and copies may only be made to the extent permitted
- * by a licensing agreement from ARM Limited.
+/**
+ * Copyright (C) ARM Limited 2012. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
*/
#include "gator.h"
@@ -23,6 +22,39 @@
#include "gator_events_mali_common.h"
+/*
+ * Mali-T6xx
+ */
+typedef struct kbase_device *kbase_find_device_type(int);
+typedef kbase_context *kbase_create_context_type(kbase_device*);
+typedef void kbase_destroy_context_type(kbase_context *);
+typedef void *kbase_va_alloc_type(kbase_context *, u32);
+typedef void kbase_va_free_type(kbase_context *, void *);
+typedef mali_error kbase_instr_hwcnt_enable_type(kbase_context *, kbase_uk_hwcnt_setup *);
+typedef mali_error kbase_instr_hwcnt_disable_type(kbase_context *);
+typedef mali_error kbase_instr_hwcnt_clear_type(kbase_context *);
+typedef mali_error kbase_instr_hwcnt_dump_irq_type(kbase_context *);
+typedef mali_bool kbase_instr_hwcnt_dump_complete_type(kbase_context *, mali_bool *);
+
+static kbase_find_device_type * kbase_find_device_symbol;
+static kbase_create_context_type * kbase_create_context_symbol;
+static kbase_va_alloc_type * kbase_va_alloc_symbol;
+static kbase_instr_hwcnt_enable_type * kbase_instr_hwcnt_enable_symbol;
+static kbase_instr_hwcnt_clear_type * kbase_instr_hwcnt_clear_symbol;
+static kbase_instr_hwcnt_dump_irq_type * kbase_instr_hwcnt_dump_irq_symbol;
+static kbase_instr_hwcnt_dump_complete_type * kbase_instr_hwcnt_dump_complete_symbol;
+static kbase_instr_hwcnt_disable_type * kbase_instr_hwcnt_disable_symbol;
+static kbase_va_free_type * kbase_va_free_symbol;
+static kbase_destroy_context_type * kbase_destroy_context_symbol;
+
+/** The interval between reads, in ns. */
+static const int READ_INTERVAL_NSEC = 1000000;
+
+
+#if GATOR_TEST
+#include "gator_events_mali_t6xx_hw_test.c"
+#endif
+
/* Blocks for HW counters */
enum
{
@@ -322,7 +354,12 @@ static void *kernel_dump_buffer;
static kbase_context *kbcontext = NULL;
static struct kbase_device *kbdevice = NULL;
-extern struct kbase_device *kbase_find_device(int minor);
+/*
+ * The following function has no external prototype in older DDK revisions. When the DDK
+ * is updated then this should be removed.
+ */
+struct kbase_device *kbase_find_device(int minor);
+
static volatile bool kbase_device_busy = false;
static unsigned int num_hardware_counters_enabled;
@@ -336,6 +373,96 @@ static mali_counter counters[NUMBER_OF_HARDWARE_COUNTERS];
*/
static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2];
+#define SYMBOL_GET(FUNCTION, ERROR_COUNT) \
+ if(FUNCTION ## _symbol) \
+ { \
+ printk("gator: mali " #FUNCTION " symbol was already registered\n"); \
+ (ERROR_COUNT)++; \
+ } \
+ else \
+ { \
+ FUNCTION ## _symbol = symbol_get(FUNCTION); \
+ if(! FUNCTION ## _symbol) \
+ { \
+ printk("gator: mali online " #FUNCTION " symbol not found\n"); \
+ (ERROR_COUNT)++; \
+ } \
+ }
+
+#define SYMBOL_CLEANUP(FUNCTION) \
+ if(FUNCTION ## _symbol) \
+ { \
+ symbol_put(FUNCTION); \
+ FUNCTION ## _symbol = NULL; \
+ }
+
+/**
+ * Execute symbol_get for all the Mali symbols and check for success.
+ * @return the number of symbols not loaded.
+ */
+static int init_symbols(void)
+{
+ int error_count = 0;
+ SYMBOL_GET(kbase_find_device, error_count);
+ SYMBOL_GET(kbase_create_context, error_count);
+ SYMBOL_GET(kbase_va_alloc, error_count);
+ SYMBOL_GET(kbase_instr_hwcnt_enable, error_count);
+ SYMBOL_GET(kbase_instr_hwcnt_clear, error_count);
+ SYMBOL_GET(kbase_instr_hwcnt_dump_irq, error_count);
+ SYMBOL_GET(kbase_instr_hwcnt_dump_complete, error_count);
+ SYMBOL_GET(kbase_instr_hwcnt_disable, error_count);
+ SYMBOL_GET(kbase_va_free, error_count);
+ SYMBOL_GET(kbase_destroy_context, error_count);
+
+ return error_count;
+}
+
+/**
+ * Execute symbol_put for all the registered Mali symbols.
+ */
+static void clean_symbols(void)
+{
+ SYMBOL_CLEANUP(kbase_find_device);
+ SYMBOL_CLEANUP(kbase_create_context);
+ SYMBOL_CLEANUP(kbase_va_alloc);
+ SYMBOL_CLEANUP(kbase_instr_hwcnt_enable);
+ SYMBOL_CLEANUP(kbase_instr_hwcnt_clear);
+ SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_irq);
+ SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_complete);
+ SYMBOL_CLEANUP(kbase_instr_hwcnt_disable);
+ SYMBOL_CLEANUP(kbase_va_free);
+ SYMBOL_CLEANUP(kbase_destroy_context);
+}
+
+/**
+ * Determines whether a read should take place
+ * @param current_time The current time, obtained from getnstimeofday()
+ * @param prev_time_s The number of seconds at the previous read attempt.
+ * @param next_read_time_ns The time (in ns) when the next read should be allowed.
+ *
+ * Note that this function has been separated out here to allow it to be tested.
+ */
+static int is_read_scheduled(const struct timespec *current_time, u32* prev_time_s, s32* next_read_time_ns)
+{
+ /* If the current ns count rolls over a second, roll the next read time too. */
+ if(current_time->tv_sec != *prev_time_s)
+ {
+ *next_read_time_ns = *next_read_time_ns - NSEC_PER_SEC;
+ }
+
+ /* Abort the read if the next read time has not arrived. */
+ if(current_time->tv_nsec < *next_read_time_ns)
+ {
+ return 0;
+ }
+
+ /* Set the next read some fixed time after this one, and update the read timestamp. */
+ *next_read_time_ns = current_time->tv_nsec + READ_INTERVAL_NSEC;
+
+ *prev_time_s = current_time->tv_sec;
+ return 1;
+}
+
static int start(void)
{
kbase_uk_hwcnt_setup setup;
@@ -368,12 +495,23 @@ static int start(void)
/* Create a kbase context for HW counters */
if (num_hardware_counters_enabled > 0)
{
- kbdevice = kbase_find_device(-1);
-
- if (kbcontext)
- return -1;
+ if(init_symbols() > 0)
+ {
+ clean_symbols();
+ /* No Mali driver code entrypoints found - not a fault. */
+ return 0;
+ }
+
+ kbdevice = kbase_find_device_symbol(-1);
+
+ /* If we already got a context, fail */
+ if (kbcontext) {
+ pr_debug("gator: Mali-T6xx: error context already present\n");
+ goto out;
+ }
- kbcontext = kbase_create_context(kbdevice);
+ /* kbcontext will only be valid after all the Mali symbols are loaded successfully */
+ kbcontext = kbase_create_context_symbol(kbdevice);
if (!kbcontext)
{
pr_debug("gator: Mali-T6xx: error creating kbase context\n");
@@ -388,7 +526,7 @@ static int start(void)
* * number of bytes per counter (always 4 in midgard)
* For a Mali-T6xx with a single core group = 1 * 8 * 64 * 4
*/
- kernel_dump_buffer = kbase_va_alloc(kbcontext, 2048);
+ kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 2048);
if (!kernel_dump_buffer)
{
pr_debug("gator: Mali-T6xx: error trying to allocate va\n");
@@ -404,14 +542,14 @@ static int start(void)
setup.l3_cache_bm = 0;
/* Use kbase API to enable hardware counters and provide dump buffer */
- err = kbase_instr_hwcnt_enable(kbcontext, &setup);
+ err = kbase_instr_hwcnt_enable_symbol(kbcontext, &setup);
if (err != MALI_ERROR_NONE)
{
pr_debug("gator: Mali-T6xx: can't setup hardware counters\n");
goto free_buffer;
}
pr_debug("gator: Mali-T6xx: hardware counters enabled\n");
- kbase_instr_hwcnt_clear(kbcontext);
+ kbase_instr_hwcnt_clear_symbol(kbcontext);
pr_debug("gator: Mali-T6xx: hardware counters cleared \n");
kbase_device_busy = false;
@@ -420,10 +558,13 @@ static int start(void)
return 0;
free_buffer:
- kbase_va_free(kbcontext, kernel_dump_buffer);
+ kbase_va_free_symbol(kbcontext, kernel_dump_buffer);
+
destroy_context:
- kbase_destroy_context(kbcontext);
+ kbase_destroy_context_symbol(kbcontext);
+
out:
+ clean_symbols();
return -1;
}
@@ -448,10 +589,13 @@ static void stop(void) {
temp_kbcontext = kbcontext;
kbcontext = NULL;
- kbase_instr_hwcnt_disable(temp_kbcontext);
- kbase_va_free(temp_kbcontext, kernel_dump_buffer);
- kbase_destroy_context(temp_kbcontext);
+ kbase_instr_hwcnt_disable_symbol(temp_kbcontext);
+ kbase_va_free_symbol(temp_kbcontext, kernel_dump_buffer);
+ kbase_destroy_context_symbol(temp_kbcontext);
+
pr_debug("gator: Mali-T6xx: hardware counters stopped\n");
+
+ clean_symbols();
}
}
@@ -461,11 +605,26 @@ static int read(int **buffer) {
u32 value = 0;
mali_bool success;
+ struct timespec current_time;
+ static u32 prev_time_s = 0;
+ static s32 next_read_time_ns = 0;
+
if (smp_processor_id()!=0)
{
return 0;
}
+ getnstimeofday(&current_time);
+
+ /*
+ * Discard reads unless a respectable time has passed. This reduces the load on the GPU without sacrificing
+ * accuracy on the Streamline display.
+ */
+ if(!is_read_scheduled(&current_time, &prev_time_s, &next_read_time_ns))
+ {
+ return 0;
+ }
+
/*
* Report the HW counters
* Only process hardware counters if at least one of the hardware counters is enabled.
@@ -484,8 +643,8 @@ static int read(int **buffer) {
return -1;
}
- // TODO: SYMBOL_GET (all kbase functions)
- if (kbase_instr_hwcnt_dump_complete(kbcontext, &success) == MALI_TRUE)
+ /* Mali symbols can be called safely since a kbcontext is valid */
+ if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE)
{
kbase_device_busy = false;
@@ -520,7 +679,7 @@ static int read(int **buffer) {
if (! kbase_device_busy)
{
kbase_device_busy = true;
- kbase_instr_hwcnt_dump_irq(kbcontext);
+ kbase_instr_hwcnt_dump_irq_symbol(kbcontext);
}
}
@@ -551,7 +710,6 @@ static int create_files(struct super_block *sb, struct dentry *root)
return 0;
}
-
static struct gator_interface gator_events_mali_t6xx_interface = {
.create_files = create_files,
.start = start,
@@ -563,6 +721,10 @@ int gator_events_mali_t6xx_hw_init(void)
{
pr_debug("gator: Mali-T6xx: sw_counters init\n");
+#if GATOR_TEST
+ test_all_is_read_scheduled();
+#endif
+
gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS);
return gator_events_install(&gator_events_mali_t6xx_interface);
diff --git a/driver/gator_events_mali_t6xx_hw_test.c b/driver/gator_events_mali_t6xx_hw_test.c
new file mode 100644
index 0000000..61ec336
--- /dev/null
+++ b/driver/gator_events_mali_t6xx_hw_test.c
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) ARM Limited 2012. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/**
+ * Test functions for mali_t600_hw code.
+ */
+
+static int is_read_scheduled(const struct timespec *current_time, u32* prev_time_s, s32* next_read_time_ns);
+
+static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int expected_result, s32 expected_next_ns)
+{
+ struct timespec current_time;
+ u32 prev_time_s = prev_s;
+ s32 next_read_time_ns = next_ns;
+
+ current_time.tv_sec = s;
+ current_time.tv_nsec = ns;
+
+ if(is_read_scheduled(&current_time, &prev_time_s, &next_read_time_ns) != expected_result)
+ {
+ printk("Failed do_read(%u, %u, %u, %d): expected %d\n", s, ns, prev_s, next_ns, expected_result);
+ return 0;
+ }
+
+ if(next_read_time_ns != expected_next_ns)
+ {
+ printk("Failed: next_read_ns expected=%d, actual=%d\n", expected_next_ns, next_read_time_ns);
+ return 0;
+ }
+
+ return 1;
+}
+
+static void test_all_is_read_scheduled(void)
+{
+ const int HIGHEST_NS = 999999999;
+ int n_tests_passed = 0;
+
+ printk("gator: running tests on %s\n", __FILE__);
+
+ n_tests_passed += test_is_read_scheduled(0,0,0,0, 1, READ_INTERVAL_NSEC); /* Null time */
+ n_tests_passed += test_is_read_scheduled(100,1000,0,0, 1, READ_INTERVAL_NSEC + 1000); /* Initial values */
+
+ n_tests_passed += test_is_read_scheduled(100, HIGHEST_NS, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500);
+ n_tests_passed += test_is_read_scheduled(101, 0001, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500 - NSEC_PER_SEC);
+ n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500 - NSEC_PER_SEC, 1, 600 + READ_INTERVAL_NSEC);
+
+ n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500, 1, 600 + READ_INTERVAL_NSEC);
+
+ printk("gator: %d tests passed\n", n_tests_passed);
+}
diff --git a/driver/gator_events_mmaped.c b/driver/gator_events_mmaped.c
index f81c402..1be6e66 100644
--- a/driver/gator_events_mmaped.c
+++ b/driver/gator_events_mmaped.c
@@ -11,12 +11,8 @@
* To add them to the events.xml, create an events-mmap.xml with the
* following contents and rebuild gatord:
*
- * <counter_set name="mmaped_cntX">
- * <counter name="mmaped_cnt0"/>
- * <counter name="mmaped_cnt1"/>
- * <counter name="mmaped_cnt2"/>
- * </counter_set>
- * <category name="mmaped" counter_set="mmaped_cntX" per_cpu="no">
+ * <counter_set name="mmaped_cnt" count="3"/>
+ * <category name="mmaped" counter_set="mmaped_cnt" per_cpu="no">
* <event event="0x0" title="Simulated" name="Sine" display="maximum" average_selection="yes" description="Sort-of-sine"/>
* <event event="0x1" title="Simulated" name="Triangle" display="maximum" average_selection="yes" description="Triangular wave"/>
* <event event="0x2" title="Simulated" name="PWM" display="maximum" average_selection="yes" description="PWM Signal"/>
diff --git a/driver/gator_events_net.c b/driver/gator_events_net.c
index 11282b5..31cc3ef 100644
--- a/driver/gator_events_net.c
+++ b/driver/gator_events_net.c
@@ -95,7 +95,11 @@ static int gator_events_net_start(void)
get_network_stats(0);
netPrev[NETRX] = rx_total;
netPrev[NETTX] = tx_total;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
setup_timer(&net_wake_up_timer, net_wake_up_handler, 0);
+#else
+ setup_deferrable_timer_on_stack(&net_wake_up_timer, net_wake_up_handler, 0);
+#endif
return 0;
}
diff --git a/driver/gator_events_perf_pmu.c b/driver/gator_events_perf_pmu.c
index 9d78b46..e025155 100644
--- a/driver/gator_events_perf_pmu.c
+++ b/driver/gator_events_perf_pmu.c
@@ -32,7 +32,6 @@ static DEFINE_PER_CPU(int[CNTMAX], perfPrevDelta);
static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt);
static DEFINE_PER_CPU(struct perf_event *[CNTMAX], pevent);
static DEFINE_PER_CPU(struct perf_event_attr *[CNTMAX], pevent_attr);
-extern DEFINE_PER_CPU(struct perf_event *, pevent_ebs);
static void gator_events_perf_pmu_stop(void);
@@ -64,6 +63,15 @@ static int gator_events_perf_pmu_create_files(struct super_block *sb, struct den
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
+static void ebs_overflow_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs)
+#else
+static void ebs_overflow_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
+#endif
+{
+ gator_backtrace_handler(regs);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
static void dummy_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs)
#else
static void dummy_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
@@ -75,15 +83,10 @@ static void dummy_handler(struct perf_event *event, struct perf_sample_data *dat
static int gator_events_perf_pmu_online(int** buffer)
{
int cnt, len = 0, cpu = smp_processor_id();
- struct perf_event * ev;
// read the counters and toss the invalid data, return zero instead
for (cnt = 0; cnt < pmnc_counters; cnt++) {
- if (pmnc_count[cnt] > 0) {
- ev = per_cpu(pevent_ebs, cpu); // special case for EBS
- } else {
- ev = per_cpu(pevent, cpu)[cnt];
- }
+ struct perf_event * ev = per_cpu(pevent, cpu)[cnt];
if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
ev->pmu->read(ev);
per_cpu(perfPrev, cpu)[cnt] = per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count);
@@ -102,18 +105,22 @@ static int gator_events_perf_pmu_online(int** buffer)
static void gator_events_perf_pmu_online_dispatch(int cpu)
{
int cnt;
+ perf_overflow_handler_t handler;
for (cnt = 0; cnt < pmnc_counters; cnt++) {
if (per_cpu(pevent, cpu)[cnt] != NULL || per_cpu(pevent_attr, cpu)[cnt] == 0)
continue;
- if (pmnc_count[cnt] > 0)
- continue; // skip the EBS counter
+ if (pmnc_count[cnt] > 0) {
+ handler = ebs_overflow_handler;
+ } else {
+ handler = dummy_handler;
+ }
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
- per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, dummy_handler);
+ per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, handler);
#else
- per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, dummy_handler, 0);
+ per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, handler, 0);
#endif
if (IS_ERR(per_cpu(pevent, cpu)[cnt])) {
pr_debug("gator: unable to online a counter on cpu %d\n", cpu);
@@ -154,6 +161,18 @@ static int gator_events_perf_pmu_start(void)
{
int cnt, cpu;
u32 size = sizeof(struct perf_event_attr);
+ int found_ebs = false;
+
+ for (cnt = 0; cnt < pmnc_counters; cnt++) {
+ if (pmnc_count[cnt] > 0) {
+ if (!found_ebs) {
+ found_ebs = true;
+ } else {
+ // Only one ebs counter is allowed
+ return -1;
+ }
+ }
+ }
for_each_present_cpu(cpu) {
for (cnt = 0; cnt < pmnc_counters; cnt++) {
@@ -174,7 +193,7 @@ static int gator_events_perf_pmu_start(void)
per_cpu(pevent_attr, cpu)[cnt]->type = PERF_TYPE_RAW;
per_cpu(pevent_attr, cpu)[cnt]->size = size;
per_cpu(pevent_attr, cpu)[cnt]->config = pmnc_event[cnt];
- per_cpu(pevent_attr, cpu)[cnt]->sample_period = 0;
+ per_cpu(pevent_attr, cpu)[cnt]->sample_period = pmnc_count[cnt];
per_cpu(pevent_attr, cpu)[cnt]->pinned = 1;
// handle special case for ccnt
@@ -212,14 +231,9 @@ static int gator_events_perf_pmu_read(int **buffer)
{
int cnt, delta, len = 0;
int cpu = smp_processor_id();
- struct perf_event * ev;
for (cnt = 0; cnt < pmnc_counters; cnt++) {
- if (pmnc_count[cnt] > 0) {
- ev = per_cpu(pevent_ebs, cpu); // special case for EBS
- } else {
- ev = per_cpu(pevent, cpu)[cnt];
- }
+ struct perf_event * ev = per_cpu(pevent, cpu)[cnt];
if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
ev->pmu->read(ev);
per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count);
@@ -300,6 +314,11 @@ int gator_events_perf_pmu_init(void)
pmnc_name = "Krait";
pmnc_counters = 4;
break;
+ case AARCH64:
+ pmnc_name = "ARM_AArch64";
+ // Copied from A15, get the correct number
+ pmnc_counters = 6;
+ break;
default:
return -1;
}
diff --git a/driver/gator_main.c b/driver/gator_main.c
index db728ad..309c6c2 100644
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
@@ -7,7 +7,7 @@
*
*/
-static unsigned long gator_protocol_version = 10;
+static unsigned long gator_protocol_version = 11;
#include <linux/slab.h>
#include <linux/cpu.h>
@@ -57,41 +57,65 @@ static unsigned long gator_protocol_version = 10;
/******************************************************************************
* DEFINES
******************************************************************************/
-#define BACKTRACE_BUFFER_SIZE (128*1024)
-#define COUNTER_BUFFER_SIZE (128*1024)
-#define ANNOTATE_BUFFER_SIZE (64*1024) // annotate counters have the core as part of the data and the core value in the frame header may be discarded
-#define SCHED_TRACE_BUFFER_SIZE (128*1024)
-#define GPU_TRACE_BUFFER_SIZE (64*1024)
-#define COUNTER2_BUFFER_SIZE (64*1024) // counters2 counters have the core as part of the data and the core value in the frame header may be discarded
-#define WFI_BUFFER_SIZE (32*1024) // wfi counters have the core as part of the data and the core value in the frame header may be discarded
-
-#define NO_COOKIE 0UL
-#define INVALID_COOKIE ~0UL
-
-#define FRAME_BACKTRACE 1
-#define FRAME_COUNTER 2
-#define FRAME_ANNOTATE 3
-#define FRAME_SCHED_TRACE 4
-#define FRAME_GPU_TRACE 5
-#define FRAME_COUNTER2 6
-#define FRAME_WFI 7
-
-#define MESSAGE_COOKIE 1
-#define MESSAGE_START_BACKTRACE 5
-#define MESSAGE_END_BACKTRACE 7
-#define MESSAGE_SUMMARY 9
-#define MESSAGE_PID_NAME 11
-
-#define MAXSIZE_PACK32 5
-#define MAXSIZE_PACK64 9
+#define SUMMARY_BUFFER_SIZE (1*1024)
+#define BACKTRACE_BUFFER_SIZE (128*1024)
+#define NAME_BUFFER_SIZE (64*1024)
+#define COUNTER_BUFFER_SIZE (64*1024) // counters have the core as part of the data and the core value in the frame header may be discarded
+#define BLOCK_COUNTER_BUFFER_SIZE (128*1024)
+#define ANNOTATE_BUFFER_SIZE (64*1024) // annotate counters have the core as part of the data and the core value in the frame header may be discarded
+#define SCHED_TRACE_BUFFER_SIZE (128*1024)
+#define GPU_TRACE_BUFFER_SIZE (64*1024) // gpu trace counters have the core as part of the data and the core value in the frame header may be discarded
+#define IDLE_BUFFER_SIZE (32*1024) // idle counters have the core as part of the data and the core value in the frame header may be discarded
+
+#define NO_COOKIE 0U
+#define INVALID_COOKIE ~0U
+
+#define FRAME_SUMMARY 1
+#define FRAME_BACKTRACE 2
+#define FRAME_NAME 3
+#define FRAME_COUNTER 4
+#define FRAME_BLOCK_COUNTER 5
+#define FRAME_ANNOTATE 6
+#define FRAME_SCHED_TRACE 7
+#define FRAME_GPU_TRACE 8
+#define FRAME_IDLE 9
+
+#define MESSAGE_END_BACKTRACE 1
+
+#define MESSAGE_COOKIE 1
+#define MESSAGE_THREAD_NAME 2
+#define HRTIMER_CORE_NAME 3
+
+#define MESSAGE_GPU_START 1
+#define MESSAGE_GPU_STOP 2
+
+#define MESSAGE_SCHED_SWITCH 1
+#define MESSAGE_SCHED_EXIT 2
+
+#define MAXSIZE_PACK32 5
+#define MAXSIZE_PACK64 10
+#define MAXSIZE_CORE_NAME 32
#if defined(__arm__)
#define PC_REG regs->ARM_pc
+#elif defined(__aarch64__)
+#define PC_REG regs->pc
#else
#define PC_REG regs->ip
#endif
-enum {BACKTRACE_BUF, COUNTER_BUF, SCHED_TRACE_BUF, GPU_TRACE_BUF, ANNOTATE_BUF, COUNTER2_BUF, WFI_BUF, NUM_GATOR_BUFS};
+enum {
+ SUMMARY_BUF,
+ BACKTRACE_BUF,
+ NAME_BUF,
+ COUNTER_BUF,
+ BLOCK_COUNTER_BUF,
+ ANNOTATE_BUF,
+ SCHED_TRACE_BUF,
+ GPU_TRACE_BUF,
+ IDLE_BUF,
+ NUM_GATOR_BUFS
+};
/******************************************************************************
* Globals
@@ -101,17 +125,13 @@ static unsigned long userspace_buffer_size;
static unsigned long gator_backtrace_depth;
static unsigned long gator_started;
+static uint64_t monotonic_started;
static unsigned long gator_buffer_opened;
static unsigned long gator_timer_count;
static unsigned long gator_response_type;
static DEFINE_MUTEX(start_mutex);
static DEFINE_MUTEX(gator_buffer_mutex);
-bool event_based_sampling;
-#if defined(__arm__) && (GATOR_PERF_PMU_SUPPORT)
-DEFINE_PER_CPU(struct perf_event *, pevent_ebs);
-#endif
-
static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
static struct timer_list gator_buffer_wake_up_timer;
static LIST_HEAD(gator_events);
@@ -125,10 +145,10 @@ static bool buffer_check_space(int cpu, int buftype, int bytes);
static int contiguous_space_available(int cpu, int bufytpe);
static void gator_buffer_write_packed_int(int cpu, int buftype, unsigned int x);
static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long long x);
-static void gator_buffer_write_bytes(int cpu, int buftype, char *x, int len);
-static void gator_buffer_write_string(int cpu, int buftype, char *x);
-static void gator_add_trace(int cpu, int buftype, unsigned int address);
-static void gator_add_sample(int cpu, int buftype, struct pt_regs * const regs);
+static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len);
+static void gator_buffer_write_string(int cpu, int buftype, const char *x);
+static void gator_add_trace(int cpu, unsigned long address);
+static void gator_add_sample(int cpu, struct pt_regs * const regs);
static uint64_t gator_get_time(void);
static uint32_t gator_buffer_size[NUM_GATOR_BUFS];
@@ -152,17 +172,20 @@ static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer);
#include "gator_backtrace.c"
#include "gator_annotate.c"
#include "gator_fs.c"
-#include "gator_ebs.c"
#include "gator_pack.c"
/******************************************************************************
* Misc
******************************************************************************/
-#if defined(__arm__)
+#if defined(__arm__) || defined(__aarch64__)
u32 gator_cpuid(void)
{
u32 val;
+#if !defined(__aarch64__)
asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (val));
+#else
+ asm volatile("mrs %0, midr_el1" : "=r" (val));
+#endif
return (val >> 4) & 0xfff;
}
#endif
@@ -237,7 +260,7 @@ static bool buffer_check_space(int cpu, int buftype, int bytes)
return per_cpu(buffer_space_available, cpu)[buftype];
}
-static void gator_buffer_write_bytes(int cpu, int buftype, char *x, int len)
+static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len)
{
int i;
u32 write = per_cpu(gator_buffer_write, cpu)[buftype];
@@ -252,7 +275,7 @@ static void gator_buffer_write_bytes(int cpu, int buftype, char *x, int len)
per_cpu(gator_buffer_write, cpu)[buftype] = write;
}
-static void gator_buffer_write_string(int cpu, int buftype, char *x)
+static void gator_buffer_write_string(int cpu, int buftype, const char *x)
{
int len = strlen(x);
gator_buffer_write_packed_int(cpu, buftype, len);
@@ -263,22 +286,38 @@ static void gator_buffer_header(int cpu, int buftype)
{
int frame;
- if (buftype == BACKTRACE_BUF)
+ switch (buftype) {
+ case SUMMARY_BUF:
+ frame = FRAME_SUMMARY;
+ break;
+ case BACKTRACE_BUF:
frame = FRAME_BACKTRACE;
- else if (buftype == COUNTER_BUF)
+ break;
+ case NAME_BUF:
+ frame = FRAME_NAME;
+ break;
+ case COUNTER_BUF:
frame = FRAME_COUNTER;
- else if (buftype == ANNOTATE_BUF)
+ break;
+ case BLOCK_COUNTER_BUF:
+ frame = FRAME_BLOCK_COUNTER;
+ break;
+ case ANNOTATE_BUF:
frame = FRAME_ANNOTATE;
- else if (buftype == SCHED_TRACE_BUF)
+ break;
+ case SCHED_TRACE_BUF:
frame = FRAME_SCHED_TRACE;
- else if (buftype == GPU_TRACE_BUF)
+ break;
+ case GPU_TRACE_BUF:
frame = FRAME_GPU_TRACE;
- else if (buftype == COUNTER2_BUF)
- frame = FRAME_COUNTER2;
- else if (buftype == WFI_BUF)
- frame = FRAME_WFI;
- else
+ break;
+ case IDLE_BUF:
+ frame = FRAME_IDLE;
+ break;
+ default:
frame = -1;
+ break;
+ }
if (per_cpu(gator_buffer, cpu)[buftype]) {
marshal_frame(cpu, buftype, frame);
@@ -308,10 +347,10 @@ static void buffer_check(int cpu, int buftype)
}
}
-static void gator_add_trace(int cpu, int buftype, unsigned int address)
+static void gator_add_trace(int cpu, unsigned long address)
{
off_t offset = 0;
- unsigned long cookie = get_address_cookie(cpu, buftype, current, address & ~1, &offset);
+ unsigned long cookie = get_address_cookie(cpu, current, address & ~1, &offset);
if (cookie == NO_COOKIE || cookie == INVALID_COOKIE) {
offset = address;
@@ -320,26 +359,29 @@ static void gator_add_trace(int cpu, int buftype, unsigned int address)
marshal_backtrace(offset & ~1, cookie);
}
-static void gator_add_sample(int cpu, int buftype, struct pt_regs * const regs)
+static void gator_add_sample(int cpu, struct pt_regs * const regs)
{
- int inKernel = regs ? !user_mode(regs) : 1;
- unsigned long exec_cookie = inKernel ? NO_COOKIE : get_exec_cookie(cpu, buftype, current);
+ bool inKernel;
+ unsigned long exec_cookie;
if (!regs)
return;
+ inKernel = !user_mode(regs);
+ exec_cookie = get_exec_cookie(cpu, current);
+
if (!marshal_backtrace_header(exec_cookie, current->tgid, current->pid, inKernel))
return;
if (inKernel) {
- kernel_backtrace(cpu, buftype, regs);
+ kernel_backtrace(cpu, regs);
} else {
// Cookie+PC
- gator_add_trace(cpu, buftype, PC_REG);
+ gator_add_trace(cpu, PC_REG);
// Backtrace
if (gator_backtrace_depth)
- arm_backtrace_eabi(cpu, buftype, regs, gator_backtrace_depth);
+ arm_backtrace_eabi(cpu, regs, gator_backtrace_depth);
}
marshal_backtrace_footer();
@@ -351,13 +393,20 @@ static void gator_add_sample(int cpu, int buftype, struct pt_regs * const regs)
static void gator_timer_interrupt(void)
{
struct pt_regs * const regs = get_irq_regs();
+ gator_backtrace_handler(regs);
+}
+
+void gator_backtrace_handler(struct pt_regs * const regs)
+{
int cpu = smp_processor_id();
// Output backtrace
- gator_add_sample(cpu, BACKTRACE_BUF, regs);
+ gator_add_sample(cpu, regs);
// Collect counters
- collect_counters();
+ if (!per_cpu(collecting, cpu)) {
+ collect_counters();
+ }
}
static int gator_running;
@@ -397,8 +446,6 @@ static void gator_timer_offline_dispatch(int cpu)
list_for_each_entry(gi, &gator_events, list)
if (gi->offline_dispatch)
gi->offline_dispatch(cpu);
-
- gator_event_sampling_offline_dispatch(cpu);
}
static void gator_timer_stop(void)
@@ -436,6 +483,32 @@ static void gator_timer_online(void* unused)
}
gator_hrtimer_online(cpu);
+#if defined(__arm__) || defined(__aarch64__)
+ {
+ const char * core_name = NULL;
+
+ // String lengths must be less than MAXSIZE_CORE_NAME
+ switch (gator_cpuid()) {
+ case ARM1136: core_name = "ARM1136"; break;
+ case ARM1156: core_name = "ARM1156"; break;
+ case ARM1176: core_name = "ARM1176"; break;
+ case ARM11MPCORE: core_name = "ARM11MPCore"; break;
+ case CORTEX_A5: core_name = "Cortex-A5"; break;
+ case CORTEX_A7: core_name = "Cortex-A7"; break;
+ case CORTEX_A8: core_name = "Cortex-A8"; break;
+ case CORTEX_A9: core_name = "Cortex-A9"; break;
+ case CORTEX_A15: core_name = "Cortex-A15"; break;
+ case SCORPION: core_name = "Scorpion"; break;
+ case SCORPIONMP: core_name = "ScorpionMP"; break;
+ case KRAITSIM: core_name = "KraitSIM"; break;
+ case KRAIT: core_name = "Krait"; break;
+ case AARCH64: core_name = "AArch64"; break;
+ default: core_name = "Unknown"; break;
+ }
+
+ marshal_core_name(core_name);
+ }
+#endif
}
// This function runs in interrupt context and may be running on a core other than core 'cpu'
@@ -446,8 +519,6 @@ static void gator_timer_online_dispatch(int cpu)
list_for_each_entry(gi, &gator_events, list)
if (gi->online_dispatch)
gi->online_dispatch(cpu);
-
- gator_event_sampling_online_dispatch(cpu);
}
int gator_timer_start(unsigned long sample_rate)
@@ -461,10 +532,6 @@ int gator_timer_start(unsigned long sample_rate)
gator_running = 1;
- // event based sampling trumps hr timer based sampling
- if (event_based_sampling)
- sample_rate = 0;
-
if (gator_hrtimer_init(sample_rate, gator_timer_interrupt) == -1)
return -1;
@@ -481,8 +548,9 @@ static uint64_t gator_get_time(void)
struct timespec ts;
uint64_t timestamp;
- getnstimeofday(&ts);
- timestamp = timespec_to_ns(&ts);
+ //getnstimeofday(&ts);
+ do_posix_clock_monotonic_gettime(&ts);
+ timestamp = timespec_to_ns(&ts) - monotonic_started;
return timestamp;
}
@@ -568,20 +636,15 @@ static void gator_notifier_stop(void)
******************************************************************************/
static void gator_summary(void)
{
- uint64_t timestamp, uptime = 0;
+ uint64_t timestamp;
struct timespec uptime_ts;
- void (*m2b)(struct timespec *ts);
timestamp = gator_get_time();
do_posix_clock_monotonic_gettime(&uptime_ts);
- m2b = symbol_get(monotonic_to_bootbased);
- if (m2b) {
- m2b(&uptime_ts);
- uptime = (long long)uptime_ts.tv_sec * 1000000000 + uptime_ts.tv_nsec;
- }
+ monotonic_started = timespec_to_ns(&uptime_ts);
- marshal_summary(timestamp, uptime);
+ marshal_summary(timestamp, monotonic_started);
}
int gator_events_install(struct gator_interface *interface)
@@ -656,8 +719,6 @@ static int gator_start(void)
goto power_failure;
if (gator_trace_gpu_start())
goto gpu_failure;
- if (gator_event_sampling_start())
- goto event_sampling_failure;
if (gator_timer_start(gator_timer_count))
goto timer_failure;
if (gator_notifier_start())
@@ -668,8 +729,6 @@ static int gator_start(void)
notifier_failure:
gator_timer_stop();
timer_failure:
- gator_event_sampling_stop();
-event_sampling_failure:
gator_trace_gpu_stop();
gpu_failure:
gator_trace_power_stop();
@@ -697,7 +756,6 @@ static void gator_stop(void)
gator_trace_sched_stop();
gator_trace_power_stop();
gator_trace_gpu_stop();
- gator_event_sampling_stop();
// stop all interrupt callback reads before tearing down other interfaces
gator_notifier_stop(); // should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined
@@ -720,26 +778,32 @@ static int gator_op_setup(void)
mutex_lock(&start_mutex);
+ gator_buffer_size[SUMMARY_BUF] = SUMMARY_BUFFER_SIZE;
+ gator_buffer_mask[SUMMARY_BUF] = SUMMARY_BUFFER_SIZE - 1;
+
gator_buffer_size[BACKTRACE_BUF] = BACKTRACE_BUFFER_SIZE;
gator_buffer_mask[BACKTRACE_BUF] = BACKTRACE_BUFFER_SIZE - 1;
+ gator_buffer_size[NAME_BUF] = NAME_BUFFER_SIZE;
+ gator_buffer_mask[NAME_BUF] = NAME_BUFFER_SIZE - 1;
+
gator_buffer_size[COUNTER_BUF] = COUNTER_BUFFER_SIZE;
gator_buffer_mask[COUNTER_BUF] = COUNTER_BUFFER_SIZE - 1;
+ gator_buffer_size[BLOCK_COUNTER_BUF] = BLOCK_COUNTER_BUFFER_SIZE;
+ gator_buffer_mask[BLOCK_COUNTER_BUF] = BLOCK_COUNTER_BUFFER_SIZE - 1;
+
+ gator_buffer_size[ANNOTATE_BUF] = ANNOTATE_BUFFER_SIZE;
+ gator_buffer_mask[ANNOTATE_BUF] = ANNOTATE_BUFFER_SIZE - 1;
+
gator_buffer_size[SCHED_TRACE_BUF] = SCHED_TRACE_BUFFER_SIZE;
gator_buffer_mask[SCHED_TRACE_BUF] = SCHED_TRACE_BUFFER_SIZE - 1;
gator_buffer_size[GPU_TRACE_BUF] = GPU_TRACE_BUFFER_SIZE;
gator_buffer_mask[GPU_TRACE_BUF] = GPU_TRACE_BUFFER_SIZE - 1;
- gator_buffer_size[ANNOTATE_BUF] = ANNOTATE_BUFFER_SIZE;
- gator_buffer_mask[ANNOTATE_BUF] = ANNOTATE_BUFFER_SIZE - 1;
-
- gator_buffer_size[COUNTER2_BUF] = COUNTER2_BUFFER_SIZE;
- gator_buffer_mask[COUNTER2_BUF] = COUNTER2_BUFFER_SIZE - 1;
-
- gator_buffer_size[WFI_BUF] = WFI_BUFFER_SIZE;
- gator_buffer_mask[WFI_BUF] = WFI_BUFFER_SIZE - 1;
+ gator_buffer_size[IDLE_BUF] = IDLE_BUFFER_SIZE;
+ gator_buffer_mask[IDLE_BUF] = IDLE_BUFFER_SIZE - 1;
// Initialize percpu per buffer variables
for (i = 0; i < NUM_GATOR_BUFS; i++) {
@@ -1047,8 +1111,8 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root)
gatorfs_create_file(sb, root, "enable", &enable_fops);
gatorfs_create_file(sb, root, "buffer", &gator_event_buffer_fops);
gatorfs_create_file(sb, root, "backtrace_depth", &depth_fops);
- gatorfs_create_ulong(sb, root, "cpu_cores", &gator_cpu_cores);
- gatorfs_create_ulong(sb, root, "buffer_size", &userspace_buffer_size);
+ gatorfs_create_ro_ulong(sb, root, "cpu_cores", &gator_cpu_cores);
+ gatorfs_create_ro_ulong(sb, root, "buffer_size", &userspace_buffer_size);
gatorfs_create_ulong(sb, root, "tick", &gator_timer_count);
gatorfs_create_ulong(sb, root, "response_type", &gator_response_type);
gatorfs_create_ro_ulong(sb, root, "version", &gator_protocol_version);
diff --git a/driver/gator_marshaling.c b/driver/gator_marshaling.c
index 630d142..a84b280 100644
--- a/driver/gator_marshaling.c
+++ b/driver/gator_marshaling.c
@@ -9,40 +9,44 @@
static void marshal_summary(long long timestamp, long long uptime) {
int cpu = 0;
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_SUMMARY);
- gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, timestamp);
- gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, uptime);
+ gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, timestamp);
+ gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, uptime);
+ buffer_check(cpu, SUMMARY_BUF);
}
static bool marshal_cookie_header(char* text) {
int cpu = smp_processor_id();
- return buffer_check_space(cpu, BACKTRACE_BUF, strlen(text) + 2 * MAXSIZE_PACK32);
+ return buffer_check_space(cpu, NAME_BUF, strlen(text) + 2*MAXSIZE_PACK32);
}
static void marshal_cookie(int cookie, char* text) {
int cpu = smp_processor_id();
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_COOKIE);
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie);
- gator_buffer_write_string(cpu, BACKTRACE_BUF, text);
+ // TODO(dreric01) How long can the string be?
+ if (buffer_check_space(cpu, NAME_BUF, 2*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_COOKIE);
+ gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
+ gator_buffer_write_string(cpu, NAME_BUF, text);
+ }
+ buffer_check(cpu, NAME_BUF);
}
-static void marshal_pid_name(int pid, char* name) {
+static void marshal_thread_name(int pid, char* name) {
unsigned long flags, cpu;
local_irq_save(flags);
cpu = smp_processor_id();
- if (buffer_check_space(cpu, BACKTRACE_BUF, TASK_COMM_LEN + 2 * MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_PID_NAME);
- gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, gator_get_time());
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, pid);
- gator_buffer_write_string(cpu, BACKTRACE_BUF, name);
+ if (buffer_check_space(cpu, NAME_BUF, TASK_COMM_LEN + 2*MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
+ gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_THREAD_NAME);
+ gator_buffer_write_packed_int64(cpu, NAME_BUF, gator_get_time());
+ gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
+ gator_buffer_write_string(cpu, NAME_BUF, name);
}
local_irq_restore(flags);
+ buffer_check(cpu, NAME_BUF);
}
static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel) {
int cpu = smp_processor_id();
- if (buffer_check_space(cpu, BACKTRACE_BUF, gator_backtrace_depth * 2 * MAXSIZE_PACK32)) {
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_START_BACKTRACE);
+ if (buffer_check_space(cpu, BACKTRACE_BUF, gator_backtrace_depth*2*MAXSIZE_PACK32)) {
gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, gator_get_time());
gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, exec_cookie);
gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, tgid);
@@ -57,9 +61,9 @@ static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inK
return false;
}
-static void marshal_backtrace(int address, int cookie) {
+static void marshal_backtrace(unsigned long address, int cookie) {
int cpu = smp_processor_id();
- gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, address);
+ gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, address);
gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie);
}
@@ -76,15 +80,15 @@ static bool marshal_event_header(void) {
bool retval = false;
local_irq_save(flags);
- if (buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
- gator_buffer_write_packed_int(cpu, COUNTER_BUF, 0); // key of zero indicates a timestamp
- gator_buffer_write_packed_int64(cpu, COUNTER_BUF, gator_get_time());
+ if (buffer_check_space(cpu, BLOCK_COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
+ gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0); // key of zero indicates a timestamp
+ gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, gator_get_time());
retval = true;
}
local_irq_restore(flags);
// Check and commit; commit is set to occur once buffer is 3/4 full
- buffer_check(cpu, COUNTER_BUF);
+ buffer_check(cpu, BLOCK_COUNTER_BUF);
return retval;
}
@@ -104,17 +108,17 @@ static void marshal_event(int len, int* buffer) {
// events must be written in key,value pairs
for (i = 0; i < len; i += 2) {
local_irq_save(flags);
- if (!buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK32 * 2)) {
+ if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2*MAXSIZE_PACK32)) {
local_irq_restore(flags);
break;
}
- gator_buffer_write_packed_int(cpu, COUNTER_BUF, buffer[i]);
- gator_buffer_write_packed_int(cpu, COUNTER_BUF, buffer[i + 1]);
+ gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i]);
+ gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i + 1]);
local_irq_restore(flags);
}
// Check and commit; commit is set to occur once buffer is 3/4 full
- buffer_check(cpu, COUNTER_BUF);
+ buffer_check(cpu, BLOCK_COUNTER_BUF);
}
static void marshal_event64(int len, long long* buffer64) {
@@ -132,17 +136,17 @@ static void marshal_event64(int len, long long* buffer64) {
// events must be written in key,value pairs
for (i = 0; i < len; i += 2) {
local_irq_save(flags);
- if (!buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK64 * 2)) {
+ if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2*MAXSIZE_PACK64)) {
local_irq_restore(flags);
break;
}
- gator_buffer_write_packed_int64(cpu, COUNTER_BUF, buffer64[i]);
- gator_buffer_write_packed_int64(cpu, COUNTER_BUF, buffer64[i + 1]);
+ gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i]);
+ gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i + 1]);
local_irq_restore(flags);
}
// Check and commit; commit is set to occur once buffer is 3/4 full
- buffer_check(cpu, COUNTER_BUF);
+ buffer_check(cpu, BLOCK_COUNTER_BUF);
}
#if GATOR_CPU_FREQ_SUPPORT
@@ -151,28 +155,28 @@ static void marshal_event_single(int core, int key, int value) {
local_irq_save(flags);
cpu = smp_processor_id();
- if (buffer_check_space(cpu, COUNTER2_BUF, MAXSIZE_PACK64 + MAXSIZE_PACK32 * 3)) {
- gator_buffer_write_packed_int64(cpu, COUNTER2_BUF, gator_get_time());
- gator_buffer_write_packed_int(cpu, COUNTER2_BUF, core);
- gator_buffer_write_packed_int(cpu, COUNTER2_BUF, key);
- gator_buffer_write_packed_int(cpu, COUNTER2_BUF, value);
+ if (buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK64 + 3*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int64(cpu, COUNTER_BUF, gator_get_time());
+ gator_buffer_write_packed_int(cpu, COUNTER_BUF, core);
+ gator_buffer_write_packed_int(cpu, COUNTER_BUF, key);
+ gator_buffer_write_packed_int(cpu, COUNTER_BUF, value);
}
local_irq_restore(flags);
// Check and commit; commit is set to occur once buffer is 3/4 full
- buffer_check(cpu, COUNTER2_BUF);
+ buffer_check(cpu, COUNTER_BUF);
}
#endif
-static void marshal_sched_gpu(int type, int unit, int core, int tgid, int pid) {
+static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid) {
unsigned long cpu = smp_processor_id(), flags;
if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
return;
local_irq_save(flags);
- if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
- gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, type);
+ if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_START);
gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, gator_get_time());
gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
@@ -185,18 +189,37 @@ static void marshal_sched_gpu(int type, int unit, int core, int tgid, int pid) {
buffer_check(cpu, GPU_TRACE_BUF);
}
-static void marshal_sched_trace(int type, int pid, int tgid, int cookie, int state) {
+static void marshal_sched_gpu_stop(int unit, int core) {
+ unsigned long cpu = smp_processor_id(), flags;
+
+ if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
+ return;
+
+ local_irq_save(flags);
+ if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 3*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_STOP);
+ gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, gator_get_time());
+ gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
+ gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
+ }
+ local_irq_restore(flags);
+
+ // Check and commit; commit is set to occur once buffer is 3/4 full
+ buffer_check(cpu, GPU_TRACE_BUF);
+}
+
+static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state) {
unsigned long cpu = smp_processor_id(), flags;
if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
return;
local_irq_save(flags);
- if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
- gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, type);
+ if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_SWITCH);
gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, gator_get_time());
- gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid);
+ gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie);
gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state);
}
@@ -206,21 +229,39 @@ static void marshal_sched_trace(int type, int pid, int tgid, int cookie, int sta
buffer_check(cpu, SCHED_TRACE_BUF);
}
+static void marshal_sched_trace_exit(int tgid, int pid) {
+ unsigned long cpu = smp_processor_id(), flags;
+
+ if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
+ return;
+
+ local_irq_save(flags);
+ if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 2*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_EXIT);
+ gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, gator_get_time());
+ gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
+ }
+ local_irq_restore(flags);
+
+ // Check and commit; commit is set to occur once buffer is 3/4 full
+ buffer_check(cpu, SCHED_TRACE_BUF);
+}
+
#if GATOR_CPU_FREQ_SUPPORT
-static void marshal_wfi(int core, int state) {
+static void marshal_idle(int core, int state) {
unsigned long flags, cpu;
local_irq_save(flags);
cpu = smp_processor_id();
- if (buffer_check_space(cpu, WFI_BUF, MAXSIZE_PACK64 + MAXSIZE_PACK32 * 2)) {
- gator_buffer_write_packed_int64(cpu, WFI_BUF, gator_get_time());
- gator_buffer_write_packed_int(cpu, WFI_BUF, core);
- gator_buffer_write_packed_int(cpu, WFI_BUF, state);
+ if (buffer_check_space(cpu, IDLE_BUF, MAXSIZE_PACK64 + 2*MAXSIZE_PACK32)) {
+ gator_buffer_write_packed_int(cpu, IDLE_BUF, state);
+ gator_buffer_write_packed_int64(cpu, IDLE_BUF, gator_get_time());
+ gator_buffer_write_packed_int(cpu, IDLE_BUF, core);
}
local_irq_restore(flags);
// Check and commit; commit is set to occur once buffer is 3/4 full
- buffer_check(cpu, WFI_BUF);
+ buffer_check(cpu, IDLE_BUF);
}
#endif
@@ -237,3 +278,18 @@ static void marshal_frame(int cpu, int buftype, int frame) {
gator_buffer_write_packed_int(cpu, buftype, frame);
gator_buffer_write_packed_int(cpu, buftype, cpu);
}
+
+#if defined(__arm__) || defined(__aarch64__)
+static void marshal_core_name(const char* name) {
+ int cpu = smp_processor_id();
+ unsigned long flags;
+ local_irq_save(flags);
+ if (buffer_check_space(cpu, NAME_BUF, MAXSIZE_PACK32 + MAXSIZE_CORE_NAME)) {
+ gator_buffer_write_packed_int(cpu, NAME_BUF, HRTIMER_CORE_NAME);
+ gator_buffer_write_string(cpu, NAME_BUF, name);
+ }
+ local_irq_restore(flags);
+
+ buffer_check(cpu, NAME_BUF);
+}
+#endif
diff --git a/driver/gator_pack.c b/driver/gator_pack.c
index 925469a..5ad53db 100644
--- a/driver/gator_pack.c
+++ b/driver/gator_pack.c
@@ -141,7 +141,7 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long
buffer[write6] = (x>>42) | 0x80;
buffer[write7] = (x>>49) & 0x7f;
per_cpu(gator_buffer_write, cpu)[buftype] = write8;
- } else {
+ } else if ((x & 0x8000000000000000LL) == 0) {
int write2 = (write + 2) & mask;
int write3 = (write + 3) & mask;
int write4 = (write + 4) & mask;
@@ -158,7 +158,28 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long
buffer[write5] = (x>>35) | 0x80;
buffer[write6] = (x>>42) | 0x80;
buffer[write7] = (x>>49) | 0x80;
- buffer[write8] = (x>>56) & 0xff;
+ buffer[write8] = (x>>56) & 0x7f;
per_cpu(gator_buffer_write, cpu)[buftype] = write9;
+ } else {
+ int write2 = (write + 2) & mask;
+ int write3 = (write + 3) & mask;
+ int write4 = (write + 4) & mask;
+ int write5 = (write + 5) & mask;
+ int write6 = (write + 6) & mask;
+ int write7 = (write + 7) & mask;
+ int write8 = (write + 8) & mask;
+ int write9 = (write + 9) & mask;
+ int write10 = (write + 10) & mask;
+ buffer[write0] = x | 0x80;
+ buffer[write1] = (x>>7) | 0x80;
+ buffer[write2] = (x>>14) | 0x80;
+ buffer[write3] = (x>>21) | 0x80;
+ buffer[write4] = (x>>28) | 0x80;
+ buffer[write5] = (x>>35) | 0x80;
+ buffer[write6] = (x>>42) | 0x80;
+ buffer[write7] = (x>>49) | 0x80;
+ buffer[write8] = (x>>56) | 0x80;
+ buffer[write9] = (x>>63) & 0x7f;
+ per_cpu(gator_buffer_write, cpu)[buftype] = write10;
}
}
diff --git a/driver/gator_trace_gpu.c b/driver/gator_trace_gpu.c
index d053987..0511d71 100644
--- a/driver/gator_trace_gpu.c
+++ b/driver/gator_trace_gpu.c
@@ -33,9 +33,7 @@ static int mali_timeline_trace_registered;
static int mali_job_slots_trace_registered;
static int gpu_trace_registered;
-#define GPU_START 1
-#define GPU_STOP 2
-
+#define GPU_UNIT_NONE 0
#define GPU_UNIT_VP 1
#define GPU_UNIT_FP 2
#define GPU_UNIT_CL 3
@@ -84,18 +82,18 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned
case EVENT_TYPE_START:
if (component == EVENT_CHANNEL_VP0) {
/* tgid = d0; pid = d1; */
- marshal_sched_gpu(GPU_START, GPU_UNIT_VP, 0, d0, d1);
+ marshal_sched_gpu_start(GPU_UNIT_VP, 0, d0, d1);
} else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
/* tgid = d0; pid = d1; */
- marshal_sched_gpu(GPU_START, GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, d0, d1);
+ marshal_sched_gpu_start(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, d0, d1);
}
break;
case EVENT_TYPE_STOP:
if (component == EVENT_CHANNEL_VP0) {
- marshal_sched_gpu(GPU_STOP, GPU_UNIT_VP, 0, 0, 0);
+ marshal_sched_gpu_stop(GPU_UNIT_VP, 0);
} else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
- marshal_sched_gpu(GPU_STOP, GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, 0, 0);
+ marshal_sched_gpu_stop(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0);
}
break;
@@ -118,11 +116,10 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned
#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid))
{
- unsigned int component, state, type, unit = 0;
+ unsigned int component, state, unit;
component = (event_id >> 16) & 0xFF; // component is an 8-bit field
state = (event_id >> 24) & 0xF; // state is a 4-bit field
- type = (state == EVENT_TYPE_START) ? GPU_START : GPU_STOP;
switch (component)
{
@@ -135,23 +132,37 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne
case 2:
unit = GPU_UNIT_CL;
break;
+ default:
+ unit = GPU_UNIT_NONE;
}
- if (unit != 0)
+ if (unit != GPU_UNIT_NONE)
{
- marshal_sched_gpu(type, unit, 0, tgid, (pid != 0 ? pid : tgid));
+ switch(state) {
+ case EVENT_TYPE_START:
+ marshal_sched_gpu_start(unit, 0, tgid, (pid != 0 ? pid : tgid));
+ break;
+ case EVENT_TYPE_STOP:
+ marshal_sched_gpu_stop(unit, 0);
+ break;
+ default:
+ /*
+ * Some jobs can be soft-stopped, so ensure that this terminates the activity trace.
+ */
+ marshal_sched_gpu_stop(unit, 0);
+ }
}
}
#endif
GATOR_DEFINE_PROBE(gpu_activity_start, TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p))
{
- marshal_sched_gpu(GPU_START, gpu_unit, gpu_core, (int)p->tgid, (int)p->pid);
+ marshal_sched_gpu_start(gpu_unit, gpu_core, (int)p->tgid, (int)p->pid);
}
GATOR_DEFINE_PROBE(gpu_activity_stop, TP_PROTO(int gpu_unit, int gpu_core))
{
- marshal_sched_gpu(GPU_STOP, gpu_unit, gpu_core, 0, 0);
+ marshal_sched_gpu_stop(gpu_unit, gpu_core);
}
int gator_trace_gpu_start(void)
diff --git a/driver/gator_trace_power.c b/driver/gator_trace_power.c
index ca89b19..b1687e1 100644
--- a/driver/gator_trace_power.c
+++ b/driver/gator_trace_power.c
@@ -9,6 +9,7 @@
#include <linux/cpufreq.h>
#include <trace/events/power.h>
+#include <asm/mach-types.h>
// cpu_frequency and cpu_idle trace points were introduced in Linux kernel v2.6.38
// the now deprecated power_frequency trace point was available prior to 2.6.38, but only for x86
@@ -52,32 +53,29 @@ GATOR_DEFINE_PROBE(cpu_frequency, TP_PROTO(unsigned int frequency, unsigned int
marshal_event_single(cpu, power_cpu_key[POWER_CPU_FREQ], frequency * 1000);
}
-#define WFI_ACTIVE_THRESHOLD 2 // may vary on platform/OS
-#define WFI_EXIT 0
+#define WFI_EXIT 2
#define WFI_ENTER 1
GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu))
{
- // the streamline engine treats all counter values as unsigned
- if (state & 0x80000000) {
- state = 0;
- }
-
if (state == per_cpu(idle_prev_state, cpu)) {
return;
}
- if (state < WFI_ACTIVE_THRESHOLD && per_cpu(idle_prev_state, cpu) >= WFI_ACTIVE_THRESHOLD) {
- // transition from wfi to non-wfi
- marshal_wfi(cpu, WFI_EXIT);
- } else if (state >= WFI_ACTIVE_THRESHOLD && per_cpu(idle_prev_state, cpu) < WFI_ACTIVE_THRESHOLD) {
- // transition from non-wfi to wfi
- marshal_wfi(cpu, WFI_ENTER);
+ if (!machine_is_omap3_beagle()) {
+ if (state == PWR_EVENT_EXIT) {
+ // transition from wfi to non-wfi
+ marshal_idle(cpu, WFI_EXIT);
+ } else {
+ // transition from non-wfi to wfi
+ marshal_idle(cpu, WFI_ENTER);
+ }
}
per_cpu(idle_prev_state, cpu) = state;
if (power_cpu_enabled[POWER_CPU_IDLE]) {
- marshal_event_single(cpu, power_cpu_key[POWER_CPU_IDLE], state);
+ // Increment state so that no negative numbers are sent
+ marshal_event_single(cpu, power_cpu_key[POWER_CPU_IDLE], state + 1);
}
}
diff --git a/driver/gator_trace_sched.c b/driver/gator_trace_sched.c
index 08b0270..9ddb822 100644
--- a/driver/gator_trace_sched.c
+++ b/driver/gator_trace_sched.c
@@ -17,6 +17,7 @@
#define TASK_MAX_COLLISIONS 2
static DEFINE_PER_CPU(uint64_t *, taskname_keys);
+static DEFINE_PER_CPU(int, collecting);
enum {
STATE_WAIT_ON_OTHER = 0,
@@ -59,7 +60,7 @@ void emit_pid_name(struct task_struct* task)
strcat(taskcomm, "...");
}
- marshal_pid_name(task->pid, taskcomm);
+ marshal_thread_name(task->pid, taskcomm);
}
}
@@ -87,12 +88,12 @@ static void probe_sched_write(int type, struct task_struct* task, struct task_st
{
int cookie = 0, state = 0;
int cpu = smp_processor_id();
- int pid = task->pid;
int tgid = task->tgid;
+ int pid = task->pid;
if (type == SCHED_SWITCH) {
// do as much work as possible before disabling interrupts
- cookie = get_exec_cookie(cpu, BACKTRACE_BUF, task);
+ cookie = get_exec_cookie(cpu, task);
emit_pid_name(task);
if (old_task->state == TASK_RUNNING) {
state = STATE_CONTENTION;
@@ -106,18 +107,24 @@ static void probe_sched_write(int type, struct task_struct* task, struct task_st
state = STATE_WAIT_ON_OTHER;
}
+ per_cpu(collecting, cpu) = 1;
collect_counters();
+ per_cpu(collecting, cpu) = 0;
}
// marshal_sched_trace() disables interrupts as the free may trigger while switch is writing to the buffer; disabling preemption is not sufficient
// is disable interrupts necessary now that exit is used instead of free?
- marshal_sched_trace(type, pid, tgid, cookie, state);
+ if (type == SCHED_SWITCH) {
+ marshal_sched_trace_switch(tgid, pid, cookie, state);
+ } else {
+ marshal_sched_trace_exit(tgid, pid);
+ }
}
// special case used during a suspend of the system
static void trace_sched_insert_idle(void)
{
- marshal_sched_trace(SCHED_SWITCH, 0, 0, 0, 0);
+ marshal_sched_trace_switch(0, 0, 0, 0);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
diff --git a/driver/mali_t6xx.mk b/driver/mali_t6xx.mk
index 2e51670..2cc6411 100644
--- a/driver/mali_t6xx.mk
+++ b/driver/mali_t6xx.mk
@@ -11,13 +11,14 @@ EXTRA_CFLAGS += -DMALI_USE_UMP=1 \
KBASE_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase
OSK_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase/osk
-UMP_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/ump
+UMP_DIR = $(DDK_DIR)/kernel/include/linux
# Include directories in the DDK
EXTRA_CFLAGS += -I$(DDK_DIR) \
-I$(KBASE_DIR)/.. \
-I$(OSK_DIR)/.. \
-I$(UMP_DIR)/.. \
+ -I$(DDK_DIR)/kernel/include \
-I$(KBASE_DIR)/osk/src/linux/include \
-I$(KBASE_DIR)/platform_dummy \
-I$(KBASE_DIR)/src