Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Michal Wajdeczko <michal.wajdeczko@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: [PATCH v4 3/3] drm/xe/ggtt: Add KUnit tests for usable and shareable pools
Date: Wed, 2 Sep 2026 20:21:54 +0200	[thread overview]
Message-ID: <5d4de95b-24ea-4aed-817a-c12e9974d183@intel.com> (raw)
In-Reply-To: <20260901164435.1395260-4-piotr.piorkowski@intel.com>



On 9/1/2026 6:44 PM, 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.

nit: keep change log under ---

> 
> Assisted-by: Claude:claude-5-sonnet
> Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Maarten Lankhorst <dev@lankhorst.se>
> ---
>  drivers/gpu/drm/xe/tests/xe_ggtt_test.c | 336 ++++++++++++++++++++++++
>  drivers/gpu/drm/xe/xe_ggtt.c            |   4 +
>  2 files changed, 340 insertions(+)
>  create mode 100644 drivers/gpu/drm/xe/tests/xe_ggtt_test.c
> 
> diff --git a/drivers/gpu/drm/xe/tests/xe_ggtt_test.c b/drivers/gpu/drm/xe/tests/xe_ggtt_test.c
> new file mode 100644
> index 000000000000..7d28b97f8afe
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/tests/xe_ggtt_test.c

for pure kunit tests we should use _kunit.c suffix instead

[1] https://elixir.bootlin.com/linux/v7.2.2/source/Documentation/dev-tools/kunit/style.rst#L188

> @@ -0,0 +1,336 @@
> +// 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 int ggtt_test_init(struct kunit *test)
> +{
> +	xe_kunit_helper_xe_device_test_init(test);
> +	return 0;
> +}

nit: if you are not planning to add custom initialization steps,
just plugin the xe_kunit_helper_xe_device_test_init() directly

> +
> +static void init_native(struct kunit *test)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +	struct xe_ggtt ggtt = { .tile = tile };
> +	u64 accessible = GUC_GGTT_TOP - xe_wopcm_size(tile_to_xe(tile));
> +	u64 usable = min_t(u64, SZ_1G, accessible);
> +
> +	ggtt.hw_size = usable;
> +	ggtt_init_ranges(&ggtt, GGTT_TEST_START, usable, 0);
> +
> +	KUNIT_EXPECT_EQ(test, ggtt.start, GGTT_TEST_START);
> +	KUNIT_EXPECT_EQ(test, ggtt.size, usable);
> +	KUNIT_EXPECT_EQ(test, ggtt.hw_size, usable);
> +
> +	drm_mm_takedown(&ggtt.mm);

but maybe this should be done in a cleanup action registered
in the custom ggtt_test_init() ?

> +}
> +
> +static void alloc_usable_pool_high(struct kunit *test)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +	struct xe_ggtt ggtt = { .tile = tile };
> +	struct xe_ggtt_node *usable_node;
> +	u64 accessible = GUC_GGTT_TOP - xe_wopcm_size(tile_to_xe(tile));
> +	u64 usable = (accessible * 3) / 4;
> +
> +	mutex_init(&ggtt.lock);

this too

> +	ggtt.hw_size = usable;
> +	ggtt_init_ranges(&ggtt, GGTT_TEST_START, usable, 0);
> +
> +	usable_node = xe_ggtt_insert_node(&ggtt, XE_PAGE_SIZE, XE_PAGE_SIZE);

did you run kunit with --raw_output flag?

did you see

	xe_tile_WARN_ON_ONCE(mmio->tile, !mmio->tile->xe->mmio.regs);

as likely GGTT would try some TLB invalidation ...

