diff mbox

[i-g-t] igt/gem_ctx_isolation: Test INSTPM back to gen6

Message ID 20180529111605.18246-1-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Wilson May 29, 2018, 11:16 a.m. UTC
Lionel pointed out that INSTPM was context saved, at least from gen6,
not from gen9. The only caveat is that INSTPM is a masked register (the
upper 16bits are a write-enable mask, the lower 16bits the value to
change) and also contains a read-only counter bit (which counts flushes,
and so flip flops between batches). Being a non-privileged register that
userspace wants to manipulate, it is writable and readable from a
userspace batch, so we can test whether or not a write from one context
is visible from a second.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
---
 tests/gem_ctx_isolation.c | 51 ++++++++++++++++++++++++++++++++-------
 1 file changed, 42 insertions(+), 9 deletions(-)

Comments

Lionel Landwerlin May 29, 2018, 2:06 p.m. UTC | #1
On 29/05/18 12:16, Chris Wilson wrote:
> Lionel pointed out that INSTPM was context saved, at least from gen6,
> not from gen9. The only caveat is that INSTPM is a masked register (the
> upper 16bits are a write-enable mask, the lower 16bits the value to
> change) and also contains a read-only counter bit (which counts flushes,
> and so flip flops between batches). Being a non-privileged register that
> userspace wants to manipulate, it is writable and readable from a
> userspace batch, so we can test whether or not a write from one context
> is visible from a second.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>

