[PATCH i-g-t v3] tests/gem_userptr_blits: subtests for MAP_FIXED mappings of regular BO

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When the memory backing the userptr object is freed 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.

v2: Grammar/naming fixes, s/posix_memalign/mmap (Tvrtko), merge tests into
single function, call set_tiling after get_pages, comments, GUP slowpath
v3: Do not assert on EFAULT from get_pages

Signed-off-by: Michał Winiarski <michal.winiarski@xxxxxxxxx>
Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
Cc: Tvrtko Ursulin <tvrtko.ursulin@xxxxxxxxx>
---
 tests/gem_userptr_blits.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/tests/gem_userptr_blits.c b/tests/gem_userptr_blits.c
index 6d38260..1868dd7 100644
--- a/tests/gem_userptr_blits.c
+++ b/tests/gem_userptr_blits.c
@@ -637,6 +637,92 @@ 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 MAP_FIXED_INVALIDATE_FILE_BACKED	(1<<3)
+#define ALL_MAP_FIXED_INVALIDATE (MAP_FIXED_INVALIDATE_OVERLAP | \
+		MAP_FIXED_INVALIDATE_BUSY | \
+		MAP_FIXED_INVALIDATE_GET_PAGES | \
+		MAP_FIXED_INVALIDATE_FILE_BACKED)
+
+static void map_fixed_invalidate_drop_caches(int fd)
+{
+	if (fd != -1) {
+		igt_assert(fsync(fd) == 0);
+		intel_purge_vm_caches();
+	}
+}
+
+static int test_map_fixed_invalidate(int fd, uint32_t flags)
+{
+	void *ptr;
+	size_t ptr_size = sizeof(linear);
+	void *map;
+	int i;
+	int num_handles = (flags & MAP_FIXED_INVALIDATE_OVERLAP) ? 2 : 1;
+	int userptr_fd = -1;
+	char userptr_fd_name[32];
+	uint32_t handle[num_handles];
+	uint32_t mmap_handle;
+	struct drm_i915_gem_mmap_gtt mmap_arg;
+	struct drm_i915_gem_set_domain set_domain;
+
+	//We can excercise mmap with fd to trigger slowpath on GUP
+	if (flags & MAP_FIXED_INVALIDATE_FILE_BACKED) {
+		snprintf(userptr_fd_name, 32, "igt.XXXXXX");
+		userptr_fd = mkstemp(userptr_fd_name);
+		igt_assert(userptr_fd != -1);
+		igt_assert(unlink(userptr_fd_name) == 0);
+		igt_assert(ftruncate(userptr_fd, ptr_size) == 0);
+		ptr = mmap(NULL, ptr_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+				userptr_fd, 0);
+	}
+	else
+		ptr = mmap(NULL, ptr_size, PROT_READ | PROT_WRITE, MAP_SHARED |
+				MAP_ANONYMOUS, -1, 0);
+	igt_assert(ptr != MAP_FAILED);
+
+	for (i=0; i<num_handles; i++)
+		handle[i] = create_userptr(fd, 0, ptr);
+	mmap_handle = gem_create(fd, PAGE_SIZE);
+
+	if (flags & MAP_FIXED_INVALIDATE_BUSY) {
+		map_fixed_invalidate_drop_caches(userptr_fd);
+		copy(fd, handle[0], handle[num_handles-1], 0);
+		map_fixed_invalidate_drop_caches(userptr_fd);
+	}
+
+	//Map regular buffer in userptr range, triggering invalidate
+	memset(&mmap_arg, 0, sizeof(mmap_arg));
+	mmap_arg.handle = mmap_handle;
+	do_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg);
+	map = mmap(ptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
+			fd, mmap_arg.offset);
+	igt_assert(map != MAP_FAILED);
+
+	//Make sure the obj is fault_mappable
+	*(uint32_t*)map = 0xdead;
+
+	//Trigger get_pages on stale userptr
+	if (flags & MAP_FIXED_INVALIDATE_GET_PAGES) {
+		memset(&set_domain, 0, sizeof(set_domain));
+		set_domain.handle = handle[0];
+		set_domain.read_domains = I915_GEM_DOMAIN_GTT;
+		set_domain.write_domain = I915_GEM_DOMAIN_GTT;
+		drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
+	}
+
+	gem_set_tiling(fd, mmap_handle, 2, 512 * 4);
+
+	munmap(ptr, ptr_size);
+	for (i=0; i<num_handles; i++)
+		gem_close(fd, handle[i]);
+	gem_close(fd, mmap_handle);
+
+	return 0;
+}
+
 static int test_forbidden_ops(int fd)
 {
 	struct drm_i915_gem_pread gem_pread;
@@ -1487,6 +1573,16 @@ 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%s",
+			flags & MAP_FIXED_INVALIDATE_OVERLAP ? "-overlap" : "",
+			flags & MAP_FIXED_INVALIDATE_BUSY ? "-busy" : "",
+			flags & MAP_FIXED_INVALIDATE_GET_PAGES ? "-gup" : "",
+			flags & MAP_FIXED_INVALIDATE_FILE_BACKED ? "-file" : "") {
+			test_map_fixed_invalidate(fd, flags);
+		}
+	}
+
 	igt_subtest("coherency-sync")
 		test_coherency(fd, count);
 
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux