On 03/09/2026 23:00, Thadeu Lima de Souza Cascardo wrote:
In order to be reuse the same dmem tests with multiple drivers, we need to
abstract a few operations. That includes getting the region name, and
allocating and releasing VRAM. As there is some initialization also when
multiple allocations are done, also provide init and deinit functions.
The Xe implementation was based on the original operations from
xe_cgroups.c written by Thomas Hellström. However, instead of doing a
deferred backing, followed by a bind, it does a simple non-deferred GEM
object creation on the VRAM region.
Signed-off-by: Thadeu Lima de Souza Cascardo <[email protected]>
---
lib/igt_dmem_driver.h | 34 ++++++++++++++++++
lib/meson.build | 1 +
lib/xe/xe_dmem.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 132 insertions(+)
diff --git a/lib/igt_dmem_driver.h b/lib/igt_dmem_driver.h
new file mode 100644
index 000000000000..e6998387eff9
--- /dev/null
+++ b/lib/igt_dmem_driver.h
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2026 Valve Corporation
+ * Authors:
+ * Thadeu Lima de Souza Cascardo <[email protected]>
+ */
+
+#ifndef __IGT_DMEM_DRIVER_H__
+#define __IGT_DMEM_DRIVER_H__
+
+#include <stdlib.h>
+
+/**
+ * struct igt_dmem_driver - vendor driver to allocate and free device memory
+ *
+ */
+struct igt_dmem_driver {
+ /** @name: Driver name */
+ const char *name;
+ /** @init: Initialize an opaque context given a DRM device fd */
+ int (*init)(void **ctx, int fd);
+ /** @deinit: Release resources associated with context */
+ void (*deinit)(void *ctx);
+ /** @get_region_name: Return expected region name at dmem cgroup files
*/
+ char * (*get_region_name)(void *ctx);
Nit - mention it returns newly allocated memory caller must free?
But LGTM on the whole:
Reviewed-by: Tvrtko Ursulin <[email protected]>
Regards,
Tvrtko
+ /** @allocate_vram: Allocate @len sized vram and return an opaque
@handle */
+ int (*allocate_vram)(void *ctx, size_t len, void **handle);
+ /** @free_vram: Free vram associated with @handle */
+ void (*free_vram)(void *ctx, void *handle);
+};
+
+extern const struct igt_dmem_driver xe_dmem_driver;
+
+#endif
diff --git a/lib/meson.build b/lib/meson.build
index b7e1be61d844..022408ce6864 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -130,6 +130,7 @@ lib_sources = [
'igt_dsc.c',
'igt_hook.c',
'xe/xe_device.c',
+ 'xe/xe_dmem.c',
'xe/xe_ggtt.c',
'xe/xe_gt.c',
'xe/xe_ioctl.c',
diff --git a/lib/xe/xe_dmem.c b/lib/xe/xe_dmem.c
new file mode 100644
index 000000000000..628c905997d4
--- /dev/null
+++ b/lib/xe/xe_dmem.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2026 Valve Corporation
+ * Authors:
+ * Thadeu Lima de Souza Cascardo <[email protected]>
+ */
+
+#include <errno.h>
+
+#include "igt.h"
+#include "igt_cgroup.h"
+#include "igt_dmem_driver.h"
+#include "xe_drm.h"
+#include "xe/xe_ioctl.h"
+#include "xe/xe_query.h"
+
+struct xe_dmem_ctx {
+ int fd;
+ uint64_t vram_region;
+};
+
+static int xe_dmem_init(void **ctx, int fd)
+{
+ struct xe_dmem_ctx *xe_ctx;
+ uint64_t region;
+
+ xe_ctx = malloc(sizeof(*xe_ctx));
+ if (!xe_ctx)
+ return -ENOMEM;
+
+ xe_ctx->vram_region = 0;
+ /* Find first VRAM region */
+ xe_for_each_mem_region(fd, all_memory_regions(fd), region) {
+ if (xe_region_class(fd, region) ==
DRM_XE_MEM_REGION_CLASS_VRAM) {
+ xe_ctx->vram_region = region;
+ break;
+ }
+ }
+ if (!xe_ctx->vram_region)
+ goto out;
+
+ xe_ctx->fd = fd;
+
+ *ctx = xe_ctx;
+
+ return 0;
+
+out:
+ free(xe_ctx);
+
+ return -ENOMEM;
+}
+
+static void xe_dmem_deinit(void *ctx)
+{
+ struct xe_dmem_ctx *xe_ctx = ctx;
+
+ free(xe_ctx);
+}
+
+static char * xe_dmem_get_region_name(void *ctx)
+{
+ struct xe_dmem_ctx *xe_ctx = ctx;
+
+ return xe_cgroup_region_name(xe_ctx->fd, xe_ctx->vram_region);
+}
+
+static int xe_dmem_allocate_vram(void *ctx, size_t len, void **ret_handle)
+{
+ struct xe_dmem_ctx *xe_ctx = ctx;
+ uint32_t handle;
+ int err;
+
+ err = __xe_bo_create(xe_ctx->fd, 0, len, xe_ctx->vram_region, 0,
+ NULL, &handle);
+ if (err)
+ return err;
+
+ *ret_handle = (void *)(uintptr_t) handle;
+ return 0;
+}
+
+static void xe_dmem_free_vram(void *ctx, void *handle)
+{
+ struct xe_dmem_ctx *xe_ctx = ctx;
+
+ gem_close(xe_ctx->fd, (uint32_t)(uintptr_t) handle);
+}
+
+const struct igt_dmem_driver xe_dmem_driver = {
+ .name = "xe",
+ .get_region_name = xe_dmem_get_region_name,
+ .init = xe_dmem_init,
+ .deinit = xe_dmem_deinit,
+ .allocate_vram = xe_dmem_allocate_vram,
+ .free_vram = xe_dmem_free_vram,
+};