summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-11-08 18:45:55 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2020-09-03 13:52:05 +0100
commit2fc7b44ee60b001431b3191f763b4d3e10acff09 (patch)
tree21ea682e95733d0e29a0cf7f32574a7be45141b8
parentd674dcd3b227952f20c016a0e4c9733747c58950 (diff)
igt/gem_userptr: Exercise new PROBE | POPULATE flags
Exercise new API to probe that the userptr range is valid (backed by struct pages and not pfn) or to populate the userptr upon creation (by calling get_user_pages() on the range). Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: MichaƂ Winiarski <michal.winiarski@intel.com>
-rw-r--r--tests/i915/gem_userptr_blits.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/tests/i915/gem_userptr_blits.c b/tests/i915/gem_userptr_blits.c
index e46ed047..853b78e4 100644
--- a/tests/i915/gem_userptr_blits.c
+++ b/tests/i915/gem_userptr_blits.c
@@ -668,6 +668,89 @@ static int test_invalid_mapping(int fd, const struct mmap_offset *t)
return 0;
}
+#define LOCAL_USERPTR_PROBE 0x2
+#define LOCAL_USERPTR_POPULATE 0x4
+static void test_probe(int fd, unsigned int flags)
+{
+#define N_PAGES 5
+ struct drm_i915_gem_mmap_gtt mmap_gtt;
+ uint32_t handle;
+
+ igt_require(__gem_userptr(fd,
+ (void *)-PAGE_SIZE, 2*PAGE_SIZE, 0,
+ flags, &handle) == -EFAULT);
+
+ /*
+ * We allocate 5 pages, and apply various combinations
+ * of unmap, remap-gtt to the pages. Then we try to
+ * create a userptr from the middle 3 pages and check
+ * if unexpectedly succeeds or fails.
+ */
+ memset(&mmap_gtt, 0, sizeof(mmap_gtt));
+ mmap_gtt.handle = gem_create(fd, PAGE_SIZE);
+ drmIoctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_gtt);
+
+ 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_gtt.offset);
+ igt_assert(fixed != MAP_FAILED);
+ if (page >= 1 && page <= 3)
+ expected = -EFAULT;
+ break;
+ }
+ }
+
+ errno = 0;
+ handle = 0;
+ igt_assert_eq(__gem_userptr(fd, ptr + PAGE_SIZE, 3*PAGE_SIZE,
+ 0, flags, &handle),
+ expected);
+ if (handle) {
+ for (int page = 0; page < 3; page++)
+ store_dword(fd, handle, page*4096, handle);
+
+ gem_sync(fd, handle);
+
+ for (int page = 1; page <= 3; page++)
+ igt_assert_eq(*(uint32_t *)(ptr + page*PAGE_SIZE),
+ handle);
+
+ gem_close(fd, handle);
+ }
+
+ munmap(ptr, N_PAGES * PAGE_SIZE);
+ }
+
+ gem_close(fd, mmap_gtt.handle);
+#undef N_PAGES
+}
+
#define PE_BUSY 0x1
static void test_process_exit(int fd, const struct mmap_offset *mmo, int flags)
{
@@ -2207,6 +2290,12 @@ igt_main_args("c:", NULL, help_str, opt_handler, NULL)
igt_subtest("invalid-null-pointer")
test_invalid_null_pointer(fd);
+ igt_subtest("probe")
+ test_probe(fd, LOCAL_USERPTR_PROBE);
+
+ igt_subtest("populate")
+ test_probe(fd, LOCAL_USERPTR_POPULATE);
+
igt_subtest("forked-access")
test_forked_access(fd);