From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 601BDE77188 for ; Wed, 18 Dec 2024 21:06:43 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 28B5310E104; Wed, 18 Dec 2024 21:06:43 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="ETuMI7el"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) by gabe.freedesktop.org (Postfix) with ESMTPS id AD1B010E104 for ; Wed, 18 Dec 2024 21:06:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1734556002; x=1766092002; h=message-id:date:mime-version:subject:to:cc:references: from:in-reply-to:content-transfer-encoding; bh=cr1byoVRtkK7+DQqYGU0T5oAf3eGae/hJCkdOCfjKfo=; b=ETuMI7el1UL5LGc0krKbXlVMUTJMDf6YHXWLn0hvbK6ltORCU7vWryoc N7rI8E+Jh6SFCnqUXc4VigxcwmdY/sR+eAuUZBLcV+FY5tbTLDoAgeR2v tMJOkEMXe/i0huY6o0yOuvxhLgsoINThJM3ICeOazxzGD7ctKc3Ik/C+c AKnjWV4pDGyWc3Gkk1bj7rYh5qmOHoEFDBq+XxtwWo+ExEBh/IleH0fqF 4bHLHyKt5SeuL1MUBo94DHmZHkDPYZvJsPuLt2awILBbIcvJ6izhzg9xk p0lgjUQX53Nnh4dIutVBgVK/7RF+TRmYVA9NWLD0v0uR8N3jsVSMGaK7h g==; X-CSE-ConnectionGUID: GayCY/tGQRS/EGn7gyp91w== X-CSE-MsgGUID: m2owiNf+RYacEkDY50bzGg== X-IronPort-AV: E=McAfee;i="6700,10204,11290"; a="34333124" X-IronPort-AV: E=Sophos;i="6.12,245,1728975600"; d="scan'208";a="34333124" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 Dec 2024 13:06:41 -0800 X-CSE-ConnectionGUID: c/Vdvp+eTrW0Z/bDnOFqMA== X-CSE-MsgGUID: MSFPJL7qQ+CJ5N62l8Y0nA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,245,1728975600"; d="scan'208";a="98381530" Received: from irvmail002.ir.intel.com ([10.43.11.120]) by fmviesa010.fm.intel.com with ESMTP; 18 Dec 2024 13:06:40 -0800 Received: from [10.246.0.69] (mwajdecz-MOBL.ger.corp.intel.com [10.246.0.69]) by irvmail002.ir.intel.com (Postfix) with ESMTP id 08F4B2711F; Wed, 18 Dec 2024 21:06:38 +0000 (GMT) Message-ID: Date: Wed, 18 Dec 2024 22:06:38 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH 13/13] drm/xe/kunit: Add KUnit tests for GuC Buffer Cache To: Matthew Brost Cc: intel-xe@lists.freedesktop.org References: <20241212010141.389-1-michal.wajdeczko@intel.com> <20241212010141.389-14-michal.wajdeczko@intel.com> Content-Language: en-US From: Michal Wajdeczko In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: intel-xe@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel Xe graphics driver List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-xe-bounces@lists.freedesktop.org Sender: "Intel-xe" On 12.12.2024 04:36, Matthew Brost wrote: > On Thu, Dec 12, 2024 at 02:01:41AM +0100, Michal Wajdeczko wrote: >> Add tests to make sure that recently added GuC Buffer Cache >> component is working as expected. >> > > My opinion is this selftest is a bit overkill, maybe other disagree, but > I'd drop this as it quite a bit of code to carry for little ROI (i.e. if > drm_suballoc is broken, the entire DRM subsystem is likely broken). but the goal of this kunit is mainly to test buf-cache API, as implementation details, which is now xe_sa & drm_sa, could be changed > > Matt > >> Signed-off-by: Michal Wajdeczko >> --- >> v2: rebased (Michal) >> --- >> drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c | 335 ++++++++++++++++++++ >> drivers/gpu/drm/xe/xe_guc_buf.c | 4 + >> 2 files changed, 339 insertions(+) >> create mode 100644 drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c >> >> diff --git a/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c b/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c >> new file mode 100644 >> index 000000000000..8a90f832915b >> --- /dev/null >> +++ b/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c >> @@ -0,0 +1,335 @@ >> +// SPDX-License-Identifier: GPL-2.0 AND MIT >> +/* >> + * Copyright © 2024 Intel Corporation >> + */ >> + >> +#include >> +#include >> +#include >> + >> +#include "xe_device.h" >> +#include "xe_ggtt.h" >> +#include "xe_guc_ct.h" >> +#include "xe_kunit_helpers.h" >> +#include "xe_pci_test.h" >> + >> +#define DUT_GGTT_START SZ_1M >> +#define DUT_GGTT_SIZE SZ_2M >> +#define DUT_DATA 1 >> + >> +static struct xe_bo *replacement_xe_managed_bo_create_pin_map(struct xe_device *xe, >> + struct xe_tile *tile, >> + size_t size, u32 flags) >> +{ >> + struct kunit *test = kunit_get_current_test(); >> + struct xe_bo *bo; >> + void *buf; >> + >> + bo = drmm_kzalloc(&xe->drm, sizeof(*bo), GFP_KERNEL); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bo); >> + >> + buf = drmm_kzalloc(&xe->drm, size, GFP_KERNEL); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf); >> + >> + bo->tile = tile; >> + bo->ttm.bdev = &xe->ttm; >> + bo->size = size; >> + iosys_map_set_vaddr(&bo->vmap, buf); >> + >> + if (flags & XE_BO_FLAG_GGTT) { >> + struct xe_ggtt *ggtt = tile->mem.ggtt; >> + >> + bo->ggtt_node[tile->id] = xe_ggtt_node_init(ggtt); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bo->ggtt_node[tile->id]); >> + >> + KUNIT_ASSERT_EQ(test, 0, >> + drm_mm_insert_node_in_range(&ggtt->mm, >> + &bo->ggtt_node[tile->id]->base, >> + bo->size, SZ_4K, >> + 0, 0, U64_MAX, 0)); >> + } >> + >> + return bo; >> +} >> + >> +static int guc_buf_test_init(struct kunit *test) >> +{ >> + struct xe_pci_fake_data fake = { >> + .sriov_mode = XE_SRIOV_MODE_PF, >> + .platform = XE_TIGERLAKE, /* some random platform */ >> + .subplatform = XE_SUBPLATFORM_NONE, >> + }; >> + struct xe_ggtt *ggtt; >> + struct xe_guc *guc; >> + >> + test->priv = &fake; >> + xe_kunit_helper_xe_device_test_init(test); >> + >> + ggtt = xe_device_get_root_tile(test->priv)->mem.ggtt; >> + guc = &xe_device_get_gt(test->priv, 0)->uc.guc; >> + >> + drm_mm_init(&ggtt->mm, DUT_GGTT_START, DUT_GGTT_SIZE); >> + mutex_init(&ggtt->lock); >> + >> + kunit_activate_static_stub(test, xe_managed_bo_create_pin_map, >> + replacement_xe_managed_bo_create_pin_map); >> + >> + KUNIT_ASSERT_EQ(test, 0, xe_guc_buf_cache_init(&guc->buf)); >> + >> + test->priv = &guc->buf; >> + return 0; >> +} >> + >> +static void test_smallest(struct kunit *test) >> +{ >> + struct xe_guc_buf_cache *cache = test->priv; >> + struct xe_guc_buf buf; >> + >> + buf = xe_guc_buf_reserve(cache, 1); >> + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); >> + KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf)); >> + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf)); >> + KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf)); >> + KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf)); >> + xe_guc_buf_release(buf); >> +} >> + >> +static void test_largest(struct kunit *test) >> +{ >> + struct xe_guc_buf_cache *cache = test->priv; >> + struct xe_guc_buf buf; >> + >> + buf = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache)); >> + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); >> + KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf)); >> + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf)); >> + KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf)); >> + KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf)); >> + xe_guc_buf_release(buf); >> +} >> + >> +static void test_granular(struct kunit *test) >> +{ >> + struct xe_guc_buf_cache *cache = test->priv; >> + struct xe_guc_buf *bufs; >> + int n, dwords; >> + >> + dwords = xe_guc_buf_cache_dwords(cache); >> + bufs = kunit_kcalloc(test, dwords, sizeof(*bufs), GFP_KERNEL); >> + KUNIT_EXPECT_NOT_NULL(test, bufs); >> + >> + for (n = 0; n < dwords; n++) >> + bufs[n] = xe_guc_buf_reserve(cache, 1); >> + >> + for (n = 0; n < dwords; n++) >> + KUNIT_EXPECT_TRUE_MSG(test, xe_guc_buf_is_valid(bufs[n]), "n=%d", n); >> + >> + for (n = 0; n < dwords; n++) >> + xe_guc_buf_release(bufs[n]); >> +} >> + >> +static void test_unique(struct kunit *test) >> +{ >> + struct xe_guc_buf_cache *cache = test->priv; >> + struct xe_guc_buf *bufs; >> + int n, m, dwords; >> + >> + dwords = xe_guc_buf_cache_dwords(cache); >> + bufs = kunit_kcalloc(test, dwords, sizeof(*bufs), GFP_KERNEL); >> + KUNIT_EXPECT_NOT_NULL(test, bufs); >> + >> + for (n = 0; n < dwords; n++) >> + bufs[n] = xe_guc_buf_reserve(cache, 1); >> + >> + for (n = 0; n < dwords; n++) { >> + for (m = n + 1; m < dwords; m++) { >> + KUNIT_EXPECT_PTR_NE_MSG(test, xe_guc_buf_cpu_ptr(bufs[n]), >> + xe_guc_buf_cpu_ptr(bufs[m]), "n=%d, m=%d", n, m); >> + KUNIT_ASSERT_NE_MSG(test, xe_guc_buf_gpu_addr(bufs[n]), >> + xe_guc_buf_gpu_addr(bufs[m]), "n=%d, m=%d", n, m); >> + } >> + } >> + >> + for (n = 0; n < dwords; n++) >> + xe_guc_buf_release(bufs[n]); >> +} >> + >> +static void test_overlap(struct kunit *test) >> +{ >> + struct xe_guc_buf_cache *cache = test->priv; >> + struct xe_guc_buf b1, b2; >> + u32 dwords = xe_guc_buf_cache_dwords(cache) / 2; >> + u32 bytes = dwords * sizeof(u32); >> + void *p1, *p2; >> + u64 a1, a2; >> + >> + b1 = xe_guc_buf_reserve(cache, dwords); >> + b2 = xe_guc_buf_reserve(cache, dwords); >> + >> + p1 = xe_guc_buf_cpu_ptr(b1); >> + p2 = xe_guc_buf_cpu_ptr(b2); >> + >> + a1 = xe_guc_buf_gpu_addr(b1); >> + a2 = xe_guc_buf_gpu_addr(b2); >> + >> + KUNIT_EXPECT_PTR_NE(test, p1, p2); >> + if (p1 < p2) >> + KUNIT_EXPECT_LT(test, (uintptr_t)(p1 + bytes - 1), (uintptr_t)p2); >> + else >> + KUNIT_EXPECT_LT(test, (uintptr_t)(p2 + bytes - 1), (uintptr_t)p1); >> + >> + KUNIT_EXPECT_NE(test, a1, a2); >> + if (a1 < a2) >> + KUNIT_EXPECT_LT(test, a1 + bytes - 1, a2); >> + else >> + KUNIT_EXPECT_LT(test, a2 + bytes - 1, a1); >> + >> + xe_guc_buf_release(b1); >> + xe_guc_buf_release(b2); >> +} >> + >> +static void test_reusable(struct kunit *test) >> +{ >> + struct xe_guc_buf_cache *cache = test->priv; >> + struct xe_guc_buf b1, b2; >> + void *p1; >> + u64 a1; >> + >> + b1 = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache)); >> + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(b1)); >> + KUNIT_EXPECT_NOT_NULL(test, p1 = xe_guc_buf_cpu_ptr(b1)); >> + KUNIT_EXPECT_NE(test, 0, a1 = xe_guc_buf_gpu_addr(b1)); >> + xe_guc_buf_release(b1); >> + >> + b2 = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache)); >> + KUNIT_EXPECT_PTR_EQ(test, p1, xe_guc_buf_cpu_ptr(b2)); >> + KUNIT_EXPECT_EQ(test, a1, xe_guc_buf_gpu_addr(b2)); >> + xe_guc_buf_release(b2); >> +} >> + >> +static void test_too_big(struct kunit *test) >> +{ >> + struct xe_guc_buf_cache *cache = test->priv; >> + struct xe_guc_buf buf; >> + >> + buf = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache) + 1); >> + KUNIT_EXPECT_FALSE(test, xe_guc_buf_is_valid(buf)); >> + xe_guc_buf_release(buf); /* shouldn't crash */ >> +} >> + >> +static void test_flush(struct kunit *test) >> +{ >> + struct xe_guc_buf_cache *cache = test->priv; >> + struct xe_guc_buf buf; >> + const u32 dwords = xe_guc_buf_cache_dwords(cache); >> + const u32 bytes = dwords * sizeof(u32); >> + u32 *s, *p, *d; >> + int n; >> + >> + KUNIT_ASSERT_NOT_NULL(test, s = kunit_kcalloc(test, dwords, sizeof(u32), GFP_KERNEL)); >> + KUNIT_ASSERT_NOT_NULL(test, d = kunit_kcalloc(test, dwords, sizeof(u32), GFP_KERNEL)); >> + >> + for (n = 0; n < dwords; n++) >> + s[n] = n; >> + >> + buf = xe_guc_buf_reserve(cache, dwords); >> + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); >> + KUNIT_ASSERT_NOT_NULL(test, p = xe_guc_buf_cpu_ptr(buf)); >> + KUNIT_EXPECT_PTR_NE(test, p, s); >> + KUNIT_EXPECT_PTR_NE(test, p, d); >> + >> + memcpy(p, s, bytes); >> + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_flush(buf)); >> + >> + iosys_map_memcpy_from(d, &cache->sam->bo->vmap, 0, bytes); >> + KUNIT_EXPECT_MEMEQ(test, s, d, bytes); >> + >> + xe_guc_buf_release(buf); >> +} >> + >> +static void test_lookup(struct kunit *test) >> +{ >> + struct xe_guc_buf_cache *cache = test->priv; >> + struct xe_guc_buf buf; >> + u32 dwords; >> + u64 addr; >> + u32 *p; >> + int n; >> + >> + dwords = xe_guc_buf_cache_dwords(cache); >> + buf = xe_guc_buf_reserve(cache, dwords); >> + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); >> + KUNIT_ASSERT_NOT_NULL(test, p = xe_guc_buf_cpu_ptr(buf)); >> + KUNIT_ASSERT_NE(test, 0, addr = xe_guc_buf_gpu_addr(buf)); >> + >> + KUNIT_EXPECT_EQ(test, 0, xe_guc_cache_gpu_addr_from_ptr(cache, p - 1, sizeof(u32))); >> + KUNIT_EXPECT_EQ(test, 0, xe_guc_cache_gpu_addr_from_ptr(cache, p + dwords, sizeof(u32))); >> + >> + for (n = 0; n < dwords; n++) >> + KUNIT_EXPECT_EQ_MSG(test, xe_guc_cache_gpu_addr_from_ptr(cache, p + n, sizeof(u32)), >> + addr + n * sizeof(u32), "n=%d", n); >> + >> + xe_guc_buf_release(buf); >> +} >> + >> +static void test_data(struct kunit *test) >> +{ >> + static const u32 data[] = { 1, 2, 3, 4, 5, 6 }; >> + struct xe_guc_buf_cache *cache = test->priv; >> + struct xe_guc_buf buf; >> + void *p; >> + >> + buf = xe_guc_buf_from_data(cache, data, sizeof(data)); >> + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); >> + KUNIT_ASSERT_NOT_NULL(test, p = xe_guc_buf_cpu_ptr(buf)); >> + KUNIT_EXPECT_MEMEQ(test, p, data, sizeof(data)); >> + >> + xe_guc_buf_release(buf); >> +} >> + >> +static void test_class(struct kunit *test) >> +{ >> + struct xe_guc_buf_cache *cache = test->priv; >> + u32 dwords = xe_guc_buf_cache_dwords(cache); >> + >> + { >> + CLASS(xe_guc_buf, buf)(cache, dwords); >> + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); >> + KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf)); >> + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf)); >> + KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf)); >> + KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf)); >> + } >> + >> + { >> + CLASS(xe_guc_buf, buf)(cache, dwords); >> + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); >> + KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf)); >> + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf)); >> + KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf)); >> + KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf)); >> + } >> +} >> + >> +static struct kunit_case guc_buf_test_cases[] = { >> + KUNIT_CASE(test_smallest), >> + KUNIT_CASE(test_largest), >> + KUNIT_CASE(test_granular), >> + KUNIT_CASE(test_unique), >> + KUNIT_CASE(test_overlap), >> + KUNIT_CASE(test_reusable), >> + KUNIT_CASE(test_too_big), >> + KUNIT_CASE(test_flush), >> + KUNIT_CASE(test_lookup), >> + KUNIT_CASE(test_data), >> + KUNIT_CASE(test_class), >> + {} >> +}; >> + >> +static struct kunit_suite guc_buf_suite = { >> + .name = "guc_buf", >> + .test_cases = guc_buf_test_cases, >> + .init = guc_buf_test_init, >> +}; >> + >> +kunit_test_suites(&guc_buf_suite); >> diff --git a/drivers/gpu/drm/xe/xe_guc_buf.c b/drivers/gpu/drm/xe/xe_guc_buf.c >> index 261c7c74417f..ce6d9830e13b 100644 >> --- a/drivers/gpu/drm/xe/xe_guc_buf.c >> +++ b/drivers/gpu/drm/xe/xe_guc_buf.c >> @@ -170,3 +170,7 @@ u64 xe_guc_cache_gpu_addr_from_ptr(struct xe_guc_buf_cache *cache, const void *p >> >> return cache->sam->gpu_addr + offset; >> } >> + >> +#if IS_BUILTIN(CONFIG_DRM_XE_KUNIT_TEST) >> +#include "tests/xe_guc_buf_kunit.c" >> +#endif >> -- >> 2.47.1 >>