[Intel-gfx] [PATCH i-g-t 7/7] test/i915: Add i915_rc6_ctx_corruption

2019-11-13 Thread Mika Kuoppala
From: Imre Deak 

Add a test to exercise the kernel's mechanism to detection of RC6
context corruptions, take the necessary action in response (disable
RC6 and runtime PM) and recover when possible (after system
suspend/resume).

v2:
- Skip test on non-existing engines.
- Fix for old kernels where the command parser returned EINVAL
  instead of EACCESS for a banned privilidged command.

Signed-off-by: Imre Deak 
---
 tests/Makefile.sources   |   3 +
 tests/i915/i915_rc6_ctx_corruption.c | 196 +++
 tests/meson.build|   1 +
 3 files changed, 200 insertions(+)
 create mode 100644 tests/i915/i915_rc6_ctx_corruption.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 75c79edb..c0f401c7 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -529,6 +529,9 @@ i915_pm_sseu_SOURCES = i915/i915_pm_sseu.c
 TESTS_progs += i915_query
 i915_query_SOURCES = i915/i915_query.c
 
+TESTS_progs += i915_rc6_ctx_corruption
+i915_rc6_ctx_corruption_SOURCES = i915/i915_rc6_ctx_corruption.c
+
 TESTS_progs += i915_selftest
 i915_selftest_SOURCES = i915/i915_selftest.c
 
