[PATCH v3 26/33] drm/xe: Add tracepoint for xe_gem_create_ioctl

From: Matthew Brost

Date: Fri Jul 10 2026 - 23:03:15 EST


Add a xe_gem_create_ioctl tracepoint to help profile GEM creation, in
particular the cost of populating a BO while holding the dma-resv lock
versus the total IOCTL cost. This is useful for evaluating the
out-of-lock preallocation path, which aims to shrink the time spent
under the lock.

The tracepoint records the BO size, the requested placement mask, the
CPU caching mode, the VM asid (0 when no VM is bound), the total time
spent in the IOCTL, and the time spent under the dma-resv lock (the
xe_validation_guard region where the lock is held).

The asid is captured at VM lookup time rather than at trace emission,
since the VM reference is dropped before the tracepoint fires.

Cc: Carlos Santa <carlos.santa@xxxxxxxxx>
Cc: Ryan Neph <ryanneph@xxxxxxxxxx>
Cc: Christian Koenig <christian.koenig@xxxxxxx>
Cc: Huang Rui <ray.huang@xxxxxxx>
Cc: Matthew Auld <matthew.auld@xxxxxxxxx>
Cc: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx>
Cc: Maxime Ripard <mripard@xxxxxxxxxx>
Cc: Thomas Zimmermann <tzimmermann@xxxxxxx>
Cc: David Airlie <airlied@xxxxxxxxx>
Cc: Simona Vetter <simona@xxxxxxxx>
Cc: dri-devel@xxxxxxxxxxxxxxxxxxxxx
Cc: linux-kernel@xxxxxxxxxxxxxxx
Cc: Thomas Hellström <thomas.hellstrom@xxxxxxxxxxxxxxx>
Assisted-by: GitHub_Copilot:claude-opus-4.8
Signed-off-by: Matthew Brost <matthew.brost@xxxxxxxxx>

---

v3:
- Guard lock_ns against an unset lock_start and use div_u64() in the
tracepoint (Sashiko)
---
drivers/gpu/drm/xe/xe_bo.c | 17 +++++++++++++++++
drivers/gpu/drm/xe/xe_trace_bo.h | 31 +++++++++++++++++++++++++++++++
2 files changed, 48 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index a646a72122d4..caf5aa0bab53 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -3953,6 +3953,10 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data,
bool have_prealloc = false;
unsigned int bo_flags;
u32 handle;
+ ktime_t ioctl_start = ktime_get();
+ ktime_t lock_start = ktime_set(0, 0);
+ u64 lock_ns = 0;
+ u32 asid = 0;
int err;

if (XE_IOCTL_DBG(xe, args->pad[0] || args->pad[1] || args->pad[2]) ||
@@ -4031,6 +4035,7 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data,
vm = xe_vm_lookup(xef, args->vm_id);
if (XE_IOCTL_DBG(xe, !vm))
return -ENOENT;
+ asid = vm->usm.asid;
}

/*
@@ -4100,6 +4105,10 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data,
if (err)
break;
}
+
+ if (lock_start == ktime_set(0, 0))
+ lock_start = ktime_get();
+
bo = xe_bo_create_user(xe, vm, args->size, args->cpu_caching,
bo_flags, have_prealloc ? &prealloc : NULL,
&exec);
@@ -4110,6 +4119,8 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data,
break;
}
}
+ if (lock_start != ktime_set(0, 0))
+ lock_ns = ktime_to_ns(ktime_sub(ktime_get(), lock_start));
if (have_prealloc)
ttm_pool_prealloc_fini(&xe->ttm.pool, &prealloc);
if (err)
@@ -4140,6 +4151,12 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data,
if (vm)
xe_vm_put(vm);

+ trace_xe_gem_create_ioctl(xe, args->size, args->placement,
+ args->cpu_caching, asid,
+ div_u64(ktime_to_ns(ktime_sub(ktime_get(),
+ ioctl_start)), 1000),
+ div_u64(lock_ns, 1000));
+
return err;
}

diff --git a/drivers/gpu/drm/xe/xe_trace_bo.h b/drivers/gpu/drm/xe/xe_trace_bo.h
index b159d37d39a1..63db37edadc2 100644
--- a/drivers/gpu/drm/xe/xe_trace_bo.h
+++ b/drivers/gpu/drm/xe/xe_trace_bo.h
@@ -144,6 +144,37 @@ TRACE_EVENT(xe_bo_defrag_one,
__entry->ret)
);

+TRACE_EVENT(xe_gem_create_ioctl,
+ TP_PROTO(struct xe_device *xe, u64 size, u32 placement,
+ u16 caching, u32 asid, u64 ioctl_us, u64 lock_us),
+ TP_ARGS(xe, size, placement, caching, asid, ioctl_us, lock_us),
+
+ TP_STRUCT__entry(
+ __string(dev, dev_name(xe->drm.dev))
+ __field(u64, size)
+ __field(u32, placement)
+ __field(u16, caching)
+ __field(u32, asid)
+ __field(u64, ioctl_us)
+ __field(u64, lock_us)
+ ),
+
+ TP_fast_assign(
+ __assign_str(dev);
+ __entry->size = size;
+ __entry->placement = placement;
+ __entry->caching = caching;
+ __entry->asid = asid;
+ __entry->ioctl_us = ioctl_us;
+ __entry->lock_us = lock_us;
+ ),
+
+ TP_printk("dev=%s, size=%llu, placement=0x%x, caching=%u, asid=%u, ioctl_us=%llu, lock_us=%llu",
+ __get_str(dev), __entry->size, __entry->placement,
+ __entry->caching, __entry->asid, __entry->ioctl_us,
+ __entry->lock_us)
+);
+
DECLARE_EVENT_CLASS(xe_vma,
TP_PROTO(struct xe_vma *vma),
TP_ARGS(vma),
--
2.34.1