On Wed, Jul 18, 2018 at 7:33 AM Lionel Landwerlin < lionel.g.landwer...@intel.com> wrote:
> Awesome tool! And not even too much code! > > Reviewed-by: Lionel Landwerlin <lionel.g.landwer...@intel.com> > Thanks! > In the interest of consistency and because this is an installable > binary, I would rename it. > Now for the hard part : intel_error2aub ? > Done. > - > Lionel > > On 18/07/18 00:05, Jason Ekstrand wrote: > > --- > > src/intel/tools/error2aub.c | 332 ++++++++++++++++++++++++++++++++++++ > > src/intel/tools/meson.build | 11 ++ > > 2 files changed, 343 insertions(+) > > create mode 100644 src/intel/tools/error2aub.c > > > > diff --git a/src/intel/tools/error2aub.c b/src/intel/tools/error2aub.c > > new file mode 100644 > > index 00000000000..ece41d93e6c > > --- /dev/null > > +++ b/src/intel/tools/error2aub.c > > @@ -0,0 +1,332 @@ > > +/* > > + * Copyright © 2007-2017 Intel Corporation > > + * > > + * 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 <assert.h> > > +#include <getopt.h> > > +#include <inttypes.h> > > +#include <signal.h> > > +#include <stdio.h> > > +#include <stdlib.h> > > +#include <string.h> > > +#include <zlib.h> > > + > > +#include "aub_write.h" > > +#include "i915_drm.h" > > +#include "intel_aub.h" > > + > > +static void __attribute__ ((format(__printf__, 2, 3))) > > +fail_if(int cond, const char *format, ...) > > +{ > > + va_list args; > > + > > + if (!cond) > > + return; > > + > > + va_start(args, format); > > + vfprintf(stderr, format, args); > > + va_end(args); > > + > > + raise(SIGTRAP); > > +} > > + > > +#define fail(...) fail_if(true, __VA_ARGS__) > > + > > +static int zlib_inflate(uint32_t **ptr, int len) > > +{ > > + struct z_stream_s zstream; > > + void *out; > > + const uint32_t out_size = 128*4096; /* approximate obj size */ > > + > > + memset(&zstream, 0, sizeof(zstream)); > > + > > + zstream.next_in = (unsigned char *)*ptr; > > + zstream.avail_in = 4*len; > > + > > + if (inflateInit(&zstream) != Z_OK) > > + return 0; > > + > > + out = malloc(out_size); > > + zstream.next_out = out; > > + zstream.avail_out = out_size; > > + > > + do { > > + switch (inflate(&zstream, Z_SYNC_FLUSH)) { > > + case Z_STREAM_END: > > + goto end; > > + case Z_OK: > > + break; > > + default: > > + inflateEnd(&zstream); > > + return 0; > > + } > > + > > + if (zstream.avail_out) > > + break; > > + > > + out = realloc(out, 2*zstream.total_out); > > + if (out == NULL) { > > + inflateEnd(&zstream); > > + return 0; > > + } > > + > > + zstream.next_out = (unsigned char *)out + zstream.total_out; > > + zstream.avail_out = zstream.total_out; > > + } while (1); > > + end: > > + inflateEnd(&zstream); > > + free(*ptr); > > + *ptr = out; > > + return zstream.total_out / 4; > > +} > > + > > +static int ascii85_decode(const char *in, uint32_t **out, bool inflate) > > +{ > > + int len = 0, size = 1024; > > + > > + *out = realloc(*out, sizeof(uint32_t)*size); > > + if (*out == NULL) > > + return 0; > > + > > + while (*in >= '!' && *in <= 'z') { > > + uint32_t v = 0; > > + > > + if (len == size) { > > + size *= 2; > > + *out = realloc(*out, sizeof(uint32_t)*size); > > + if (*out == NULL) > > + return 0; > > + } > > + > > + if (*in == 'z') { > > + in++; > > + } else { > > + v += in[0] - 33; v *= 85; > > + v += in[1] - 33; v *= 85; > > + v += in[2] - 33; v *= 85; > > + v += in[3] - 33; v *= 85; > > + v += in[4] - 33; > > + in += 5; > > + } > > + (*out)[len++] = v; > > + } > > + > > + if (!inflate) > > + return len; > > + > > + return zlib_inflate(out, len); > > +} > > + > > +static void > > +print_help(const char *progname, FILE *file) > > +{ > > + fprintf(file, > > + "Usage: %s [OPTION]... [FILE]\n" > > + "Convert an Intel GPU i915 error state to an aub file.\n" > > + " -h, --help display this help and exit\n" > > + " -o, --output=FILE the output aub file (default > FILE.aub)\n", > > + progname); > > +} > > + > > +int > > +main(int argc, char *argv[]) > > +{ > > + int i, c; > > + bool help = false; > > + char *out_filename = NULL, *in_filename = NULL; > > + const struct option aubinator_opts[] = { > > + { "help", no_argument, NULL, 'h' }, > > + { "output", required_argument, NULL, 'o' }, > > + { NULL, 0, NULL, 0 } > > + }; > > + > > + i = 0; > > + while ((c = getopt_long(argc, argv, "ho:", aubinator_opts, &i)) != > -1) { > > + switch (c) { > > + case 'h': > > + help = true; > > + break; > > + case 'o': > > + out_filename = strdup(optarg); > > + break; > > + default: > > + break; > > + } > > + } > > + > > + if (optind < argc) > > + in_filename = argv[optind++]; > > + > > + if (help || argc == 1 || !in_filename) { > > + print_help(argv[0], stderr); > > + return in_filename ? EXIT_SUCCESS : EXIT_FAILURE; > > + } > > + > > + if (out_filename == NULL) { > > + int out_filename_size = strlen(in_filename) + 5; > > + out_filename = malloc(out_filename_size); > > + snprintf(out_filename, out_filename_size, "%s.aub", in_filename); > > + } > > + > > + FILE *err_file = fopen(in_filename, "r"); > > + fail_if(!err_file, "Failed to open error file \"%s\": %m\n", > in_filename); > > + > > + FILE *aub_file = fopen(out_filename, "w"); > > + fail_if(!aub_file, "Failed to open aub file \"%s\": %m\n", > in_filename); > > + > > + struct aub_file aub = {}; > > + > > + uint32_t active_ring = 0; > > + int num_ring_bos = 0; > > + > > + uint64_t batch_addr = 0; > > + > > + enum bo_type { > > + BO_TYPE_UNKNOWN = 0, > > + BO_TYPE_BATCH, > > + BO_TYPE_USER, > > + } bo_type; > > + uint64_t bo_addr; > > + > > + char *line = NULL; > > + size_t line_size; > > + while (getline(&line, &line_size, err_file) > 0) { > > + const char *pci_id_start = strstr(line, "PCI ID"); > > + if (pci_id_start) { > > + int pci_id; > > + int matched = sscanf(line, "PCI ID: 0x%04x\n", &pci_id); > > + fail_if(!matched, "Invalid error state file!\n"); > > + > > + aub_file_init(&aub, aub_file, pci_id); > > + fail_if(!aub_use_execlists(&aub), > > + "%s currently only works on gen8+\n", argv[0]); > > + > > + aub_write_header(&aub, "error state"); > > + continue; > > + } > > + > > + const char *active_start = "Active ("; > > + if (strncmp(line, active_start, strlen(active_start)) == 0) { > > + fail_if(active_ring != 0, "TODO: Handle multiple active > rings\n"); > > + > > + char *ring = line + strlen(active_start); > > + > > + const struct { > > + const char *match; > > + uint32_t ring; > > + } rings[] = { > > + { "rcs", I915_EXEC_RENDER }, > > + { "vcs", I915_EXEC_VEBOX }, > > + { "bcs", I915_EXEC_BLT }, > > + { NULL, BO_TYPE_UNKNOWN }, > > + }, *r; > > + > > + for (r = rings; r->match; r++) { > > + if (strncasecmp(ring, r->match, strlen(r->match)) == 0) { > > + active_ring = r->ring; > > + break; > > + } > > + } > > + > > + char *count = strchr(ring, '['); > > + fail_if(!count || sscanf(count, "[%d]:", &num_ring_bos) < 1, > > + "Failed to parse BO table header\n"); > > + continue; > > + } > > + > > + if (num_ring_bos > 0) { > > + unsigned hi, lo, size; > > + if (sscanf(line, " %x_%x %d", &hi, &lo, &size) == 3) { > > + assert(aub_use_execlists(&aub)); > > + aub_map_ppgtt(&aub, ((uint64_t)hi) << 32 | lo, size); > > + num_ring_bos--; > > + } else { > > + fail("Not enough BO entries in the active table\n"); > > + } > > + continue; > > + } > > + > > + if (line[0] == ':' || line[0] == '~') { > > + if (bo_type == BO_TYPE_UNKNOWN) > > + continue; > > + > > + uint32_t *data = NULL; > > + int count = ascii85_decode(line+1, &data, line[0] == ':'); > > + fail_if(count == 0, "ASCII85 decode failed.\n"); > > + uint64_t bo_size = count * 4; > > + > > + if (bo_type == BO_TYPE_BATCH) { > > + aub_write_trace_block(&aub, AUB_TRACE_TYPE_BATCH, > > + data, bo_size, bo_addr); > > + batch_addr = bo_addr; > > + } else { > > + assert(bo_type == BO_TYPE_USER); > > + aub_write_trace_block(&aub, AUB_TRACE_TYPE_NOTYPE, > > + data, bo_size, bo_addr); > > + } > > + > > + continue; > > + } > > + > > + char *dashes = strstr(line, "---"); > > + if (dashes) { > > + dashes += 4; > > + > > + const struct { > > + const char *match; > > + enum bo_type type; > > + } bo_types[] = { > > + { "gtt_offset", BO_TYPE_BATCH }, > > + { "user", BO_TYPE_USER }, > > + { NULL, BO_TYPE_UNKNOWN }, > > + }, *b; > > + > > + bo_type = BO_TYPE_UNKNOWN; > > + for (b = bo_types; b->match; b++) { > > + if (strncasecmp(dashes, b->match, strlen(b->match)) == 0) { > > + bo_type = b->type; > > + break; > > + } > > + } > > + > > + if (bo_type != BO_TYPE_UNKNOWN) { > > + uint32_t hi, lo; > > + dashes = strchr(dashes, '='); > > + if (dashes && sscanf(dashes, "= 0x%08x %08x\n", &hi, &lo) > == 2) { > > + bo_addr = ((uint64_t) hi) << 32 | lo; > > + } else { > > + fail("User BO does not have an address\n"); > > + } > > + } > > + continue; > > + } > > + } > > + > > + fail_if(!batch_addr, "Failed to find batch buffer.\n"); > > + > > + aub_write_exec(&aub, batch_addr, aub_gtt_size(&aub), > I915_EXEC_RENDER); > > + > > + return EXIT_SUCCESS; > > +} > > + > > +/* vim: set ts=8 sw=8 tw=0 cino=:0,(0 noet :*/ > > diff --git a/src/intel/tools/meson.build b/src/intel/tools/meson.build > > index b4c23e01db2..1a6f8b2eebf 100644 > > --- a/src/intel/tools/meson.build > > +++ b/src/intel/tools/meson.build > > @@ -40,6 +40,17 @@ aubinator_error_decode = executable( > > install : with_tools.contains('intel'), > > ) > > > > +error2aub = executable( > > + 'error2aub', > > + files('aub_write.h', 'aub_write.c', 'error2aub.c'), > > + dependencies : [dep_zlib, dep_dl, dep_thread, dep_m], > > + include_directories : [inc_common, inc_intel, inc_drm_uapi], > > + link_with : [libintel_dev], > > + c_args : [c_vis_args, no_override_init_args], > > + build_by_default : with_tools.contains('intel'), > > + install : with_tools.contains('intel'), > > +) > > + > > if with_tools.contains('intel') > > sanitize_data = configuration_data() > > sanitize_data.set( > > >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev