@@ -35,6 +35,8 @@ lib_source_list = \
igt_stats.h \
igt_sysfs.c \
igt_sysfs.h \
+ igt_sysrq.c \
+ igt_sysrq.h \
igt_x86.h \
igt_x86.c \
igt_vgem.c \
@@ -70,6 +70,7 @@
#include "igt_core.h"
#include "igt_aux.h"
#include "igt_sysfs.h"
+#include "igt_sysrq.h"
#include "igt_rc.h"
#define UNW_LOCAL_ONLY
@@ -1136,6 +1137,28 @@ void igt_fail(int exitcode)
}
}
+/**
+ * igt_fatal_error: Stop test execution on fatal errors
+ *
+ * Stop test execution or optionally, if the IGT_REBOOT_ON_FATAL_ERROR
+ * environment variable is set, reboot the machine.
+ *
+ * Since out test runner (piglit) does support fatal test exit codes, we
+ * implement the default behaviour by waiting endlessly.
+ */
+void __attribute__((noreturn)) igt_fatal_error(void)
+{
+ if (igt_check_boolean_env_var("IGT_REBOOT_ON_FATAL_ERROR", false)) {
+ igt_warn("FATAL ERROR - REBOOTING\n");
+ igt_sysrq_reboot();
+ } else {
+ igt_warn("FATAL ERROR\n");
+ for (;;)
+ pause();
+ }
+}
+
+
/**
* igt_can_fail:
*
@@ -311,6 +311,7 @@ void __igt_fail_assert(const char *domain, const char *file,
const char *format, ...)
__attribute__((noreturn));
void igt_exit(void) __attribute__((noreturn));
+void igt_fatal_error(void) __attribute__((noreturn));
/**
* igt_ignore_warn:
new file mode 100644
@@ -0,0 +1,27 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/reboot.h>
+
+#include "igt_core.h"
+
+#include "igt_sysrq.h"
+
+/**
+ * igt_sysrq_reboot: Reboots the machine
+ *
+ * Syncs filesystems and immediately reboots the machine.
+ */
+void igt_sysrq_reboot(void)
+{
+ sync();
+
+ /* Try to be nice at first, and if that fails pull the trigger */
+ if (reboot(RB_AUTOBOOT)) {
+ int fd = open("/proc/sysrq-trigger", O_WRONLY);
+ igt_ignore_warn(write(fd, "b", 2));
+ close(fd);
+ }
+
+ abort();
+}
new file mode 100644
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2018 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.
+ *
+ */
+
+#ifndef __IGT_SYSRQ_H__
+#define __IGT_SYSRQ_H__
+
+void igt_sysrq_reboot(void) __attribute__((noreturn));
+
+#endif /* __IGT_SYSRQ_H__ */
@@ -14,6 +14,7 @@ lib_sources = [
'igt_stats.c',
'igt_syncobj.c',
'igt_sysfs.c',
+ 'igt_sysrq.c',
'igt_vgem.c',
'igt_x86.c',
'instdone.c',
@@ -965,6 +965,7 @@ static void cpu_hotplug(int gem_fd)
int link[2];
int fd, ret;
int cur = 0;
+ char buf;
igt_skip_on(IS_BROXTON(intel_get_drm_devid(gem_fd)));
igt_require(cpu0_hotplug_support());
@@ -1011,9 +1012,32 @@ static void cpu_hotplug(int gem_fd)
}
/* Offline followed by online a CPU. */
- igt_assert_eq(write(cpufd, "0", 2), 2);
+
+ ret = write(cpufd, "0", 2);
+ if (ret < 0) {
+ /*
+ * If we failed to offline a CPU we don't want
+ * to proceed.
+ */
+ igt_warn("Failed to offline cpu%u! (%d)\n",
+ cpu, errno);
+ igt_assert_eq(write(link[1], "s", 1), 1);
+ break;
+ }
+
usleep(1e6);
- igt_assert_eq(write(cpufd, "1", 2), 2);
+
+ ret = write(cpufd, "1", 2);
+ if (ret < 0) {
+ /*
+ * Failed to bring a CPU back online is fatal
+ * for the sanity of a test run so stop further
+ * testing.
+ */
+ igt_warn("Failed to online cpu%u! (%d)\n",
+ cpu, errno);
+ igt_fatal_error();
+ }
close(cpufd);
cpu++;
@@ -1027,15 +1051,12 @@ static void cpu_hotplug(int gem_fd)
* until the CPU core shuffler finishes one loop.
*/
for (;;) {
- char buf;
- int ret2;
-
usleep(500e3);
end_spin(gem_fd, spin[cur], 0);
/* Check if the child is signaling completion. */
- ret2 = read(link[0], &buf, 1);
- if ( ret2 == 1 || (ret2 < 0 && errno != EAGAIN))
+ ret = read(link[0], &buf, 1);
+ if ( ret == 1 || (ret < 0 && errno != EAGAIN))
break;
igt_spin_batch_free(gem_fd, spin[cur]);
@@ -1054,6 +1075,9 @@ static void cpu_hotplug(int gem_fd)
close(fd);
close(link[0]);
+ /* Skip if child signals a problem with offlining a CPU. */
+ igt_skip_on(buf == 's');
+
assert_within_epsilon(val, ts[1] - ts[0], tolerance);
}