[Intel-gfx] [PATCH] intel_error_decode: Inflate compressed error state

Chris Wilson chris at chris-wilson.co.uk
Fri Oct 31 12:33:25 CET 2014


Recent kernels compress the active objects using zlib + ascii85
encoding. This adapts the tool to decompress those inplace.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 tools/Makefile.sources     |  1 +
 tools/intel_error_decode.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+)

diff --git a/tools/Makefile.sources b/tools/Makefile.sources
index 48b89db..94c070c 100644
--- a/tools/Makefile.sources
+++ b/tools/Makefile.sources
@@ -42,6 +42,7 @@ intel_dump_decode_SOURCES = 	\
 
 intel_error_decode_SOURCES =	\
 	intel_error_decode.c
+intel_error_decode_LDFLAGS = -lz
 
 intel_bios_reader_SOURCES =	\
 	intel_bios_reader.c	\
diff --git a/tools/intel_error_decode.c b/tools/intel_error_decode.c
index 14589a3..b443e35 100644
--- a/tools/intel_error_decode.c
+++ b/tools/intel_error_decode.c
@@ -51,6 +51,7 @@
 #include <err.h>
 #include <assert.h>
 #include <intel_bufmgr.h>
+#include <zlib.h>
 
 #include "intel_chipset.h"
 #include "intel_io.h"
@@ -334,6 +335,87 @@ static void decode(struct drm_intel_decode *ctx, bool is_batch,
 	*count = 0;
 }
 
+static int zlib_inflate(uint32_t **ptr, int len)
+{
+	struct z_stream_s zstream;
+	void *out;
+
+	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(128*4096); /* approximate obj size */
+	zstream.next_out = out;
+	zstream.avail_out = 40*len;
+
+	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)
+{
+	int len = 0, size = 1024;
+
+	*out = realloc(*out, sizeof(uint32_t)*size);
+	if (*out == NULL)
+		return 0;
+
+	while (*in != '\n') {
+		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;
+	}
+
+	return zlib_inflate(out, len);
+}
+
 static void
 read_data_file(FILE *file)
 {
@@ -387,6 +469,17 @@ read_data_file(FILE *file)
 			}
 		}
 
+		if (line[0] == ':') {
+			count = ascii85_decode(line+1, &data);
+			if (count == 0) {
+				fprintf(stderr, "ASCII85 decode failed.\n");
+				exit(1);
+			}
+			decode(decode_ctx, is_batch, ring_name, gtt_offset,
+			       data, &count);
+			continue;
+		}
+
 		matched = sscanf(line, "%08x : %08x", &offset, &value);
 		if (matched != 2) {
 			unsigned int reg;
-- 
2.1.1




More information about the Intel-gfx mailing list