All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Laguna, Lukasz" <lukasz.laguna@intel.com>
To: "Piórkowski, Piotr" <piotr.piorkowski@intel.com>,
	intel-xe@lists.freedesktop.org
Cc: "Ville Syrjälä" <ville.syrjala@linux.intel.com>,
	"Maarten Lankhorst" <dev@lankhorst.se>
Subject: Re: [v7,5/5] drm/xe/ggtt: Add KUnit tests for usable and shareable pools
Date: Tue, 10 Nov 2026 16:31:45 +0100	[thread overview]
Message-ID: <cfb7a910-823d-416d-beab-7a6e3077788f@intel.com> (raw)
In-Reply-To: <20261021085716.709503-6-piotr.piorkowski@intel.com>


On 10/21/2026 10:57, Piórkowski, Piotr wrote:
> From: Piotr Piórkowski <piotr.piorkowski@intel.com>
>
> Add GGTT KUnit tests focused on the newly introduced usable and
> shareable pools.
>
> Cover range initialization for native and PF modes, including partially
> overlapping pools. Exercise allocation direction and conflicts between
> the pools, as well as the unavailable shareable pool and requests
> exceeding pool capacity.
>
> v2:
>   - Init ggtt.lock with mutex_init() in each test.
> v3:
>   - Rename the test file to use the _kunit.c suffix.
>   - Use shared GGTT setup and cleanup helpers.
>   - Split PCI IOV coverage into a separate KUnit suite.
> v4:
>   - Release allocated nodes through KUnit deferred actions, so that an
>     aborted test does not leak them into drm_mm_takedown() (Sashiko).
> v5:
>   - Move ggtt_test_insert_node_shareable() under CONFIG_PCI_IOV to fix
>     the !CONFIG_PCI_IOV build (Sashiko).
>
> Assisted-by: Claude:claude-5-sonnet
> Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Maarten Lankhorst <dev@lankhorst.se>
> ---
>   drivers/gpu/drm/xe/tests/xe_ggtt_kunit.c | 341 +++++++++++++++++++++++
>   drivers/gpu/drm/xe/xe_ggtt.c             |   4 +
>   2 files changed, 345 insertions(+)
>   create mode 100644 drivers/gpu/drm/xe/tests/xe_ggtt_kunit.c
>
> diff --git a/drivers/gpu/drm/xe/tests/xe_ggtt_kunit.c b/drivers/gpu/drm/xe/tests/xe_ggtt_kunit.c
> new file mode 100644
> index 0000000000000..53c17d4c1da99
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/tests/xe_ggtt_kunit.c
> @@ -0,0 +1,341 @@
> +// SPDX-License-Identifier: GPL-2.0 AND MIT
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +#include <kunit/test.h>
> +
> +#include "xe_device.h"
> +#include "xe_kunit_helpers.h"
> +
> +#define GGTT_TEST_START		SZ_1M
> +
> +static u64 ggtt_test_accessible_size(struct kunit *test)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +
> +	return GUC_GGTT_TOP - xe_wopcm_size(tile_to_xe(tile));
> +}
> +
> +static void ggtt_test_fini(void *data)
> +{
> +	struct xe_ggtt *ggtt = data;
> +
> +	drm_mm_takedown(&ggtt->mm);
> +}
> +
> +static struct xe_ggtt *ggtt_test_create(struct kunit *test, u64 full_size,
> +					u64 usable_size, u64 shareable_size)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +	struct xe_ggtt *ggtt;
> +	int err;
> +
> +	ggtt = kunit_kzalloc(test, sizeof(*ggtt), GFP_KERNEL);

Can't we use ggtt = xe_device_get_root_tile(test->priv)->mem.ggtt; ?

Thanks,
Lukasz