> ---
>   tests/gem_ctx_isolation.c | 51 ++++++++++++++++++++++++++++++++-------
>   1 file changed, 42 insertions(+), 9 deletions(-)
>
> diff --git a/tests/gem_ctx_isolation.c b/tests/gem_ctx_isolation.c
> index 4968e3678..fe7d3490c 100644
> --- a/tests/gem_ctx_isolation.c
> +++ b/tests/gem_ctx_isolation.c
> @@ -63,10 +63,12 @@ static const struct named_register {
>   	unsigned int engine_mask;
>   	uint32_t offset;
>   	uint32_t count;
> +	uint32_t ignore_bits;
> +	bool masked;
>   } nonpriv_registers[] = {
>   	{ "NOPID", NOCTX, RCS0, 0x2094 },
>   	{ "MI_PREDICATE_RESULT_2", NOCTX, RCS0, 0x23bc },
> -	{ "INSTPM", GEN9, RCS0, 0x20c0 },
> +	{ "INSTPM", GEN6, RCS0, 0x20c0, 1, BIT(8) /* ro counter */, true },
>   	{ "IA_VERTICES_COUNT", GEN4, RCS0, 0x2310, 2 },
>   	{ "IA_PRIMITIVES_COUNT", GEN4, RCS0, 0x2318, 2 },
>   	{ "VS_INVOCATION_COUNT", GEN4, RCS0, 0x2320, 2 },
> @@ -167,6 +169,17 @@ static const char *register_name(uint32_t offset, char *buf, size_t len)
>   	return "unknown";
>   }
>   
> +static const struct named_register *lookup_register(uint32_t offset)
> +{
> +	for (const struct named_register *r = nonpriv_registers; r->name; r++) {
> +		unsigned int width = r->count ? 4*r->count : 4;
> +		if (offset >= r->offset && offset < r->offset + width)
> +			return r;
> +	}
> +
> +	return NULL;
> +}
> +
>   static bool ignore_register(uint32_t offset)
>   {
>   	for (const struct named_register *r = ignore_registers; r->name; r++) {
> @@ -283,7 +296,10 @@ static void write_regs(int fd,
>   		     count--; offset += 4) {
>   			*b++ = 0x22 << 23 | 1; /* LRI */
>   			*b++ = offset;
> -			*b++ = value;
> +			if (r->masked)
> +				*b++ = value | 0xffffu << 16;
> +			else
> +				*b++ = value;
>   		}
>   	}
>   	*b++ = MI_BATCH_BUFFER_END;
> @@ -424,14 +440,31 @@ static void compare_regs(int fd, uint32_t A, uint32_t B, const char *who)
>   
>   	num_errors = 0;
>   	for (unsigned int n = 0; n < NUM_REGS; n++) {
> +		const struct named_register *r;
>   		uint32_t offset = n * sizeof(uint32_t);
> -		if (a[n] != b[n] && !ignore_register(offset)) {
> -			igt_warn("Register 0x%04x (%s): A=%08x B=%08x\n",
> -				 offset,
> -				 register_name(offset, buf, sizeof(buf)),
> -				 a[n], b[n]);
> -			num_errors++;
> -		}
> +		uint32_t mask;
> +
> +		if (a[n] == b[n])
> +			continue;
> +
> +		if (ignore_register(offset))
> +			continue;
> +
> +		mask = ~0u;
> +		r = lookup_register(offset);
> +		if (r && r->masked)
> +			mask >>= 16;
> +		if (r && r->ignore_bits)
> +			mask &= ~r->ignore_bits;
> +
> +		if ((a[n] & mask) == (b[n] & mask))
> +			continue;
> +
> +		igt_warn("Register 0x%04x (%s): A=%08x B=%08x\n",
> +			 offset,
> +			 register_name(offset, buf, sizeof(buf)),
> +			 a[n] & mask, b[n] & mask);
> +		num_errors++;
>   	}
>   	munmap(b, regs_size);
>   	munmap(a, regs_size);
diff mbox

Patch

diff --git a/tests/gem_ctx_isolation.c b/tests/gem_ctx_isolation.c
index 4968e3678..fe7d3490c 100644
--- a/tests/gem_ctx_isolation.c
+++ b/tests/gem_ctx_isolation.c
@@ -63,10 +63,12 @@  static const struct named_register {
 	unsigned int engine_mask;
 	uint32_t offset;
 	uint32_t count;
+	uint32_t ignore_bits;
+	bool masked;
 } nonpriv_registers[] = {
 	{ "NOPID", NOCTX, RCS0, 0x2094 },
 	{ "MI_PREDICATE_RESULT_2", NOCTX, RCS0, 0x23bc },
-	{ "INSTPM", GEN9, RCS0, 0x20c0 },
+	{ "INSTPM", GEN6, RCS0, 0x20c0, 1, BIT(8) /* ro counter */, true },
 	{ "IA_VERTICES_COUNT", GEN4, RCS0, 0x2310, 2 },
 	{ "IA_PRIMITIVES_COUNT", GEN4, RCS0, 0x2318, 2 },
 	{ "VS_INVOCATION_COUNT", GEN4, RCS0, 0x2320, 2 },
@@ -167,6 +169,17 @@  static const char *register_name(uint32_t offset, char *buf, size_t len)
 	return "unknown";
 }
 
+static const struct named_register *lookup_register(uint32_t offset)
+{
+	for (const struct named_register *r = nonpriv_registers; r->name; r++) {
+		unsigned int width = r->count ? 4*r->count : 4;
+		if (offset >= r->offset && offset < r->offset + width)
+			return r;
+	}
+
+	return NULL;
+}
+
 static bool ignore_register(uint32_t offset)
 {
 	for (const struct named_register *r = ignore_registers; r->name; r++) {
@@ -283,7 +296,10 @@  static void write_regs(int fd,
 		     count--; offset += 4) {
 			*b++ = 0x22 << 23 | 1; /* LRI */
 			*b++ = offset;
-			*b++ = value;
+			if (r->masked)
+				*b++ = value | 0xffffu << 16;
+			else
+				*b++ = value;
 		}
 	}
 	*b++ = MI_BATCH_BUFFER_END;
@@ -424,14 +440,31 @@  static void compare_regs(int fd, uint32_t A, uint32_t B, const char *who)
 
 	num_errors = 0;
 	for (unsigned int n = 0; n < NUM_REGS; n++) {
+		const struct named_register *r;
 		uint32_t offset = n * sizeof(uint32_t);
-		if (a[n] != b[n] && !ignore_register(offset)) {
-			igt_warn("Register 0x%04x (%s): A=%08x B=%08x\n",
-				 offset,
-				 register_name(offset, buf, sizeof(buf)),
-				 a[n], b[n]);
-			num_errors++;
-		}
+		uint32_t mask;
+
+		if (a[n] == b[n])
+			continue;
+
+		if (ignore_register(offset))
+			continue;
+
+		mask = ~0u;
+		r = lookup_register(offset);
+		if (r && r->masked)
+			mask >>= 16;
+		if (r && r->ignore_bits)
+			mask &= ~r->ignore_bits;
+
+		if ((a[n] & mask) == (b[n] & mask))
+			continue;
+
+		igt_warn("Register 0x%04x (%s): A=%08x B=%08x\n",
+			 offset,
+			 register_name(offset, buf, sizeof(buf)),
+			 a[n] & mask, b[n] & mask);
+		num_errors++;
 	}
 	munmap(b, regs_size);
 	munmap(a, regs_size);