From patchwork Fri Mar 23 11:54:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 10304313 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 38D75600F6 for ; Fri, 23 Mar 2018 11:54:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 25E1028DF9 for ; Fri, 23 Mar 2018 11:54:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 19D4928DFC; Fri, 23 Mar 2018 11:54:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 191AF28DF9 for ; Fri, 23 Mar 2018 11:54:41 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 687DF6E2FF; Fri, 23 Mar 2018 11:54:40 +0000 (UTC) X-Original-To: Intel-gfx@lists.freedesktop.org Delivered-To: Intel-gfx@lists.freedesktop.org Received: from mail-wm0-x242.google.com (mail-wm0-x242.google.com [IPv6:2a00:1450:400c:c09::242]) by gabe.freedesktop.org (Postfix) with ESMTPS id 734326E2E3 for ; Fri, 23 Mar 2018 11:54:39 +0000 (UTC) Received: by mail-wm0-x242.google.com with SMTP id i75so3074665wmf.0 for ; Fri, 23 Mar 2018 04:54:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ursulin-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=3f2jjwYw5AiMuTa8d/yUHjfPCeCJaYtLFNnpCXJ7W2k=; b=boqh+fKc2u+Oihwf3Y4fW2Wiru6Z8AETAy7qkxodQ3grJHLtm293HfOjwZKk/p6es8 TldHSrfpeIC8dsf6hW8IRwXwQRkh7PAj/Bq1xTzha8SrLRz2InBPY63oTCdPQ+JKgIGR ZRvi0IID/7Oj43WCmytRr/qkgPwm6MggDGDhp2+TJYnBX6Dm2gY4pQB3fOdKy/uYVPhP Wm5rXiVspqN1f275rvfTBniqQ+uGcwSJsQDCuxIdUGiArYgfxLty/EM8vPgTdCSAyiSR OfoVwan4Q7L1jajaAjeN8msmcDidnroDsnILSq6sIaFJhfmfCizSb+zrpNE5id7e7thZ 6sDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=3f2jjwYw5AiMuTa8d/yUHjfPCeCJaYtLFNnpCXJ7W2k=; b=lgTtlnMzn+90qUihs7gj4HUShhNh8JqvJBjJTjb+MNMD4oV3KUdmqk+kb/1glOpGss b2zZsXe6cOrb+m4rCLBnKmmLETdNeXC0tP2jjtHeA3JeWi01vbou30hUx8/AAAwdx0ku KyYEPThtz1ktvyKd4hcoGfVJ+Y6PNESpOcbEgInM3q2Ed7HFvk6ZjoP/Wj0mnb+2RuLl Zvq/Tf+d0eh3s33IqkR1JItjSwhYqlOrOMGRrK8gR6gt8mdp5MQ8PB5tjSWbhhyhmNlL KmgKf8AzP7DzVDlpVzmNIoK5a9c4ac9EjYVyfq71jfM4qWaOPlpke8LE7SsJX6LAkfn0 gVPw== X-Gm-Message-State: AElRT7HHXXhg4GMn5OH97Ge88O270GoP+KZuPitEyI5vWvjgLrPAXtZm C7s8+6Th0KFKlK6oL1QPS82iBw== X-Google-Smtp-Source: AG47ELsDBfWGri3v8iUJOPRFdb/TKf0+UOqDJisfDjUe1s8qmpzpPsOiylk2taJDIu8JKhXtQCWzHg== X-Received: by 10.28.159.209 with SMTP id i200mr7640000wme.87.1521806077580; Fri, 23 Mar 2018 04:54:37 -0700 (PDT) Received: from localhost.localdomain ([95.146.144.186]) by smtp.gmail.com with ESMTPSA id 96sm8080411wrk.54.2018.03.23.04.54.36 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Mar 2018 04:54:37 -0700 (PDT) From: Tvrtko Ursulin X-Google-Original-From: Tvrtko Ursulin To: igt-dev@lists.freedesktop.org Date: Fri, 23 Mar 2018 11:54:28 +0000 Message-Id: <20180323115428.23406-1-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <152179884167.23562.9863516190314553500@mail.alporthouse.com> References: <152179884167.23562.9863516190314553500@mail.alporthouse.com> Subject: [Intel-gfx] [PATCH i-g-t v3 2/3] tests/gem_eio: Speed up test execution X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Intel-gfx@lists.freedesktop.org MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP From: Tvrtko Ursulin If we stop relying on regular GPU hangs to be detected, but trigger them manually as soon as we know our batch of interest is actually executing on the GPU, we can dramatically speed up various subtests. This is enabled by the pollable spin batch added in the previous patch. v2: * Test gem_wait after reset/wedge and with reset/wedge after a few predefined intervals since gem_wait invocation. (Chris Wilson) v3: Chris Wilson: * Decrease short test to 1us. * Use POSIX timers instead of signals to avoid interrupting gem_wait. * Improve comment. Signed-off-by: Tvrtko Ursulin Suggested-by: Chris Wilson Cc: Antonio Argenziano Reviewed-by: Chris Wilson --- tests/Makefile.am | 1 + tests/gem_eio.c | 235 +++++++++++++++++++++++++++++++++++++++++------------- tests/meson.build | 8 +- 3 files changed, 189 insertions(+), 55 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index dbc7be722eb9..f41ad5096349 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -130,6 +130,7 @@ gem_userptr_blits_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) gem_userptr_blits_LDADD = $(LDADD) -lpthread perf_pmu_LDADD = $(LDADD) $(top_builddir)/lib/libigt_perf.la +gem_eio_LDADD = $(LDADD) -lrt gem_wait_LDADD = $(LDADD) -lrt kms_flip_LDADD = $(LDADD) -lrt -lpthread pm_rc6_residency_LDADD = $(LDADD) -lrt diff --git a/tests/gem_eio.c b/tests/gem_eio.c index 4bcc5937db39..b824d9d4c9c0 100644 --- a/tests/gem_eio.c +++ b/tests/gem_eio.c @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include @@ -62,6 +64,10 @@ static bool i915_reset_control(bool enable) static void trigger_reset(int fd) { + struct timespec ts = { }; + + igt_nsec_elapsed(&ts); + igt_force_gpu_reset(fd); /* And just check the gpu is indeed running again */ @@ -69,22 +75,12 @@ static void trigger_reset(int fd) gem_test_engine(fd, ALL_ENGINES); gem_quiescent_gpu(fd); -} - -static void wedge_gpu(int fd) -{ - /* First idle the GPU then disable GPU resets before injecting a hang */ - gem_quiescent_gpu(fd); - - igt_require(i915_reset_control(false)); - - igt_debug("Wedging GPU by injecting hang\n"); - igt_post_hang_ring(fd, igt_hang_ring(fd, I915_EXEC_DEFAULT)); - igt_assert(i915_reset_control(true)); + /* We expect forced reset and health check to be quick. */ + igt_assert(igt_seconds_elapsed(&ts) < 2); } -static void wedgeme(int drm_fd) +static void manual_hang(int drm_fd) { int dir = igt_debugfs_dir(drm_fd); @@ -93,6 +89,16 @@ static void wedgeme(int drm_fd) close(dir); } +static void wedge_gpu(int fd) +{ + /* First idle the GPU then disable GPU resets before injecting a hang */ + gem_quiescent_gpu(fd); + + igt_require(i915_reset_control(false)); + manual_hang(fd); + igt_assert(i915_reset_control(true)); +} + static int __gem_throttle(int fd) { int err = 0; @@ -149,26 +155,124 @@ static int __gem_wait(int fd, uint32_t handle, int64_t timeout) return err; } -static void test_wait(int fd) +static igt_spin_t * __spin_poll(int fd, uint32_t ctx, unsigned long flags) { - igt_hang_t hang; + if (gem_can_store_dword(fd, flags)) + return __igt_spin_batch_new_poll(fd, ctx, flags); + else + return __igt_spin_batch_new(fd, ctx, flags, 0); +} + +static void __spin_wait(int fd, igt_spin_t *spin) +{ + if (spin->running) { + igt_spin_busywait_until_running(spin); + } else { + igt_debug("__spin_wait - usleep mode\n"); + usleep(500e3); /* Better than nothing! */ + } +} + +static igt_spin_t * spin_sync(int fd, uint32_t ctx, unsigned long flags) +{ + igt_spin_t *spin = __spin_poll(fd, ctx, flags); + + __spin_wait(fd, spin); + + return spin; +} + +struct hang_ctx { + int debugfs; + struct timespec ts; + timer_t timer; +}; + +static void hang_handler(union sigval arg) +{ + struct hang_ctx *ctx = arg.sival_ptr; + + igt_debug("hang delay = %.2fus\n", igt_nsec_elapsed(&ctx->ts) / 1000.0); + + igt_assert(igt_sysfs_set(ctx->debugfs, "i915_wedged", "-1")); + + igt_assert_eq(timer_delete(ctx->timer), 0); + close(ctx->debugfs); + free(ctx); +} + +static void hang_after(int fd, unsigned int us) +{ + struct sigevent sev = { + .sigev_notify = SIGEV_THREAD, + .sigev_notify_function = hang_handler + }; + struct itimerspec its = { + .it_value.tv_sec = us / USEC_PER_SEC, + .it_value.tv_nsec = us % USEC_PER_SEC * 1000, + }; + struct hang_ctx *ctx; + + ctx = calloc(1, sizeof(*ctx)); + igt_assert(ctx); + + ctx->debugfs = igt_debugfs_dir(fd); + igt_assert_fd(ctx->debugfs); + + sev.sigev_value.sival_ptr = ctx; + + igt_assert_eq(timer_create(CLOCK_MONOTONIC, &sev, &ctx->timer), 0); + + igt_nsec_elapsed(&ctx->ts); + + igt_assert_eq(timer_settime(ctx->timer, 0, &its, NULL), 0); +} + +static int __check_wait(int fd, uint32_t bo, unsigned int wait) +{ + unsigned long wait_timeout = 250e6; /* Some margin for actual reset. */ + int ret; + + if (wait) { + /* + * Double the wait plus some fixed margin to ensure gem_wait + * can never time out before the async hang runs. + */ + wait_timeout += wait * 2000 + 250e6; + hang_after(fd, wait); + } else { + manual_hang(fd); + } + + ret = __gem_wait(fd, bo, wait_timeout); + + return ret; +} + +#define TEST_WEDGE (1) + +static void test_wait(int fd, unsigned int flags, unsigned int wait) +{ + igt_spin_t *hang; igt_require_gem(fd); - /* If the request we wait on completes due to a hang (even for + /* + * If the request we wait on completes due to a hang (even for * that request), the user expects the return value to 0 (success). */ - hang = igt_hang_ring(fd, I915_EXEC_DEFAULT); - igt_assert_eq(__gem_wait(fd, hang.handle, -1), 0); - igt_post_hang_ring(fd, hang); - /* If the GPU is wedged during the wait, again we expect the return - * value to be 0 (success). - */ - igt_require(i915_reset_control(false)); - hang = igt_hang_ring(fd, I915_EXEC_DEFAULT); - igt_assert_eq(__gem_wait(fd, hang.handle, -1), 0); - igt_post_hang_ring(fd, hang); + if (flags & TEST_WEDGE) + igt_require(i915_reset_control(false)); + else + igt_require(i915_reset_control(true)); + + hang = spin_sync(fd, 0, I915_EXEC_DEFAULT); + + igt_assert_eq(__check_wait(fd, hang->handle, wait), 0); + + igt_spin_batch_free(fd, hang); + igt_require(i915_reset_control(true)); trigger_reset(fd); @@ -181,7 +285,7 @@ static void test_suspend(int fd, int state) /* Check we can suspend when the driver is already wedged */ igt_require(i915_reset_control(false)); - wedgeme(fd); + manual_hang(fd); igt_system_suspend_autoresume(state, SUSPEND_TEST_DEVICES); @@ -189,7 +293,7 @@ static void test_suspend(int fd, int state) trigger_reset(fd); } -static void test_inflight(int fd) +static void test_inflight(int fd, unsigned int wait) { const uint32_t bbe = MI_BATCH_BUFFER_END; struct drm_i915_gem_exec_object2 obj[2]; @@ -209,11 +313,10 @@ static void test_inflight(int fd) int fence[64]; /* conservative estimate of ring size */ gem_quiescent_gpu(fd); - igt_debug("Starting %s on engine '%s'\n", __func__, e__->name); igt_require(i915_reset_control(false)); - hang = __igt_spin_batch_new(fd, 0, engine, 0); + hang = spin_sync(fd, 0, engine); obj[0].handle = hang->handle; memset(&execbuf, 0, sizeof(execbuf)); @@ -227,7 +330,8 @@ static void test_inflight(int fd) igt_assert(fence[n] != -1); } - igt_assert_eq(__gem_wait(fd, obj[1].handle, -1), 0); + igt_assert_eq(__check_wait(fd, obj[1].handle, wait), 0); + for (unsigned int n = 0; n < ARRAY_SIZE(fence); n++) { igt_assert_eq(sync_fence_status(fence[n]), -EIO); close(fence[n]); @@ -256,7 +360,7 @@ static void test_inflight_suspend(int fd) obj[1].handle = gem_create(fd, 4096); gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe)); - hang = __igt_spin_batch_new(fd, 0, 0, 0); + hang = spin_sync(fd, 0, 0); obj[0].handle = hang->handle; memset(&execbuf, 0, sizeof(execbuf)); @@ -273,7 +377,8 @@ static void test_inflight_suspend(int fd) igt_set_autoresume_delay(30); igt_system_suspend_autoresume(SUSPEND_STATE_MEM, SUSPEND_TEST_NONE); - igt_assert_eq(__gem_wait(fd, obj[1].handle, -1), 0); + igt_assert_eq(__check_wait(fd, obj[1].handle, 10), 0); + for (unsigned int n = 0; n < ARRAY_SIZE(fence); n++) { igt_assert_eq(sync_fence_status(fence[n]), -EIO); close(fence[n]); @@ -301,7 +406,7 @@ static uint32_t context_create_safe(int i915) return param.ctx_id; } -static void test_inflight_contexts(int fd) +static void test_inflight_contexts(int fd, unsigned int wait) { struct drm_i915_gem_exec_object2 obj[2]; const uint32_t bbe = MI_BATCH_BUFFER_END; @@ -330,7 +435,7 @@ static void test_inflight_contexts(int fd) igt_debug("Starting %s on engine '%s'\n", __func__, e__->name); igt_require(i915_reset_control(false)); - hang = __igt_spin_batch_new(fd, 0, engine, 0); + hang = spin_sync(fd, 0, engine); obj[0].handle = hang->handle; memset(&execbuf, 0, sizeof(execbuf)); @@ -345,7 +450,8 @@ static void test_inflight_contexts(int fd) igt_assert(fence[n] != -1); } - igt_assert_eq(__gem_wait(fd, obj[1].handle, -1), 0); + igt_assert_eq(__check_wait(fd, obj[1].handle, wait), 0); + for (unsigned int n = 0; n < ARRAY_SIZE(fence); n++) { igt_assert_eq(sync_fence_status(fence[n]), -EIO); close(fence[n]); @@ -375,7 +481,7 @@ static void test_inflight_external(int fd) fence = igt_cork_plug(&cork, fd); igt_require(i915_reset_control(false)); - hang = __igt_spin_batch_new(fd, 0, 0, 0); + hang = __spin_poll(fd, 0, 0); memset(&obj, 0, sizeof(obj)); obj.handle = gem_create(fd, 4096); @@ -393,6 +499,9 @@ static void test_inflight_external(int fd) fence = execbuf.rsvd2 >> 32; igt_assert(fence != -1); + __spin_wait(fd, hang); + manual_hang(fd); + gem_sync(fd, hang->handle); /* wedged, with an unready batch */ igt_assert(!gem_bo_busy(fd, hang->handle)); igt_assert(gem_bo_busy(fd, obj.handle)); @@ -407,7 +516,7 @@ static void test_inflight_external(int fd) trigger_reset(fd); } -static void test_inflight_internal(int fd) +static void test_inflight_internal(int fd, unsigned int wait) { struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 obj[2]; @@ -420,7 +529,7 @@ static void test_inflight_internal(int fd) igt_require(gem_has_exec_fence(fd)); igt_require(i915_reset_control(false)); - hang = __igt_spin_batch_new(fd, 0, 0, 0); + hang = spin_sync(fd, 0, 0); memset(obj, 0, sizeof(obj)); obj[0].handle = hang->handle; @@ -441,7 +550,8 @@ static void test_inflight_internal(int fd) nfence++; } - igt_assert_eq(__gem_wait(fd, obj[1].handle, -1), 0); + igt_assert_eq(__check_wait(fd, obj[1].handle, wait), 0); + while (nfence--) { igt_assert_eq(sync_fence_status(fences[nfence]), -EIO); close(fences[nfence]); @@ -484,29 +594,46 @@ igt_main igt_subtest("execbuf") test_execbuf(fd); - igt_subtest("wait") - test_wait(fd); - igt_subtest("suspend") test_suspend(fd, SUSPEND_STATE_MEM); igt_subtest("hibernate") test_suspend(fd, SUSPEND_STATE_DISK); - igt_subtest("in-flight") - test_inflight(fd); - - igt_subtest("in-flight-contexts") - test_inflight_contexts(fd); - igt_subtest("in-flight-external") test_inflight_external(fd); - igt_subtest("in-flight-internal") { - igt_skip_on(gem_has_semaphores(fd)); - test_inflight_internal(fd); - } - igt_subtest("in-flight-suspend") test_inflight_suspend(fd); + + igt_subtest_group { + const struct { + unsigned int wait; + const char *name; + } waits[] = { + { .wait = 0, .name = "immediate" }, + { .wait = 1, .name = "1us" }, + { .wait = 10000, .name = "10ms" }, + }; + unsigned int i; + + for (i = 0; i < sizeof(waits) / sizeof(waits[0]); i++) { + igt_subtest_f("wait-%s", waits[i].name) + test_wait(fd, 0, waits[i].wait); + + igt_subtest_f("wait-wedge-%s", waits[i].name) + test_wait(fd, TEST_WEDGE, waits[i].wait); + + igt_subtest_f("in-flight-%s", waits[i].name) + test_inflight(fd, waits[i].wait); + + igt_subtest_f("in-flight-contexts-%s", waits[i].name) + test_inflight_contexts(fd, waits[i].wait); + + igt_subtest_f("in-flight-internal-%s", waits[i].name) { + igt_skip_on(gem_has_semaphores(fd)); + test_inflight_internal(fd, waits[i].wait); + } + } + } } diff --git a/tests/meson.build b/tests/meson.build index 122aefabe0f0..4720dfe21a66 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -40,7 +40,6 @@ test_progs = [ 'gem_ctx_switch', 'gem_ctx_thrash', 'gem_double_irq_loop', - 'gem_eio', 'gem_evict_alignment', 'gem_evict_everything', 'gem_exec_alignment', @@ -289,6 +288,13 @@ foreach prog : test_progs install : true) endforeach +test_executables += executable('gem_eio', 'gem_eio.c', + dependencies : test_deps + [ realtime ], + install_dir : libexecdir, + install_rpath : rpathdir, + install : true) +test_progs += 'gem_eio' + test_executables += executable('perf_pmu', 'perf_pmu.c', dependencies : test_deps + [ lib_igt_perf ], install_dir : libexecdir,