diff options
-rw-r--r-- | src/gallium/drivers/panfrost/meson.build | 1 | ||||
-rw-r--r-- | src/gallium/drivers/panfrost/pan_screen.c | 7 | ||||
-rw-r--r-- | src/gallium/drivers/panfrost/pan_screen.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/panfrost/pan_trace.c | 146 | ||||
-rw-r--r-- | src/gallium/drivers/panfrost/pan_trace.h | 33 |
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 |