From 8ac5cfb4db9c7bc593beec18a6be1e2ff163106c Mon Sep 17 00:00:00 2001 From: Arkadiusz Hiler Date: Thu, 25 Oct 2018 16:44:36 +0300 Subject: tests: Move drv_ tests to i915 directory The drv_ tests are i915 specific, so let's move them to i915 directory and change the binary prefix to i915_. Additionally, while we at moving stuff around, let's rename module_reload to module_load and do the following cleanup with the subtests: basic-reload -> reload basic-no-display -> reload-no-display basic-reload-inject -> reload-with-fault-injection Cc: Martin Peres Cc: Chris Wilson Cc: Petri Latvala Signed-off-by: Arkadiusz Hiler Reviewed-by: Chris Wilson Acked-by: Martin Peres --- docs/reference/igt-gpu-tools/Makefile.am | 4 +- docs/reference/igt-gpu-tools/igt_test_programs.xml | 18 +- docs/reference/igt-gpu-tools/meson.build | 2 +- tests/Makefile.sources | 23 +- tests/drv_getparams_basic.c | 164 --------- tests/drv_hangman.c | 282 ---------------- tests/drv_missed_irq.c | 164 --------- tests/drv_module_reload.c | 369 --------------------- tests/drv_selftest.c | 37 --- tests/drv_suspend.c | 254 -------------- tests/feat_profile.json | 10 +- tests/i915/getparams_basic.c | 164 +++++++++ tests/i915/hangman.c | 282 ++++++++++++++++ tests/i915/missed_irq.c | 164 +++++++++ tests/i915/module_load.c | 369 +++++++++++++++++++++ tests/i915/selftest.c | 37 +++ tests/i915/suspend.c | 254 ++++++++++++++ tests/igt_command_line.sh | 2 +- tests/intel-ci/blacklist.txt | 4 +- tests/intel-ci/fast-feedback.testlist | 12 +- tests/meson.build | 12 +- 21 files changed, 1319 insertions(+), 1308 deletions(-) delete mode 100644 tests/drv_getparams_basic.c delete mode 100644 tests/drv_hangman.c delete mode 100644 tests/drv_missed_irq.c delete mode 100644 tests/drv_module_reload.c delete mode 100644 tests/drv_selftest.c delete mode 100644 tests/drv_suspend.c create mode 100644 tests/i915/getparams_basic.c create mode 100644 tests/i915/hangman.c create mode 100644 tests/i915/missed_irq.c create mode 100644 tests/i915/module_load.c create mode 100644 tests/i915/selftest.c create mode 100644 tests/i915/suspend.c diff --git a/docs/reference/igt-gpu-tools/Makefile.am b/docs/reference/igt-gpu-tools/Makefile.am index 11ada326..c77c6a65 100644 --- a/docs/reference/igt-gpu-tools/Makefile.am +++ b/docs/reference/igt-gpu-tools/Makefile.am @@ -144,8 +144,6 @@ test_program_files = xml/igt_test_programs_amdgpu_description.xml \ xml/igt_test_programs_debugfs_programs.xml \ xml/igt_test_programs_drm_description.xml \ xml/igt_test_programs_drm_programs.xml \ - xml/igt_test_programs_drv_description.xml \ - xml/igt_test_programs_drv_programs.xml \ xml/igt_test_programs_gem_description.xml \ xml/igt_test_programs_gem_programs.xml \ xml/igt_test_programs_gen3_description.xml \ @@ -154,6 +152,8 @@ test_program_files = xml/igt_test_programs_amdgpu_description.xml \ xml/igt_test_programs_gen7_programs.xml \ xml/igt_test_programs_gvt_description.xml \ xml/igt_test_programs_gvt_programs.xml \ + xml/igt_test_programs_i915_description.xml \ + xml/igt_test_programs_i915_programs.xml \ xml/igt_test_programs_kms_description.xml \ xml/igt_test_programs_kms_programs.xml \ xml/igt_test_programs_meta_description.xml \ diff --git a/docs/reference/igt-gpu-tools/igt_test_programs.xml b/docs/reference/igt-gpu-tools/igt_test_programs.xml index 95c4653e..2487da79 100644 --- a/docs/reference/igt-gpu-tools/igt_test_programs.xml +++ b/docs/reference/igt-gpu-tools/igt_test_programs.xml @@ -145,15 +145,6 @@ - - - DRV Tests - Tests for overall driver behaviour - - - - - GEM Tests @@ -190,6 +181,15 @@ + + + i915 Tests + Tests for overall i915 driver behaviour + + + + + KMS Tests diff --git a/docs/reference/igt-gpu-tools/meson.build b/docs/reference/igt-gpu-tools/meson.build index e544e71b..b2b2c1c2 100644 --- a/docs/reference/igt-gpu-tools/meson.build +++ b/docs/reference/igt-gpu-tools/meson.build @@ -29,11 +29,11 @@ test_groups = [ 'core', 'debugfs', 'drm', - 'drv', 'gem', 'gen3', 'gen7', 'gvt', + 'i915', 'kms', 'meta', 'perf', diff --git a/tests/Makefile.sources b/tests/Makefile.sources index d007ebc7..5620c1d6 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -33,12 +33,6 @@ TESTS_progs = \ drm_import_export \ drm_mm \ drm_read \ - drv_getparams_basic \ - drv_hangman \ - drv_missed_irq \ - drv_module_reload \ - drv_selftest \ - drv_suspend \ kms_3d \ kms_addfb_basic \ kms_atomic \ @@ -479,9 +473,26 @@ gen3_render_tiledx_blits_SOURCES = i915/gen3_render_tiledx_blits.c TESTS_progs += gen3_render_tiledy_blits gen3_render_tiledy_blits_SOURCES = i915/gen3_render_tiledy_blits.c +TESTS_progs += i915_getparams_basic +i915_getparams_basic_SOURCES = i915/getparams_basic.c + +TESTS_progs += i915_hangman +i915_hangman_SOURCES = i915/hangman.c + +TESTS_progs += i915_missed_irq +i915_missed_irq_SOURCES = i915/missed_irq.c + +TESTS_progs += i915_module_load +i915_module_load_SOURCES = i915/module_load.c + TESTS_progs += i915_query i915_query_SOURCES = i915/query.c +TESTS_progs += i915_selftest +i915_selftest_SOURCES = i915/selftest.c + +TESTS_progs += i915_suspend +i915_suspend_SOURCES = i915/suspend.c TESTS_progs_X = gem_concurrent_all gem_concurrent_all_SOURCES = i915/gem_concurrent_all.c diff --git a/tests/drv_getparams_basic.c b/tests/drv_getparams_basic.c deleted file mode 100644 index 7cb210df..00000000 --- a/tests/drv_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/drv_hangman.c b/tests/drv_hangman.c deleted file mode 100644 index 6ddae491..00000000 --- a/tests/drv_hangman.c +++ /dev/null @@ -1,282 +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 void test_sysfs_error_exists(void) -{ - char *error; - - error = igt_sysfs_get(sysfs, "error"); - igt_assert(error); - free(error); -} - -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_subtest("error-state-sysfs-entry") - test_sysfs_error_exists(); - - 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/drv_missed_irq.c b/tests/drv_missed_irq.c deleted file mode 100644 index 78690c36..00000000 --- a/tests/drv_missed_irq.c +++ /dev/null @@ -1,164 +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); - igt_fork_hang_detector(device); - - debugfs = igt_debugfs_dir(device); - - expect_rings = engine_mask(debugfs); - - 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/drv_module_reload.c b/tests/drv_module_reload.c deleted file mode 100644 index cf4aea80..00000000 --- a/tests/drv_module_reload.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("basic-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("basic-no-display") { - igt_i915_driver_unload(); - - igt_assert_eq(igt_i915_driver_load("disable_display=1"), 0); - - igt_i915_driver_unload(); - } - - igt_subtest("basic-reload-inject") { - 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/drv_selftest.c b/tests/drv_selftest.c deleted file mode 100644 index 80e515c6..00000000 --- a/tests/drv_selftest.c +++ /dev/null @@ -1,37 +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 -{ - igt_kselftests("i915", - "mock_selftests=-1 disable_display=1", - NULL, "mock"); - igt_kselftests("i915", - "live_selftests=-1 disable_display=1", - "live_selftests", "live"); -} diff --git a/tests/drv_suspend.c b/tests/drv_suspend.c deleted file mode 100644 index 84cb3b49..00000000 --- a/tests/drv_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/feat_profile.json b/tests/feat_profile.json index ccc2ad86..f13d636e 100644 --- a/tests/feat_profile.json +++ b/tests/feat_profile.json @@ -24,11 +24,6 @@ "exclude_tests" : "", "target_rate" : 90 }, - "drv" : { - "include_tests" : "drv", - "exclude_tests" : "", - "target_rate" : 90 - }, "gem" : { "include_tests" : "gem", "exclude_tests" : "", @@ -40,6 +35,11 @@ "exclude_tests" : "", "target_rate" : 90 }, + "i915" : { + "include_tests" : "i915", + "exclude_tests" : "", + "target_rate" : 90 + }, "kms" : { "include_tests" : "kms", "exclude_tests" : "", diff --git a/tests/i915/getparams_basic.c b/tests/i915/getparams_basic.c new file mode 100644 index 00000000..7cb210df --- /dev/null +++ b/tests/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/hangman.c b/tests/i915/hangman.c new file mode 100644 index 00000000..6ddae491 --- /dev/null +++ b/tests/i915/hangman.c @@ -0,0 +1,282 @@ +/* + * 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 void test_sysfs_error_exists(void) +{ + char *error; + + error = igt_sysfs_get(sysfs, "error"); + igt_assert(error); + free(error); +} + +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_subtest("error-state-sysfs-entry") + test_sysfs_error_exists(); + + 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/missed_irq.c b/tests/i915/missed_irq.c new file mode 100644 index 00000000..78690c36 --- /dev/null +++ b/tests/i915/missed_irq.c @@ -0,0 +1,164 @@ +/* + * 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); + igt_fork_hang_detector(device); + + debugfs = igt_debugfs_dir(device); + + expect_rings = engine_mask(debugfs); + + 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 new file mode 100644 index 00000000..7fe83520 --- /dev/null +++ b/tests/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/selftest.c b/tests/i915/selftest.c new file mode 100644 index 00000000..80e515c6 --- /dev/null +++ b/tests/i915/selftest.c @@ -0,0 +1,37 @@ +/* + * 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 +{ + igt_kselftests("i915", + "mock_selftests=-1 disable_display=1", + NULL, "mock"); + igt_kselftests("i915", + "live_selftests=-1 disable_display=1", + "live_selftests", "live"); +} diff --git a/tests/i915/suspend.c b/tests/i915/suspend.c new file mode 100644 index 00000000..84cb3b49 --- /dev/null +++ b/tests/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/igt_command_line.sh b/tests/igt_command_line.sh index a4ec3f95..e05ec34c 100755 --- a/tests/igt_command_line.sh +++ b/tests/igt_command_line.sh @@ -90,7 +90,7 @@ check_test () # Subtest enumeration of kernel selftest launchers depends # on the running kernel. If selftests are not enabled, # they will output nothing and exit with 0. - if [ "$testname" != "drv_selftest" -a "$testname" != "drm_mm" -a "$testname" != "kms_selftest" ]; then + if [ "$testname" != "i915_selftest" -a "$testname" != "drm_mm" -a "$testname" != "kms_selftest" ]; then fail $test fi fi diff --git a/tests/intel-ci/blacklist.txt b/tests/intel-ci/blacklist.txt index 88b2fe31..77f0c905 100644 --- a/tests/intel-ci/blacklist.txt +++ b/tests/intel-ci/blacklist.txt @@ -2,7 +2,7 @@ igt@meta_test(@.*)? ############################################### # Kernel selftests (run separately) ############################################### -igt@drv_selftest(@.*)? +igt@i915_selftest(@.*)? igt@drm_mm(@.*)? ############################################### # Handle module reloads with great care! @@ -12,7 +12,7 @@ igt@drm_mm(@.*)? # self-contained tests, leading to random # failures in tests run afterwards. ############################################### -igt@drv_module_reload(@.*)? +igt@i915_module_load(@.*)? igt@pm_rpm@module-reload ############################################### # GEM diff --git a/tests/intel-ci/fast-feedback.testlist b/tests/intel-ci/fast-feedback.testlist index c625904d..6d42792c 100644 --- a/tests/intel-ci/fast-feedback.testlist +++ b/tests/intel-ci/fast-feedback.testlist @@ -3,9 +3,6 @@ igt@core_auth@basic-auth igt@core_prop_blob@basic igt@debugfs_test@read_all_entries -igt@drv_getparams_basic@basic-eu-total -igt@drv_getparams_basic@basic-subslice-total -igt@drv_hangman@error-state-basic igt@gem_basic@bad-close igt@gem_basic@create-close igt@gem_basic@create-fd-close @@ -139,6 +136,9 @@ igt@gem_wait@basic-busy-all igt@gem_wait@basic-wait-all igt@gem_wait@basic-await-all igt@gem_workarounds@basic-read +igt@i915_getparams_basic@basic-eu-total +igt@i915_getparams_basic@basic-subslice-total +igt@i915_hangman@error-state-basic igt@kms_addfb_basic@addfb25-bad-modifier igt@kms_addfb_basic@addfb25-framebuffer-vs-set-tiling igt@kms_addfb_basic@addfb25-modifier-no-flag @@ -269,7 +269,7 @@ igt@vgem_basic@sysfs # driver in a broken state that is not otherwise noticed in that test. igt@vgem_basic@unload -igt@drv_module_reload@basic-reload -igt@drv_module_reload@basic-no-display -igt@drv_module_reload@basic-reload-inject +igt@i915_module_load@reload +igt@i915_module_load@reload-no-display +igt@i915_module_load@reload-with-fault-injection igt@pm_rpm@module-reload diff --git a/tests/meson.build b/tests/meson.build index 3020f798..52f91a22 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -10,12 +10,6 @@ test_progs = [ 'drm_import_export', 'drm_mm', 'drm_read', - 'drv_getparams_basic', - 'drv_hangman', - 'drv_missed_irq', - 'drv_module_reload', - 'drv_selftest', - 'drv_suspend', 'kms_3d', 'kms_addfb_basic', 'kms_atomic', @@ -98,7 +92,13 @@ test_progs = [ ] i915_progs = [ + 'getparams_basic', + 'hangman', + 'missed_irq', + 'module_load', 'query', + 'selftest', + 'suspend', ] gem_progs = [ -- cgit v1.2.3