> +	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);
> +
> +	ggtt_node_remove(usable_node);
> +	drm_mm_takedown(&ggtt.mm);
> +}
> +
> +static void alloc_usable_pool_oversized(struct kunit *test)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +	struct xe_ggtt ggtt = { .tile = tile };
> +	struct xe_ggtt_node *node;
> +	u64 accessible = GUC_GGTT_TOP - xe_wopcm_size(tile_to_xe(tile));
> +	u64 usable = (accessible * 3) / 4;
> +
> +	KUNIT_ASSERT_LE(test, usable + XE_PAGE_SIZE, (u64)U32_MAX);
> +
> +	mutex_init(&ggtt.lock);
> +	ggtt.hw_size = usable;
> +	ggtt_init_ranges(&ggtt, GGTT_TEST_START, usable, 0);
> +
> +	node = xe_ggtt_insert_node(&ggtt, usable + XE_PAGE_SIZE, XE_PAGE_SIZE);
> +	KUNIT_ASSERT_TRUE(test, IS_ERR(node));
> +	KUNIT_EXPECT_EQ(test, PTR_ERR(node), -ENOSPC);
> +
> +	drm_mm_takedown(&ggtt.mm);
> +}
> +
> +#if IS_ENABLED(CONFIG_PCI_IOV)
> +static void init_shared_pf(struct kunit *test)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +	struct xe_ggtt ggtt = { .tile = tile };
> +	u64 accessible = GUC_GGTT_TOP - xe_wopcm_size(tile_to_xe(tile));
> +
> +	ggtt.hw_size = accessible;
> +	ggtt_init_ranges(&ggtt, GGTT_TEST_START, accessible, accessible);
> +
> +	KUNIT_EXPECT_EQ(test, ggtt.size, accessible);
> +	KUNIT_EXPECT_EQ(test, ggtt.shareable.start, 0);
> +	KUNIT_EXPECT_EQ(test, ggtt.shareable.size, accessible);
> +	KUNIT_EXPECT_EQ(test, ggtt.hw_size, accessible);
> +
> +	drm_mm_takedown(&ggtt.mm);
> +}
> +
> +static void init_partial_overlap(struct kunit *test)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +	struct xe_ggtt ggtt = { .tile = tile };
> +	u64 accessible = GUC_GGTT_TOP - xe_wopcm_size(tile_to_xe(tile));
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +
> +	KUNIT_ASSERT_GT(test, accessible, 0ULL);
> +	KUNIT_ASSERT_GT(test, usable, shareable);
> +
> +	ggtt.hw_size = accessible;
> +	ggtt_init_ranges(&ggtt, GGTT_TEST_START, usable, shareable);
> +
> +	KUNIT_EXPECT_EQ(test, ggtt.size, usable);
> +	KUNIT_EXPECT_EQ(test, ggtt.shareable.start, accessible - shareable);
> +	KUNIT_EXPECT_EQ(test, ggtt.shareable.size, shareable);
> +	KUNIT_EXPECT_LT(test, ggtt.shareable.start, usable);
> +	KUNIT_EXPECT_EQ(test, ggtt.hw_size, accessible);
> +
> +	drm_mm_takedown(&ggtt.mm);
> +}
> +
> +static void alloc_usable_pool_low(struct kunit *test)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +	struct xe_ggtt ggtt = { .tile = tile };
> +	struct xe_ggtt_node *usable_node;
> +	u64 accessible = GUC_GGTT_TOP - xe_wopcm_size(tile_to_xe(tile));
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +
> +	mutex_init(&ggtt.lock);
> +	ggtt.hw_size = accessible;
> +	ggtt_init_ranges(&ggtt, GGTT_TEST_START, usable, shareable);
> +
> +	usable_node = xe_ggtt_insert_node(&ggtt, XE_PAGE_SIZE, 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);
> +
> +	ggtt_node_remove(usable_node);
> +	drm_mm_takedown(&ggtt.mm);
> +}
> +
> +static void alloc_shareable_pool_high(struct kunit *test)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +	struct xe_ggtt ggtt = { .tile = tile };
> +	struct xe_ggtt_node *shareable_node;
> +	u64 accessible = GUC_GGTT_TOP - xe_wopcm_size(tile_to_xe(tile));
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +
> +	mutex_init(&ggtt.lock);
> +	ggtt.hw_size = accessible;
> +	ggtt_init_ranges(&ggtt, GGTT_TEST_START, usable, shareable);
> +
> +	shareable_node = xe_ggtt_insert_node_shareable(&ggtt,
> +						       XE_PAGE_SIZE,
> +						       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);
> +
> +	ggtt_node_remove(shareable_node);
> +	drm_mm_takedown(&ggtt.mm);
> +}
> +
> +static void alloc_partial_overlap(struct kunit *test)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +	struct xe_ggtt ggtt = { .tile = tile };
> +	struct xe_ggtt_node *usable_node, *shareable_node;
> +	u64 accessible = GUC_GGTT_TOP - xe_wopcm_size(tile_to_xe(tile));
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +
> +	mutex_init(&ggtt.lock);
> +	ggtt.hw_size = accessible;
> +	ggtt_init_ranges(&ggtt, GGTT_TEST_START, usable, shareable);
> +
> +	usable_node = xe_ggtt_insert_node(&ggtt, XE_PAGE_SIZE, XE_PAGE_SIZE);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, usable_node);
> +	shareable_node = xe_ggtt_insert_node_shareable(&ggtt,
> +						       XE_PAGE_SIZE,
> +						       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);
> +
> +	ggtt_node_remove(shareable_node);
> +	ggtt_node_remove(usable_node);
> +	drm_mm_takedown(&ggtt.mm);
> +}
> +
> +static void alloc_partial_overlap_usable_full(struct kunit *test)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +	struct xe_ggtt ggtt = { .tile = tile };
> +	struct xe_ggtt_node *usable_node, *shareable_node;
> +	u64 accessible = GUC_GGTT_TOP - xe_wopcm_size(tile_to_xe(tile));
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +
> +	KUNIT_ASSERT_LE(test, usable, (u64)U32_MAX);
> +	KUNIT_ASSERT_LE(test, shareable, (u64)U32_MAX);
> +
> +	mutex_init(&ggtt.lock);
> +	ggtt.hw_size = accessible;
> +	ggtt_init_ranges(&ggtt, GGTT_TEST_START, usable, shareable);
> +
> +	usable_node = xe_ggtt_insert_node(&ggtt, usable, XE_PAGE_SIZE);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, usable_node);
> +	shareable_node = xe_ggtt_insert_node_shareable(&ggtt,
> +						       shareable,
> +						       XE_PAGE_SIZE);
> +	KUNIT_ASSERT_TRUE(test, IS_ERR(shareable_node));
> +	KUNIT_EXPECT_EQ(test, PTR_ERR(shareable_node), -ENOSPC);
> +
> +	ggtt_node_remove(usable_node);
> +	drm_mm_takedown(&ggtt.mm);
> +}
> +
> +static void alloc_partial_overlap_shareable_full(struct kunit *test)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +	struct xe_ggtt ggtt = { .tile = tile };
> +	struct xe_ggtt_node *usable_node, *shareable_node;
> +	u64 accessible = GUC_GGTT_TOP - xe_wopcm_size(tile_to_xe(tile));
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +
> +	KUNIT_ASSERT_LE(test, usable, (u64)U32_MAX);
> +	KUNIT_ASSERT_LE(test, shareable, (u64)U32_MAX);
> +
> +	mutex_init(&ggtt.lock);
> +	ggtt.hw_size = accessible;
> +	ggtt_init_ranges(&ggtt, GGTT_TEST_START, usable, shareable);
> +
> +	shareable_node = xe_ggtt_insert_node_shareable(&ggtt,
> +						       shareable,
> +						       XE_PAGE_SIZE);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, shareable_node);
> +	usable_node = xe_ggtt_insert_node(&ggtt, usable, XE_PAGE_SIZE);
> +	KUNIT_ASSERT_TRUE(test, IS_ERR(usable_node));
> +	KUNIT_EXPECT_EQ(test, PTR_ERR(usable_node), -ENOSPC);
> +
> +	ggtt_node_remove(shareable_node);
> +	drm_mm_takedown(&ggtt.mm);
> +}
> +
> +static void alloc_shareable_pool_unavailable(struct kunit *test)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +	struct xe_ggtt ggtt = { .tile = tile };
> +	struct xe_ggtt_node *node;
> +	u64 accessible = GUC_GGTT_TOP - xe_wopcm_size(tile_to_xe(tile));
> +	u64 usable = (accessible * 3) / 4;
> +
> +	mutex_init(&ggtt.lock);
> +	ggtt.hw_size = usable;
> +	ggtt_init_ranges(&ggtt, GGTT_TEST_START, usable, 0);
> +
> +	node = xe_ggtt_insert_node_shareable(&ggtt, XE_PAGE_SIZE, XE_PAGE_SIZE);
> +	KUNIT_ASSERT_TRUE(test, IS_ERR(node));
> +	KUNIT_EXPECT_EQ(test, PTR_ERR(node), -ENOSPC);
> +
> +	drm_mm_takedown(&ggtt.mm);
> +}
> +
> +static void alloc_shareable_pool_oversized(struct kunit *test)
> +{
> +	struct xe_tile *tile = xe_device_get_root_tile(test->priv);
> +	struct xe_ggtt ggtt = { .tile = tile };
> +	struct xe_ggtt_node *node;
> +	u64 accessible = GUC_GGTT_TOP - xe_wopcm_size(tile_to_xe(tile));
> +	u64 usable = (accessible * 3) / 4;
> +	u64 shareable = accessible / 2;
> +
> +	KUNIT_ASSERT_LE(test, shareable + XE_PAGE_SIZE, (u64)U32_MAX);
> +
> +	mutex_init(&ggtt.lock);
> +	ggtt.hw_size = accessible;
> +	ggtt_init_ranges(&ggtt, GGTT_TEST_START, usable, shareable);
> +
> +	node = xe_ggtt_insert_node_shareable(&ggtt,
> +					     shareable + XE_PAGE_SIZE,
> +					     XE_PAGE_SIZE);
> +	KUNIT_ASSERT_TRUE(test, IS_ERR(node));
> +	KUNIT_EXPECT_EQ(test, PTR_ERR(node), -ENOSPC);
> +
> +	drm_mm_takedown(&ggtt.mm);
> +}
> +#else
> +#define GGTT_PCI_IOV_TEST_SKIP(_name) \
> +	static void _name(struct kunit *test) \
> +	{ \
> +		kunit_skip(test, "requires CONFIG_PCI_IOV"); \
> +	}
> +
> +GGTT_PCI_IOV_TEST_SKIP(init_shared_pf)
> +GGTT_PCI_IOV_TEST_SKIP(init_partial_overlap)
> +GGTT_PCI_IOV_TEST_SKIP(alloc_usable_pool_low)
> +GGTT_PCI_IOV_TEST_SKIP(alloc_shareable_pool_high)
> +GGTT_PCI_IOV_TEST_SKIP(alloc_partial_overlap)
> +GGTT_PCI_IOV_TEST_SKIP(alloc_partial_overlap_usable_full)
> +GGTT_PCI_IOV_TEST_SKIP(alloc_partial_overlap_shareable_full)
> +GGTT_PCI_IOV_TEST_SKIP(alloc_shareable_pool_unavailable)
> +GGTT_PCI_IOV_TEST_SKIP(alloc_shareable_pool_oversized)
> +
> +#undef GGTT_PCI_IOV_TEST_SKIP
> +#endif /* CONFIG_PCI_IOV */

