summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-09-04 09:26:24 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2015-01-07 17:35:14 +0000
commit16bafdf5bf0248c02ea9824aca003b2a23d464be (patch)
tree458e41ee3d09e66115755c3300081e9c0c5c2ee9 /tests
parent25cf0551c7d210c8c085c109891dc97a2cc61e27 (diff)
igt/gem_concurrent_blit: Inject hangs before verifying contents
After setting up the copy operations, add a hanging batch. This should mean that we complete the copy and the compare then races against the GEM reset. Hopefully, this will catch driver bugs where the target object is no longer accessible after the hang. Note: hang injection is disabled until the required kernel interface is completed. But there are useful additional tests here... Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'tests')
-rw-r--r--tests/gem_concurrent_blit.c245
1 files changed, 180 insertions, 65 deletions
diff --git a/tests/gem_concurrent_blit.c b/tests/gem_concurrent_blit.c
index 9d157b68..48ee48a6 100644
--- a/tests/gem_concurrent_blit.c
+++ b/tests/gem_concurrent_blit.c
@@ -49,11 +49,13 @@
#include "ioctl_wrappers.h"
#include "drmtest.h"
+#include "igt_aux.h"
+#include "igt_core.h"
+#include "igt_gt.h"
#include "intel_bufmgr.h"
#include "intel_batchbuffer.h"
#include "intel_io.h"
#include "intel_chipset.h"
-#include "igt_aux.h"
IGT_TEST_DESCRIPTION("Test of pread/pwrite behavior when writing to active"
" buffers.");
@@ -365,6 +367,7 @@ const int width = 512, height = 512;
igt_render_copyfunc_t rendercopy;
typedef void (*do_copy)(drm_intel_bo *dst, drm_intel_bo *src);
+typedef struct igt_hang_ring (*do_hang)(void);
static void render_copy_bo(drm_intel_bo *dst, drm_intel_bo *src)
{
@@ -454,11 +457,33 @@ static void wc_copy_bo(drm_intel_bo *dst, drm_intel_bo *src)
munmap(s, size);
}
+static struct igt_hang_ring no_hang(void)
+{
+ return (struct igt_hang_ring){0, 0};
+}
+
+static struct igt_hang_ring bcs_hang(void)
+{
+ return igt_hang_ring(fd, gen, I915_EXEC_BLT);
+}
+
+static struct igt_hang_ring rcs_hang(void)
+{
+ return igt_hang_ring(fd, gen, I915_EXEC_RENDER);
+}
+
+static void hang_require(void)
+{
+ igt_require(igt_can_hang_ring(fd, gen, -1));
+}
+
static void do_overwrite_source(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
- do_copy do_copy_func)
+ do_copy do_copy_func,
+ do_hang do_hang_func)
{
+ struct igt_hang_ring hang;
int i;
gem_quiescent_gpu(fd);
@@ -468,17 +493,63 @@ static void do_overwrite_source(const struct access_mode *mode,
}
for (i = 0; i < num_buffers; i++)
do_copy_func(dst[i], src[i]);
+ hang = do_hang_func();
for (i = num_buffers; i--; )
mode->set_bo(src[i], 0xdeadbeef, width, height);
for (i = 0; i < num_buffers; i++)
mode->cmp_bo(dst[i], i, width, height, dummy);
+ igt_post_hang_ring(fd, hang);
+}
+
+static void do_overwrite_source__rev(const struct access_mode *mode,
+ drm_intel_bo **src, drm_intel_bo **dst,
+ drm_intel_bo *dummy,
+ do_copy do_copy_func,
+ do_hang do_hang_func)
+{
+ struct igt_hang_ring hang;
+ int i;
+
+ gem_quiescent_gpu(fd);
+ for (i = 0; i < num_buffers; i++) {
+ mode->set_bo(src[i], i, width, height);
+ mode->set_bo(dst[i], ~i, width, height);
+ }
+ for (i = 0; i < num_buffers; i++)
+ do_copy_func(dst[i], src[i]);
+ hang = do_hang_func();
+ for (i = 0; i < num_buffers; i++)
+ mode->set_bo(src[i], 0xdeadbeef, width, height);
+ for (i = num_buffers; i--; )
+ mode->cmp_bo(dst[i], i, width, height, dummy);
+ igt_post_hang_ring(fd, hang);
+}
+
+static void do_overwrite_source__one(const struct access_mode *mode,
+ drm_intel_bo **src, drm_intel_bo **dst,
+ drm_intel_bo *dummy,
+ do_copy do_copy_func,
+ do_hang do_hang_func)
+{
+ struct igt_hang_ring hang;
+
+ gem_quiescent_gpu(fd);
+ mode->set_bo(src[0], 0, width, height);
+ mode->set_bo(dst[0], ~0, width, height);
+ do_copy_func(dst[0], src[0]);
+ hang = do_hang_func();
+ mode->set_bo(src[0], 0xdeadbeef, width, height);
+ mode->cmp_bo(dst[0], 0, width, height, dummy);
+ igt_post_hang_ring(fd, hang);
}
static void do_early_read(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
- do_copy do_copy_func)
+ do_copy do_copy_func,
+ do_hang do_hang_func)
{
+ struct igt_hang_ring hang;
int i;
gem_quiescent_gpu(fd);
@@ -486,15 +557,19 @@ static void do_early_read(const struct access_mode *mode,
mode->set_bo(src[i], 0xdeadbeef, width, height);
for (i = 0; i < num_buffers; i++)
do_copy_func(dst[i], src[i]);
+ hang = do_hang_func();
for (i = num_buffers; i--; )
mode->cmp_bo(dst[i], 0xdeadbeef, width, height, dummy);
+ igt_post_hang_ring(fd, hang);
}
static void do_gpu_read_after_write(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
- do_copy do_copy_func)
+ do_copy do_copy_func,
+ do_hang do_hang_func)
{
+ struct igt_hang_ring hang;
int i;
gem_quiescent_gpu(fd);
@@ -504,47 +579,54 @@ static void do_gpu_read_after_write(const struct access_mode *mode,
do_copy_func(dst[i], src[i]);
for (i = num_buffers; i--; )
do_copy_func(dummy, dst[i]);
+ hang = do_hang_func();
for (i = num_buffers; i--; )
mode->cmp_bo(dst[i], 0xabcdabcd, width, height, dummy);
+ igt_post_hang_ring(fd, hang);
}
typedef void (*do_test)(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
- do_copy do_copy_func);
+ do_copy do_copy_func,
+ do_hang do_hang_func);
typedef void (*run_wrap)(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
do_test do_test_func,
- do_copy do_copy_func);
+ do_copy do_copy_func,
+ do_hang do_hang_func);
static void run_single(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
do_test do_test_func,
- do_copy do_copy_func)
+ do_copy do_copy_func,
+ do_hang do_hang_func)
{
- do_test_func(mode, src, dst, dummy, do_copy_func);
+ do_test_func(mode, src, dst, dummy, do_copy_func, do_hang_func);
}
static void run_interruptible(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
do_test do_test_func,
- do_copy do_copy_func)
+ do_copy do_copy_func,
+ do_hang do_hang_func)
{
int loop;
for (loop = 0; loop < 10; loop++)
- do_test_func(mode, src, dst, dummy, do_copy_func);
+ do_test_func(mode, src, dst, dummy, do_copy_func, do_hang_func);
}
static void run_forked(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
do_test do_test_func,
- do_copy do_copy_func)
+ do_copy do_copy_func,
+ do_hang do_hang_func)
{
const int old_num_buffers = num_buffers;
@@ -555,6 +637,7 @@ static void run_forked(const struct access_mode *mode,
drm_intel_bufmgr *bufmgr;
/* recreate process local variables */
+ fd = drm_open_any();
bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
drm_intel_bufmgr_gem_enable_reuse(bufmgr);
@@ -567,18 +650,14 @@ static void run_forked(const struct access_mode *mode,
dummy = mode->create_bo(bufmgr, width, height);
for (int loop = 0; loop < 10; loop++)
- do_test_func(mode, src, dst, dummy, do_copy_func);
+ do_test_func(mode, src, dst, dummy,
+ do_copy_func, do_hang_func);
- /* as we borrow the fd, we need to reap our bo */
for (int i = 0; i < num_buffers; i++) {
mode->release_bo(src[i]);
mode->release_bo(dst[i]);
}
mode->release_bo(dummy);
-
- intel_batchbuffer_free(batch);
-
- drm_intel_bufmgr_destroy(bufmgr);
}
igt_waitchildren();
@@ -629,10 +708,13 @@ static void rcs_require(void)
igt_require(rendercopy);
}
+static void no_require(void)
+{
+}
+
static void
run_basic_modes(const struct access_mode *mode,
- drm_intel_bo **src, drm_intel_bo **dst,
- drm_intel_bo *dummy, const char *suffix,
+ const char *suffix,
run_wrap run_wrap_func)
{
const struct {
@@ -647,27 +729,85 @@ run_basic_modes(const struct access_mode *mode,
{ "rcs", render_copy_bo, rcs_require },
{ NULL, NULL }
}, *p;
+ const struct {
+ const char *suffix;
+ do_hang hang;
+ void (*require)(void);
+ } hangs[] = {
+ { "", no_hang, no_require },
+ { "-hang(bcs)", bcs_hang, hang_require },
+ { "-hang(rcs)", rcs_hang, hang_require },
+ { NULL, NULL },
+ }, *h;
+ drm_intel_bo *src[MAX_NUM_BUFFERS], *dst[MAX_NUM_BUFFERS], *dummy = NULL;
+ drm_intel_bufmgr *bufmgr;
- for (p = pipelines; p->prefix; p++) {
- /* try to overwrite the source values */
- igt_subtest_f("%s-%s-overwrite-source%s", mode->name, p->prefix, suffix) {
- p->require();
- run_wrap_func(mode, src, dst, dummy,
- do_overwrite_source, p->copy);
- }
- /* try to read the results before the copy completes */
- igt_subtest_f("%s-%s-early-read%s", mode->name, p->prefix, suffix) {
- p->require();
- run_wrap_func(mode, src, dst, dummy,
- do_early_read, p->copy);
- }
+ for (h = hangs; h->suffix; h++) {
+ for (p = pipelines; p->prefix; p++) {
+ igt_fixture {
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
- /* and finally try to trick the kernel into loosing the pending write */
- igt_subtest_f("%s-%s-gpu-read-after-write%s", mode->name, p->prefix, suffix) {
- p->require();
- run_wrap_func(mode, src, dst, dummy,
- do_gpu_read_after_write, p->copy);
+ for (int i = 0; i < num_buffers; i++) {
+ src[i] = mode->create_bo(bufmgr, width, height);
+ dst[i] = mode->create_bo(bufmgr, width, height);
+ }
+ dummy = mode->create_bo(bufmgr, width, height);
+ }
+
+ /* try to overwrite the source values */
+ igt_subtest_f("%s-%s-overwrite-source-one%s%s", mode->name, p->prefix, suffix, h->suffix) {
+ h->require();
+ p->require();
+ run_wrap_func(mode, src, dst, dummy,
+ do_overwrite_source__one,
+ p->copy, h->hang);
+ }
+
+ igt_subtest_f("%s-%s-overwrite-source%s%s", mode->name, p->prefix, suffix, h->suffix) {
+ h->require();
+ p->require();
+ run_wrap_func(mode, src, dst, dummy,
+ do_overwrite_source,
+ p->copy, h->hang);
+ }
+ igt_subtest_f("%s-%s-overwrite-source-rev%s%s", mode->name, p->prefix, suffix, h->suffix) {
+ h->require();
+ p->require();
+ run_wrap_func(mode, src, dst, dummy,
+ do_overwrite_source__rev,
+ p->copy, h->hang);
+ }
+
+ /* try to read the results before the copy completes */
+ igt_subtest_f("%s-%s-early-read%s%s", mode->name, p->prefix, suffix, h->suffix) {
+ h->require();
+ p->require();
+ run_wrap_func(mode, src, dst, dummy,
+ do_early_read,
+ p->copy, h->hang);
+ }
+
+ /* and finally try to trick the kernel into loosing the pending write */
+ igt_subtest_f("%s-%s-gpu-read-after-write%s%s", mode->name, p->prefix, suffix, h->suffix) {
+ h->require();
+ p->require();
+ run_wrap_func(mode, src, dst, dummy,
+ do_gpu_read_after_write,
+ p->copy, h->hang);
+ }
+
+ igt_fixture {
+ for (int i = 0; i < num_buffers; i++) {
+ mode->release_bo(src[i]);
+ mode->release_bo(dst[i]);
+ }
+ mode->release_bo(dummy);
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+ }
}
}
}
@@ -675,39 +815,14 @@ run_basic_modes(const struct access_mode *mode,
static void
run_modes(const struct access_mode *mode)
{
- drm_intel_bo *src[MAX_NUM_BUFFERS], *dst[MAX_NUM_BUFFERS], *dummy = NULL;
- drm_intel_bufmgr *bufmgr;
-
- igt_fixture {
- bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
- drm_intel_bufmgr_gem_enable_reuse(bufmgr);
- batch = intel_batchbuffer_alloc(bufmgr, devid);
-
- for (int i = 0; i < num_buffers; i++) {
- src[i] = mode->create_bo(bufmgr, width, height);
- dst[i] = mode->create_bo(bufmgr, width, height);
- }
- dummy = mode->create_bo(bufmgr, width, height);
- }
-
- run_basic_modes(mode, src, dst, dummy, "", run_single);
+ run_basic_modes(mode, "", run_single);
igt_fork_signal_helper();
- run_basic_modes(mode, src, dst, dummy, "-interruptible", run_interruptible);
+ run_basic_modes(mode, "-interruptible", run_interruptible);
igt_stop_signal_helper();
- igt_fixture {
- for (int i = 0; i < num_buffers; i++) {
- mode->release_bo(src[i]);
- mode->release_bo(dst[i]);
- }
- mode->release_bo(dummy);
- intel_batchbuffer_free(batch);
- drm_intel_bufmgr_destroy(bufmgr);
- }
-
igt_fork_signal_helper();
- run_basic_modes(mode, src, dst, dummy, "-forked", run_forked);
+ run_basic_modes(mode, "-forked", run_forked);
igt_stop_signal_helper();
}