summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2016-07-15 09:01:59 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2016-07-15 09:04:15 +0100
commitc8ab577cbdeb5480f000f55ed2decae7b7932197 (patch)
treea1530140612f4e9537ae17faccde910d85042132
parent2ed42d3c4dc180ddbb99b1292f8656ca52d1d90e (diff)
igt/vgem_slow/nohang: Test fence autotimeout
To protect the kernel against unscrupulous fence users, fences should automatically signal after a timeout. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--lib/igt_vgem.c30
-rw-r--r--lib/igt_vgem.h5
-rw-r--r--tests/Makefile.sources1
-rw-r--r--tests/prime_vgem.c33
-rw-r--r--tests/vgem_basic.c8
-rw-r--r--tests/vgem_slow.c90
6 files changed, 145 insertions, 22 deletions
diff --git a/lib/igt_vgem.c b/lib/igt_vgem.c
index 95731d9b..66557913 100644
--- a/lib/igt_vgem.c
+++ b/lib/igt_vgem.c
@@ -89,7 +89,6 @@ void *vgem_mmap(int fd, struct vgem_bo *bo, unsigned prot)
struct local_vgem_fence_attach {
uint32_t handle;
uint32_t flags;
-#define VGEM_FENCE_WRITE 0x1
uint32_t out_fence;
uint32_t pad;
};
@@ -121,14 +120,37 @@ static int __vgem_fence_attach(int fd, struct local_vgem_fence_attach *arg)
return err;
}
-uint32_t vgem_fence_attach(int fd, struct vgem_bo *bo, bool write)
+bool vgem_fence_has_flag(int fd, unsigned flags)
+{
+ struct local_vgem_fence_attach arg;
+ struct vgem_bo bo;
+ bool ret = false;
+
+ memset(&bo, 0, sizeof(bo));
+ bo.width = 1;
+ bo.height = 1;
+ bo.bpp = 32;
+ vgem_create(fd, &bo);
+
+ memset(&arg, 0, sizeof(arg));
+ arg.handle = bo.handle;
+ arg.flags = flags;
+ if (__vgem_fence_attach(fd, &arg) == 0) {
+ vgem_fence_signal(fd, arg.out_fence);
+ ret = true;
+ }
+ gem_close(fd, bo.handle);
+
+ return ret;
+}
+
+uint32_t vgem_fence_attach(int fd, struct vgem_bo *bo, unsigned flags)
{
struct local_vgem_fence_attach arg;
memset(&arg, 0, sizeof(arg));
arg.handle = bo->handle;
- if (write)
- arg.flags |= VGEM_FENCE_WRITE;
+ arg.flags = flags;
igt_assert_eq(__vgem_fence_attach(fd, &arg), 0);
return arg.out_fence;
}
diff --git a/lib/igt_vgem.h b/lib/igt_vgem.h
index 91c77baf..ab9ece4c 100644
--- a/lib/igt_vgem.h
+++ b/lib/igt_vgem.h
@@ -40,7 +40,10 @@ void *__vgem_mmap(int fd, struct vgem_bo *bo, unsigned prot);
void *vgem_mmap(int fd, struct vgem_bo *bo, unsigned prot);
bool vgem_has_fences(int fd);
-uint32_t vgem_fence_attach(int fd, struct vgem_bo *bo, bool write);
+bool vgem_fence_has_flag(int fd, unsigned flags);
+uint32_t vgem_fence_attach(int fd, struct vgem_bo *bo, unsigned flags);
+#define VGEM_FENCE_WRITE 0x1
+#define WIP_VGEM_FENCE_NOTIMEOUT 0x2
void vgem_fence_signal(int fd, uint32_t fence);
#endif /* IGT_VGEM_H */
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 80e9a353..8a9a7ec9 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -124,6 +124,7 @@ TESTS_progs_M = \
prime_vgem \
template \
vgem_basic \
+ vgem_slow \
$(NULL)
TESTS_progs_XM = \
diff --git a/tests/prime_vgem.c b/tests/prime_vgem.c
index d0534872..a1541dac 100644
--- a/tests/prime_vgem.c
+++ b/tests/prime_vgem.c
@@ -338,7 +338,7 @@ static void test_fence_wait(int i915, int vgem, unsigned ring, unsigned flags)
vgem_create(vgem, &scratch);
dmabuf = prime_handle_to_fd(vgem, scratch.handle);
- fence = vgem_fence_attach(vgem, &scratch, true);
+ fence = vgem_fence_attach(vgem, &scratch, VGEM_FENCE_WRITE);
igt_assert(prime_busy(dmabuf, false));
gem_close(vgem, scratch.handle);
@@ -369,7 +369,7 @@ static void test_fence_wait(int i915, int vgem, unsigned ring, unsigned flags)
munmap(ptr, scratch.size);
}
-static void test_fence_hang(int i915, int vgem, bool write)
+static void test_fence_hang(int i915, int vgem, unsigned flags)
{
struct vgem_bo scratch;
uint32_t *ptr;
@@ -381,7 +381,7 @@ static void test_fence_hang(int i915, int vgem, bool write)
scratch.bpp = 32;
vgem_create(vgem, &scratch);
dmabuf = prime_handle_to_fd(vgem, scratch.handle);
- vgem_fence_attach(vgem, &scratch, write);
+ vgem_fence_attach(vgem, &scratch, flags | WIP_VGEM_FENCE_NOTIMEOUT);
ptr = mmap(NULL, scratch.size, PROT_READ, MAP_SHARED, dmabuf, 0);
igt_assert(ptr != MAP_FAILED);
@@ -499,7 +499,7 @@ static unsigned get_vblank(int fd, int pipe, unsigned flags)
return vbl.reply.sequence;
}
-static void test_flip(int i915, int vgem, bool hang)
+static void test_flip(int i915, int vgem, unsigned hang)
{
struct drm_event_vblank vbl;
uint32_t fb_id, crtc_id;
@@ -524,7 +524,7 @@ static void test_flip(int i915, int vgem, bool hang)
igt_require((crtc_id = set_fb_on_crtc(i915, 0, &bo, fb_id)));
/* Schedule a flip to wait upon vgem being written */
- fence = vgem_fence_attach(vgem, &bo, true);
+ fence = vgem_fence_attach(vgem, &bo, VGEM_FENCE_WRITE | hang);
do_or_die(drmModePageFlip(i915, crtc_id, fb_id,
DRM_MODE_PAGE_FLIP_EVENT, &fb_id));
@@ -638,15 +638,22 @@ igt_main
}
}
- igt_subtest("fence-read-hang")
- test_fence_hang(i915, vgem, false);
- igt_subtest("fence-write-hang")
- test_fence_hang(i915, vgem, true);
-
igt_subtest("basic-fence-flip")
- test_flip(i915, vgem, false);
- igt_subtest("fence-flip-hang")
- test_flip(i915, vgem, true);
+ test_flip(i915, vgem, 0);
+
+ igt_subtest_group {
+ igt_fixture {
+ igt_require(vgem_fence_has_flag(vgem, WIP_VGEM_FENCE_NOTIMEOUT));
+ }
+
+ igt_subtest("fence-read-hang")
+ test_fence_hang(i915, vgem, 0);
+ igt_subtest("fence-write-hang")
+ test_fence_hang(i915, vgem, VGEM_FENCE_WRITE);
+
+ igt_subtest("fence-flip-hang")
+ test_flip(i915, vgem, WIP_VGEM_FENCE_NOTIMEOUT);
+ }
}
igt_fixture {
diff --git a/tests/vgem_basic.c b/tests/vgem_basic.c
index 31166241..591973d0 100644
--- a/tests/vgem_basic.c
+++ b/tests/vgem_basic.c
@@ -172,7 +172,7 @@ static void test_dmabuf_fence(int fd)
dmabuf = prime_handle_to_fd(fd, bo.handle);
- fence = vgem_fence_attach(fd, &bo, false);
+ fence = vgem_fence_attach(fd, &bo, 0);
igt_assert(!prime_busy(dmabuf, false));
igt_assert(prime_busy(dmabuf, true));
@@ -180,7 +180,7 @@ static void test_dmabuf_fence(int fd)
igt_assert(!prime_busy(dmabuf, false));
igt_assert(!prime_busy(dmabuf, true));
- fence = vgem_fence_attach(fd, &bo, true);
+ fence = vgem_fence_attach(fd, &bo, VGEM_FENCE_WRITE);
igt_assert(prime_busy(dmabuf, false));
igt_assert(prime_busy(dmabuf, true));
@@ -202,7 +202,7 @@ static void test_dmabuf_fence_before(int fd)
bo.bpp = 32;
vgem_create(fd, &bo);
- fence = vgem_fence_attach(fd, &bo, false);
+ fence = vgem_fence_attach(fd, &bo, 0);
dmabuf = prime_handle_to_fd(fd, bo.handle);
igt_assert(!prime_busy(dmabuf, false));
@@ -215,7 +215,7 @@ static void test_dmabuf_fence_before(int fd)
gem_close(fd, bo.handle);
vgem_create(fd, &bo);
- fence = vgem_fence_attach(fd, &bo, true);
+ fence = vgem_fence_attach(fd, &bo, VGEM_FENCE_WRITE);
dmabuf = prime_handle_to_fd(fd, bo.handle);
igt_assert(prime_busy(dmabuf, false));
igt_assert(prime_busy(dmabuf, true));
diff --git a/tests/vgem_slow.c b/tests/vgem_slow.c
new file mode 100644
index 00000000..4a1ae702
--- /dev/null
+++ b/tests/vgem_slow.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "igt.h"
+#include "igt_vgem.h"
+#include "igt_debugfs.h"
+#include "igt_sysfs.h"
+
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+IGT_TEST_DESCRIPTION("Extended sanity check of Virtual GEM module (vGEM).");
+
+static bool has_prime_export(int fd)
+{
+ uint64_t value;
+
+ if (drmGetCap(fd, DRM_CAP_PRIME, &value))
+ return false;
+
+ return value & DRM_PRIME_CAP_EXPORT;
+}
+
+
+static void test_nohang(int fd)
+{
+ struct vgem_bo bo;
+ uint32_t fence;
+ struct pollfd pfd;
+
+ /* A vGEM fence must expire automatically to prevent driver hangs */
+
+ igt_require(has_prime_export(fd));
+ igt_require(vgem_has_fences(fd));
+
+ bo.width = 1;
+ bo.height = 1;
+ bo.bpp = 32;
+ vgem_create(fd, &bo);
+
+ pfd.fd = prime_handle_to_fd(fd, bo.handle);
+ pfd.events = POLLOUT;
+
+ fence = vgem_fence_attach(fd, &bo, 0);
+
+ igt_assert(poll(&pfd, 1, 0) == 0);
+ igt_assert(poll(&pfd, 1, 60*1000) == 1);
+
+ vgem_fence_signal(fd, fence);
+ close(pfd.fd);
+ gem_close(fd, bo.handle);
+}
+
+igt_main
+{
+ int fd = -1;
+
+ igt_fixture {
+ fd = drm_open_driver(DRIVER_VGEM);
+ }
+
+ igt_subtest_f("nohang")
+ test_nohang(fd);
+
+ igt_fixture {
+ close(fd);
+ }
+}