summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>2021-02-18 23:30:45 -0800
committerNiranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>2022-06-17 21:27:58 +0000
commit9400a71aa241d35102adfdb3514518fbb69064ad (patch)
treedbcd5752942488f57472b1daee1711cd33ab2f80
parent5417d8f44d3afc35683351a3ef658bf4fe41fe88 (diff)
tests/i915/vm_bind: Add vm_bind sanity test
Add sanity test to exercise vm_bind uapi. Test for various cases with vm_bind and vm_unbind ioctls. Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
-rw-r--r--lib/intel_chipset.h2
-rw-r--r--lib/ioctl_wrappers.c39
-rw-r--r--lib/ioctl_wrappers.h1
-rw-r--r--tests/i915/i915_vm_bind_sanity.c137
-rw-r--r--tests/meson.build1
-rw-r--r--tests/prime_mmap.c26
6 files changed, 178 insertions, 28 deletions
diff --git a/lib/intel_chipset.h b/lib/intel_chipset.h
index db75a829f61c..1d0275c74254 100644
--- a/lib/intel_chipset.h
+++ b/lib/intel_chipset.h
@@ -221,4 +221,6 @@ void intel_check_pch(void);
#define HAS_FLATCCS(devid) (intel_get_device_info(devid)->has_flatccs)
+#define HAS_64K_PAGES(devid) (IS_DG2(devid))
+
#endif /* _INTEL_CHIPSET_H */
diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c
index ec6cfeaf82c1..e7ad77c6ad7d 100644
--- a/lib/ioctl_wrappers.c
+++ b/lib/ioctl_wrappers.c
@@ -1153,28 +1153,55 @@ void gem_require_mocs_registers(int fd)
/* prime */
/**
- * prime_handle_to_fd:
+ * prime_handle_to_fd_no_assert:
* @fd: open i915 drm file descriptor
* @handle: file-private gem buffer object handle
+ * @flags: DRM_IOCTL_PRIME_HANDLE_TO_FD ioctl flags
+ * @fd_out: place holder for output file handle
*
* This wraps the PRIME_HANDLE_TO_FD ioctl, which is used to export a gem buffer
* object into a global (i.e. potentially cross-device) dma-buf file-descriptor
* handle.
*
- * Returns: The created dma-buf fd handle.
+ * Returns: 0 on sucess, error otherwise. Upon success, it returns
+ * the created dma-buf fd handle in fd_out.
*/
-int prime_handle_to_fd(int fd, uint32_t handle)
+int prime_handle_to_fd_no_assert(int fd, uint32_t handle, int flags, int *fd_out)
{
struct drm_prime_handle args;
+ int ret;
memset(&args, 0, sizeof(args));
args.handle = handle;
- args.flags = DRM_CLOEXEC;
+ args.flags = flags;
args.fd = -1;
- do_ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
+ ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
+ if (ret)
+ ret = -errno;
+ *fd_out = args.fd;
- return args.fd;
+ return ret;
+}
+
+/**
+ * prime_handle_to_fd:
+ * @fd: open i915 drm file descriptor
+ * @handle: file-private gem buffer object handle
+ *
+ * This wraps the PRIME_HANDLE_TO_FD ioctl, which is used to export a gem buffer
+ * object into a global (i.e. potentially cross-device) dma-buf file-descriptor
+ * handle. It asserts that ioctl succeeds.
+ *
+ * Returns: The created dma-buf fd handle.
+ */
+int prime_handle_to_fd(int fd, uint32_t handle)
+{
+ int dmabuf;
+
+ igt_assert_eq(prime_handle_to_fd_no_assert(fd, handle, DRM_CLOEXEC, &dmabuf), 0);
+
+ return dmabuf;
}
/**
diff --git a/lib/ioctl_wrappers.h b/lib/ioctl_wrappers.h
index 9cad3e4cee1a..8cbfd69f102f 100644
--- a/lib/ioctl_wrappers.h
+++ b/lib/ioctl_wrappers.h
@@ -149,6 +149,7 @@ struct local_dma_buf_sync {
#define LOCAL_DMA_BUF_BASE 'b'
#define LOCAL_DMA_BUF_IOCTL_SYNC _IOW(LOCAL_DMA_BUF_BASE, 0, struct local_dma_buf_sync)
+int prime_handle_to_fd_no_assert(int fd, uint32_t handle, int flags, int *fd_out);
int prime_handle_to_fd(int fd, uint32_t handle);
#ifndef DRM_RDWR
#define DRM_RDWR O_RDWR
diff --git a/tests/i915/i915_vm_bind_sanity.c b/tests/i915/i915_vm_bind_sanity.c
new file mode 100644
index 000000000000..dd2bd64f310c
--- /dev/null
+++ b/tests/i915/i915_vm_bind_sanity.c
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2021 Intel Corporation. All rights reserved.
+ */
+
+/** @file i915_vm_bind_sanity.c
+ *
+ * This is the sanity test for VM_BIND UAPI.
+ *
+ * The goal is to test the UAPI interface.
+ */
+
+#include <fcntl.h>
+
+#include "i915/gem.h"
+#include "i915/gem_create.h"
+#include "igt.h"
+
+#include "i915/gem_vm.h"
+
+#define ENOTSUPP 524
+
+#define PAGE_SIZE 4096
+#define SZ_64K (16 * PAGE_SIZE)
+
+#define VA 0xa0000000
+
+static void basic(int fd, bool test_lmem)
+{
+ uint32_t vm_id, vm_id2, vm_id_exec_mode, handle, pg_size, size;
+ unsigned int region = test_lmem ? REGION_LMEM(0) : REGION_SMEM;
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 obj;
+ const intel_ctx_t *ctx;
+ int dmabuf;
+
+ pg_size = (test_lmem && HAS_64K_PAGES(intel_get_drm_devid(fd))) ? SZ_64K : PAGE_SIZE;
+ size = pg_size * 4;
+
+ vm_id = gem_vm_create_in_vm_bind_mode(fd);
+ handle = gem_create_in_memory_regions(fd, size, region);
+
+ /* Bind and unbind */
+ gem_vm_bind(fd, vm_id, handle, VA, 0, size, 0, 0);
+ gem_vm_unbind(fd, vm_id, VA, size, 0, 0);
+
+ /* Aliasing bind and unbind */
+ gem_vm_bind(fd, vm_id, handle, VA, 0, size, 0, 0);
+ gem_vm_bind(fd, vm_id, handle, VA + size, 0, size, 0, 0);
+ gem_vm_unbind(fd, vm_id, VA, size, 0, 0);
+ gem_vm_unbind(fd, vm_id, VA + size, size, 0, 0);
+
+ /* Invalid handle */
+ igt_assert_eq(__gem_vm_bind(fd, vm_id, handle + 10, VA, 0, size, 0, 0), -ENOENT);
+
+ /* Invalid mapping range */
+ igt_assert_eq(__gem_vm_bind(fd, vm_id, handle, VA, 0, 0, 0, 0), -EINVAL);
+ igt_assert_eq(__gem_vm_bind(fd, vm_id, handle, VA, pg_size, size, 0, 0), -EINVAL);
+
+ /* Unaligned binds */
+ igt_assert_eq(__gem_vm_bind(fd, vm_id, handle, VA, pg_size / 2, pg_size, 0, 0), -EINVAL);
+ igt_assert_eq(__gem_vm_bind(fd, vm_id, handle, VA, 0, pg_size / 2, 0, 0), -EINVAL);
+
+ /* range overflow binds */
+ igt_assert_eq(__gem_vm_bind(fd, vm_id, handle, VA, pg_size, -pg_size, 0, 0), -EINVAL);
+ igt_assert_eq(__gem_vm_bind(fd, vm_id, handle, VA, pg_size * 2, -pg_size, 0, 0), -EINVAL);
+
+ /* re-bind VA range without unbinding */
+ gem_vm_bind(fd, vm_id, handle, VA, 0, size, 0, 0);
+ igt_assert_eq(__gem_vm_bind(fd, vm_id, handle, VA, 0, size, 0, 0), -EEXIST);
+ gem_vm_unbind(fd, vm_id, VA, size, 0, 0);
+
+ /* unbind a non-existing mapping */
+ igt_assert_eq(__gem_vm_bind(fd, vm_id, 0, VA + VA, 0, size, 0, 0), -ENOENT);
+
+ /* unbind with length mismatch */
+ gem_vm_bind(fd, vm_id, handle, VA, 0, size, 0, 0);
+ igt_assert_eq(__gem_vm_bind(fd, vm_id, handle, VA, 0, size * 2, 0, 0), -EINVAL);
+ gem_vm_unbind(fd, vm_id, VA, size, 0, 0);
+
+ /* validate exclusivity of vm_bind & exec modes of binding */
+ vm_id_exec_mode = gem_vm_create(fd);
+ igt_assert_eq(__gem_vm_bind(fd, vm_id_exec_mode, handle, VA, 0, size, 0, 0), -ENOTSUPP);
+
+ ctx = intel_ctx_create_all_physical(fd);
+ gem_context_set_vm(fd, ctx->id, vm_id);
+ (void)gem_context_get_vm(fd, ctx->id);
+
+ memset(&obj, 0, sizeof(obj));
+ memset(&execbuf, 0, sizeof(execbuf));
+ execbuf.buffers_ptr = to_user_pointer(&obj);
+ execbuf.buffer_count = 1;
+ obj.handle = handle;
+ i915_execbuffer2_set_context_id(execbuf, ctx->id);
+ igt_assert_eq(__gem_execbuf(fd, &execbuf), -ENOTSUPP);
+
+ intel_ctx_destroy(fd, ctx);
+ gem_vm_destroy(fd, vm_id_exec_mode);
+ gem_close(fd, handle);
+
+ /* validate VM private objects */
+ vm_id2 = gem_vm_create_in_vm_bind_mode(fd);
+ handle = gem_create_vm_private_in_memory_regions(fd, size, vm_id2, region);
+
+ igt_assert_eq(prime_handle_to_fd_no_assert(fd, handle, DRM_CLOEXEC, &dmabuf), -EINVAL);
+ igt_assert_eq(__gem_vm_bind(fd, vm_id, handle, VA, 0, size, 0, 0), -EINVAL);
+ gem_vm_bind(fd, vm_id2, handle, VA, 0, size, 0, 0);
+ gem_vm_unbind(fd, vm_id2, VA, size, 0, 0);
+
+ gem_close(fd, handle);
+ gem_vm_destroy(fd, vm_id2);
+ gem_vm_destroy(fd, vm_id);
+}
+
+igt_main
+{
+ int fd;
+ bool has_lmem;
+
+ igt_fixture {
+ fd = drm_open_driver(DRIVER_INTEL);
+ igt_require_gem(fd);
+ has_lmem = gem_has_lmem(fd);
+ }
+
+ igt_subtest_f("basic") {
+ basic(fd, false);
+ if (has_lmem)
+ basic(fd, true);
+ }
+
+ igt_fixture {
+ close(fd);
+ }
+
+ igt_exit();
+}
diff --git a/tests/meson.build b/tests/meson.build
index fb0f1e37f633..2bb884a71f47 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -248,6 +248,7 @@ i915_progs = [
'sysfs_heartbeat_interval',
'sysfs_preempt_timeout',
'sysfs_timeslice_duration',
+ 'i915_vm_bind_sanity',
]
msm_progs = [
diff --git a/tests/prime_mmap.c b/tests/prime_mmap.c
index d53185ff1027..4c7656490701 100644
--- a/tests/prime_mmap.c
+++ b/tests/prime_mmap.c
@@ -298,24 +298,6 @@ test_dup(uint32_t region, int size)
close (dma_buf_fd);
}
-/* Used for error case testing to avoid wrapper */
-static int prime_handle_to_fd_no_assert(uint32_t handle, int flags, int *fd_out)
-{
- struct drm_prime_handle args;
- int ret;
-
- args.handle = handle;
- args.flags = flags;
- args.fd = -1;
-
- ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
- if (ret)
- ret = errno;
- *fd_out = args.fd;
-
- return ret;
-}
-
static bool has_userptr(void)
{
uint32_t handle = 0;
@@ -346,9 +328,9 @@ test_userptr(uint32_t region, int size)
gem_userptr(fd, (uint32_t *)ptr, size, 0, 0, &handle);
/* export userptr */
- ret = prime_handle_to_fd_no_assert(handle, DRM_CLOEXEC, &dma_buf_fd);
+ ret = prime_handle_to_fd_no_assert(fd, handle, DRM_CLOEXEC, &dma_buf_fd);
if (ret) {
- igt_assert(ret == EINVAL || ret == ENODEV);
+ igt_assert(ret == -EINVAL || ret == -ENODEV);
goto free_userptr;
} else {
igt_assert_eq(ret, 0);
@@ -376,7 +358,7 @@ test_errors(uint32_t region, int size)
/* Test for invalid flags */
handle = gem_create_in_memory_regions(fd, size, region);
for (i = 0; i < ARRAY_SIZE(invalid_flags); i++) {
- prime_handle_to_fd_no_assert(handle, invalid_flags[i], &dma_buf_fd);
+ prime_handle_to_fd_no_assert(fd, handle, invalid_flags[i], &dma_buf_fd);
igt_assert_eq(errno, EINVAL);
errno = 0;
}
@@ -386,7 +368,7 @@ test_errors(uint32_t region, int size)
handle = gem_create_in_memory_regions(fd, size, region);
fill_bo(handle, size);
gem_close(fd, handle);
- prime_handle_to_fd_no_assert(handle, DRM_CLOEXEC, &dma_buf_fd);
+ prime_handle_to_fd_no_assert(fd, handle, DRM_CLOEXEC, &dma_buf_fd);
igt_assert(dma_buf_fd == -1 && errno == ENOENT);
errno = 0;