From patchwork Fri Sep 8 09:05:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Wang, Zhi A" X-Patchwork-Id: 9943445 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 C1CDC60224 for ; Fri, 8 Sep 2017 09:06:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B44DB2859A for ; Fri, 8 Sep 2017 09:06:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A92C2285CB; Fri, 8 Sep 2017 09:06: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=-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 0A2282859A for ; Fri, 8 Sep 2017 09:06:16 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 837E26EAF1; Fri, 8 Sep 2017 09:06:15 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4F34B6EAEF; Fri, 8 Sep 2017 09:06:14 +0000 (UTC) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 08 Sep 2017 02:06:14 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.42,360,1500966000"; d="scan'208";a="133140844" Received: from ciaragor-mobl.ger.corp.intel.com (HELO zhiwang1-MOBL.ger.corp.intel.com) ([10.252.5.221]) by orsmga002.jf.intel.com with ESMTP; 08 Sep 2017 02:06:11 -0700 From: Zhi Wang To: intel-gfx@lists.freedesktop.org, intel-gvt-dev@lists.freedesktop.org Date: Fri, 8 Sep 2017 17:05:53 +0800 Message-Id: <1504861553-19815-5-git-send-email-zhi.a.wang@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1504861553-19815-1-git-send-email-zhi.a.wang@intel.com> References: <1504861553-19815-1-git-send-email-zhi.a.wang@intel.com> Cc: Rodrigo Vivi , Ben Widawsky Subject: [Intel-gfx] [PATCH v8 5/5] drm/i915/selftests: Introduce live tests of private PAT management 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: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Introduce two live tests of private PAT management: igt_ppat_init - This test is to check if all the PPAT configuration is written into HW. igt_ppat_get - This test performs several sub-tests on intel_ppat_get() and intel_ppat_put(). The "perfect match" test case will try to get a PPAT entry with an existing value, then check if the returned PPAT entry is the same one. The "alloc entries" test case will run out of PPAT table, and check if all the requested values are put into the newly allocated PPAT entries. The negative test case will try to generate a new PPAT value, and get it when PPAT table is full. The "partial match" test case will generate a parital matched value from the existing PPAT table and try to match it. The "put entries" test case will free all the PPAT entries that allocated in "alloc entries" test case. It will check if the values of freed PPAT entries turn into ppat->clear_value. v8: - Remove noisy output. (Chris) - Add negative test case. (Chris) Cc: Ben Widawsky Cc: Rodrigo Vivi Cc: Joonas Lahtinen Suggested-by: Chris Wilson Signed-off-by: Zhi Wang --- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 276 ++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 6b132ca..c5179ce 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -1094,6 +1094,280 @@ static int igt_ggtt_page(void *arg) return err; } +static int check_cnl_ppat(struct drm_i915_private *dev_priv) +{ + struct intel_ppat *ppat = &dev_priv->ppat; + int i; + + for (i = 0; i < ppat->max_entries; i++) { + u32 value = I915_READ(GEN10_PAT_INDEX(i)); + + if (value != ppat->entries[i].value) { + pr_err("expected PPAT value isn't written into HW\n"); + return -EINVAL; + } + } + return 0; +} + +static int check_bdw_ppat(struct drm_i915_private *dev_priv) +{ + struct intel_ppat *ppat = &dev_priv->ppat; + u64 pat, hw_pat; + int i; + + pat = hw_pat = 0; + + for (i = 0; i < ppat->max_entries; i++) + pat |= GEN8_PPAT(i, ppat->entries[i].value); + + hw_pat = I915_READ(GEN8_PRIVATE_PAT_HI); + hw_pat <<= 32; + hw_pat |= I915_READ(GEN8_PRIVATE_PAT_LO); + + if (pat != hw_pat) { + pr_err("expected PPAT value isn't written into HW\n"); + return -EINVAL; + } + return 0; +} + +static int igt_ppat_check(void *arg) +{ + struct drm_i915_private *i915 = arg; + int ret; + + if (!i915->ppat.max_entries) + return 0; + + if (INTEL_GEN(i915) >= 10) + ret = check_cnl_ppat(i915); + else + ret = check_bdw_ppat(i915); + + return ret; +} + +static u8 generate_new_value(struct intel_ppat *ppat, bool partial, + bool negative) +{ + u8 ca[] = { GEN8_PPAT_WB, GEN8_PPAT_WT, GEN8_PPAT_UC, GEN8_PPAT_WC }; + u8 tc[] = { GEN8_PPAT_LLC, GEN8_PPAT_LLCELLC, GEN8_PPAT_LLCeLLC }; + u8 age[] = { GEN8_PPAT_AGE(3), GEN8_PPAT_AGE(2), GEN8_PPAT_AGE(1), + GEN8_PPAT_AGE(0) }; + u8 value = 0; + bool same; + int ca_index, tc_index, age_index, i; + +#define for_each_ppat_attr(ca_index, tc_index, age_index) \ + for ((ca_index) = 0 ; (ca_index) < ARRAY_SIZE(ca); (ca_index)++) \ + for ((tc_index) = 0; (tc_index) < ARRAY_SIZE(tc); (tc_index)++) \ + for ((age_index) = 0; (age_index) < ARRAY_SIZE(age); (age_index)++) + + for_each_ppat_attr(ca_index, tc_index, age_index) { + value = age[age_index] | ca[ca_index] | tc[tc_index]; + same = false; + + for_each_set_bit(i, ppat->used, ppat->max_entries) { + if (value != ppat->entries[i].value) + continue; + + same = true; + break; + } + + if (same) + continue; + + if (!partial && !negative) + return value; + + if (partial) { + /* cache attribute has to be the same. */ + for_each_set_bit(i, ppat->used, ppat->max_entries) { + if (GEN8_PPAT_GET_CA(value) != + GEN8_PPAT_GET_CA(ppat->entries[i].value)) + continue; + + return value; + } + } + + if (negative) { + /* cache attribute has to be new. */ + same = false; + for_each_set_bit(i, ppat->used, ppat->max_entries) { + if (GEN8_PPAT_GET_CA(value) == + GEN8_PPAT_GET_CA(ppat->entries[i].value)) { + same = true; + break; + } + } + if (same) + continue; + return value; + } + } +#undef for_each_ppat_attr + return 0; +} + +static inline bool ppat_table_is_full(struct intel_ppat *ppat) +{ + return bitmap_weight(ppat->used, ppat->max_entries) == + ppat->max_entries; +} + +static int igt_ppat_get(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct intel_ppat *ppat = &i915->ppat; + const struct intel_ppat_entry **entries; + const struct intel_ppat_entry *entry; + unsigned int size = 0; + u8 value; + int i, ret; + + if (!ppat->max_entries) + return 0; + + ret = igt_ppat_check(i915); + if (ret) + return ret; + + /* case 1: perfect match */ + entry = intel_ppat_get(i915, ppat->entries[0].value); + if (IS_ERR(entry)) + return PTR_ERR(entry); + + if (entry != &ppat->entries[0]) { + pr_err("not expected entry\n"); + intel_ppat_put(entry); + return -EINVAL; + } + + intel_ppat_put(entry); + + /* case 2: alloc new entries */ + entries = NULL; + ret = 0; + + while (!ppat_table_is_full(ppat)) { + const struct intel_ppat_entry **p; + DECLARE_BITMAP(used, INTEL_MAX_PPAT_ENTRIES); + + bitmap_copy(used, ppat->used, ppat->max_entries); + + p = krealloc(entries, (size + 1) * + sizeof(struct intel_ppat_entry *), + GFP_KERNEL); + if (!p) { + ret = -ENOSPC; + break; + } + entries = p; + + p = &entries[size++]; + *p = NULL; + + value = generate_new_value(ppat, false, false); + if (!value) { + pr_err("cannot fill the unused PPAT entries?\n"); + ret = -EINVAL; + break; + } + + *p = entry = intel_ppat_get(i915, value); + if (IS_ERR(entry)) { + pr_err("fail to get new entry\n"); + ret = PTR_ERR(entry); + break; + } + + if (entry->value != value) { + pr_err("fail to get expected new value\n"); + ret = -EINVAL; + break; + } + + if (bitmap_equal(used, ppat->used, ppat->max_entries)) { + pr_err("fail to alloc a new entry\n"); + ret = -EINVAL; + break; + } + } + + if (ret) + goto ppat_put; + + /* case 3: negative test, suppose PPAT table is full now */ + value = generate_new_value(ppat, false, true); + if (!value) { + pr_err("fail to get new value\n"); + ret = -EINVAL; + goto ppat_put; + } + + entry = intel_ppat_get(i915, value); + if (!IS_ERR(entry) || PTR_ERR(entry) != -ENOSPC) { + pr_err("fail on negative test\n"); + ret = -EINVAL; + goto ppat_put; + } + + ret = 0; + + /* case 4: partial match */ + value = generate_new_value(ppat, true, false); + if (!value) { + pr_err("fail to get new value\n"); + ret = -EINVAL; + goto ppat_put; + } + + entry = intel_ppat_get(i915, value); + if (IS_ERR(entry)) { + pr_err("fail to get new entry\n"); + ret = PTR_ERR(entry); + goto ppat_put; + } + + if (!(entry->value != value && + GEN8_PPAT_GET_CA(entry->value) == GEN8_PPAT_GET_CA(value))) { + pr_err("fail to get expected value\n"); + ret = -EINVAL; + } + + intel_ppat_put(entry); + +ppat_put: + if (entries) { + for (i = 0; i < size; i++) { + if (IS_ERR(entries[i]) || !entries[i]) + continue; + + intel_ppat_put(entries[i]); + + if (entries[i]->value != ppat->clear_value) { + pr_err("fail to put ppat value\n"); + ret = -EINVAL; + break; + } + } + kfree(entries); + entries = NULL; + } + + if (ret) + return ret; + + ret = igt_ppat_check(i915); + if (ret) + return ret; + + return 0; +} + static void track_vma_bind(struct i915_vma *vma) { struct drm_i915_gem_object *obj = vma->obj; @@ -1560,6 +1834,8 @@ int i915_gem_gtt_live_selftests(struct drm_i915_private *i915) SUBTEST(igt_ggtt_pot), SUBTEST(igt_ggtt_fill), SUBTEST(igt_ggtt_page), + SUBTEST(igt_ppat_check), + SUBTEST(igt_ppat_get), }; GEM_BUG_ON(offset_in_page(i915->ggtt.base.total));