summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/panfrost/meson.build1
-rw-r--r--src/gallium/drivers/panfrost/pan_screen.c7
-rw-r--r--src/gallium/drivers/panfrost/pan_screen.h1
-rw-r--r--src/gallium/drivers/panfrost/pan_trace.c146
-rw-r--r--src/gallium/drivers/panfrost/pan_trace.h33
5 files changed, 188 insertions, 0 deletions
diff --git a/src/gallium/drivers/panfrost/meson.build b/src/gallium/drivers/panfrost/meson.build
index 9c36daeb0f2..73fcca3e648 100644
--- a/src/gallium/drivers/panfrost/meson.build
+++ b/src/gallium/drivers/panfrost/meson.build
@@ -31,6 +31,7 @@ files_panfrost = files(
'midgard/disassemble.c',
'pan_context.c',
+ 'pan_trace.c',
'pan_drm.c',
'pan_allocate.c',
'pan_assemble.c',
diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c
index 0995d2f3142..f61758d1bb9 100644
--- a/src/gallium/drivers/panfrost/pan_screen.c
+++ b/src/gallium/drivers/panfrost/pan_screen.c
@@ -551,6 +551,13 @@ panfrost_create_screen(int fd, struct renderonly *ro, bool is_drm)
#endif
}
+ /* Enable pantrace iff asked for in the environment */
+ const char *pantrace_base = getenv("PANTRACE_BASE");
+
+ if (pantrace_base) {
+ pantrace_initialize(pantrace_base);
+ }
+
#ifdef DUMP_PERFORMANCE_COUNTERS
screen->driver->allocate_slab(screen, &screen->perf_counters, 64, true, 0, 0, 0);
screen->driver->enable_counters(screen);
diff --git a/src/gallium/drivers/panfrost/pan_screen.h b/src/gallium/drivers/panfrost/pan_screen.h
index 646923c9864..4ff690de658 100644
--- a/src/gallium/drivers/panfrost/pan_screen.h
+++ b/src/gallium/drivers/panfrost/pan_screen.h
@@ -35,6 +35,7 @@
#include <panfrost-misc.h>
#include "pan_allocate.h"
+#include "pan_trace.h"
struct panfrost_context;
struct panfrost_resource;
diff --git a/src/gallium/drivers/panfrost/pan_trace.c b/src/gallium/drivers/panfrost/pan_trace.c
new file mode 100644
index 00000000000..205a822dee9
--- /dev/null
+++ b/src/gallium/drivers/panfrost/pan_trace.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2019 Alyssa Rosenzweig
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <panfrost-job.h>
+#include "pan_trace.h"
+#include "util/list.h"
+
+/* The pandecode utility is capable of parsing a command stream trace and
+ * disassembling any referenced shaders. Traces themselves are glorified memory
+ * dumps, a directory consisting of .bin's for each memory segment, and a
+ * simple plain-text description of the interesting kernel activity.
+ * Historically, these dumps have been produced via panwrap, an LD_PRELOAD shim
+ * sitting between the driver and the kernel. However, for modern Panfrost, we
+ * can just produce the dumps ourselves, which is rather less fragile. This
+ * file (pantrace) implements this functionality. */
+
+static FILE *pan_control_log;
+static const char *pan_control_base;
+
+/* Represent the abstraction for a single mmap chunk */
+
+static unsigned pantrace_memory_count = 0;
+
+struct pantrace_memory {
+ struct list_head node;
+
+ mali_ptr gpu;
+ void *cpu;
+ size_t sz;
+ char *full_filename;
+};
+
+static struct pantrace_memory mmaps;
+
+void
+pantrace_initialize(const char *base)
+{
+ /* Open the control.log */
+ char fn[128];
+ snprintf(fn, 128, "%s/control.log", base);
+ pan_control_log = fopen(fn, "w+");
+ assert(pan_control_log);
+
+ /* Save the base for later */
+ pan_control_base = base;
+
+ /* Initialize the mmap list */
+ list_inithead(&mmaps.node);
+}
+
+static bool
+pantrace_is_initialized(void)
+{
+ return pan_control_log && pan_control_base;
+}
+
+/* Traces a submitted job with a given job chain, core requirements, and
+ * platform */
+
+void
+pantrace_submit_job(mali_ptr jc, unsigned core_req, unsigned is_bifrost)
+{
+ if (!pantrace_is_initialized())
+ return;
+
+ fprintf(pan_control_log, "JS %" PRIx64 " %x %x\n",
+ jc, core_req, is_bifrost);
+ fflush(pan_control_log);
+}
+
+/* Dumps a given mapped memory buffer with the given label. If no label
+ * is given (label == NULL), one is created */
+
+void
+pantrace_mmap(mali_ptr gpu, void *cpu, size_t sz, char *label)
+{
+ if (!pantrace_is_initialized())
+ return;
+
+ char *filename = NULL;
+ char *full_filename = NULL;
+
+ /* Create a filename based on the label or count */
+
+ if (label) {
+ asprintf(&filename, "%s.bin", label);
+ } else {
+ asprintf(&filename, "memory_%d.bin", pantrace_memory_count++);
+ }
+
+ /* Emit an mmap for it */
+ fprintf(pan_control_log, "MMAP %" PRIx64 " %s\n", gpu, filename);
+ fflush(pan_control_log);
+
+ /* Dump the memory itself */
+ asprintf(&full_filename, "%s/%s", pan_control_base, filename);
+ free(filename);
+
+ struct pantrace_memory *mem = malloc(sizeof(*mem));
+ list_inithead(&mem->node);
+ mem->gpu = gpu;
+ mem->cpu = cpu;
+ mem->sz = sz;
+ mem->full_filename = full_filename;
+ list_add(&mem->node, &mmaps.node);
+}
+
+/* Dump all memory at once, once everything has been written */
+
+void
+pantrace_dump_memory(void)
+{
+ if (!pantrace_is_initialized())
+ return;
+
+ list_for_each_entry(struct pantrace_memory, pos, &mmaps.node, node) {
+ /* Save the mapping */
+ FILE *fp = fopen(pos->full_filename, "wb");
+ fwrite(pos->cpu, 1, pos->sz, fp);
+ fclose(fp);
+ }
+}
diff --git a/src/gallium/drivers/panfrost/pan_trace.h b/src/gallium/drivers/panfrost/pan_trace.h
new file mode 100644
index 00000000000..9b0b79aa23e
--- /dev/null
+++ b/src/gallium/drivers/panfrost/pan_trace.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 Alyssa Rosenzweig
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __PAN_TRACE_H__
+#define __PAN_TRACE_H__
+
+void pantrace_initialize(const char *base);
+void pantrace_submit_job(mali_ptr jc, unsigned core_req, unsigned is_bifrost);
+void pantrace_mmap(mali_ptr gpu, void *cpu, size_t sz, char *label);
+void pantrace_dump_memory(void);
+
+#endif