From patchwork Mon Oct 30 22:29:21 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: oscar.mateo@intel.com X-Patchwork-Id: 10033337 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 13593600C5 for ; Mon, 30 Oct 2017 22:29:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 02A172897D for ; Mon, 30 Oct 2017 22:29:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E9F902898E; Mon, 30 Oct 2017 22:29: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=-4.2 required=2.0 tests=BAYES_00, 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 0679B2897D for ; Mon, 30 Oct 2017 22:29:14 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 30AAF6E12F; Mon, 30 Oct 2017 22:29:13 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id EF9DD6E12F for ; Mon, 30 Oct 2017 22:29:11 +0000 (UTC) Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Oct 2017 15:29:11 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,321,1505804400"; d="scan'208";a="167057408" Received: from omateolo-linux.fm.intel.com ([10.1.27.13]) by orsmga005.jf.intel.com with ESMTP; 30 Oct 2017 15:29:10 -0700 From: Oscar Mateo To: intel-gfx@lists.freedesktop.org Date: Mon, 30 Oct 2017 15:29:21 -0700 Message-Id: <1509402561-24379-1-git-send-email-oscar.mateo@intel.com> X-Mailer: git-send-email 1.9.1 MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t v5] igt/gem_workarounds: Test all types of workarounds X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Apart from context based workarounds, we can now also test for global MMIO and whitelisting ones. Do take into account that this test does not guarantee that all known WAs for a given platform are applied. It only checks that the WAs the kernel does know about are correctly applied (e.g. they didn't get lost on a GPU reset or a suspend/resume). v2: - Do not wait for the GPU unnecessarily (Chris) - Make a comment that this tests only looks for regressions (Chris) v3: - GT instead of MMIO (Chris, Mika) - Limit register access to just the mmio tests (Chris) - Add the possibility to read the WAs from a local file (Chris) - Display workarounds (Ville) v4: - Keep backward compatibility with older kernels (Petri) - Unify the result checker and pretty print the result (Chris) v5: - Avoid error with even older kernels - Missing mem free Signed-off-by: Oscar Mateo Cc: Chris Wilson Cc: Mika Kuoppala Cc: Ville Syrjälä Cc: Petri Latvala --- tests/gem_workarounds.c | 260 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 197 insertions(+), 63 deletions(-) diff --git a/tests/gem_workarounds.c b/tests/gem_workarounds.c index 7b99961..216ec45 100644 --- a/tests/gem_workarounds.c +++ b/tests/gem_workarounds.c @@ -28,6 +28,7 @@ #include "igt.h" #include +#include #define PAGE_SIZE 4096 #define PAGE_ALIGN(x) ALIGN(x, PAGE_SIZE) @@ -62,27 +63,53 @@ static struct write_only_list { */ }; -static struct intel_wa_reg *wa_regs; -static int num_wa_regs; +static struct intel_wa_reg *ctx_wa_regs; +static int num_ctx_wa_regs; + +static struct intel_wa_reg *gt_wa_regs; +static int num_gt_wa_regs; + +static struct intel_wa_reg *display_wa_regs; +static int num_display_wa_regs; + +static struct intel_wa_reg *whitelist_wa_regs; +static int num_whitelist_wa_regs; static bool write_only(const uint32_t addr) { int i; - for (i = 0; i < ARRAY_SIZE(wo_list); i++) { - if (gen == wo_list[i].gen && - addr == wo_list[i].addr) { - igt_info("Skipping check for 0x%x due to write only\n", addr); + for (i = 0; i < ARRAY_SIZE(wo_list); i++) + if (gen == wo_list[i].gen && addr == wo_list[i].addr) return true; - } - } return false; } +static int check_result(struct intel_wa_reg *wa_reg, + uint32_t out, const char *type) +{ + const bool ok = (wa_reg->value & wa_reg->mask) == (out & wa_reg->mask); + char buf[80]; + + snprintf(buf, sizeof(buf), "0x%05X\t0x%08X\t0x%08X\t0x%08X\t(%s)", + wa_reg->addr, wa_reg->value, wa_reg->mask, out, type); + + if (ok) { + igt_debug("%s\tOK\n", buf); + } else if (write_only(wa_reg->addr)) { + igt_debug("%s\tIGNORED (w/o)\n", buf); + } else { + igt_warn("%s\tFAIL\n", buf); + return 1; + } + + return 0; +} + #define MI_STORE_REGISTER_MEM (0x24 << 23) -static int workaround_fail_count(int fd, uint32_t ctx) +static int ctx_workarounds_fail_count(int fd, uint32_t ctx) { struct drm_i915_gem_exec_object2 obj[2]; struct drm_i915_gem_relocation_entry *reloc; @@ -91,13 +118,16 @@ static int workaround_fail_count(int fd, uint32_t ctx) uint32_t *base, *out; int fail_count = 0; - reloc = calloc(num_wa_regs, sizeof(*reloc)); + if (!num_ctx_wa_regs) + return 0; + + reloc = calloc(num_ctx_wa_regs, sizeof(*reloc)); igt_assert(reloc); - result_sz = 4 * num_wa_regs; + result_sz = 4 * num_ctx_wa_regs; result_sz = PAGE_ALIGN(result_sz); - batch_sz = 16 * num_wa_regs + 4; + batch_sz = 16 * num_ctx_wa_regs + 4; batch_sz = PAGE_ALIGN(batch_sz); memset(obj, 0, sizeof(obj)); @@ -105,12 +135,12 @@ static int workaround_fail_count(int fd, uint32_t ctx) gem_set_caching(fd, obj[0].handle, I915_CACHING_CACHED); obj[1].handle = gem_create(fd, batch_sz); obj[1].relocs_ptr = to_user_pointer(reloc); - obj[1].relocation_count = num_wa_regs; + obj[1].relocation_count = num_ctx_wa_regs; out = base = gem_mmap__cpu(fd, obj[1].handle, 0, batch_sz, PROT_WRITE); - for (int i = 0; i < num_wa_regs; i++) { + for (int i = 0; i < num_ctx_wa_regs; i++) { *out++ = MI_STORE_REGISTER_MEM | ((gen >= 8 ? 4 : 2) - 2); - *out++ = wa_regs[i].addr; + *out++ = ctx_wa_regs[i].addr; reloc[i].target_handle = obj[0].handle; reloc[i].offset = (out - base) * sizeof(*out); reloc[i].delta = i * sizeof(uint32_t); @@ -131,29 +161,9 @@ static int workaround_fail_count(int fd, uint32_t ctx) gem_set_domain(fd, obj[0].handle, I915_GEM_DOMAIN_CPU, 0); - igt_debug("Address\tval\t\tmask\t\tread\t\tresult\n"); - out = gem_mmap__cpu(fd, obj[0].handle, 0, result_sz, PROT_READ); - for (int i = 0; i < num_wa_regs; i++) { - const bool ok = - (wa_regs[i].value & wa_regs[i].mask) == - (out[i] & wa_regs[i].mask); - char buf[80]; - - snprintf(buf, sizeof(buf), - "0x%05X\t0x%08X\t0x%08X\t0x%08X", - wa_regs[i].addr, wa_regs[i].value, wa_regs[i].mask, - out[i]); - - if (ok) { - igt_debug("%s\tOK\n", buf); - } else if (write_only(wa_regs[i].addr)) { - igt_debug("%s\tIGNORED (w/o)\n", buf); - } else { - igt_warn("%s\tFAIL\n", buf); - fail_count++; - } - } + for (int i = 0; i < num_ctx_wa_regs; i++) + fail_count += check_result(&ctx_wa_regs[i], out[i], "ctx"); munmap(out, result_sz); gem_close(fd, obj[1].handle); @@ -163,6 +173,44 @@ static int workaround_fail_count(int fd, uint32_t ctx) return fail_count; } +static int mmio_workarounds_fail_count(struct intel_wa_reg *wa_regs, + int num_wa_regs, const char *type) +{ + int i, fail_count = 0; + + for (i = 0; i < num_wa_regs; i++) { + const uint32_t val = intel_register_read(wa_regs[i].addr); + fail_count += check_result(&wa_regs[i], val, type); + } + + return fail_count; +} + +static int workarounds_fail_count(int fd, uint32_t ctx) +{ + int fail_count = 0; + + igt_debug("Address\tval\t\tmask\t\tread\t\ttype\tresult\n"); + + fail_count += ctx_workarounds_fail_count(fd, ctx); + + intel_register_access_init(intel_get_pci_device(), 0, fd); + + fail_count += mmio_workarounds_fail_count(gt_wa_regs, + num_gt_wa_regs, + "gt"); + fail_count += mmio_workarounds_fail_count(display_wa_regs, + num_display_wa_regs, + "disp"); + fail_count += mmio_workarounds_fail_count(whitelist_wa_regs, + num_whitelist_wa_regs, + "wlist"); + + intel_register_access_fini(); + + return fail_count; +} + static int reopen(int fd) { char path[256]; @@ -185,7 +233,7 @@ static void check_workarounds(int fd, enum operation op, unsigned int flags) if (flags & CONTEXT) ctx = gem_context_create(fd); - igt_assert_eq(workaround_fail_count(fd, ctx), 0); + igt_assert_eq(workarounds_fail_count(fd, ctx), 0); switch (op) { case GPU_RESET: @@ -209,7 +257,7 @@ static void check_workarounds(int fd, enum operation op, unsigned int flags) igt_assert(0); } - igt_assert_eq(workaround_fail_count(fd, ctx), 0); + igt_assert_eq(workarounds_fail_count(fd, ctx), 0); if (flags & CONTEXT) gem_context_destroy(fd, ctx); @@ -217,6 +265,74 @@ static void check_workarounds(int fd, enum operation op, unsigned int flags) close(fd); } +static bool is_empty(const char *s) +{ + while (*s != '\0') { + if (!isspace(*s)) + return false; + s++; + } + + return true; +} + +static char *skip_preamble(char *s, const char *preamble) +{ + int i = strlen(preamble); + + while (*s == *preamble) { + s++; + preamble++; + i--; + } + + return (i == 0) ? s : NULL; +} + +static void read_workarounds(FILE *file, const char *preamble, + struct intel_wa_reg **regs, int *num) +{ + char *header, *line = NULL; + size_t line_size; + struct intel_wa_reg *wa_regs = NULL; + int num_wa_regs = 0; + int i = 0; + + if (getline(&line, &line_size, file) <= 0) + goto out; + + header = skip_preamble(line, preamble); + if (!header) + goto out; + + igt_debug("i915_wa_registers: %s", line); + + sscanf(header, " applied: %d", &num_wa_regs); + if (!num_wa_regs) + goto out; + + wa_regs = malloc(num_wa_regs * sizeof(*wa_regs)); + + while (getline(&line, &line_size, file) > 0) { + if (is_empty(line)) + break; + + if (sscanf(line, "0x%X: 0x%08X, mask: 0x%08X", + &wa_regs[i].addr, + &wa_regs[i].value, + &wa_regs[i].mask) == 3) + i++; + } + + igt_assert_lte(i, num_wa_regs); + +out: + *regs = wa_regs; + *num = num_wa_regs; + + free(line); +} + igt_main { int device = -1; @@ -242,38 +358,49 @@ igt_main igt_fixture { FILE *file; - char *line = NULL; - size_t line_size; - int i, fd; + int fd; device = drm_open_driver(DRIVER_INTEL); igt_require_gem(device); gen = intel_gen(intel_get_drm_devid(device)); - fd = igt_debugfs_open(device, "i915_wa_registers", O_RDONLY); - file = fdopen(fd, "r"); - igt_assert(getline(&line, &line_size, file) > 0); - igt_debug("i915_wa_registers: %s", line); - sscanf(line, "Workarounds applied: %d", &num_wa_regs); - igt_require(num_wa_regs > 0); - - wa_regs = malloc(num_wa_regs * sizeof(*wa_regs)); - igt_assert(wa_regs); - - i = 0; - while (getline(&line, &line_size, file) > 0) { - igt_debug("%s", line); - if (sscanf(line, "0x%X: 0x%08X, mask: 0x%08X", - &wa_regs[i].addr, - &wa_regs[i].value, - &wa_regs[i].mask) == 3) - i++; + if ((file = fopen("wa_registers.txt", "r"))) { + igt_info("Using a local workarounds file\n"); + } else { + fd = igt_debugfs_open(device, "i915_wa_registers", O_RDONLY); + file = fdopen(fd, "r"); } + igt_assert(file); + + /* + * This test relies on the list of workarounds the kernel says + * have been applied and it only checks that those are (indeed) + * correctly applied. It does not report whether the system has + * applied all known workarounds for a fiven platform. + */ + read_workarounds(file, "Workarounds", + &ctx_wa_regs, &num_ctx_wa_regs); + + if (num_ctx_wa_regs == 0) { + /* Newish kernel, with support for more WA types */ + rewind(file); + + read_workarounds(file, "Context workarounds", + &ctx_wa_regs, &num_ctx_wa_regs); + read_workarounds(file, "GT workarounds", + >_wa_regs, &num_gt_wa_regs); + read_workarounds(file, "Display workarounds", + &display_wa_regs, + &num_display_wa_regs); + read_workarounds(file, "Whitelist workarounds", + &whitelist_wa_regs, + &num_whitelist_wa_regs); + } + igt_require(num_ctx_wa_regs + + num_gt_wa_regs + + num_whitelist_wa_regs > 0); - igt_assert_lte(i, num_wa_regs); - - free(line); fclose(file); close(fd); } @@ -284,4 +411,11 @@ igt_main check_workarounds(device, op->op, m->flags); } } + + igt_fixture { + free(ctx_wa_regs); + free(gt_wa_regs); + free(display_wa_regs); + free(whitelist_wa_regs); + } }