instead of defining test stubs, just add separate suite

 +static struct kunit_suite ggtt_iov_suite = {
 +	.name = "xe_ggtt_iov",
 +	.test_cases = ggtt_iov_test_cases,
 +	.init = ggtt_test_init,

under the same if ENABLED(CONFIG_PCI_IOV)

> +
> +static struct kunit_case ggtt_test_cases[] = {
> +	KUNIT_CASE(init_native),
> +	KUNIT_CASE(alloc_usable_pool_high),
> +	KUNIT_CASE(alloc_usable_pool_oversized),
> +	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_suite = {
> +	.name = "xe_ggtt",
> +	.test_cases = ggtt_test_cases,
> +	.init = ggtt_test_init,
> +};
> +
> +kunit_test_suites(&ggtt_suite);
> diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c
> index 7fcd686f9729..19f9c564030b 100644
> --- a/drivers/gpu/drm/xe/xe_ggtt.c
> +++ b/drivers/gpu/drm/xe/xe_ggtt.c
> @@ -1397,3 +1397,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_test.c"
> +#endif


  reply	other threads:[~2026-09-02 18:22 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-01 16:44 [PATCH v4 0/3] Separate GGTT pools for submissions and VFs provisioning Piórkowski, Piotr
2026-09-01 16:44 ` [PATCH v4 1/3] drm/xe/ggtt: Split GGTT into usable and shareable pools Piórkowski, Piotr
2026-09-02 17:59   ` Michal Wajdeczko
2026-09-03 16:14     ` Piotr Piórkowski
2026-09-01 16:44 ` [PATCH v4 2/3] drm/xe/ggtt: Initialize GGTT pools by SR-IOV mode Piórkowski, Piotr
2026-09-01 16:53   ` sashiko-bot
2026-09-02 18:07   ` Michal Wajdeczko
2026-09-01 16:44 ` [PATCH v4 3/3] drm/xe/ggtt: Add KUnit tests for usable and shareable pools Piórkowski, Piotr
2026-09-02 18:21   ` Michal Wajdeczko [this message]
2026-09-01 16:51 ` ✗ CI.checkpatch: warning for Separate GGTT pools for submissions and VFs provisioning (rev4) Patchwork
2026-09-01 16:53 ` ✓ CI.KUnit: success " Patchwork
2026-09-01 17:35 ` ✓ Xe.CI.BAT: " Patchwork
2026-09-01 19:38 ` ✓ Xe.CI.FULL: " 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=5d4de95b-24ea-4aed-817a-c12e9974d183@intel.com \
    --to=michal.wajdeczko@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox