summaryrefslogtreecommitdiff
path: root/tests/i915/gem_mmap_gtt.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2019-01-17 23:57:00 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2019-01-24 15:35:25 +0000
commitdcdf4b04e16312f8f52ad389388d834f9d74b8f0 (patch)
tree02abc4eed68ade2178d099e2d75e213b00f9d13f /tests/i915/gem_mmap_gtt.c
parent82789816ace346f3bd917f44d3cc7cfd85add319 (diff)
i915/gem_mmap_gtt: Reset faster and longer to catch fencing errors
Performing a GPU reset clobbers the fence registers, affecting which addresses the tiled GTT mmap access. If the driver does not take precautions across a GPU reset, a client may read the wrong values (but only within their own buffer as the fence will only be degraded to I915_TILING_NONE, reducing the access area). However, as this requires performing a read using the indirect GTT at exactly the same time as the reset occurs, it can be quite difficult to catch, so repeat the test many times and across all cores simultaneously. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Diffstat (limited to 'tests/i915/gem_mmap_gtt.c')
-rw-r--r--tests/i915/gem_mmap_gtt.c99
1 files changed, 68 insertions, 31 deletions
diff --git a/tests/i915/gem_mmap_gtt.c b/tests/i915/gem_mmap_gtt.c
index f6353555..f9d811ad 100644
--- a/tests/i915/gem_mmap_gtt.c
+++ b/tests/i915/gem_mmap_gtt.c
@@ -38,6 +38,7 @@
#include "drm.h"
#include "igt.h"
+#include "igt_sysfs.h"
#include "igt_x86.h"
#ifndef PAGE_SIZE
@@ -375,50 +376,86 @@ test_clflush(int fd)
static void
test_hang(int fd)
{
- igt_hang_t hang;
- uint32_t patterns[] = {
+ const uint32_t patterns[] = {
0, 0xaaaaaaaa, 0x55555555, 0xcccccccc,
};
- uint32_t *gtt[3];
- int last_pattern = 0;
- int next_pattern = 1;
- int i;
+ const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+ struct {
+ bool done;
+ bool error;
+ } *control;
+ unsigned long count;
+ igt_hang_t hang;
+ int dir;
- for (i = I915_TILING_NONE; i <= I915_TILING_Y; i++) {
- uint32_t handle;
+ hang = igt_allow_hang(fd, 0, 0);
+ igt_require(igt_sysfs_set_parameter(fd, "reset", "1")); /* global */
- handle = gem_create(fd, OBJECT_SIZE);
- gem_set_tiling(fd, handle, i, 2048);
+ control = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+ igt_assert(control != MAP_FAILED);
- gtt[i] = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_WRITE);
- set_domain_gtt(fd, handle);
- gem_close(fd, handle);
- }
+ igt_fork(child, ncpus) {
+ int last_pattern = 0;
+ int next_pattern = 1;
+ uint32_t *gtt[2];
- hang = igt_hang_ring(fd, I915_EXEC_RENDER);
+ for (int i = 0; i < ARRAY_SIZE(gtt); i++) {
+ uint32_t handle;
- do {
- for (i = 0; i < OBJECT_SIZE / 64; i++) {
- int x = 16*i + (i%16);
+ handle = gem_create(fd, OBJECT_SIZE);
+ gem_set_tiling(fd, handle, I915_TILING_X + i, 2048);
- igt_assert(gtt[0][x] == patterns[last_pattern]);
- igt_assert(gtt[1][x] == patterns[last_pattern]);
- igt_assert(gtt[2][x] == patterns[last_pattern]);
+ gtt[i] = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_WRITE);
+ set_domain_gtt(fd, handle);
+ gem_close(fd, handle);
+ }
- gtt[0][x] = patterns[next_pattern];
- gtt[1][x] = patterns[next_pattern];
- gtt[2][x] = patterns[next_pattern];
+ while (!READ_ONCE(control->done)) {
+ for (int i = 0; i < OBJECT_SIZE / 64; i++) {
+ const unsigned int x = 16 * i + ( i% 16);
+ uint32_t expected = patterns[last_pattern];
+ uint32_t found[2];
+
+ found[0] = READ_ONCE(gtt[0][x]);
+ found[1] = READ_ONCE(gtt[1][x]);
+
+ if (found[0] != expected ||
+ found[1] != expected) {
+ igt_warn("child[%d] found (%x, %x), expecting %x\n",
+ child,
+ found[0], found[1],
+ expected);
+ control->error = true;
+ exit(0);
+ }
+
+ gtt[0][x] = patterns[next_pattern];
+ gtt[1][x] = patterns[next_pattern];
+ }
+
+ last_pattern = next_pattern;
+ next_pattern = (next_pattern + 1) % ARRAY_SIZE(patterns);
}
+ }
- last_pattern = next_pattern;
- next_pattern = (next_pattern + 1) % ARRAY_SIZE(patterns);
- } while (gem_bo_busy(fd, hang.spin->handle));
+ count = 0;
+ dir = igt_debugfs_dir(fd);
+ igt_until_timeout(5) {
+ igt_sysfs_set(dir, "i915_wedged", "-1");
+ if (READ_ONCE(control->error))
+ break;
+ count++;
+ }
+ close(dir);
+ igt_info("%lu resets\n", count);
+
+ control->done = true;
+ igt_waitchildren();
- igt_post_hang_ring(fd, hang);
+ igt_assert(!control->error);
+ munmap(control, 4096);
- munmap(gtt[0], OBJECT_SIZE);
- munmap(gtt[1], OBJECT_SIZE);
- munmap(gtt[2], OBJECT_SIZE);
+ igt_disallow_hang(fd, hang);
}
static int min_tile_width(uint32_t devid, int tiling)