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 <daniel.charles@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Link: https://patch.msgid.link/20260930164645.1243801-1-daniel.charles@intel.com
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
This commit is contained in:
Daniel Charles 2026-09-30 09:46:45 -07:00 committed by Rodrigo Vivi
parent 23930d5018
commit 64455314d6
No known key found for this signature in database
GPG Key ID: FA625F640EEB13CA
3 changed files with 73 additions and 4 deletions

View File

@ -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);

View File

@ -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 */

View File

@ -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);
}