From patchwork Thu Mar 14 14:19:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852971 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C760217DF for ; Thu, 14 Mar 2019 14:20:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AC7DA2A4B2 for ; Thu, 14 Mar 2019 14:20:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9BFD92A402; Thu, 14 Mar 2019 14:20:14 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 ADE802A402 for ; Thu, 14 Mar 2019 14:20:08 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 640E16E2EB; Thu, 14 Mar 2019 14:20:03 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4AB886E2DA; Thu, 14 Mar 2019 14:19:59 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889924-1500050 for multiple; Thu, 14 Mar 2019 14:19:41 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:15 +0000 Message-Id: <20190314141939.26246-1-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 01/25] i915/gem_create: Always try to create an object of at least one page 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: igt-dev@lists.freedesktop.org, Matthew Auld Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP 0-byte objects are not allowed. References: https://bugs.freedesktop.org/show_bug.cgi?id=110106 Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld --- tests/i915/gem_create.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/i915/gem_create.c b/tests/i915/gem_create.c index 605b7f9d9..2a861ca8a 100644 --- a/tests/i915/gem_create.c +++ b/tests/i915/gem_create.c @@ -149,7 +149,7 @@ static uint64_t get_npages(uint64_t *global, uint64_t npages) max = *global; do { old = max; - try = npages % (max / 2); + try = 1 + npages % (max / 2); max -= try; } while ((max = __sync_val_compare_and_swap(global, old, max)) != old); From patchwork Thu Mar 14 14:19:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852967 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BA7121850 for ; Thu, 14 Mar 2019 14:20:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9F1B42A4E3 for ; Thu, 14 Mar 2019 14:20:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 93B302A42D; Thu, 14 Mar 2019 14:20:16 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 EE4A32A498 for ; Thu, 14 Mar 2019 14:20:12 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 491F76E2F3; Thu, 14 Mar 2019 14:20:05 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 141096E2DC; Thu, 14 Mar 2019 14:19:59 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889925-1500050 for multiple; Thu, 14 Mar 2019 14:19:41 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:16 +0000 Message-Id: <20190314141939.26246-2-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 02/25] lib/i915: Pretty print HW semaphores 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Include whether the scheduler is using HW semaphore assistance in our pretty debug strings, and make the caps known for requires. Signed-off-by: Chris Wilson --- lib/i915/gem_scheduler.c | 22 +++++++++++++++++++--- lib/i915/gem_scheduler.h | 2 ++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/i915/gem_scheduler.c b/lib/i915/gem_scheduler.c index ad156306f..f9e052278 100644 --- a/lib/i915/gem_scheduler.c +++ b/lib/i915/gem_scheduler.c @@ -67,7 +67,7 @@ unsigned gem_scheduler_capability(int fd) } /** - * gem_has_scheduler: + * gem_scheduler_enabled: * @fd: open i915 drm file descriptor * * Feature test macro to query whether the driver has scheduling capability. @@ -79,7 +79,7 @@ bool gem_scheduler_enabled(int fd) } /** - * gem_has_ctx_priority: + * gem_scheduler_has_ctx_priority: * @fd: open i915 drm file descriptor * * Feature test macro to query whether the driver supports assigning custom @@ -92,7 +92,7 @@ bool gem_scheduler_has_ctx_priority(int fd) } /** - * gem_has_preemption: + * gem_scheduler_has_preemption: * @fd: open i915 drm file descriptor * * Feature test macro to query whether the driver supports preempting active @@ -104,6 +104,20 @@ bool gem_scheduler_has_preemption(int fd) LOCAL_I915_SCHEDULER_CAP_PREEMPTION; } +/** + * gem_scheduler_has_semaphores: + * @fd: open i915 drm file descriptor + * + * Feature test macro to query whether the driver supports using HW semaphores + * to schedule dependencies in parallel (using the HW to delay execution until + * ready to reduce latency). + */ +bool gem_scheduler_has_semaphores(int fd) +{ + return gem_scheduler_capability(fd) & + LOCAL_I915_SCHEDULER_CAP_SEMAPHORES; +} + /** * gem_scheduler_print_capability: * @fd: open i915 drm file descriptor @@ -122,4 +136,6 @@ void gem_scheduler_print_capability(int fd) igt_info(" - With priority sorting\n"); if (caps & LOCAL_I915_SCHEDULER_CAP_PREEMPTION) igt_info(" - With preemption enabled\n"); + if (caps & LOCAL_I915_SCHEDULER_CAP_SEMAPHORES) + igt_info(" - With HW semaphores enabled\n"); } diff --git a/lib/i915/gem_scheduler.h b/lib/i915/gem_scheduler.h index 9fcb02665..ead3eacb5 100644 --- a/lib/i915/gem_scheduler.h +++ b/lib/i915/gem_scheduler.h @@ -27,11 +27,13 @@ #define LOCAL_I915_SCHEDULER_CAP_ENABLED (1 << 0) #define LOCAL_I915_SCHEDULER_CAP_PRIORITY (1 << 1) #define LOCAL_I915_SCHEDULER_CAP_PREEMPTION (1 << 2) +#define LOCAL_I915_SCHEDULER_CAP_SEMAPHORES (1 << 3) unsigned gem_scheduler_capability(int fd); bool gem_scheduler_enabled(int fd); bool gem_scheduler_has_ctx_priority(int fd); bool gem_scheduler_has_preemption(int fd); +bool gem_scheduler_has_semaphores(int fd); void gem_scheduler_print_capability(int fd); #endif /* GEM_SCHEDULER_H */ From patchwork Thu Mar 14 14:19:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10853003 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 49C3D13B5 for ; Thu, 14 Mar 2019 14:21:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3447028BBA for ; Thu, 14 Mar 2019 14:21:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2898428BCE; Thu, 14 Mar 2019 14:21:37 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 9322328BBA for ; Thu, 14 Mar 2019 14:21:36 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6F7256E2DC; Thu, 14 Mar 2019 14:21:33 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7FAEC6E2AE; Thu, 14 Mar 2019 14:21:30 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889926-1500050 for multiple; Thu, 14 Mar 2019 14:19:42 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:17 +0000 Message-Id: <20190314141939.26246-3-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 03/25] lib: Add GPU power measurement 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Read the RAPL power metrics courtesy of perf. Or your local HW equivalent? v2: uselocale() Signed-off-by: Chris Wilson --- lib/Makefile.am | 1 + lib/Makefile.sources | 2 + lib/igt_gpu_power.c | 114 +++++++++++++++++++++++++++++++++++++++++++ lib/igt_gpu_power.h | 59 ++++++++++++++++++++++ lib/meson.build | 2 + 5 files changed, 178 insertions(+) create mode 100644 lib/igt_gpu_power.c create mode 100644 lib/igt_gpu_power.h diff --git a/lib/Makefile.am b/lib/Makefile.am index 3e6a7fdba..62e8bda73 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -84,4 +84,5 @@ libintel_tools_la_LIBADD = \ $(LIBUDEV_LIBS) \ $(PIXMAN_LIBS) \ $(GLIB_LIBS) \ + libigt_perf.la \ -lm diff --git a/lib/Makefile.sources b/lib/Makefile.sources index cf2720981..e00347f94 100644 --- a/lib/Makefile.sources +++ b/lib/Makefile.sources @@ -26,6 +26,8 @@ lib_source_list = \ igt_color_encoding.c \ igt_color_encoding.h \ igt_edid_template.h \ + igt_gpu_power.c \ + igt_gpu_power.h \ igt_gt.c \ igt_gt.h \ igt_gvt.c \ diff --git a/lib/igt_gpu_power.c b/lib/igt_gpu_power.c new file mode 100644 index 000000000..a4e3c1420 --- /dev/null +++ b/lib/igt_gpu_power.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include + +#include "igt_gpu_power.h" +#include "igt_perf.h" + +static int filename_to_buf(const char *filename, char *buf, unsigned int sz) +{ + int fd; + ssize_t ret; + + fd = open(filename, O_RDONLY); + if (fd < 0) + return -1; + + ret = read(fd, buf, sz - 1); + close(fd); + if (ret < 1) + return -1; + + buf[ret] = '\0'; + + return 0; +} + +static uint64_t filename_to_u64(const char *filename, int base) +{ + char buf[64], *b; + + if (filename_to_buf(filename, buf, sizeof(buf))) + return 0; + + /* + * Handle both single integer and key=value formats by skipping + * leading non-digits. + */ + b = buf; + while (*b && !isdigit(*b)) + b++; + + return strtoull(b, NULL, base); +} + +static double filename_to_double(const char *filename) +{ + locale_t locale, oldlocale; + char buf[80]; + double v; + + if (filename_to_buf(filename, buf, sizeof(buf))) + return 0; + + /* Replace user environment with plain C to match kernel format */ + locale = newlocale(LC_ALL, "C", 0); + oldlocale = uselocale(locale); + + v = strtod(buf, NULL); + + uselocale(oldlocale); + freelocale(locale); + + return v; +} + +static uint64_t rapl_type_id(void) +{ + return filename_to_u64("/sys/devices/power/type", 10); +} + +static uint64_t rapl_gpu_power(void) +{ + return filename_to_u64("/sys/devices/power/events/energy-gpu", 0); +} + +static double rapl_gpu_power_scale(void) +{ + return filename_to_double("/sys/devices/power/events/energy-gpu.scale"); +} + +int gpu_power_open(struct gpu_power *power) +{ + power->fd = igt_perf_open(rapl_type_id(), rapl_gpu_power()); + if (power->fd < 0) { + power->fd = -errno; + goto err; + } + + power->scale = rapl_gpu_power_scale(); + if (isnan(power->scale) || !power->scale) { + close(power->fd); + goto err; + } + power->scale *= 1e9; + + return 0; + +err: + errno = 0; + return power->fd; +} + +bool gpu_power_read(struct gpu_power *power, struct gpu_power_sample *s) +{ + return read(power->fd, s, sizeof(*s)) == sizeof(*s); +} + +void gpu_power_close(struct gpu_power *power) +{ + close(power->fd); +} diff --git a/lib/igt_gpu_power.h b/lib/igt_gpu_power.h new file mode 100644 index 000000000..4e1b747c0 --- /dev/null +++ b/lib/igt_gpu_power.h @@ -0,0 +1,59 @@ +/* + * Copyright © 2019 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef IGT_GPU_POWER_H +#define IGT_GPU_POWER_H + +#include +#include + +struct gpu_power { + int fd; + double scale; +}; + +struct gpu_power_sample { + uint64_t energy; + uint64_t time; +}; + +int gpu_power_open(struct gpu_power *power); +bool gpu_power_read(struct gpu_power *power, struct gpu_power_sample *s); +void gpu_power_close(struct gpu_power *power); + +static inline double gpu_power_J(const struct gpu_power *p, + const struct gpu_power_sample *t0, + const struct gpu_power_sample *t1) +{ + return (t1->energy - t0->energy) * p->scale * 1e-9; +} + +static inline double gpu_power_W(const struct gpu_power *p, + const struct gpu_power_sample *t0, + const struct gpu_power_sample *t1) +{ + return (t1->energy - t0->energy) * p->scale / (t1->time - t0->time); +} + +#endif /* IGT_GPU_POWER_H */ diff --git a/lib/meson.build b/lib/meson.build index 0eb5585d7..89de06e69 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -9,9 +9,11 @@ lib_sources = [ 'igt_debugfs.c', 'igt_device.c', 'igt_aux.c', + 'igt_gpu_power.c', 'igt_gt.c', 'igt_gvt.c', 'igt_matrix.c', + 'igt_perf.c', 'igt_primes.c', 'igt_rand.c', 'igt_stats.c', From patchwork Thu Mar 14 14:19:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852975 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 12D4E18A6 for ; Thu, 14 Mar 2019 14:20:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EF8C72A42D for ; Thu, 14 Mar 2019 14:20:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E01B52A498; Thu, 14 Mar 2019 14:20:16 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 3FED728BCE for ; Thu, 14 Mar 2019 14:20:16 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 025F76E2FF; Thu, 14 Mar 2019 14:20:15 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id D8C076E2F0; Thu, 14 Mar 2019 14:20:04 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889927-1500050 for multiple; Thu, 14 Mar 2019 14:19:42 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:18 +0000 Message-Id: <20190314141939.26246-4-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 04/25] i915/gem_exec_schedule: Measure semaphore power consumption 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP How much energy does spinning on a semaphore consume relative to plain old spinning? Signed-off-by: Chris Wilson --- tests/i915/gem_exec_schedule.c | 72 +++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/tests/i915/gem_exec_schedule.c b/tests/i915/gem_exec_schedule.c index a9383000a..4f0577b4e 100644 --- a/tests/i915/gem_exec_schedule.c +++ b/tests/i915/gem_exec_schedule.c @@ -29,9 +29,10 @@ #include #include "igt.h" -#include "igt_vgem.h" +#include "igt_gpu_power.h" #include "igt_rand.h" #include "igt_sysfs.h" +#include "igt_vgem.h" #include "i915/gem_ring.h" #define LO 0 @@ -1202,6 +1203,65 @@ static void test_pi_ringfull(int fd, unsigned int engine) munmap(result, 4096); } +static void measure_semaphore_power(int i915) +{ + struct gpu_power power; + unsigned int engine, signaler; + + igt_require(gpu_power_open(&power) == 0); + + for_each_physical_engine(i915, signaler) { + struct gpu_power_sample s_spin[2]; + struct gpu_power_sample s_sema[2]; + double baseline, total; + int64_t jiffie = 1; + igt_spin_t *spin; + + spin = __igt_spin_batch_new(i915, + .engine = signaler, + .flags = IGT_SPIN_POLL_RUN); + gem_wait(i915, spin->handle, &jiffie); /* waitboost */ + igt_assert(spin->running); + igt_spin_busywait_until_running(spin); + + gpu_power_read(&power, &s_spin[0]); + usleep(100*1000); + gpu_power_read(&power, &s_spin[1]); + + /* Add a waiter to each engine */ + for_each_physical_engine(i915, engine) { + igt_spin_t *sema; + + if (engine == signaler) + continue; + + sema = __igt_spin_batch_new(i915, + .engine = engine, + .dependency = spin->handle); + + igt_spin_batch_free(i915, sema); + } + usleep(10); /* just give the tasklets a chance to run */ + + gpu_power_read(&power, &s_sema[0]); + usleep(100*1000); + gpu_power_read(&power, &s_sema[1]); + + igt_spin_batch_free(i915, spin); + + baseline = gpu_power_W(&power, &s_spin[0], &s_spin[1]); + total = gpu_power_W(&power, &s_sema[0], &s_sema[1]); + + igt_info("%s: %.1fmW + %.1fmW (total %1.fmW)\n", + e__->name, + 1e3 * baseline, + 1e3 * (total - baseline), + 1e3 * total); + } + + gpu_power_close(&power); +} + igt_main { const struct intel_execution_engine *e; @@ -1362,6 +1422,16 @@ igt_main } } + igt_subtest_group { + igt_fixture { + igt_require(gem_scheduler_enabled(fd)); + igt_require(gem_scheduler_has_semaphores(fd)); + } + + igt_subtest("semaphore-power") + measure_semaphore_power(fd); + } + igt_fixture { igt_stop_hang_detector(); close(fd); From patchwork Thu Mar 14 14:19:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852979 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D104A17EF for ; Thu, 14 Mar 2019 14:20:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BCFBB2A42B for ; Thu, 14 Mar 2019 14:20:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A9EC92A4B2; Thu, 14 Mar 2019 14:20:17 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 356732A42A for ; Thu, 14 Mar 2019 14:20:11 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 88D816E2DC; Thu, 14 Mar 2019 14:20:04 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1BD3F6E2E0; Thu, 14 Mar 2019 14:19:59 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889928-1500050 for multiple; Thu, 14 Mar 2019 14:19:42 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:19 +0000 Message-Id: <20190314141939.26246-5-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 05/25] i915/gem_exec_whisper: Measure total power consumed 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Show the total power consumed across all the whispers. Signed-off-by: Chris Wilson --- tests/i915/gem_exec_whisper.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/i915/gem_exec_whisper.c b/tests/i915/gem_exec_whisper.c index 0b15fe431..6c3b53756 100644 --- a/tests/i915/gem_exec_whisper.c +++ b/tests/i915/gem_exec_whisper.c @@ -28,8 +28,9 @@ */ #include "igt.h" -#include "igt_gt.h" #include "igt_debugfs.h" +#include "igt_gpu_power.h" +#include "igt_gt.h" #include "igt_rand.h" #include "igt_sysfs.h" @@ -192,6 +193,8 @@ static void whisper(int fd, unsigned engine, unsigned flags) unsigned int reloc_migrations = 0; unsigned int reloc_interruptions = 0; unsigned int eb_migrations = 0; + struct gpu_power_sample sample[2]; + struct gpu_power power; uint64_t old_offset; int i, n, loc; int debugfs; @@ -202,6 +205,7 @@ static void whisper(int fd, unsigned engine, unsigned flags) } debugfs = igt_debugfs_dir(fd); + gpu_power_open(&power); nengine = 0; if (engine == ALL_ENGINES) { @@ -226,6 +230,7 @@ static void whisper(int fd, unsigned engine, unsigned flags) init_hang(&hang); intel_detect_and_clear_missed_interrupts(fd); + gpu_power_read(&power, &sample[0]); igt_fork(child, flags & FORKED ? sysconf(_SC_NPROCESSORS_ONLN) : 1) { unsigned int pass; @@ -495,6 +500,10 @@ static void whisper(int fd, unsigned engine, unsigned flags) fini_hang(&hang); else igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0); + if (gpu_power_read(&power, &sample[1])) { + igt_info("Total energy used: %.1fmJ\n", + gpu_power_J(&power, &sample[0], &sample[1]) * 1e3); + } close(debugfs); } From patchwork Thu Mar 14 14:19:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852993 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 363DF17DF for ; Thu, 14 Mar 2019 14:20:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 225B62A422 for ; Thu, 14 Mar 2019 14:20:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 172932A42B; Thu, 14 Mar 2019 14:20:28 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 B23D42A422 for ; Thu, 14 Mar 2019 14:20:27 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 964B16E2E6; Thu, 14 Mar 2019 14:20:26 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 06EB56E2F2; Thu, 14 Mar 2019 14:20:04 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889929-1500050 for multiple; Thu, 14 Mar 2019 14:19:42 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:20 +0000 Message-Id: <20190314141939.26246-6-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 06/25] i915/gem_exec_schedule: Verify that using HW semaphores doesn't block 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP We may use HW semaphores to schedule nearly-ready work such that they are already spinning on the GPU waiting for the completion on another engine. However, we don't want for that spinning task to actually block any real work should it be scheduled. Signed-off-by: Chris Wilson --- tests/i915/gem_exec_schedule.c | 87 ++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/tests/i915/gem_exec_schedule.c b/tests/i915/gem_exec_schedule.c index 4f0577b4e..ae850c4a3 100644 --- a/tests/i915/gem_exec_schedule.c +++ b/tests/i915/gem_exec_schedule.c @@ -48,6 +48,10 @@ #define MAX_CONTEXTS 1024 +#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) + IGT_TEST_DESCRIPTION("Check that we can control the order of execution"); static inline @@ -320,6 +324,86 @@ static void smoketest(int fd, unsigned ring, unsigned timeout) } } +static uint32_t __batch_create(int i915, uint32_t offset) +{ + const uint32_t bbe = MI_BATCH_BUFFER_END; + uint32_t handle; + + handle = gem_create(i915, ALIGN(offset + 4, 4096)); + gem_write(i915, handle, offset, &bbe, sizeof(bbe)); + + return handle; +} + +static uint32_t batch_create(int i915) +{ + return __batch_create(i915, 0); +} + +static void semaphore_userlock(int i915) +{ + struct drm_i915_gem_exec_object2 obj = { + .handle = batch_create(i915), + }; + igt_spin_t *spin = NULL; + unsigned int engine; + uint32_t scratch; + + igt_require(gem_scheduler_has_preemption(i915)); + + /* + * Given the use of semaphores to govern parallel submission + * of nearly-ready work to HW, we still want to run actually + * ready work immediately. Without semaphores, the dependent + * work wouldn't be submitted so our ready work will run. + */ + + scratch = gem_create(i915, 4096); + for_each_physical_engine(i915, engine) { + if (!spin) { + spin = igt_spin_batch_new(i915, + .dependency = scratch, + .engine = engine); + } else { + typeof(spin->execbuf.flags) saved = spin->execbuf.flags; + + spin->execbuf.flags &= ~ENGINE_MASK; + spin->execbuf.flags |= engine; + + gem_execbuf(i915, &spin->execbuf); + + spin->execbuf.flags = saved; + } + } + igt_require(spin); + gem_close(i915, scratch); + + /* + * On all dependent engines, the request may be executing (busywaiting + * on a HW semaphore) but it should not prevent any real work from + * taking precedence. + */ + scratch = gem_context_create(i915); + for_each_physical_engine(i915, engine) { + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = to_user_pointer(&obj), + .buffer_count = 1, + .flags = engine, + .rsvd1 = scratch, + }; + + if (engine == (spin->execbuf.flags & ENGINE_MASK)) + continue; + + gem_execbuf(i915, &execbuf); + } + gem_context_destroy(i915, scratch); + gem_sync(i915, obj.handle); /* to hang unless we can preempt */ + gem_close(i915, obj.handle); + + igt_spin_batch_free(i915, spin); +} + static void reorder(int fd, unsigned ring, unsigned flags) #define EQUAL 1 { @@ -1307,6 +1391,9 @@ igt_main igt_require(gem_scheduler_has_ctx_priority(fd)); } + igt_subtest("semaphore-user") + semaphore_userlock(fd); + igt_subtest("smoketest-all") smoketest(fd, ALL_ENGINES, 30); From patchwork Thu Mar 14 14:19:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852977 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 390314939 for ; Thu, 14 Mar 2019 14:20:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2366E28BBA for ; Thu, 14 Mar 2019 14:20:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 17C1D2A42D; Thu, 14 Mar 2019 14:20:17 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 E549E2A402 for ; Thu, 14 Mar 2019 14:20:14 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 511A26E2F8; Thu, 14 Mar 2019 14:20:14 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6CF266E2E8; Thu, 14 Mar 2019 14:20:01 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889930-1500050 for multiple; Thu, 14 Mar 2019 14:19:42 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:21 +0000 Message-Id: <20190314141939.26246-7-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 07/25] i915/gem_exec_nop: poll-sequential requires ordering between rings 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP In order to correctly serialise the order of execution between rings, we need to flag the scratch address as being written. Make it so. Signed-off-by: Chris Wilson --- tests/i915/gem_exec_nop.c | 152 +++++++++++++++++++++++++++++++++----- 1 file changed, 133 insertions(+), 19 deletions(-) diff --git a/tests/i915/gem_exec_nop.c b/tests/i915/gem_exec_nop.c index 59a08ad08..b91b4d0f6 100644 --- a/tests/i915/gem_exec_nop.c +++ b/tests/i915/gem_exec_nop.c @@ -104,7 +104,7 @@ static double nop_on_ring(int fd, uint32_t handle, unsigned ring_id, return elapsed(&start, &now); } -static void poll_ring(int fd, unsigned ring, const char *name, int timeout) +static void poll_ring(int fd, unsigned engine, const char *name, int timeout) { const int gen = intel_gen(intel_get_drm_devid(fd)); const uint32_t MI_ARB_CHK = 0x5 << 23; @@ -112,29 +112,17 @@ static void poll_ring(int fd, unsigned ring, const char *name, int timeout) struct drm_i915_gem_exec_object2 obj; struct drm_i915_gem_relocation_entry reloc[4], *r; uint32_t *bbe[2], *state, *batch; - unsigned engines[16], nengine, flags; struct timespec tv = {}; unsigned long cycles; + unsigned flags; uint64_t elapsed; flags = I915_EXEC_NO_RELOC; if (gen == 4 || gen == 5) flags |= I915_EXEC_SECURE; - nengine = 0; - if (ring == ALL_ENGINES) { - for_each_physical_engine(fd, ring) { - if (!gem_can_store_dword(fd, ring)) - continue; - - engines[nengine++] = ring; - } - } else { - gem_require_ring(fd, ring); - igt_require(gem_can_store_dword(fd, ring)); - engines[nengine++] = ring; - } - igt_require(nengine); + gem_require_ring(fd, engine); + igt_require(gem_can_store_dword(fd, engine)); memset(&obj, 0, sizeof(obj)); obj.handle = gem_create(fd, 4096); @@ -198,7 +186,7 @@ static void poll_ring(int fd, unsigned ring, const char *name, int timeout) memset(&execbuf, 0, sizeof(execbuf)); execbuf.buffers_ptr = to_user_pointer(&obj); execbuf.buffer_count = 1; - execbuf.flags = engines[0]; + execbuf.flags = engine | flags; cycles = 0; do { @@ -208,7 +196,6 @@ static void poll_ring(int fd, unsigned ring, const char *name, int timeout) execbuf.batch_start_offset = (bbe[idx] - batch) * sizeof(*batch) - 64; - execbuf.flags = engines[cycles % nengine] | flags; gem_execbuf(fd, &execbuf); *bbe[!idx] = MI_BATCH_BUFFER_END; @@ -227,6 +214,133 @@ static void poll_ring(int fd, unsigned ring, const char *name, int timeout) gem_close(fd, obj.handle); } +static void poll_sequential(int fd, const char *name, int timeout) +{ + const int gen = intel_gen(intel_get_drm_devid(fd)); + const uint32_t MI_ARB_CHK = 0x5 << 23; + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 obj[2]; + struct drm_i915_gem_relocation_entry reloc[4], *r; + uint32_t *bbe[2], *state, *batch; + unsigned engines[16], nengine, engine, flags; + struct timespec tv = {}; + unsigned long cycles; + uint64_t elapsed; + bool cached; + + flags = I915_EXEC_NO_RELOC; + if (gen == 4 || gen == 5) + flags |= I915_EXEC_SECURE; + + nengine = 0; + for_each_physical_engine(fd, engine) { + if (!gem_can_store_dword(fd, engine)) + continue; + + engines[nengine++] = engine; + } + igt_require(nengine); + + memset(obj, 0, sizeof(obj)); + obj[0].handle = gem_create(fd, 4096); + obj[0].flags = EXEC_OBJECT_WRITE; + cached = __gem_set_caching(fd, obj[0].handle, 1) == 0; + obj[1].handle = gem_create(fd, 4096); + obj[1].relocs_ptr = to_user_pointer(reloc); + obj[1].relocation_count = ARRAY_SIZE(reloc); + + r = memset(reloc, 0, sizeof(reloc)); + batch = gem_mmap__wc(fd, obj[1].handle, 0, 4096, PROT_WRITE); + + for (unsigned int start_offset = 0; + start_offset <= 128; + start_offset += 128) { + uint32_t *b = batch + start_offset / sizeof(*batch); + + r->target_handle = obj[0].handle; + r->offset = (b - batch + 1) * sizeof(uint32_t); + r->delta = 0; + r->read_domains = I915_GEM_DOMAIN_RENDER; + r->write_domain = I915_GEM_DOMAIN_RENDER; + + *b = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0); + if (gen >= 8) { + *++b = r->delta; + *++b = 0; + } else if (gen >= 4) { + r->offset += sizeof(uint32_t); + *++b = 0; + *++b = r->delta; + } else { + *b -= 1; + *++b = r->delta; + } + *++b = start_offset != 0; + r++; + + b = batch + (start_offset + 64) / sizeof(*batch); + bbe[start_offset != 0] = b; + *b++ = MI_ARB_CHK; + + r->target_handle = obj[1].handle; + r->offset = (b - batch + 1) * sizeof(uint32_t); + r->read_domains = I915_GEM_DOMAIN_COMMAND; + r->delta = start_offset + 64; + if (gen >= 8) { + *b++ = MI_BATCH_BUFFER_START | 1 << 8 | 1; + *b++ = r->delta; + *b++ = 0; + } else if (gen >= 6) { + *b++ = MI_BATCH_BUFFER_START | 1 << 8; + *b++ = r->delta; + } else { + *b++ = MI_BATCH_BUFFER_START | 2 << 6; + if (gen < 4) + r->delta |= 1; + *b++ = r->delta; + } + r++; + } + igt_assert(r == reloc + ARRAY_SIZE(reloc)); + + if (cached) + state = gem_mmap__cpu(fd, obj[0].handle, 0, 4096, PROT_READ); + else + state = gem_mmap__wc(fd, obj[0].handle, 0, 4096, PROT_READ); + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = to_user_pointer(obj); + execbuf.buffer_count = ARRAY_SIZE(obj); + + cycles = 0; + do { + unsigned int idx = ++cycles & 1; + + *bbe[idx] = MI_ARB_CHK; + execbuf.batch_start_offset = + (bbe[idx] - batch) * sizeof(*batch) - 64; + + execbuf.flags = engines[cycles % nengine] | flags; + gem_execbuf(fd, &execbuf); + + *bbe[!idx] = MI_BATCH_BUFFER_END; + __sync_synchronize(); + + while (READ_ONCE(*state) != idx) + ; + } while ((elapsed = igt_nsec_elapsed(&tv)) >> 30 < timeout); + *bbe[cycles & 1] = MI_BATCH_BUFFER_END; + gem_sync(fd, obj[1].handle); + + igt_info("%s completed %ld cycles: %.3f us\n", + name, cycles, elapsed*1e-3/cycles); + + munmap(state, 4096); + munmap(batch, 4096); + gem_close(fd, obj[1].handle); + gem_close(fd, obj[0].handle); +} + static void single(int fd, uint32_t handle, unsigned ring_id, const char *ring_name) { @@ -813,7 +927,7 @@ igt_main } igt_subtest("poll-sequential") - poll_ring(device, ALL_ENGINES, "Sequential", 20); + poll_sequential(device, "Sequential", 20); igt_subtest("headless") { /* Requires master for changing display modes */ From patchwork Thu Mar 14 14:19:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852999 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0B4D66C2 for ; Thu, 14 Mar 2019 14:21:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E8EEB28BBA for ; Thu, 14 Mar 2019 14:21:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DD71928BCE; Thu, 14 Mar 2019 14:21:34 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 8E70F28BBA for ; Thu, 14 Mar 2019 14:21:34 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A15FC6E2AE; Thu, 14 Mar 2019 14:21:32 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7F9506E184; Thu, 14 Mar 2019 14:21:30 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889931-1500050 for multiple; Thu, 14 Mar 2019 14:19:42 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:22 +0000 Message-Id: <20190314141939.26246-8-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 08/25] i915/gem_sync: Make switch-default asymmetric 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP To make the demonstration of the cheeky preemption more impactful, make the second context a nop to contrast the first being 1024 MI_STORE_DWORD_IMM. Then if we execute and wait on the second context before executing the first, the client latency is even more drastically reduced. To more clearly show any effect on wait reordering, measure the alternative path and present both. Signed-off-by: Chris Wilson --- tests/i915/gem_sync.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/tests/i915/gem_sync.c b/tests/i915/gem_sync.c index fb209977d..3e4feff32 100644 --- a/tests/i915/gem_sync.c +++ b/tests/i915/gem_sync.c @@ -651,7 +651,7 @@ switch_ring(int fd, unsigned ring, int num_children, int timeout) struct drm_i915_gem_relocation_entry reloc[1024]; struct drm_i915_gem_execbuffer2 execbuf; } contexts[2]; - double start, elapsed; + double elapsed, baseline; unsigned long cycles; for (int i = 0; i < ARRAY_SIZE(contexts); i++) { @@ -679,7 +679,7 @@ switch_ring(int fd, unsigned ring, int num_children, int timeout) c->object[1].handle = gem_create(fd, sz); c->object[1].relocs_ptr = to_user_pointer(c->reloc); - c->object[1].relocation_count = 1024; + c->object[1].relocation_count = 1024 * i; batch = gem_mmap__cpu(fd, c->object[1].handle, 0, sz, PROT_WRITE | PROT_READ); @@ -688,7 +688,7 @@ switch_ring(int fd, unsigned ring, int num_children, int timeout) memset(c->reloc, 0, sizeof(c->reloc)); b = batch; - for (int r = 0; r < 1024; r++) { + for (int r = 0; r < c->object[1].relocation_count; r++) { uint64_t offset; c->reloc[r].presumed_offset = c->object[0].offset; @@ -722,26 +722,44 @@ switch_ring(int fd, unsigned ring, int num_children, int timeout) } cycles = 0; - elapsed = 0; - start = gettime(); - do { + baseline = 0; + igt_until_timeout(timeout) { do { double this; - gem_execbuf(fd, &contexts[0].execbuf); gem_execbuf(fd, &contexts[1].execbuf); + gem_execbuf(fd, &contexts[0].execbuf); this = gettime(); gem_sync(fd, contexts[1].object[1].handle); - elapsed += gettime() - this; + gem_sync(fd, contexts[0].object[1].handle); + baseline += gettime() - this; + } while (++cycles & 1023); + } + baseline /= cycles; + + cycles = 0; + elapsed = 0; + igt_until_timeout(timeout) { + do { + double this; + gem_execbuf(fd, &contexts[1].execbuf); + gem_execbuf(fd, &contexts[0].execbuf); + + this = gettime(); gem_sync(fd, contexts[0].object[1].handle); + elapsed += gettime() - this; + + gem_sync(fd, contexts[1].object[1].handle); } while (++cycles & 1023); - } while ((gettime() - start) < timeout); - igt_info("%s%sompleted %ld cycles: %.3f us\n", + } + elapsed /= cycles; + + igt_info("%s%sompleted %ld cycles: %.3f us, baseline %.3f us\n", names[child % num_engines] ?: "", names[child % num_engines] ? " c" : "C", - cycles, elapsed*1e6/cycles); + cycles, elapsed*1e6, baseline*1e6); for (int i = 0; i < ARRAY_SIZE(contexts); i++) { gem_close(fd, contexts[i].object[1].handle); From patchwork Thu Mar 14 14:19:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852963 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 47C221850 for ; Thu, 14 Mar 2019 14:20:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3195A2A381 for ; Thu, 14 Mar 2019 14:20:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2459D2A405; Thu, 14 Mar 2019 14:20:03 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 C43082A381 for ; Thu, 14 Mar 2019 14:20:02 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E5D966E2E5; Thu, 14 Mar 2019 14:20:00 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4AC106E2DC; Thu, 14 Mar 2019 14:19:59 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889932-1500050 for multiple; Thu, 14 Mar 2019 14:19:42 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:23 +0000 Message-Id: <20190314141939.26246-9-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 09/25] i915/gem_ctx_param: Remove kneecapping 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP The invalid set/get tests do not serve the purpose of detecting whether or not invalid parameters are indeed detect correctly -- simply because the kernel is the arbiter of what is invalid and this test second guesses that and is wrong. The intent of this test was to ensure that we didn't include any holes in the parameter space that may have been used for nefarious undisclosed purposes, i.e. the maintainer's job backed up by reviewers. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen --- tests/i915/gem_ctx_param.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/tests/i915/gem_ctx_param.c b/tests/i915/gem_ctx_param.c index acc1e6297..b3f8637df 100644 --- a/tests/i915/gem_ctx_param.c +++ b/tests/i915/gem_ctx_param.c @@ -296,22 +296,6 @@ igt_main /* I915_CONTEXT_PARAM_SSEU tests are located in gem_ctx_sseu.c */ - /* NOTE: This testcase intentionally tests for the next free parameter - * to catch ABI extensions. Don't "fix" this testcase without adding all - * the tests for the new param first. - */ - arg.param = I915_CONTEXT_PARAM_SSEU + 1; - - igt_subtest("invalid-param-get") { - arg.ctx_id = ctx; - igt_assert_eq(__gem_context_get_param(fd, &arg), -EINVAL); - } - - igt_subtest("invalid-param-set") { - arg.ctx_id = ctx; - igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); - } - igt_fixture close(fd); } From patchwork Thu Mar 14 14:19:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10853007 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 04F9113B5 for ; Thu, 14 Mar 2019 14:21:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E4F9328BBA for ; Thu, 14 Mar 2019 14:21:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D965F2A381; Thu, 14 Mar 2019 14:21:40 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 6CF8528BBA for ; Thu, 14 Mar 2019 14:21:40 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 33AB66E2F0; Thu, 14 Mar 2019 14:21:37 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 82E136E2B9; Thu, 14 Mar 2019 14:21:31 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889933-1500050 for multiple; Thu, 14 Mar 2019 14:19:43 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:24 +0000 Message-Id: <20190314141939.26246-10-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 10/25] i915/gem_exec_big: Add a single shot test 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP CI complains that the exhaustive test of trying every size up to the limit is too slow, so add a simple test that tries to submit one extreme batch buffer and check all the relocations land. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105555 Signed-off-by: Chris Wilson --- tests/i915/gem_exec_big.c | 70 ++++++++++++++++++++++++++++++------ tests/intel-ci/blacklist.txt | 1 + 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/tests/i915/gem_exec_big.c b/tests/i915/gem_exec_big.c index a15672f66..015f59e29 100644 --- a/tests/i915/gem_exec_big.c +++ b/tests/i915/gem_exec_big.c @@ -71,7 +71,7 @@ static void exec1(int fd, uint32_t handle, uint64_t reloc_ofs, unsigned flags, c gem_exec[0].relocs_ptr = to_user_pointer(gem_reloc); gem_exec[0].alignment = 0; gem_exec[0].offset = 0; - gem_exec[0].flags = 0; + gem_exec[0].flags = EXEC_OBJECT_SUPPORTS_48B_ADDRESS; gem_exec[0].rsvd1 = 0; gem_exec[0].rsvd2 = 0; @@ -154,12 +154,11 @@ static void execN(int fd, uint32_t handle, uint64_t batch_size, unsigned flags, gem_exec[0].handle = handle; gem_exec[0].relocation_count = nreloc; gem_exec[0].relocs_ptr = to_user_pointer(gem_reloc); + gem_exec[0].flags = EXEC_OBJECT_SUPPORTS_48B_ADDRESS; memset(&execbuf, 0, sizeof(execbuf)); execbuf.buffers_ptr = to_user_pointer(gem_exec); execbuf.buffer_count = 1; - execbuf.batch_start_offset = 0; - execbuf.batch_len = 8; execbuf.flags = flags; /* Avoid hitting slowpaths in the reloc processing which might yield a @@ -197,16 +196,10 @@ static void execN(int fd, uint32_t handle, uint64_t batch_size, unsigned flags, #undef reloc_ofs } -igt_simple_main +static void exhaustive(int fd) { uint32_t batch[2] = {MI_BATCH_BUFFER_END}; uint64_t batch_size, max, ggtt_max, reloc_ofs; - int fd; - - fd = drm_open_driver(DRIVER_INTEL); - igt_require_gem(fd); - - use_64bit_relocs = intel_gen(intel_get_drm_devid(fd)) >= 8; max = 3 * gem_aperture_size(fd) / 4; ggtt_max = 3 * gem_global_aperture_size(fd) / 4; @@ -258,6 +251,61 @@ igt_simple_main else batch_size *= 2; } +} + +static void single(int i915) +{ + const uint32_t bbe = MI_BATCH_BUFFER_END; + uint64_t batch_size, limit; + uint32_t handle; + void *ptr; + + batch_size = (intel_get_avail_ram_mb() - 128) << 20; /* CI slack */ + limit = gem_aperture_size(i915) - (256 << 10); /* low pages reserved */ + if (!gem_uses_full_ppgtt(i915)) + limit = 3 * limit / 4; + + batch_size = min(batch_size, limit); + batch_size = ALIGN(batch_size, 4096); + igt_info("Submitting a %'"PRId64"MiB batch, %saperture size %'"PRId64"MiB\n", + batch_size >> 20, + gem_uses_full_ppgtt(i915) ? "" : "shared ", + gem_aperture_size(i915) >> 20); + intel_require_memory(1, batch_size, CHECK_RAM); + + handle = gem_create(i915, batch_size); + gem_write(i915, handle, 0, &bbe, sizeof(bbe)); + + if (!FORCE_PREAD_PWRITE && gem_has_llc(i915)) + ptr = __gem_mmap__cpu(i915, handle, 0, batch_size, PROT_READ); + else if (!FORCE_PREAD_PWRITE && gem_mmap__has_wc(i915)) + ptr = __gem_mmap__wc(i915, handle, 0, batch_size, PROT_READ); + else + ptr = NULL; + + execN(i915, handle, batch_size, 0, ptr); + + if (ptr) + munmap(ptr, batch_size); +} + +igt_main +{ + int i915 = -1; + + igt_fixture { + i915 = drm_open_driver(DRIVER_INTEL); + igt_require_gem(i915); + + use_64bit_relocs = intel_gen(intel_get_drm_devid(i915)) >= 8; + } + + igt_subtest("single") + single(i915); + + igt_subtest("exhaustive") + exhaustive(i915); - close(fd); + igt_fixture + close(i915); } diff --git a/tests/intel-ci/blacklist.txt b/tests/intel-ci/blacklist.txt index a2101ae71..ae61efe3f 100644 --- a/tests/intel-ci/blacklist.txt +++ b/tests/intel-ci/blacklist.txt @@ -28,6 +28,7 @@ igt@gem_ctx_thrash(@.*)? igt@gem_evict_alignment(@.*)? igt@gem_evict_everything(@.*)? igt@gem_exec_alignment@(?!.*single).* +igt@gem_exec_big@(?!.*single).* igt@gem_exec_capture@many-(?!4K-).* igt@gem_exec_fence@(?!.*basic).* igt@gem_exec_flush@(?!.*basic).* From patchwork Thu Mar 14 14:19:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852983 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 37C5F17DF for ; Thu, 14 Mar 2019 14:20:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 23B182A423 for ; Thu, 14 Mar 2019 14:20:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1864C2A405; Thu, 14 Mar 2019 14:20:18 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 AEA2F2A4EC for ; Thu, 14 Mar 2019 14:20:16 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 152826E2DB; Thu, 14 Mar 2019 14:20:15 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5D0666E2DA; Thu, 14 Mar 2019 14:20:01 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889934-1500050 for multiple; Thu, 14 Mar 2019 14:19:43 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:25 +0000 Message-Id: <20190314141939.26246-11-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 11/25] kms_fence_pin_leak: Ask for the GPU before use 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Check that the GPU even exists before submitting a batch. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=109589 Signed-off-by: Chris Wilson --- tests/kms_fence_pin_leak.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/kms_fence_pin_leak.c b/tests/kms_fence_pin_leak.c index 62c52b627..e6c8b33c3 100644 --- a/tests/kms_fence_pin_leak.c +++ b/tests/kms_fence_pin_leak.c @@ -201,6 +201,7 @@ igt_simple_main igt_skip_on_simulation(); data.drm_fd = drm_open_driver_master(DRIVER_INTEL); + igt_require_gem(data.drm_fd); data.devid = intel_get_drm_devid(data.drm_fd); From patchwork Thu Mar 14 14:19:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852987 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D315418FD for ; Thu, 14 Mar 2019 14:20:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BC09728BBA for ; Thu, 14 Mar 2019 14:20:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B023B2A405; Thu, 14 Mar 2019 14:20:18 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 9CDC228BBA for ; Thu, 14 Mar 2019 14:20:17 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id AD8C16E2F9; Thu, 14 Mar 2019 14:20:15 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5E49A6E2E7; Thu, 14 Mar 2019 14:20:01 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889935-1500050 for multiple; Thu, 14 Mar 2019 14:19:43 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:26 +0000 Message-Id: <20190314141939.26246-12-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 12/25] drm-uapi: Import i915_drm.h upto 364df3d04d51 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP commit 364df3d04d51f0aad13b898f3dffca8c2d03d2b3 (HEAD) Author: Chris Wilson Date: Fri Jun 30 13:40:53 2017 +0100 drm/i915: Allow specification of parallel execbuf Signed-off-by: Chris Wilson --- include/drm-uapi/i915_drm.h | 372 +++++++++++++++++++++++++++++------- 1 file changed, 299 insertions(+), 73 deletions(-) diff --git a/include/drm-uapi/i915_drm.h b/include/drm-uapi/i915_drm.h index 43fb8ede2..cb6d66178 100644 --- a/include/drm-uapi/i915_drm.h +++ b/include/drm-uapi/i915_drm.h @@ -62,6 +62,28 @@ extern "C" { #define I915_ERROR_UEVENT "ERROR" #define I915_RESET_UEVENT "RESET" +/* + * i915_user_extension: Base class for defining a chain of extensions + * + * Many interfaces need to grow over time. In most cases we can simply + * extend the struct and have userspace pass in more data. Another option, + * as demonstrated by Vulkan's approach to providing extensions for forward + * and backward compatibility, is to use a list of optional structs to + * provide those extra details. + * + * The key advantage to using an extension chain is that it allows us to + * redefine the interface more easily than an ever growing struct of + * increasing complexity, and for large parts of that interface to be + * entirely optional. The downside is more pointer chasing; chasing across + * the boundary with pointers encapsulated inside u64. + */ +struct i915_user_extension { + __u64 next_extension; + __u32 name; + __u32 flags; /* All undefined bits must be zero. */ + __u32 rsvd[4]; /* Reserved for future use; must be zero. */ +}; + /* * MOCS indexes used for GPU surfaces, defining the cacheability of the * surface data and the coherency for this data wrt. CPU vs. GPU accesses. @@ -99,9 +121,14 @@ enum drm_i915_gem_engine_class { I915_ENGINE_CLASS_VIDEO = 2, I915_ENGINE_CLASS_VIDEO_ENHANCE = 3, + /* should be kept compact */ + I915_ENGINE_CLASS_INVALID = -1 }; +#define I915_ENGINE_CLASS_INVALID_NONE -1 +#define I915_ENGINE_CLASS_INVALID_VIRTUAL 0 + /** * DOC: perf_events exposed by i915 through /sys/bus/event_sources/drivers/i915 * @@ -319,6 +346,9 @@ typedef struct _drm_i915_sarea { #define DRM_I915_PERF_ADD_CONFIG 0x37 #define DRM_I915_PERF_REMOVE_CONFIG 0x38 #define DRM_I915_QUERY 0x39 +#define DRM_I915_GEM_VM_CREATE 0x3a +#define DRM_I915_GEM_VM_DESTROY 0x3b +/* Must be kept compact -- no holes */ #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -367,6 +397,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) #define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait) #define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create) +#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create_ext) #define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy) #define DRM_IOCTL_I915_REG_READ DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read) #define DRM_IOCTL_I915_GET_RESET_STATS DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats) @@ -377,6 +408,8 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config) #define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64) #define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query) +#define DRM_IOCTL_I915_GEM_VM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_CREATE, struct drm_i915_gem_vm_control) +#define DRM_IOCTL_I915_GEM_VM_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_VM_DESTROY, struct drm_i915_gem_vm_control) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -476,6 +509,7 @@ typedef struct drm_i915_irq_wait { #define I915_SCHEDULER_CAP_ENABLED (1ul << 0) #define I915_SCHEDULER_CAP_PRIORITY (1ul << 1) #define I915_SCHEDULER_CAP_PREEMPTION (1ul << 2) +#define I915_SCHEDULER_CAP_SEMAPHORES (1ul << 3) #define I915_PARAM_HUC_STATUS 42 @@ -559,6 +593,14 @@ typedef struct drm_i915_irq_wait { */ #define I915_PARAM_MMAP_GTT_COHERENT 52 +/* + * Query whether DRM_I915_GEM_EXECBUFFER2 supports coordination of parallel + * execution through use of explicit fence support. + * See I915_EXEC_FENCE_OUT and I915_EXEC_FENCE_SUBMIT. + */ +#define I915_PARAM_HAS_EXEC_SUBMIT_FENCE 53 +/* Must be kept compact -- no holes and well documented */ + typedef struct drm_i915_getparam { __s32 param; /* @@ -574,6 +616,7 @@ typedef struct drm_i915_getparam { #define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 #define I915_SETPARAM_ALLOW_BATCHBUFFER 3 #define I915_SETPARAM_NUM_USED_FENCES 4 +/* Must be kept compact -- no holes */ typedef struct drm_i915_setparam { int param; @@ -972,7 +1015,7 @@ struct drm_i915_gem_execbuffer2 { * struct drm_i915_gem_exec_fence *fences. */ __u64 cliprects_ptr; -#define I915_EXEC_RING_MASK (7<<0) +#define I915_EXEC_RING_MASK (0x3f) #define I915_EXEC_DEFAULT (0<<0) #define I915_EXEC_RENDER (1<<0) #define I915_EXEC_BSD (2<<0) @@ -1078,7 +1121,16 @@ struct drm_i915_gem_execbuffer2 { */ #define I915_EXEC_FENCE_ARRAY (1<<19) -#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1)) +/* + * Setting I915_EXEC_FENCE_SUBMIT implies that lower_32_bits(rsvd2) represent + * a sync_file fd to wait upon (in a nonblocking manner) prior to executing + * the batch. + * + * Returns -EINVAL if the sync_file fd cannot be found. + */ +#define I915_EXEC_FENCE_SUBMIT (1 << 20) + +#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SUBMIT << 1)) #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) #define i915_execbuffer2_set_context_id(eb2, context) \ @@ -1120,32 +1172,34 @@ struct drm_i915_gem_busy { * as busy may become idle before the ioctl is completed. * * Furthermore, if the object is busy, which engine is busy is only - * provided as a guide. There are race conditions which prevent the - * report of which engines are busy from being always accurate. - * However, the converse is not true. If the object is idle, the - * result of the ioctl, that all engines are idle, is accurate. + * provided as a guide and only indirectly by reporting its class + * (there may be more than one engine in each class). There are race + * conditions which prevent the report of which engines are busy from + * being always accurate. However, the converse is not true. If the + * object is idle, the result of the ioctl, that all engines are idle, + * is accurate. * * The returned dword is split into two fields to indicate both - * the engines on which the object is being read, and the - * engine on which it is currently being written (if any). + * the engine classess on which the object is being read, and the + * engine class on which it is currently being written (if any). * * The low word (bits 0:15) indicate if the object is being written * to by any engine (there can only be one, as the GEM implicit * synchronisation rules force writes to be serialised). Only the - * engine for the last write is reported. + * engine class (offset by 1, I915_ENGINE_CLASS_RENDER is reported as + * 1 not 0 etc) for the last write is reported. * - * The high word (bits 16:31) are a bitmask of which engines are - * currently reading from the object. Multiple engines may be + * The high word (bits 16:31) are a bitmask of which engines classes + * are currently reading from the object. Multiple engines may be * reading from the object simultaneously. * - * The value of each engine is the same as specified in the - * EXECBUFFER2 ioctl, i.e. I915_EXEC_RENDER, I915_EXEC_BSD etc. - * Note I915_EXEC_DEFAULT is a symbolic value and is mapped to - * the I915_EXEC_RENDER engine for execution, and so it is never + * The value of each engine class is the same as specified in the + * I915_CONTEXT_SET_ENGINES parameter and via perf, i.e. + * I915_ENGINE_CLASS_RENDER, I915_ENGINE_CLASS_COPY, etc. * reported as active itself. Some hardware may have parallel * execution engines, e.g. multiple media engines, which are - * mapped to the same identifier in the EXECBUFFER2 ioctl and - * so are not separately reported for busyness. + * mapped to the same class identifier and so are not separately + * reported for busyness. * * Caveat emptor: * Only the boolean result of this query is reliable; that is whether @@ -1412,65 +1466,18 @@ struct drm_i915_gem_wait { }; struct drm_i915_gem_context_create { - /* output: id of new context*/ - __u32 ctx_id; - __u32 pad; -}; - -struct drm_i915_gem_context_destroy { - __u32 ctx_id; - __u32 pad; -}; - -struct drm_i915_reg_read { - /* - * Register offset. - * For 64bit wide registers where the upper 32bits don't immediately - * follow the lower 32bits, the offset of the lower 32bits must - * be specified - */ - __u64 offset; -#define I915_REG_READ_8B_WA (1ul << 0) - - __u64 val; /* Return value */ -}; -/* Known registers: - * - * Render engine timestamp - 0x2358 + 64bit - gen7+ - * - Note this register returns an invalid value if using the default - * single instruction 8byte read, in order to workaround that pass - * flag I915_REG_READ_8B_WA in offset field. - * - */ - -struct drm_i915_reset_stats { - __u32 ctx_id; - __u32 flags; - - /* All resets since boot/module reload, for all contexts */ - __u32 reset_count; - - /* Number of batches lost when active in GPU, for this context */ - __u32 batch_active; - - /* Number of batches lost pending for execution, for this context */ - __u32 batch_pending; - + __u32 ctx_id; /* output: id of new context*/ __u32 pad; }; -struct drm_i915_gem_userptr { - __u64 user_ptr; - __u64 user_size; +struct drm_i915_gem_context_create_ext { + __u32 ctx_id; /* output: id of new context*/ __u32 flags; -#define I915_USERPTR_READ_ONLY 0x1 -#define I915_USERPTR_UNSYNCHRONIZED 0x80000000 - /** - * Returned handle for the object. - * - * Object handles are nonzero. - */ - __u32 handle; +#define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS (1u << 0) +#define I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE (1u << 1) +#define I915_CONTEXT_CREATE_FLAGS_UNKNOWN \ + (-(I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE << 1)) + __u64 extensions; }; struct drm_i915_gem_context_param { @@ -1511,6 +1518,43 @@ struct drm_i915_gem_context_param { * On creation, all new contexts are marked as recoverable. */ #define I915_CONTEXT_PARAM_RECOVERABLE 0x8 + + /* + * The id of the associated virtual memory address space (ppGTT) of + * this context. Can be retrieved and passed to another context + * (on the same fd) for both to use the same ppGTT and so share + * address layouts, and avoid reloading the page tables on context + * switches between themselves. + * + * See DRM_I915_GEM_VM_CREATE and DRM_I915_GEM_VM_DESTROY. + */ +#define I915_CONTEXT_PARAM_VM 0x9 + +/* + * I915_CONTEXT_PARAM_ENGINES: + * + * Bind this context to operate on this subset of available engines. Henceforth, + * the I915_EXEC_RING selector for DRM_IOCTL_I915_GEM_EXECBUFFER2 operates as + * an index into this array of engines; I915_EXEC_DEFAULT selecting engine[0] + * and upwards. Slots 0...N are filled in using the specified (class, instance). + * Use + * engine_class: I915_ENGINE_CLASS_INVALID, + * engine_instance: I915_ENGINE_CLASS_INVALID_NONE + * to specify a gap in the array that can be filled in later, e.g. by a + * virtual engine used for load balancing. + * + * Setting the number of engines bound to the context to 0, by passing a zero + * sized argument, will revert back to default settings. + * + * See struct i915_context_param_engines. + * + * Extensions: + * i915_context_engines_load_balance (I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE) + * i915_context_engines_bond (I915_CONTEXT_ENGINES_EXT_BOND) + */ +#define I915_CONTEXT_PARAM_ENGINES 0xa +/* Must be kept compact -- no holes and well documented */ + __u64 value; }; @@ -1543,9 +1587,10 @@ struct drm_i915_gem_context_param_sseu { __u16 engine_instance; /* - * Unused for now. Must be cleared to zero. + * Unknown flags must be cleared to zero. */ __u32 flags; +#define I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX (1u << 0) /* * Mask of slices to enable for the context. Valid values are a subset @@ -1573,6 +1618,186 @@ struct drm_i915_gem_context_param_sseu { __u32 rsvd; }; +/* + * i915_context_engines_load_balance: + * + * Enable load balancing across this set of engines. + * + * Into the I915_EXEC_DEFAULT slot [0], a virtual engine is created that when + * used will proxy the execbuffer request onto one of the set of engines + * in such a way as to distribute the load evenly across the set. + * + * The set of engines must be compatible (e.g. the same HW class) as they + * will share the same logical GPU context and ring. + * + * To intermix rendering with the virtual engine and direct rendering onto + * the backing engines (bypassing the load balancing proxy), the context must + * be defined to use a single timeline for all engines. + */ +struct i915_context_engines_load_balance { + struct i915_user_extension base; + + __u16 engine_index; + __u16 mbz16; /* reserved for future use; must be zero */ + __u32 flags; /* all undefined flags must be zero */ + + __u64 engines_mask; /* selection mask of engines[] */ + + __u64 mbz64[4]; /* reserved for future use; must be zero */ +}; + +/* + * i915_context_engines_bond: + * + * Constructed bonded pairs for execution within a virtual engine. + * + * All engines are equal, but some are more equal than others. Given + * the distribution of resources in the HW, it may be preferable to run + * a request on a given subset of engines in parallel to a request on a + * specific engine. We enable this selection of engines within a virtual + * engine by specifying bonding pairs, for any given master engine we will + * only execute on one of the corresponding siblings within the virtual engine. + * + * To execute a request in parallel on the master engine and a sibling requires + * coordination with a I915_EXEC_FENCE_SUBMIT. + */ +struct i915_context_engines_bond { + struct i915_user_extension base; + + __u16 virtual_index; /* index of virtual engine in ctx->engines[] */ + __u16 mbz; + + __u16 master_class; + __u16 master_instance; + + __u64 sibling_mask; /* bitmask of BIT(sibling_index) wrt the v.engine */ + __u64 flags; /* all undefined flags must be zero */ +}; + +struct i915_context_param_engines { + __u64 extensions; /* linked chain of extension blocks, 0 terminates */ +#define I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE 0 +#define I915_CONTEXT_ENGINES_EXT_BOND 1 + + struct { + __u16 engine_class; /* see enum drm_i915_gem_engine_class */ + __u16 engine_instance; + } class_instance[0]; +} __attribute__((packed)); + +#define I915_DEFINE_CONTEXT_PARAM_ENGINES(name__, N__) struct { \ + __u64 extensions; \ + struct { \ + __u16 engine_class; \ + __u16 engine_instance; \ + } class_instance[N__]; \ +} __attribute__((packed)) name__ + +struct drm_i915_gem_context_create_ext_setparam { +#define I915_CONTEXT_CREATE_EXT_SETPARAM 0 + struct i915_user_extension base; + struct drm_i915_gem_context_param param; +}; + +struct drm_i915_gem_context_create_ext_clone { +#define I915_CONTEXT_CREATE_EXT_CLONE 1 + struct i915_user_extension base; + __u32 clone_id; + __u32 flags; +#define I915_CONTEXT_CLONE_FLAGS (1u << 0) +#define I915_CONTEXT_CLONE_SCHEDATTR (1u << 1) +#define I915_CONTEXT_CLONE_SSEU (1u << 2) +#define I915_CONTEXT_CLONE_TIMELINE (1u << 3) +#define I915_CONTEXT_CLONE_VM (1u << 4) +#define I915_CONTEXT_CLONE_ENGINES (1u << 5) +#define I915_CONTEXT_CLONE_UNKNOWN -(I915_CONTEXT_CLONE_ENGINES << 1) + __u64 rsvd; +}; + +struct drm_i915_gem_context_destroy { + __u32 ctx_id; + __u32 pad; +}; + +/* + * DRM_I915_GEM_VM_CREATE - + * + * Create a new virtual memory address space (ppGTT) for use within a context + * on the same file. Extensions can be provided to configure exactly how the + * address space is setup upon creation. + * + * The id of new VM (bound to the fd) for use with I915_CONTEXT_PARAM_VM is + * returned in the outparam @id. + * + * No flags are defined, with all bits reserved and must be zero. + * + * An extension chain maybe provided, starting with @extensions, and terminated + * by the @next_extension being 0. Currently, no extensions are defined. + * + * DRM_I915_GEM_VM_DESTROY - + * + * Destroys a previously created VM id, specified in @id. + * + * No extensions or flags are allowed currently, and so must be zero. + */ +struct drm_i915_gem_vm_control { + __u64 extensions; + __u32 flags; + __u32 vm_id; +}; + +struct drm_i915_reg_read { + /* + * Register offset. + * For 64bit wide registers where the upper 32bits don't immediately + * follow the lower 32bits, the offset of the lower 32bits must + * be specified + */ + __u64 offset; +#define I915_REG_READ_8B_WA (1ul << 0) + + __u64 val; /* Return value */ +}; + +/* Known registers: + * + * Render engine timestamp - 0x2358 + 64bit - gen7+ + * - Note this register returns an invalid value if using the default + * single instruction 8byte read, in order to workaround that pass + * flag I915_REG_READ_8B_WA in offset field. + * + */ + +struct drm_i915_reset_stats { + __u32 ctx_id; + __u32 flags; + + /* All resets since boot/module reload, for all contexts */ + __u32 reset_count; + + /* Number of batches lost when active in GPU, for this context */ + __u32 batch_active; + + /* Number of batches lost pending for execution, for this context */ + __u32 batch_pending; + + __u32 pad; +}; + +struct drm_i915_gem_userptr { + __u64 user_ptr; + __u64 user_size; + __u32 flags; +#define I915_USERPTR_READ_ONLY 0x1 +#define I915_USERPTR_UNSYNCHRONIZED 0x80000000 + /** + * Returned handle for the object. + * + * Object handles are nonzero. + */ + __u32 handle; +}; + enum drm_i915_oa_format { I915_OA_FORMAT_A13 = 1, /* HSW only */ I915_OA_FORMAT_A29, /* HSW only */ @@ -1734,6 +1959,7 @@ struct drm_i915_perf_oa_config { struct drm_i915_query_item { __u64 query_id; #define DRM_I915_QUERY_TOPOLOGY_INFO 1 +/* Must be kept compact -- no holes and well documented */ /* * When set to zero by userspace, this is filled with the size of the From patchwork Thu Mar 14 14:19:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10853005 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8C5456C2 for ; Thu, 14 Mar 2019 14:21:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 77AA628BCE for ; Thu, 14 Mar 2019 14:21:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6BF362A381; Thu, 14 Mar 2019 14:21:40 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 8FF5C28BBA for ; Thu, 14 Mar 2019 14:21:38 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B99AF6E2E7; Thu, 14 Mar 2019 14:21:36 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 819096E2B5; Thu, 14 Mar 2019 14:21:31 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889936-1500050 for multiple; Thu, 14 Mar 2019 14:19:43 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:27 +0000 Message-Id: <20190314141939.26246-13-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 13/25] lib/i915: Improve gem_context error messages 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Avoid embedding the DRM_IOCTL() macro into the error message as it is unreadable, and instead always wrap the ioctl with a self-descriptive helper. Signed-off-by: Chris Wilson --- lib/i915/gem_context.c | 72 ++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/lib/i915/gem_context.c b/lib/i915/gem_context.c index 16004685e..8b4d5b704 100644 --- a/lib/i915/gem_context.c +++ b/lib/i915/gem_context.c @@ -113,16 +113,16 @@ uint32_t gem_context_create(int fd) int __gem_context_destroy(int fd, uint32_t ctx_id) { - struct drm_i915_gem_context_destroy destroy; - int ret; + struct drm_i915_gem_context_destroy destroy = { ctx_id }; + int err = 0; - memset(&destroy, 0, sizeof(destroy)); - destroy.ctx_id = ctx_id; + if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy)) { + err = -errno; + igt_assume(err); + } - ret = igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy); - if (ret) - return -errno; - return 0; + errno = 0; + return err; } /** @@ -134,21 +134,20 @@ int __gem_context_destroy(int fd, uint32_t ctx_id) */ void gem_context_destroy(int fd, uint32_t ctx_id) { - struct drm_i915_gem_context_destroy destroy; - - memset(&destroy, 0, sizeof(destroy)); - destroy.ctx_id = ctx_id; - - do_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy); + igt_assert_eq(__gem_context_destroy(fd, ctx_id), 0); } int __gem_context_get_param(int fd, struct drm_i915_gem_context_param *p) { - if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, p)) - return -errno; + int err = 0; + + if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, p)) { + err = -errno; + igt_assume(err); + } errno = 0; - return 0; + return err; } /** @@ -161,18 +160,22 @@ int __gem_context_get_param(int fd, struct drm_i915_gem_context_param *p) */ void gem_context_get_param(int fd, struct drm_i915_gem_context_param *p) { - igt_assert(__gem_context_get_param(fd, p) == 0); + igt_assert_eq(__gem_context_get_param(fd, p), 0); } - int __gem_context_set_param(int fd, struct drm_i915_gem_context_param *p) { - if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, p)) - return -errno; + int err = 0; + + if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, p)) { + err = -errno; + igt_assume(err); + } errno = 0; - return 0; + return err; } + /** * gem_context_set_param: * @fd: open i915 drm file descriptor @@ -183,7 +186,7 @@ int __gem_context_set_param(int fd, struct drm_i915_gem_context_param *p) */ void gem_context_set_param(int fd, struct drm_i915_gem_context_param *p) { - igt_assert(__gem_context_set_param(fd, p) == 0); + igt_assert_eq(__gem_context_set_param(fd, p), 0); } /** @@ -196,14 +199,9 @@ void gem_context_set_param(int fd, struct drm_i915_gem_context_param *p) */ void gem_context_require_param(int fd, uint64_t param) { - struct drm_i915_gem_context_param p; - - p.ctx_id = 0; - p.param = param; - p.value = 0; - p.size = 0; + struct drm_i915_gem_context_param p = { .param = param }; - igt_require(igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &p) == 0); + igt_require(__gem_context_get_param(fd, &p) == 0); } void gem_context_require_bannable(int fd) @@ -252,13 +250,11 @@ void gem_context_require_bannable(int fd) */ int __gem_context_set_priority(int fd, uint32_t ctx_id, int prio) { - struct drm_i915_gem_context_param p; - - memset(&p, 0, sizeof(p)); - p.ctx_id = ctx_id; - p.size = 0; - p.param = DRM_I915_CONTEXT_PARAM_PRIORITY; - p.value = prio; + struct drm_i915_gem_context_param p = { + .ctx_id = ctx_id, + .param = DRM_I915_CONTEXT_PARAM_PRIORITY, + .value = prio, + }; return __gem_context_set_param(fd, &p); } @@ -273,5 +269,5 @@ int __gem_context_set_priority(int fd, uint32_t ctx_id, int prio) */ void gem_context_set_priority(int fd, uint32_t ctx_id, int prio) { - igt_assert(__gem_context_set_priority(fd, ctx_id, prio) == 0); + igt_assert_eq(__gem_context_set_priority(fd, ctx_id, prio), 0); } From patchwork Thu Mar 14 14:19:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10853013 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D0C3213B5 for ; Thu, 14 Mar 2019 14:21:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BB09A28BC8 for ; Thu, 14 Mar 2019 14:21:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AF9B528BBA; Thu, 14 Mar 2019 14:21: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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 6090428BC8 for ; Thu, 14 Mar 2019 14:21:42 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 31DDE6E2EF; Thu, 14 Mar 2019 14:21:37 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7CFF16E2AE; Thu, 14 Mar 2019 14:21:31 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889937-1500050 for multiple; Thu, 14 Mar 2019 14:19:43 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:28 +0000 Message-Id: <20190314141939.26246-14-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 14/25] i915/gem_ctx_param: Test set/get (copy) VM 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Exercise reusing the GTT of one ctx in another. Signed-off-by: Chris Wilson --- tests/i915/gem_ctx_param.c | 83 ++++++++++++++++++++++++++++++++------ 1 file changed, 71 insertions(+), 12 deletions(-) diff --git a/tests/i915/gem_ctx_param.c b/tests/i915/gem_ctx_param.c index b3f8637df..54ade8b4b 100644 --- a/tests/i915/gem_ctx_param.c +++ b/tests/i915/gem_ctx_param.c @@ -36,17 +36,6 @@ IGT_TEST_DESCRIPTION("Basic test for context set/get param input validation."); #define NEW_CTX BIT(0) #define USER BIT(1) -static int reopen_driver(int fd) -{ - char path[256]; - - snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); - fd = open(path, O_RDWR); - igt_assert_lte(0, fd); - - return fd; -} - static void set_priority(int i915) { static const int64_t test_values[] = { @@ -91,7 +80,7 @@ static void set_priority(int i915) igt_permute_array(values, size, igt_exchange_int64); igt_fork(flags, NEW_CTX | USER) { - int fd = reopen_driver(i915); + int fd = gem_reopen_driver(i915); struct drm_i915_gem_context_param arg = { .param = I915_CONTEXT_PARAM_PRIORITY, .ctx_id = flags & NEW_CTX ? gem_context_create(fd) : 0, @@ -143,6 +132,73 @@ static void set_priority(int i915) free(values); } +static uint32_t __batch_create(int i915, uint32_t offset) +{ + const uint32_t bbe = MI_BATCH_BUFFER_END; + uint32_t handle; + + handle = gem_create(i915, ALIGN(offset + 4, 4096)); + gem_write(i915, handle, offset, &bbe, sizeof(bbe)); + + return handle; +} + +static uint32_t batch_create(int i915) +{ + return __batch_create(i915, 0); +} + +static void test_vm(int i915) +{ + struct drm_i915_gem_exec_object2 batch = { + .handle = batch_create(i915), + }; + struct drm_i915_gem_execbuffer2 eb = { + .buffers_ptr = to_user_pointer(&batch), + .buffer_count = 1, + }; + struct drm_i915_gem_context_param arg = { + .param = I915_CONTEXT_PARAM_VM, + }; + uint32_t parent, child; + + arg.value = -1ull; + igt_require(__gem_context_set_param(i915, &arg) == -ENOENT); + + parent = gem_context_create(i915); + child = gem_context_create(i915); + + eb.rsvd1 = parent; + batch.offset = 48 << 20; + gem_execbuf(i915, &eb); + igt_assert_eq_u64(batch.offset, 48 << 20); + + eb.rsvd1 = child; + batch.offset = 0; + gem_execbuf(i915, &eb); + igt_assert_eq_u64(batch.offset, 0); + + eb.rsvd1 = parent; + gem_execbuf(i915, &eb); + igt_assert_eq_u64(batch.offset, 48 << 20); + + arg.ctx_id = parent; + gem_context_get_param(i915, &arg); + + arg.ctx_id = child; + gem_context_set_param(i915, &arg); + + eb.rsvd1 = child; + gem_execbuf(i915, &eb); + igt_assert_eq_u64(batch.offset, 48 << 20); + + gem_context_destroy(i915, child); + gem_context_destroy(i915, parent); + + gem_sync(i915, batch.handle); + gem_close(i915, batch.handle); +} + igt_main { struct drm_i915_gem_context_param arg; @@ -253,6 +309,9 @@ igt_main gem_context_set_param(fd, &arg); } + igt_subtest("vm") + test_vm(fd); + arg.param = I915_CONTEXT_PARAM_PRIORITY; igt_subtest("set-priority-not-supported") { From patchwork Thu Mar 14 14:19:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852991 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C5DD11850 for ; Thu, 14 Mar 2019 14:20:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B04D328BBA for ; Thu, 14 Mar 2019 14:20:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A4DB52A405; Thu, 14 Mar 2019 14:20:20 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 5DF1128BBA for ; Thu, 14 Mar 2019 14:20:20 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9961E6E2E9; Thu, 14 Mar 2019 14:20:17 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1D9E26E2DC; Thu, 14 Mar 2019 14:20:00 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889938-1500050 for multiple; Thu, 14 Mar 2019 14:19:43 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:29 +0000 Message-Id: <20190314141939.26246-15-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 15/25] i915/gem_ctx_create: Basic checks for constructor properties 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Check that the extended create interface accepts setparam. Signed-off-by: Chris Wilson --- tests/i915/gem_ctx_create.c | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tests/i915/gem_ctx_create.c b/tests/i915/gem_ctx_create.c index a664070db..e12f41691 100644 --- a/tests/i915/gem_ctx_create.c +++ b/tests/i915/gem_ctx_create.c @@ -308,6 +308,60 @@ static void maximum(int fd, int ncpus, unsigned mode) free(contexts); } +static int __create_ext(int i915, struct drm_i915_gem_context_create_ext *arg) +{ + int err; + + err = 0; + if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT, arg)) + err = -errno; + + errno = 0; + return err; +} + +static void basic_ext_param(int i915) +{ + struct drm_i915_gem_context_create_ext_setparam ext = { + { .name = I915_CONTEXT_CREATE_EXT_SETPARAM }, + }; + struct drm_i915_gem_context_create_ext create = { + .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS + }; + struct drm_i915_gem_context_param get; + + igt_require(__create_ext(i915, &create) == 0); + gem_context_destroy(i915, create.ctx_id); + + create.extensions = -1ull; + igt_assert_eq(__create_ext(i915, &create), -EFAULT); + + create.extensions = to_user_pointer(&ext); + igt_assert_eq(__create_ext(i915, &create), -EINVAL); + + ext.param.param = I915_CONTEXT_PARAM_PRIORITY; + if (__create_ext(i915, &create) != -ENODEV) { + gem_context_destroy(i915, create.ctx_id); + + ext.base.next_extension = -1ull; + igt_assert_eq(__create_ext(i915, &create), -EFAULT); + ext.base.next_extension = to_user_pointer(&ext); + igt_assert_eq(__create_ext(i915, &create), -E2BIG); + ext.base.next_extension = 0; + + ext.param.value = 32; + igt_assert_eq(__create_ext(i915, &create), 0); + + memset(&get, 0, sizeof(get)); + get.ctx_id = create.ctx_id; + get.param = I915_CONTEXT_PARAM_PRIORITY; + gem_context_get_param(i915, &get); + igt_assert_eq(get.value, ext.param.value); + + gem_context_destroy(i915, create.ctx_id); + } +} + igt_main { const int ncpus = sysconf(_SC_NPROCESSORS_ONLN); @@ -352,6 +406,9 @@ igt_main igt_assert_eq(__gem_context_create_local(fd, &create), -EINVAL); } + igt_subtest("ext-param") + basic_ext_param(fd); + igt_subtest("maximum-mem") maximum(fd, ncpus, CHECK_RAM); igt_subtest("maximum-swap") From patchwork Thu Mar 14 14:19:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852985 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A63BB18A6 for ; Thu, 14 Mar 2019 14:20:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8D55C2A422 for ; Thu, 14 Mar 2019 14:20:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 81F3F2A405; Thu, 14 Mar 2019 14:20:18 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 5BD372A422 for ; Thu, 14 Mar 2019 14:20:10 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E97D86E2EA; Thu, 14 Mar 2019 14:20:02 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4A55C6E2E1; Thu, 14 Mar 2019 14:20:00 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889939-1500050 for multiple; Thu, 14 Mar 2019 14:19:44 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:30 +0000 Message-Id: <20190314141939.26246-16-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 16/25] i915: Add gem_ctx_clone 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Exercise cloning contexts, an extension of merely creating one. Signed-off-by: Chris Wilson --- tests/Makefile.sources | 1 + tests/i915/gem_ctx_clone.c | 421 +++++++++++++++++++++++++++++++++++++ tests/meson.build | 1 + 3 files changed, 423 insertions(+) create mode 100644 tests/i915/gem_ctx_clone.c diff --git a/tests/Makefile.sources b/tests/Makefile.sources index 71ccf00af..6d0fe1c95 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -21,6 +21,7 @@ TESTS_progs = \ drm_import_export \ drm_mm \ drm_read \ + i915/gem_ctx_clone \ kms_3d \ kms_addfb_basic \ kms_atomic \ diff --git a/tests/i915/gem_ctx_clone.c b/tests/i915/gem_ctx_clone.c new file mode 100644 index 000000000..7d83c6350 --- /dev/null +++ b/tests/i915/gem_ctx_clone.c @@ -0,0 +1,421 @@ +/* + * Copyright © 2019 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 "i915/gem_vm.h" +#include "i915_drm.h" + +static int __create_ext(int i915, struct drm_i915_gem_context_create_ext *arg) +{ + int err; + + err = 0; + if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT, arg)) + err = -errno; + + errno = 0; + return err; +} + +static bool has_ctx_clone(int i915) +{ + struct drm_i915_gem_context_create_ext_clone ext = { + { .name = I915_CONTEXT_CREATE_EXT_CLONE }, + .clone_id = -1, + }; + struct drm_i915_gem_context_create_ext create = { + .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS, + .extensions = to_user_pointer(&ext), + }; + return __create_ext(i915, &create) == -ENOENT; +} + +static void invalid_clone(int i915) +{ + struct drm_i915_gem_context_create_ext_clone ext = { + { .name = I915_CONTEXT_CREATE_EXT_CLONE }, + }; + struct drm_i915_gem_context_create_ext create = { + .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS, + .extensions = to_user_pointer(&ext), + }; + + igt_assert_eq(__create_ext(i915, &create), 0); + gem_context_destroy(i915, create.ctx_id); + + ext.flags = -1; /* Hopefully we won't run out of flags */ + igt_assert_eq(__create_ext(i915, &create), -EINVAL); + ext.flags = 0; + + ext.base.next_extension = -1; + igt_assert_eq(__create_ext(i915, &create), -EFAULT); + ext.base.next_extension = to_user_pointer(&ext); + igt_assert_eq(__create_ext(i915, &create), -E2BIG); + ext.base.next_extension = 0; + + ext.clone_id = -1; + igt_assert_eq(__create_ext(i915, &create), -ENOENT); + ext.clone_id = 0; +} + +static void clone_flags(int i915) +{ + struct drm_i915_gem_context_create_ext_setparam set = { + { .name = I915_CONTEXT_CREATE_EXT_SETPARAM }, + { .param = I915_CONTEXT_PARAM_RECOVERABLE }, + }; + struct drm_i915_gem_context_create_ext_clone ext = { + { .name = I915_CONTEXT_CREATE_EXT_CLONE }, + .flags = I915_CONTEXT_CLONE_FLAGS, + }; + struct drm_i915_gem_context_create_ext create = { + .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS, + .extensions = to_user_pointer(&ext), + }; + int expected; + + set.param.value = 1; /* default is recoverable */ + igt_require(__gem_context_set_param(i915, &set.param) == 0); + + for (int pass = 0; pass < 2; pass++) { /* cloning default, then child */ + igt_debug("Cloning %d\n", ext.clone_id); + igt_assert_eq(__create_ext(i915, &create), 0); + + set.param.ctx_id = ext.clone_id; + gem_context_get_param(i915, &set.param); + expected = set.param.value; + + set.param.ctx_id = create.ctx_id; + gem_context_get_param(i915, &set.param); + + igt_assert_eq_u64(set.param.param, + I915_CONTEXT_PARAM_RECOVERABLE); + igt_assert_eq((int)set.param.value, expected); + + gem_context_destroy(i915, create.ctx_id); + + expected = set.param.value = 0; + set.param.ctx_id = ext.clone_id; + gem_context_set_param(i915, &set.param); + + igt_assert_eq(__create_ext(i915, &create), 0); + + set.param.ctx_id = create.ctx_id; + gem_context_get_param(i915, &set.param); + + igt_assert_eq_u64(set.param.param, + I915_CONTEXT_PARAM_RECOVERABLE); + igt_assert_eq((int)set.param.value, expected); + + gem_context_destroy(i915, create.ctx_id); + + /* clone but then reset priority to default */ + set.param.ctx_id = 0; + set.param.value = 1; + ext.base.next_extension = to_user_pointer(&set); + igt_assert_eq(__create_ext(i915, &create), 0); + ext.base.next_extension = 0; + + set.param.ctx_id = create.ctx_id; + gem_context_get_param(i915, &set.param); + igt_assert_eq_u64(set.param.value, 1); + + set.param.ctx_id = ext.clone_id; + gem_context_get_param(i915, &set.param); + igt_assert_eq_u64(set.param.value, 0); + + gem_context_destroy(i915, create.ctx_id); + ext.clone_id = gem_context_create(i915); + } + + gem_context_destroy(i915, ext.clone_id); +} + +static void clone_engines(int i915) +{ + struct drm_i915_gem_context_create_ext_setparam set = { + { .name = I915_CONTEXT_CREATE_EXT_SETPARAM }, + { .param = I915_CONTEXT_PARAM_ENGINES }, + }; + struct drm_i915_gem_context_create_ext_clone ext = { + { .name = I915_CONTEXT_CREATE_EXT_CLONE }, + .flags = I915_CONTEXT_CLONE_ENGINES, + }; + struct drm_i915_gem_context_create_ext create = { + .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS, + .extensions = to_user_pointer(&ext), + }; + I915_DEFINE_CONTEXT_PARAM_ENGINES(expected, 64); + I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, 64); + uint64_t ex_size; + + memset(&expected, 0, sizeof(expected)); + memset(&engines, 0, sizeof(engines)); + + igt_require(__gem_context_set_param(i915, &set.param) == 0); + + for (int pass = 0; pass < 2; pass++) { /* cloning default, then child */ + igt_debug("Cloning %d\n", ext.clone_id); + igt_assert_eq(__create_ext(i915, &create), 0); + + set.param.ctx_id = ext.clone_id; + set.param.size = sizeof(expected); + set.param.value = to_user_pointer(&expected); + gem_context_get_param(i915, &set.param); + ex_size = set.param.size; + + set.param.ctx_id = create.ctx_id; + set.param.size = sizeof(engines); + set.param.value = to_user_pointer(&engines); + gem_context_get_param(i915, &set.param); + + igt_assert_eq_u64(set.param.param, I915_CONTEXT_PARAM_ENGINES); + igt_assert_eq_u64(set.param.size, ex_size); + igt_assert(!memcmp(&engines, &expected, ex_size)); + + gem_context_destroy(i915, create.ctx_id); + + expected.class_instance[0].engine_class = + I915_ENGINE_CLASS_INVALID; + expected.class_instance[0].engine_instance = + I915_ENGINE_CLASS_INVALID_NONE; + ex_size = (sizeof(struct i915_context_param_engines) + + sizeof(expected.class_instance[0])); + + set.param.ctx_id = ext.clone_id; + set.param.size = ex_size; + set.param.value = to_user_pointer(&expected); + gem_context_set_param(i915, &set.param); + + igt_assert_eq(__create_ext(i915, &create), 0); + + set.param.ctx_id = create.ctx_id; + set.param.size = sizeof(engines); + set.param.value = to_user_pointer(&engines); + gem_context_get_param(i915, &set.param); + + igt_assert_eq_u64(set.param.size, ex_size); + igt_assert(!memcmp(&engines, &expected, ex_size)); + + gem_context_destroy(i915, create.ctx_id); + + /* clone but then reset engines to default */ + set.param.ctx_id = 0; + set.param.size = 0; + set.param.value = 0; + ext.base.next_extension = to_user_pointer(&set); + + igt_assert_eq(__create_ext(i915, &create), 0); + ext.base.next_extension = 0; + + set.param.ctx_id = create.ctx_id; + set.param.size = sizeof(engines); + set.param.value = to_user_pointer(&engines); + gem_context_get_param(i915, &set.param); + igt_assert_eq_u64(set.param.size, 0); + + gem_context_destroy(i915, create.ctx_id); + + /* And check we ignore the flag */ + ext.flags = 0; + igt_assert_eq(__create_ext(i915, &create), 0); + ext.flags = I915_CONTEXT_CLONE_ENGINES; + + set.param.ctx_id = create.ctx_id; + set.param.size = sizeof(engines); + set.param.value = to_user_pointer(&engines); + gem_context_get_param(i915, &set.param); + igt_assert_eq_u64(set.param.size, 0); + + ext.clone_id = gem_context_create(i915); + } + + gem_context_destroy(i915, ext.clone_id); +} + +static void clone_scheduler(int i915) +{ + struct drm_i915_gem_context_create_ext_setparam set = { + { .name = I915_CONTEXT_CREATE_EXT_SETPARAM }, + { .param = I915_CONTEXT_PARAM_PRIORITY }, + }; + struct drm_i915_gem_context_create_ext_clone ext = { + { .name = I915_CONTEXT_CREATE_EXT_CLONE }, + .flags = I915_CONTEXT_CLONE_SCHEDATTR, + }; + struct drm_i915_gem_context_create_ext create = { + .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS, + .extensions = to_user_pointer(&ext), + }; + int expected; + + igt_require(__gem_context_set_param(i915, &set.param) == 0); + + for (int pass = 0; pass < 2; pass++) { /* cloning default, then child */ + igt_debug("Cloning %d\n", ext.clone_id); + igt_assert_eq(__create_ext(i915, &create), 0); + + set.param.ctx_id = ext.clone_id; + gem_context_get_param(i915, &set.param); + expected = set.param.value; + + set.param.ctx_id = create.ctx_id; + gem_context_get_param(i915, &set.param); + + igt_assert_eq_u64(set.param.param, I915_CONTEXT_PARAM_PRIORITY); + igt_assert_eq((int)set.param.value, expected); + + gem_context_destroy(i915, create.ctx_id); + + expected = set.param.value = 1; + set.param.ctx_id = ext.clone_id; + gem_context_set_param(i915, &set.param); + + igt_assert_eq(__create_ext(i915, &create), 0); + + set.param.ctx_id = create.ctx_id; + gem_context_get_param(i915, &set.param); + + igt_assert_eq_u64(set.param.param, I915_CONTEXT_PARAM_PRIORITY); + igt_assert_eq((int)set.param.value, expected); + + gem_context_destroy(i915, create.ctx_id); + + /* clone but then reset priority to default */ + set.param.ctx_id = 0; + set.param.value = 0; + ext.base.next_extension = to_user_pointer(&set); + igt_assert_eq(__create_ext(i915, &create), 0); + ext.base.next_extension = 0; + + set.param.ctx_id = create.ctx_id; + gem_context_get_param(i915, &set.param); + igt_assert_eq_u64(set.param.value, 0); + + set.param.ctx_id = ext.clone_id; + gem_context_get_param(i915, &set.param); + igt_assert_eq_u64(set.param.value, 1); + + gem_context_destroy(i915, create.ctx_id); + ext.clone_id = gem_context_create(i915); + } + + gem_context_destroy(i915, ext.clone_id); +} + +static void clone_vm(int i915) +{ + struct drm_i915_gem_context_create_ext_setparam set = { + { .name = I915_CONTEXT_CREATE_EXT_SETPARAM }, + { .param = I915_CONTEXT_PARAM_VM }, + }; + struct drm_i915_gem_context_create_ext_clone ext = { + { .name = I915_CONTEXT_CREATE_EXT_CLONE }, + .flags = I915_CONTEXT_CLONE_VM, + }; + struct drm_i915_gem_context_create_ext create = { + .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS, + .extensions = to_user_pointer(&ext), + }; + uint32_t vm_id[2]; + int expected; + + igt_require(__gem_context_set_param(i915, &set.param) == -ENOENT); + + set.param.ctx_id = gem_context_create(i915); + gem_context_get_param(i915, &set.param); + vm_id[0] = set.param.value; + gem_context_destroy(i915, set.param.ctx_id); + set.param.ctx_id = 0; + + vm_id[1] = gem_vm_create(i915); + + for (int pass = 0; pass < 2; pass++) { /* cloning default, then child */ + igt_debug("Cloning %d\n", ext.clone_id); + igt_assert_eq(__create_ext(i915, &create), 0); + + set.param.ctx_id = ext.clone_id; + gem_context_get_param(i915, &set.param); + expected = set.param.value; + + set.param.ctx_id = create.ctx_id; + gem_context_get_param(i915, &set.param); + + igt_assert_eq_u64(set.param.param, I915_CONTEXT_PARAM_VM); + igt_assert_eq((int)set.param.value, expected); + + gem_context_destroy(i915, create.ctx_id); + + expected = set.param.value = vm_id[0]; + set.param.ctx_id = ext.clone_id; + gem_context_set_param(i915, &set.param); + + igt_assert_eq(__create_ext(i915, &create), 0); + + set.param.ctx_id = create.ctx_id; + gem_context_get_param(i915, &set.param); + + igt_assert_eq_u64(set.param.param, I915_CONTEXT_PARAM_VM); + igt_assert_eq((int)set.param.value, expected); + + gem_context_destroy(i915, create.ctx_id); + ext.clone_id = gem_context_create(i915); + } + + gem_context_destroy(i915, ext.clone_id); + + for (int i = 0; i < ARRAY_SIZE(vm_id); i++) + gem_vm_destroy(i915, vm_id[i]); +} + +igt_main +{ + int i915 = -1; + + igt_fixture { + i915 = drm_open_driver(DRIVER_INTEL); + igt_require_gem(i915); + gem_require_contexts(i915); + + igt_require(has_ctx_clone(i915)); + } + + igt_subtest("invalid") + invalid_clone(i915); + + igt_subtest("engines") + clone_engines(i915); + + igt_subtest("flags") + clone_flags(i915); + + igt_subtest("scheduler") + clone_scheduler(i915); + + igt_subtest("vm") + clone_vm(i915); + + igt_fixture { + close(i915); + } +} diff --git a/tests/meson.build b/tests/meson.build index 9015f809e..2b6132345 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -108,6 +108,7 @@ i915_progs = [ 'gem_cs_prefetch', 'gem_cs_tlb', 'gem_ctx_bad_destroy', + 'gem_ctx_clone', 'gem_ctx_create', 'gem_ctx_exec', 'gem_ctx_isolation', From patchwork Thu Mar 14 14:19:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10853011 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2679D17DF for ; Thu, 14 Mar 2019 14:21:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 148B228BBA for ; Thu, 14 Mar 2019 14:21:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 08EAD29F05; Thu, 14 Mar 2019 14:21: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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 2DE1928BBA for ; Thu, 14 Mar 2019 14:21:41 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 933686E2E3; Thu, 14 Mar 2019 14:21:36 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7AC656E255; Thu, 14 Mar 2019 14:21:31 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889940-1500050 for multiple; Thu, 14 Mar 2019 14:19:44 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:31 +0000 Message-Id: <20190314141939.26246-17-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 17/25] i915: Add gem_vm_create 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Exercise basic creation and swapping between new address spaces. Signed-off-by: Chris Wilson --- lib/Makefile.sources | 2 + lib/i915/gem_vm.c | 130 ++++++++++++++++++++ lib/i915/gem_vm.h | 38 ++++++ lib/meson.build | 1 + tests/Makefile.sources | 1 + tests/i915/gem_vm_create.c | 236 +++++++++++++++++++++++++++++++++++++ tests/meson.build | 1 + 7 files changed, 409 insertions(+) create mode 100644 lib/i915/gem_vm.c create mode 100644 lib/i915/gem_vm.h create mode 100644 tests/i915/gem_vm_create.c diff --git a/lib/Makefile.sources b/lib/Makefile.sources index e00347f94..a7074209a 100644 --- a/lib/Makefile.sources +++ b/lib/Makefile.sources @@ -13,6 +13,8 @@ lib_source_list = \ i915/gem_ring.c \ i915/gem_mman.c \ i915/gem_mman.h \ + i915/gem_vm.c \ + i915/gem_vm.h \ i915_3d.h \ i915_reg.h \ i915_pciids.h \ diff --git a/lib/i915/gem_vm.c b/lib/i915/gem_vm.c new file mode 100644 index 000000000..e0d46d509 --- /dev/null +++ b/lib/i915/gem_vm.c @@ -0,0 +1,130 @@ +/* + * Copyright © 2019 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 + +#include "ioctl_wrappers.h" +#include "drmtest.h" + +#include "i915/gem_vm.h" + +/** + * SECTION:gem_vm + * @short_description: Helpers for dealing with address spaces (vm/GTT) + * @title: GEM Virtual Memory + * + * This helper library contains functions used for handling gem address + * spaces.. + */ + +/** + * gem_has_vm: + * @i915: open i915 drm file descriptor + * + * Returns: whether VM creation is supported or not. + */ +bool gem_has_vm(int i915) +{ + uint32_t vm_id = 0; + + __gem_vm_create(i915, &vm_id); + if (vm_id) + gem_vm_destroy(i915, vm_id); + + return vm_id; +} + +/** + * gem_require_vm: + * @i915: open i915 drm file descriptor + * + * This helper will automatically skip the test on platforms where address + * space creation is not available. + */ +void gem_require_vm(int i915) +{ + igt_require(gem_has_vm(i915)); +} + +int __gem_vm_create(int i915, uint32_t *vm_id) +{ + struct drm_i915_gem_vm_control ctl = {}; + int err = 0; + + if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_VM_CREATE, &ctl) == 0) { + *vm_id = ctl.vm_id; + } else { + err = -errno; + igt_assume(err != 0); + } + + errno = 0; + return err; +} + +/** + * gem_vm_create: + * @i915: open i915 drm file descriptor + * + * This wraps the VM_CREATE ioctl, which is used to allocate a new + * vm_set_caching() this wrapper skips on + * kernels and platforms where address space support is not available. + * + * Returns: The id of the allocated address space. + */ +uint32_t gem_vm_create(int i915) +{ + uint32_t vm_id; + + igt_assert_eq(__gem_vm_create(i915, &vm_id), 0); + igt_assert(vm_id != 0); + + return vm_id; +} + +int __gem_vm_destroy(int i915, uint32_t vm_id) +{ + struct drm_i915_gem_vm_control ctl = { .vm_id = vm_id }; + int err = 0; + + if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_VM_DESTROY, &ctl)) { + err = -errno; + igt_assume(err); + } + + errno = 0; + return err; +} + +/** + * gem_vm_destroy: + * @i915: open i915 drm file descriptor + * @vm_id: i915 VM id + * + * This wraps the VM_DESTROY ioctl, which is used to free an address space. + */ +void gem_vm_destroy(int i915, uint32_t vm_id) +{ + igt_assert_eq(__gem_vm_destroy(i915, vm_id), 0); +} diff --git a/lib/i915/gem_vm.h b/lib/i915/gem_vm.h new file mode 100644 index 000000000..27af899d4 --- /dev/null +++ b/lib/i915/gem_vm.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2019 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef GEM_VM_H +#define GEM_VM_H + +#include + +bool gem_has_vm(int i915); +void gem_require_vm(int i915); + +uint32_t gem_vm_create(int i915); +int __gem_vm_create(int i915, uint32_t *vm_id); + +void gem_vm_destroy(int i915, uint32_t vm_id); +int __gem_vm_destroy(int i915, uint32_t vm_id); + +#endif /* GEM_VM_H */ diff --git a/lib/meson.build b/lib/meson.build index 89de06e69..f95922330 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -5,6 +5,7 @@ lib_sources = [ 'i915/gem_submission.c', 'i915/gem_ring.c', 'i915/gem_mman.c', + 'i915/gem_vm.c', 'igt_color_encoding.c', 'igt_debugfs.c', 'igt_device.c', diff --git a/tests/Makefile.sources b/tests/Makefile.sources index 6d0fe1c95..12f4bbd75 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -22,6 +22,7 @@ TESTS_progs = \ drm_mm \ drm_read \ i915/gem_ctx_clone \ + i915/gem_vm_create \ kms_3d \ kms_addfb_basic \ kms_atomic \ diff --git a/tests/i915/gem_vm_create.c b/tests/i915/gem_vm_create.c new file mode 100644 index 000000000..0264fa301 --- /dev/null +++ b/tests/i915/gem_vm_create.c @@ -0,0 +1,236 @@ +/* + * Copyright © 2019 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_dummyload.h" +#include "i915/gem_vm.h" + +static int __gem_vm_create_local(int i915, struct drm_i915_gem_vm_control *ctl) +{ + int err = 0; + if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_VM_CREATE, ctl)) { + err = -errno; + igt_assume(err); + } + errno = 0; + return err; +} + +static int __gem_vm_destroy_local(int i915, struct drm_i915_gem_vm_control *ctl) +{ + int err = 0; + if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_VM_DESTROY, ctl)) { + err = -errno; + igt_assume(err); + } + errno = 0; + return err; +} + +static bool has_vm(int i915) +{ + struct drm_i915_gem_vm_control ctl = {}; + int err; + + err = __gem_vm_create_local(i915, &ctl); + switch (err) { + case -EINVAL: /* unknown ioctl */ + case -ENODEV: /* !full-ppgtt */ + return false; + + case 0: + gem_vm_destroy(i915, ctl.vm_id); + return true; + + default: + igt_fail_on_f(err, "Unknown response from VM_CREATE\n"); + return false; + } +} + +static void invalid_create(int i915) +{ + struct drm_i915_gem_vm_control ctl = {}; + struct i915_user_extension ext = { .name = -1 }; + + igt_assert_eq(__gem_vm_create_local(i915, &ctl), 0); + gem_vm_destroy(i915, ctl.vm_id); + + ctl.vm_id = 0xdeadbeef; + igt_assert_eq(__gem_vm_create_local(i915, &ctl), 0); + gem_vm_destroy(i915, ctl.vm_id); + ctl.vm_id = 0; + + ctl.flags = -1; + igt_assert_eq(__gem_vm_create_local(i915, &ctl), -EINVAL); + ctl.flags = 0; + + ctl.extensions = -1; + igt_assert_eq(__gem_vm_create_local(i915, &ctl), -EFAULT); + ctl.extensions = to_user_pointer(&ext); + igt_assert_eq(__gem_vm_create_local(i915, &ctl), -EINVAL); + ctl.extensions = 0; +} + +static void invalid_destroy(int i915) +{ + struct drm_i915_gem_vm_control ctl = {}; + + igt_assert_eq(__gem_vm_destroy_local(i915, &ctl), -ENOENT); + + igt_assert_eq(__gem_vm_create_local(i915, &ctl), 0); + igt_assert_eq(__gem_vm_destroy_local(i915, &ctl), 0); + igt_assert_eq(__gem_vm_destroy_local(i915, &ctl), -ENOENT); + + igt_assert_eq(__gem_vm_create_local(i915, &ctl), 0); + ctl.vm_id = ctl.vm_id + 1; /* XXX assume cyclic allocator */ + igt_assert_eq(__gem_vm_destroy_local(i915, &ctl), -ENOENT); + ctl.vm_id = ctl.vm_id - 1; + igt_assert_eq(__gem_vm_destroy_local(i915, &ctl), 0); + + igt_assert_eq(__gem_vm_create_local(i915, &ctl), 0); + ctl.flags = -1; + igt_assert_eq(__gem_vm_destroy_local(i915, &ctl), -EINVAL); + ctl.flags = 0; + igt_assert_eq(__gem_vm_destroy_local(i915, &ctl), 0); + + igt_assert_eq(__gem_vm_create_local(i915, &ctl), 0); + ctl.extensions = -1; + igt_assert_eq(__gem_vm_destroy_local(i915, &ctl), -EINVAL); + ctl.extensions = 0; + igt_assert_eq(__gem_vm_destroy_local(i915, &ctl), 0); +} + +static uint32_t __batch_create(int i915, uint32_t offset) +{ + const uint32_t bbe = MI_BATCH_BUFFER_END; + uint32_t handle; + + handle = gem_create(i915, ALIGN(offset + 4, 4096)); + gem_write(i915, handle, offset, &bbe, sizeof(bbe)); + + return handle; +} + +static uint32_t batch_create(int i915) +{ + return __batch_create(i915, 0); +} + +static void execbuf(int i915) +{ + struct drm_i915_gem_exec_object2 batch = { + .handle = batch_create(i915), + }; + struct drm_i915_gem_execbuffer2 eb = { + .buffers_ptr = to_user_pointer(&batch), + .buffer_count = 1, + }; + struct drm_i915_gem_context_param arg = { + .param = I915_CONTEXT_PARAM_VM, + }; + + /* First verify that we try to use "softpinning" by default */ + batch.offset = 48 << 20; + gem_execbuf(i915, &eb); + igt_assert_eq_u64(batch.offset, 48 << 20); + + arg.value = gem_vm_create(i915); + gem_context_set_param(i915, &arg); + gem_execbuf(i915, &eb); + igt_assert_eq_u64(batch.offset, 48 << 20); + gem_vm_destroy(i915, arg.value); + + arg.value = gem_vm_create(i915); + gem_context_set_param(i915, &arg); + batch.offset = 0; + gem_execbuf(i915, &eb); + igt_assert_eq_u64(batch.offset, 0); + gem_vm_destroy(i915, arg.value); + + gem_sync(i915, batch.handle); + gem_close(i915, batch.handle); +} + +static void async_destroy(int i915) +{ + struct drm_i915_gem_context_param arg = { + .ctx_id = gem_context_create(i915), + .value = gem_vm_create(i915), + .param = I915_CONTEXT_PARAM_VM, + }; + igt_spin_t *spin[2]; + + spin[0] = igt_spin_batch_new(i915, + .ctx = arg.ctx_id, + .flags = IGT_SPIN_POLL_RUN); + igt_spin_busywait_until_running(spin[0]); + + gem_context_set_param(i915, &arg); + spin[1] = __igt_spin_batch_new(i915, .ctx = arg.ctx_id); + + igt_spin_batch_end(spin[0]); + gem_sync(i915, spin[0]->handle); + + gem_vm_destroy(i915, arg.value); + gem_context_destroy(i915, arg.ctx_id); + + igt_spin_batch_end(spin[1]); + gem_sync(i915, spin[1]->handle); + + for (int i = 0; i < ARRAY_SIZE(spin); i++) + igt_spin_batch_free(i915, spin[i]); +} + +igt_main +{ + int i915 = -1; + + igt_fixture { + i915 = drm_open_driver(DRIVER_INTEL); + igt_require_gem(i915); + igt_require(has_vm(i915)); + } + + igt_subtest("invalid-create") + invalid_create(i915); + + igt_subtest("invalid-destroy") + invalid_destroy(i915); + + igt_subtest_group { + igt_fixture { + gem_context_require_param(i915, I915_CONTEXT_PARAM_VM); + } + + igt_subtest("execbuf") + execbuf(i915); + + igt_subtest("async-destroy") + async_destroy(i915); + } + + igt_fixture { + close(i915); + } +} diff --git a/tests/meson.build b/tests/meson.build index 2b6132345..7c194c3e3 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -210,6 +210,7 @@ i915_progs = [ 'gem_unfence_active_buffers', 'gem_unref_active_buffers', 'gem_userptr_blits', + 'gem_vm_create', 'gem_wait', 'gem_workarounds', 'gem_write_read_ring_switch', From patchwork Thu Mar 14 14:19:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852995 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3112C17DF for ; Thu, 14 Mar 2019 14:20:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1588B2A422 for ; Thu, 14 Mar 2019 14:20:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 092C22A405; Thu, 14 Mar 2019 14:20:29 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 4FE562A405 for ; Thu, 14 Mar 2019 14:20:27 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id BB4D16E2ED; Thu, 14 Mar 2019 14:20:26 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0FFBF6E2E6; Thu, 14 Mar 2019 14:20:00 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889941-1500050 for multiple; Thu, 14 Mar 2019 14:19:44 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:32 +0000 Message-Id: <20190314141939.26246-18-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 18/25] i915: Exercise creating context with shared GTT 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP v2: Test each shared context is its own timeline and allows request reordering between shared contexts. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Cc: Mika Kuoppala Cc: Michal Wajdeczko --- lib/i915/gem_context.c | 68 +++ lib/i915/gem_context.h | 13 + tests/Makefile.sources | 1 + tests/i915/gem_ctx_shared.c | 890 ++++++++++++++++++++++++++++++++++ tests/i915/gem_exec_whisper.c | 32 +- tests/meson.build | 1 + 6 files changed, 996 insertions(+), 9 deletions(-) create mode 100644 tests/i915/gem_ctx_shared.c diff --git a/lib/i915/gem_context.c b/lib/i915/gem_context.c index 8b4d5b704..e005192d4 100644 --- a/lib/i915/gem_context.c +++ b/lib/i915/gem_context.c @@ -271,3 +271,71 @@ void gem_context_set_priority(int fd, uint32_t ctx_id, int prio) { igt_assert_eq(__gem_context_set_priority(fd, ctx_id, prio), 0); } + +int +__gem_context_clone(int i915, + uint32_t src, unsigned int share, + unsigned int flags, + uint32_t *out) +{ + struct drm_i915_gem_context_create_ext_clone clone = { + { .name = I915_CONTEXT_CREATE_EXT_CLONE }, + .clone_id = src, + .flags = share, + }; + struct drm_i915_gem_context_create_ext arg = { + .flags = flags | I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS, + .extensions = to_user_pointer(&clone), + }; + int err = 0; + + if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT, &arg)) + err = -errno; + + *out = arg.ctx_id; + + errno = 0; + return err; +} + +static bool __gem_context_has(int i915, uint32_t share, unsigned int flags) +{ + uint32_t ctx; + + __gem_context_clone(i915, 0, share, flags, &ctx); + if (ctx) + gem_context_destroy(i915, ctx); + + errno = 0; + return ctx; +} + +bool gem_contexts_has_shared_gtt(int i915) +{ + return __gem_context_has(i915, I915_CONTEXT_CLONE_VM, 0); +} + +bool gem_has_queues(int i915) +{ + return __gem_context_has(i915, + I915_CONTEXT_CLONE_VM, + I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE); +} + +uint32_t gem_context_clone(int i915, + uint32_t src, unsigned int share, + unsigned int flags) +{ + uint32_t ctx; + + igt_assert_eq(__gem_context_clone(i915, src, share, flags, &ctx), 0); + + return ctx; +} + +uint32_t gem_queue_create(int i915) +{ + return gem_context_clone(i915, 0, + I915_CONTEXT_CLONE_VM, + I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE); +} diff --git a/lib/i915/gem_context.h b/lib/i915/gem_context.h index aef68dda6..ce2617980 100644 --- a/lib/i915/gem_context.h +++ b/lib/i915/gem_context.h @@ -29,6 +29,19 @@ int __gem_context_create(int fd, uint32_t *ctx_id); void gem_context_destroy(int fd, uint32_t ctx_id); int __gem_context_destroy(int fd, uint32_t ctx_id); +int __gem_context_clone(int i915, + uint32_t src, unsigned int share, + unsigned int flags, + uint32_t *out); +uint32_t gem_context_clone(int i915, + uint32_t src, unsigned int share, + unsigned int flags); + +uint32_t gem_queue_create(int i915); + +bool gem_contexts_has_shared_gtt(int i915); +bool gem_has_queues(int i915); + bool gem_has_contexts(int fd); void gem_require_contexts(int fd); void gem_context_require_bannable(int fd); diff --git a/tests/Makefile.sources b/tests/Makefile.sources index 12f4bbd75..7e06c969f 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -22,6 +22,7 @@ TESTS_progs = \ drm_mm \ drm_read \ i915/gem_ctx_clone \ + i915/gem_ctx_shared \ i915/gem_vm_create \ kms_3d \ kms_addfb_basic \ diff --git a/tests/i915/gem_ctx_shared.c b/tests/i915/gem_ctx_shared.c new file mode 100644 index 000000000..426155356 --- /dev/null +++ b/tests/i915/gem_ctx_shared.c @@ -0,0 +1,890 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "igt.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "igt_rand.h" +#include "igt_vgem.h" +#include "sync_file.h" + +#define LO 0 +#define HI 1 +#define NOISE 2 + +#define MAX_PRIO LOCAL_I915_CONTEXT_MAX_USER_PRIORITY +#define MIN_PRIO LOCAL_I915_CONTEXT_MIN_USER_PRIORITY + +static int priorities[] = { + [LO] = MIN_PRIO / 2, + [HI] = MAX_PRIO / 2, +}; + +#define MAX_ELSP_QLEN 16 + +IGT_TEST_DESCRIPTION("Test shared contexts."); + +static void create_shared_gtt(int i915, unsigned int flags) +#define DETACHED 0x1 +{ + const uint32_t bbe = MI_BATCH_BUFFER_END; + struct drm_i915_gem_exec_object2 obj = { + .handle = gem_create(i915, 4096), + }; + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = to_user_pointer(&obj), + .buffer_count = 1, + }; + uint32_t parent, child; + + gem_write(i915, obj.handle, 0, &bbe, sizeof(bbe)); + gem_execbuf(i915, &execbuf); + gem_sync(i915, obj.handle); + + child = flags & DETACHED ? gem_context_create(i915) : 0; + igt_until_timeout(2) { + parent = flags & DETACHED ? child : 0; + child = gem_context_clone(i915, + parent, I915_CONTEXT_CLONE_VM, + 0); + execbuf.rsvd1 = child; + gem_execbuf(i915, &execbuf); + + if (flags & DETACHED) { + gem_context_destroy(i915, parent); + gem_execbuf(i915, &execbuf); + } else { + parent = child; + gem_context_destroy(i915, parent); + } + + execbuf.rsvd1 = parent; + igt_assert_eq(__gem_execbuf(i915, &execbuf), -ENOENT); + igt_assert_eq(__gem_context_clone(i915, + parent, I915_CONTEXT_CLONE_VM, + 0, &parent), -ENOENT); + } + if (flags & DETACHED) + gem_context_destroy(i915, child); + + gem_sync(i915, obj.handle); + gem_close(i915, obj.handle); +} + +static void disjoint_timelines(int i915) +{ + const uint32_t bbe = MI_BATCH_BUFFER_END; + struct drm_i915_gem_exec_object2 obj = { + .handle = gem_create(i915, 4096), + }; + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = to_user_pointer(&obj), + .buffer_count = 1, + }; + struct sync_fence_info parent, child; + struct sync_file_info sync_file_info = { + .num_fences = 1, + }; + + igt_require(gem_has_execlists(i915)); + + /* + * Each context, although they share a vm, are expected to be + * distinct timelines. A request queued to one context should be + * independent of any shared contexts. + * + * This information is exposed via the sync_file->name which + * includes the fence.context. + */ + + gem_write(i915, obj.handle, 0, &bbe, sizeof(bbe)); + gem_execbuf(i915, &execbuf); + gem_sync(i915, obj.handle); + + execbuf.flags = I915_EXEC_FENCE_OUT; + gem_execbuf_wr(i915, &execbuf); + sync_file_info.sync_fence_info = to_user_pointer(&parent); + do_ioctl(execbuf.rsvd2 >> 32, SYNC_IOC_FILE_INFO, &sync_file_info); + close(execbuf.rsvd2 >> 32); + + execbuf.rsvd1 = + gem_context_clone(i915, 0, I915_CONTEXT_CLONE_VM, 0); + gem_execbuf_wr(i915, &execbuf); + sync_file_info.sync_fence_info = to_user_pointer(&child); + do_ioctl(execbuf.rsvd2 >> 32, SYNC_IOC_FILE_INFO, &sync_file_info); + close(execbuf.rsvd2 >> 32); + gem_context_destroy(i915, execbuf.rsvd1); + + igt_info("Parent fence: %s %s\n", parent.driver_name, parent.obj_name); + igt_info("Child fence: %s %s\n", child.driver_name, child.obj_name); + + /* Driver should be the same, but on different timelines */ + igt_assert(strcmp(parent.driver_name, child.driver_name) == 0); + igt_assert(strcmp(parent.obj_name, child.obj_name) != 0); + + gem_sync(i915, obj.handle); + gem_close(i915, obj.handle); +} + +static int reopen_driver(int fd) +{ + char path[256]; + + snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); + fd = open(path, O_RDWR); + igt_assert_lte(0, fd); + + return fd; +} + +static void exhaust_shared_gtt(int i915, unsigned int flags) +#define EXHAUST_LRC 0x1 +{ + i915 = reopen_driver(i915); + + igt_fork(pid, 1) { + const uint32_t bbe = MI_BATCH_BUFFER_END; + struct drm_i915_gem_exec_object2 obj = { + .handle = gem_create(i915, 4096) + }; + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = to_user_pointer(&obj), + .buffer_count = 1, + }; + uint32_t parent, child; + unsigned long count = 0; + int err; + + gem_write(i915, obj.handle, 0, &bbe, sizeof(bbe)); + + child = 0; + for (;;) { + parent = child; + err = __gem_context_clone(i915, + parent, I915_CONTEXT_CLONE_VM, + 0, &child); + if (err) + break; + + if (flags & EXHAUST_LRC) { + execbuf.rsvd1 = child; + err = __gem_execbuf(i915, &execbuf); + if (err) + break; + } + + count++; + } + gem_sync(i915, obj.handle); + + igt_info("Created %lu shared contexts, before %d (%s)\n", + count, err, strerror(-err)); + } + close(i915); + igt_waitchildren(); +} + +static void exec_shared_gtt(int i915, unsigned int ring) +{ + const int gen = intel_gen(intel_get_drm_devid(i915)); + const uint32_t bbe = MI_BATCH_BUFFER_END; + struct drm_i915_gem_exec_object2 obj = { + .handle = gem_create(i915, 4096) + }; + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = to_user_pointer(&obj), + .buffer_count = 1, + .flags = ring, + }; + uint32_t scratch = obj.handle; + uint32_t batch[16]; + int i; + + gem_require_ring(i915, ring); + igt_require(gem_can_store_dword(i915, ring)); + + /* Load object into place in the GTT */ + gem_write(i915, obj.handle, 0, &bbe, sizeof(bbe)); + gem_execbuf(i915, &execbuf); + + /* Presume nothing causes an eviction in the meantime */ + + obj.handle = gem_create(i915, 4096); + + i = 0; + batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0); + if (gen >= 8) { + batch[++i] = obj.offset; + batch[++i] = 0; + } else if (gen >= 4) { + batch[++i] = 0; + batch[++i] = obj.offset; + } else { + batch[i]--; + batch[++i] = obj.offset; + } + batch[++i] = 0xc0ffee; + batch[++i] = MI_BATCH_BUFFER_END; + gem_write(i915, obj.handle, 0, batch, sizeof(batch)); + + obj.offset += 4096; /* make sure we don't cause an eviction! */ + obj.flags |= EXEC_OBJECT_PINNED; + execbuf.rsvd1 = gem_context_clone(i915, 0, I915_CONTEXT_CLONE_VM, 0); + if (gen > 3 && gen < 6) + execbuf.flags |= I915_EXEC_SECURE; + + gem_execbuf(i915, &execbuf); + gem_context_destroy(i915, execbuf.rsvd1); + gem_sync(i915, obj.handle); /* write hazard lies */ + gem_close(i915, obj.handle); + + gem_read(i915, scratch, 0, batch, sizeof(uint32_t)); + gem_close(i915, scratch); + + igt_assert_eq_u32(*batch, 0xc0ffee); +} + +static int nop_sync(int i915, uint32_t ctx, unsigned int ring, int64_t timeout) +{ + const uint32_t bbe = MI_BATCH_BUFFER_END; + struct drm_i915_gem_exec_object2 obj = { + .handle = gem_create(i915, 4096), + }; + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = to_user_pointer(&obj), + .buffer_count = 1, + .flags = ring, + .rsvd1 = ctx, + }; + int err; + + gem_write(i915, obj.handle, 0, &bbe, sizeof(bbe)); + gem_execbuf(i915, &execbuf); + err = gem_wait(i915, obj.handle, &timeout); + gem_close(i915, obj.handle); + + return err; +} + +static bool has_single_timeline(int i915) +{ + uint32_t ctx; + + __gem_context_clone(i915, 0, 0, + I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE, + &ctx); + if (ctx) + gem_context_destroy(i915, ctx); + + return ctx != 0; +} + +static bool ignore_engine(unsigned engine) +{ + if (engine == 0) + return true; + + if (engine == I915_EXEC_BSD) + return true; + + return false; +} + +static void single_timeline(int i915) +{ + const uint32_t bbe = MI_BATCH_BUFFER_END; + struct drm_i915_gem_exec_object2 obj = { + .handle = gem_create(i915, 4096), + }; + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = to_user_pointer(&obj), + .buffer_count = 1, + }; + struct sync_fence_info rings[16]; + struct sync_file_info sync_file_info = { + .num_fences = 1, + }; + unsigned int engine; + int n; + + igt_require(has_single_timeline(i915)); + + gem_write(i915, obj.handle, 0, &bbe, sizeof(bbe)); + gem_execbuf(i915, &execbuf); + gem_sync(i915, obj.handle); + + /* + * For a "single timeline" context, each ring is on the common + * timeline, unlike a normal context where each ring has an + * independent timeline. That is no matter which engine we submit + * to, it reports the same timeline name and fence context. However, + * the fence context is not reported through the sync_fence_info. + */ + execbuf.rsvd1 = + gem_context_clone(i915, 0, 0, + I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE); + execbuf.flags = I915_EXEC_FENCE_OUT; + n = 0; + for_each_engine(i915, engine) { + gem_execbuf_wr(i915, &execbuf); + sync_file_info.sync_fence_info = to_user_pointer(&rings[n]); + do_ioctl(execbuf.rsvd2 >> 32, SYNC_IOC_FILE_INFO, &sync_file_info); + close(execbuf.rsvd2 >> 32); + + igt_info("ring[%d] fence: %s %s\n", + n, rings[n].driver_name, rings[n].obj_name); + n++; + } + gem_sync(i915, obj.handle); + gem_close(i915, obj.handle); + + for (int i = 1; i < n; i++) { + igt_assert(!strcmp(rings[0].driver_name, rings[i].driver_name)); + igt_assert(!strcmp(rings[0].obj_name, rings[i].obj_name)); + } +} + +static void exec_single_timeline(int i915, unsigned int ring) +{ + unsigned int other; + igt_spin_t *spin; + uint32_t ctx; + + gem_require_ring(i915, ring); + igt_require(has_single_timeline(i915)); + + /* + * On an ordinary context, a blockage on one ring doesn't prevent + * execution on an other. + */ + ctx = 0; + spin = NULL; + for_each_engine(i915, other) { + if (other == ring || ignore_engine(other)) + continue; + + if (spin == NULL) { + spin = __igt_spin_batch_new(i915, .ctx = ctx, .engine = other); + } else { + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = spin->execbuf.buffers_ptr, + .buffer_count = spin->execbuf.buffer_count, + .flags = other, + .rsvd1 = ctx, + }; + gem_execbuf(i915, &execbuf); + } + } + igt_require(spin); + igt_assert_eq(nop_sync(i915, ctx, ring, NSEC_PER_SEC), 0); + igt_spin_batch_free(i915, spin); + + /* + * But if we create a context with just a single shared timeline, + * then it will block waiting for the earlier requests on the + * other engines. + */ + ctx = gem_context_clone(i915, 0, 0, + I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE); + spin = NULL; + for_each_engine(i915, other) { + if (other == ring || ignore_engine(other)) + continue; + + if (spin == NULL) { + spin = __igt_spin_batch_new(i915, .ctx = ctx, .engine = other); + } else { + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = spin->execbuf.buffers_ptr, + .buffer_count = spin->execbuf.buffer_count, + .flags = other, + .rsvd1 = ctx, + }; + gem_execbuf(i915, &execbuf); + } + } + igt_assert(spin); + igt_assert_eq(nop_sync(i915, ctx, ring, NSEC_PER_SEC), -ETIME); + igt_spin_batch_free(i915, spin); +} + +static void store_dword(int i915, uint32_t ctx, unsigned ring, + uint32_t target, uint32_t offset, uint32_t value, + uint32_t cork, unsigned write_domain) +{ + const int gen = intel_gen(intel_get_drm_devid(i915)); + struct drm_i915_gem_exec_object2 obj[3]; + struct drm_i915_gem_relocation_entry reloc; + struct drm_i915_gem_execbuffer2 execbuf; + uint32_t batch[16]; + int i; + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = to_user_pointer(obj + !cork); + execbuf.buffer_count = 2 + !!cork; + execbuf.flags = ring; + if (gen < 6) + execbuf.flags |= I915_EXEC_SECURE; + execbuf.rsvd1 = ctx; + + memset(obj, 0, sizeof(obj)); + obj[0].handle = cork; + obj[1].handle = target; + obj[2].handle = gem_create(i915, 4096); + + memset(&reloc, 0, sizeof(reloc)); + reloc.target_handle = obj[1].handle; + reloc.presumed_offset = 0; + reloc.offset = sizeof(uint32_t); + reloc.delta = offset; + reloc.read_domains = I915_GEM_DOMAIN_INSTRUCTION; + reloc.write_domain = write_domain; + obj[2].relocs_ptr = to_user_pointer(&reloc); + obj[2].relocation_count = 1; + + i = 0; + batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0); + if (gen >= 8) { + batch[++i] = offset; + batch[++i] = 0; + } else if (gen >= 4) { + batch[++i] = 0; + batch[++i] = offset; + reloc.offset += sizeof(uint32_t); + } else { + batch[i]--; + batch[++i] = offset; + } + batch[++i] = value; + batch[++i] = MI_BATCH_BUFFER_END; + gem_write(i915, obj[2].handle, 0, batch, sizeof(batch)); + gem_execbuf(i915, &execbuf); + gem_close(i915, obj[2].handle); +} + +static uint32_t create_highest_priority(int i915) +{ + uint32_t ctx = gem_context_create(i915); + + /* + * If there is no priority support, all contexts will have equal + * priority (and therefore the max user priority), so no context + * can overtake us, and we effectively can form a plug. + */ + __gem_context_set_priority(i915, ctx, MAX_PRIO); + + return ctx; +} + +static void unplug_show_queue(int i915, struct igt_cork *c, unsigned int engine) +{ + igt_spin_t *spin[MAX_ELSP_QLEN]; + + for (int n = 0; n < ARRAY_SIZE(spin); n++) { + const struct igt_spin_factory opts = { + .ctx = create_highest_priority(i915), + .engine = engine, + }; + spin[n] = __igt_spin_batch_factory(i915, &opts); + gem_context_destroy(i915, opts.ctx); + } + + igt_cork_unplug(c); /* batches will now be queued on the engine */ + igt_debugfs_dump(i915, "i915_engine_info"); + + for (int n = 0; n < ARRAY_SIZE(spin); n++) + igt_spin_batch_free(i915, spin[n]); +} + +static uint32_t store_timestamp(int i915, + uint32_t ctx, unsigned ring, + unsigned mmio_base) +{ + const bool r64b = intel_gen(intel_get_drm_devid(i915)) >= 8; + struct drm_i915_gem_exec_object2 obj = { + .handle = gem_create(i915, 4096), + .relocation_count = 1, + }; + struct drm_i915_gem_relocation_entry reloc = { + .target_handle = obj.handle, + .offset = 2 * sizeof(uint32_t), + .delta = 4092, + .read_domains = I915_GEM_DOMAIN_INSTRUCTION, + }; + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = to_user_pointer(&obj), + .buffer_count = 1, + .flags = ring, + .rsvd1 = ctx, + }; + uint32_t batch[] = { + 0x24 << 23 | (1 + r64b), /* SRM */ + mmio_base + 0x358, + 4092, + 0, + MI_BATCH_BUFFER_END + }; + + igt_require(intel_gen(intel_get_drm_devid(i915)) >= 7); + + gem_write(i915, obj.handle, 0, batch, sizeof(batch)); + obj.relocs_ptr = to_user_pointer(&reloc); + + gem_execbuf(i915, &execbuf); + + return obj.handle; +} + +static void independent(int i915, unsigned ring, unsigned flags) +{ + uint32_t handle[ARRAY_SIZE(priorities)]; + igt_spin_t *spin[MAX_ELSP_QLEN]; + unsigned int mmio_base; + + /* XXX i915_query()! */ + igt_skip_on(intel_gen(intel_get_drm_devid(i915)) >= 11); + switch (ring) { + case I915_EXEC_DEFAULT: + case I915_EXEC_RENDER: + mmio_base = 0x2000; + break; +#if 0 + case I915_EXEC_BSD: + mmio_base = 0x12000; + break; +#endif + case I915_EXEC_BLT: + mmio_base = 0x22000; + break; + case I915_EXEC_VEBOX: + mmio_base = 0x1a000; + break; + + default: + igt_skip("mmio base not known"); + } + + for (int n = 0; n < ARRAY_SIZE(spin); n++) { + const struct igt_spin_factory opts = { + .ctx = create_highest_priority(i915), + .engine = ring, + }; + spin[n] = __igt_spin_batch_factory(i915, &opts); + gem_context_destroy(i915, opts.ctx); + } + + for (int i = 0; i < ARRAY_SIZE(priorities); i++) { + uint32_t ctx = gem_queue_create(i915); + gem_context_set_priority(i915, ctx, priorities[i]); + handle[i] = store_timestamp(i915, ctx, ring, mmio_base); + gem_context_destroy(i915, ctx); + } + + for (int n = 0; n < ARRAY_SIZE(spin); n++) + igt_spin_batch_free(i915, spin[n]); + + for (int i = 0; i < ARRAY_SIZE(priorities); i++) { + uint32_t *ptr; + + ptr = gem_mmap__gtt(i915, handle[i], 4096, PROT_READ); + gem_set_domain(i915, handle[i], /* no write hazard lies! */ + I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); + gem_close(i915, handle[i]); + + handle[i] = ptr[1023]; + munmap(ptr, 4096); + + igt_debug("ctx[%d] .prio=%d, timestamp=%u\n", + i, priorities[i], handle[i]); + } + + igt_assert((int32_t)(handle[HI] - handle[LO]) < 0); +} + +static void reorder(int i915, unsigned ring, unsigned flags) +#define EQUAL 1 +{ + IGT_CORK_HANDLE(cork); + uint32_t scratch; + uint32_t *ptr; + uint32_t ctx[2]; + uint32_t plug; + + ctx[LO] = gem_queue_create(i915); + gem_context_set_priority(i915, ctx[LO], MIN_PRIO); + + ctx[HI] = gem_queue_create(i915); + gem_context_set_priority(i915, ctx[HI], flags & EQUAL ? MIN_PRIO : 0); + + scratch = gem_create(i915, 4096); + plug = igt_cork_plug(&cork, i915); + + /* We expect the high priority context to be executed first, and + * so the final result will be value from the low priority context. + */ + store_dword(i915, ctx[LO], ring, scratch, 0, ctx[LO], plug, 0); + store_dword(i915, ctx[HI], ring, scratch, 0, ctx[HI], plug, 0); + + unplug_show_queue(i915, &cork, ring); + gem_close(i915, plug); + + gem_context_destroy(i915, ctx[LO]); + gem_context_destroy(i915, ctx[HI]); + + ptr = gem_mmap__gtt(i915, scratch, 4096, PROT_READ); + gem_set_domain(i915, scratch, /* no write hazard lies! */ + I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); + gem_close(i915, scratch); + + if (flags & EQUAL) /* equal priority, result will be fifo */ + igt_assert_eq_u32(ptr[0], ctx[HI]); + else + igt_assert_eq_u32(ptr[0], ctx[LO]); + munmap(ptr, 4096); +} + +static void promotion(int i915, unsigned ring) +{ + IGT_CORK_HANDLE(cork); + uint32_t result, dep; + uint32_t *ptr; + uint32_t ctx[3]; + uint32_t plug; + + ctx[LO] = gem_queue_create(i915); + gem_context_set_priority(i915, ctx[LO], MIN_PRIO); + + ctx[HI] = gem_queue_create(i915); + gem_context_set_priority(i915, ctx[HI], 0); + + ctx[NOISE] = gem_queue_create(i915); + gem_context_set_priority(i915, ctx[NOISE], MIN_PRIO/2); + + result = gem_create(i915, 4096); + dep = gem_create(i915, 4096); + + plug = igt_cork_plug(&cork, i915); + + /* Expect that HI promotes LO, so the order will be LO, HI, NOISE. + * + * fifo would be NOISE, LO, HI. + * strict priority would be HI, NOISE, LO + */ + store_dword(i915, ctx[NOISE], ring, result, 0, ctx[NOISE], plug, 0); + store_dword(i915, ctx[LO], ring, result, 0, ctx[LO], plug, 0); + + /* link LO <-> HI via a dependency on another buffer */ + store_dword(i915, ctx[LO], ring, dep, 0, ctx[LO], 0, I915_GEM_DOMAIN_INSTRUCTION); + store_dword(i915, ctx[HI], ring, dep, 0, ctx[HI], 0, 0); + + store_dword(i915, ctx[HI], ring, result, 0, ctx[HI], 0, 0); + + unplug_show_queue(i915, &cork, ring); + gem_close(i915, plug); + + gem_context_destroy(i915, ctx[NOISE]); + gem_context_destroy(i915, ctx[LO]); + gem_context_destroy(i915, ctx[HI]); + + ptr = gem_mmap__gtt(i915, dep, 4096, PROT_READ); + gem_set_domain(i915, dep, /* no write hazard lies! */ + I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); + gem_close(i915, dep); + + igt_assert_eq_u32(ptr[0], ctx[HI]); + munmap(ptr, 4096); + + ptr = gem_mmap__gtt(i915, result, 4096, PROT_READ); + gem_set_domain(i915, result, /* no write hazard lies! */ + I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); + gem_close(i915, result); + + igt_assert_eq_u32(ptr[0], ctx[NOISE]); + munmap(ptr, 4096); +} + +static void smoketest(int i915, unsigned ring, unsigned timeout) +{ + const int ncpus = sysconf(_SC_NPROCESSORS_ONLN); + unsigned engines[16]; + unsigned nengine; + unsigned engine; + uint32_t scratch; + uint32_t *ptr; + + nengine = 0; + for_each_engine(i915, engine) { + if (ignore_engine(engine)) + continue; + + engines[nengine++] = engine; + } + igt_require(nengine); + + scratch = gem_create(i915, 4096); + igt_fork(child, ncpus) { + unsigned long count = 0; + uint32_t ctx; + + hars_petruska_f54_1_random_perturb(child); + + ctx = gem_queue_create(i915); + igt_until_timeout(timeout) { + int prio; + + prio = hars_petruska_f54_1_random_unsafe_max(MAX_PRIO - MIN_PRIO) + MIN_PRIO; + gem_context_set_priority(i915, ctx, prio); + + engine = engines[hars_petruska_f54_1_random_unsafe_max(nengine)]; + store_dword(i915, ctx, engine, scratch, + 8*child + 0, ~child, + 0, 0); + for (unsigned int step = 0; step < 8; step++) + store_dword(i915, ctx, engine, scratch, + 8*child + 4, count++, + 0, 0); + } + gem_context_destroy(i915, ctx); + } + igt_waitchildren(); + + ptr = gem_mmap__gtt(i915, scratch, 4096, PROT_READ); + gem_set_domain(i915, scratch, /* no write hazard lies! */ + I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); + gem_close(i915, scratch); + + for (unsigned n = 0; n < ncpus; n++) { + igt_assert_eq_u32(ptr[2*n], ~n); + /* + * Note this count is approximate due to unconstrained + * ordering of the dword writes between engines. + * + * Take the result with a pinch of salt. + */ + igt_info("Child[%d] completed %u cycles\n", n, ptr[2*n+1]); + } + munmap(ptr, 4096); +} + +igt_main +{ + const struct intel_execution_engine *e; + int i915 = -1; + + igt_fixture { + i915 = drm_open_driver(DRIVER_INTEL); + igt_require_gem(i915); + } + + igt_subtest_group { + igt_fixture { + igt_require(gem_contexts_has_shared_gtt(i915)); + igt_fork_hang_detector(i915); + } + + igt_subtest("create-shared-gtt") + create_shared_gtt(i915, 0); + + igt_subtest("detached-shared-gtt") + create_shared_gtt(i915, DETACHED); + + igt_subtest("disjoint-timelines") + disjoint_timelines(i915); + + igt_subtest("single-timeline") + single_timeline(i915); + + igt_subtest("exhaust-shared-gtt") + exhaust_shared_gtt(i915, 0); + + igt_subtest("exhaust-shared-gtt-lrc") + exhaust_shared_gtt(i915, EXHAUST_LRC); + + for (e = intel_execution_engines; e->name; e++) { + igt_subtest_f("exec-shared-gtt-%s", e->name) + exec_shared_gtt(i915, e->exec_id | e->flags); + + if (!ignore_engine(e->exec_id | e->flags)) { + igt_subtest_f("exec-single-timeline-%s", + e->name) + exec_single_timeline(i915, + e->exec_id | e->flags); + } + + /* + * Check that the shared contexts operate independently, + * that is requests on one ("queue") can be scheduled + * around another queue. We only check the basics here, + * enough to reduce the queue into just another context, + * and so rely on gem_exec_schedule to prove the rest. + */ + igt_subtest_group { + igt_fixture { + gem_require_ring(i915, e->exec_id | e->flags); + igt_require(gem_can_store_dword(i915, e->exec_id) | e->flags); + igt_require(gem_scheduler_enabled(i915)); + igt_require(gem_scheduler_has_ctx_priority(i915)); + } + + igt_subtest_f("Q-independent-%s", e->name) + independent(i915, e->exec_id | e->flags, 0); + + igt_subtest_f("Q-in-order-%s", e->name) + reorder(i915, e->exec_id | e->flags, EQUAL); + + igt_subtest_f("Q-out-order-%s", e->name) + reorder(i915, e->exec_id | e->flags, 0); + + igt_subtest_f("Q-promotion-%s", e->name) + promotion(i915, e->exec_id | e->flags); + + igt_subtest_f("Q-smoketest-%s", e->name) + smoketest(i915, e->exec_id | e->flags, 5); + } + } + + igt_subtest("Q-smoketest-all") { + igt_require(gem_scheduler_enabled(i915)); + igt_require(gem_scheduler_has_ctx_priority(i915)); + smoketest(i915, -1, 30); + } + + igt_fixture { + igt_stop_hang_detector(); + } + } +} diff --git a/tests/i915/gem_exec_whisper.c b/tests/i915/gem_exec_whisper.c index 6c3b53756..d3e0b0ba2 100644 --- a/tests/i915/gem_exec_whisper.c +++ b/tests/i915/gem_exec_whisper.c @@ -87,6 +87,7 @@ static void verify_reloc(int fd, uint32_t handle, #define HANG 0x20 #define SYNC 0x40 #define PRIORITY 0x80 +#define QUEUES 0x100 struct hang { struct drm_i915_gem_exec_object2 obj; @@ -171,7 +172,7 @@ static void ctx_set_random_priority(int fd, uint32_t ctx) { int prio = hars_petruska_f54_1_random_unsafe_max(1024) - 512; gem_context_set_priority(fd, ctx, prio); -}; +} static void whisper(int fd, unsigned engine, unsigned flags) { @@ -226,6 +227,9 @@ static void whisper(int fd, unsigned engine, unsigned flags) if (flags & CONTEXTS) gem_require_contexts(fd); + if (flags & QUEUES) + igt_require(gem_has_queues(fd)); + if (flags & HANG) init_hang(&hang); @@ -290,6 +294,10 @@ static void whisper(int fd, unsigned engine, unsigned flags) for (n = 0; n < 64; n++) contexts[n] = gem_context_create(fd); } + if (flags & QUEUES) { + for (n = 0; n < 64; n++) + contexts[n] = gem_queue_create(fd); + } if (flags & FDS) { for (n = 0; n < 64; n++) fds[n] = drm_open_driver(DRIVER_INTEL); @@ -403,7 +411,7 @@ static void whisper(int fd, unsigned engine, unsigned flags) execbuf.flags &= ~ENGINE_MASK; execbuf.flags |= engines[rand() % nengine]; } - if (flags & CONTEXTS) { + if (flags & (CONTEXTS | QUEUES)) { execbuf.rsvd1 = contexts[rand() % 64]; if (flags & PRIORITY) ctx_set_random_priority(this_fd, execbuf.rsvd1); @@ -486,7 +494,7 @@ static void whisper(int fd, unsigned engine, unsigned flags) for (n = 0; n < 64; n++) close(fds[n]); } - if (flags & CONTEXTS) { + if (flags & (CONTEXTS | QUEUES)) { for (n = 0; n < 64; n++) gem_context_destroy(fd, contexts[n]); } @@ -522,18 +530,24 @@ igt_main { "chain-forked", CHAIN | FORKED }, { "chain-interruptible", CHAIN | INTERRUPTIBLE }, { "chain-sync", CHAIN | SYNC }, - { "contexts", CONTEXTS }, - { "contexts-interruptible", CONTEXTS | INTERRUPTIBLE}, - { "contexts-forked", CONTEXTS | FORKED}, - { "contexts-priority", CONTEXTS | FORKED | PRIORITY }, - { "contexts-chain", CONTEXTS | CHAIN }, - { "contexts-sync", CONTEXTS | SYNC }, { "fds", FDS }, { "fds-interruptible", FDS | INTERRUPTIBLE}, { "fds-forked", FDS | FORKED}, { "fds-priority", FDS | FORKED | PRIORITY }, { "fds-chain", FDS | CHAIN}, { "fds-sync", FDS | SYNC}, + { "contexts", CONTEXTS }, + { "contexts-interruptible", CONTEXTS | INTERRUPTIBLE}, + { "contexts-forked", CONTEXTS | FORKED}, + { "contexts-priority", CONTEXTS | FORKED | PRIORITY }, + { "contexts-chain", CONTEXTS | CHAIN }, + { "contexts-sync", CONTEXTS | SYNC }, + { "queues", QUEUES }, + { "queues-interruptible", QUEUES | INTERRUPTIBLE}, + { "queues-forked", QUEUES | FORKED}, + { "queues-priority", QUEUES | FORKED | PRIORITY }, + { "queues-chain", QUEUES | CHAIN }, + { "queues-sync", QUEUES | SYNC }, { NULL } }; int fd; diff --git a/tests/meson.build b/tests/meson.build index 7c194c3e3..e005c79c4 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -113,6 +113,7 @@ i915_progs = [ 'gem_ctx_exec', 'gem_ctx_isolation', 'gem_ctx_param', + 'gem_ctx_shared', 'gem_ctx_switch', 'gem_ctx_thrash', 'gem_double_irq_loop', From patchwork Thu Mar 14 14:19:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852973 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CFCCB18FD for ; Thu, 14 Mar 2019 14:20:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BB2552A423 for ; Thu, 14 Mar 2019 14:20:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AFA532A381; Thu, 14 Mar 2019 14:20:16 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 3652D2A381 for ; Thu, 14 Mar 2019 14:20:12 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 045576E2F1; Thu, 14 Mar 2019 14:20:05 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4A9576E2E2; Thu, 14 Mar 2019 14:20:00 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889942-1500050 for multiple; Thu, 14 Mar 2019 14:19:44 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:33 +0000 Message-Id: <20190314141939.26246-19-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 19/25] i915/gem_ctx_switch: Exercise queues 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Queues are a form of contexts that share vm and enfore a single timeline across all engines. Test switching between them, just like ordinary contexts. Signed-off-by: Chris Wilson --- tests/i915/gem_ctx_switch.c | 75 +++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 20 deletions(-) diff --git a/tests/i915/gem_ctx_switch.c b/tests/i915/gem_ctx_switch.c index 87e13b915..647911d4c 100644 --- a/tests/i915/gem_ctx_switch.c +++ b/tests/i915/gem_ctx_switch.c @@ -44,7 +44,8 @@ #define LOCAL_I915_EXEC_NO_RELOC (1<<11) #define LOCAL_I915_EXEC_HANDLE_LUT (1<<12) -#define INTERRUPTIBLE 1 +#define INTERRUPTIBLE 0x1 +#define QUEUE 0x2 static double elapsed(const struct timespec *start, const struct timespec *end) { @@ -126,8 +127,12 @@ static void single(int fd, uint32_t handle, gem_require_ring(fd, e->exec_id | e->flags); - for (n = 0; n < 64; n++) - contexts[n] = gem_context_create(fd); + for (n = 0; n < 64; n++) { + if (flags & QUEUE) + contexts[n] = gem_queue_create(fd); + else + contexts[n] = gem_context_create(fd); + } memset(&obj, 0, sizeof(obj)); obj.handle = handle; @@ -232,8 +237,12 @@ static void all(int fd, uint32_t handle, unsigned flags, int timeout) } igt_require(nengine); - for (n = 0; n < ARRAY_SIZE(contexts); n++) - contexts[n] = gem_context_create(fd); + for (n = 0; n < ARRAY_SIZE(contexts); n++) { + if (flags & QUEUE) + contexts[n] = gem_queue_create(fd); + else + contexts[n] = gem_context_create(fd); + } memset(obj, 0, sizeof(obj)); obj[1].handle = handle; @@ -298,6 +307,17 @@ igt_main { const int ncpus = sysconf(_SC_NPROCESSORS_ONLN); const struct intel_execution_engine *e; + static const struct { + const char *name; + unsigned int flags; + bool (*require)(int fd); + } phases[] = { + { "", 0, NULL }, + { "-interruptible", INTERRUPTIBLE, NULL }, + { "-queue", QUEUE, gem_has_queues }, + { "-queue-interruptible", QUEUE | INTERRUPTIBLE, gem_has_queues }, + { } + }; uint32_t light = 0, heavy; int fd = -1; @@ -319,21 +339,26 @@ igt_main } for (e = intel_execution_engines; e->name; e++) { - igt_subtest_f("%s%s", e->exec_id == 0 ? "basic-" : "", e->name) - single(fd, light, e, 0, 1, 5); - - igt_skip_on_simulation(); - - igt_subtest_f("%s%s-heavy", e->exec_id == 0 ? "basic-" : "", e->name) - single(fd, heavy, e, 0, 1, 5); - igt_subtest_f("%s-interruptible", e->name) - single(fd, light, e, INTERRUPTIBLE, 1, 150); - igt_subtest_f("forked-%s", e->name) - single(fd, light, e, 0, ncpus, 150); - igt_subtest_f("forked-%s-heavy", e->name) - single(fd, heavy, e, 0, ncpus, 150); - igt_subtest_f("forked-%s-interruptible", e->name) - single(fd, light, e, INTERRUPTIBLE, ncpus, 150); + for (typeof(*phases) *p = phases; p->name; p++) { + igt_subtest_group { + igt_fixture { + if (p->require) + igt_require(p->require(fd)); + } + + igt_subtest_f("%s%s%s", e->exec_id == 0 ? "basic-" : "", e->name, p->name) + single(fd, light, e, p->flags, 1, 5); + + igt_skip_on_simulation(); + + igt_subtest_f("%s%s-heavy%s", e->exec_id == 0 ? "basic-" : "", e->name, p->name) + single(fd, heavy, e, p->flags, 1, 5); + igt_subtest_f("forked-%s%s", e->name, p->name) + single(fd, light, e, p->flags, ncpus, 150); + igt_subtest_f("forked-%s-heavy%s", e->name, p->name) + single(fd, heavy, e, p->flags, ncpus, 150); + } + } } igt_subtest("basic-all-light") @@ -341,6 +366,16 @@ igt_main igt_subtest("basic-all-heavy") all(fd, heavy, 0, 5); + igt_subtest_group { + igt_fixture { + igt_require(gem_has_queues(fd)); + } + igt_subtest("basic-queue-light") + all(fd, light, QUEUE, 5); + igt_subtest("basic-queue-heavy") + all(fd, heavy, QUEUE, 5); + } + igt_fixture { igt_stop_hang_detector(); gem_close(fd, heavy); From patchwork Thu Mar 14 14:19:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10853015 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6A50317DF for ; Thu, 14 Mar 2019 14:21:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 543F228BBA for ; Thu, 14 Mar 2019 14:21:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 48F8128BCE; Thu, 14 Mar 2019 14:21:43 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 E825C28BBA for ; Thu, 14 Mar 2019 14:21:42 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A66C66E2EE; Thu, 14 Mar 2019 14:21:38 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 79F3A6E184; Thu, 14 Mar 2019 14:21:31 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889943-1500050 for multiple; Thu, 14 Mar 2019 14:19:44 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:34 +0000 Message-Id: <20190314141939.26246-20-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 20/25] i915/gem_exec_whisper: Fork all-engine tests one-per-engine 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Add a new mode for some more stress, submit the all-engines tests simultaneously, a stream per engine. Signed-off-by: Chris Wilson --- tests/i915/gem_exec_whisper.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/tests/i915/gem_exec_whisper.c b/tests/i915/gem_exec_whisper.c index d3e0b0ba2..d5afc8119 100644 --- a/tests/i915/gem_exec_whisper.c +++ b/tests/i915/gem_exec_whisper.c @@ -88,6 +88,7 @@ static void verify_reloc(int fd, uint32_t handle, #define SYNC 0x40 #define PRIORITY 0x80 #define QUEUES 0x100 +#define ALL 0x200 struct hang { struct drm_i915_gem_exec_object2 obj; @@ -199,6 +200,7 @@ static void whisper(int fd, unsigned engine, unsigned flags) uint64_t old_offset; int i, n, loc; int debugfs; + int nchild; if (flags & PRIORITY) { igt_require(gem_scheduler_enabled(fd)); @@ -215,6 +217,7 @@ static void whisper(int fd, unsigned engine, unsigned flags) engines[nengine++] = engine; } } else { + igt_assert(!(flags & ALL)); igt_require(gem_has_ring(fd, engine)); igt_require(gem_can_store_dword(fd, engine)); engines[nengine++] = engine; @@ -233,11 +236,22 @@ static void whisper(int fd, unsigned engine, unsigned flags) if (flags & HANG) init_hang(&hang); + nchild = 1; + if (flags & FORKED) + nchild *= sysconf(_SC_NPROCESSORS_ONLN); + if (flags & ALL) + nchild *= nengine; + intel_detect_and_clear_missed_interrupts(fd); gpu_power_read(&power, &sample[0]); - igt_fork(child, flags & FORKED ? sysconf(_SC_NPROCESSORS_ONLN) : 1) { + igt_fork(child, nchild) { unsigned int pass; + if (flags & ALL) { + engines[0] = engines[child % nengine]; + nengine = 1; + } + memset(&scratch, 0, sizeof(scratch)); scratch.handle = gem_create(fd, 4096); scratch.flags = EXEC_OBJECT_WRITE; @@ -341,7 +355,7 @@ static void whisper(int fd, unsigned engine, unsigned flags) igt_until_timeout(150) { uint64_t offset; - if (!(flags & FORKED)) + if (nchild == 1) write_seqno(debugfs, pass); if (flags & HANG) @@ -382,8 +396,8 @@ static void whisper(int fd, unsigned engine, unsigned flags) gem_write(fd, batches[1023].handle, loc, &pass, sizeof(pass)); for (n = 1024; --n >= 1; ) { + uint32_t handle[2] = {}; int this_fd = fd; - uint32_t handle[2]; execbuf.buffers_ptr = to_user_pointer(&batches[n-1]); reloc_migrations += batches[n-1].offset != inter[n].presumed_offset; @@ -550,7 +564,7 @@ igt_main { "queues-sync", QUEUES | SYNC }, { NULL } }; - int fd; + int fd = -1; igt_fixture { fd = drm_open_driver_master(DRIVER_INTEL); @@ -561,9 +575,12 @@ igt_main igt_fork_hang_detector(fd); } - for (const struct mode *m = modes; m->name; m++) + for (const struct mode *m = modes; m->name; m++) { igt_subtest_f("%s", m->name) whisper(fd, ALL_ENGINES, m->flags); + igt_subtest_f("%s-all", m->name) + whisper(fd, ALL_ENGINES, m->flags | ALL); + } for (const struct intel_execution_engine *e = intel_execution_engines; e->name; e++) { From patchwork Thu Mar 14 14:19:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10853001 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F40A313B5 for ; Thu, 14 Mar 2019 14:21:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DF27A28BBA for ; Thu, 14 Mar 2019 14:21:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D36DC28BCE; Thu, 14 Mar 2019 14:21:35 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 8FC2328BBA for ; Thu, 14 Mar 2019 14:21:35 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id AD6746E2B5; Thu, 14 Mar 2019 14:21:32 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 865736E2B9; Thu, 14 Mar 2019 14:21:30 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889944-1500050 for multiple; Thu, 14 Mar 2019 14:19:44 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:35 +0000 Message-Id: <20190314141939.26246-21-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 21/25] i915/gem_exec_whisper: debugfs/next_seqno is defunct 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP We removed next_seqno in 5.1, so time to wave goodbye. Signed-off-by: Chris Wilson --- tests/i915/gem_exec_whisper.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/i915/gem_exec_whisper.c b/tests/i915/gem_exec_whisper.c index d5afc8119..61b8d6dac 100644 --- a/tests/i915/gem_exec_whisper.c +++ b/tests/i915/gem_exec_whisper.c @@ -44,15 +44,6 @@ #define VERIFY 0 -static void write_seqno(int dir, unsigned offset) -{ - uint32_t seqno = UINT32_MAX - offset; - - igt_sysfs_printf(dir, "i915_next_seqno", "0x%x", seqno); - - igt_debug("next seqno set to: 0x%x\n", seqno); -} - static void check_bo(int fd, uint32_t handle, int pass) { uint32_t *map; @@ -355,9 +346,6 @@ static void whisper(int fd, unsigned engine, unsigned flags) igt_until_timeout(150) { uint64_t offset; - if (nchild == 1) - write_seqno(debugfs, pass); - if (flags & HANG) submit_hang(&hang, engines, nengine, flags); From patchwork Thu Mar 14 14:19:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852965 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C3F8F17DF for ; Thu, 14 Mar 2019 14:20:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AD20D2A381 for ; Thu, 14 Mar 2019 14:20:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A10692A422; Thu, 14 Mar 2019 14:20:07 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 440E92A381 for ; Thu, 14 Mar 2019 14:20:06 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 7AB146E2EC; Thu, 14 Mar 2019 14:20:03 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4AF156E2E0; Thu, 14 Mar 2019 14:19:59 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889945-1500050 for multiple; Thu, 14 Mar 2019 14:19:45 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:36 +0000 Message-Id: <20190314141939.26246-22-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 22/25] i915: Add gem_ctx_engines 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP To exercise the new I915_CONTEXT_PARAM_ENGINES and interactions with gem_execbuf(). Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Andi Shyti --- tests/Makefile.sources | 1 + tests/i915/gem_ctx_engines.c | 441 +++++++++++++++++++++++++++++++++++ tests/meson.build | 1 + 3 files changed, 443 insertions(+) create mode 100644 tests/i915/gem_ctx_engines.c diff --git a/tests/Makefile.sources b/tests/Makefile.sources index 7e06c969f..2f5612b07 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -22,6 +22,7 @@ TESTS_progs = \ drm_mm \ drm_read \ i915/gem_ctx_clone \ + i915/gem_ctx_engines \ i915/gem_ctx_shared \ i915/gem_vm_create \ kms_3d \ diff --git a/tests/i915/gem_ctx_engines.c b/tests/i915/gem_ctx_engines.c new file mode 100644 index 000000000..588ecf196 --- /dev/null +++ b/tests/i915/gem_ctx_engines.c @@ -0,0 +1,441 @@ +/* + * Copyright © 2018 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "igt.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "i915/gem_context.h" + +#define engine_class(e, n) ((e)->class_instance[(n)].engine_class) +#define engine_instance(e, n) ((e)->class_instance[(n)].engine_instance) + +static bool has_context_engines(int i915) +{ + struct drm_i915_gem_context_param param = { + .ctx_id = 0, + .param = I915_CONTEXT_PARAM_ENGINES, + }; + return __gem_context_set_param(i915, ¶m) == 0; +} + +static void invalid_engines(int i915) +{ + struct i915_context_param_engines stack = {}, *engines; + struct drm_i915_gem_context_param param = { + .ctx_id = gem_context_create(i915), + .param = I915_CONTEXT_PARAM_ENGINES, + .value = to_user_pointer(&stack), + }; + uint32_t handle; + void *ptr; + + param.size = 0; + igt_assert_eq(__gem_context_set_param(i915, ¶m), 0); + + param.size = 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EINVAL); + + param.size = sizeof(stack) - 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EINVAL); + + param.size = sizeof(stack) + 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EINVAL); + + param.size = 0; + igt_assert_eq(__gem_context_set_param(i915, ¶m), 0); + + /* Create a single page surrounded by inaccessible nothingness */ + ptr = mmap(NULL, 3 * 4096, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + igt_assert(ptr != MAP_FAILED); + + munmap(ptr, 4096); + engines = ptr + 4096; + munmap(ptr + 2 *4096, 4096); + + param.size = sizeof(*engines) + sizeof(*engines->class_instance); + param.value = to_user_pointer(engines); + + engines->class_instance[0].engine_class = -1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -ENOENT); + + mprotect(engines, 4096, PROT_READ); + igt_assert_eq(__gem_context_set_param(i915, ¶m), -ENOENT); + + mprotect(engines, 4096, PROT_WRITE); + engines->class_instance[0].engine_class = 0; + if (__gem_context_set_param(i915, ¶m)) /* XXX needs RCS */ + goto out; + + engines->extensions = to_user_pointer(ptr); + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + engines->extensions = 0; + igt_assert_eq(__gem_context_set_param(i915, ¶m), 0); + + param.value = to_user_pointer(engines - 1); + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) - 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) - param.size + 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) + 4096; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) - param.size + 4096; + igt_assert_eq(__gem_context_set_param(i915, ¶m), 0); + + param.value = to_user_pointer(engines) - param.size + 4096 + 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) + 4096; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) + 4096 - 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) - 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines - 1); + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines - 1) + 4096; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines - 1) + 4096 - sizeof(*engines->class_instance) / 2; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + handle = gem_create(i915, 4096 * 3); + ptr = gem_mmap__gtt(i915, handle, 4096 * 3, PROT_READ); + gem_close(i915, handle); + + munmap(ptr, 4096); + munmap(ptr + 8192, 4096); + + param.value = to_user_pointer(ptr + 4096); + igt_assert_eq(__gem_context_set_param(i915, ¶m), 0); + + param.value = to_user_pointer(ptr); + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(ptr) + 4095; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(ptr) + 8192; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(ptr) + 12287; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + munmap(ptr + 4096, 4096); + +out: + munmap(engines, 4096); + gem_context_destroy(i915, param.ctx_id); +} + +static void idempotent(int i915) +{ + I915_DEFINE_CONTEXT_PARAM_ENGINES(engines , I915_EXEC_RING_MASK + 1); + I915_DEFINE_CONTEXT_PARAM_ENGINES(expected , I915_EXEC_RING_MASK + 1); + struct drm_i915_gem_context_param p = { + .ctx_id = gem_context_create(i915), + .param = I915_CONTEXT_PARAM_ENGINES, + .value = to_user_pointer(&engines), + .size = sizeof(engines), + }; + const size_t base = sizeof(struct i915_context_param_engines); + const struct intel_execution_engine2 *e; + int idx; + + /* What goes in, must come out. And what comes out, must go in */ + + gem_context_get_param(i915, &p); + igt_assert_eq(p.size, 0); /* atm default is to use legacy ring mask */ + + idx = 0; + memset(&engines, 0, sizeof(engines)); + for_each_engine_class_instance(i915, e) { + engines.class_instance[idx].engine_class = e->class; + engines.class_instance[idx].engine_instance = e->instance; + idx++; + } + idx *= sizeof(*engines.class_instance); + p.size = base + idx; + gem_context_set_param(i915, &p); + + memcpy(&expected, &engines, sizeof(expected)); + + gem_context_get_param(i915, &p); + igt_assert_eq(p.size, base + idx); + igt_assert(!memcmp(&expected, &engines, idx)); + + p.size = base; + gem_context_set_param(i915, &p); + gem_context_get_param(i915, &p); + igt_assert_eq(p.size, base); + + /* and it should not have overwritten the previous contents */ + igt_assert(!memcmp(&expected, &engines, idx)); + + memset(&engines, 0, sizeof(engines)); + engines.class_instance[0].engine_class = I915_ENGINE_CLASS_INVALID; + engines.class_instance[0].engine_instance = I915_ENGINE_CLASS_INVALID_NONE; + idx = sizeof(*engines.class_instance); + p.size = base + idx; + gem_context_set_param(i915, &p); + + memcpy(&expected, &engines, sizeof(expected)); + + gem_context_get_param(i915, &p); + igt_assert_eq(p.size, base + idx); + igt_assert(!memcmp(&expected, &engines, idx)); + + memset(&engines, 0, sizeof(engines)); + p.size = sizeof(engines); + gem_context_set_param(i915, &p); + + memcpy(&expected, &engines, sizeof(expected)); + + gem_context_get_param(i915, &p); + igt_assert_eq(p.size, sizeof(engines)); + igt_assert(!memcmp(&expected, &engines, idx)); + + gem_context_destroy(i915, p.ctx_id); +} + +static void execute_one(int i915) +{ + I915_DEFINE_CONTEXT_PARAM_ENGINES(engines , I915_EXEC_RING_MASK + 1); + struct drm_i915_gem_context_param param = { + .ctx_id = gem_context_create(i915), + .param = I915_CONTEXT_PARAM_ENGINES, + .value = to_user_pointer(&engines), + /* .size to be filled in later */ + }; + struct drm_i915_gem_exec_object2 obj = { + .handle = gem_create(i915, 4096), + }; + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = to_user_pointer(&obj), + .buffer_count = 1, + .rsvd1 = param.ctx_id, + }; + const uint32_t bbe = MI_BATCH_BUFFER_END; + const struct intel_execution_engine2 *e; + + gem_write(i915, obj.handle, 0, &bbe, sizeof(bbe)); + + /* Unadulterated I915_EXEC_DEFAULT should work */ + execbuf.flags = 0; + igt_assert_eq(__gem_execbuf(i915, &execbuf), 0); + gem_sync(i915, obj.handle); + + for_each_engine_class_instance(i915, e) { + struct drm_i915_gem_busy busy = { .handle = obj.handle }; + + for (int i = -1; i <= I915_EXEC_RING_MASK; i++) { + igt_spin_t *spin; + + memset(&engines, 0, sizeof(engines)); + engine_class(&engines, 0) = e->class; + engine_instance(&engines, 0) = e->instance; + param.size = offsetof(typeof(engines), class_instance[1]); + gem_context_set_param(i915, ¶m); + + spin = igt_spin_batch_new(i915, + .ctx = param.ctx_id, + .engine = 0); + + igt_debug("Testing with map of %d engines\n", i + 1); + memset(&engines.class_instance, -1, sizeof(engines.class_instance)); + if (i != -1) { + engine_class(&engines, i) = e->class; + engine_instance(&engines, i) = e->instance; + } + param.size = sizeof(uint64_t) + (i + 1) * sizeof(uint32_t); + gem_context_set_param(i915, ¶m); + + for (int j = 0; j <= I915_EXEC_RING_MASK; j++) { + int err; + + execbuf.flags = j; + err =__gem_execbuf(i915, &execbuf); + if (j == i) { + igt_assert_f(err == 0, + "Failed to report the valid engine for slot %d\n", + i); + } else { + igt_assert_f(err == -EINVAL, + "Failed to report an invalid engine for slot %d (valid at %d)\n", + j, i); + } + } + + do_ioctl(i915, DRM_IOCTL_I915_GEM_BUSY, &busy); + if (i != -1) { + igt_assert_eq(busy.busy, 1 << (e->class + 16)); + } else { + igt_assert_eq(busy.busy, 0); + } + + igt_spin_batch_free(i915, spin); + + gem_sync(i915, obj.handle); + do_ioctl(i915, DRM_IOCTL_I915_GEM_BUSY, &busy); + igt_assert_eq(busy.busy, 0); + } + } + + /* Restore the defaults and check I915_EXEC_DEFAULT works again. */ + param.size = 0; + gem_context_set_param(i915, ¶m); + execbuf.flags = 0; + igt_assert_eq(__gem_execbuf(i915, &execbuf), 0); + + gem_close(i915, obj.handle); + gem_context_destroy(i915, param.ctx_id); +} + +static void execute_oneforall(int i915) +{ + I915_DEFINE_CONTEXT_PARAM_ENGINES(engines , I915_EXEC_RING_MASK + 1); + struct drm_i915_gem_context_param param = { + .ctx_id = gem_context_create(i915), + .param = I915_CONTEXT_PARAM_ENGINES, + .value = to_user_pointer(&engines), + .size = sizeof(engines), + }; + const struct intel_execution_engine2 *e; + + for_each_engine_class_instance(i915, e) { + memset(&engines, 0, sizeof(engines)); + for (int i = 0; i <= I915_EXEC_RING_MASK; i++) { + engine_class(&engines, i) = e->class; + engine_instance(&engines, i) = e->instance; + } + gem_context_set_param(i915, ¶m); + + for (int i = 0; i <= I915_EXEC_RING_MASK; i++) { + struct drm_i915_gem_busy busy = {}; + igt_spin_t *spin; + + spin = __igt_spin_batch_new(i915, + .ctx = param.ctx_id, + .engine = i); + + busy.handle = spin->handle; + do_ioctl(i915, DRM_IOCTL_I915_GEM_BUSY, &busy); + igt_assert_eq(busy.busy, 1 << (e->class + 16)); + + igt_spin_batch_free(i915, spin); + } + } + + gem_context_destroy(i915, param.ctx_id); +} + +static void execute_allforone(int i915) +{ + I915_DEFINE_CONTEXT_PARAM_ENGINES(engines , I915_EXEC_RING_MASK + 1); + struct drm_i915_gem_context_param param = { + .ctx_id = gem_context_create(i915), + .param = I915_CONTEXT_PARAM_ENGINES, + .value = to_user_pointer(&engines), + }; + const struct intel_execution_engine2 *e; + int i; + + i = 0; + memset(&engines, 0, sizeof(engines)); + for_each_engine_class_instance(i915, e) { + engine_class(&engines, i) = e->class; + engine_instance(&engines, i) = e->instance; + i++; + } + param.size = sizeof(uint64_t) + i * sizeof(uint32_t); + gem_context_set_param(i915, ¶m); + + i = 0; + for_each_engine_class_instance(i915, e) { + struct drm_i915_gem_busy busy = {}; + igt_spin_t *spin; + + spin = __igt_spin_batch_new(i915, + .ctx = param.ctx_id, + .engine = i++); + + busy.handle = spin->handle; + do_ioctl(i915, DRM_IOCTL_I915_GEM_BUSY, &busy); + igt_assert_eq(busy.busy, 1 << (e->class + 16)); + + igt_spin_batch_free(i915, spin); + } + + gem_context_destroy(i915, param.ctx_id); +} + +igt_main +{ + int i915 = -1; + + igt_fixture { + i915 = drm_open_driver_render(DRIVER_INTEL); + igt_require_gem(i915); + + gem_require_contexts(i915); + igt_require(has_context_engines(i915)); + } + + igt_subtest("invalid-engines") + invalid_engines(i915); + + igt_subtest("idempotent") + idempotent(i915); + + igt_subtest("execute-one") + execute_one(i915); + + igt_subtest("execute-oneforall") + execute_oneforall(i915); + + igt_subtest("execute-allforone") + execute_allforone(i915); +} diff --git a/tests/meson.build b/tests/meson.build index e005c79c4..abfc85f46 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -110,6 +110,7 @@ i915_progs = [ 'gem_ctx_bad_destroy', 'gem_ctx_clone', 'gem_ctx_create', + 'gem_ctx_engines', 'gem_ctx_exec', 'gem_ctx_isolation', 'gem_ctx_param', From patchwork Thu Mar 14 14:19:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852989 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3DA0F17DF for ; Thu, 14 Mar 2019 14:20:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 25E0A28BBA for ; Thu, 14 Mar 2019 14:20:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 19EB328BCE; Thu, 14 Mar 2019 14:20:20 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 9D2122A42B for ; Thu, 14 Mar 2019 14:20:18 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id F16D36E30B; Thu, 14 Mar 2019 14:20:15 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 456586E2DA; Thu, 14 Mar 2019 14:20:00 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889946-1500050 for multiple; Thu, 14 Mar 2019 14:19:45 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:37 +0000 Message-Id: <20190314141939.26246-23-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 23/25] i915: Add gem_exec_balancer 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Exercise the in-kernel load balancer checking that we can distribute batches across the set of ctx->engines to avoid load. Signed-off-by: Chris Wilson --- tests/Makefile.am | 1 + tests/Makefile.sources | 1 + tests/i915/gem_exec_balancer.c | 760 +++++++++++++++++++++++++++++++++ tests/meson.build | 7 + 4 files changed, 769 insertions(+) create mode 100644 tests/i915/gem_exec_balancer.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 289249b42..68a9c14bf 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -102,6 +102,7 @@ gem_close_race_LDADD = $(LDADD) -lpthread gem_ctx_thrash_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) gem_ctx_thrash_LDADD = $(LDADD) -lpthread gem_ctx_sseu_LDADD = $(LDADD) $(top_builddir)/lib/libigt_perf.la +i915_gem_exec_balancer_LDADD = $(LDADD) $(top_builddir)/lib/libigt_perf.la gem_exec_capture_LDADD = $(LDADD) -lz gem_exec_parallel_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) gem_exec_parallel_LDADD = $(LDADD) -lpthread diff --git a/tests/Makefile.sources b/tests/Makefile.sources index 2f5612b07..8981a8ae7 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -24,6 +24,7 @@ TESTS_progs = \ i915/gem_ctx_clone \ i915/gem_ctx_engines \ i915/gem_ctx_shared \ + i915/gem_exec_balancer \ i915/gem_vm_create \ kms_3d \ kms_addfb_basic \ diff --git a/tests/i915/gem_exec_balancer.c b/tests/i915/gem_exec_balancer.c new file mode 100644 index 000000000..8fe6a464d --- /dev/null +++ b/tests/i915/gem_exec_balancer.c @@ -0,0 +1,760 @@ +/* + * Copyright © 2018 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include + +#include "igt.h" +#include "igt_perf.h" +#include "i915/gem_ring.h" +#include "sw_sync.h" + +IGT_TEST_DESCRIPTION("Exercise in-kernel load-balancing"); + +struct class_instance { + uint16_t class; + uint16_t instance; +}; +#define INSTANCE_COUNT (1 << I915_PMU_SAMPLE_INSTANCE_BITS) + +static bool has_class_instance(int i915, uint16_t class, uint16_t instance) +{ + int fd; + + fd = perf_i915_open(I915_PMU_ENGINE_BUSY(class, instance)); + if (fd != -1) { + close(fd); + return true; + } + + return false; +} + +static struct class_instance * +list_engines(int i915, uint32_t class_mask, unsigned int *out) +{ + unsigned int count = 0, size = 64; + struct class_instance *engines; + + engines = malloc(size * sizeof(*engines)); + if (!engines) { + *out = 0; + return NULL; + } + + for (enum drm_i915_gem_engine_class class = I915_ENGINE_CLASS_RENDER; + class_mask; + class++, class_mask >>= 1) { + if (!(class_mask & 1)) + continue; + + for (unsigned int instance = 0; + instance < INSTANCE_COUNT; + instance++) { + if (!has_class_instance(i915, class, instance)) + continue; + + if (count == size) { + struct class_instance *e; + + size *= 2; + e = realloc(engines, size*sizeof(*engines)); + if (!e) { + *out = count; + return engines; + } + + engines = e; + } + + engines[count++] = (struct class_instance){ + .class = class, + .instance = instance, + }; + } + } + + if (!count) { + free(engines); + engines = NULL; + } + + *out = count; + return engines; +} + +static int __set_load_balancer(int i915, uint32_t ctx, + const struct class_instance *ci, + unsigned int count) +{ + struct i915_context_engines_load_balance balancer = { + { .name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE }, + .engines_mask = ~0ull, + }; + I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, count + 1); + struct drm_i915_gem_context_param p = { + .ctx_id = ctx, + .param = I915_CONTEXT_PARAM_ENGINES, + .size = sizeof(engines), + .value = to_user_pointer(&engines) + }; + + engines.extensions = to_user_pointer(&balancer), + engines.class_instance[0].engine_class = I915_ENGINE_CLASS_INVALID; + engines.class_instance[0].engine_instance = I915_ENGINE_CLASS_INVALID_NONE; + memcpy(engines.class_instance + 1, ci, count * sizeof(*ci)); + + return __gem_context_set_param(i915, &p); +} + +static void set_load_balancer(int i915, uint32_t ctx, + const struct class_instance *ci, + unsigned int count) +{ + igt_assert_eq(__set_load_balancer(i915, ctx, ci, count), 0); +} + +static uint32_t load_balancer_create(int i915, + const struct class_instance *ci, + unsigned int count) +{ + uint32_t ctx; + + ctx = gem_context_create(i915); + set_load_balancer(i915, ctx, ci, count); + + return ctx; +} + +static void invalid_balancer(int i915) +{ + struct i915_context_engines_load_balance balancer = { + { .name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE }, + }; + I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, 64); + struct drm_i915_gem_context_param p = { + .param = I915_CONTEXT_PARAM_ENGINES, + .value = to_user_pointer(&engines) + }; + struct class_instance *ci; + unsigned int count; + uint32_t handle; + void *ptr; + + /* + * Assume that I915_CONTEXT_PARAM_ENGINE validates the array + * of engines[], our job is to determine if the load_balancer + * extension explodes. + */ + + ci = list_engines(i915, ~0u, &count); + if (!ci) + return; + + igt_debug("Found %d engines\n", count); + + p.ctx_id = gem_context_create(i915); + p.size = (sizeof(struct i915_context_param_engines) + + (count + 1) * sizeof(*engines.class_instance)); + + memset(&engines, 0, sizeof(engines)); + engines.class_instance[0].engine_class = I915_ENGINE_CLASS_INVALID; + engines.class_instance[0].engine_instance = I915_ENGINE_CLASS_INVALID_NONE; + memcpy(engines.class_instance + 1, ci, count * sizeof(ci)); + gem_context_set_param(i915, &p); + + engines.extensions = -1ull; + igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT); + + engines.extensions = 1ull; + igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT); + + engines.extensions = to_user_pointer(&balancer); + igt_assert_eq(__gem_context_set_param(i915, &p), -EINVAL); + + balancer.engines_mask = 0x1; + igt_assert_eq(__gem_context_set_param(i915, &p), -EINVAL); + + balancer.engines_mask = 0x2; + gem_context_set_param(i915, &p); + + balancer.engine_index = 1; + igt_assert_eq(__gem_context_set_param(i915, &p), -EEXIST); + + balancer.engine_index = count; + igt_assert_eq(__gem_context_set_param(i915, &p), -EEXIST); + + balancer.engine_index = count + 1; + igt_assert_eq(__gem_context_set_param(i915, &p), -EINVAL); + + balancer.engine_index = 0; + gem_context_set_param(i915, &p); + + balancer.engines_mask = -1ull << (count + 1); + igt_assert_eq(__gem_context_set_param(i915, &p), -EINVAL); + + balancer.engines_mask = 0x2; + gem_context_set_param(i915, &p); + + balancer.base.next_extension = to_user_pointer(&balancer); + igt_assert_eq(__gem_context_set_param(i915, &p), -EEXIST); + + balancer.base.next_extension = -1ull; + igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT); + + handle = gem_create(i915, 4096 * 3); + ptr = gem_mmap__gtt(i915, handle, 4096 * 3, PROT_WRITE); + gem_close(i915, handle); + + memset(&engines, 0, sizeof(engines)); + engines.class_instance[0].engine_class = I915_ENGINE_CLASS_INVALID; + engines.class_instance[0].engine_instance = I915_ENGINE_CLASS_INVALID_NONE; + engines.class_instance[1].engine_class = I915_ENGINE_CLASS_INVALID; + engines.class_instance[1].engine_instance = I915_ENGINE_CLASS_INVALID_NONE; + memcpy(engines.class_instance + 2, ci, count * sizeof(ci)); + p.size = (sizeof(struct i915_context_param_engines) + + (count + 2) * sizeof(*engines.class_instance)); + gem_context_set_param(i915, &p); + + balancer.base.next_extension = 0; + balancer.engine_index = 1; + balancer.engines_mask = 0x4; + engines.extensions = to_user_pointer(&balancer); + gem_context_set_param(i915, &p); + + memcpy(ptr + 4096 - 8, &balancer, sizeof(balancer)); + memcpy(ptr + 8192 - 8, &balancer, sizeof(balancer)); + balancer.engine_index = 0; + + engines.extensions = to_user_pointer(ptr) + 4096 - 8; + gem_context_set_param(i915, &p); + + balancer.base.next_extension = engines.extensions; + engines.extensions = to_user_pointer(&balancer); + gem_context_set_param(i915, &p); + + munmap(ptr, 4096); + igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT); + engines.extensions = to_user_pointer(ptr) + 4096 - 8; + igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT); + + engines.extensions = to_user_pointer(ptr) + 8192 - 8; + gem_context_set_param(i915, &p); + + balancer.base.next_extension = engines.extensions; + engines.extensions = to_user_pointer(&balancer); + gem_context_set_param(i915, &p); + + munmap(ptr + 8192, 4096); + igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT); + engines.extensions = to_user_pointer(ptr) + 8192 - 8; + igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT); + + munmap(ptr + 4096, 4096); + + gem_context_destroy(i915, p.ctx_id); + free(ci); +} + +static void kick_kthreads(int period_us) +{ + sched_yield(); + usleep(period_us); +} + +static double measure_load(int pmu, int period_us) +{ + uint64_t data[2]; + uint64_t d_t, d_v; + + kick_kthreads(period_us); + + igt_assert_eq(read(pmu, data, sizeof(data)), sizeof(data)); + d_v = -data[0]; + d_t = -data[1]; + + usleep(period_us); + + igt_assert_eq(read(pmu, data, sizeof(data)), sizeof(data)); + d_v += data[0]; + d_t += data[1]; + + return d_v / (double)d_t; +} + +static double measure_min_load(int pmu, unsigned int num, int period_us) +{ + uint64_t data[2 + num]; + uint64_t d_t, d_v[num]; + uint64_t min = -1, max = 0; + + kick_kthreads(period_us); + + igt_assert_eq(read(pmu, data, sizeof(data)), sizeof(data)); + for (unsigned int n = 0; n < num; n++) + d_v[n] = -data[2 + n]; + d_t = -data[1]; + + usleep(period_us); + + igt_assert_eq(read(pmu, data, sizeof(data)), sizeof(data)); + + d_t += data[1]; + for (unsigned int n = 0; n < num; n++) { + d_v[n] += data[2 + n]; + igt_debug("engine[%d]: %.1f%%\n", + n, d_v[n] / (double)d_t * 100); + if (d_v[n] < min) + min = d_v[n]; + if (d_v[n] > max) + max = d_v[n]; + } + + igt_debug("elapsed: %"PRIu64"ns, load [%.1f, %.1f]%%\n", + d_t, min / (double)d_t * 100, max / (double)d_t * 100); + + return min / (double)d_t; +} + +static void check_individual_engine(int i915, + uint32_t ctx, + const struct class_instance *ci, + int idx) +{ + igt_spin_t *spin; + double load; + int pmu; + + pmu = perf_i915_open(I915_PMU_ENGINE_BUSY(ci[idx].class, + ci[idx].instance)); + + spin = igt_spin_batch_new(i915, .ctx = ctx, .engine = idx + 1); + load = measure_load(pmu, 10000); + igt_spin_batch_free(i915, spin); + + close(pmu); + + igt_assert_f(load > 0.90, + "engine %d (class:instance %d:%d) was found to be only %.1f%% busy\n", + idx, ci[idx].class, ci[idx].instance, load*100); +} + +static void individual(int i915) +{ + uint32_t ctx; + + /* + * I915_CONTEXT_PARAM_ENGINE allows us to index into the user + * supplied array from gem_execbuf(). Our check is to build the + * ctx->engine[] with various different engine classes, feed in + * a spinner and then ask pmu to confirm it the expected engine + * was busy. + */ + + ctx = gem_context_create(i915); + + for (int mask = 0; mask < 32; mask++) { + struct class_instance *ci; + unsigned int count; + + ci = list_engines(i915, 1u << mask, &count); + if (!ci) + continue; + + igt_debug("Found %d engines of class %d\n", count, mask); + + for (int pass = 0; pass < count; pass++) { /* approx. count! */ + igt_permute_array(ci, count, igt_exchange_int64); + set_load_balancer(i915, ctx, ci, count); + for (unsigned int n = 0; n < count; n++) + check_individual_engine(i915, ctx, ci, n); + } + + free(ci); + } + + gem_context_destroy(i915, ctx); + gem_quiescent_gpu(i915); +} + +static int add_pmu(int pmu, const struct class_instance *ci) +{ + return perf_i915_open_group(I915_PMU_ENGINE_BUSY(ci->class, + ci->instance), + pmu); +} + +static uint32_t __batch_create(int i915, uint32_t offset) +{ + const uint32_t bbe = MI_BATCH_BUFFER_END; + uint32_t handle; + + handle = gem_create(i915, ALIGN(offset + 4, 4096)); + gem_write(i915, handle, offset, &bbe, sizeof(bbe)); + + return handle; +} + +static uint32_t batch_create(int i915) +{ + return __batch_create(i915, 0); +} + +static void full(int i915, unsigned int flags) +#define PULSE 0x1 +#define LATE 0x2 +{ + struct drm_i915_gem_exec_object2 batch = { + .handle = batch_create(i915), + }; + + if (flags & LATE) + igt_require_sw_sync(); + + /* + * I915_CONTEXT_PARAM_ENGINE changes the meaning of I915_EXEC_DEFAULT + * to provide an automatic selection from the ctx->engine[]. It + * employs load-balancing to evenly distribute the workload the + * array. If we submit N spinners, we expect them to be simultaneously + * running across N engines and use PMU to confirm that the entire + * set of engines are busy. + * + * We complicate matters by interpersing shortlived tasks to challenge + * the kernel to search for space in which to insert new batches. + */ + + + for (int mask = 0; mask < 32; mask++) { + struct class_instance *ci; + igt_spin_t *spin = NULL; + IGT_CORK_FENCE(cork); + unsigned int count; + double load; + int fence = -1; + int *pmu; + + ci = list_engines(i915, 1u << mask, &count); + if (!ci) + continue; + + igt_debug("Found %d engines of class %d\n", count, mask); + + pmu = malloc(sizeof(*pmu) * count); + igt_assert(pmu); + + if (flags & LATE) + fence = igt_cork_plug(&cork, i915); + + pmu[0] = -1; + for (unsigned int n = 0; n < count; n++) { + uint32_t ctx; + + pmu[n] = add_pmu(pmu[0], &ci[n]); + + if (flags & PULSE) { + struct drm_i915_gem_execbuffer2 eb = { + .buffers_ptr = to_user_pointer(&batch), + .buffer_count = 1, + .rsvd2 = fence, + .flags = flags & LATE ? I915_EXEC_FENCE_IN : 0, + }; + gem_execbuf(i915, &eb); + } + + /* + * Each spinner needs to be one a new timeline, + * otherwise they will just sit in the single queue + * and not run concurrently. + */ + ctx = load_balancer_create(i915, ci, count); + + if (spin == NULL) { + spin = __igt_spin_batch_new(i915, .ctx = ctx); + } else { + struct drm_i915_gem_execbuffer2 eb = { + .buffers_ptr = spin->execbuf.buffers_ptr, + .buffer_count = spin->execbuf.buffer_count, + .rsvd1 = ctx, + .rsvd2 = fence, + .flags = flags & LATE ? I915_EXEC_FENCE_IN : 0, + }; + gem_execbuf(i915, &eb); + } + + gem_context_destroy(i915, ctx); + } + + if (flags & LATE) { + igt_cork_unplug(&cork); + close(fence); + } + + load = measure_min_load(pmu[0], count, 10000); + igt_spin_batch_free(i915, spin); + + close(pmu[0]); + free(pmu); + + free(ci); + + igt_assert_f(load > 0.90, + "minimum load for %d x class:%d was found to be only %.1f%% busy\n", + count, mask, load*100); + gem_quiescent_gpu(i915); + } + + gem_close(i915, batch.handle); + gem_quiescent_gpu(i915); +} + +static void ping(int i915, uint32_t ctx, unsigned int engine) +{ + struct drm_i915_gem_exec_object2 obj = { + .handle = batch_create(i915), + }; + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = to_user_pointer(&obj), + .buffer_count = 1, + .flags = engine, + .rsvd1 = ctx, + }; + gem_execbuf(i915, &execbuf); + gem_sync(i915, obj.handle); + gem_close(i915, obj.handle); +} + +static void semaphore(int i915) +{ + uint32_t block[2], scratch; + igt_spin_t *spin[3]; + + /* + * If we are using HW semaphores to launch serialised requests + * on different engine concurrently, we want to verify that real + * work is unimpeded. + */ + igt_require(gem_scheduler_has_preemption(i915)); + + block[0] = gem_context_create(i915); + block[1] = gem_context_create(i915); + + scratch = gem_create(i915, 4096); + spin[2] = igt_spin_batch_new(i915, .dependency = scratch); + for (int mask = 1; mask < 32; mask++) { + struct class_instance *ci; + unsigned int count; + uint32_t vip; + + ci = list_engines(i915, 1u << mask, &count); + if (!ci) + continue; + + if (count < ARRAY_SIZE(block)) + continue; + + /* Ensure that we completely occupy all engines in this group */ + count = ARRAY_SIZE(block); + + for (int i = 0; i < count; i++) { + set_load_balancer(i915, block[i], ci, count); + spin[i] = __igt_spin_batch_new(i915, + .ctx = block[i], + .dependency = scratch); + } + + /* + * Either we haven't blocked both engines with semaphores, + * or we let the vip through. If not, we hang. + */ + vip = gem_context_create(i915); + set_load_balancer(i915, vip, ci, count); + ping(i915, vip, 0); + gem_context_destroy(i915, vip); + + for (int i = 0; i < count; i++) + igt_spin_batch_free(i915, spin[i]); + + free(ci); + } + igt_spin_batch_free(i915, spin[2]); + gem_close(i915, scratch); + + gem_context_destroy(i915, block[1]); + gem_context_destroy(i915, block[0]); + + gem_quiescent_gpu(i915); +} + +static void smoketest(int i915, int timeout) +{ + struct drm_i915_gem_exec_object2 batch[2] = { + { .handle = __batch_create(i915, 16380) } + }; + unsigned int ncontext = 0; + uint32_t *contexts = NULL; + uint32_t *handles = NULL; + + igt_require_sw_sync(); + + for (int mask = 0; mask < 32; mask++) { + struct class_instance *ci; + unsigned int count = 0; + + ci = list_engines(i915, 1u << mask, &count); + if (!ci || count < 2) { + free(ci); + continue; + } + + igt_debug("Found %d engines of class %d\n", count, mask); + + ncontext += 128; + contexts = realloc(contexts, sizeof(*contexts) * ncontext); + igt_assert(contexts); + + for (unsigned int n = ncontext - 128; n < ncontext; n++) { + contexts[n] = load_balancer_create(i915, ci, count); + igt_assert(contexts[n]); + } + + free(ci); + } + igt_debug("Created %d virtual engines (one per context)\n", ncontext); + igt_require(ncontext); + + contexts = realloc(contexts, sizeof(*contexts) * ncontext * 4); + igt_assert(contexts); + memcpy(contexts + ncontext, contexts, ncontext * sizeof(*contexts)); + ncontext *= 2; + memcpy(contexts + ncontext, contexts, ncontext * sizeof(*contexts)); + ncontext *= 2; + + handles = malloc(sizeof(*handles) * ncontext); + igt_assert(handles); + for (unsigned int n = 0; n < ncontext; n++) + handles[n] = gem_create(i915, 4096); + + igt_until_timeout(timeout) { + unsigned int count = 1 + (rand() % (ncontext - 1)); + IGT_CORK_FENCE(cork); + int fence = igt_cork_plug(&cork, i915); + + for (unsigned int n = 0; n < count; n++) { + struct drm_i915_gem_execbuffer2 eb = { + .buffers_ptr = to_user_pointer(batch), + .buffer_count = ARRAY_SIZE(batch), + .rsvd1 = contexts[n], + .rsvd2 = fence, + .flags = I915_EXEC_BATCH_FIRST | I915_EXEC_FENCE_IN, + }; + batch[1].handle = handles[n]; + gem_execbuf(i915, &eb); + } + igt_permute_array(handles, count, igt_exchange_int); + + igt_cork_unplug(&cork); + for (unsigned int n = 0; n < count; n++) + gem_sync(i915, handles[n]); + + close(fence); + } + + for (unsigned int n = 0; n < ncontext; n++) { + gem_close(i915, handles[n]); + __gem_context_destroy(i915, contexts[n]); + } + free(handles); + free(contexts); + gem_close(i915, batch[0].handle); +} + +static bool has_context_engines(int i915) +{ + struct drm_i915_gem_context_param p = { + .param = I915_CONTEXT_PARAM_ENGINES, + }; + + return __gem_context_set_param(i915, &p) == 0; +} + +static bool has_load_balancer(int i915) +{ + struct class_instance ci = {}; + uint32_t ctx; + int err; + + ctx = gem_context_create(i915); + err = __set_load_balancer(i915, ctx, &ci, 1); + gem_context_destroy(i915, ctx); + + return err == 0; +} + +igt_main +{ + int i915 = -1; + + igt_skip_on_simulation(); + + igt_fixture { + i915 = drm_open_driver(DRIVER_INTEL); + igt_require_gem(i915); + + gem_require_contexts(i915); + igt_require(has_context_engines(i915)); + igt_require(has_load_balancer(i915)); + + igt_fork_hang_detector(i915); + } + + igt_subtest("invalid-balancer") + invalid_balancer(i915); + + igt_subtest("individual") + individual(i915); + + igt_subtest_group { + static const struct { + const char *name; + unsigned int flags; + } phases[] = { + { "", 0 }, + { "-pulse", PULSE }, + { "-late", LATE }, + { "-late-pulse", PULSE | LATE }, + { } + }; + for (typeof(*phases) *p = phases; p->name; p++) + igt_subtest_f("full%s", p->name) + full(i915, p->flags); + } + + igt_subtest("semaphore") + semaphore(i915); + + igt_subtest("smoke") + smoketest(i915, 20); + + igt_fixture { + igt_stop_hang_detector(); + } +} diff --git a/tests/meson.build b/tests/meson.build index abfc85f46..718d3eaff 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -295,6 +295,13 @@ test_executables += executable('gem_eio', install : true) test_list += 'gem_eio' +test_executables += executable('gem_exec_balancer', 'i915/gem_exec_balancer.c', + dependencies : test_deps + [ lib_igt_perf ], + install_dir : libexecdir, + install_rpath : libexecdir_rpathdir, + install : true) +test_progs += 'gem_exec_balancer' + test_executables += executable('gem_mocs_settings', join_paths('i915', 'gem_mocs_settings.c'), dependencies : test_deps + [ lib_igt_perf ], From patchwork Thu Mar 14 14:19:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10853009 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 016DD6C2 for ; Thu, 14 Mar 2019 14:21:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DCE3428BC8 for ; Thu, 14 Mar 2019 14:21:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D18542A381; Thu, 14 Mar 2019 14:21:41 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 1FA2C28BC8 for ; Thu, 14 Mar 2019 14:21:39 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 01B066E2EC; Thu, 14 Mar 2019 14:21:37 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 86F5E6E2D9; Thu, 14 Mar 2019 14:21:30 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889947-1500050 for multiple; Thu, 14 Mar 2019 14:19:45 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:38 +0000 Message-Id: <20190314141939.26246-24-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 24/25] i915/gem_exec_balancer: Exercise bonded pairs 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP The submit-fence + load_balancing apis allow for us to execute a named pair of engines in parallel; that this by submitting a request to one engine, we can then use the generated submit-fence to submit a second request to another engine and have it execute at the same time. Furthermore, by specifying bonded pairs, we can direct the virtual engine to use a particular engine in parallel to the first request. Signed-off-by: Chris Wilson --- tests/i915/gem_exec_balancer.c | 234 +++++++++++++++++++++++++++++++-- 1 file changed, 225 insertions(+), 9 deletions(-) diff --git a/tests/i915/gem_exec_balancer.c b/tests/i915/gem_exec_balancer.c index 8fe6a464d..3e4bd643c 100644 --- a/tests/i915/gem_exec_balancer.c +++ b/tests/i915/gem_exec_balancer.c @@ -102,12 +102,41 @@ list_engines(int i915, uint32_t class_mask, unsigned int *out) return engines; } +static int __set_engines(int i915, uint32_t ctx, + const struct class_instance *ci, + unsigned int count) +{ + I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, count); + struct drm_i915_gem_context_param p = { + .ctx_id = ctx, + .param = I915_CONTEXT_PARAM_ENGINES, + .size = sizeof(engines), + .value = to_user_pointer(&engines) + }; + + engines.extensions = 0; + memcpy(engines.class_instance, ci, sizeof(engines.class_instance)); + + return __gem_context_set_param(i915, &p); +} + +static void set_engines(int i915, uint32_t ctx, + const struct class_instance *ci, + unsigned int count) +{ + igt_assert_eq(__set_engines(i915, ctx, ci, count), 0); +} + static int __set_load_balancer(int i915, uint32_t ctx, const struct class_instance *ci, - unsigned int count) + unsigned int count, + void *ext) { struct i915_context_engines_load_balance balancer = { - { .name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE }, + { + .next_extension = to_user_pointer(ext), + .name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE + }, .engines_mask = ~0ull, }; I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, count + 1); @@ -128,9 +157,10 @@ static int __set_load_balancer(int i915, uint32_t ctx, static void set_load_balancer(int i915, uint32_t ctx, const struct class_instance *ci, - unsigned int count) + unsigned int count, + void *ext) { - igt_assert_eq(__set_load_balancer(i915, ctx, ci, count), 0); + igt_assert_eq(__set_load_balancer(i915, ctx, ci, count, ext), 0); } static uint32_t load_balancer_create(int i915, @@ -140,7 +170,7 @@ static uint32_t load_balancer_create(int i915, uint32_t ctx; ctx = gem_context_create(i915); - set_load_balancer(i915, ctx, ci, count); + set_load_balancer(i915, ctx, ci, count, NULL); return ctx; } @@ -275,6 +305,74 @@ static void invalid_balancer(int i915) free(ci); } +static void invalid_bonds(int i915) +{ + struct i915_context_engines_bond bonds[16]; + I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, 1); + struct drm_i915_gem_context_param p = { + .ctx_id = gem_context_create(i915), + .param = I915_CONTEXT_PARAM_ENGINES, + .value = to_user_pointer(&engines), + .size = sizeof(engines), + }; + uint32_t handle; + void *ptr; + + memset(&engines, 0, sizeof(engines)); + gem_context_set_param(i915, &p); + + memset(bonds, 0, sizeof(bonds)); + for (int n = 0; n < ARRAY_SIZE(bonds); n++) { + bonds[n].base.name = I915_CONTEXT_ENGINES_EXT_BOND; + bonds[n].base.next_extension = + n ? to_user_pointer(&bonds[n - 1]) : 0; + bonds[n].sibling_mask = 0x1; + } + engines.extensions = to_user_pointer(&bonds); + gem_context_set_param(i915, &p); + + bonds[0].base.next_extension = -1ull; + igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT); + + bonds[0].base.next_extension = to_user_pointer(&bonds[0]); + igt_assert_eq(__gem_context_set_param(i915, &p), -E2BIG); + + engines.extensions = to_user_pointer(&bonds[1]); + igt_assert_eq(__gem_context_set_param(i915, &p), -E2BIG); + bonds[0].base.next_extension = 0; + gem_context_set_param(i915, &p); + + handle = gem_create(i915, 4096 * 3); + ptr = gem_mmap__gtt(i915, handle, 4096 * 3, PROT_WRITE); + gem_close(i915, handle); + + memcpy(ptr + 4096, &bonds[0], sizeof(bonds[0])); + engines.extensions = to_user_pointer(ptr) + 4096; + gem_context_set_param(i915, &p); + + memcpy(ptr, &bonds[0], sizeof(bonds[0])); + bonds[0].base.next_extension = to_user_pointer(ptr); + memcpy(ptr + 4096, &bonds[0], sizeof(bonds[0])); + gem_context_set_param(i915, &p); + + munmap(ptr, 4096); + igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT); + + bonds[0].base.next_extension = 0; + memcpy(ptr + 8192, &bonds[0], sizeof(bonds[0])); + bonds[0].base.next_extension = to_user_pointer(ptr) + 8192; + memcpy(ptr + 4096, &bonds[0], sizeof(bonds[0])); + gem_context_set_param(i915, &p); + + munmap(ptr + 8192, 4096); + igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT); + + munmap(ptr + 4096, 4096); + igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT); + + gem_context_destroy(i915, p.ctx_id); +} + static void kick_kthreads(int period_us) { sched_yield(); @@ -384,7 +482,7 @@ static void individual(int i915) for (int pass = 0; pass < count; pass++) { /* approx. count! */ igt_permute_array(ci, count, igt_exchange_int64); - set_load_balancer(i915, ctx, ci, count); + set_load_balancer(i915, ctx, ci, count, NULL); for (unsigned int n = 0; n < count; n++) check_individual_engine(i915, ctx, ci, n); } @@ -396,6 +494,115 @@ static void individual(int i915) gem_quiescent_gpu(i915); } +static void bonded(int i915, unsigned int flags) +#define CORK 0x1 +{ + struct i915_context_engines_bond bonds[16]; + struct class_instance *master_engines; + uint32_t master; + + /* + * I915_CONTEXT_PARAM_ENGINE provides an extension that allows us + * to specify which engine(s) to pair with a parallel (EXEC_SUBMIT) + * request submitted to another engine. + */ + + master = gem_queue_create(i915); + + memset(bonds, 0, sizeof(bonds)); + for (int n = 0; n < ARRAY_SIZE(bonds); n++) { + bonds[n].base.name = I915_CONTEXT_ENGINES_EXT_BOND; + bonds[n].base.next_extension = + n ? to_user_pointer(&bonds[n - 1]) : 0; + bonds[n].sibling_mask = 1 << n; + } + + for (int mask = 0; mask < 32; mask++) { + unsigned int count, limit; + struct class_instance *siblings; + uint32_t ctx; + int n; + + siblings = list_engines(i915, 1u << mask, &count); + if (!siblings) + continue; + + if (count < 2) { + free(siblings); + continue; + } + + igt_debug("Found %d engines of class %d\n", count, mask); + + master_engines = list_engines(i915, ~(1u << mask), &limit); + set_engines(i915, master, master_engines, limit); + + limit = min(count, limit); + for (n = 0; n < limit; n++) { + bonds[n].master_class = master_engines[n].class; + bonds[n].master_instance = master_engines[n].instance; + } + + ctx = gem_context_clone(i915, + master, I915_CONTEXT_CLONE_VM, + I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE); + set_load_balancer(i915, ctx, siblings, count, &bonds[limit - 1]); + + for (n = 0; n < limit; n++) { + struct drm_i915_gem_execbuffer2 eb; + IGT_CORK_HANDLE(cork); + igt_spin_t *spin, *plug; + double load; + int pmu; + + igt_assert(siblings[n].class != master_engines[n].class); + + pmu = perf_i915_open(I915_PMU_ENGINE_BUSY(siblings[n].class, + siblings[n].instance)); + + plug = NULL; + if (flags & CORK) { + plug = __igt_spin_batch_new(i915, + .ctx = master, + .engine = n, + .dependency = igt_cork_plug(&cork, i915)); + } + + spin = __igt_spin_batch_new(i915, + .ctx = master, + .engine = n, + .flags = IGT_SPIN_FENCE_OUT); + + eb = spin->execbuf; + eb.rsvd1 = ctx; + eb.rsvd2 = spin->out_fence; + eb.flags = I915_EXEC_FENCE_SUBMIT; + gem_execbuf(i915, &eb); + + if (plug) { + igt_cork_unplug(&cork); + igt_spin_batch_free(i915, plug); + } + + load = measure_load(pmu, 10000); + igt_spin_batch_free(i915, spin); + + close(pmu); + + igt_assert_f(load > 0.90, + "engine %d (class:instance %d:%d) was found to be only %.1f%% busy\n", + n, siblings[n].class, siblings[n].instance, + load*100); + } + + gem_context_destroy(i915, ctx); + free(master_engines); + free(siblings); + } + + gem_context_destroy(i915, master); +} + static int add_pmu(int pmu, const struct class_instance *ci) { return perf_i915_open_group(I915_PMU_ENGINE_BUSY(ci->class, @@ -575,7 +782,7 @@ static void semaphore(int i915) count = ARRAY_SIZE(block); for (int i = 0; i < count; i++) { - set_load_balancer(i915, block[i], ci, count); + set_load_balancer(i915, block[i], ci, count, NULL); spin[i] = __igt_spin_batch_new(i915, .ctx = block[i], .dependency = scratch); @@ -586,7 +793,7 @@ static void semaphore(int i915) * or we let the vip through. If not, we hang. */ vip = gem_context_create(i915); - set_load_balancer(i915, vip, ci, count); + set_load_balancer(i915, vip, ci, count, NULL); ping(i915, vip, 0); gem_context_destroy(i915, vip); @@ -703,7 +910,7 @@ static bool has_load_balancer(int i915) int err; ctx = gem_context_create(i915); - err = __set_load_balancer(i915, ctx, &ci, 1); + err = __set_load_balancer(i915, ctx, &ci, 1, NULL); gem_context_destroy(i915, ctx); return err == 0; @@ -729,6 +936,9 @@ igt_main igt_subtest("invalid-balancer") invalid_balancer(i915); + igt_subtest("invalid-bonds") + invalid_bonds(i915); + igt_subtest("individual") individual(i915); @@ -754,6 +964,12 @@ igt_main igt_subtest("smoke") smoketest(i915, 20); + igt_subtest("bonded-imm") + bonded(i915, 0); + + igt_subtest("bonded-cork") + bonded(i915, CORK); + igt_fixture { igt_stop_hang_detector(); } From patchwork Thu Mar 14 14:19:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10852997 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6FBC86C2 for ; Thu, 14 Mar 2019 14:21:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 586CA28BBA for ; Thu, 14 Mar 2019 14:21:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4BEE728BCE; Thu, 14 Mar 2019 14:21:33 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 D4EA428BBA for ; Thu, 14 Mar 2019 14:21:32 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1EEFA6E2D9; Thu, 14 Mar 2019 14:21:32 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 824ED6E2B5; Thu, 14 Mar 2019 14:21:30 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 15889948-1500050 for multiple; Thu, 14 Mar 2019 14:19:45 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Mar 2019 14:19:39 +0000 Message-Id: <20190314141939.26246-25-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190314141939.26246-1-chris@chris-wilson.co.uk> References: <20190314141939.26246-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 25/25] i915/gem_exec_latency: Measure the latency of context switching 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: igt-dev@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Measure the baseline latency between contexts in order to directly compare that with the additional cost of preemption. Signed-off-by: Chris Wilson --- tests/i915/gem_ctx_shared.c | 2 +- tests/i915/gem_exec_latency.c | 142 ++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 1 deletion(-) diff --git a/tests/i915/gem_ctx_shared.c b/tests/i915/gem_ctx_shared.c index 426155356..187921c7e 100644 --- a/tests/i915/gem_ctx_shared.c +++ b/tests/i915/gem_ctx_shared.c @@ -595,7 +595,7 @@ static void independent(int i915, unsigned ring, unsigned flags) break; default: - igt_skip("mmio base not known"); + igt_skip("mmio base not known\n"); } for (int n = 0; n < ARRAY_SIZE(spin); n++) { diff --git a/tests/i915/gem_exec_latency.c b/tests/i915/gem_exec_latency.c index 6dd191ece..89c5af647 100644 --- a/tests/i915/gem_exec_latency.c +++ b/tests/i915/gem_exec_latency.c @@ -628,6 +628,139 @@ rthog_latency_on_ring(int fd, unsigned int engine, const char *name, unsigned in munmap(results, MMAP_SZ); } +static void context_switch(int i915, + unsigned int engine, const char *name, + unsigned int flags) +{ + struct drm_i915_gem_exec_object2 obj[2]; + struct drm_i915_gem_relocation_entry reloc[5]; + struct drm_i915_gem_execbuffer2 eb; + uint32_t *cs, *bbe, *results, v; + unsigned int mmio_base; + struct igt_mean mean; + uint32_t ctx[2]; + + /* XXX i915_query()! */ + igt_skip_on(intel_gen(intel_get_drm_devid(i915)) >= 11); + switch (engine) { + case I915_EXEC_DEFAULT: + case I915_EXEC_RENDER: + mmio_base = 0x2000; + break; +#if 0 + case I915_EXEC_BSD: + mmio_base = 0x12000; + break; +#endif + case I915_EXEC_BLT: + mmio_base = 0x22000; + break; + case I915_EXEC_VEBOX: + mmio_base = 0x1a000; + break; + + default: + igt_skip("mmio base not known"); + } + + for (int i = 0; i < ARRAY_SIZE(ctx); i++) + ctx[i] = gem_context_create(i915); + + if (flags & PREEMPT) { + gem_context_set_priority(i915, ctx[0], -1023); + gem_context_set_priority(i915, ctx[1], +1023); + } + + memset(obj, 0, sizeof(obj)); + obj[0].handle = gem_create(i915, 4096); + gem_set_caching(i915, obj[0].handle, 1); + results = gem_mmap__cpu(i915, obj[0].handle, 0, 4096, PROT_READ); + gem_set_domain(i915, obj[0].handle, I915_GEM_DOMAIN_CPU, 0); + + obj[1].handle = gem_create(i915, 4096); + memset(reloc,0, sizeof(reloc)); + obj[1].relocation_count = ARRAY_SIZE(reloc); + obj[1].relocs_ptr = to_user_pointer(reloc); + bbe = gem_mmap__wc(i915, obj[1].handle, 0, 4096, PROT_WRITE); + gem_set_domain(i915, obj[1].handle, + I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC); + + cs = bbe; + *cs++ = 0x5 << 23; + *cs++ = 0x24 << 23 | 2; /* SRM */ + *cs++ = mmio_base + 0x358; /* TIMESTAMP */ + reloc[0].target_handle = obj[0].handle; + reloc[0].offset = (cs - bbe) * sizeof(*cs); + *cs++ = 0; + *cs++ = 0; + *cs++ = MI_BATCH_BUFFER_START | 1; + reloc[1].target_handle = obj[1].handle; + reloc[1].offset = (cs - bbe) * sizeof(*cs); + *cs++ = 0; + *cs++ = 0; + + cs = bbe + 64; + *cs++ = 0x24 << 23 | 2; /* SRM */ + *cs++ = mmio_base + 0x358; /* TIMESTAMP */ + reloc[2].target_handle = obj[0].handle; + reloc[2].offset = (cs - bbe) * sizeof(*cs); + *cs++ = reloc[2].delta = 4; + *cs++ = 0; + *cs++ = 0x29 << 23 | 2; /* LRM */ + *cs++ = mmio_base + 0x600; /* GPR0 */ + reloc[3].target_handle = obj[0].handle; + reloc[3].offset = (cs - bbe) * sizeof(*cs); + *cs++ = 0; + *cs++ = 0; + *cs++ = 0x24 << 23 | 2; /* SRM */ + *cs++ = mmio_base + 0x600; /* GPR0 */ + reloc[4].target_handle = obj[0].handle; + reloc[4].offset = (cs - bbe) * sizeof(*cs); + *cs++ = reloc[4].delta = 8; + *cs++ = 0; + *cs++ = 0xa << 23; + + memset(&eb, 0, sizeof(eb)); + eb.buffers_ptr = to_user_pointer(obj); + eb.buffer_count = ARRAY_SIZE(obj); + eb.flags = engine; + eb.flags |= LOCAL_I915_EXEC_NO_RELOC; + + v = 0; + igt_mean_init(&mean); + igt_until_timeout(5) { + eb.rsvd1 = ctx[0]; + eb.batch_start_offset = 0; + gem_execbuf(i915, &eb); + + while (results[0] == v) + igt_assert(gem_bo_busy(i915, obj[1].handle)); + + eb.rsvd1 = ctx[1]; + eb.batch_start_offset = 64 * sizeof(*cs); + gem_execbuf(i915, &eb); + + *bbe = 0xa << 23; + gem_sync(i915, obj[1].handle); + *bbe = 0x5 << 23; + + v = results[0]; + igt_mean_add(&mean, (results[1] - results[2]) * rcs_clock); + } + igt_info("%s context switch latency%s: %.2f±%.2fus\n", + name, flags & PREEMPT ? " (preempt)" : "", + 1e-3 * igt_mean_get(&mean), + 1e-3 * sqrt(igt_mean_get_variance(&mean))); + munmap(results, 4096); + munmap(bbe, 4096); + + for (int i = 0; i < ARRAY_SIZE(obj); i++) + gem_close(i915, obj[i].handle); + + for (int i = 0; i < ARRAY_SIZE(ctx); i++) + gem_context_destroy(i915, ctx[i]); +} + static double clockrate(int i915, int reg) { volatile uint32_t *mmio; @@ -753,12 +886,21 @@ igt_main e->exec_id | e->flags, e->name, CORK); + igt_subtest_f("%s-cs", e->name) + context_switch(device, + e->exec_id | e->flags, + e->name, 0); igt_subtest_group { igt_fixture { gem_require_contexts(device); igt_require(gem_scheduler_has_preemption(device)); } + igt_subtest_f("%s-cs-preempt", e->name) + context_switch(device, + e->exec_id | e->flags, + e->name, PREEMPT); + igt_subtest_f("%s-preemption", e->name) latency_from_ring(device, e->exec_id | e->flags,