Add intel_error_decode.
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 12 Feb 2010 13:28:40 +0000 (13:28 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 12 Feb 2010 13:35:14 +0000 (13:35 +0000)
A simple variant of intel_gpu_dump that explicitly handles parsing of
i915_error_state.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
.gitignore
tools/Makefile.am
tools/intel_decode_file.c [deleted file]
tools/intel_error_decode.c [new file with mode: 0644]

index b176a3d..a4b2fa9 100644 (file)
@@ -47,7 +47,7 @@ tests/gem_bad_address
 tests/gem_bad_batch
 tests/gem_bad_blit
 tests/gem_hang
-tools/intel_decode
+tools/intel_error_decode
 tools/intel_gpu_dump
 tools/intel_gpu_time
 tools/intel_gpu_top
index eb2b1fc..d6d63ab 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS = \
        intel_audio_dump \
-       intel_decode \
+       intel_error_decode \
        intel_gpu_dump \
        intel_gpu_top \
        intel_gpu_time \
@@ -16,8 +16,8 @@ intel_gpu_dump_SOURCES = \
        intel_decode.c \
        intel_decode.h
 
-intel_decode_SOURCES = \
-       intel_decode_file.c \
+intel_error_decode_SOURCES = \
+       intel_error_decode.c \
        intel_decode.c \
        intel_decode.h
 
diff --git a/tools/intel_decode_file.c b/tools/intel_decode_file.c
deleted file mode 100644 (file)
index 9331e4e..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "intel_decode.h"
-
-static void
-read_data_text (const char *filename, uint32_t devid, int is_batch)
-{
-    FILE *file;
-    uint32_t *data = NULL;
-    int data_size = 0, count = 0, line_number = 0, matched;
-    char *line = NULL;
-    size_t line_size;
-    uint32_t offset, value;
-    uint32_t gtt_offset = 0, new_gtt_offset;
-    char *buffer_type = is_batch ? "batchbuffer" : "ringbuffer";
-
-    file = fopen (filename, "r");
-    if (file == NULL) {
-       fprintf (stderr, "Failed to open %s: %s\n",
-                filename, strerror (errno));
-       exit (1);
-    }
-
-    while (getline (&line, &line_size, file) > 0) {
-       line_number++;
-
-       matched = sscanf (line, "--- gtt_offset = 0x%08x\n", &new_gtt_offset);
-       if (matched == 1) {
-           if (count) {
-               printf("%s at 0x%08x:\n", buffer_type, gtt_offset);
-               intel_decode (data, count, gtt_offset, devid, 0);
-               count = 0;
-           }
-           gtt_offset = new_gtt_offset;
-           continue;
-       }
-
-       matched = sscanf (line, "%08x : %08x", &offset, &value);
-       if (matched !=2 ) {
-           fprintf (stderr, "Warning: Ignoring unrecognized line at %s:%d:\n%s",
-                    filename, line_number, line);
-           continue;
-       }
-
-       count++;
-
-       if (count > data_size) {
-           data_size = data_size ? data_size * 2 : 1024;
-           data = realloc (data, data_size * sizeof (uint32_t));
-           if (data == NULL) {
-               fprintf (stderr, "Out of memory.\n");
-               exit (1);
-           }
-       }
-
-       data[count-1] = value;
-    }
-
-    if (count) {
-       printf("%s at 0x%08x:\n", buffer_type, gtt_offset);
-       intel_decode (data, count, gtt_offset, devid, 0);
-    }
-
-    free (data);
-    free (line);
-
-    fclose (file);
-}
-
-static int
-read_data_file (const char *filename, uint32_t devid, int is_batch)
-{
-    FILE *file;
-    uint32_t *buf;
-    uint32_t len = 4096;
-    int count = 0;
-
-    buf = malloc (sizeof (uint32_t) * len);
-    if (buf == NULL) {
-       fprintf (stderr, "Failed to allocate memory for %s.\n",
-                filename);
-       return 0;
-    }
-
-    file = fopen (filename, "rb");
-    if (file == NULL) {
-       free (buf);
-       fprintf (stderr, "Failed to open %s: %s\n",
-                filename, strerror (errno));
-       return 0;
-    }
-
-    do {
-       uint32_t *newbuf;
-
-       count += fread (buf + count, sizeof (uint32_t), len - count, file);
-       if (count < len)
-           break;
-
-       len *= 2;
-       newbuf = realloc (buf, len * sizeof (uint32_t));
-       if (newbuf == NULL) {
-           free (buf);
-           fclose (file);
-           fprintf (stderr, "Failed to allocate memory for %s.\n",
-                    filename);
-           return 0;
-       }
-
-       buf = newbuf;
-    } while (1);
-
-    fclose (file);
-
-    intel_decode (buf, count, 0x0, devid, 1);
-    intel_decode_context_reset ();
-    free (buf);
-
-    return 1;
-}
-
-int
-main (int argc, char **argv)
-{
-       int is_text = 0;
-       int i;
-       uint32_t devid =0x27A2;
-
-       for (i = 1; i < argc; i++) {
-               if (strncmp (argv[i], "--pci-id=", 9) == 0) {
-                       devid = atoi (argv[i] + 9);
-                       continue;
-               }
-
-               if (is_text)
-                       read_data_text (argv[i], devid, 1);
-               else
-                       read_data_file (argv[i], devid, 1);
-       }
-
-       return 0;
-}
diff --git a/tools/intel_error_decode.c b/tools/intel_error_decode.c
new file mode 100644 (file)
index 0000000..4dc3d43
--- /dev/null
@@ -0,0 +1,235 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2007 Intel Corporation
+ * Copyright © 2009 Intel Corporation
+ * Copyright © 2010 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.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *    Carl Worth <cworth@cworth.org>
+ *    Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+/** @file intel_decode.c
+ * This file contains code to print out batchbuffer contents in a
+ * human-readable format.
+ *
+ * The current version only supports i915 packets, and only pretty-prints a
+ * subset of them.  The intention is for it to make just a best attempt to
+ * decode, but never crash in the process.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <err.h>
+
+#include "intel_decode.h"
+#include "intel_chipset.h"
+#include "intel_gpu_tools.h"
+#include "instdone.h"
+
+static void
+print_instdone (unsigned int instdone, unsigned int instdone1)
+{
+    int i;
+
+    for (i = 0; i < num_instdone_bits; i++) {
+       int busy = 0;
+
+       if (instdone_bits[i].reg == INST_DONE_1) {
+           if (!(instdone1 & instdone_bits[i].bit))
+               busy = 1;
+       } else {
+           if (!(instdone & instdone_bits[i].bit))
+               busy = 1;
+       }
+
+       if (busy)
+           printf("    busy: %s\n", instdone_bits[i].name);
+    }
+}
+
+static void
+read_data_file (const char * filename)
+{
+    FILE *file;
+    int devid = PCI_CHIP_I855_GM;
+    uint32_t *data = NULL;
+    int data_size = 0, count = 0, line_number = 0, matched;
+    char *line = NULL;
+    size_t line_size;
+    uint32_t offset, value;
+    uint32_t gtt_offset = 0, new_gtt_offset;
+    char *buffer_type[2] = {  "ringbuffer", "batchbuffer" };
+    int is_batch = 1;
+
+    file = fopen (filename, "r");
+    if (file == NULL) {
+       fprintf (stderr, "Failed to open %s: %s\n",
+                filename, strerror (errno));
+       exit (1);
+    }
+
+    while (getline (&line, &line_size, file) > 0) {
+       line_number++;
+
+       matched = sscanf (line, "--- gtt_offset = 0x%08x\n", &new_gtt_offset);
+       if (matched == 1) {
+           if (count) {
+               printf("%s at 0x%08x:\n", buffer_type[is_batch], gtt_offset);
+               intel_decode (data, count, gtt_offset, devid, 0);
+               count = 0;
+           }
+           gtt_offset = new_gtt_offset;
+           is_batch = 1;
+           continue;
+       }
+
+       matched = sscanf (line, "--- ringbuffer = 0x%08x\n", &new_gtt_offset);
+       if (matched == 1) {
+           if (count) {
+               printf("%s at 0x%08x:\n", buffer_type[is_batch], gtt_offset);
+               intel_decode (data, count, gtt_offset, devid, 0);
+               count = 0;
+           }
+           gtt_offset = new_gtt_offset;
+           is_batch = 0;
+           continue;
+       }
+
+       matched = sscanf (line, "%08x : %08x", &offset, &value);
+       if (matched != 2) {
+           unsigned int reg;
+
+           printf("%s", line);
+
+           matched = sscanf (line, "PCI ID: 0x%04x\n", &reg);
+           if (matched)
+                   devid = reg;
+
+           matched = sscanf (line, "  ACTHD: 0x%08x\n", &reg);
+           if (matched)
+                   intel_decode_context_set_head_tail(reg, 0xffffffff);
+
+           matched = sscanf (line, "  INSTDONE: 0x%08x\n", &reg);
+           if (matched)
+               print_instdone (reg, -1);
+
+           matched = sscanf (line, "  INSTDONE1: 0x%08x\n", &reg);
+           if (matched)
+               print_instdone (-1, reg);
+
+           continue;
+       }
+
+       count++;
+
+       if (count > data_size) {
+           data_size = data_size ? data_size * 2 : 1024;
+           data = realloc (data, data_size * sizeof (uint32_t));
+           if (data == NULL) {
+               fprintf (stderr, "Out of memory.\n");
+               exit (1);
+           }
+       }
+
+       data[count-1] = value;
+    }
+
+    if (count) {
+       printf("%s at 0x%08x:\n", buffer_type[is_batch], gtt_offset);
+       intel_decode (data, count, gtt_offset, devid, 0);
+    }
+
+    free (data);
+    free (line);
+
+    fclose (file);
+}
+
+int
+main (int argc, char *argv[])
+{
+    const char *path;
+    struct stat st;
+    int err;
+
+    if (argc > 2) {
+       fprintf (stderr,
+                "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
+                "Usage:\n"
+                "\t%s [<file>]\n"
+                "\n"
+                "With no arguments, debugfs-dri-directory is probed for in "
+                "/debug and \n"
+                "/sys/kernel/debug.  Otherwise, it may be "
+                "specified.  If a file is given,\n"
+                "it is parsed as an GPU dump in the format of "
+                "/debug/dri/0/i915_error_state.\n",
+                argv[0]);
+       return 1;
+    }
+
+    init_instdone_definitions();
+
+    if (argc == 1) {
+       path = "/debug/dri/0";
+       err = stat (path, &st);
+       if (err != 0) {
+           path = "/sys/kernel/debug/dri/0";
+           err = stat (path, &st);
+           if (err != 0) {
+               errx(1,
+                    "Couldn't find i915 debugfs directory.\n\n"
+                    "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
+                    "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
+           }
+       }
+    } else {
+       path = argv[1];
+       err = stat (path, &st);
+       if (err != 0) {
+           fprintf (stderr, "Error opening %s: %s\n",
+                    path, strerror (errno));
+           exit (1);
+       }
+    }
+
+    if (S_ISDIR (st.st_mode)) {
+       char *filename;
+
+       asprintf (&filename, "%s/i915_error_state", path);
+       read_data_file (filename);
+       free (filename);
+    } else {
+       read_data_file (path);
+    }
+
+    return 0;
+}