summaryrefslogtreecommitdiff
path: root/tests/gem_userptr_blits.c
diff options
context:
space:
mode:
authorMichał Winiarski <michal.winiarski@intel.com>2015-06-30 17:01:10 +0200
committerChris Wilson <chris@chris-wilson.co.uk>2017-03-08 21:57:09 +0000
commit7b46ae1ba16082669dc7947b290e327a86b68afa (patch)
tree93a1e4f1c23fc91baf1a40eaba46e0c0ca179b18 /tests/gem_userptr_blits.c
parentfd9f3647bb4a5ead4c2e55c3cf04bd5364486c6a (diff)
tests/gem_userptr_blits: subtests for MAP_FIXED mappings of regular BO
When the memory backing the userptr object is released by the user, but the BO itself is not closed, it's possible to trigger recursive deadlock caused by operations done on different BO mapped in that region. Testcases are simulating such behaviour by using MAP_FIXED mmap flag. Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Diffstat (limited to 'tests/gem_userptr_blits.c')
-rw-r--r--tests/gem_userptr_blits.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/tests/gem_userptr_blits.c b/tests/gem_userptr_blits.c
index 0df53105..49a7f2f4 100644
--- a/tests/gem_userptr_blits.c
+++ b/tests/gem_userptr_blits.c
@@ -614,6 +614,74 @@ static void test_forked_access(int fd)
free(ptr2);
}
+#define MAP_FIXED_INVALIDATE_OVERLAP (1<<0)
+#define MAP_FIXED_INVALIDATE_BUSY (1<<1)
+#define MAP_FIXED_INVALIDATE_GET_PAGES (1<<2)
+#define ALL_MAP_FIXED_INVALIDATE (MAP_FIXED_INVALIDATE_OVERLAP | \
+ MAP_FIXED_INVALIDATE_BUSY | \
+ MAP_FIXED_INVALIDATE_GET_PAGES)
+
+static int test_map_fixed_invalidate(int fd, uint32_t flags)
+{
+ const size_t ptr_size = sizeof(linear) + 2*PAGE_SIZE;
+ const int num_handles = (flags & MAP_FIXED_INVALIDATE_OVERLAP) ? 2 : 1;
+ uint32_t handle[num_handles];
+ uint32_t *ptr;
+
+ ptr = mmap(NULL, ptr_size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS,
+ -1, 0);
+ igt_assert(ptr != MAP_FAILED);
+
+ for (int i = 0; i < num_handles; i++)
+ handle[i] = create_userptr(fd, 0, ptr + PAGE_SIZE/sizeof(*ptr));
+
+ for (char *fixed = (char *)ptr, *end = fixed + ptr_size;
+ fixed + 2*PAGE_SIZE <= end;
+ fixed += PAGE_SIZE) {
+ struct drm_i915_gem_mmap_gtt mmap_gtt;
+ char *map;
+
+ ptr = mmap(ptr, ptr_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED,
+ -1, 0);
+
+ memset(&mmap_gtt, 0, sizeof(mmap_gtt));
+ mmap_gtt.handle = gem_create(fd, 2*PAGE_SIZE);
+ do_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_gtt);
+
+ if (flags & MAP_FIXED_INVALIDATE_BUSY)
+ copy(fd, handle[0], handle[num_handles-1], 0);
+
+ map = mmap(fixed, 2*PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_FIXED,
+ fd, mmap_gtt.offset);
+ igt_assert(map == fixed);
+
+ gem_set_tiling(fd, mmap_gtt.handle, I915_TILING_NONE, 0);
+ *(uint32_t*)map = 0xdead;
+
+ if (flags & MAP_FIXED_INVALIDATE_GET_PAGES)
+ igt_assert_eq(__gem_set_domain(fd, handle[0],
+ I915_GEM_DOMAIN_GTT,
+ I915_GEM_DOMAIN_GTT),
+ -EFAULT);
+
+ gem_set_tiling(fd, mmap_gtt.handle, I915_TILING_Y, 512 * 4);
+ *(uint32_t*)map = 0xbeef;
+
+ gem_close(fd, mmap_gtt.handle);
+ }
+
+ for (int i = 0; i < num_handles; i++)
+ gem_close(fd, handle[i]);
+ munmap(ptr, ptr_size);
+
+ return 0;
+}
+
static int test_forbidden_ops(int fd)
{
struct drm_i915_gem_pread gem_pread;
@@ -1504,6 +1572,15 @@ int main(int argc, char **argv)
igt_subtest("stress-mm-invalidate-close-overlap")
test_invalidate_close_race(fd, true);
+ for (unsigned flags = 0; flags < ALL_MAP_FIXED_INVALIDATE + 1; flags++) {
+ igt_subtest_f("map-fixed-invalidate%s%s%s",
+ flags & MAP_FIXED_INVALIDATE_OVERLAP ? "-overlap" : "",
+ flags & MAP_FIXED_INVALIDATE_BUSY ? "-busy" : "",
+ flags & MAP_FIXED_INVALIDATE_GET_PAGES ? "-gup" : "") {
+ test_map_fixed_invalidate(fd, flags);
+ }
+ }
+
igt_subtest("coherency-sync")
test_coherency(fd, count);