[igt-dev] [Intel-gfx] [PATCH i-g-t 3/8] tests/i915/gem_exec_capture: Make the error decode a common helper

Matthew Brost matthew.brost at intel.com
Fri Oct 29 02:34:46 UTC 2021


On Thu, Oct 21, 2021 at 04:40:39PM -0700, John.C.Harrison at Intel.com wrote:
> From: John Harrison <John.C.Harrison at Intel.com>
> 
> The decode of the error capture contents was happening in two
> different sub-tests with two very different pieces of code. One being
> much more extensive than the other (actually decodes and verifies the
> contents of the captured buffers rather than just the address). So,
> move the code into a common helper function and use that in both
> places.
> 
> Signed-off-by: John Harrison <John.C.Harrison at Intel.com>

Reviewed-by: Matthew Brost <matthew.brost at intel.com>

> ---
>  tests/i915/gem_exec_capture.c | 344 +++++++++++++++++-----------------
>  1 file changed, 170 insertions(+), 174 deletions(-)
> 
> diff --git a/tests/i915/gem_exec_capture.c b/tests/i915/gem_exec_capture.c
> index 47ca64dd6..c85c198f7 100644
> --- a/tests/i915/gem_exec_capture.c
> +++ b/tests/i915/gem_exec_capture.c
> @@ -33,32 +33,175 @@
>  
>  IGT_TEST_DESCRIPTION("Check that we capture the user specified objects on a hang");
>  
> -static void check_error_state(int dir, struct drm_i915_gem_exec_object2 *obj)
> +struct offset {
> +	uint64_t addr;
> +	unsigned long idx;
> +	bool found;
> +};
> +
> +static unsigned long zlib_inflate(uint32_t **ptr, unsigned long 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 = 128*4096;
> +
> +	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 unsigned long
> +ascii85_decode(char *in, uint32_t **out, bool inflate, char **end)
> +{
> +	unsigned long 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;
> +	}
> +	*end = in;
> +
> +	if (!inflate)
> +		return len;
> +
> +	return zlib_inflate(out, len);
> +}
> +
> +static int check_error_state(int dir, struct offset *obj_offsets, int obj_count,
> +			     uint64_t obj_size, bool incremental)
>  {
>  	char *error, *str;
> -	bool found = false;
> +	int blobs = 0;
>  
>  	error = igt_sysfs_get(dir, "error");
>  	igt_sysfs_set(dir, "error", "Begone!");
> -
>  	igt_assert(error);
>  	igt_debug("%s\n", error);
>  
>  	/* render ring --- user = 0x00000000 ffffd000 */
> -	for (str = error; (str = strstr(str, "--- user = ")); str++) {
> +	for (str = error; (str = strstr(str, "--- user = ")); ) {
> +		uint32_t *data = NULL;
>  		uint64_t addr;
> -		uint32_t hi, lo;
> +		unsigned long i, sz;
> +		unsigned long start;
> +		unsigned long end;
>  
> -		igt_assert(sscanf(str, "--- user = 0x%x %x", &hi, &lo) == 2);
> -		addr = hi;
> +		if (strncmp(str, "--- user = 0x", 13))
> +			break;
> +		str += 13;
> +		addr = strtoul(str, &str, 16);
>  		addr <<= 32;
> -		addr |= lo;
> -		igt_assert_eq_u64(addr, obj->offset);
> -		found = true;
> +		addr |= strtoul(str + 1, &str, 16);
> +		igt_assert(*str++ == '\n');
> +
> +		start = 0;
> +		end = obj_count;
> +		while (end > start) {
> +			i = (end - start) / 2 + start;
> +			if (obj_offsets[i].addr < addr)
> +				start = i + 1;
> +			else if (obj_offsets[i].addr > addr)
> +				end = i;
> +			else
> +				break;
> +		}
> +		igt_assert(obj_offsets[i].addr == addr);
> +		igt_assert(!obj_offsets[i].found);
> +		obj_offsets[i].found = true;
> +		igt_debug("offset:%"PRIx64", index:%ld\n",
> +			  addr, obj_offsets[i].idx);
> +
> +		/* gtt_page_sizes = 0x00010000 */
> +		if (strncmp(str, "gtt_page_sizes = 0x", 19) == 0) {
> +			str += 19 + 8;
> +			igt_assert(*str++ == '\n');
> +		}
> +
> +		if (!(*str == ':' || *str == '~'))
> +			continue;
> +
> +		igt_debug("blob:%.64s\n", str);
> +		sz = ascii85_decode(str + 1, &data, *str == ':', &str);
> +
> +		igt_assert_eq(4 * sz, obj_size);
> +		igt_assert(*str++ == '\n');
> +		str = strchr(str, '-');
> +
> +		if (incremental) {
> +			uint32_t expect;
> +
> +			expect = obj_offsets[i].idx * obj_size;
> +			for (i = 0; i < sz; i++)
> +				igt_assert_eq(data[i], expect++);
> +		} else {
> +			for (i = 0; i < sz; i++)
> +				igt_assert_eq(data[i], 0);
> +		}
> +
> +		blobs++;
> +		free(data);
>  	}
>  
>  	free(error);
> -	igt_assert(found);
> +	return blobs;
>  }
>  
>  static void __capture1(int fd, int dir, uint64_t ahnd, const intel_ctx_t *ctx,
> @@ -73,6 +216,7 @@ static void __capture1(int fd, int dir, uint64_t ahnd, const intel_ctx_t *ctx,
>  	struct drm_i915_gem_relocation_entry reloc[2];
>  	struct drm_i915_gem_execbuffer2 execbuf;
>  	uint32_t *batch, *seqno;
> +	struct offset offset;
>  	int i;
>  
>  	memset(obj, 0, sizeof(obj));
> @@ -168,7 +312,10 @@ static void __capture1(int fd, int dir, uint64_t ahnd, const intel_ctx_t *ctx,
>  
>  	/* Check that only the buffer we marked is reported in the error */
>  	igt_force_gpu_reset(fd);
> -	check_error_state(dir, &obj[CAPTURE]);
> +	memset(&offset, 0, sizeof(offset));
> +	offset.addr = obj[CAPTURE].offset;
> +	igt_assert_eq(check_error_state(dir, &offset, 1, target_size, false), 1);
> +	igt_assert(offset.found);
>  
>  	gem_sync(fd, obj[BATCH].handle);
>  
> @@ -183,11 +330,12 @@ static void capture(int fd, int dir, const intel_ctx_t *ctx, unsigned ring)
>  {
>  	uint32_t handle;
>  	uint64_t ahnd;
> +	int obj_size = 4096;
>  
> -	handle = gem_create(fd, 4096);
> +	handle = gem_create(fd, obj_size);
>  	ahnd = get_reloc_ahnd(fd, ctx->id);
>  
> -	__capture1(fd, dir, ahnd, ctx, ring, handle, 4096);
> +	__capture1(fd, dir, ahnd, ctx, ring, handle, obj_size);
>  
>  	gem_close(fd, handle);
>  	put_ahnd(ahnd);
> @@ -206,10 +354,8 @@ static int cmp(const void *A, const void *B)
>  	return 0;
>  }
>  
> -static struct offset {
> -	uint64_t addr;
> -	unsigned long idx;
> -} *__captureN(int fd, int dir, uint64_t ahnd, unsigned ring,
> +static struct offset *
> +__captureN(int fd, int dir, uint64_t ahnd, unsigned ring,
>  	      unsigned int size, int count,
>  	      unsigned int flags)
>  #define INCREMENTAL 0x1
> @@ -357,98 +503,11 @@ static struct offset {
>  	return offsets;
>  }
>  
> -static unsigned long zlib_inflate(uint32_t **ptr, unsigned long 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 = 128*4096;
> -
> -	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 unsigned long
> -ascii85_decode(char *in, uint32_t **out, bool inflate, char **end)
> -{
> -	unsigned long 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;
> -	}
> -	*end = in;
> -
> -	if (!inflate)
> -		return len;
> -
> -	return zlib_inflate(out, len);
> -}
> -
>  static void many(int fd, int dir, uint64_t size, unsigned int flags)
>  {
>  	uint64_t ram, gtt, ahnd;
>  	unsigned long count, blobs;
>  	struct offset *offsets;
> -	char *error, *str;
>  
>  	gtt = gem_aperture_size(fd) / size;
>  	ram = (intel_get_avail_ram_mb() << 20) / size;
> @@ -463,75 +522,10 @@ static void many(int fd, int dir, uint64_t size, unsigned int flags)
>  
>  	offsets = __captureN(fd, dir, ahnd, 0, size, count, flags);
>  
> -	error = igt_sysfs_get(dir, "error");
> -	igt_sysfs_set(dir, "error", "Begone!");
> -	igt_assert(error);
> -
> -	blobs = 0;
> -	/* render ring --- user = 0x00000000 ffffd000 */
> -	str = strstr(error, "--- user = ");
> -	while (str) {
> -		uint32_t *data = NULL;
> -		unsigned long i, sz;
> -		uint64_t addr;
> -
> -		if (strncmp(str, "--- user = 0x", 13))
> -			break;
> -
> -		str += 13;
> -		addr = strtoul(str, &str, 16);
> -		addr <<= 32;
> -		addr |= strtoul(str + 1, &str, 16);
> -		igt_assert(*str++ == '\n');
> -
> -		/* gtt_page_sizes = 0x00010000 */
> -		if (strncmp(str, "gtt_page_sizes = 0x", 19) == 0) {
> -			str += 19 + 8;
> -			igt_assert(*str++ == '\n');
> -		}
> -
> -		if (!(*str == ':' || *str == '~'))
> -			continue;
> -
> -		igt_debug("blob:%.64s\n", str);
> -		sz = ascii85_decode(str + 1, &data, *str == ':', &str);
> -		igt_assert_eq(4 * sz, size);
> -		igt_assert(*str++ == '\n');
> -		str = strchr(str, '-');
> -
> -		if (flags & INCREMENTAL) {
> -			unsigned long start = 0;
> -			unsigned long end = count;
> -			uint32_t expect;
> -
> -			while (end > start) {
> -				i = (end - start) / 2 + start;
> -				if (offsets[i].addr < addr)
> -					start = i + 1;
> -				else if (offsets[i].addr > addr)
> -					end = i;
> -				else
> -					break;
> -			}
> -			igt_assert(offsets[i].addr == addr);
> -			igt_debug("offset:%"PRIx64", index:%ld\n",
> -				  addr, offsets[i].idx);
> -
> -			expect = offsets[i].idx * size;
> -			for (i = 0; i < sz; i++)
> -				igt_assert_eq(data[i], expect++);
> -		} else {
> -			for (i = 0; i < sz; i++)
> -				igt_assert_eq(data[i], 0);
> -		}
> -
> -		blobs++;
> -		free(data);
> -	}
> +	blobs = check_error_state(dir, offsets, count, size, !!(flags & INCREMENTAL));
>  	igt_info("Captured %lu %"PRId64"-blobs out of a total of %lu\n",
>  		 blobs, size >> 12, count);
>  
> -	free(error);
>  	free(offsets);
>  	put_ahnd(ahnd);
>  }
> @@ -625,12 +619,14 @@ static void userptr(int fd, int dir)
>  	uint32_t handle;
>  	uint64_t ahnd;
>  	void *ptr;
> +	int obj_size = 4096;
>  
> -	igt_assert(posix_memalign(&ptr, 4096, 4096) == 0);
> -	igt_require(__gem_userptr(fd, ptr, 4096, 0, 0, &handle) == 0);
> +	igt_assert(posix_memalign(&ptr, obj_size, obj_size) == 0);
> +	memset(ptr, 0, obj_size);
> +	igt_require(__gem_userptr(fd, ptr, obj_size, 0, 0, &handle) == 0);
>  	ahnd = get_reloc_ahnd(fd, ctx->id);
>  
> -	__capture1(fd, dir, ahnd, intel_ctx_0(fd), 0, handle, 4096);
> +	__capture1(fd, dir, ahnd, intel_ctx_0(fd), 0, handle, obj_size);
>  
>  	gem_close(fd, handle);
>  	put_ahnd(ahnd);
> -- 
> 2.25.1
> 


More information about the igt-dev mailing list