diff mbox

intel_error_decode: Inflate compressed error state

Message ID 1414755205-18888-1-git-send-email-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Wilson Oct. 31, 2014, 11:33 a.m. UTC
Recent kernels compress the active objects using zlib + ascii85
encoding. This adapts the tool to decompress those inplace.

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

Comments

Rodrigo Vivi Nov. 24, 2014, 11:13 p.m. UTC | #1
both deflate and inflate was listed to -collector but got a hard conflict.
If it is still needed please rebase it over -nightly

On Fri, Oct 31, 2014 at 4:33 AM, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> Recent kernels compress the active objects using zlib + ascii85
> encoding. This adapts the tool to decompress those inplace.
>
> Signed-off-by: Chris Wilson <chris@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
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff mbox

Patch

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;