> +	if (!ggtt)
> +		return NULL;
> +
> +	ggtt->tile = tile;
> +	mutex_init(&ggtt->lock);
> +	ggtt_init_ranges(ggtt, GGTT_TEST_START, full_size, usable_size, shareable_size);
> +
> +	err = kunit_add_action_or_reset(test, ggtt_test_fini, ggtt);
> +	if (err)
> +		return NULL;
> +
> +	return ggtt;
> +}
> +
> +static void ggtt_test_remove_node(void *data)
> +{
> +	struct xe_ggtt_node *node = data;
> +	struct xe_ggtt *ggtt = node->ggtt;
> +
> +	mutex_lock(&ggtt->lock);
> +	drm_mm_remove_node(&node->base);
> +	node->base.size = 0;
> +	mutex_unlock(&ggtt->lock);
> +
> +	ggtt_node_fini(node);
> +}
> +
> +/*
> + * Release the node on test exit, before the GGTT is torn down, so that an
> + * aborted test does not leave it in the drm_mm.
> + */
> +static struct xe_ggtt_node *ggtt_test_track_node(struct kunit *test,
> +						 struct xe_ggtt_node *node)
> +{
> +	if (!IS_ERR_OR_NULL(node) &&
> +	    kunit_add_action_or_reset(test, ggtt_test_remove_node, node))
> +		return ERR_PTR(-ENOMEM);
> +
> +	return node;
> +}
> +
> +static struct xe_ggtt_node *ggtt_test_insert_node(struct kunit *test,
> +						  struct xe_ggtt *ggtt, u32 size)
> +{
> +	return ggtt_test_track_node(test, xe_ggtt_insert_node(ggtt, size, XE_PAGE_SIZE));
> +}
> +
> +static void init_native(struct kunit *test)
> +{
> +	u64 accessible = ggtt_test_accessible_size(test);
> +	u64 usable = min_t(u64, SZ_1G, accessible);
> +	struct xe_ggtt *ggtt;
> +
> +	ggtt = ggtt_test_create(test, usable, usable, 0);
> +	KUNIT_ASSERT_NOT_NULL(test, ggtt);
> +
> +	KUNIT_EXPECT_EQ(test, ggtt->start, GGTT_TEST_START);
> +	KUNIT_EXPECT_EQ(test, ggtt->size, usable);
> +	KUNIT_EXPECT_EQ(test, ggtt->full_size, usable);
> +}
> +
> +static void alloc_usable_pool_high(struct kunit *test)
> +{
> +	u64 accessible = ggtt_test_accessible_size(test);
> +	u64 usable = (accessible * 3) / 4;
> +	struct xe_ggtt_node *usable_node;
> +	struct xe_ggtt *ggtt;
> +
> +	ggtt = ggtt_test_create(test, usable, usable, 0);
> +	KUNIT_ASSERT_NOT_NULL(test, ggtt);
> +
> +	usable_node = ggtt_test_insert_node(test, ggtt, XE_PAGE_SIZE);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, usable_node);
> +	KUNIT_EXPECT_EQ(test, xe_ggtt_node_addr(usable_node),
> +			GGTT_TEST_START + usable - XE_PAGE_SIZE);
> +}
> +
> +static void alloc_usable_pool_oversized(struct kunit *test)
> +{
> +	u64 accessible = ggtt_test_accessible_size(test);
> +	u64 usable = (accessible * 3) / 4;
> +	struct xe_ggtt_node *node;
> +	struct xe_ggtt *ggtt;
> +
> +	KUNIT_ASSERT_LE(test, usable + XE_PAGE_SIZE, (u64)U32_MAX);
> +
> +	ggtt = ggtt_test_create(test, usable, usable, 0);
> +	KUNIT_ASSERT_NOT_NULL(test, ggtt);
> +
> +	node = ggtt_test_insert_node(test, ggtt, usable + XE_PAGE_SIZE);
> +	KUNIT_ASSERT_TRUE(test, IS_ERR(node));
> +	KUNIT_EXPECT_EQ(test, PTR_ERR(node), -ENOSPC);
> +}
> +
> +static struct kunit_case ggtt_test_cases[] = {
> +	KUNIT_CASE(init_native),
> +	KUNIT_CASE(alloc_usable_pool_high),
> +	KUNIT_CASE(alloc_usable_pool_oversized),
> +	{}
> +};
> +
> +static struct kunit_suite ggtt_suite = {
> +	.name = "xe_ggtt",
> +	.test_cases = ggtt_test_cases,
> +	.init = xe_kunit_helper_xe_device_test_init,
> +};
> +
> +#if IS_ENABLED(CONFIG_PCI_IOV)
> +static struct xe_ggtt_node *ggtt_test_insert_node_shareable(struct kunit *test,
> +							    struct xe_ggtt *ggtt, u32 size)
> +{
> +	return ggtt_test_track_node(test,
> +				    xe_ggtt_insert_node_shareable(ggtt, size, XE_PAGE_SIZE));
> +}
> +
> +static void init_shared_pf(struct kunit *test)
> +{
> +	u64 accessible = ggtt_test_accessible_size(test);
> +	struct xe_ggtt *ggtt;
> +
> +	ggtt = ggtt_test_create(test, accessible, accessible, accessible);
> +	KUNIT_ASSERT_NOT_NULL(test, ggtt);
> +
> +	KUNIT_EXPECT_EQ(test, ggtt->size, accessible);
> +	KUNIT_EXPECT_EQ(test, ggtt_shareable_offset(ggtt), 0);
> +	KUNIT_EXPECT_EQ(test, ggtt->shareable_size, accessible);
> +	KUNIT_EXPECT_EQ(test, ggtt->full_size, accessible);
> +}
> +
> +static void init_partial_overlap(struct kunit *test)
> +{
> +	u64 accessible = ggtt_test_accessible_size(test);
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +	struct xe_ggtt *ggtt;
> +
> +	KUNIT_ASSERT_GT(test, accessible, 0ULL);
> +	KUNIT_ASSERT_GT(test, usable, shareable);
> +
> +	ggtt = ggtt_test_create(test, accessible, usable, shareable);
> +	KUNIT_ASSERT_NOT_NULL(test, ggtt);
> +
> +	KUNIT_EXPECT_EQ(test, ggtt->size, usable);
> +	KUNIT_EXPECT_EQ(test, ggtt_shareable_offset(ggtt), accessible - shareable);
> +	KUNIT_EXPECT_EQ(test, ggtt->shareable_size, shareable);
> +	KUNIT_EXPECT_LT(test, ggtt_shareable_offset(ggtt), usable);
> +	KUNIT_EXPECT_EQ(test, ggtt->full_size, accessible);
> +}
> +
> +static void alloc_usable_pool_low(struct kunit *test)
> +{
> +	u64 accessible = ggtt_test_accessible_size(test);
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +	struct xe_ggtt_node *usable_node;
> +	struct xe_ggtt *ggtt;
> +
> +	ggtt = ggtt_test_create(test, accessible, usable, shareable);
> +	KUNIT_ASSERT_NOT_NULL(test, ggtt);
> +
> +	usable_node = ggtt_test_insert_node(test, ggtt, XE_PAGE_SIZE);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, usable_node);
> +	KUNIT_EXPECT_EQ(test, xe_ggtt_node_addr(usable_node), GGTT_TEST_START);
> +	KUNIT_EXPECT_EQ(test, xe_ggtt_node_size(usable_node), (u64)XE_PAGE_SIZE);
> +}
> +
> +static void alloc_shareable_pool_high(struct kunit *test)
> +{
> +	u64 accessible = ggtt_test_accessible_size(test);
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +	struct xe_ggtt_node *shareable_node;
> +	struct xe_ggtt *ggtt;
> +
> +	ggtt = ggtt_test_create(test, accessible, usable, shareable);
> +	KUNIT_ASSERT_NOT_NULL(test, ggtt);
> +
> +	shareable_node = ggtt_test_insert_node_shareable(test, ggtt, XE_PAGE_SIZE);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, shareable_node);
> +	KUNIT_EXPECT_EQ(test, xe_ggtt_node_addr(shareable_node),
> +			GGTT_TEST_START + accessible - XE_PAGE_SIZE);
> +	KUNIT_EXPECT_EQ(test, xe_ggtt_node_size(shareable_node), (u64)XE_PAGE_SIZE);
> +}
> +
> +static void alloc_partial_overlap(struct kunit *test)
> +{
> +	u64 accessible = ggtt_test_accessible_size(test);
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +	struct xe_ggtt_node *shareable_node;
> +	struct xe_ggtt_node *usable_node;
> +	struct xe_ggtt *ggtt;
> +
> +	ggtt = ggtt_test_create(test, accessible, usable, shareable);
> +	KUNIT_ASSERT_NOT_NULL(test, ggtt);
> +
> +	usable_node = ggtt_test_insert_node(test, ggtt, XE_PAGE_SIZE);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, usable_node);
> +	shareable_node = ggtt_test_insert_node_shareable(test, ggtt, XE_PAGE_SIZE);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, shareable_node);
> +
> +	KUNIT_EXPECT_EQ(test, xe_ggtt_node_addr(usable_node), GGTT_TEST_START);
> +	KUNIT_EXPECT_EQ(test, xe_ggtt_node_addr(shareable_node),
> +			GGTT_TEST_START + accessible - XE_PAGE_SIZE);
> +}
> +
> +static void alloc_partial_overlap_usable_full(struct kunit *test)
> +{
> +	u64 accessible = ggtt_test_accessible_size(test);
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +	struct xe_ggtt_node *shareable_node;
> +	struct xe_ggtt_node *usable_node;
> +	struct xe_ggtt *ggtt;
> +
> +	KUNIT_ASSERT_LE(test, usable, (u64)U32_MAX);
> +	KUNIT_ASSERT_LE(test, shareable, (u64)U32_MAX);
> +
> +	ggtt = ggtt_test_create(test, accessible, usable, shareable);
> +	KUNIT_ASSERT_NOT_NULL(test, ggtt);
> +
> +	usable_node = ggtt_test_insert_node(test, ggtt, usable);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, usable_node);
> +	shareable_node = ggtt_test_insert_node_shareable(test, ggtt, shareable);
> +	KUNIT_ASSERT_TRUE(test, IS_ERR(shareable_node));
> +	KUNIT_EXPECT_EQ(test, PTR_ERR(shareable_node), -ENOSPC);
> +}
> +
> +static void alloc_partial_overlap_shareable_full(struct kunit *test)
> +{
> +	u64 accessible = ggtt_test_accessible_size(test);
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +	struct xe_ggtt_node *shareable_node;
> +	struct xe_ggtt_node *usable_node;
> +	struct xe_ggtt *ggtt;
> +
> +	KUNIT_ASSERT_LE(test, usable, (u64)U32_MAX);
> +	KUNIT_ASSERT_LE(test, shareable, (u64)U32_MAX);
> +
> +	ggtt = ggtt_test_create(test, accessible, usable, shareable);
> +	KUNIT_ASSERT_NOT_NULL(test, ggtt);
> +
> +	shareable_node = ggtt_test_insert_node_shareable(test, ggtt, shareable);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, shareable_node);
> +	usable_node = ggtt_test_insert_node(test, ggtt, usable);
> +	KUNIT_ASSERT_TRUE(test, IS_ERR(usable_node));
> +	KUNIT_EXPECT_EQ(test, PTR_ERR(usable_node), -ENOSPC);
> +}
> +
> +static void alloc_shareable_pool_unavailable(struct kunit *test)
> +{
> +	u64 accessible = ggtt_test_accessible_size(test);
> +	u64 usable = (accessible * 3) / 4;
> +	struct xe_ggtt_node *node;
> +	struct xe_ggtt *ggtt;
> +
> +	ggtt = ggtt_test_create(test, usable, usable, 0);
> +	KUNIT_ASSERT_NOT_NULL(test, ggtt);
> +
> +	node = ggtt_test_insert_node_shareable(test, ggtt, XE_PAGE_SIZE);
> +	KUNIT_ASSERT_TRUE(test, IS_ERR(node));
> +	KUNIT_EXPECT_EQ(test, PTR_ERR(node), -ENOSPC);
> +}
> +
> +static void alloc_shareable_pool_oversized(struct kunit *test)
> +{
> +	u64 accessible = ggtt_test_accessible_size(test);
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +	struct xe_ggtt_node *node;
> +	struct xe_ggtt *ggtt;
> +
> +	KUNIT_ASSERT_LE(test, shareable + XE_PAGE_SIZE, (u64)U32_MAX);
> +
> +	ggtt = ggtt_test_create(test, accessible, usable, shareable);
> +	KUNIT_ASSERT_NOT_NULL(test, ggtt);
> +
> +	node = ggtt_test_insert_node_shareable(test, ggtt, shareable + XE_PAGE_SIZE);
> +	KUNIT_ASSERT_TRUE(test, IS_ERR(node));
> +	KUNIT_EXPECT_EQ(test, PTR_ERR(node), -ENOSPC);
> +}
> +
> +static struct kunit_case ggtt_iov_test_cases[] = {
> +	KUNIT_CASE(init_shared_pf),
> +	KUNIT_CASE(init_partial_overlap),
> +	KUNIT_CASE(alloc_usable_pool_low),
> +	KUNIT_CASE(alloc_shareable_pool_high),
> +	KUNIT_CASE(alloc_partial_overlap),
> +	KUNIT_CASE(alloc_partial_overlap_usable_full),
> +	KUNIT_CASE(alloc_partial_overlap_shareable_full),
> +	KUNIT_CASE(alloc_shareable_pool_unavailable),
> +	KUNIT_CASE(alloc_shareable_pool_oversized),
> +	{}
> +};
> +
> +static struct kunit_suite ggtt_iov_suite = {
> +	.name = "xe_ggtt_iov",
> +	.test_cases = ggtt_iov_test_cases,
> +	.init = xe_kunit_helper_xe_device_test_init,
> +};
> +#endif
> +
> +kunit_test_suites(&ggtt_suite);
> +#if IS_ENABLED(CONFIG_PCI_IOV)
> +kunit_test_suites(&ggtt_iov_suite);
> +#endif
> diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c
> index b7e3d626e8cb8..3dd029bc76dfc 100644
> --- a/drivers/gpu/drm/xe/xe_ggtt.c
> +++ b/drivers/gpu/drm/xe/xe_ggtt.c
> @@ -1395,3 +1395,7 @@ u64 xe_ggtt_node_size(const struct xe_ggtt_node *node)
>   {
>   	return node->base.size;
>   }
> +
> +#if IS_BUILTIN(CONFIG_DRM_XE_KUNIT_TEST)
> +#include "tests/xe_ggtt_kunit.c"
> +#endif

  parent reply	other threads:[~2026-11-10 15:32 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-21  8:57 [PATCH v7 0/5] Separate GGTT pools for submissions and VFs provisioning Piórkowski, Piotr
2026-10-21  8:57 ` [PATCH v7 1/5] drm/xe/ggtt: Assert lower bound of GGTT PTE address Piórkowski, Piotr
2026-10-28 15:50   ` Lis, Tomasz
2026-10-21  8:57 ` [PATCH v7 2/5] drm/xe/ggtt: Introduce full GGTT range size Piórkowski, Piotr
2026-10-28 15:56   ` Lis, Tomasz
2026-10-21  8:57 ` [PATCH v7 3/5] drm/xe/ggtt: Split GGTT into usable and shareable pools Piórkowski, Piotr
2026-10-28 23:59   ` Lis, Tomasz
2026-10-21  8:57 ` [PATCH v7 4/5] drm/xe/ggtt: Initialize GGTT pools by SR-IOV mode Piórkowski, Piotr
2026-10-28 15:23   ` Lis, Tomasz
2026-10-21  8:57 ` [PATCH v7 5/5] drm/xe/ggtt: Add KUnit tests for usable and shareable pools Piórkowski, Piotr
2026-10-27 16:31   ` Jani Nikula
2026-10-29 12:12     ` Piotr Piórkowski
2026-11-09  8:54       ` Piotr Piórkowski
2026-11-10 15:31   ` Laguna, Lukasz [this message]
2026-11-12 11:00     ` [v7,5/5] " Piotr Piórkowski
2026-10-21  9:04 ` ✗ CI.checkpatch: warning for Separate GGTT pools for submissions and VFs provisioning (rev7) Patchwork
2026-10-21  9:06 ` ✓ CI.KUnit: success " Patchwork
2026-10-21  9:44 ` ✓ Xe.CI.BAT: " Patchwork
2026-10-21 12:03 ` ✗ Xe.CI.FULL: failure " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cfb7a910-823d-416d-beab-7a6e3077788f@intel.com \
    --to=lukasz.laguna@intel.com \
    --cc=dev@lankhorst.se \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=piotr.piorkowski@intel.com \
    --cc=ville.syrjala@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.