[igt-dev] [PATCH i-g-t] igt/gem_userptr: Exercise new PROBE flag

Matthew Auld matthew.auld at intel.com
Thu Jul 15 10:09:32 UTC 2021


From: Chris Wilson <chris at chris-wilson.co.uk>

Exercise new API to probe that the userptr range is valid (backed by
struct pages and not pfn).

v2: remove POPULATE for now

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Signed-off-by: Matthew Auld <matthew.auld at intel.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 tests/i915/gem_userptr_blits.c | 86 ++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/tests/i915/gem_userptr_blits.c b/tests/i915/gem_userptr_blits.c
index 0616a937..532298dc 100644
--- a/tests/i915/gem_userptr_blits.c
+++ b/tests/i915/gem_userptr_blits.c
@@ -2127,6 +2127,87 @@ static int userfaultfd(int flags)
 	return syscall(SYS_userfaultfd, flags);
 }
 
+#define LOCAL_I915_PARAM_HAS_USERPTR_PROBE 56
+#define LOCAL_I915_USERPTR_PROBE 0x2
+
+static bool has_userptr_probe(int fd)
+{
+	struct drm_i915_getparam gp;
+	int value = 0;
+
+	memset(&gp, 0, sizeof(gp));
+	gp.param = LOCAL_I915_PARAM_HAS_USERPTR_PROBE;
+	gp.value = &value;
+
+	ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp, sizeof(gp));
+	errno = 0;
+
+	return value;
+}
+
+static void test_probe(int fd)
+{
+#define N_PAGES 5
+	struct drm_i915_gem_mmap_offset mmap_offset;
+	uint32_t handle;
+
+	/*
+	 * We allocate 5 pages, and apply various combinations of unmap,
+	 * remap-mmap-offset to the pages. Then we try to create a userptr from
+	 * the middle 3 pages and check if unexpectedly succeeds or fails.
+	 */
+	memset(&mmap_offset, 0, sizeof(mmap_offset));
+	mmap_offset.handle = gem_create(fd, PAGE_SIZE);
+	mmap_offset.flags = I915_MMAP_OFFSET_WB;
+	igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP_OFFSET, &mmap_offset), 0);
+
+	for (unsigned long pass = 0; pass < 4 * 4 * 4 * 4 * 4; pass++) {
+		int expected = 0;
+		void *ptr;
+
+		ptr = mmap(NULL, N_PAGES * PAGE_SIZE,
+			   PROT_READ | PROT_WRITE,
+			   MAP_SHARED | MAP_ANONYMOUS,
+			   -1, 0);
+
+		for (int page = 0; page < N_PAGES; page++) {
+			int mode = (pass >> (2 * page)) & 3;
+			void *fixed = ptr + page * PAGE_SIZE;
+
+			switch (mode) {
+			default:
+			case 0:
+				break;
+
+			case 1:
+				munmap(fixed, PAGE_SIZE);
+				if (page >= 1 && page <= 3)
+					expected = -EFAULT;
+				break;
+
+			case 2:
+				fixed = mmap(fixed, PAGE_SIZE,
+					     PROT_READ | PROT_WRITE,
+					     MAP_SHARED | MAP_FIXED,
+					     fd, mmap_offset.offset);
+				igt_assert(fixed != MAP_FAILED);
+				if (page >= 1 && page <= 3)
+					expected = -EFAULT;
+				break;
+			}
+		}
+
+		igt_assert_eq(__gem_userptr(fd, ptr + PAGE_SIZE, 3*PAGE_SIZE,
+					    0, LOCAL_I915_USERPTR_PROBE, &handle),
+			      expected);
+
+		munmap(ptr, N_PAGES * PAGE_SIZE);
+	}
+
+	gem_close(fd, mmap_offset.handle);
+#undef N_PAGES
+}
+
 static void test_userfault(int i915)
 {
 	struct uffdio_api api = { .api = UFFD_API };
@@ -2516,4 +2597,9 @@ igt_main_args("c:", NULL, help_str, opt_handler, NULL)
 
 	igt_subtest("access-control")
 		test_access_control(fd);
+
+	igt_subtest("probe") {
+		igt_require(has_userptr_probe(fd));
+		test_probe(fd);
+	}
 }
-- 
2.26.3



More information about the igt-dev mailing list