From be29b2ebe81cfca08a2c601e5e047664bad8cf7a Mon Sep 17 00:00:00 2001 From: Arkadiusz Hiler Date: Tue, 19 Feb 2019 13:40:07 +0200 Subject: tests/i915: Rename files so they correspond to binary names So we do not have to do any rename shenanigans in the build system and the .c files are easier to find. Cc: Chris Wilson Cc: Petri Latvala Signed-off-by: Arkadiusz Hiler Reviewed-by: Petri Latvala --- tests/Makefile.sources | 16 +- tests/i915/fb_tiling.c | 46 ---- tests/i915/getparams_basic.c | 164 ------------ tests/i915/hangman.c | 291 --------------------- tests/i915/i915_fb_tiling.c | 46 ++++ tests/i915/i915_getparams_basic.c | 164 ++++++++++++ tests/i915/i915_hangman.c | 291 +++++++++++++++++++++ tests/i915/i915_missed_irq.c | 165 ++++++++++++ tests/i915/i915_module_load.c | 369 ++++++++++++++++++++++++++ tests/i915/i915_query.c | 536 ++++++++++++++++++++++++++++++++++++++ tests/i915/i915_selftest.c | 43 +++ tests/i915/i915_suspend.c | 254 ++++++++++++++++++ tests/i915/missed_irq.c | 165 ------------ tests/i915/module_load.c | 369 -------------------------- tests/i915/query.c | 536 -------------------------------------- tests/i915/selftest.c | 43 --- tests/i915/suspend.c | 254 ------------------ tests/meson.build | 43 +-- 18 files changed, 1889 insertions(+), 1906 deletions(-) delete mode 100644 tests/i915/fb_tiling.c delete mode 100644 tests/i915/getparams_basic.c delete mode 100644 tests/i915/hangman.c create mode 100644 tests/i915/i915_fb_tiling.c create mode 100644 tests/i915/i915_getparams_basic.c create mode 100644 tests/i915/i915_hangman.c create mode 100644 tests/i915/i915_missed_irq.c create mode 100644 tests/i915/i915_module_load.c create mode 100644 tests/i915/i915_query.c create mode 100644 tests/i915/i915_selftest.c create mode 100644 tests/i915/i915_suspend.c delete mode 100644 tests/i915/missed_irq.c delete mode 100644 tests/i915/module_load.c delete mode 100644 tests/i915/query.c delete mode 100644 tests/i915/selftest.c delete mode 100644 tests/i915/suspend.c diff --git a/tests/Makefile.sources b/tests/Makefile.sources index d2c4f9fe..1efd3ecb 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -472,28 +472,28 @@ TESTS_progs += gen3_render_tiledy_blits gen3_render_tiledy_blits_SOURCES = i915/gen3_render_tiledy_blits.c TESTS_progs += i915_fb_tiling -i915_fb_tiling_SOURCES = i915/fb_tiling.c +i915_fb_tiling_SOURCES = i915/i915_fb_tiling.c TESTS_progs += i915_getparams_basic -i915_getparams_basic_SOURCES = i915/getparams_basic.c +i915_getparams_basic_SOURCES = i915/i915_getparams_basic.c TESTS_progs += i915_hangman -i915_hangman_SOURCES = i915/hangman.c +i915_hangman_SOURCES = i915/i915_hangman.c TESTS_progs += i915_missed_irq -i915_missed_irq_SOURCES = i915/missed_irq.c +i915_missed_irq_SOURCES = i915/i915_missed_irq.c TESTS_progs += i915_module_load -i915_module_load_SOURCES = i915/module_load.c +i915_module_load_SOURCES = i915/i915_module_load.c TESTS_progs += i915_query -i915_query_SOURCES = i915/query.c +i915_query_SOURCES = i915/i915_query.c TESTS_progs += i915_selftest -i915_selftest_SOURCES = i915/selftest.c +i915_selftest_SOURCES = i915/i915_selftest.c TESTS_progs += i915_suspend -i915_suspend_SOURCES = i915/suspend.c +i915_suspend_SOURCES = i915/i915_suspend.c TESTS_progs_X = gem_concurrent_all gem_concurrent_all_SOURCES = i915/gem_concurrent_all.c diff --git a/tests/i915/fb_tiling.c b/tests/i915/fb_tiling.c deleted file mode 100644 index 7d5c3f1f..00000000 --- a/tests/i915/fb_tiling.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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. - * - */ - -#include "igt.h" - -IGT_TEST_DESCRIPTION("Object tiling must be fixed after framebuffer creation."); - -igt_simple_main -{ - int drm_fd = drm_open_driver_master(DRIVER_INTEL); - struct igt_fb fb; - int ret; - - igt_create_fb(drm_fd, 512, 512, DRM_FORMAT_XRGB8888, - LOCAL_I915_FORMAT_MOD_X_TILED, &fb); - - ret = __gem_set_tiling(drm_fd, fb.gem_handle, I915_TILING_X, fb.strides[0]); - igt_assert_eq(ret, 0); - - ret = __gem_set_tiling(drm_fd, fb.gem_handle, I915_TILING_NONE, fb.strides[0]); - igt_assert_eq(ret, -EBUSY); - - igt_remove_fb(drm_fd, &fb); - close(drm_fd); -} diff --git a/tests/i915/getparams_basic.c b/tests/i915/getparams_basic.c deleted file mode 100644 index 7cb210df..00000000 --- a/tests/i915/getparams_basic.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright © 2014 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. - * - * Authors: - * Jeff McGee - * - */ - -#include "igt.h" -#include -#include -#include -#include -#include "intel_bufmgr.h" - -IGT_TEST_DESCRIPTION("Tests the export of parameters via DRM_IOCTL_I915_GETPARAM\n"); - -int drm_fd; -int devid; - -static void -init(void) -{ - drm_fd = drm_open_driver(DRIVER_INTEL); - devid = intel_get_drm_devid(drm_fd); -} - -static void -deinit(void) -{ - close(drm_fd); -} - -#define LOCAL_I915_PARAM_SUBSLICE_TOTAL 33 -#define LOCAL_I915_PARAM_EU_TOTAL 34 - -static int -getparam(int param, int *value) -{ - drm_i915_getparam_t gp; - int ret; - - memset(&gp, 0, sizeof(gp)); - gp.value = value; - gp.param = param; - ret = drmIoctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp); - if (ret) - return -errno; - - return 0; -} - -static void -subslice_total(void) -{ - unsigned int subslice_total = 0; - int ret; - - ret = getparam(LOCAL_I915_PARAM_SUBSLICE_TOTAL, (int*)&subslice_total); - igt_skip_on_f(ret == -EINVAL && intel_gen(devid), "Interface not supported by kernel\n"); - - if (ret) { - /* - * These devices are not required to implement the - * interface. If they do not, -ENODEV must be returned. - */ - if ((intel_gen(devid) < 8) || - IS_BROADWELL(devid) || - igt_run_in_simulation()) { - igt_assert_eq(ret, -ENODEV); - igt_info("subslice total: unknown\n"); - /* - * All other devices must implement the interface, so - * fail them if we are here. - */ - } else { - igt_assert_eq(ret, 0); - } - } else { - /* - * On success, just make sure the returned count value is - * non-zero. The validity of the count value for the given - * device is not checked. - */ - igt_assert_neq(subslice_total, 0); - igt_info("subslice total: %u\n", subslice_total); - } -} - -static void -eu_total(void) -{ - unsigned int eu_total = 0; - int ret; - - ret = getparam(LOCAL_I915_PARAM_EU_TOTAL, (int*)&eu_total); - igt_skip_on_f(ret == -EINVAL, "Interface not supported by kernel\n"); - - if (ret) { - /* - * These devices are not required to implement the - * interface. If they do not, -ENODEV must be returned. - */ - if ((intel_gen(devid) < 8) || - IS_BROADWELL(devid) || - igt_run_in_simulation()) { - igt_assert_eq(ret, -ENODEV); - igt_info("EU total: unknown\n"); - /* - * All other devices must implement the interface, so - * fail them if we are here. - */ - } else { - igt_assert_eq(ret, 0); - } - } else { - /* - * On success, just make sure the returned count value is - * non-zero. The validity of the count value for the given - * device is not checked. - */ - igt_assert_neq(eu_total, 0); - igt_info("EU total: %u\n", eu_total); - } -} - -static void -exit_handler(int sig) -{ - deinit(); -} - -igt_main -{ - igt_fixture { - igt_install_exit_handler(exit_handler); - init(); - } - - igt_subtest("basic-subslice-total") - subslice_total(); - - igt_subtest("basic-eu-total") - eu_total(); -} diff --git a/tests/i915/hangman.c b/tests/i915/hangman.c deleted file mode 100644 index df1e0afe..00000000 --- a/tests/i915/hangman.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright © 2014 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. - * - * Authors: - * Mika Kuoppala - * Oscar Mateo - * - */ - -#include "igt.h" -#include -#include -#include -#include - -#include "igt_sysfs.h" -#include "igt_debugfs.h" - -#ifndef I915_PARAM_CMD_PARSER_VERSION -#define I915_PARAM_CMD_PARSER_VERSION 28 -#endif - -static int device = -1; -static int sysfs = -1; - -static bool has_error_state(int dir) -{ - bool result; - int fd; - - fd = openat(dir, "error", O_RDONLY); - if (fd < 0) - return false; - - if (read(fd, &result, sizeof(result)) < 0) - result = false; - else - result = true; - - close(fd); - return result; -} - -static void assert_entry(const char *s, bool expect) -{ - char *error; - - error = igt_sysfs_get(sysfs, "error"); - igt_assert(error); - - igt_assert_f(!!strcasecmp(error, s) != expect, - "contents of error: '%s' (expected %s '%s')\n", - error, expect ? "": "not", s); - - free(error); -} - -static void assert_error_state_clear(void) -{ - assert_entry("no error state collected", true); -} - -static void assert_error_state_collected(void) -{ - assert_entry("no error state collected", false); -} - -static void clear_error_state(void) -{ - igt_sysfs_write(sysfs, "error", "", 1); -} - -static void test_error_state_basic(void) -{ - int fd; - - clear_error_state(); - assert_error_state_clear(); - - /* Manually trigger a hang by request a reset */ - fd = igt_debugfs_open(device, "i915_wedged", O_WRONLY); - igt_ignore_warn(write(fd, "1\n", 2)); - close(fd); - - assert_error_state_collected(); - - clear_error_state(); - assert_error_state_clear(); -} - -static FILE *open_error(void) -{ - int fd; - - fd = openat(sysfs, "error", O_RDONLY); - if (fd < 0) - return NULL; - - return fdopen(fd, "r"); -} - -static bool uses_cmd_parser(void) -{ - int parser_version = 0; - drm_i915_getparam_t gp; - - gp.param = I915_PARAM_CMD_PARSER_VERSION; - gp.value = &parser_version; - drmIoctl(device, DRM_IOCTL_I915_GETPARAM, &gp); - - return parser_version > 0; -} - -static void check_error_state(const char *expected_ring_name, - uint64_t expected_offset, - const uint32_t *batch) -{ - bool cmd_parser = uses_cmd_parser(); - FILE *file = open_error(); - char *line = NULL; - size_t line_size = 0; - bool found = false; - - igt_debug("%s(expected ring name=%s, expected offset=%"PRIx64")\n", - __func__, expected_ring_name, expected_offset); - igt_debugfs_dump(device, "i915_error_state"); - - igt_assert(getline(&line, &line_size, file) != -1); - igt_assert(strcasecmp(line, "No error state collected")); - - while (getline(&line, &line_size, file) > 0) { - char *dashes; - uint32_t gtt_offset_upper, gtt_offset_lower; - int matched; - - dashes = strstr(line, "---"); - if (!dashes) - continue; - - matched = sscanf(dashes, "--- gtt_offset = 0x%08x %08x\n", - >t_offset_upper, >t_offset_lower); - if (matched) { - char expected_line[128]; - uint64_t gtt_offset; - int i; - - strncpy(expected_line, line, dashes - line); - expected_line[dashes - line - 1] = '\0'; - igt_assert(strstr(expected_line, expected_ring_name)); - - gtt_offset = gtt_offset_upper; - if (matched == 2) { - gtt_offset <<= 32; - gtt_offset |= gtt_offset_lower; - } - if (!cmd_parser) - igt_assert_eq_u64(gtt_offset, expected_offset); - - for (i = 0; i < 1024; i++) { - igt_assert(getline(&line, &line_size, file) > 0); - if (line[0] == ':' || line[0] == '~') - break; - - snprintf(expected_line, sizeof(expected_line), - "%08x : %08x", - 4*i, batch[i]); - igt_assert(strstr(line, expected_line)); - } - - found = true; - break; - } - } - - free(line); - fclose(file); - - clear_error_state(); - - igt_assert(found); -} - -static void test_error_state_capture(unsigned ring_id, - const char *ring_name) -{ - uint32_t *batch; - igt_hang_t hang; - uint64_t offset; - - clear_error_state(); - - hang = igt_hang_ctx(device, 0, ring_id, HANG_ALLOW_CAPTURE); - offset = hang.spin->obj[1].offset; - - batch = gem_mmap__cpu(device, hang.spin->handle, 0, 4096, PROT_READ); - gem_set_domain(device, hang.spin->handle, I915_GEM_DOMAIN_CPU, 0); - - igt_post_hang_ring(device, hang); - - check_error_state(ring_name, offset, batch); - munmap(batch, 4096); -} - -/* This test covers the case where we end up in an uninitialised area of the - * ppgtt and keep executing through it. This is particularly relevant if 48b - * ppgtt is enabled because the ppgtt is massively bigger compared to the 32b - * case and it takes a lot more time to wrap, so the acthd can potentially keep - * increasing for a long time - */ -static void hangcheck_unterminated(void) -{ - /* timeout needs to be greater than ~5*hangcheck */ - int64_t timeout_ns = 100ull * NSEC_PER_SEC; /* 100 seconds */ - struct drm_i915_gem_execbuffer2 execbuf; - struct drm_i915_gem_exec_object2 gem_exec; - uint32_t handle; - - igt_require(gem_uses_full_ppgtt(device)); - igt_require_hang_ring(device, 0); - - handle = gem_create(device, 4096); - - memset(&gem_exec, 0, sizeof(gem_exec)); - gem_exec.handle = handle; - - memset(&execbuf, 0, sizeof(execbuf)); - execbuf.buffers_ptr = (uintptr_t)&gem_exec; - execbuf.buffer_count = 1; - - gem_execbuf(device, &execbuf); - if (gem_wait(device, handle, &timeout_ns) != 0) { - /* need to manually trigger an hang to clean before failing */ - igt_force_gpu_reset(device); - igt_assert_f(0, "unterminated batch did not trigger an hang!"); - } -} - -igt_main -{ - const struct intel_execution_engine *e; - - igt_skip_on_simulation(); - - igt_fixture { - int idx; - - device = drm_open_driver(DRIVER_INTEL); - igt_require_gem(device); - - sysfs = igt_sysfs_open(device, &idx); - igt_assert(sysfs != -1); - - igt_require(has_error_state(sysfs)); - } - - igt_subtest("error-state-basic") - test_error_state_basic(); - - for (e = intel_execution_engines; e->name; e++) { - if (e->exec_id == 0) - continue; - - igt_subtest_f("error-state-capture-%s", e->name) { - igt_require(gem_ring_has_physical_engine(device, e->exec_id | e->flags)); - test_error_state_capture(e->exec_id | e->flags, - e->full_name); - } - } - - igt_subtest("hangcheck-unterminated") - hangcheck_unterminated(); -} diff --git a/tests/i915/i915_fb_tiling.c b/tests/i915/i915_fb_tiling.c new file mode 100644 index 00000000..7d5c3f1f --- /dev/null +++ b/tests/i915/i915_fb_tiling.c @@ -0,0 +1,46 @@ +/* + * 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. + * + */ + +#include "igt.h" + +IGT_TEST_DESCRIPTION("Object tiling must be fixed after framebuffer creation."); + +igt_simple_main +{ + int drm_fd = drm_open_driver_master(DRIVER_INTEL); + struct igt_fb fb; + int ret; + + igt_create_fb(drm_fd, 512, 512, DRM_FORMAT_XRGB8888, + LOCAL_I915_FORMAT_MOD_X_TILED, &fb); + + ret = __gem_set_tiling(drm_fd, fb.gem_handle, I915_TILING_X, fb.strides[0]); + igt_assert_eq(ret, 0); + + ret = __gem_set_tiling(drm_fd, fb.gem_handle, I915_TILING_NONE, fb.strides[0]); + igt_assert_eq(ret, -EBUSY); + + igt_remove_fb(drm_fd, &fb); + close(drm_fd); +} diff --git a/tests/i915/i915_getparams_basic.c b/tests/i915/i915_getparams_basic.c new file mode 100644 index 00000000..7cb210df --- /dev/null +++ b/tests/i915/i915_getparams_basic.c @@ -0,0 +1,164 @@ +/* + * Copyright © 2014 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. + * + * Authors: + * Jeff McGee + * + */ + +#include "igt.h" +#include +#include +#include +#include +#include "intel_bufmgr.h" + +IGT_TEST_DESCRIPTION("Tests the export of parameters via DRM_IOCTL_I915_GETPARAM\n"); + +int drm_fd; +int devid; + +static void +init(void) +{ + drm_fd = drm_open_driver(DRIVER_INTEL); + devid = intel_get_drm_devid(drm_fd); +} + +static void +deinit(void) +{ + close(drm_fd); +} + +#define LOCAL_I915_PARAM_SUBSLICE_TOTAL 33 +#define LOCAL_I915_PARAM_EU_TOTAL 34 + +static int +getparam(int param, int *value) +{ + drm_i915_getparam_t gp; + int ret; + + memset(&gp, 0, sizeof(gp)); + gp.value = value; + gp.param = param; + ret = drmIoctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp); + if (ret) + return -errno; + + return 0; +} + +static void +subslice_total(void) +{ + unsigned int subslice_total = 0; + int ret; + + ret = getparam(LOCAL_I915_PARAM_SUBSLICE_TOTAL, (int*)&subslice_total); + igt_skip_on_f(ret == -EINVAL && intel_gen(devid), "Interface not supported by kernel\n"); + + if (ret) { + /* + * These devices are not required to implement the + * interface. If they do not, -ENODEV must be returned. + */ + if ((intel_gen(devid) < 8) || + IS_BROADWELL(devid) || + igt_run_in_simulation()) { + igt_assert_eq(ret, -ENODEV); + igt_info("subslice total: unknown\n"); + /* + * All other devices must implement the interface, so + * fail them if we are here. + */ + } else { + igt_assert_eq(ret, 0); + } + } else { + /* + * On success, just make sure the returned count value is + * non-zero. The validity of the count value for the given + * device is not checked. + */ + igt_assert_neq(subslice_total, 0); + igt_info("subslice total: %u\n", subslice_total); + } +} + +static void +eu_total(void) +{ + unsigned int eu_total = 0; + int ret; + + ret = getparam(LOCAL_I915_PARAM_EU_TOTAL, (int*)&eu_total); + igt_skip_on_f(ret == -EINVAL, "Interface not supported by kernel\n"); + + if (ret) { + /* + * These devices are not required to implement the + * interface. If they do not, -ENODEV must be returned. + */ + if ((intel_gen(devid) < 8) || + IS_BROADWELL(devid) || + igt_run_in_simulation()) { + igt_assert_eq(ret, -ENODEV); + igt_info("EU total: unknown\n"); + /* + * All other devices must implement the interface, so + * fail them if we are here. + */ + } else { + igt_assert_eq(ret, 0); + } + } else { + /* + * On success, just make sure the returned count value is + * non-zero. The validity of the count value for the given + * device is not checked. + */ + igt_assert_neq(eu_total, 0); + igt_info("EU total: %u\n", eu_total); + } +} + +static void +exit_handler(int sig) +{ + deinit(); +} + +igt_main +{ + igt_fixture { + igt_install_exit_handler(exit_handler); + init(); + } + + igt_subtest("basic-subslice-total") + subslice_total(); + + igt_subtest("basic-eu-total") + eu_total(); +} diff --git a/tests/i915/i915_hangman.c b/tests/i915/i915_hangman.c new file mode 100644 index 00000000..df1e0afe --- /dev/null +++ b/tests/i915/i915_hangman.c @@ -0,0 +1,291 @@ +/* + * Copyright © 2014 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. + * + * Authors: + * Mika Kuoppala + * Oscar Mateo + * + */ + +#include "igt.h" +#include +#include +#include +#include + +#include "igt_sysfs.h" +#include "igt_debugfs.h" + +#ifndef I915_PARAM_CMD_PARSER_VERSION +#define I915_PARAM_CMD_PARSER_VERSION 28 +#endif + +static int device = -1; +static int sysfs = -1; + +static bool has_error_state(int dir) +{ + bool result; + int fd; + + fd = openat(dir, "error", O_RDONLY); + if (fd < 0) + return false; + + if (read(fd, &result, sizeof(result)) < 0) + result = false; + else + result = true; + + close(fd); + return result; +} + +static void assert_entry(const char *s, bool expect) +{ + char *error; + + error = igt_sysfs_get(sysfs, "error"); + igt_assert(error); + + igt_assert_f(!!strcasecmp(error, s) != expect, + "contents of error: '%s' (expected %s '%s')\n", + error, expect ? "": "not", s); + + free(error); +} + +static void assert_error_state_clear(void) +{ + assert_entry("no error state collected", true); +} + +static void assert_error_state_collected(void) +{ + assert_entry("no error state collected", false); +} + +static void clear_error_state(void) +{ + igt_sysfs_write(sysfs, "error", "", 1); +} + +static void test_error_state_basic(void) +{ + int fd; + + clear_error_state(); + assert_error_state_clear(); + + /* Manually trigger a hang by request a reset */ + fd = igt_debugfs_open(device, "i915_wedged", O_WRONLY); + igt_ignore_warn(write(fd, "1\n", 2)); + close(fd); + + assert_error_state_collected(); + + clear_error_state(); + assert_error_state_clear(); +} + +static FILE *open_error(void) +{ + int fd; + + fd = openat(sysfs, "error", O_RDONLY); + if (fd < 0) + return NULL; + + return fdopen(fd, "r"); +} + +static bool uses_cmd_parser(void) +{ + int parser_version = 0; + drm_i915_getparam_t gp; + + gp.param = I915_PARAM_CMD_PARSER_VERSION; + gp.value = &parser_version; + drmIoctl(device, DRM_IOCTL_I915_GETPARAM, &gp); + + return parser_version > 0; +} + +static void check_error_state(const char *expected_ring_name, + uint64_t expected_offset, + const uint32_t *batch) +{ + bool cmd_parser = uses_cmd_parser(); + FILE *file = open_error(); + char *line = NULL; + size_t line_size = 0; + bool found = false; + + igt_debug("%s(expected ring name=%s, expected offset=%"PRIx64")\n", + __func__, expected_ring_name, expected_offset); + igt_debugfs_dump(device, "i915_error_state"); + + igt_assert(getline(&line, &line_size, file) != -1); + igt_assert(strcasecmp(line, "No error state collected")); + + while (getline(&line, &line_size, file) > 0) { + char *dashes; + uint32_t gtt_offset_upper, gtt_offset_lower; + int matched; + + dashes = strstr(line, "---"); + if (!dashes) + continue; + + matched = sscanf(dashes, "--- gtt_offset = 0x%08x %08x\n", + >t_offset_upper, >t_offset_lower); + if (matched) { + char expected_line[128]; + uint64_t gtt_offset; + int i; + + strncpy(expected_line, line, dashes - line); + expected_line[dashes - line - 1] = '\0'; + igt_assert(strstr(expected_line, expected_ring_name)); + + gtt_offset = gtt_offset_upper; + if (matched == 2) { + gtt_offset <<= 32; + gtt_offset |= gtt_offset_lower; + } + if (!cmd_parser) + igt_assert_eq_u64(gtt_offset, expected_offset); + + for (i = 0; i < 1024; i++) { + igt_assert(getline(&line, &line_size, file) > 0); + if (line[0] == ':' || line[0] == '~') + break; + + snprintf(expected_line, sizeof(expected_line), + "%08x : %08x", + 4*i, batch[i]); + igt_assert(strstr(line, expected_line)); + } + + found = true; + break; + } + } + + free(line); + fclose(file); + + clear_error_state(); + + igt_assert(found); +} + +static void test_error_state_capture(unsigned ring_id, + const char *ring_name) +{ + uint32_t *batch; + igt_hang_t hang; + uint64_t offset; + + clear_error_state(); + + hang = igt_hang_ctx(device, 0, ring_id, HANG_ALLOW_CAPTURE); + offset = hang.spin->obj[1].offset; + + batch = gem_mmap__cpu(device, hang.spin->handle, 0, 4096, PROT_READ); + gem_set_domain(device, hang.spin->handle, I915_GEM_DOMAIN_CPU, 0); + + igt_post_hang_ring(device, hang); + + check_error_state(ring_name, offset, batch); + munmap(batch, 4096); +} + +/* This test covers the case where we end up in an uninitialised area of the + * ppgtt and keep executing through it. This is particularly relevant if 48b + * ppgtt is enabled because the ppgtt is massively bigger compared to the 32b + * case and it takes a lot more time to wrap, so the acthd can potentially keep + * increasing for a long time + */ +static void hangcheck_unterminated(void) +{ + /* timeout needs to be greater than ~5*hangcheck */ + int64_t timeout_ns = 100ull * NSEC_PER_SEC; /* 100 seconds */ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 gem_exec; + uint32_t handle; + + igt_require(gem_uses_full_ppgtt(device)); + igt_require_hang_ring(device, 0); + + handle = gem_create(device, 4096); + + memset(&gem_exec, 0, sizeof(gem_exec)); + gem_exec.handle = handle; + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = (uintptr_t)&gem_exec; + execbuf.buffer_count = 1; + + gem_execbuf(device, &execbuf); + if (gem_wait(device, handle, &timeout_ns) != 0) { + /* need to manually trigger an hang to clean before failing */ + igt_force_gpu_reset(device); + igt_assert_f(0, "unterminated batch did not trigger an hang!"); + } +} + +igt_main +{ + const struct intel_execution_engine *e; + + igt_skip_on_simulation(); + + igt_fixture { + int idx; + + device = drm_open_driver(DRIVER_INTEL); + igt_require_gem(device); + + sysfs = igt_sysfs_open(device, &idx); + igt_assert(sysfs != -1); + + igt_require(has_error_state(sysfs)); + } + + igt_subtest("error-state-basic") + test_error_state_basic(); + + for (e = intel_execution_engines; e->name; e++) { + if (e->exec_id == 0) + continue; + + igt_subtest_f("error-state-capture-%s", e->name) { + igt_require(gem_ring_has_physical_engine(device, e->exec_id | e->flags)); + test_error_state_capture(e->exec_id | e->flags, + e->full_name); + } + } + + igt_subtest("hangcheck-unterminated") + hangcheck_unterminated(); +} diff --git a/tests/i915/i915_missed_irq.c b/tests/i915/i915_missed_irq.c new file mode 100644 index 00000000..302da0e8 --- /dev/null +++ b/tests/i915/i915_missed_irq.c @@ -0,0 +1,165 @@ +/* + * 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 + +#include "igt.h" +#include "igt_debugfs.h" +#include "igt_dummyload.h" +#include "igt_sysfs.h" + +IGT_TEST_DESCRIPTION("Inject missed interrupts and make sure they are caught"); + +static void trigger_missed_interrupt(int fd, unsigned ring) +{ + igt_spin_t *spin = __igt_spin_batch_new(fd, .engine = ring); + uint32_t go; + int link[2]; + + igt_assert(pipe(link) == 0); + + igt_fork(child, 1) { + /* + * We are now a low priority child on the *same* CPU as the + * parent. We will have to wait for our parent to sleep + * (gem_sync -> i915_wait_request) before we run. + */ + read(link[0], &go, sizeof(go)); + igt_assert(gem_bo_busy(fd, spin->handle)); + igt_spin_batch_end(spin); + } + + write(link[1], &go, sizeof(go)); + gem_sync(fd, spin->handle); + igt_waitchildren(); + + igt_spin_batch_free(fd, spin); + close(link[1]); + close(link[0]); +} + +static void bind_to_cpu(int cpu) +{ + const int ncpus = sysconf(_SC_NPROCESSORS_ONLN); + struct sched_param rt = {.sched_priority = 99 }; + cpu_set_t allowed; + + igt_assert(sched_setscheduler(getpid(), SCHED_RR | SCHED_RESET_ON_FORK, &rt) == 0); + + CPU_ZERO(&allowed); + CPU_SET(cpu % ncpus, &allowed); + igt_assert(sched_setaffinity(getpid(), sizeof(cpu_set_t), &allowed) == 0); +} + +static void enable_missed_irq(int dir) +{ + igt_sysfs_printf(dir, "i915_ring_test_irq", "0x%x", -1); +} + +static uint32_t disable_missed_irq(int dir) +{ + uint32_t mask = 0; + + igt_sysfs_scanf(dir, "i915_ring_test_irq", "%x", &mask); + igt_sysfs_set(dir, "i915_ring_test_irq", "0"); + + return mask; +} + +static uint32_t engine_mask(int dir) +{ + enable_missed_irq(dir); + return disable_missed_irq(dir); +} + +igt_simple_main +{ + const struct intel_execution_engine *e; + unsigned expect_rings; + unsigned missed_rings; + unsigned check_rings; + int debugfs, device; + + igt_skip_on_simulation(); + bind_to_cpu(0); + + device = drm_open_driver(DRIVER_INTEL); + igt_require_gem(device); + igt_skip_on(gem_has_guc_submission(device)); /* irq forced for guc */ + gem_require_mmap_wc(device); + debugfs = igt_debugfs_dir(device); + + expect_rings = engine_mask(debugfs); + igt_require(expect_rings); + + igt_fork_hang_detector(device); + + igt_debug("Clearing rings %x\n", expect_rings); + intel_detect_and_clear_missed_interrupts(device); + for (e = intel_execution_engines; e->name; e++) { + if (expect_rings == -1 && e->exec_id) + continue; + + if (expect_rings != -1 && e->exec_id == 0) + continue; + + if (!gem_has_ring(device, e->exec_id | e->flags)) + continue; + + igt_debug("Clearing ring %s [%x]\n", + e->name, e->exec_id | e->flags); + trigger_missed_interrupt(device, e->exec_id | e->flags); + } + igt_assert_eq(intel_detect_and_clear_missed_interrupts(device), 0); + + igt_debug("Testing rings %x\n", expect_rings); + enable_missed_irq(debugfs); + for (e = intel_execution_engines; e->name; e++) { + if (expect_rings == -1 && e->exec_id) + continue; + + if (expect_rings != -1 && e->exec_id == 0) + continue; + + if (!gem_has_ring(device, e->exec_id | e->flags)) + continue; + + igt_debug("Executing on ring %s [%x]\n", + e->name, e->exec_id | e->flags); + trigger_missed_interrupt(device, e->exec_id | e->flags); + } + missed_rings = intel_detect_and_clear_missed_interrupts(device); + + check_rings = disable_missed_irq(debugfs); + igt_assert_eq_u32(check_rings, expect_rings); + + if (expect_rings == -1) + igt_assert_eq_u32(missed_rings, 1); + else + igt_assert_eq_u32(missed_rings, expect_rings); + + close(debugfs); + igt_stop_hang_detector(); + close(device); +} diff --git a/tests/i915/i915_module_load.c b/tests/i915/i915_module_load.c new file mode 100644 index 00000000..7fe83520 --- /dev/null +++ b/tests/i915/i915_module_load.c @@ -0,0 +1,369 @@ +/* + * 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_debugfs.h" +#include "igt_aux.h" +#include "igt_kmod.h" +#include "igt_sysfs.h" +#include "igt_core.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define LOCAL_I915_EXEC_BSD_SHIFT (13) +#define LOCAL_I915_EXEC_BSD_MASK (3 << LOCAL_I915_EXEC_BSD_SHIFT) + +#define ENGINE_MASK (I915_EXEC_RING_MASK | LOCAL_I915_EXEC_BSD_MASK) + +static void store_dword(int fd, unsigned ring) +{ + const int gen = intel_gen(intel_get_drm_devid(fd)); + struct drm_i915_gem_exec_object2 obj[2]; + struct drm_i915_gem_relocation_entry reloc; + struct drm_i915_gem_execbuffer2 execbuf; + uint32_t batch[16]; + int i; + + if (!gem_can_store_dword(fd, ring)) + return; + + if (!gem_has_ring(fd, ring)) + return; + + intel_detect_and_clear_missed_interrupts(fd); + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = (uintptr_t)obj; + execbuf.buffer_count = 2; + execbuf.flags = ring; + if (gen < 6) + execbuf.flags |= I915_EXEC_SECURE; + + memset(obj, 0, sizeof(obj)); + obj[0].handle = gem_create(fd, 4096); + obj[1].handle = gem_create(fd, 4096); + + memset(&reloc, 0, sizeof(reloc)); + reloc.target_handle = obj[0].handle; + reloc.presumed_offset = 0; + reloc.offset = sizeof(uint32_t); + reloc.delta = 0; + reloc.read_domains = I915_GEM_DOMAIN_INSTRUCTION; + reloc.write_domain = I915_GEM_DOMAIN_INSTRUCTION; + obj[1].relocs_ptr = (uintptr_t)&reloc; + obj[1].relocation_count = 1; + + i = 0; + batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0); + if (gen >= 8) { + batch[++i] = 0; + batch[++i] = 0; + } else if (gen >= 4) { + batch[++i] = 0; + batch[++i] = 0; + reloc.offset += sizeof(uint32_t); + } else { + batch[i]--; + batch[++i] = 0; + } + batch[++i] = 0xc0ffee; + batch[++i] = MI_BATCH_BUFFER_END; + gem_write(fd, obj[1].handle, 0, batch, sizeof(batch)); + gem_execbuf(fd, &execbuf); + gem_close(fd, obj[1].handle); + + gem_read(fd, obj[0].handle, 0, batch, sizeof(batch)); + gem_close(fd, obj[0].handle); + igt_assert_eq(*batch, 0xc0ffee); + igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0); +} + +static void store_all(int fd) +{ + const int gen = intel_gen(intel_get_drm_devid(fd)); + struct drm_i915_gem_exec_object2 obj[2]; + struct drm_i915_gem_relocation_entry reloc[32]; + struct drm_i915_gem_execbuffer2 execbuf; + unsigned engines[16], permuted[16]; + uint32_t batch[16]; + uint64_t offset; + unsigned engine, nengine; + int value; + int i, j; + + if (!gem_can_store_dword(fd, 0)) + return; + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = (uintptr_t)obj; + execbuf.buffer_count = 2; + if (gen < 6) + execbuf.flags |= I915_EXEC_SECURE; + + memset(reloc, 0, sizeof(reloc)); + memset(obj, 0, sizeof(obj)); + obj[0].handle = gem_create(fd, 4096); + obj[1].handle = gem_create(fd, 4096); + obj[1].relocation_count = 1; + + offset = sizeof(uint32_t); + i = 0; + batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0); + if (gen >= 8) { + batch[++i] = 0; + batch[++i] = 0; + } else if (gen >= 4) { + batch[++i] = 0; + batch[++i] = 0; + offset += sizeof(uint32_t); + } else { + batch[i]--; + batch[++i] = 0; + } + batch[value = ++i] = 0xc0ffee; + batch[++i] = MI_BATCH_BUFFER_END; + + nengine = 0; + intel_detect_and_clear_missed_interrupts(fd); + for_each_engine(fd, engine) { + if (!gem_can_store_dword(fd, engine)) + continue; + + igt_assert(2*(nengine+1)*sizeof(batch) <= 4096); + + execbuf.flags &= ~ENGINE_MASK; + execbuf.flags |= engine; + + j = 2*nengine; + reloc[j].target_handle = obj[0].handle; + reloc[j].presumed_offset = ~0; + reloc[j].offset = j*sizeof(batch) + offset; + reloc[j].delta = nengine*sizeof(uint32_t); + reloc[j].read_domains = I915_GEM_DOMAIN_INSTRUCTION; + reloc[j].write_domain = I915_GEM_DOMAIN_INSTRUCTION; + obj[1].relocs_ptr = (uintptr_t)&reloc[j]; + + batch[value] = 0xdeadbeef; + gem_write(fd, obj[1].handle, j*sizeof(batch), + batch, sizeof(batch)); + execbuf.batch_start_offset = j*sizeof(batch); + gem_execbuf(fd, &execbuf); + + j = 2*nengine + 1; + reloc[j].target_handle = obj[0].handle; + reloc[j].presumed_offset = ~0; + reloc[j].offset = j*sizeof(batch) + offset; + reloc[j].delta = nengine*sizeof(uint32_t); + reloc[j].read_domains = I915_GEM_DOMAIN_INSTRUCTION; + reloc[j].write_domain = I915_GEM_DOMAIN_INSTRUCTION; + obj[1].relocs_ptr = (uintptr_t)&reloc[j]; + + batch[value] = nengine; + gem_write(fd, obj[1].handle, j*sizeof(batch), + batch, sizeof(batch)); + execbuf.batch_start_offset = j*sizeof(batch); + gem_execbuf(fd, &execbuf); + + engines[nengine++] = engine; + } + gem_sync(fd, obj[1].handle); + + for (i = 0; i < nengine; i++) { + obj[1].relocs_ptr = (uintptr_t)&reloc[2*i]; + execbuf.batch_start_offset = 2*i*sizeof(batch); + memcpy(permuted, engines, nengine*sizeof(engines[0])); + igt_permute_array(permuted, nengine, igt_exchange_int); + for (j = 0; j < nengine; j++) { + execbuf.flags &= ~ENGINE_MASK; + execbuf.flags |= permuted[j]; + gem_execbuf(fd, &execbuf); + } + obj[1].relocs_ptr = (uintptr_t)&reloc[2*i+1]; + execbuf.batch_start_offset = (2*i+1)*sizeof(batch); + execbuf.flags &= ~ENGINE_MASK; + execbuf.flags |= engines[i]; + gem_execbuf(fd, &execbuf); + } + gem_close(fd, obj[1].handle); + + gem_read(fd, obj[0].handle, 0, engines, sizeof(engines)); + gem_close(fd, obj[0].handle); + + for (i = 0; i < nengine; i++) + igt_assert_eq_u32(engines[i], i); + igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0); +} + +static int open_parameters(const char *module_name) +{ + char path[256]; + + snprintf(path, sizeof(path), "/sys/module/%s/parameters", module_name); + return open(path, O_RDONLY); +} + +static int +inject_fault(const char *module_name, const char *opt, int fault) +{ + char buf[1024]; + int dir; + + igt_assert(fault > 0); + snprintf(buf, sizeof(buf), "%s=%d", opt, fault); + + if (igt_kmod_load(module_name, buf)) { + igt_warn("Failed to load module '%s' with options '%s'\n", + module_name, buf); + return 1; + } + + dir = open_parameters(module_name); + igt_sysfs_scanf(dir, opt, "%d", &fault); + close(dir); + + igt_debug("Loaded '%s %s', result=%d\n", module_name, buf, fault); + + if (strcmp(module_name, "i915")) /* XXX better ideas! */ + igt_kmod_unload(module_name, 0); + else + igt_i915_driver_unload(); + + return fault; +} + +static void +gem_sanitycheck(void) +{ + int err = 0; + int fd; + struct drm_i915_gem_caching args = {}; + + + fd = __drm_open_driver(DRIVER_INTEL); + igt_set_timeout(1, "Module reload timeout!"); + + if (ioctl(fd, DRM_IOCTL_I915_GEM_SET_CACHING, &args) < 0) + err = -errno; + + igt_set_timeout(0, NULL); + close(fd); + + igt_assert_eq(err, -ENOENT); +} + +static void +gem_exec_store(void) +{ + int fd; + const struct intel_execution_engine *e; + + fd = __drm_open_driver(DRIVER_INTEL); + igt_fork_hang_detector(fd); + + for (e = intel_execution_engines; e->name; e++) { + if (gem_can_store_dword(fd, e->exec_id | e->flags)) + store_dword(fd, e->exec_id | e->flags); + } + + store_all(fd); + + igt_stop_hang_detector(); + close(fd); +} + +static void +hda_dynamic_debug(bool enable) +{ + FILE *fp; + const char snd_hda_intel_on[] = "module snd_hda_intel +pf"; + const char snd_hda_core_on[] = "module snd_hda_core +pf"; + + const char snd_hda_intel_off[] = "module snd_hda_core =_"; + const char snd_hda_core_off[] = "module snd_hda_intel =_"; + + fp = fopen("/sys/kernel/debug/dynamic_debug/control", "w"); + if (!fp) { + igt_debug("hda dynamic debug not available\n"); + return; + } + + if (enable) { + fwrite(snd_hda_intel_on, 1, sizeof(snd_hda_intel_on), fp); + fwrite(snd_hda_core_on, 1, sizeof(snd_hda_core_on), fp); + } else { + fwrite(snd_hda_intel_off, 1, sizeof(snd_hda_intel_off), fp); + fwrite(snd_hda_core_off, 1, sizeof(snd_hda_core_off), fp); + } + + fclose(fp); +} + +igt_main +{ + igt_subtest("reload") { + int load_error; + + igt_i915_driver_unload(); + + hda_dynamic_debug(true); + load_error = igt_i915_driver_load(NULL); + hda_dynamic_debug(false); + + igt_assert_eq(load_error, 0); + + gem_sanitycheck(); + gem_exec_store(); + + /* only default modparams, can leave module loaded */ + } + + igt_subtest("reload-no-display") { + igt_i915_driver_unload(); + + igt_assert_eq(igt_i915_driver_load("disable_display=1"), 0); + + igt_i915_driver_unload(); + } + + igt_subtest("reload-with-fault-injection") { + int i = 0; + + igt_i915_driver_unload(); + + while (inject_fault("i915", "inject_load_failure", ++i) == 0) + ; + + /* We expect to hit at least one fault! */ + igt_assert(i > 1); + + /* inject_fault() leaves the module unloaded */ + } + + /* Subtests should unload the module themselves if they use modparams */ +} diff --git a/tests/i915/i915_query.c b/tests/i915/i915_query.c new file mode 100644 index 00000000..7d0c0e3a --- /dev/null +++ b/tests/i915/i915_query.c @@ -0,0 +1,536 @@ +/* + * Copyright © 2017 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_TEST_DESCRIPTION("Testing the i915 query uAPI."); + +/* + * We should at least get 3 bytes for data for each slices, subslices & EUs + * masks. + */ +#define MIN_TOPOLOGY_ITEM_SIZE (sizeof(struct drm_i915_query_topology_info) + 3) + +static int +__i915_query(int fd, struct drm_i915_query *q) +{ + if (igt_ioctl(fd, DRM_IOCTL_I915_QUERY, q)) + return -errno; + return 0; +} + +static int +__i915_query_items(int fd, struct drm_i915_query_item *items, uint32_t n_items) +{ + struct drm_i915_query q = { + .num_items = n_items, + .items_ptr = to_user_pointer(items), + }; + return __i915_query(fd, &q); +} + +#define i915_query_items(fd, items, n_items) do { \ + igt_assert_eq(__i915_query_items(fd, items, n_items), 0); \ + errno = 0; \ + } while (0) +#define i915_query_items_err(fd, items, n_items, err) do { \ + igt_assert_eq(__i915_query_items(fd, items, n_items), -err); \ + } while (0) + +static bool has_query_supports(int fd) +{ + struct drm_i915_query query = {}; + + return __i915_query(fd, &query) == 0; +} + +static void test_query_garbage(int fd) +{ + struct drm_i915_query query; + struct drm_i915_query_item item; + + /* Verify that invalid query pointers are rejected. */ + igt_assert_eq(__i915_query(fd, NULL), -EFAULT); + igt_assert_eq(__i915_query(fd, (void *) -1), -EFAULT); + + /* + * Query flags field is currently valid only if equals to 0. This might + * change in the future. + */ + memset(&query, 0, sizeof(query)); + query.flags = 42; + igt_assert_eq(__i915_query(fd, &query), -EINVAL); + + /* Test a couple of invalid pointers. */ + i915_query_items_err(fd, (void *) ULONG_MAX, 1, EFAULT); + i915_query_items_err(fd, (void *) 0, 1, EFAULT); + + /* Test the invalid query id = 0. */ + memset(&item, 0, sizeof(item)); + i915_query_items_err(fd, &item, 1, EINVAL); +} + +static void test_query_garbage_items(int fd) +{ + struct drm_i915_query_item items[2]; + struct drm_i915_query_item *items_ptr; + int i, n_items; + + /* + * Query item flags field is currently valid only if equals to 0. + * Subject to change in the future. + */ + memset(items, 0, sizeof(items)); + items[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; + items[0].flags = 42; + i915_query_items(fd, items, 1); + igt_assert_eq(items[0].length, -EINVAL); + + /* + * Test an invalid query id in the second item and verify that the first + * one is properly processed. + */ + memset(items, 0, sizeof(items)); + items[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; + items[1].query_id = ULONG_MAX; + i915_query_items(fd, items, 2); + igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items[0].length); + igt_assert_eq(items[1].length, -EINVAL); + + /* + * Test a invalid query id in the first item and verify that the second + * one is properly processed (the driver is expected to go through them + * all and place error codes in the failed items). + */ + memset(items, 0, sizeof(items)); + items[0].query_id = ULONG_MAX; + items[1].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; + i915_query_items(fd, items, 2); + igt_assert_eq(items[0].length, -EINVAL); + igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items[1].length); + + /* Test a couple of invalid data pointer in query item. */ + memset(items, 0, sizeof(items)); + items[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; + i915_query_items(fd, items, 1); + igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items[0].length); + + items[0].data_ptr = 0; + i915_query_items(fd, items, 1); + igt_assert_eq(items[0].length, -EFAULT); + + items[0].data_ptr = ULONG_MAX; + i915_query_items(fd, items, 1); + igt_assert_eq(items[0].length, -EFAULT); + + + /* Test an invalid query item length. */ + memset(items, 0, sizeof(items)); + items[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; + items[1].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; + items[1].length = sizeof(struct drm_i915_query_topology_info) - 1; + i915_query_items(fd, items, 2); + igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items[0].length); + igt_assert_eq(items[1].length, -EINVAL); + + /* + * Map memory for a query item in which the kernel is going to write the + * length of the item in the first ioctl(). Then unmap that memory and + * verify that the kernel correctly returns EFAULT as memory of the item + * has been removed from our address space. + */ + items_ptr = mmap(0, 4096, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + items_ptr[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; + i915_query_items(fd, items_ptr, 1); + igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items_ptr[0].length); + munmap(items_ptr, 4096); + i915_query_items_err(fd, items_ptr, 1, EFAULT); + + /* + * Map memory for a query item, then make it read only and verify that + * the kernel errors out with EFAULT. + */ + items_ptr = mmap(0, 4096, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + items_ptr[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; + igt_assert_eq(0, mprotect(items_ptr, 4096, PROT_READ)); + i915_query_items_err(fd, items_ptr, 1, EFAULT); + munmap(items_ptr, 4096); + + /* + * Allocate 2 pages, prepare those 2 pages with valid query items, then + * switch the second page to read only and expect an EFAULT error. + */ + items_ptr = mmap(0, 8192, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + memset(items_ptr, 0, 8192); + n_items = 8192 / sizeof(struct drm_i915_query_item); + for (i = 0; i < n_items; i++) + items_ptr[i].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; + mprotect(((uint8_t *)items_ptr) + 4096, 4096, PROT_READ); + i915_query_items_err(fd, items_ptr, n_items, EFAULT); + munmap(items_ptr, 8192); +} + +/* + * Allocate more on both sides of where the kernel is going to write and verify + * that it writes only where it's supposed to. + */ +static void test_query_topology_kernel_writes(int fd) +{ + struct drm_i915_query_item item; + struct drm_i915_query_topology_info *topo_info; + uint8_t *_topo_info; + int b, total_size; + + memset(&item, 0, sizeof(item)); + item.query_id = DRM_I915_QUERY_TOPOLOGY_INFO; + i915_query_items(fd, &item, 1); + igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, item.length); + + total_size = item.length + 2 * sizeof(*_topo_info); + _topo_info = malloc(total_size); + memset(_topo_info, 0xff, total_size); + topo_info = (struct drm_i915_query_topology_info *) (_topo_info + sizeof(*_topo_info)); + memset(topo_info, 0, item.length); + + item.data_ptr = to_user_pointer(topo_info); + i915_query_items(fd, &item, 1); + + for (b = 0; b < sizeof(*_topo_info); b++) { + igt_assert_eq(_topo_info[b], 0xff); + igt_assert_eq(_topo_info[sizeof(*_topo_info) + item.length + b], 0xff); + } +} + +static bool query_topology_supported(int fd) +{ + struct drm_i915_query_item item = { + .query_id = DRM_I915_QUERY_TOPOLOGY_INFO, + }; + + return __i915_query_items(fd, &item, 1) == 0 && item.length > 0; +} + +static void test_query_topology_unsupported(int fd) +{ + struct drm_i915_query_item item = { + .query_id = DRM_I915_QUERY_TOPOLOGY_INFO, + }; + + i915_query_items(fd, &item, 1); + igt_assert_eq(item.length, -ENODEV); +} + +static bool +slice_available(const struct drm_i915_query_topology_info *topo_info, + int s) +{ + return (topo_info->data[s / 8] >> (s % 8)) & 1; +} + +static bool +subslice_available(const struct drm_i915_query_topology_info *topo_info, + int s, int ss) +{ + return (topo_info->data[topo_info->subslice_offset + + s * topo_info->subslice_stride + + ss / 8] >> (ss % 8)) & 1; +} + +static bool +eu_available(const struct drm_i915_query_topology_info *topo_info, + int s, int ss, int eu) +{ + return (topo_info->data[topo_info->eu_offset + + (s * topo_info->max_subslices + ss) * topo_info->eu_stride + + eu / 8] >> (eu % 8)) & 1; +} + +/* + * Verify that we get coherent values between the legacy getparam slice/subslice + * masks and the new topology query. + */ +static void +test_query_topology_coherent_slice_mask(int fd) +{ + struct drm_i915_query_item item; + struct drm_i915_query_topology_info *topo_info; + drm_i915_getparam_t gp; + int slice_mask, subslice_mask; + int s, topology_slices, topology_subslices_slice0; + int32_t first_query_length; + + gp.param = I915_PARAM_SLICE_MASK; + gp.value = &slice_mask; + igt_skip_on(igt_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) != 0); + + gp.param = I915_PARAM_SUBSLICE_MASK; + gp.value = &subslice_mask; + igt_skip_on(igt_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) != 0); + + /* Slices */ + memset(&item, 0, sizeof(item)); + item.query_id = DRM_I915_QUERY_TOPOLOGY_INFO; + i915_query_items(fd, &item, 1); + /* We expect at least one byte for each slices, subslices & EUs masks. */ + igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, item.length); + first_query_length = item.length; + + topo_info = calloc(1, item.length); + + item.data_ptr = to_user_pointer(topo_info); + i915_query_items(fd, &item, 1); + /* We should get the same size once the data has been written. */ + igt_assert_eq(first_query_length, item.length); + /* We expect at least one byte for each slices, subslices & EUs masks. */ + igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, item.length); + + topology_slices = 0; + for (s = 0; s < topo_info->max_slices; s++) { + if (slice_available(topo_info, s)) + topology_slices |= 1UL << s; + } + + igt_debug("slice mask getparam=0x%x / query=0x%x\n", + slice_mask, topology_slices); + + /* These 2 should always match. */ + igt_assert_eq(slice_mask, topology_slices); + + topology_subslices_slice0 = 0; + for (s = 0; s < topo_info->max_subslices; s++) { + if (subslice_available(topo_info, 0, s)) + topology_subslices_slice0 |= 1UL << s; + } + + igt_debug("subslice mask getparam=0x%x / query=0x%x\n", + subslice_mask, topology_subslices_slice0); + + /* + * I915_PARAM_SUBSLICE_MASK returns the value for slice0, we should + * match the values for the first slice of the topology. + */ + igt_assert_eq(subslice_mask, topology_subslices_slice0); + + free(topo_info); +} + +/* + * Verify that we get same total number of EUs from getparam and topology query. + */ +static void +test_query_topology_matches_eu_total(int fd) +{ + struct drm_i915_query_item item; + struct drm_i915_query_topology_info *topo_info; + drm_i915_getparam_t gp; + int n_eus, n_eus_topology, s; + + gp.param = I915_PARAM_EU_TOTAL; + gp.value = &n_eus; + do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); + igt_debug("n_eus=%i\n", n_eus); + + memset(&item, 0, sizeof(item)); + item.query_id = DRM_I915_QUERY_TOPOLOGY_INFO; + i915_query_items(fd, &item, 1); + + topo_info = calloc(1, item.length); + + item.data_ptr = to_user_pointer(topo_info); + i915_query_items(fd, &item, 1); + + igt_debug("max_slices=%hu max_subslices=%hu max_eus_per_subslice=%hu\n", + topo_info->max_slices, topo_info->max_subslices, + topo_info->max_eus_per_subslice); + igt_debug(" subslice_offset=%hu subslice_stride=%hu\n", + topo_info->subslice_offset, topo_info->subslice_stride); + igt_debug(" eu_offset=%hu eu_stride=%hu\n", + topo_info->eu_offset, topo_info->eu_stride); + + n_eus_topology = 0; + for (s = 0; s < topo_info->max_slices; s++) { + int ss; + + igt_debug("slice%i: (%s)\n", s, + slice_available(topo_info, s) ? "available" : "fused"); + + if (!slice_available(topo_info, s)) + continue; + + for (ss = 0; ss < topo_info->max_subslices; ss++) { + int eu, n_subslice_eus = 0; + + igt_debug("\tsubslice%i: (%s)\n", ss, + subslice_available(topo_info, s, ss) ? "available" : "fused"); + + if (!subslice_available(topo_info, s, ss)) + continue; + + igt_debug("\t\teu_mask: 0b"); + for (eu = 0; eu < topo_info->max_eus_per_subslice; eu++) { + uint8_t val = eu_available(topo_info, s, ss, + topo_info->max_eus_per_subslice - 1 - eu); + igt_debug("%hhi", val); + n_subslice_eus += __builtin_popcount(val); + n_eus_topology += __builtin_popcount(val); + } + + igt_debug(" (%i)\n", n_subslice_eus); + + /* Sanity checks. */ + if (n_subslice_eus > 0) { + igt_assert(slice_available(topo_info, s)); + igt_assert(subslice_available(topo_info, s, ss)); + } + if (subslice_available(topo_info, s, ss)) { + igt_assert(slice_available(topo_info, s)); + } + } + } + + free(topo_info); + + igt_assert(n_eus_topology == n_eus); +} + +/* + * Verify some numbers on Gens that we know for sure the characteristics from + * the PCI ids. + */ +static void +test_query_topology_known_pci_ids(int fd, int devid) +{ + const struct intel_device_info *dev_info = intel_get_device_info(devid); + struct drm_i915_query_item item; + struct drm_i915_query_topology_info *topo_info; + int n_slices = 0, n_subslices = 0; + int s, ss; + + /* The GT size on some Broadwell skus is not defined, skip those. */ + igt_skip_on(dev_info->gt == 0); + + memset(&item, 0, sizeof(item)); + item.query_id = DRM_I915_QUERY_TOPOLOGY_INFO; + i915_query_items(fd, &item, 1); + + topo_info = (struct drm_i915_query_topology_info *) calloc(1, item.length); + + item.data_ptr = to_user_pointer(topo_info); + i915_query_items(fd, &item, 1); + + for (s = 0; s < topo_info->max_slices; s++) { + if (slice_available(topo_info, s)) + n_slices++; + + for (ss = 0; ss < topo_info->max_subslices; ss++) { + if (subslice_available(topo_info, s, ss)) + n_subslices++; + } + } + + igt_debug("Platform=%s GT=%u slices=%u subslices=%u\n", + dev_info->codename, dev_info->gt, n_slices, n_subslices); + + switch (dev_info->gt) { + case 1: + igt_assert_eq(n_slices, 1); + igt_assert(n_subslices == 1 || n_subslices == 2 || n_subslices == 3); + break; + case 2: + igt_assert_eq(n_slices, 1); + if (dev_info->is_haswell) + igt_assert_eq(n_subslices, 2); + else + igt_assert_eq(n_subslices, 3); + break; + case 3: + igt_assert_eq(n_slices, 2); + if (dev_info->is_haswell) + igt_assert_eq(n_subslices, 2 * 2); + else + igt_assert_eq(n_subslices, 2 * 3); + break; + case 4: + igt_assert_eq(n_slices, 3); + igt_assert_eq(n_subslices, 3 * 3); + break; + default: + igt_assert(false); + } + + free(topo_info); +} + +igt_main +{ + int fd = -1; + int devid; + + igt_fixture { + fd = drm_open_driver(DRIVER_INTEL); + igt_require(has_query_supports(fd)); + devid = intel_get_drm_devid(fd); + } + + igt_subtest("query-garbage") + test_query_garbage(fd); + + igt_subtest("query-garbage-items") { + igt_require(query_topology_supported(fd)); + test_query_garbage_items(fd); + } + + igt_subtest("query-topology-kernel-writes") { + igt_require(query_topology_supported(fd)); + test_query_topology_kernel_writes(fd); + } + + igt_subtest("query-topology-unsupported") { + igt_require(!query_topology_supported(fd)); + test_query_topology_unsupported(fd); + } + + igt_subtest("query-topology-coherent-slice-mask") { + igt_require(query_topology_supported(fd)); + test_query_topology_coherent_slice_mask(fd); + } + + igt_subtest("query-topology-matches-eu-total") { + igt_require(query_topology_supported(fd)); + test_query_topology_matches_eu_total(fd); + } + + igt_subtest("query-topology-known-pci-ids") { + igt_require(query_topology_supported(fd)); + igt_require(IS_HASWELL(devid) || IS_BROADWELL(devid) || + IS_SKYLAKE(devid) || IS_KABYLAKE(devid) || + IS_COFFEELAKE(devid)); + test_query_topology_known_pci_ids(fd, devid); + } + + igt_fixture { + close(fd); + } +} diff --git a/tests/i915/i915_selftest.c b/tests/i915/i915_selftest.c new file mode 100644 index 00000000..6d597e68 --- /dev/null +++ b/tests/i915/i915_selftest.c @@ -0,0 +1,43 @@ +/* + * 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_kmod.h" + +IGT_TEST_DESCRIPTION("Basic unit tests for i915.ko"); + +igt_main +{ + const char *env = getenv("SELFTESTS") ?: ""; + char opts[1024]; + + igt_assert(snprintf(opts, sizeof(opts), + "mock_selftests=-1 disable_display=1 st_filter=%s", + env) < sizeof(opts)); + igt_kselftests("i915", opts, NULL, "mock"); + + igt_assert(snprintf(opts, sizeof(opts), + "live_selftests=-1 disable_display=1 st_filter=%s", + env) < sizeof(opts)); + igt_kselftests("i915", opts, "live_selftests", "live"); +} diff --git a/tests/i915/i915_suspend.c b/tests/i915/i915_suspend.c new file mode 100644 index 00000000..84cb3b49 --- /dev/null +++ b/tests/i915/i915_suspend.c @@ -0,0 +1,254 @@ +/* + * Copyright © 2013, 2015 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. + * + * Authors: + * Daniel Vetter + * David Weinehall + * + */ + +#include "igt.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#define OBJECT_SIZE (16*1024*1024) + +static void +test_fence_restore(int fd, bool tiled2untiled, bool hibernate) +{ + uint32_t handle1, handle2, handle_tiled; + uint32_t *ptr1, *ptr2, *ptr_tiled; + int i; + + /* We wall the tiled object with untiled canary objects to make sure + * that we detect tile leaking in both directions. */ + handle1 = gem_create(fd, OBJECT_SIZE); + handle2 = gem_create(fd, OBJECT_SIZE); + handle_tiled = gem_create(fd, OBJECT_SIZE); + + /* Access the buffer objects in the order we want to have the laid out. */ + ptr1 = gem_mmap__gtt(fd, handle1, OBJECT_SIZE, PROT_READ | PROT_WRITE); + for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) + ptr1[i] = i; + + ptr_tiled = gem_mmap__gtt(fd, handle_tiled, OBJECT_SIZE, + PROT_READ | PROT_WRITE); + if (tiled2untiled) + gem_set_tiling(fd, handle_tiled, I915_TILING_X, 2048); + for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) + ptr_tiled[i] = i; + + ptr2 = gem_mmap__gtt(fd, handle2, OBJECT_SIZE, PROT_READ | PROT_WRITE); + for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) + ptr2[i] = i; + + if (tiled2untiled) + gem_set_tiling(fd, handle_tiled, I915_TILING_NONE, 2048); + else + gem_set_tiling(fd, handle_tiled, I915_TILING_X, 2048); + + if (hibernate) + igt_system_suspend_autoresume(SUSPEND_STATE_DISK, + SUSPEND_TEST_NONE); + else + igt_system_suspend_autoresume(SUSPEND_STATE_MEM, + SUSPEND_TEST_NONE); + + igt_info("checking the first canary object\n"); + for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) + igt_assert(ptr1[i] == i); + + igt_info("checking the second canary object\n"); + for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) + igt_assert(ptr2[i] == i); + + gem_close(fd, handle1); + gem_close(fd, handle2); + gem_close(fd, handle_tiled); + + munmap(ptr1, OBJECT_SIZE); + munmap(ptr2, OBJECT_SIZE); + munmap(ptr_tiled, OBJECT_SIZE); +} + +static void +test_debugfs_reader(bool hibernate) +{ + struct igt_helper_process reader = {}; + reader.use_SIGKILL = true; + + igt_fork_helper(&reader) { + static const char dfs_base[] = "/sys/kernel/debug/dri"; + static char tmp[1024]; + + snprintf(tmp, sizeof(tmp) - 1, + "while true; do find %s/%i/ -type f ! -path \"*/crc/*\" | xargs cat > /dev/null 2>&1; done", + dfs_base, drm_get_card()); + igt_assert(execl("/bin/sh", "sh", "-c", tmp, (char *) NULL) != -1); + } + + sleep(1); + + if (hibernate) + igt_system_suspend_autoresume(SUSPEND_STATE_DISK, + SUSPEND_TEST_NONE); + else + igt_system_suspend_autoresume(SUSPEND_STATE_MEM, + SUSPEND_TEST_NONE); + + sleep(1); + + igt_stop_helper(&reader); +} + +static void +test_sysfs_reader(bool hibernate) +{ + struct igt_helper_process reader = {}; + reader.use_SIGKILL = true; + + igt_fork_helper(&reader) { + static const char dfs_base[] = "/sys/class/drm/card"; + static char tmp[1024]; + + snprintf(tmp, sizeof(tmp) - 1, + "while true; do find %s%i*/ -type f | xargs cat > /dev/null 2>&1; done", + dfs_base, drm_get_card()); + igt_assert(execl("/bin/sh", "sh", "-c", tmp, (char *) NULL) != -1); + } + + sleep(1); + + if (hibernate) + igt_system_suspend_autoresume(SUSPEND_STATE_DISK, + SUSPEND_TEST_NONE); + else + igt_system_suspend_autoresume(SUSPEND_STATE_MEM, + SUSPEND_TEST_NONE); + + sleep(1); + + igt_stop_helper(&reader); +} + +static void +test_shrink(int fd, unsigned int mode) +{ + void *mem; + size_t size; + + gem_quiescent_gpu(fd); + intel_purge_vm_caches(fd); + + size = intel_get_total_pinnable_mem(); + igt_require(size > 64 << 20); + size -= 64 << 20; + + mem = mmap(NULL, size, PROT_READ, MAP_SHARED | MAP_ANON, -1, 0); + + intel_purge_vm_caches(fd); + + igt_debug("Locking %'zu B (%'zu MiB)\n", + size, size >> 20); + igt_assert(!mlock(mem, size)); + igt_info("Locked %'zu B (%'zu MiB)\n", + size, size >> 20); + + intel_purge_vm_caches(fd); + igt_system_suspend_autoresume(mode, SUSPEND_TEST_NONE); + + munmap(mem, size); +} + +static void +test_forcewake(int fd, bool hibernate) +{ + int fw_fd; + + fw_fd = igt_open_forcewake_handle(fd); + igt_assert_lte(0, fw_fd); + + if (hibernate) + igt_system_suspend_autoresume(SUSPEND_STATE_DISK, + SUSPEND_TEST_NONE); + else + igt_system_suspend_autoresume(SUSPEND_STATE_MEM, + SUSPEND_TEST_NONE); + + close (fw_fd); +} + +int fd; + +igt_main +{ + igt_skip_on_simulation(); + + igt_fixture + fd = drm_open_driver(DRIVER_INTEL); + + igt_subtest("fence-restore-tiled2untiled") + test_fence_restore(fd, true, false); + + igt_subtest("fence-restore-untiled") + test_fence_restore(fd, false, false); + + igt_subtest("debugfs-reader") + test_debugfs_reader(false); + + igt_subtest("sysfs-reader") + test_sysfs_reader(false); + + igt_subtest("shrink") + test_shrink(fd, SUSPEND_STATE_MEM); + + igt_subtest("forcewake") + test_forcewake(fd, false); + + igt_subtest("fence-restore-tiled2untiled-hibernate") + test_fence_restore(fd, true, true); + + igt_subtest("fence-restore-untiled-hibernate") + test_fence_restore(fd, false, true); + + igt_subtest("debugfs-reader-hibernate") + test_debugfs_reader(true); + + igt_subtest("sysfs-reader-hibernate") + test_sysfs_reader(true); + + igt_subtest("forcewake-hibernate") + test_forcewake(fd, true); + + igt_fixture + close(fd); +} diff --git a/tests/i915/missed_irq.c b/tests/i915/missed_irq.c deleted file mode 100644 index 302da0e8..00000000 --- a/tests/i915/missed_irq.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * 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 - -#include "igt.h" -#include "igt_debugfs.h" -#include "igt_dummyload.h" -#include "igt_sysfs.h" - -IGT_TEST_DESCRIPTION("Inject missed interrupts and make sure they are caught"); - -static void trigger_missed_interrupt(int fd, unsigned ring) -{ - igt_spin_t *spin = __igt_spin_batch_new(fd, .engine = ring); - uint32_t go; - int link[2]; - - igt_assert(pipe(link) == 0); - - igt_fork(child, 1) { - /* - * We are now a low priority child on the *same* CPU as the - * parent. We will have to wait for our parent to sleep - * (gem_sync -> i915_wait_request) before we run. - */ - read(link[0], &go, sizeof(go)); - igt_assert(gem_bo_busy(fd, spin->handle)); - igt_spin_batch_end(spin); - } - - write(link[1], &go, sizeof(go)); - gem_sync(fd, spin->handle); - igt_waitchildren(); - - igt_spin_batch_free(fd, spin); - close(link[1]); - close(link[0]); -} - -static void bind_to_cpu(int cpu) -{ - const int ncpus = sysconf(_SC_NPROCESSORS_ONLN); - struct sched_param rt = {.sched_priority = 99 }; - cpu_set_t allowed; - - igt_assert(sched_setscheduler(getpid(), SCHED_RR | SCHED_RESET_ON_FORK, &rt) == 0); - - CPU_ZERO(&allowed); - CPU_SET(cpu % ncpus, &allowed); - igt_assert(sched_setaffinity(getpid(), sizeof(cpu_set_t), &allowed) == 0); -} - -static void enable_missed_irq(int dir) -{ - igt_sysfs_printf(dir, "i915_ring_test_irq", "0x%x", -1); -} - -static uint32_t disable_missed_irq(int dir) -{ - uint32_t mask = 0; - - igt_sysfs_scanf(dir, "i915_ring_test_irq", "%x", &mask); - igt_sysfs_set(dir, "i915_ring_test_irq", "0"); - - return mask; -} - -static uint32_t engine_mask(int dir) -{ - enable_missed_irq(dir); - return disable_missed_irq(dir); -} - -igt_simple_main -{ - const struct intel_execution_engine *e; - unsigned expect_rings; - unsigned missed_rings; - unsigned check_rings; - int debugfs, device; - - igt_skip_on_simulation(); - bind_to_cpu(0); - - device = drm_open_driver(DRIVER_INTEL); - igt_require_gem(device); - igt_skip_on(gem_has_guc_submission(device)); /* irq forced for guc */ - gem_require_mmap_wc(device); - debugfs = igt_debugfs_dir(device); - - expect_rings = engine_mask(debugfs); - igt_require(expect_rings); - - igt_fork_hang_detector(device); - - igt_debug("Clearing rings %x\n", expect_rings); - intel_detect_and_clear_missed_interrupts(device); - for (e = intel_execution_engines; e->name; e++) { - if (expect_rings == -1 && e->exec_id) - continue; - - if (expect_rings != -1 && e->exec_id == 0) - continue; - - if (!gem_has_ring(device, e->exec_id | e->flags)) - continue; - - igt_debug("Clearing ring %s [%x]\n", - e->name, e->exec_id | e->flags); - trigger_missed_interrupt(device, e->exec_id | e->flags); - } - igt_assert_eq(intel_detect_and_clear_missed_interrupts(device), 0); - - igt_debug("Testing rings %x\n", expect_rings); - enable_missed_irq(debugfs); - for (e = intel_execution_engines; e->name; e++) { - if (expect_rings == -1 && e->exec_id) - continue; - - if (expect_rings != -1 && e->exec_id == 0) - continue; - - if (!gem_has_ring(device, e->exec_id | e->flags)) - continue; - - igt_debug("Executing on ring %s [%x]\n", - e->name, e->exec_id | e->flags); - trigger_missed_interrupt(device, e->exec_id | e->flags); - } - missed_rings = intel_detect_and_clear_missed_interrupts(device); - - check_rings = disable_missed_irq(debugfs); - igt_assert_eq_u32(check_rings, expect_rings); - - if (expect_rings == -1) - igt_assert_eq_u32(missed_rings, 1); - else - igt_assert_eq_u32(missed_rings, expect_rings); - - close(debugfs); - igt_stop_hang_detector(); - close(device); -} diff --git a/tests/i915/module_load.c b/tests/i915/module_load.c deleted file mode 100644 index 7fe83520..00000000 --- a/tests/i915/module_load.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * 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_debugfs.h" -#include "igt_aux.h" -#include "igt_kmod.h" -#include "igt_sysfs.h" -#include "igt_core.h" - -#include -#include -#include -#include -#include -#include -#include -#include - - -#define LOCAL_I915_EXEC_BSD_SHIFT (13) -#define LOCAL_I915_EXEC_BSD_MASK (3 << LOCAL_I915_EXEC_BSD_SHIFT) - -#define ENGINE_MASK (I915_EXEC_RING_MASK | LOCAL_I915_EXEC_BSD_MASK) - -static void store_dword(int fd, unsigned ring) -{ - const int gen = intel_gen(intel_get_drm_devid(fd)); - struct drm_i915_gem_exec_object2 obj[2]; - struct drm_i915_gem_relocation_entry reloc; - struct drm_i915_gem_execbuffer2 execbuf; - uint32_t batch[16]; - int i; - - if (!gem_can_store_dword(fd, ring)) - return; - - if (!gem_has_ring(fd, ring)) - return; - - intel_detect_and_clear_missed_interrupts(fd); - memset(&execbuf, 0, sizeof(execbuf)); - execbuf.buffers_ptr = (uintptr_t)obj; - execbuf.buffer_count = 2; - execbuf.flags = ring; - if (gen < 6) - execbuf.flags |= I915_EXEC_SECURE; - - memset(obj, 0, sizeof(obj)); - obj[0].handle = gem_create(fd, 4096); - obj[1].handle = gem_create(fd, 4096); - - memset(&reloc, 0, sizeof(reloc)); - reloc.target_handle = obj[0].handle; - reloc.presumed_offset = 0; - reloc.offset = sizeof(uint32_t); - reloc.delta = 0; - reloc.read_domains = I915_GEM_DOMAIN_INSTRUCTION; - reloc.write_domain = I915_GEM_DOMAIN_INSTRUCTION; - obj[1].relocs_ptr = (uintptr_t)&reloc; - obj[1].relocation_count = 1; - - i = 0; - batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0); - if (gen >= 8) { - batch[++i] = 0; - batch[++i] = 0; - } else if (gen >= 4) { - batch[++i] = 0; - batch[++i] = 0; - reloc.offset += sizeof(uint32_t); - } else { - batch[i]--; - batch[++i] = 0; - } - batch[++i] = 0xc0ffee; - batch[++i] = MI_BATCH_BUFFER_END; - gem_write(fd, obj[1].handle, 0, batch, sizeof(batch)); - gem_execbuf(fd, &execbuf); - gem_close(fd, obj[1].handle); - - gem_read(fd, obj[0].handle, 0, batch, sizeof(batch)); - gem_close(fd, obj[0].handle); - igt_assert_eq(*batch, 0xc0ffee); - igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0); -} - -static void store_all(int fd) -{ - const int gen = intel_gen(intel_get_drm_devid(fd)); - struct drm_i915_gem_exec_object2 obj[2]; - struct drm_i915_gem_relocation_entry reloc[32]; - struct drm_i915_gem_execbuffer2 execbuf; - unsigned engines[16], permuted[16]; - uint32_t batch[16]; - uint64_t offset; - unsigned engine, nengine; - int value; - int i, j; - - if (!gem_can_store_dword(fd, 0)) - return; - - memset(&execbuf, 0, sizeof(execbuf)); - execbuf.buffers_ptr = (uintptr_t)obj; - execbuf.buffer_count = 2; - if (gen < 6) - execbuf.flags |= I915_EXEC_SECURE; - - memset(reloc, 0, sizeof(reloc)); - memset(obj, 0, sizeof(obj)); - obj[0].handle = gem_create(fd, 4096); - obj[1].handle = gem_create(fd, 4096); - obj[1].relocation_count = 1; - - offset = sizeof(uint32_t); - i = 0; - batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0); - if (gen >= 8) { - batch[++i] = 0; - batch[++i] = 0; - } else if (gen >= 4) { - batch[++i] = 0; - batch[++i] = 0; - offset += sizeof(uint32_t); - } else { - batch[i]--; - batch[++i] = 0; - } - batch[value = ++i] = 0xc0ffee; - batch[++i] = MI_BATCH_BUFFER_END; - - nengine = 0; - intel_detect_and_clear_missed_interrupts(fd); - for_each_engine(fd, engine) { - if (!gem_can_store_dword(fd, engine)) - continue; - - igt_assert(2*(nengine+1)*sizeof(batch) <= 4096); - - execbuf.flags &= ~ENGINE_MASK; - execbuf.flags |= engine; - - j = 2*nengine; - reloc[j].target_handle = obj[0].handle; - reloc[j].presumed_offset = ~0; - reloc[j].offset = j*sizeof(batch) + offset; - reloc[j].delta = nengine*sizeof(uint32_t); - reloc[j].read_domains = I915_GEM_DOMAIN_INSTRUCTION; - reloc[j].write_domain = I915_GEM_DOMAIN_INSTRUCTION; - obj[1].relocs_ptr = (uintptr_t)&reloc[j]; - - batch[value] = 0xdeadbeef; - gem_write(fd, obj[1].handle, j*sizeof(batch), - batch, sizeof(batch)); - execbuf.batch_start_offset = j*sizeof(batch); - gem_execbuf(fd, &execbuf); - - j = 2*nengine + 1; - reloc[j].target_handle = obj[0].handle; - reloc[j].presumed_offset = ~0; - reloc[j].offset = j*sizeof(batch) + offset; - reloc[j].delta = nengine*sizeof(uint32_t); - reloc[j].read_domains = I915_GEM_DOMAIN_INSTRUCTION; - reloc[j].write_domain = I915_GEM_DOMAIN_INSTRUCTION; - obj[1].relocs_ptr = (uintptr_t)&reloc[j]; - - batch[value] = nengine; - gem_write(fd, obj[1].handle, j*sizeof(batch), - batch, sizeof(batch)); - execbuf.batch_start_offset = j*sizeof(batch); - gem_execbuf(fd, &execbuf); - - engines[nengine++] = engine; - } - gem_sync(fd, obj[1].handle); - - for (i = 0; i < nengine; i++) { - obj[1].relocs_ptr = (uintptr_t)&reloc[2*i]; - execbuf.batch_start_offset = 2*i*sizeof(batch); - memcpy(permuted, engines, nengine*sizeof(engines[0])); - igt_permute_array(permuted, nengine, igt_exchange_int); - for (j = 0; j < nengine; j++) { - execbuf.flags &= ~ENGINE_MASK; - execbuf.flags |= permuted[j]; - gem_execbuf(fd, &execbuf); - } - obj[1].relocs_ptr = (uintptr_t)&reloc[2*i+1]; - execbuf.batch_start_offset = (2*i+1)*sizeof(batch); - execbuf.flags &= ~ENGINE_MASK; - execbuf.flags |= engines[i]; - gem_execbuf(fd, &execbuf); - } - gem_close(fd, obj[1].handle); - - gem_read(fd, obj[0].handle, 0, engines, sizeof(engines)); - gem_close(fd, obj[0].handle); - - for (i = 0; i < nengine; i++) - igt_assert_eq_u32(engines[i], i); - igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0); -} - -static int open_parameters(const char *module_name) -{ - char path[256]; - - snprintf(path, sizeof(path), "/sys/module/%s/parameters", module_name); - return open(path, O_RDONLY); -} - -static int -inject_fault(const char *module_name, const char *opt, int fault) -{ - char buf[1024]; - int dir; - - igt_assert(fault > 0); - snprintf(buf, sizeof(buf), "%s=%d", opt, fault); - - if (igt_kmod_load(module_name, buf)) { - igt_warn("Failed to load module '%s' with options '%s'\n", - module_name, buf); - return 1; - } - - dir = open_parameters(module_name); - igt_sysfs_scanf(dir, opt, "%d", &fault); - close(dir); - - igt_debug("Loaded '%s %s', result=%d\n", module_name, buf, fault); - - if (strcmp(module_name, "i915")) /* XXX better ideas! */ - igt_kmod_unload(module_name, 0); - else - igt_i915_driver_unload(); - - return fault; -} - -static void -gem_sanitycheck(void) -{ - int err = 0; - int fd; - struct drm_i915_gem_caching args = {}; - - - fd = __drm_open_driver(DRIVER_INTEL); - igt_set_timeout(1, "Module reload timeout!"); - - if (ioctl(fd, DRM_IOCTL_I915_GEM_SET_CACHING, &args) < 0) - err = -errno; - - igt_set_timeout(0, NULL); - close(fd); - - igt_assert_eq(err, -ENOENT); -} - -static void -gem_exec_store(void) -{ - int fd; - const struct intel_execution_engine *e; - - fd = __drm_open_driver(DRIVER_INTEL); - igt_fork_hang_detector(fd); - - for (e = intel_execution_engines; e->name; e++) { - if (gem_can_store_dword(fd, e->exec_id | e->flags)) - store_dword(fd, e->exec_id | e->flags); - } - - store_all(fd); - - igt_stop_hang_detector(); - close(fd); -} - -static void -hda_dynamic_debug(bool enable) -{ - FILE *fp; - const char snd_hda_intel_on[] = "module snd_hda_intel +pf"; - const char snd_hda_core_on[] = "module snd_hda_core +pf"; - - const char snd_hda_intel_off[] = "module snd_hda_core =_"; - const char snd_hda_core_off[] = "module snd_hda_intel =_"; - - fp = fopen("/sys/kernel/debug/dynamic_debug/control", "w"); - if (!fp) { - igt_debug("hda dynamic debug not available\n"); - return; - } - - if (enable) { - fwrite(snd_hda_intel_on, 1, sizeof(snd_hda_intel_on), fp); - fwrite(snd_hda_core_on, 1, sizeof(snd_hda_core_on), fp); - } else { - fwrite(snd_hda_intel_off, 1, sizeof(snd_hda_intel_off), fp); - fwrite(snd_hda_core_off, 1, sizeof(snd_hda_core_off), fp); - } - - fclose(fp); -} - -igt_main -{ - igt_subtest("reload") { - int load_error; - - igt_i915_driver_unload(); - - hda_dynamic_debug(true); - load_error = igt_i915_driver_load(NULL); - hda_dynamic_debug(false); - - igt_assert_eq(load_error, 0); - - gem_sanitycheck(); - gem_exec_store(); - - /* only default modparams, can leave module loaded */ - } - - igt_subtest("reload-no-display") { - igt_i915_driver_unload(); - - igt_assert_eq(igt_i915_driver_load("disable_display=1"), 0); - - igt_i915_driver_unload(); - } - - igt_subtest("reload-with-fault-injection") { - int i = 0; - - igt_i915_driver_unload(); - - while (inject_fault("i915", "inject_load_failure", ++i) == 0) - ; - - /* We expect to hit at least one fault! */ - igt_assert(i > 1); - - /* inject_fault() leaves the module unloaded */ - } - - /* Subtests should unload the module themselves if they use modparams */ -} diff --git a/tests/i915/query.c b/tests/i915/query.c deleted file mode 100644 index 7d0c0e3a..00000000 --- a/tests/i915/query.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright © 2017 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_TEST_DESCRIPTION("Testing the i915 query uAPI."); - -/* - * We should at least get 3 bytes for data for each slices, subslices & EUs - * masks. - */ -#define MIN_TOPOLOGY_ITEM_SIZE (sizeof(struct drm_i915_query_topology_info) + 3) - -static int -__i915_query(int fd, struct drm_i915_query *q) -{ - if (igt_ioctl(fd, DRM_IOCTL_I915_QUERY, q)) - return -errno; - return 0; -} - -static int -__i915_query_items(int fd, struct drm_i915_query_item *items, uint32_t n_items) -{ - struct drm_i915_query q = { - .num_items = n_items, - .items_ptr = to_user_pointer(items), - }; - return __i915_query(fd, &q); -} - -#define i915_query_items(fd, items, n_items) do { \ - igt_assert_eq(__i915_query_items(fd, items, n_items), 0); \ - errno = 0; \ - } while (0) -#define i915_query_items_err(fd, items, n_items, err) do { \ - igt_assert_eq(__i915_query_items(fd, items, n_items), -err); \ - } while (0) - -static bool has_query_supports(int fd) -{ - struct drm_i915_query query = {}; - - return __i915_query(fd, &query) == 0; -} - -static void test_query_garbage(int fd) -{ - struct drm_i915_query query; - struct drm_i915_query_item item; - - /* Verify that invalid query pointers are rejected. */ - igt_assert_eq(__i915_query(fd, NULL), -EFAULT); - igt_assert_eq(__i915_query(fd, (void *) -1), -EFAULT); - - /* - * Query flags field is currently valid only if equals to 0. This might - * change in the future. - */ - memset(&query, 0, sizeof(query)); - query.flags = 42; - igt_assert_eq(__i915_query(fd, &query), -EINVAL); - - /* Test a couple of invalid pointers. */ - i915_query_items_err(fd, (void *) ULONG_MAX, 1, EFAULT); - i915_query_items_err(fd, (void *) 0, 1, EFAULT); - - /* Test the invalid query id = 0. */ - memset(&item, 0, sizeof(item)); - i915_query_items_err(fd, &item, 1, EINVAL); -} - -static void test_query_garbage_items(int fd) -{ - struct drm_i915_query_item items[2]; - struct drm_i915_query_item *items_ptr; - int i, n_items; - - /* - * Query item flags field is currently valid only if equals to 0. - * Subject to change in the future. - */ - memset(items, 0, sizeof(items)); - items[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; - items[0].flags = 42; - i915_query_items(fd, items, 1); - igt_assert_eq(items[0].length, -EINVAL); - - /* - * Test an invalid query id in the second item and verify that the first - * one is properly processed. - */ - memset(items, 0, sizeof(items)); - items[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; - items[1].query_id = ULONG_MAX; - i915_query_items(fd, items, 2); - igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items[0].length); - igt_assert_eq(items[1].length, -EINVAL); - - /* - * Test a invalid query id in the first item and verify that the second - * one is properly processed (the driver is expected to go through them - * all and place error codes in the failed items). - */ - memset(items, 0, sizeof(items)); - items[0].query_id = ULONG_MAX; - items[1].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; - i915_query_items(fd, items, 2); - igt_assert_eq(items[0].length, -EINVAL); - igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items[1].length); - - /* Test a couple of invalid data pointer in query item. */ - memset(items, 0, sizeof(items)); - items[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; - i915_query_items(fd, items, 1); - igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items[0].length); - - items[0].data_ptr = 0; - i915_query_items(fd, items, 1); - igt_assert_eq(items[0].length, -EFAULT); - - items[0].data_ptr = ULONG_MAX; - i915_query_items(fd, items, 1); - igt_assert_eq(items[0].length, -EFAULT); - - - /* Test an invalid query item length. */ - memset(items, 0, sizeof(items)); - items[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; - items[1].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; - items[1].length = sizeof(struct drm_i915_query_topology_info) - 1; - i915_query_items(fd, items, 2); - igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items[0].length); - igt_assert_eq(items[1].length, -EINVAL); - - /* - * Map memory for a query item in which the kernel is going to write the - * length of the item in the first ioctl(). Then unmap that memory and - * verify that the kernel correctly returns EFAULT as memory of the item - * has been removed from our address space. - */ - items_ptr = mmap(0, 4096, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); - items_ptr[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; - i915_query_items(fd, items_ptr, 1); - igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items_ptr[0].length); - munmap(items_ptr, 4096); - i915_query_items_err(fd, items_ptr, 1, EFAULT); - - /* - * Map memory for a query item, then make it read only and verify that - * the kernel errors out with EFAULT. - */ - items_ptr = mmap(0, 4096, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); - items_ptr[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; - igt_assert_eq(0, mprotect(items_ptr, 4096, PROT_READ)); - i915_query_items_err(fd, items_ptr, 1, EFAULT); - munmap(items_ptr, 4096); - - /* - * Allocate 2 pages, prepare those 2 pages with valid query items, then - * switch the second page to read only and expect an EFAULT error. - */ - items_ptr = mmap(0, 8192, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); - memset(items_ptr, 0, 8192); - n_items = 8192 / sizeof(struct drm_i915_query_item); - for (i = 0; i < n_items; i++) - items_ptr[i].query_id = DRM_I915_QUERY_TOPOLOGY_INFO; - mprotect(((uint8_t *)items_ptr) + 4096, 4096, PROT_READ); - i915_query_items_err(fd, items_ptr, n_items, EFAULT); - munmap(items_ptr, 8192); -} - -/* - * Allocate more on both sides of where the kernel is going to write and verify - * that it writes only where it's supposed to. - */ -static void test_query_topology_kernel_writes(int fd) -{ - struct drm_i915_query_item item; - struct drm_i915_query_topology_info *topo_info; - uint8_t *_topo_info; - int b, total_size; - - memset(&item, 0, sizeof(item)); - item.query_id = DRM_I915_QUERY_TOPOLOGY_INFO; - i915_query_items(fd, &item, 1); - igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, item.length); - - total_size = item.length + 2 * sizeof(*_topo_info); - _topo_info = malloc(total_size); - memset(_topo_info, 0xff, total_size); - topo_info = (struct drm_i915_query_topology_info *) (_topo_info + sizeof(*_topo_info)); - memset(topo_info, 0, item.length); - - item.data_ptr = to_user_pointer(topo_info); - i915_query_items(fd, &item, 1); - - for (b = 0; b < sizeof(*_topo_info); b++) { - igt_assert_eq(_topo_info[b], 0xff); - igt_assert_eq(_topo_info[sizeof(*_topo_info) + item.length + b], 0xff); - } -} - -static bool query_topology_supported(int fd) -{ - struct drm_i915_query_item item = { - .query_id = DRM_I915_QUERY_TOPOLOGY_INFO, - }; - - return __i915_query_items(fd, &item, 1) == 0 && item.length > 0; -} - -static void test_query_topology_unsupported(int fd) -{ - struct drm_i915_query_item item = { - .query_id = DRM_I915_QUERY_TOPOLOGY_INFO, - }; - - i915_query_items(fd, &item, 1); - igt_assert_eq(item.length, -ENODEV); -} - -static bool -slice_available(const struct drm_i915_query_topology_info *topo_info, - int s) -{ - return (topo_info->data[s / 8] >> (s % 8)) & 1; -} - -static bool -subslice_available(const struct drm_i915_query_topology_info *topo_info, - int s, int ss) -{ - return (topo_info->data[topo_info->subslice_offset + - s * topo_info->subslice_stride + - ss / 8] >> (ss % 8)) & 1; -} - -static bool -eu_available(const struct drm_i915_query_topology_info *topo_info, - int s, int ss, int eu) -{ - return (topo_info->data[topo_info->eu_offset + - (s * topo_info->max_subslices + ss) * topo_info->eu_stride + - eu / 8] >> (eu % 8)) & 1; -} - -/* - * Verify that we get coherent values between the legacy getparam slice/subslice - * masks and the new topology query. - */ -static void -test_query_topology_coherent_slice_mask(int fd) -{ - struct drm_i915_query_item item; - struct drm_i915_query_topology_info *topo_info; - drm_i915_getparam_t gp; - int slice_mask, subslice_mask; - int s, topology_slices, topology_subslices_slice0; - int32_t first_query_length; - - gp.param = I915_PARAM_SLICE_MASK; - gp.value = &slice_mask; - igt_skip_on(igt_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) != 0); - - gp.param = I915_PARAM_SUBSLICE_MASK; - gp.value = &subslice_mask; - igt_skip_on(igt_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) != 0); - - /* Slices */ - memset(&item, 0, sizeof(item)); - item.query_id = DRM_I915_QUERY_TOPOLOGY_INFO; - i915_query_items(fd, &item, 1); - /* We expect at least one byte for each slices, subslices & EUs masks. */ - igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, item.length); - first_query_length = item.length; - - topo_info = calloc(1, item.length); - - item.data_ptr = to_user_pointer(topo_info); - i915_query_items(fd, &item, 1); - /* We should get the same size once the data has been written. */ - igt_assert_eq(first_query_length, item.length); - /* We expect at least one byte for each slices, subslices & EUs masks. */ - igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, item.length); - - topology_slices = 0; - for (s = 0; s < topo_info->max_slices; s++) { - if (slice_available(topo_info, s)) - topology_slices |= 1UL << s; - } - - igt_debug("slice mask getparam=0x%x / query=0x%x\n", - slice_mask, topology_slices); - - /* These 2 should always match. */ - igt_assert_eq(slice_mask, topology_slices); - - topology_subslices_slice0 = 0; - for (s = 0; s < topo_info->max_subslices; s++) { - if (subslice_available(topo_info, 0, s)) - topology_subslices_slice0 |= 1UL << s; - } - - igt_debug("subslice mask getparam=0x%x / query=0x%x\n", - subslice_mask, topology_subslices_slice0); - - /* - * I915_PARAM_SUBSLICE_MASK returns the value for slice0, we should - * match the values for the first slice of the topology. - */ - igt_assert_eq(subslice_mask, topology_subslices_slice0); - - free(topo_info); -} - -/* - * Verify that we get same total number of EUs from getparam and topology query. - */ -static void -test_query_topology_matches_eu_total(int fd) -{ - struct drm_i915_query_item item; - struct drm_i915_query_topology_info *topo_info; - drm_i915_getparam_t gp; - int n_eus, n_eus_topology, s; - - gp.param = I915_PARAM_EU_TOTAL; - gp.value = &n_eus; - do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); - igt_debug("n_eus=%i\n", n_eus); - - memset(&item, 0, sizeof(item)); - item.query_id = DRM_I915_QUERY_TOPOLOGY_INFO; - i915_query_items(fd, &item, 1); - - topo_info = calloc(1, item.length); - - item.data_ptr = to_user_pointer(topo_info); - i915_query_items(fd, &item, 1); - - igt_debug("max_slices=%hu max_subslices=%hu max_eus_per_subslice=%hu\n", - topo_info->max_slices, topo_info->max_subslices, - topo_info->max_eus_per_subslice); - igt_debug(" subslice_offset=%hu subslice_stride=%hu\n", - topo_info->subslice_offset, topo_info->subslice_stride); - igt_debug(" eu_offset=%hu eu_stride=%hu\n", - topo_info->eu_offset, topo_info->eu_stride); - - n_eus_topology = 0; - for (s = 0; s < topo_info->max_slices; s++) { - int ss; - - igt_debug("slice%i: (%s)\n", s, - slice_available(topo_info, s) ? "available" : "fused"); - - if (!slice_available(topo_info, s)) - continue; - - for (ss = 0; ss < topo_info->max_subslices; ss++) { - int eu, n_subslice_eus = 0; - - igt_debug("\tsubslice%i: (%s)\n", ss, - subslice_available(topo_info, s, ss) ? "available" : "fused"); - - if (!subslice_available(topo_info, s, ss)) - continue; - - igt_debug("\t\teu_mask: 0b"); - for (eu = 0; eu < topo_info->max_eus_per_subslice; eu++) { - uint8_t val = eu_available(topo_info, s, ss, - topo_info->max_eus_per_subslice - 1 - eu); - igt_debug("%hhi", val); - n_subslice_eus += __builtin_popcount(val); - n_eus_topology += __builtin_popcount(val); - } - - igt_debug(" (%i)\n", n_subslice_eus); - - /* Sanity checks. */ - if (n_subslice_eus > 0) { - igt_assert(slice_available(topo_info, s)); - igt_assert(subslice_available(topo_info, s, ss)); - } - if (subslice_available(topo_info, s, ss)) { - igt_assert(slice_available(topo_info, s)); - } - } - } - - free(topo_info); - - igt_assert(n_eus_topology == n_eus); -} - -/* - * Verify some numbers on Gens that we know for sure the characteristics from - * the PCI ids. - */ -static void -test_query_topology_known_pci_ids(int fd, int devid) -{ - const struct intel_device_info *dev_info = intel_get_device_info(devid); - struct drm_i915_query_item item; - struct drm_i915_query_topology_info *topo_info; - int n_slices = 0, n_subslices = 0; - int s, ss; - - /* The GT size on some Broadwell skus is not defined, skip those. */ - igt_skip_on(dev_info->gt == 0); - - memset(&item, 0, sizeof(item)); - item.query_id = DRM_I915_QUERY_TOPOLOGY_INFO; - i915_query_items(fd, &item, 1); - - topo_info = (struct drm_i915_query_topology_info *) calloc(1, item.length); - - item.data_ptr = to_user_pointer(topo_info); - i915_query_items(fd, &item, 1); - - for (s = 0; s < topo_info->max_slices; s++) { - if (slice_available(topo_info, s)) - n_slices++; - - for (ss = 0; ss < topo_info->max_subslices; ss++) { - if (subslice_available(topo_info, s, ss)) - n_subslices++; - } - } - - igt_debug("Platform=%s GT=%u slices=%u subslices=%u\n", - dev_info->codename, dev_info->gt, n_slices, n_subslices); - - switch (dev_info->gt) { - case 1: - igt_assert_eq(n_slices, 1); - igt_assert(n_subslices == 1 || n_subslices == 2 || n_subslices == 3); - break; - case 2: - igt_assert_eq(n_slices, 1); - if (dev_info->is_haswell) - igt_assert_eq(n_subslices, 2); - else - igt_assert_eq(n_subslices, 3); - break; - case 3: - igt_assert_eq(n_slices, 2); - if (dev_info->is_haswell) - igt_assert_eq(n_subslices, 2 * 2); - else - igt_assert_eq(n_subslices, 2 * 3); - break; - case 4: - igt_assert_eq(n_slices, 3); - igt_assert_eq(n_subslices, 3 * 3); - break; - default: - igt_assert(false); - } - - free(topo_info); -} - -igt_main -{ - int fd = -1; - int devid; - - igt_fixture { - fd = drm_open_driver(DRIVER_INTEL); - igt_require(has_query_supports(fd)); - devid = intel_get_drm_devid(fd); - } - - igt_subtest("query-garbage") - test_query_garbage(fd); - - igt_subtest("query-garbage-items") { - igt_require(query_topology_supported(fd)); - test_query_garbage_items(fd); - } - - igt_subtest("query-topology-kernel-writes") { - igt_require(query_topology_supported(fd)); - test_query_topology_kernel_writes(fd); - } - - igt_subtest("query-topology-unsupported") { - igt_require(!query_topology_supported(fd)); - test_query_topology_unsupported(fd); - } - - igt_subtest("query-topology-coherent-slice-mask") { - igt_require(query_topology_supported(fd)); - test_query_topology_coherent_slice_mask(fd); - } - - igt_subtest("query-topology-matches-eu-total") { - igt_require(query_topology_supported(fd)); - test_query_topology_matches_eu_total(fd); - } - - igt_subtest("query-topology-known-pci-ids") { - igt_require(query_topology_supported(fd)); - igt_require(IS_HASWELL(devid) || IS_BROADWELL(devid) || - IS_SKYLAKE(devid) || IS_KABYLAKE(devid) || - IS_COFFEELAKE(devid)); - test_query_topology_known_pci_ids(fd, devid); - } - - igt_fixture { - close(fd); - } -} diff --git a/tests/i915/selftest.c b/tests/i915/selftest.c deleted file mode 100644 index 6d597e68..00000000 --- a/tests/i915/selftest.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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_kmod.h" - -IGT_TEST_DESCRIPTION("Basic unit tests for i915.ko"); - -igt_main -{ - const char *env = getenv("SELFTESTS") ?: ""; - char opts[1024]; - - igt_assert(snprintf(opts, sizeof(opts), - "mock_selftests=-1 disable_display=1 st_filter=%s", - env) < sizeof(opts)); - igt_kselftests("i915", opts, NULL, "mock"); - - igt_assert(snprintf(opts, sizeof(opts), - "live_selftests=-1 disable_display=1 st_filter=%s", - env) < sizeof(opts)); - igt_kselftests("i915", opts, "live_selftests", "live"); -} diff --git a/tests/i915/suspend.c b/tests/i915/suspend.c deleted file mode 100644 index 84cb3b49..00000000 --- a/tests/i915/suspend.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright © 2013, 2015 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. - * - * Authors: - * Daniel Vetter - * David Weinehall - * - */ - -#include "igt.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - -#define OBJECT_SIZE (16*1024*1024) - -static void -test_fence_restore(int fd, bool tiled2untiled, bool hibernate) -{ - uint32_t handle1, handle2, handle_tiled; - uint32_t *ptr1, *ptr2, *ptr_tiled; - int i; - - /* We wall the tiled object with untiled canary objects to make sure - * that we detect tile leaking in both directions. */ - handle1 = gem_create(fd, OBJECT_SIZE); - handle2 = gem_create(fd, OBJECT_SIZE); - handle_tiled = gem_create(fd, OBJECT_SIZE); - - /* Access the buffer objects in the order we want to have the laid out. */ - ptr1 = gem_mmap__gtt(fd, handle1, OBJECT_SIZE, PROT_READ | PROT_WRITE); - for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) - ptr1[i] = i; - - ptr_tiled = gem_mmap__gtt(fd, handle_tiled, OBJECT_SIZE, - PROT_READ | PROT_WRITE); - if (tiled2untiled) - gem_set_tiling(fd, handle_tiled, I915_TILING_X, 2048); - for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) - ptr_tiled[i] = i; - - ptr2 = gem_mmap__gtt(fd, handle2, OBJECT_SIZE, PROT_READ | PROT_WRITE); - for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) - ptr2[i] = i; - - if (tiled2untiled) - gem_set_tiling(fd, handle_tiled, I915_TILING_NONE, 2048); - else - gem_set_tiling(fd, handle_tiled, I915_TILING_X, 2048); - - if (hibernate) - igt_system_suspend_autoresume(SUSPEND_STATE_DISK, - SUSPEND_TEST_NONE); - else - igt_system_suspend_autoresume(SUSPEND_STATE_MEM, - SUSPEND_TEST_NONE); - - igt_info("checking the first canary object\n"); - for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) - igt_assert(ptr1[i] == i); - - igt_info("checking the second canary object\n"); - for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) - igt_assert(ptr2[i] == i); - - gem_close(fd, handle1); - gem_close(fd, handle2); - gem_close(fd, handle_tiled); - - munmap(ptr1, OBJECT_SIZE); - munmap(ptr2, OBJECT_SIZE); - munmap(ptr_tiled, OBJECT_SIZE); -} - -static void -test_debugfs_reader(bool hibernate) -{ - struct igt_helper_process reader = {}; - reader.use_SIGKILL = true; - - igt_fork_helper(&reader) { - static const char dfs_base[] = "/sys/kernel/debug/dri"; - static char tmp[1024]; - - snprintf(tmp, sizeof(tmp) - 1, - "while true; do find %s/%i/ -type f ! -path \"*/crc/*\" | xargs cat > /dev/null 2>&1; done", - dfs_base, drm_get_card()); - igt_assert(execl("/bin/sh", "sh", "-c", tmp, (char *) NULL) != -1); - } - - sleep(1); - - if (hibernate) - igt_system_suspend_autoresume(SUSPEND_STATE_DISK, - SUSPEND_TEST_NONE); - else - igt_system_suspend_autoresume(SUSPEND_STATE_MEM, - SUSPEND_TEST_NONE); - - sleep(1); - - igt_stop_helper(&reader); -} - -static void -test_sysfs_reader(bool hibernate) -{ - struct igt_helper_process reader = {}; - reader.use_SIGKILL = true; - - igt_fork_helper(&reader) { - static const char dfs_base[] = "/sys/class/drm/card"; - static char tmp[1024]; - - snprintf(tmp, sizeof(tmp) - 1, - "while true; do find %s%i*/ -type f | xargs cat > /dev/null 2>&1; done", - dfs_base, drm_get_card()); - igt_assert(execl("/bin/sh", "sh", "-c", tmp, (char *) NULL) != -1); - } - - sleep(1); - - if (hibernate) - igt_system_suspend_autoresume(SUSPEND_STATE_DISK, - SUSPEND_TEST_NONE); - else - igt_system_suspend_autoresume(SUSPEND_STATE_MEM, - SUSPEND_TEST_NONE); - - sleep(1); - - igt_stop_helper(&reader); -} - -static void -test_shrink(int fd, unsigned int mode) -{ - void *mem; - size_t size; - - gem_quiescent_gpu(fd); - intel_purge_vm_caches(fd); - - size = intel_get_total_pinnable_mem(); - igt_require(size > 64 << 20); - size -= 64 << 20; - - mem = mmap(NULL, size, PROT_READ, MAP_SHARED | MAP_ANON, -1, 0); - - intel_purge_vm_caches(fd); - - igt_debug("Locking %'zu B (%'zu MiB)\n", - size, size >> 20); - igt_assert(!mlock(mem, size)); - igt_info("Locked %'zu B (%'zu MiB)\n", - size, size >> 20); - - intel_purge_vm_caches(fd); - igt_system_suspend_autoresume(mode, SUSPEND_TEST_NONE); - - munmap(mem, size); -} - -static void -test_forcewake(int fd, bool hibernate) -{ - int fw_fd; - - fw_fd = igt_open_forcewake_handle(fd); - igt_assert_lte(0, fw_fd); - - if (hibernate) - igt_system_suspend_autoresume(SUSPEND_STATE_DISK, - SUSPEND_TEST_NONE); - else - igt_system_suspend_autoresume(SUSPEND_STATE_MEM, - SUSPEND_TEST_NONE); - - close (fw_fd); -} - -int fd; - -igt_main -{ - igt_skip_on_simulation(); - - igt_fixture - fd = drm_open_driver(DRIVER_INTEL); - - igt_subtest("fence-restore-tiled2untiled") - test_fence_restore(fd, true, false); - - igt_subtest("fence-restore-untiled") - test_fence_restore(fd, false, false); - - igt_subtest("debugfs-reader") - test_debugfs_reader(false); - - igt_subtest("sysfs-reader") - test_sysfs_reader(false); - - igt_subtest("shrink") - test_shrink(fd, SUSPEND_STATE_MEM); - - igt_subtest("forcewake") - test_forcewake(fd, false); - - igt_subtest("fence-restore-tiled2untiled-hibernate") - test_fence_restore(fd, true, true); - - igt_subtest("fence-restore-untiled-hibernate") - test_fence_restore(fd, false, true); - - igt_subtest("debugfs-reader-hibernate") - test_debugfs_reader(true); - - igt_subtest("sysfs-reader-hibernate") - test_sysfs_reader(true); - - igt_subtest("forcewake-hibernate") - test_forcewake(fd, true); - - igt_fixture - close(fd); -} diff --git a/tests/meson.build b/tests/meson.build index ec980651..bb90711e 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -97,17 +97,11 @@ test_progs = [ ] i915_progs = [ - 'fb_tiling', - 'getparams_basic', - 'hangman', - 'missed_irq', - 'module_load', - 'query', - 'selftest', - 'suspend', -] - -gem_progs = [ + 'gen3_mixed_blits', + 'gen3_render_linear_blits', + 'gen3_render_mixed_blits', + 'gen3_render_tiledx_blits', + 'gen3_render_tiledy_blits', 'gem_bad_reloc', 'gem_basic', 'gem_busy', @@ -224,14 +218,14 @@ gem_progs = [ 'gem_wait', 'gem_workarounds', 'gem_write_read_ring_switch', -] - -gen3_progs = [ - 'gen3_mixed_blits', - 'gen3_render_linear_blits', - 'gen3_render_mixed_blits', - 'gen3_render_tiledx_blits', - 'gen3_render_tiledy_blits', + 'i915_fb_tiling', + 'i915_getparams_basic', + 'i915_hangman', + 'i915_missed_irq', + 'i915_module_load', + 'i915_query', + 'i915_selftest', + 'i915_suspend', ] test_deps = [ igt_deps ] @@ -272,17 +266,6 @@ foreach prog : test_progs endforeach foreach prog : i915_progs - prog_name = 'i915_' + prog - test_executables += executable(prog_name, - join_paths('i915', prog + '.c'), - dependencies : test_deps, - install_dir : libexecdir, - install_rpath : libexecdir_rpathdir, - install : true) - test_list += prog_name -endforeach - -foreach prog : gem_progs + gen3_progs test_executables += executable(prog, join_paths('i915', prog + '.c'), dependencies : test_deps, -- cgit v1.2.3