summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2021-07-15 11:09:32 +0100
committerMaarten Lankhorst <maarten.lankhorst@linux.intel.com>2021-08-05 12:13:57 +0200
commit4287344dd6a39d9036c5fb9a047a7d8f10bee981 (patch)
treeaf1f411103c454cca57e3912319e6fd012bdda7c /tests
parent6135b9cc319ed965e3aafb5b2ae2abf4762a06b2 (diff)
igt/gem_userptr: Exercise new PROBE flag
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@chris-wilson.co.uk> Signed-off-by: Matthew Auld <matthew.auld@intel.com> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/i915/gem_userptr_blits.c86
1 files changed, 86 insertions, 0 deletions
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);
+ }
}