From 64455314d641639db5b077129849fb00357334bc Mon Sep 17 00:00:00 2001 From: Daniel Charles Date: Wed, 30 Sep 2026 09:46:45 -0700 Subject: [PATCH] drm/xe: Add focused VM teardown and page fault tracing Trace the start of VM teardown and ASID removal so late page faults can be correlated with the VM lifecycle. Emit one failure event for all page fault errors. Include the existing page fault reason alongside the errno. Keep the trace set focused by avoiding separate events for userptr pin attempts, individual close phases, ASID lookup rejection, and faults during shutdown. v2: Fix checkpatch warnings. v3: Pass xe to the page fault tracepoint and print VM mode as dma-fence/preempt-fence/fault (Matt) Assisted-by: GitHub Copilot using Claude Sonnet 5 Signed-off-by: Daniel Charles Reviewed-by: Matthew Brost Signed-off-by: Matthew Brost Link: https://patch.msgid.link/20260930164645.1243801-1-daniel.charles@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_pagefault.c | 15 ++++++-- drivers/gpu/drm/xe/xe_trace_bo.h | 58 +++++++++++++++++++++++++++++-- drivers/gpu/drm/xe/xe_vm.c | 4 +++ 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pagefault.c b/drivers/gpu/drm/xe/xe_pagefault.c index f11c4f8e2907..98cce0f12b12 100644 --- a/drivers/gpu/drm/xe/xe_pagefault.c +++ b/drivers/gpu/drm/xe/xe_pagefault.c @@ -267,6 +267,7 @@ static struct xe_vm *xe_pagefault_asid_to_vm(struct xe_pagefault *pf, u32 asid) static int xe_pagefault_service(struct xe_pagefault *pf) { struct xe_gt *gt = pf->gt; + struct xe_device *xe = gt_to_xe(gt); struct xe_vm *vm; struct xe_vma *vma = NULL; int err; @@ -278,8 +279,13 @@ static int xe_pagefault_service(struct xe_pagefault *pf) return -EFAULT; vm = xe_pagefault_asid_to_vm(pf, asid); - if (IS_ERR(vm)) - return PTR_ERR(vm); + if (IS_ERR(vm)) { + err = PTR_ERR(vm); + trace_xe_pagefault_fail(xe, NULL, NULL, asid, + xe_pagefault_addr(pf), + xe_pagefault_get_error(pf), err); + return err; + } xe_migrate_ulls_enter(gt_to_tile(gt)->migrate); @@ -314,6 +320,11 @@ static int xe_pagefault_service(struct xe_pagefault *pf) err = xe_pagefault_handle_vma(gt, vma, pf, atomic); unlock_vm: + if (err) + trace_xe_pagefault_fail(xe, vm, vma, asid, + xe_pagefault_addr(pf), + xe_pagefault_get_error(pf), err); + up_read(&vm->lock); xe_vm_put(vm); diff --git a/drivers/gpu/drm/xe/xe_trace_bo.h b/drivers/gpu/drm/xe/xe_trace_bo.h index 86323cf3be2c..36fc7eb65882 100644 --- a/drivers/gpu/drm/xe/xe_trace_bo.h +++ b/drivers/gpu/drm/xe/xe_trace_bo.h @@ -16,10 +16,15 @@ #include "xe_bo_types.h" #include "xe_vm.h" +#define __dev_name_xe(xe) dev_name((xe)->drm.dev) #define __dev_name_bo(bo) dev_name(xe_bo_device(bo)->drm.dev) #define __dev_name_vm(vm) dev_name((vm)->xe->drm.dev) #define __dev_name_vma(vma) __dev_name_vm(xe_vma_vm(vma)) +#define XE_VM_TRACE_MODE_DMA_FENCE 0 +#define XE_VM_TRACE_MODE_PREEMPT_FENCE 1 +#define XE_VM_TRACE_MODE_FAULT 2 + DECLARE_EVENT_CLASS(xe_bo, TP_PROTO(struct xe_bo *bo), TP_ARGS(bo), @@ -194,6 +199,7 @@ DECLARE_EVENT_CLASS(xe_vm, __field(struct xe_vm *, vm) __field(u32, asid) __field(u32, flags) + __field(u8, mode) ), TP_fast_assign( @@ -201,11 +207,20 @@ DECLARE_EVENT_CLASS(xe_vm, __entry->vm = vm; __entry->asid = vm->usm.asid; __entry->flags = vm->flags; + __entry->mode = xe_vm_in_fault_mode(vm) ? + XE_VM_TRACE_MODE_FAULT : + xe_vm_in_preempt_fence_mode(vm) ? + XE_VM_TRACE_MODE_PREEMPT_FENCE : + XE_VM_TRACE_MODE_DMA_FENCE; ), - TP_printk("dev=%s, vm=%p, asid=0x%05x, vm flags=0x%05x", + TP_printk("dev=%s, vm=%p, asid=0x%05x, vm flags=0x%05x, mode=%s", __get_str(dev), __entry->vm, __entry->asid, - __entry->flags) + __entry->flags, + __print_symbolic(__entry->mode, + { XE_VM_TRACE_MODE_DMA_FENCE, "dma-fence" }, + { XE_VM_TRACE_MODE_PREEMPT_FENCE, "preempt-fence" }, + { XE_VM_TRACE_MODE_FAULT, "fault" })) ); DEFINE_EVENT(xe_vm, xe_vm_kill, @@ -223,6 +238,16 @@ DEFINE_EVENT(xe_vm, xe_vm_free, TP_ARGS(vm) ); +DEFINE_EVENT(xe_vm, xe_vm_close_and_put, + TP_PROTO(struct xe_vm *vm), + TP_ARGS(vm) +); + +DEFINE_EVENT(xe_vm, xe_vm_asid_release, + TP_PROTO(struct xe_vm *vm), + TP_ARGS(vm) +); + DEFINE_EVENT(xe_vm, xe_vm_cpu_bind, TP_PROTO(struct xe_vm *vm), TP_ARGS(vm) @@ -253,6 +278,35 @@ DEFINE_EVENT(xe_vm, xe_vm_ops_fail, TP_ARGS(vm) ); +TRACE_EVENT(xe_pagefault_fail, + TP_PROTO(struct xe_device *xe, struct xe_vm *vm, struct xe_vma *vma, + u32 asid, u64 page_addr, u8 reason, int err), + TP_ARGS(xe, vm, vma, asid, page_addr, reason, err), + + TP_STRUCT__entry(__string(dev, __dev_name_xe(xe)) + __field(struct xe_vm *, vm) + __field(struct xe_vma *, vma) + __field(u32, asid) + __field(u64, page_addr) + __field(u8, reason) + __field(int, err) + ), + + TP_fast_assign(__assign_str(dev); + __entry->vm = vm; + __entry->vma = vma; + __entry->asid = asid; + __entry->page_addr = page_addr; + __entry->reason = reason; + __entry->err = err; + ), + + TP_printk("dev=%s, vm=%p, vma=%p, asid=0x%05x, page_addr=0x%012llx, reason=%u, err=%d", + __get_str(dev), __entry->vm, __entry->vma, + __entry->asid, __entry->page_addr, __entry->reason, + __entry->err) +); + #endif /* This part must be outside protection */ diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 03e0c06ec82c..ea5bfb307db1 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -1915,6 +1915,8 @@ void xe_vm_close_and_put(struct xe_vm *vm) xe_assert(xe, !vm->preempt.num_exec_queues); + trace_xe_vm_close_and_put(vm); + xe_vm_close(vm); if (xe_vm_in_preempt_fence_mode(vm)) { mutex_lock(&xe->rebind_resume_lock); @@ -1993,6 +1995,8 @@ void xe_vm_close_and_put(struct xe_vm *vm) xe_assert(xe, xe->info.has_asid); xe_assert(xe, !(vm->flags & XE_VM_FLAG_MIGRATION)); + trace_xe_vm_asid_release(vm); + lookup = xa_erase(&xe->usm.asid_to_vm, vm->usm.asid); xe_assert(xe, lookup == vm); }