diff --git a/tests/i915/i915_rc6_ctx_corruption.c 
b/tests/i915/i915_rc6_ctx_corruption.c
new file mode 100644
index ..a3326307
--- /dev/null
+++ b/tests/i915/i915_rc6_ctx_corruption.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright © 2019 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.
+ */
+
+#include 
+
+#include "igt.h"
+#include "igt_gt.h"
+#include "igt_device.h"
+
+#define CTX_INFO_REG   0xA300
+
+static int drm_fd;
+static struct pci_device *pci_dev;
+static uint32_t devid;
+
+static int read_reg_on_engine(const struct intel_execution_engine2 *engine,
+ int reg_address, uint32_t *reg_val)
+{
+   const bool r64b = intel_gen(devid) >= 8;
+   struct drm_i915_gem_exec_object2 obj[2];
+   struct drm_i915_gem_relocation_entry reloc[1];
+   struct drm_i915_gem_execbuffer2 execbuf;
+   uint32_t *batch;
+   uint32_t *dst_buf;
+   int ret;
+   int i;
+
+   memset(obj, 0, sizeof(obj));
+   obj[0].handle = gem_create(drm_fd, 4096);
+   obj[1].handle = gem_create(drm_fd, 4096);
+   obj[1].relocs_ptr = to_user_pointer(reloc);
+   obj[1].relocation_count = 1;
+
+   batch = gem_mmap__cpu(drm_fd, obj[1].handle, 0, 4096, PROT_WRITE);
+   gem_set_domain(drm_fd, obj[1].handle,
+  I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+
+   i = 0;
+   batch[i++] = 0x24 << 23 | (1 + r64b); /* SRM */
+   batch[i++] = reg_address;
+   reloc[0].target_handle = obj[0].handle;
+   reloc[0].presumed_offset = obj[0].offset;
+   reloc[0].offset = i * sizeof(uint32_t);
+   reloc[0].delta = 0;
+   reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;
+   reloc[0].write_domain = I915_GEM_DOMAIN_RENDER;
+   batch[i++] = reloc[0].delta;
+   if (r64b)
+   batch[i++] = 0;
+
+   batch[i++] = MI_BATCH_BUFFER_END;
+   munmap(batch, 4096);
+
+   memset(&execbuf, 0, sizeof(execbuf));
+   execbuf.buffers_ptr = to_user_pointer(obj);
+   execbuf.buffer_count = 2;
+   execbuf.flags = engine->flags;
+
+   ret = __gem_execbuf(drm_fd, &execbuf);
+   gem_close(drm_fd, obj[1].handle);
+
+   if (ret)
+   goto err;
+
+   if (reg_val) {
+   dst_buf = gem_mmap__cpu(drm_fd, obj[0].handle, 0, 4096,
+   PROT_READ);
+   gem_set_domain(drm_fd, obj[0].handle, I915_GEM_DOMAIN_CPU, 0);
+
+   *reg_val = dst_buf[0];
+   munmap(dst_buf, 4096);
+   }
+
+err:
+   gem_close(drm_fd, obj[0].handle);
+
+   return ret;
+}
+
+static bool need_ctx_corruption_wa(void)
+{
+   return IS_BROADWELL(devid) || intel_gen(devid) == 9;
+}
+
+static void test_read_on_engine(co

Re: [Intel-gfx] [PATCH i-g-t 7/7] test/i915: Add i915_rc6_ctx_corruption

2019-11-13 Thread Chris Wilson
Quoting Mika Kuoppala (2019-11-13 15:49:13)
> From: Imre Deak 
> 
> Add a test to exercise the kernel's mechanism to detection of RC6
> context corruptions, take the necessary action in response (disable
> RC6 and runtime PM) and recover when possible (after system
> suspend/resume).
> 
> v2:
> - Skip test on non-existing engines.
> - Fix for old kernels where the command parser returned EINVAL
>   instead of EACCESS for a banned privilidged command.
> 
> Signed-off-by: Imre Deak 
> ---
>  tests/Makefile.sources   |   3 +
>  tests/i915/i915_rc6_ctx_corruption.c | 196 +++
>  tests/meson.build|   1 +
>  3 files changed, 200 insertions(+)
>  create mode 100644 tests/i915/i915_rc6_ctx_corruption.c
> 
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index 75c79edb..c0f401c7 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -529,6 +529,9 @@ i915_pm_sseu_SOURCES = i915/i915_pm_sseu.c
>  TESTS_progs += i915_query
>  i915_query_SOURCES = i915/i915_query.c
>  
> +TESTS_progs += i915_rc6_ctx_corruption
> +i915_rc6_ctx_corruption_SOURCES = i915/i915_rc6_ctx_corruption.c
> +
>  TESTS_progs += i915_selftest
>  i915_selftest_SOURCES = i915/i915_selftest.c
>  
> diff --git a/tests/i915/i915_rc6_ctx_corruption.c 
> b/tests/i915/i915_rc6_ctx_corruption.c
> new file mode 100644
> index ..a3326307
> --- /dev/null
> +++ b/tests/i915/i915_rc6_ctx_corruption.c
> @@ -0,0 +1,196 @@
> +/*
> + * Copyright © 2019 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.
> + */
> +
> +#include 
> +
> +#include "igt.h"
> +#include "igt_gt.h"
> +#include "igt_device.h"
> +
> +#define CTX_INFO_REG   0xA300
> +
> +static int drm_fd;
> +static struct pci_device *pci_dev;
> +static uint32_t devid;
> +
> +static int read_reg_on_engine(const struct intel_execution_engine2 *engine,
> + int reg_address, uint32_t *reg_val)
> +{
> +   const bool r64b = intel_gen(devid) >= 8;
> +   struct drm_i915_gem_exec_object2 obj[2];
> +   struct drm_i915_gem_relocation_entry reloc[1];
> +   struct drm_i915_gem_execbuffer2 execbuf;
> +   uint32_t *batch;
> +   uint32_t *dst_buf;
> +   int ret;
> +   int i;
> +
> +   memset(obj, 0, sizeof(obj));
> +   obj[0].handle = gem_create(drm_fd, 4096);
> +   obj[1].handle = gem_create(drm_fd, 4096);
> +   obj[1].relocs_ptr = to_user_pointer(reloc);
> +   obj[1].relocation_count = 1;
> +
> +   batch = gem_mmap__cpu(drm_fd, obj[1].handle, 0, 4096, PROT_WRITE);
> +   gem_set_domain(drm_fd, obj[1].handle,
> +  I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
> +
> +   i = 0;
> +   batch[i++] = 0x24 << 23 | (1 + r64b); /* SRM */
> +   batch[i++] = reg_address;
> +   reloc[0].target_handle = obj[0].handle;
> +   reloc[0].presumed_offset = obj[0].offset;
> +   reloc[0].offset = i * sizeof(uint32_t);
> +   reloc[0].delta = 0;
> +   reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;
> +   reloc[0].write_domain = I915_GEM_DOMAIN_RENDER;
> +   batch[i++] = reloc[0].delta;
> +   if (r64b)
> +   batch[i++] = 0;
> +
> +   batch[i++] = MI_BATCH_BUFFER_END;
> +   munmap(batch, 4096);
> +
> +   memset(&execbuf, 0, sizeof(execbuf));
> +   execbuf.buffers_ptr = to_user_pointer(obj);
> +   execbuf.buffer_count = 2;
> +   execbuf.flags = engine->flags;
> +
> +   ret = __gem_execbuf(drm_fd, &execbuf);
> +   gem_close(drm_fd, obj[1].handle);
> +
> +   if (ret)
> +   goto err;
> +
> +   if (reg_val) {
> +   dst_buf = gem_mmap__cpu(drm_fd, obj[0].handle, 0, 4096,
> +   PROT_READ);
> +   gem_set_domain(drm_fd, obj[0].handle, I915_GEM_DOMAIN_CPU, 0);
> +
> +