diff mbox

[1/3] igt/gem_evict_(alignment|everything): contend with GPU hangs

Message ID 1414091156-571-1-git-send-email-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Wilson Oct. 23, 2014, 7:05 p.m. UTC
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 lib/igt_aux.c                | 69 ++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_aux.h                |  4 +++
 tests/gem_evict_alignment.c  | 15 ++++++++++
 tests/gem_evict_everything.c | 15 ++++++++++
 4 files changed, 103 insertions(+)
diff mbox

Patch

diff --git a/lib/igt_aux.c b/lib/igt_aux.c
index 0e1eeea..b78ca2f 100644
--- a/lib/igt_aux.c
+++ b/lib/igt_aux.c
@@ -53,6 +53,7 @@ 
 #include "intel_chipset.h"
 #include "igt_aux.h"
 #include "igt_debugfs.h"
+#include "igt_gt.h"
 #include "config.h"
 #include "intel_reg.h"
 #include "ioctl_wrappers.h"
@@ -131,6 +132,74 @@  void igt_stop_signal_helper(void)
 	sig_stat = 0;
 }
 
+/* GPU abusers */
+static struct igt_helper_process hang_helper;
+static void __attribute__((noreturn))
+hang_helper_process(pid_t pid, int fd, int gen)
+{
+	while (1) {
+		if (kill(pid, 0)) /* Parent has died, so must we. */
+			exit(0);
+
+		igt_post_hang_ring(fd,
+				   igt_hang_ring(fd, gen, I915_EXEC_DEFAULT));
+
+		sleep(1);
+	}
+}
+
+/**
+ * igt_fork_hang_helper:
+ *
+ * Fork a child process using #igt_fork_helper to hang the default engine
+ * of the GPU at regular intervals.
+ *
+ * This is useful to exercise slow running code (such as aperture placement)
+ * which needs to be robust against a GPU reset.
+ *
+ * In tests with subtests this function can be called outside of failure
+ * catching code blocks like #igt_fixture or #igt_subtest.
+ */
+int igt_fork_hang_helper(void)
+{
+	int fd, gen;
+
+	if (igt_only_list_subtests())
+		return 1;
+
+	fd = drm_open_any();
+	if (fd == -1)
+		return 0;
+
+	gen = intel_gen(intel_get_drm_devid(fd));
+	if (gen < 5) {
+		close(fd);
+		return 0;
+	}
+
+	igt_fork_helper(&hang_helper)
+		hang_helper_process(getppid(), fd, gen);
+
+	close(fd);
+	return 1;
+}
+
+/**
+ * igt_stop_hang_helper:
+ *
+ * Stops the child process spawned with igt_fork_hang_helper().
+ *
+ * In tests with subtests this function can be called outside of failure
+ * catching code blocks like #igt_fixture or #igt_subtest.
+ */
+void igt_stop_hang_helper(void)
+{
+	if (igt_only_list_subtests())
+		return;
+
+	igt_stop_helper(&hang_helper);
+}
+
 /**
  * igt_check_boolean_env_var:
  * @env_var: environment variable name
diff --git a/lib/igt_aux.h b/lib/igt_aux.h
index 9b42918..6056575 100644
--- a/lib/igt_aux.h
+++ b/lib/igt_aux.h
@@ -35,6 +35,10 @@ 
 /* generally useful helpers */
 void igt_fork_signal_helper(void);
 void igt_stop_signal_helper(void);
+
+int igt_fork_hang_helper(void);
+void igt_stop_hang_helper(void);
+
 void igt_exchange_int(void *array, unsigned i, unsigned j);
 void igt_permute_array(void *array, unsigned size,
 			   void (*exchange_func)(void *array,
diff --git a/tests/gem_evict_alignment.c b/tests/gem_evict_alignment.c
index e814f36..3ee23b9 100644
--- a/tests/gem_evict_alignment.c
+++ b/tests/gem_evict_alignment.c
@@ -221,6 +221,21 @@  igt_main
 		count = 4;
 		major_evictions(fd, size, count);
 	}
+
+	if (igt_fork_hang_helper()) {
+		igt_subtest("minor-hang") {
+			size = 1024 * 1024;
+			count = 3*gem_aperture_size(fd) / size / 4;
+			minor_evictions(fd, size, count);
+		}
+
+		igt_subtest("major-hang") {
+			size = 3*gem_aperture_size(fd) / 4;
+			count = 4;
+			major_evictions(fd, size, count);
+		}
+		igt_stop_hang_helper();
+	}
 	igt_stop_signal_helper();
 
 	igt_fixture
diff --git a/tests/gem_evict_everything.c b/tests/gem_evict_everything.c
index c1eb3bd..596891c 100644
--- a/tests/gem_evict_everything.c
+++ b/tests/gem_evict_everything.c
@@ -234,6 +234,21 @@  igt_main
 		test_major_evictions(fd, size, count);
 	}
 
+	if (igt_fork_hang_helper()) {
+		igt_subtest("swapping-hang")
+			test_swapping_evictions(fd, size, count);
+
+		igt_subtest("minor-hang")
+			test_minor_evictions(fd, size, count);
+
+		igt_subtest("major-hang") {
+			size = 3*gem_aperture_size(fd) / 4;
+			count = 4;
+			test_major_evictions(fd, size, count);
+		}
+
+		igt_stop_hang_helper();
+	}
 	igt_stop_signal_helper();
 
 	igt_fixture {