From: Maarten Lankhorst <dev@lankhorst.se>
To: intel-xe@lists.freedesktop.org
Cc: Maarten Lankhorst <dev@lankhorst.se>
Subject: [PATCH 4/4] drm/xe: Add migrate performance kunit test
Date: Fri, 2 May 2025 11:35:13 +0200 [thread overview]
Message-ID: <20250502093514.510621-5-dev@lankhorst.se> (raw)
In-Reply-To: <20250502093514.510621-1-dev@lankhorst.se>
Ever since we added migration, we didn't have concrete numbers on how
performant our implementation is. We are currently writing pagetables,
flushing, then writing data and flushing again. Lets see what happens
when we fix this.
Signed-off-by: Maarten Lankhorst <dev@lankhorst.se>
---
drivers/gpu/drm/xe/tests/xe_migrate.c | 235 ++++++++++++++++++++++++++
1 file changed, 235 insertions(+)
diff --git a/drivers/gpu/drm/xe/tests/xe_migrate.c b/drivers/gpu/drm/xe/tests/xe_migrate.c
index 12a3318b1a5d5..d8992ba71281b 100644
--- a/drivers/gpu/drm/xe/tests/xe_migrate.c
+++ b/drivers/gpu/drm/xe/tests/xe_migrate.c
@@ -661,6 +661,128 @@ static struct xe_bo *migratable_bo_create_pin_map(struct kunit *test, struct xe_
return bo;
}
+static bool handle_vm_fence(struct xe_device *xe, struct dma_fence *fence,
+ struct kunit *test)
+{
+ bool ret;
+
+ if (!fence)
+ return false;
+
+ ret = sanity_fence_failed(xe, fence, "VM_BIND", test);
+ if (!IS_ERR(fence))
+ dma_fence_put(fence);
+ return ret;
+}
+
+#define BS_BO2BO MAX_PREEMPTDISABLE_TRANSFER
+
+static void write_bo2bo_copy(struct xe_tile *tile, struct xe_bo *batch,
+ u64 src_ofs, u64 dst_ofs, u64 size)
+{
+ struct xe_bb bb = {
+ .cs = batch->vmap.vaddr,
+ .len = 0,
+ };
+
+ while (size) {
+ u64 block = min(size, BS_BO2BO);
+
+ emit_copy(tile->primary_gt, &bb, src_ofs, dst_ofs, block, SZ_32K);
+
+ src_ofs += block;
+ dst_ofs += block;
+ size -= block;
+ }
+ bb.cs[bb.len++] = MI_BATCH_BUFFER_END;
+ xe_gt_assert(tile->primary_gt, bb.len * 4 < batch->size);
+}
+
+static void compare_bo2bo(struct kunit *test,
+ struct xe_tile *tile,
+ struct xe_vm *vm,
+ struct xe_exec_queue *q,
+ struct xe_bo *batch_bo, u64 batch_ofs,
+ struct xe_bo *src, u64 src_ofs,
+ struct xe_bo *dst, u64 dst_ofs,
+ const char *description)
+{
+ struct xe_device *xe = tile->xe;
+ s64 t_migrate = 0, t_job = 0;
+ int iter = 4;
+
+ for (int n = 0; n < iter; n++) {
+ struct xe_sched_job *job;
+ struct dma_fence *fence;
+ u64 delta;
+ ktime_t start;
+
+ start = ktime_get();
+ job = xe_sched_job_create(q, &batch_ofs);
+
+ write_bo2bo_copy(tile, batch_bo, src_ofs, dst_ofs, src->size);
+
+ xe_sched_job_arm(job);
+ fence = dma_fence_get(&job->drm.s_fence->finished);
+ xe_sched_job_push(job);
+
+ sanity_fence_failed(xe, fence, description, test);
+ if (IS_ERR(fence))
+ return;
+
+ dma_fence_put(fence);
+
+ delta = ktime_to_us(ktime_sub(ktime_get(), start));
+ drm_dbg(&xe->drm, "[%i] Job (%s) copy of %lu buffer took %llu µs\n", n, description, src->size >> 20, delta);
+ t_job += delta;
+
+ start = ktime_get();
+ fence = xe_migrate_copy(tile->migrate, src, dst, src->ttm.resource, dst->ttm.resource, false);
+ sanity_fence_failed(xe, fence, description, test);
+ if (IS_ERR(fence))
+ return;
+
+ dma_fence_put(fence);
+ delta = ktime_to_us(ktime_sub(ktime_get(), start));
+ drm_dbg(&xe->drm, "[%i] Job (%s) migration of %lu buffer took %llu µs\n", n, description, src->size >> 20, delta);
+ t_migrate += delta;
+
+ cond_resched();
+ }
+
+ drm_info(&xe->drm, "%s %lu MB buffer took on average %llu us for copy, %llu us for migrate\n", description, src->size >> 20, div_u64(t_job, iter), div_u64(t_migrate, iter));
+}
+
+static void performance_tile(struct xe_device *xe,
+ struct xe_tile *tile,
+ struct kunit *test,
+ struct xe_vm *vm,
+ struct xe_exec_queue *q,
+ struct xe_bo *batch_bo, u64 batch_ofs,
+ struct xe_bo *sys_bo, u64 sys_ofs,
+ struct xe_bo *vram_bo, u64 vram_ofs,
+ struct xe_bo *alt_bo, u64 alt_ofs)
+{
+ drm_dbg(&xe->drm, "Using %u block size for copy, %u for migrate\n",
+ BS_BO2BO, MAX_PREEMPTDISABLE_TRANSFER);
+
+ compare_bo2bo(test, tile, vm, q, batch_bo, batch_ofs,
+ sys_bo, sys_ofs, vram_bo, vram_ofs,
+ "sysmem -> vram");
+
+ compare_bo2bo(test, tile, vm, q, batch_bo, batch_ofs,
+ vram_bo, vram_ofs, sys_bo, sys_ofs,
+ "vram -> sysmem");
+
+ compare_bo2bo(test, tile, vm, q, batch_bo, batch_ofs,
+ vram_bo, vram_ofs, alt_bo, alt_ofs,
+ "vram -> vram");
+
+ compare_bo2bo(test, tile, vm, q, batch_bo, batch_ofs,
+ sys_bo, sys_ofs, sys_bo, sys_ofs,
+ "sysmem -> sysmem");
+}
+
static void bo_unpin_map_user(struct xe_bo *bo)
{
if (!bo->vm)
@@ -672,6 +794,116 @@ static void bo_unpin_map_user(struct xe_bo *bo)
xe_bo_put(bo);
}
+static void performance_test_run_tile(struct xe_device *xe,
+ struct xe_tile *tile,
+ struct kunit *test)
+{
+ struct xe_bo *sys_bo, *vram_bo = NULL, *alt_bo = NULL, *batch_bo = NULL;
+ unsigned int bo_flags = XE_BO_FLAG_VRAM_IF_DGFX(tile);
+ struct xe_vm *vm;
+ struct xe_exec_queue *q;
+ struct dma_fence *fence;
+ u64 size = ALIGN(tile->mem.vram.usable_size / 3, SZ_2M);
+ u64 block = ALIGN(size, SZ_1G);
+ bool failed = true;
+
+ vm = xe_vm_create(xe, XE_VM_FLAG_SET_TILE_ID(tile));
+ if (IS_ERR(vm))
+ goto out;
+
+ q = xe_migrate_create_queue(tile, vm);
+ if (IS_ERR(q))
+ goto free_vm;
+
+ xe_vm_lock(vm, false);
+
+ sys_bo = migratable_bo_create_pin_map(test, xe, vm, size, DRM_XE_GEM_CPU_CACHING_WC, XE_BO_FLAG_SYSTEM | XE_BO_FLAG_NEEDS_CPU_ACCESS);
+ if (IS_ERR(sys_bo))
+ goto free_q;
+
+ alt_bo = migratable_bo_create_pin_map(test, xe, vm, size,
+ DRM_XE_GEM_CPU_CACHING_WC,
+ bo_flags);
+ if (IS_ERR(alt_bo))
+ goto free_sysbo;
+
+ vram_bo = migratable_bo_create_pin_map(test, xe, vm, size,
+ DRM_XE_GEM_CPU_CACHING_WC,
+ bo_flags);
+ if (IS_ERR(vram_bo))
+ goto free_altbo;
+
+ batch_bo = migratable_bo_create_pin_map(test, xe, vm, SZ_2M, DRM_XE_GEM_CPU_CACHING_WC, XE_BO_FLAG_SYSTEM | XE_BO_FLAG_NEEDS_CPU_ACCESS);
+ if (IS_ERR(batch_bo))
+ goto free_vrambo;
+
+ xe_vm_unlock(vm);
+
+ failed = false;
+
+ fence = xe_vm_bind_kernel_bo(vm, batch_bo, NULL, SZ_2M, XE_CACHE_WT);
+ failed |= handle_vm_fence(xe, fence, test);
+
+ fence = xe_vm_bind_kernel_bo(vm, sys_bo, NULL, block, XE_CACHE_WT);
+ failed |= handle_vm_fence(xe, fence, test);
+
+ fence = xe_vm_bind_kernel_bo(vm, vram_bo, NULL, 2 * block, XE_CACHE_NONE);
+ failed |= handle_vm_fence(xe, fence, test);
+
+ fence = xe_vm_bind_kernel_bo(vm, alt_bo, NULL, 3 * block, XE_CACHE_NONE);
+ failed |= handle_vm_fence(xe, fence, test);
+ if (failed)
+ goto free_batchbo;
+
+ xe_vm_lock(vm, false);
+
+ performance_tile(xe, tile, test, vm, q,
+ batch_bo, SZ_2M, sys_bo, block,
+ vram_bo, 2 * block, alt_bo, 3 * block);
+
+free_batchbo:
+ bo_unpin_map_user(batch_bo);
+free_vrambo:
+ bo_unpin_map_user(vram_bo);
+free_altbo:
+ bo_unpin_map_user(alt_bo);
+free_sysbo:
+ bo_unpin_map_user(sys_bo);
+free_q:
+ xe_vm_unlock(vm);
+ xe_exec_queue_put(q);
+free_vm:
+ xe_vm_close_and_put(vm);
+out:
+ if (failed)
+ KUNIT_FAIL(test, "Test setup failed\n");
+}
+
+static void xe_migrate_performance_kunit(struct kunit *test)
+{
+ struct xe_device *xe = test->priv;
+ struct xe_tile *tile;
+ int id;
+
+ if (!IS_DGFX(xe)) {
+ kunit_skip(test, "test requires VRAM\n");
+ return;
+ }
+
+ xe_pm_runtime_get(xe);
+
+ for_each_tile(tile, xe, id) {
+ if (tile->mem.vram.io_size < tile->mem.vram.usable_size) {
+ kunit_skip(test, "Small bar device.\n");
+ break;
+ }
+
+ performance_test_run_tile(xe, tile, test);
+ }
+
+ xe_pm_runtime_put(xe);
+}
+
static void validate_ccs_test_run_tile(struct xe_device *xe, struct xe_tile *tile,
struct kunit *test)
{
@@ -740,6 +972,9 @@ static void xe_validate_ccs_kunit(struct kunit *test)
static struct kunit_case xe_migrate_tests[] = {
KUNIT_CASE_PARAM(xe_migrate_sanity_kunit, xe_pci_live_device_gen_param),
+ KUNIT_CASE_PARAM_ATTR(xe_migrate_performance_kunit,
+ xe_pci_live_device_gen_param,
+ {.speed = KUNIT_SPEED_SLOW}),
KUNIT_CASE_PARAM(xe_validate_ccs_kunit, xe_pci_live_device_gen_param),
{}
};
--
2.45.2
next prev parent reply other threads:[~2025-05-02 9:35 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-02 9:35 [PATCH 0/4] drm/xe: Update migration tests Maarten Lankhorst
2025-05-02 9:35 ` [PATCH 1/4] drm/xe: Simplify migration kunit tests Maarten Lankhorst
2025-05-02 16:54 ` Matthew Brost
2025-05-02 9:35 ` [PATCH 2/4] drm/xe: Silence migrate debug message Maarten Lankhorst
2025-05-02 16:55 ` Matthew Brost
2025-05-02 9:35 ` [PATCH 3/4] drm/xe: Fix small leak in migration error path Maarten Lankhorst
2025-05-02 16:59 ` Matthew Brost
2025-05-02 9:35 ` Maarten Lankhorst [this message]
2025-05-08 6:49 ` [PATCH 4/4] drm/xe: Add migrate performance kunit test Matthew Brost
2025-05-02 11:02 ` ✓ CI.Patch_applied: success for drm/xe: Update migration tests Patchwork
2025-05-02 11:02 ` ✗ CI.checkpatch: warning " Patchwork
2025-05-02 11:03 ` ✓ CI.KUnit: success " Patchwork
2025-05-02 11:12 ` ✓ CI.Build: " Patchwork
2025-05-02 11:14 ` ✓ CI.Hooks: " Patchwork
2025-05-02 11:15 ` ✓ CI.checksparse: " Patchwork
2025-05-02 15:21 ` ✗ Xe.CI.Full: failure " Patchwork
2025-05-06 7:59 ` ✗ Xe.CI.BAT: " 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=20250502093514.510621-5-dev@lankhorst.se \
--to=dev@lankhorst.se \
--cc=intel-xe@lists.freedesktop.org \
/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.