All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/30] Refactor VM bind code
@ 2024-03-08  5:07 Matthew Brost
  2024-03-08  5:07 ` [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL Matthew Brost
                   ` (36 more replies)
  0 siblings, 37 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Broken into roughly 5 parts:
Part 1: Prep patches, patches 1-14
Part 2: 1 jobs per VM bind IOCTL and error handling, patches 15-23
Part 3: CPU binds, patches 24-27
Part 4: Error injection for testing, patch 28
Part 5: PT exec queues 29-30

For reviewing, let's focus on part 1 for now and see if patches from
that part can start to get merged.

Tested with [1] and new error handling appears to be working. Also
tested with existing tests at every patch in the series and should be
working at every patch in the series.

Latest version includes some of Thomas's patches too [2].

Matt

[1] https://patchwork.freedesktop.org/series/129606/
[2] https://patchwork.freedesktop.org/series/130871/

Matthew Brost (28):
  drm/xe: Lock all gpuva ops during VM bind IOCTL
  drm/xe: Add ops_execute function which returns a fence
  drm/xe: Move migrate to prefetch to op_lock function
  drm/xe: Add struct xe_vma_ops abstraction
  drm/xe: Update xe_vm_rebind to use dummy VMA operations
  drm/xe: Simplify VM bind IOCTL error handling and cleanup
  drm/xe: Update pagefaults to use dummy VMA operations
  drm/xe: s/xe_tile_migrate_engine/xe_tile_migrate_exec_queue
  drm/xe: Add some members to xe_vma_ops
  drm/xe: Add vm_bind_ioctl_ops_install_fences helper
  drm/xe: Move setting last fence to vm_bind_ioctl_ops_install_fences
  drm/xe: Move ufence check to op_lock
  drm/xe: Move ufence add to vm_bind_ioctl_ops_install_fences
  drm/xe: Add xe_gt_tlb_invalidation_range and convert PT layer to use
    this
  drm/xe: Add xe_vm_pgtable_update_op to xe_vma_ops
  drm/xe: Use ordered WQ for TLB invalidation fences
  drm/xe: Delete PT update selftest
  drm/xe: Convert multiple bind ops into single job
  drm/xe: Remove old functions defs in xe_pt.h
  drm/xe: Update PT layer with better error handling
  drm/xe: Update VM trace events
  drm/xe: Update clear / populate arguments
  drm/xe: Add __xe_migrate_update_pgtables_cpu helper
  drm/xe: CPU binds for jobs
  drm/xe: Don't use migrate exec queue for page fault binds
  drm/xe: Add VM bind IOCTL error injection
  drm/xe/guc: Assert time'd out jobs are not from a VM exec queue
  drm/xe: Add PT exec queues

Thomas Hellström (2):
  drm/xe: Update xe_vm_rebind to return int
  drm/xe: Move vma rebinding to the drm_exec locking loop

 drivers/gpu/drm/xe/Makefile                 |    1 +
 drivers/gpu/drm/xe/tests/xe_migrate.c       |   86 --
 drivers/gpu/drm/xe/xe_bo.c                  |    7 +-
 drivers/gpu/drm/xe/xe_bo.h                  |    4 +-
 drivers/gpu/drm/xe/xe_device.c              |   35 +
 drivers/gpu/drm/xe/xe_device.h              |    2 +
 drivers/gpu/drm/xe/xe_device_types.h        |   16 +
 drivers/gpu/drm/xe/xe_exec.c                |   41 +-
 drivers/gpu/drm/xe/xe_exec_queue.c          |  120 +-
 drivers/gpu/drm/xe/xe_exec_queue_types.h    |   20 +-
 drivers/gpu/drm/xe/xe_gt_pagefault.c        |   10 +-
 drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c |   59 +-
 drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h |    3 +
 drivers/gpu/drm/xe/xe_guc_submit.c          |   22 +-
 drivers/gpu/drm/xe/xe_migrate.c             |  385 ++----
 drivers/gpu/drm/xe/xe_migrate.h             |   46 +-
 drivers/gpu/drm/xe/xe_pt.c                  | 1236 ++++++++++++-------
 drivers/gpu/drm/xe/xe_pt.h                  |   15 +-
 drivers/gpu/drm/xe/xe_pt_exec_queue.c       |  180 +++
 drivers/gpu/drm/xe/xe_pt_exec_queue.h       |   14 +
 drivers/gpu/drm/xe/xe_pt_types.h            |   53 +
 drivers/gpu/drm/xe/xe_sched_job.c           |   68 +-
 drivers/gpu/drm/xe/xe_sched_job_types.h     |   31 +-
 drivers/gpu/drm/xe/xe_sync.c                |   15 +
 drivers/gpu/drm/xe/xe_sync.h                |    1 +
 drivers/gpu/drm/xe/xe_trace.h               |   21 +-
 drivers/gpu/drm/xe/xe_vm.c                  | 1124 ++++++++---------
 drivers/gpu/drm/xe/xe_vm.h                  |    9 +-
 drivers/gpu/drm/xe/xe_vm_types.h            |  198 +--
 29 files changed, 2118 insertions(+), 1704 deletions(-)
 create mode 100644 drivers/gpu/drm/xe/xe_pt_exec_queue.c
 create mode 100644 drivers/gpu/drm/xe/xe_pt_exec_queue.h

-- 
2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-10 17:44   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 02/30] drm/xe: Add ops_execute function which returns a fence Matthew Brost
                   ` (35 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Lock all gpuva ops and validate all BOs in a single step durin the VM
bind IOCTL. This help with the transition to making all gpuva ops in a
VM bind IOCTL a single atomic job.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c | 142 ++++++++++++++++++++++++++-----------
 1 file changed, 101 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 643b3701a738..3b5dc6de07f7 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -413,19 +413,23 @@ int __xe_vm_userptr_needs_repin(struct xe_vm *vm)
 
 #define XE_VM_REBIND_RETRY_TIMEOUT_MS 1000
 
-static void xe_vm_kill(struct xe_vm *vm)
+static void xe_vm_kill(struct xe_vm *vm, bool unlocked)
 {
 	struct xe_exec_queue *q;
 
 	lockdep_assert_held(&vm->lock);
 
-	xe_vm_lock(vm, false);
+	if (unlocked)
+		xe_vm_lock(vm, false);
+
 	vm->flags |= XE_VM_FLAG_BANNED;
 	trace_xe_vm_kill(vm);
 
 	list_for_each_entry(q, &vm->preempt.exec_queues, compute.link)
 		q->ops->kill(q);
-	xe_vm_unlock(vm);
+
+	if (unlocked)
+		xe_vm_unlock(vm);
 
 	/* TODO: Inform user the VM is banned */
 }
@@ -621,7 +625,7 @@ static void preempt_rebind_work_func(struct work_struct *w)
 
 	if (err) {
 		drm_warn(&vm->xe->drm, "VM worker error: %d\n", err);
-		xe_vm_kill(vm);
+		xe_vm_kill(vm, true);
 	}
 	up_write(&vm->lock);
 
@@ -1831,17 +1835,9 @@ static int xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue
 		      u32 num_syncs, bool immediate, bool first_op,
 		      bool last_op)
 {
-	int err;
-
 	xe_vm_assert_held(vm);
 	xe_bo_assert_held(bo);
 
-	if (bo && immediate) {
-		err = xe_bo_validate(bo, vm, true);
-		if (err)
-			return err;
-	}
-
 	return __xe_vm_bind(vm, vma, q, syncs, num_syncs, immediate, first_op,
 			    last_op);
 }
@@ -2488,17 +2484,12 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 	return 0;
 }
 
-static int op_execute(struct drm_exec *exec, struct xe_vm *vm,
-		      struct xe_vma *vma, struct xe_vma_op *op)
+static int op_execute(struct xe_vm *vm, struct xe_vma *vma,
+		      struct xe_vma_op *op)
 {
 	int err;
 
 	lockdep_assert_held_write(&vm->lock);
-
-	err = xe_vm_prepare_vma(exec, vma, 1);
-	if (err)
-		return err;
-
 	xe_vm_assert_held(vm);
 	xe_bo_assert_held(xe_vma_bo(vma));
 
@@ -2579,19 +2570,10 @@ static int op_execute(struct drm_exec *exec, struct xe_vm *vm,
 static int __xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
 			       struct xe_vma_op *op)
 {
-	struct drm_exec exec;
 	int err;
 
 retry_userptr:
-	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
-	drm_exec_until_all_locked(&exec) {
-		err = op_execute(&exec, vm, vma, op);
-		drm_exec_retry_on_contention(&exec);
-		if (err)
-			break;
-	}
-	drm_exec_fini(&exec);
-
+	err = op_execute(vm, vma, op);
 	if (err == -EAGAIN) {
 		lockdep_assert_held_write(&vm->lock);
 
@@ -2756,29 +2738,107 @@ static void vm_bind_ioctl_ops_unwind(struct xe_vm *vm,
 	}
 }
 
+static int vma_lock(struct drm_exec *exec, struct xe_vma *vma, bool validate)
+{
+	struct xe_bo *bo = xe_vma_bo(vma);
+	int err = 0;
+
+	if (bo) {
+		if (!bo->vm)
+			err = drm_exec_prepare_obj(exec, &bo->ttm.base, 1);
+		if (!err && validate)
+			err = xe_bo_validate(bo, xe_vma_vm(vma), true);
+	}
+
+	return err;
+}
+
+static int op_lock(struct drm_exec *exec, struct xe_vm *vm,
+		   struct xe_vma_op *op)
+{
+	int err = 0;
+
+	switch (op->base.op) {
+	case DRM_GPUVA_OP_MAP:
+		err = vma_lock(exec, op->map.vma, !xe_vm_in_fault_mode(vm));
+		break;
+	case DRM_GPUVA_OP_REMAP:
+		err = vma_lock(exec, gpuva_to_vma(op->base.remap.unmap->va),
+			       false);
+		if (!err && op->remap.prev)
+			err = vma_lock(exec, op->remap.prev, true);
+		if (!err && op->remap.next)
+			err = vma_lock(exec, op->remap.next, true);
+		break;
+	case DRM_GPUVA_OP_UNMAP:
+		err = vma_lock(exec, gpuva_to_vma(op->base.unmap.va), false);
+		break;
+	case DRM_GPUVA_OP_PREFETCH:
+		err = vma_lock(exec, gpuva_to_vma(op->base.prefetch.va), true);
+		break;
+	default:
+		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
+	}
+
+	return err;
+}
+
+static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
+				  struct xe_vm *vm,
+				  struct list_head *ops_list)
+{
+	struct xe_vma_op *op;
+	int err;
+
+	err = drm_exec_prepare_obj(exec, xe_vm_obj(vm), 1);
+	if (err)
+		return err;
+
+	list_for_each_entry(op, ops_list, link) {
+		err = op_lock(exec, vm, op);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
 static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
 				     struct list_head *ops_list)
 {
+	struct drm_exec exec;
 	struct xe_vma_op *op, *next;
 	int err;
 
 	lockdep_assert_held_write(&vm->lock);
 
-	list_for_each_entry_safe(op, next, ops_list, link) {
-		err = xe_vma_op_execute(vm, op);
-		if (err) {
-			drm_warn(&vm->xe->drm, "VM op(%d) failed with %d",
-				 op->base.op, err);
-			/*
-			 * FIXME: Killing VM rather than proper error handling
-			 */
-			xe_vm_kill(vm);
-			return -ENOSPC;
+	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT |
+		      DRM_EXEC_IGNORE_DUPLICATES, 0);
+	drm_exec_until_all_locked(&exec) {
+		err = vm_bind_ioctl_ops_lock(&exec, vm, ops_list);
+		drm_exec_retry_on_contention(&exec);
+		if (err)
+			goto unlock;
+
+		list_for_each_entry_safe(op, next, ops_list, link) {
+			err = xe_vma_op_execute(vm, op);
+			if (err) {
+				drm_warn(&vm->xe->drm, "VM op(%d) failed with %d",
+					 op->base.op, err);
+				/*
+				 * FIXME: Killing VM rather than proper error handling
+				 */
+				xe_vm_kill(vm, false);
+				err = -ENOSPC;
+				goto unlock;
+			}
+			xe_vma_op_cleanup(vm, op);
 		}
-		xe_vma_op_cleanup(vm, op);
 	}
 
-	return 0;
+unlock:
+	drm_exec_fini(&exec);
+	return err;
 }
 
 #define SUPPORTED_FLAGS	(DRM_XE_VM_BIND_FLAG_NULL | \
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 02/30] drm/xe: Add ops_execute function which returns a fence
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
  2024-03-08  5:07 ` [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-22 16:11   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 03/30] drm/xe: Move migrate to prefetch to op_lock function Matthew Brost
                   ` (34 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Add ops_execute function which returns a fence. This will be helpful to
initiate all binds (VM bind IOCTL, rebinds in exec IOCTL, rebinds in
preempt rebind worker, and rebinds in pagefaults) via a gpuva ops list.
Returning a fence is needed in various paths.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c | 211 +++++++++++++++++++------------------
 1 file changed, 111 insertions(+), 100 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 3b5dc6de07f7..fb73afcab3b7 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1789,16 +1789,17 @@ find_ufence_get(struct xe_sync_entry *syncs, u32 num_syncs)
 	return NULL;
 }
 
-static int __xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma,
-			struct xe_exec_queue *q, struct xe_sync_entry *syncs,
-			u32 num_syncs, bool immediate, bool first_op,
-			bool last_op)
+static struct dma_fence *
+xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue *q,
+	   struct xe_bo *bo, struct xe_sync_entry *syncs, u32 num_syncs,
+	   bool immediate, bool first_op, bool last_op)
 {
 	struct dma_fence *fence;
 	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, q);
 	struct xe_user_fence *ufence;
 
 	xe_vm_assert_held(vm);
+	xe_bo_assert_held(bo);
 
 	ufence = find_ufence_get(syncs, num_syncs);
 	if (vma->ufence && ufence)
@@ -1810,7 +1811,7 @@ static int __xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma,
 		fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, first_op,
 				       last_op);
 		if (IS_ERR(fence))
-			return PTR_ERR(fence);
+			return fence;
 	} else {
 		int i;
 
@@ -1825,26 +1826,14 @@ static int __xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma,
 
 	if (last_op)
 		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
-	dma_fence_put(fence);
-
-	return 0;
-}
-
-static int xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue *q,
-		      struct xe_bo *bo, struct xe_sync_entry *syncs,
-		      u32 num_syncs, bool immediate, bool first_op,
-		      bool last_op)
-{
-	xe_vm_assert_held(vm);
-	xe_bo_assert_held(bo);
 
-	return __xe_vm_bind(vm, vma, q, syncs, num_syncs, immediate, first_op,
-			    last_op);
+	return fence;
 }
 
-static int xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
-			struct xe_exec_queue *q, struct xe_sync_entry *syncs,
-			u32 num_syncs, bool first_op, bool last_op)
+static struct dma_fence *
+xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
+	     struct xe_exec_queue *q, struct xe_sync_entry *syncs,
+	     u32 num_syncs, bool first_op, bool last_op)
 {
 	struct dma_fence *fence;
 	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, q);
@@ -1854,14 +1843,13 @@ static int xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
 
 	fence = xe_vm_unbind_vma(vma, q, syncs, num_syncs, first_op, last_op);
 	if (IS_ERR(fence))
-		return PTR_ERR(fence);
+		return fence;
 
 	xe_vma_destroy(vma, fence);
 	if (last_op)
 		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
-	dma_fence_put(fence);
 
-	return 0;
+	return fence;
 }
 
 #define ALL_DRM_XE_VM_CREATE_FLAGS (DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE | \
@@ -2004,10 +1992,11 @@ static const u32 region_to_mem_type[] = {
 	XE_PL_VRAM1,
 };
 
-static int xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
-			  struct xe_exec_queue *q, u32 region,
-			  struct xe_sync_entry *syncs, u32 num_syncs,
-			  bool first_op, bool last_op)
+static struct dma_fence *
+xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
+	       struct xe_exec_queue *q, u32 region,
+	       struct xe_sync_entry *syncs, u32 num_syncs,
+	       bool first_op, bool last_op)
 {
 	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, q);
 	int err;
@@ -2017,27 +2006,24 @@ static int xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
 	if (!xe_vma_has_no_bo(vma)) {
 		err = xe_bo_migrate(xe_vma_bo(vma), region_to_mem_type[region]);
 		if (err)
-			return err;
+			return ERR_PTR(err);
 	}
 
 	if (vma->tile_mask != (vma->tile_present & ~vma->usm.tile_invalidated)) {
 		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs, num_syncs,
 				  true, first_op, last_op);
 	} else {
+		struct dma_fence *fence =
+			xe_exec_queue_last_fence_get(wait_exec_queue, vm);
 		int i;
 
 		/* Nothing to do, signal fences now */
 		if (last_op) {
-			for (i = 0; i < num_syncs; i++) {
-				struct dma_fence *fence =
-					xe_exec_queue_last_fence_get(wait_exec_queue, vm);
-
+			for (i = 0; i < num_syncs; i++)
 				xe_sync_entry_signal(&syncs[i], NULL, fence);
-				dma_fence_put(fence);
-			}
 		}
 
-		return 0;
+		return fence;
 	}
 }
 
@@ -2484,10 +2470,10 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 	return 0;
 }
 
-static int op_execute(struct xe_vm *vm, struct xe_vma *vma,
-		      struct xe_vma_op *op)
+static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma *vma,
+				    struct xe_vma_op *op)
 {
-	int err;
+	struct dma_fence *fence = NULL;
 
 	lockdep_assert_held_write(&vm->lock);
 	xe_vm_assert_held(vm);
@@ -2495,11 +2481,11 @@ static int op_execute(struct xe_vm *vm, struct xe_vma *vma,
 
 	switch (op->base.op) {
 	case DRM_GPUVA_OP_MAP:
-		err = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
-				 op->syncs, op->num_syncs,
-				 !xe_vm_in_fault_mode(vm),
-				 op->flags & XE_VMA_OP_FIRST,
-				 op->flags & XE_VMA_OP_LAST);
+		fence = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
+				   op->syncs, op->num_syncs,
+				   !xe_vm_in_fault_mode(vm),
+				   op->flags & XE_VMA_OP_FIRST,
+				   op->flags & XE_VMA_OP_LAST);
 		break;
 	case DRM_GPUVA_OP_REMAP:
 	{
@@ -2509,37 +2495,39 @@ static int op_execute(struct xe_vm *vm, struct xe_vma *vma,
 		if (!op->remap.unmap_done) {
 			if (prev || next)
 				vma->gpuva.flags |= XE_VMA_FIRST_REBIND;
-			err = xe_vm_unbind(vm, vma, op->q, op->syncs,
-					   op->num_syncs,
-					   op->flags & XE_VMA_OP_FIRST,
-					   op->flags & XE_VMA_OP_LAST &&
-					   !prev && !next);
-			if (err)
+			fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
+					     op->num_syncs,
+					     op->flags & XE_VMA_OP_FIRST,
+					     op->flags & XE_VMA_OP_LAST &&
+					     !prev && !next);
+			if (IS_ERR(fence))
 				break;
 			op->remap.unmap_done = true;
 		}
 
 		if (prev) {
 			op->remap.prev->gpuva.flags |= XE_VMA_LAST_REBIND;
-			err = xe_vm_bind(vm, op->remap.prev, op->q,
-					 xe_vma_bo(op->remap.prev), op->syncs,
-					 op->num_syncs, true, false,
-					 op->flags & XE_VMA_OP_LAST && !next);
+			dma_fence_put(fence);
+			fence = xe_vm_bind(vm, op->remap.prev, op->q,
+					   xe_vma_bo(op->remap.prev), op->syncs,
+					   op->num_syncs, true, false,
+					   op->flags & XE_VMA_OP_LAST && !next);
 			op->remap.prev->gpuva.flags &= ~XE_VMA_LAST_REBIND;
-			if (err)
+			if (IS_ERR(fence))
 				break;
 			op->remap.prev = NULL;
 		}
 
 		if (next) {
 			op->remap.next->gpuva.flags |= XE_VMA_LAST_REBIND;
-			err = xe_vm_bind(vm, op->remap.next, op->q,
-					 xe_vma_bo(op->remap.next),
-					 op->syncs, op->num_syncs,
-					 true, false,
-					 op->flags & XE_VMA_OP_LAST);
+			dma_fence_put(fence);
+			fence = xe_vm_bind(vm, op->remap.next, op->q,
+					   xe_vma_bo(op->remap.next),
+					   op->syncs, op->num_syncs,
+					   true, false,
+					   op->flags & XE_VMA_OP_LAST);
 			op->remap.next->gpuva.flags &= ~XE_VMA_LAST_REBIND;
-			if (err)
+			if (IS_ERR(fence))
 				break;
 			op->remap.next = NULL;
 		}
@@ -2547,34 +2535,36 @@ static int op_execute(struct xe_vm *vm, struct xe_vma *vma,
 		break;
 	}
 	case DRM_GPUVA_OP_UNMAP:
-		err = xe_vm_unbind(vm, vma, op->q, op->syncs,
-				   op->num_syncs, op->flags & XE_VMA_OP_FIRST,
-				   op->flags & XE_VMA_OP_LAST);
+		fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
+				     op->num_syncs, op->flags & XE_VMA_OP_FIRST,
+				     op->flags & XE_VMA_OP_LAST);
 		break;
 	case DRM_GPUVA_OP_PREFETCH:
-		err = xe_vm_prefetch(vm, vma, op->q, op->prefetch.region,
-				     op->syncs, op->num_syncs,
-				     op->flags & XE_VMA_OP_FIRST,
-				     op->flags & XE_VMA_OP_LAST);
+		fence = xe_vm_prefetch(vm, vma, op->q, op->prefetch.region,
+				       op->syncs, op->num_syncs,
+				       op->flags & XE_VMA_OP_FIRST,
+				       op->flags & XE_VMA_OP_LAST);
 		break;
 	default:
 		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
 	}
 
-	if (err)
+	if (IS_ERR(fence))
 		trace_xe_vma_fail(vma);
 
-	return err;
+	return fence;
 }
 
-static int __xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
-			       struct xe_vma_op *op)
+static struct dma_fence *
+__xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
+		    struct xe_vma_op *op)
 {
+	struct dma_fence *fence;
 	int err;
 
 retry_userptr:
-	err = op_execute(vm, vma, op);
-	if (err == -EAGAIN) {
+	fence = op_execute(vm, vma, op);
+	if (IS_ERR(fence) && PTR_ERR(fence) == -EAGAIN) {
 		lockdep_assert_held_write(&vm->lock);
 
 		if (op->base.op == DRM_GPUVA_OP_REMAP) {
@@ -2591,22 +2581,24 @@ static int __xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
 			if (!err)
 				goto retry_userptr;
 
+			fence = ERR_PTR(err);
 			trace_xe_vma_fail(vma);
 		}
 	}
 
-	return err;
+	return fence;
 }
 
-static int xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
+static struct dma_fence *
+xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
 {
-	int ret = 0;
+	struct dma_fence *fence = ERR_PTR(-ENOMEM);
 
 	lockdep_assert_held_write(&vm->lock);
 
 	switch (op->base.op) {
 	case DRM_GPUVA_OP_MAP:
-		ret = __xe_vma_op_execute(vm, op->map.vma, op);
+		fence = __xe_vma_op_execute(vm, op->map.vma, op);
 		break;
 	case DRM_GPUVA_OP_REMAP:
 	{
@@ -2619,23 +2611,23 @@ static int xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
 		else
 			vma = op->remap.next;
 
-		ret = __xe_vma_op_execute(vm, vma, op);
+		fence = __xe_vma_op_execute(vm, vma, op);
 		break;
 	}
 	case DRM_GPUVA_OP_UNMAP:
-		ret = __xe_vma_op_execute(vm, gpuva_to_vma(op->base.unmap.va),
-					  op);
+		fence = __xe_vma_op_execute(vm, gpuva_to_vma(op->base.unmap.va),
+					    op);
 		break;
 	case DRM_GPUVA_OP_PREFETCH:
-		ret = __xe_vma_op_execute(vm,
-					  gpuva_to_vma(op->base.prefetch.va),
-					  op);
+		fence = __xe_vma_op_execute(vm,
+					    gpuva_to_vma(op->base.prefetch.va),
+					    op);
 		break;
 	default:
 		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
 	}
 
-	return ret;
+	return fence;
 }
 
 static void xe_vma_op_cleanup(struct xe_vm *vm, struct xe_vma_op *op)
@@ -2803,11 +2795,35 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
 	return 0;
 }
 
+static struct dma_fence *ops_execute(struct xe_vm *vm,
+				     struct list_head *ops_list,
+				     bool cleanup)
+{
+	struct xe_vma_op *op, *next;
+	struct dma_fence *fence = NULL;
+
+	list_for_each_entry_safe(op, next, ops_list, link) {
+		if (!IS_ERR(fence)) {
+			dma_fence_put(fence);
+			fence = xe_vma_op_execute(vm, op);
+		}
+		if (IS_ERR(fence)) {
+			drm_warn(&vm->xe->drm, "VM op(%d) failed with %ld",
+				 op->base.op, PTR_ERR(fence));
+			fence = ERR_PTR(-ENOSPC);
+		}
+		if (cleanup)
+			xe_vma_op_cleanup(vm, op);
+	}
+
+	return fence;
+}
+
 static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
 				     struct list_head *ops_list)
 {
 	struct drm_exec exec;
-	struct xe_vma_op *op, *next;
+	struct dma_fence *fence;
 	int err;
 
 	lockdep_assert_held_write(&vm->lock);
@@ -2820,19 +2836,14 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
 		if (err)
 			goto unlock;
 
-		list_for_each_entry_safe(op, next, ops_list, link) {
-			err = xe_vma_op_execute(vm, op);
-			if (err) {
-				drm_warn(&vm->xe->drm, "VM op(%d) failed with %d",
-					 op->base.op, err);
-				/*
-				 * FIXME: Killing VM rather than proper error handling
-				 */
-				xe_vm_kill(vm, false);
-				err = -ENOSPC;
-				goto unlock;
-			}
-			xe_vma_op_cleanup(vm, op);
+		fence = ops_execute(vm, ops_list, true);
+		if (IS_ERR(fence)) {
+			err = PTR_ERR(fence);
+			/* FIXME: Killing VM rather than proper error handling */
+			xe_vm_kill(vm, false);
+			goto unlock;
+		} else {
+			dma_fence_put(fence);
 		}
 	}
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 03/30] drm/xe: Move migrate to prefetch to op_lock function
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
  2024-03-08  5:07 ` [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL Matthew Brost
  2024-03-08  5:07 ` [PATCH v4 02/30] drm/xe: Add ops_execute function which returns a fence Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-22 17:06   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 04/30] drm/xe: Add struct xe_vma_ops abstraction Matthew Brost
                   ` (33 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Migrates need to be done under drm exec to make lockdep happy, move
the migrate done for prefetches under the op_lock function.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index fb73afcab3b7..70a5ba621e4e 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1994,20 +1994,10 @@ static const u32 region_to_mem_type[] = {
 
 static struct dma_fence *
 xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
-	       struct xe_exec_queue *q, u32 region,
-	       struct xe_sync_entry *syncs, u32 num_syncs,
-	       bool first_op, bool last_op)
+	       struct xe_exec_queue *q, struct xe_sync_entry *syncs,
+	       u32 num_syncs, bool first_op, bool last_op)
 {
 	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, q);
-	int err;
-
-	xe_assert(vm->xe, region <= ARRAY_SIZE(region_to_mem_type));
-
-	if (!xe_vma_has_no_bo(vma)) {
-		err = xe_bo_migrate(xe_vma_bo(vma), region_to_mem_type[region]);
-		if (err)
-			return ERR_PTR(err);
-	}
 
 	if (vma->tile_mask != (vma->tile_present & ~vma->usm.tile_invalidated)) {
 		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs, num_syncs,
@@ -2540,8 +2530,7 @@ static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma *vma,
 				     op->flags & XE_VMA_OP_LAST);
 		break;
 	case DRM_GPUVA_OP_PREFETCH:
-		fence = xe_vm_prefetch(vm, vma, op->q, op->prefetch.region,
-				       op->syncs, op->num_syncs,
+		fence = xe_vm_prefetch(vm, vma, op->q, op->syncs, op->num_syncs,
 				       op->flags & XE_VMA_OP_FIRST,
 				       op->flags & XE_VMA_OP_LAST);
 		break;
@@ -2766,8 +2755,17 @@ static int op_lock(struct drm_exec *exec, struct xe_vm *vm,
 		err = vma_lock(exec, gpuva_to_vma(op->base.unmap.va), false);
 		break;
 	case DRM_GPUVA_OP_PREFETCH:
-		err = vma_lock(exec, gpuva_to_vma(op->base.prefetch.va), true);
+	{
+		struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va);
+		u32 region = op->prefetch.region;
+
+		xe_assert(vm->xe, region <= ARRAY_SIZE(region_to_mem_type));
+
+		err = vma_lock(exec, vma, false);
+		if (!err && !xe_vma_has_no_bo(vma))
+			err = xe_bo_migrate(xe_vma_bo(vma), region);
 		break;
+	}
 	default:
 		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
 	}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 04/30] drm/xe: Add struct xe_vma_ops abstraction
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (2 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 03/30] drm/xe: Move migrate to prefetch to op_lock function Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-22 17:13   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 05/30] drm/xe: Update xe_vm_rebind to use dummy VMA operations Matthew Brost
                   ` (32 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Having a structure which encapsulates a list of VMA operations will help
enable 1 job for the entire list.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c       | 37 ++++++++++++++++++--------------
 drivers/gpu/drm/xe/xe_vm_types.h |  7 ++++++
 2 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 70a5ba621e4e..e342af6b51b1 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -2305,7 +2305,7 @@ static int xe_vma_op_commit(struct xe_vm *vm, struct xe_vma_op *op)
 static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 				   struct drm_gpuva_ops *ops,
 				   struct xe_sync_entry *syncs, u32 num_syncs,
-				   struct list_head *ops_list, bool last)
+				   struct xe_vma_ops *vops, bool last)
 {
 	struct xe_device *xe = vm->xe;
 	struct xe_vma_op *last_op = NULL;
@@ -2317,11 +2317,11 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 	drm_gpuva_for_each_op(__op, ops) {
 		struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
 		struct xe_vma *vma;
-		bool first = list_empty(ops_list);
+		bool first = list_empty(&vops->list);
 		unsigned int flags = 0;
 
 		INIT_LIST_HEAD(&op->link);
-		list_add_tail(&op->link, ops_list);
+		list_add_tail(&op->link, &vops->list);
 
 		if (first) {
 			op->flags |= XE_VMA_OP_FIRST;
@@ -2445,7 +2445,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 	}
 
 	/* FIXME: Unhandled corner case */
-	XE_WARN_ON(!last_op && last && !list_empty(ops_list));
+	XE_WARN_ON(!last_op && last && !list_empty(&vops->list));
 
 	if (!last_op)
 		return 0;
@@ -2775,7 +2775,7 @@ static int op_lock(struct drm_exec *exec, struct xe_vm *vm,
 
 static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
 				  struct xe_vm *vm,
-				  struct list_head *ops_list)
+				  struct xe_vma_ops *vops)
 {
 	struct xe_vma_op *op;
 	int err;
@@ -2784,7 +2784,7 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
 	if (err)
 		return err;
 
-	list_for_each_entry(op, ops_list, link) {
+	list_for_each_entry(op, &vops->list, link) {
 		err = op_lock(exec, vm, op);
 		if (err)
 			return err;
@@ -2794,13 +2794,13 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
 }
 
 static struct dma_fence *ops_execute(struct xe_vm *vm,
-				     struct list_head *ops_list,
+				     struct xe_vma_ops *vops,
 				     bool cleanup)
 {
 	struct xe_vma_op *op, *next;
 	struct dma_fence *fence = NULL;
 
-	list_for_each_entry_safe(op, next, ops_list, link) {
+	list_for_each_entry_safe(op, next, &vops->list, link) {
 		if (!IS_ERR(fence)) {
 			dma_fence_put(fence);
 			fence = xe_vma_op_execute(vm, op);
@@ -2818,7 +2818,7 @@ static struct dma_fence *ops_execute(struct xe_vm *vm,
 }
 
 static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
-				     struct list_head *ops_list)
+				     struct xe_vma_ops *vops)
 {
 	struct drm_exec exec;
 	struct dma_fence *fence;
@@ -2829,12 +2829,12 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
 	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT |
 		      DRM_EXEC_IGNORE_DUPLICATES, 0);
 	drm_exec_until_all_locked(&exec) {
-		err = vm_bind_ioctl_ops_lock(&exec, vm, ops_list);
+		err = vm_bind_ioctl_ops_lock(&exec, vm, vops);
 		drm_exec_retry_on_contention(&exec);
 		if (err)
 			goto unlock;
 
-		fence = ops_execute(vm, ops_list, true);
+		fence = ops_execute(vm, vops, true);
 		if (IS_ERR(fence)) {
 			err = PTR_ERR(fence);
 			/* FIXME: Killing VM rather than proper error handling */
@@ -2992,6 +2992,11 @@ static int vm_bind_ioctl_signal_fences(struct xe_vm *vm,
 	return err;
 }
 
+static void xe_vma_ops_init(struct xe_vma_ops *vops)
+{
+	INIT_LIST_HEAD(&vops->list);
+}
+
 int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 {
 	struct xe_device *xe = to_xe_device(dev);
@@ -3005,7 +3010,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 	u32 num_syncs, num_ufence = 0;
 	struct xe_sync_entry *syncs = NULL;
 	struct drm_xe_vm_bind_op *bind_ops;
-	LIST_HEAD(ops_list);
+	struct xe_vma_ops vops;
 	int err;
 	int i;
 
@@ -3156,6 +3161,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 		goto free_syncs;
 	}
 
+	xe_vma_ops_init(&vops);
 	for (i = 0; i < args->num_binds; ++i) {
 		u64 range = bind_ops[i].range;
 		u64 addr = bind_ops[i].addr;
@@ -3175,14 +3181,13 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 		}
 
 		err = vm_bind_ioctl_ops_parse(vm, q, ops[i], syncs, num_syncs,
-					      &ops_list,
-					      i == args->num_binds - 1);
+					      &vops, i == args->num_binds - 1);
 		if (err)
 			goto unwind_ops;
 	}
 
 	/* Nothing to do */
-	if (list_empty(&ops_list)) {
+	if (list_empty(&vops.list)) {
 		err = -ENODATA;
 		goto unwind_ops;
 	}
@@ -3191,7 +3196,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 	if (q)
 		xe_exec_queue_get(q);
 
-	err = vm_bind_ioctl_ops_execute(vm, &ops_list);
+	err = vm_bind_ioctl_ops_execute(vm, &vops);
 
 	up_write(&vm->lock);
 
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index 79b5cab57711..cc3dce893f1e 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -355,4 +355,11 @@ struct xe_vma_op {
 		struct xe_vma_op_prefetch prefetch;
 	};
 };
+
+/** struct xe_vma_ops - VMA operations */
+struct xe_vma_ops {
+	/** @list: list of VMA operations */
+	struct list_head list;
+};
+
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 05/30] drm/xe: Update xe_vm_rebind to use dummy VMA operations
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (3 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 04/30] drm/xe: Add struct xe_vma_ops abstraction Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-22 21:23   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 06/30] drm/xe: Simplify VM bind IOCTL error handling and cleanup Matthew Brost
                   ` (31 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

All bind interfaces are transitioning to use VMA ops, update
xe_vm_rebind to use VMA ops.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c       |  47 +++++---
 drivers/gpu/drm/xe/xe_vm_types.h | 189 ++++++++++++++++---------------
 2 files changed, 132 insertions(+), 104 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index e342af6b51b1..0bb807c05d7b 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -755,10 +755,22 @@ int xe_vm_userptr_check_repin(struct xe_vm *vm)
 		list_empty_careful(&vm->userptr.invalidated)) ? 0 : -EAGAIN;
 }
 
-static struct dma_fence *
-xe_vm_bind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
-	       struct xe_sync_entry *syncs, u32 num_syncs,
-	       bool first_op, bool last_op);
+static void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma)
+{
+	vm->dummy_ops.op.base.op = DRM_GPUVA_OP_MAP;
+	vm->dummy_ops.op.base.map.va.addr = vma->gpuva.va.addr;
+	vm->dummy_ops.op.base.map.va.range = vma->gpuva.va.range;
+	vm->dummy_ops.op.base.map.gem.obj = vma->gpuva.gem.obj;
+	vm->dummy_ops.op.base.map.gem.offset = vma->gpuva.gem.offset;
+	vm->dummy_ops.op.map.vma = vma;
+	vm->dummy_ops.op.map.immediate = true;
+	vm->dummy_ops.op.map.dumpable = vma->gpuva.flags & XE_VMA_DUMPABLE;
+	vm->dummy_ops.op.map.is_null = xe_vma_is_null(vma);
+}
+
+static struct dma_fence *ops_execute(struct xe_vm *vm,
+				     struct xe_vma_ops *vops,
+				     bool cleanup);
 
 struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
 {
@@ -780,7 +792,9 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
 			trace_xe_vma_rebind_worker(vma);
 		else
 			trace_xe_vma_rebind_exec(vma);
-		fence = xe_vm_bind_vma(vma, NULL, NULL, 0, false, false);
+
+		xe_vm_populate_dummy_rebind(vm, vma);
+		fence = ops_execute(vm, &vm->dummy_ops.vops, false);
 		if (IS_ERR(fence))
 			return fence;
 	}
@@ -1289,6 +1303,11 @@ static void xe_vm_free_scratch(struct xe_vm *vm)
 	}
 }
 
+static void xe_vma_ops_init(struct xe_vma_ops *vops)
+{
+	INIT_LIST_HEAD(&vops->list);
+}
+
 struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
 {
 	struct drm_gem_object *vm_resv_obj;
@@ -1310,6 +1329,10 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
 	init_rwsem(&vm->lock);
 	mutex_init(&vm->snap_mutex);
 
+	xe_vma_ops_init(&vm->dummy_ops.vops);
+	INIT_LIST_HEAD(&vm->dummy_ops.op.link);
+	list_add(&vm->dummy_ops.op.link, &vm->dummy_ops.vops.list);
+
 	INIT_LIST_HEAD(&vm->rebind_list);
 
 	INIT_LIST_HEAD(&vm->userptr.repin_list);
@@ -2140,6 +2163,7 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_bo *bo,
 		struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
 
 		if (__op->op == DRM_GPUVA_OP_MAP) {
+			op->map.immediate = !xe_vm_in_fault_mode(vm);
 			op->map.is_null = flags & DRM_XE_VM_BIND_FLAG_NULL;
 			op->map.dumpable = flags & DRM_XE_VM_BIND_FLAG_DUMPABLE;
 			op->map.pat_index = pat_index;
@@ -2465,7 +2489,7 @@ static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma *vma,
 {
 	struct dma_fence *fence = NULL;
 
-	lockdep_assert_held_write(&vm->lock);
+	lockdep_assert_held(&vm->lock);
 	xe_vm_assert_held(vm);
 	xe_bo_assert_held(xe_vma_bo(vma));
 
@@ -2473,7 +2497,7 @@ static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma *vma,
 	case DRM_GPUVA_OP_MAP:
 		fence = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
 				   op->syncs, op->num_syncs,
-				   !xe_vm_in_fault_mode(vm),
+				   op->map.immediate,
 				   op->flags & XE_VMA_OP_FIRST,
 				   op->flags & XE_VMA_OP_LAST);
 		break;
@@ -2554,7 +2578,7 @@ __xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
 retry_userptr:
 	fence = op_execute(vm, vma, op);
 	if (IS_ERR(fence) && PTR_ERR(fence) == -EAGAIN) {
-		lockdep_assert_held_write(&vm->lock);
+		lockdep_assert_held(&vm->lock);
 
 		if (op->base.op == DRM_GPUVA_OP_REMAP) {
 			if (!op->remap.unmap_done)
@@ -2583,7 +2607,7 @@ xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
 {
 	struct dma_fence *fence = ERR_PTR(-ENOMEM);
 
-	lockdep_assert_held_write(&vm->lock);
+	lockdep_assert_held(&vm->lock);
 
 	switch (op->base.op) {
 	case DRM_GPUVA_OP_MAP:
@@ -2992,11 +3016,6 @@ static int vm_bind_ioctl_signal_fences(struct xe_vm *vm,
 	return err;
 }
 
-static void xe_vma_ops_init(struct xe_vma_ops *vops)
-{
-	INIT_LIST_HEAD(&vops->list);
-}
-
 int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 {
 	struct xe_device *xe = to_xe_device(dev);
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index cc3dce893f1e..7ef9e632154a 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -18,6 +18,7 @@
 #include "xe_range_fence.h"
 
 struct xe_bo;
+struct xe_device;
 struct xe_sync_entry;
 struct xe_user_fence;
 struct xe_vm;
@@ -124,7 +125,96 @@ struct xe_userptr_vma {
 	struct xe_userptr userptr;
 };
 
-struct xe_device;
+/** struct xe_vma_op_map - VMA map operation */
+struct xe_vma_op_map {
+	/** @vma: VMA to map */
+	struct xe_vma *vma;
+	/** @immediate: Immediate bind */
+	bool immediate;
+	/** @is_null: is NULL binding */
+	bool is_null;
+	/** @dumpable: whether BO is dumped on GPU hang */
+	bool dumpable;
+	/** @pat_index: The pat index to use for this operation. */
+	u16 pat_index;
+};
+
+/** struct xe_vma_op_remap - VMA remap operation */
+struct xe_vma_op_remap {
+	/** @prev: VMA preceding part of a split mapping */
+	struct xe_vma *prev;
+	/** @next: VMA subsequent part of a split mapping */
+	struct xe_vma *next;
+	/** @start: start of the VMA unmap */
+	u64 start;
+	/** @range: range of the VMA unmap */
+	u64 range;
+	/** @skip_prev: skip prev rebind */
+	bool skip_prev;
+	/** @skip_next: skip next rebind */
+	bool skip_next;
+	/** @unmap_done: unmap operation in done */
+	bool unmap_done;
+};
+
+/** struct xe_vma_op_prefetch - VMA prefetch operation */
+struct xe_vma_op_prefetch {
+	/** @region: memory region to prefetch to */
+	u32 region;
+};
+
+/** enum xe_vma_op_flags - flags for VMA operation */
+enum xe_vma_op_flags {
+	/** @XE_VMA_OP_FIRST: first VMA operation for a set of syncs */
+	XE_VMA_OP_FIRST			= BIT(0),
+	/** @XE_VMA_OP_LAST: last VMA operation for a set of syncs */
+	XE_VMA_OP_LAST			= BIT(1),
+	/** @XE_VMA_OP_COMMITTED: VMA operation committed */
+	XE_VMA_OP_COMMITTED		= BIT(2),
+	/** @XE_VMA_OP_PREV_COMMITTED: Previous VMA operation committed */
+	XE_VMA_OP_PREV_COMMITTED	= BIT(3),
+	/** @XE_VMA_OP_NEXT_COMMITTED: Next VMA operation committed */
+	XE_VMA_OP_NEXT_COMMITTED	= BIT(4),
+};
+
+/** struct xe_vma_op - VMA operation */
+struct xe_vma_op {
+	/** @base: GPUVA base operation */
+	struct drm_gpuva_op base;
+	/**
+	 * @ops: GPUVA ops, when set call drm_gpuva_ops_free after this
+	 * operations is processed
+	 */
+	struct drm_gpuva_ops *ops;
+	/** @q: exec queue for this operation */
+	struct xe_exec_queue *q;
+	/**
+	 * @syncs: syncs for this operation, only used on first and last
+	 * operation
+	 */
+	struct xe_sync_entry *syncs;
+	/** @num_syncs: number of syncs */
+	u32 num_syncs;
+	/** @link: async operation link */
+	struct list_head link;
+	/** @flags: operation flags */
+	enum xe_vma_op_flags flags;
+
+	union {
+		/** @map: VMA map operation specific data */
+		struct xe_vma_op_map map;
+		/** @remap: VMA remap operation specific data */
+		struct xe_vma_op_remap remap;
+		/** @prefetch: VMA prefetch operation specific data */
+		struct xe_vma_op_prefetch prefetch;
+	};
+};
+
+/** struct xe_vma_ops - VMA operations */
+struct xe_vma_ops {
+	/** @list: list of VMA operations */
+	struct list_head list;
+};
 
 struct xe_vm {
 	/** @gpuvm: base GPUVM used to track VMAs */
@@ -267,99 +357,18 @@ struct xe_vm {
 		bool capture_once;
 	} error_capture;
 
+	/** @dummy_ops: dummy VMA ops to issue rebinds */
+	struct {
+		/** @dummy_ops.ops: dummy VMA ops */
+		struct xe_vma_ops vops;
+		/** @dummy_ops.op: dummy VMA op */
+		struct xe_vma_op op;
+	} dummy_ops;
+
 	/** @batch_invalidate_tlb: Always invalidate TLB before batch start */
 	bool batch_invalidate_tlb;
 	/** @xef: XE file handle for tracking this VM's drm client */
 	struct xe_file *xef;
 };
 
-/** struct xe_vma_op_map - VMA map operation */
-struct xe_vma_op_map {
-	/** @vma: VMA to map */
-	struct xe_vma *vma;
-	/** @is_null: is NULL binding */
-	bool is_null;
-	/** @dumpable: whether BO is dumped on GPU hang */
-	bool dumpable;
-	/** @pat_index: The pat index to use for this operation. */
-	u16 pat_index;
-};
-
-/** struct xe_vma_op_remap - VMA remap operation */
-struct xe_vma_op_remap {
-	/** @prev: VMA preceding part of a split mapping */
-	struct xe_vma *prev;
-	/** @next: VMA subsequent part of a split mapping */
-	struct xe_vma *next;
-	/** @start: start of the VMA unmap */
-	u64 start;
-	/** @range: range of the VMA unmap */
-	u64 range;
-	/** @skip_prev: skip prev rebind */
-	bool skip_prev;
-	/** @skip_next: skip next rebind */
-	bool skip_next;
-	/** @unmap_done: unmap operation in done */
-	bool unmap_done;
-};
-
-/** struct xe_vma_op_prefetch - VMA prefetch operation */
-struct xe_vma_op_prefetch {
-	/** @region: memory region to prefetch to */
-	u32 region;
-};
-
-/** enum xe_vma_op_flags - flags for VMA operation */
-enum xe_vma_op_flags {
-	/** @XE_VMA_OP_FIRST: first VMA operation for a set of syncs */
-	XE_VMA_OP_FIRST			= BIT(0),
-	/** @XE_VMA_OP_LAST: last VMA operation for a set of syncs */
-	XE_VMA_OP_LAST			= BIT(1),
-	/** @XE_VMA_OP_COMMITTED: VMA operation committed */
-	XE_VMA_OP_COMMITTED		= BIT(2),
-	/** @XE_VMA_OP_PREV_COMMITTED: Previous VMA operation committed */
-	XE_VMA_OP_PREV_COMMITTED	= BIT(3),
-	/** @XE_VMA_OP_NEXT_COMMITTED: Next VMA operation committed */
-	XE_VMA_OP_NEXT_COMMITTED	= BIT(4),
-};
-
-/** struct xe_vma_op - VMA operation */
-struct xe_vma_op {
-	/** @base: GPUVA base operation */
-	struct drm_gpuva_op base;
-	/**
-	 * @ops: GPUVA ops, when set call drm_gpuva_ops_free after this
-	 * operations is processed
-	 */
-	struct drm_gpuva_ops *ops;
-	/** @q: exec queue for this operation */
-	struct xe_exec_queue *q;
-	/**
-	 * @syncs: syncs for this operation, only used on first and last
-	 * operation
-	 */
-	struct xe_sync_entry *syncs;
-	/** @num_syncs: number of syncs */
-	u32 num_syncs;
-	/** @link: async operation link */
-	struct list_head link;
-	/** @flags: operation flags */
-	enum xe_vma_op_flags flags;
-
-	union {
-		/** @map: VMA map operation specific data */
-		struct xe_vma_op_map map;
-		/** @remap: VMA remap operation specific data */
-		struct xe_vma_op_remap remap;
-		/** @prefetch: VMA prefetch operation specific data */
-		struct xe_vma_op_prefetch prefetch;
-	};
-};
-
-/** struct xe_vma_ops - VMA operations */
-struct xe_vma_ops {
-	/** @list: list of VMA operations */
-	struct list_head list;
-};
-
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 06/30] drm/xe: Simplify VM bind IOCTL error handling and cleanup
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (4 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 05/30] drm/xe: Update xe_vm_rebind to use dummy VMA operations Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-25 16:03   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 07/30] drm/xe: Update pagefaults to use dummy VMA operations Matthew Brost
                   ` (30 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Clean up everything in VM bind IOCTL in 1 path for both errors and
non-errors. Also move VM bind IOCTL cleanup from ops (also used by
non-IOCTL binds) to the VM bind IOCTL.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c       | 60 +++++---------------------------
 drivers/gpu/drm/xe/xe_vm_types.h |  5 ---
 2 files changed, 9 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 0bb807c05d7b..dde777c807cf 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -769,8 +769,7 @@ static void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma)
 }
 
 static struct dma_fence *ops_execute(struct xe_vm *vm,
-				     struct xe_vma_ops *vops,
-				     bool cleanup);
+				     struct xe_vma_ops *vops);
 
 struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
 {
@@ -794,7 +793,7 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
 			trace_xe_vma_rebind_exec(vma);
 
 		xe_vm_populate_dummy_rebind(vm, vma);
-		fence = ops_execute(vm, &vm->dummy_ops.vops, false);
+		fence = ops_execute(vm, &vm->dummy_ops.vops);
 		if (IS_ERR(fence))
 			return fence;
 	}
@@ -2474,7 +2473,6 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 	if (!last_op)
 		return 0;
 
-	last_op->ops = ops;
 	if (last) {
 		last_op->flags |= XE_VMA_OP_LAST;
 		last_op->num_syncs = num_syncs;
@@ -2643,25 +2641,6 @@ xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
 	return fence;
 }
 
-static void xe_vma_op_cleanup(struct xe_vm *vm, struct xe_vma_op *op)
-{
-	bool last = op->flags & XE_VMA_OP_LAST;
-
-	if (last) {
-		while (op->num_syncs--)
-			xe_sync_entry_cleanup(&op->syncs[op->num_syncs]);
-		kfree(op->syncs);
-		if (op->q)
-			xe_exec_queue_put(op->q);
-	}
-	if (!list_empty(&op->link))
-		list_del(&op->link);
-	if (op->ops)
-		drm_gpuva_ops_free(&vm->gpuvm, op->ops);
-	if (last)
-		xe_vm_put(vm);
-}
-
 static void xe_vma_op_unwind(struct xe_vm *vm, struct xe_vma_op *op,
 			     bool post_commit, bool prev_post_commit,
 			     bool next_post_commit)
@@ -2738,8 +2717,6 @@ static void vm_bind_ioctl_ops_unwind(struct xe_vm *vm,
 					 op->flags & XE_VMA_OP_PREV_COMMITTED,
 					 op->flags & XE_VMA_OP_NEXT_COMMITTED);
 		}
-
-		drm_gpuva_ops_free(&vm->gpuvm, __ops);
 	}
 }
 
@@ -2818,8 +2795,7 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
 }
 
 static struct dma_fence *ops_execute(struct xe_vm *vm,
-				     struct xe_vma_ops *vops,
-				     bool cleanup)
+				     struct xe_vma_ops *vops)
 {
 	struct xe_vma_op *op, *next;
 	struct dma_fence *fence = NULL;
@@ -2834,8 +2810,6 @@ static struct dma_fence *ops_execute(struct xe_vm *vm,
 				 op->base.op, PTR_ERR(fence));
 			fence = ERR_PTR(-ENOSPC);
 		}
-		if (cleanup)
-			xe_vma_op_cleanup(vm, op);
 	}
 
 	return fence;
@@ -2858,7 +2832,7 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
 		if (err)
 			goto unlock;
 
-		fence = ops_execute(vm, vops, true);
+		fence = ops_execute(vm, vops);
 		if (IS_ERR(fence)) {
 			err = PTR_ERR(fence);
 			/* FIXME: Killing VM rather than proper error handling */
@@ -3211,30 +3185,14 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 		goto unwind_ops;
 	}
 
-	xe_vm_get(vm);
-	if (q)
-		xe_exec_queue_get(q);
-
 	err = vm_bind_ioctl_ops_execute(vm, &vops);
 
-	up_write(&vm->lock);
-
-	if (q)
-		xe_exec_queue_put(q);
-	xe_vm_put(vm);
-
-	for (i = 0; bos && i < args->num_binds; ++i)
-		xe_bo_put(bos[i]);
-
-	kvfree(bos);
-	kvfree(ops);
-	if (args->num_binds > 1)
-		kvfree(bind_ops);
-
-	return err;
-
 unwind_ops:
-	vm_bind_ioctl_ops_unwind(vm, ops, args->num_binds);
+	if (err && err != -ENODATA)
+		vm_bind_ioctl_ops_unwind(vm, ops, args->num_binds);
+	for (i = args->num_binds - 1; i >= 0; --i)
+		if (ops[i])
+			drm_gpuva_ops_free(&vm->gpuvm, ops[i]);
 free_syncs:
 	if (err == -ENODATA)
 		err = vm_bind_ioctl_signal_fences(vm, q, syncs, num_syncs);
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index 7ef9e632154a..f097fe318a74 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -181,11 +181,6 @@ enum xe_vma_op_flags {
 struct xe_vma_op {
 	/** @base: GPUVA base operation */
 	struct drm_gpuva_op base;
-	/**
-	 * @ops: GPUVA ops, when set call drm_gpuva_ops_free after this
-	 * operations is processed
-	 */
-	struct drm_gpuva_ops *ops;
 	/** @q: exec queue for this operation */
 	struct xe_exec_queue *q;
 	/**
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 07/30] drm/xe: Update pagefaults to use dummy VMA operations
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (5 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 06/30] drm/xe: Simplify VM bind IOCTL error handling and cleanup Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-08  5:07 ` [PATCH v4 08/30] drm/xe: s/xe_tile_migrate_engine/xe_tile_migrate_exec_queue Matthew Brost
                   ` (29 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

All bind interfaces are transitioning to use VMA ops, update
pagefaults to use VMA ops.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_gt_pagefault.c |  7 ++--
 drivers/gpu/drm/xe/xe_vm.c           | 54 +++++++++++++++++++---------
 drivers/gpu/drm/xe/xe_vm.h           |  3 ++
 drivers/gpu/drm/xe/xe_vm_types.h     |  2 ++
 4 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c
index 73c535193a98..3c7d6e4e3917 100644
--- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
+++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
@@ -19,7 +19,6 @@
 #include "xe_guc.h"
 #include "xe_guc_ct.h"
 #include "xe_migrate.h"
-#include "xe_pt.h"
 #include "xe_trace.h"
 #include "xe_vm.h"
 
@@ -209,8 +208,10 @@ static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf)
 
 	/* Bind VMA only to the GT that has faulted */
 	trace_xe_vma_pf_bind(vma);
-	fence = __xe_pt_bind_vma(tile, vma, xe_tile_migrate_engine(tile), NULL, 0,
-				 vma->tile_present & BIT(tile->id));
+	xe_vm_populate_dummy_rebind(vm, vma);
+	vm->dummy_ops.op.tile_mask = BIT(tile->id);
+	vm->dummy_ops.op.q = xe_tile_migrate_engine(tile);
+	fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
 	if (IS_ERR(fence)) {
 		ret = PTR_ERR(fence);
 		goto unlock_dma_resv;
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index dde777c807cf..a6bae2f5e296 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -755,22 +755,27 @@ int xe_vm_userptr_check_repin(struct xe_vm *vm)
 		list_empty_careful(&vm->userptr.invalidated)) ? 0 : -EAGAIN;
 }
 
-static void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma)
+/**
+ * xe_vm_populate_dummy_rebind() - Populate dummy rebind VMA ops
+ * @vm: The VM.
+ * @vma: VMA to populate dummy VMA ops
+ *
+ * Populate dummy VMA ops which can be used to issue a rebind for the VMA
+ */
+void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma)
 {
 	vm->dummy_ops.op.base.op = DRM_GPUVA_OP_MAP;
 	vm->dummy_ops.op.base.map.va.addr = vma->gpuva.va.addr;
 	vm->dummy_ops.op.base.map.va.range = vma->gpuva.va.range;
 	vm->dummy_ops.op.base.map.gem.obj = vma->gpuva.gem.obj;
 	vm->dummy_ops.op.base.map.gem.offset = vma->gpuva.gem.offset;
+	vm->dummy_ops.op.tile_mask = vma->tile_mask;
 	vm->dummy_ops.op.map.vma = vma;
 	vm->dummy_ops.op.map.immediate = true;
 	vm->dummy_ops.op.map.dumpable = vma->gpuva.flags & XE_VMA_DUMPABLE;
 	vm->dummy_ops.op.map.is_null = xe_vma_is_null(vma);
 }
 
-static struct dma_fence *ops_execute(struct xe_vm *vm,
-				     struct xe_vma_ops *vops);
-
 struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
 {
 	struct dma_fence *fence = NULL;
@@ -793,7 +798,7 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
 			trace_xe_vma_rebind_exec(vma);
 
 		xe_vm_populate_dummy_rebind(vm, vma);
-		fence = ops_execute(vm, &vm->dummy_ops.vops);
+		fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
 		if (IS_ERR(fence))
 			return fence;
 	}
@@ -1724,7 +1729,7 @@ xe_vm_unbind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
 static struct dma_fence *
 xe_vm_bind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
 	       struct xe_sync_entry *syncs, u32 num_syncs,
-	       bool first_op, bool last_op)
+	       u8 tile_mask, bool first_op, bool last_op)
 {
 	struct xe_tile *tile;
 	struct dma_fence *fence;
@@ -1746,7 +1751,7 @@ xe_vm_bind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
 	}
 
 	for_each_tile(tile, vm->xe, id) {
-		if (!(vma->tile_mask & BIT(id)))
+		if (!(tile_mask & BIT(id)))
 			goto next;
 
 		fence = __xe_pt_bind_vma(tile, vma, q ? q : vm->q[id],
@@ -1814,7 +1819,7 @@ find_ufence_get(struct xe_sync_entry *syncs, u32 num_syncs)
 static struct dma_fence *
 xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue *q,
 	   struct xe_bo *bo, struct xe_sync_entry *syncs, u32 num_syncs,
-	   bool immediate, bool first_op, bool last_op)
+	   u8 tile_mask, bool immediate, bool first_op, bool last_op)
 {
 	struct dma_fence *fence;
 	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, q);
@@ -1830,8 +1835,8 @@ xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue *q,
 	vma->ufence = ufence ?: vma->ufence;
 
 	if (immediate) {
-		fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, first_op,
-				       last_op);
+		fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, tile_mask,
+				       first_op, last_op);
 		if (IS_ERR(fence))
 			return fence;
 	} else {
@@ -2023,7 +2028,7 @@ xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
 
 	if (vma->tile_mask != (vma->tile_present & ~vma->usm.tile_invalidated)) {
 		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs, num_syncs,
-				  true, first_op, last_op);
+				  vma->tile_mask, true, first_op, last_op);
 	} else {
 		struct dma_fence *fence =
 			xe_exec_queue_last_fence_get(wait_exec_queue, vm);
@@ -2333,10 +2338,15 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 	struct xe_device *xe = vm->xe;
 	struct xe_vma_op *last_op = NULL;
 	struct drm_gpuva_op *__op;
+	struct xe_tile *tile;
+	u8 id, tile_mask = 0;
 	int err = 0;
 
 	lockdep_assert_held_write(&vm->lock);
 
+	for_each_tile(tile, vm->xe, id)
+		tile_mask |= 0x1 << id;
+
 	drm_gpuva_for_each_op(__op, ops) {
 		struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
 		struct xe_vma *vma;
@@ -2353,6 +2363,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 		}
 
 		op->q = q;
+		op->tile_mask = tile_mask;
 
 		switch (op->base.op) {
 		case DRM_GPUVA_OP_MAP:
@@ -2493,9 +2504,11 @@ static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma *vma,
 
 	switch (op->base.op) {
 	case DRM_GPUVA_OP_MAP:
+		/* FIXME: Override vma->tile_mask for page faults */
 		fence = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
 				   op->syncs, op->num_syncs,
 				   op->map.immediate,
+				   op->tile_mask,
 				   op->flags & XE_VMA_OP_FIRST,
 				   op->flags & XE_VMA_OP_LAST);
 		break;
@@ -2522,7 +2535,8 @@ static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma *vma,
 			dma_fence_put(fence);
 			fence = xe_vm_bind(vm, op->remap.prev, op->q,
 					   xe_vma_bo(op->remap.prev), op->syncs,
-					   op->num_syncs, true, false,
+					   op->num_syncs, op->remap.prev->tile_mask,
+					   true, false,
 					   op->flags & XE_VMA_OP_LAST && !next);
 			op->remap.prev->gpuva.flags &= ~XE_VMA_LAST_REBIND;
 			if (IS_ERR(fence))
@@ -2536,7 +2550,7 @@ static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma *vma,
 			fence = xe_vm_bind(vm, op->remap.next, op->q,
 					   xe_vma_bo(op->remap.next),
 					   op->syncs, op->num_syncs,
-					   true, false,
+					   op->remap.next->tile_mask, true, false,
 					   op->flags & XE_VMA_OP_LAST);
 			op->remap.next->gpuva.flags &= ~XE_VMA_LAST_REBIND;
 			if (IS_ERR(fence))
@@ -2794,8 +2808,16 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
 	return 0;
 }
 
-static struct dma_fence *ops_execute(struct xe_vm *vm,
-				     struct xe_vma_ops *vops)
+/**
+ * xe_vm_ops_execute() - Execute VMA ops
+ * @vm: The VM.
+ * @vops: VMA ops to execute
+ *
+ * Execute VMA ops binding / unbinding VMAs
+ *
+ * Return: A fence for VMA ops on success, ERR_PTR on failure
+ */
+struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops *vops)
 {
 	struct xe_vma_op *op, *next;
 	struct dma_fence *fence = NULL;
@@ -2832,7 +2854,7 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
 		if (err)
 			goto unlock;
 
-		fence = ops_execute(vm, vops);
+		fence = xe_vm_ops_execute(vm, vops);
 		if (IS_ERR(fence)) {
 			err = PTR_ERR(fence);
 			/* FIXME: Killing VM rather than proper error handling */
diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
index 6df1f1c7f85d..b40160b1be01 100644
--- a/drivers/gpu/drm/xe/xe_vm.h
+++ b/drivers/gpu/drm/xe/xe_vm.h
@@ -262,6 +262,9 @@ static inline struct dma_resv *xe_vm_resv(struct xe_vm *vm)
  */
 #define xe_vm_assert_held(vm) dma_resv_assert_held(xe_vm_resv(vm))
 
+void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma);
+struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops *vops);
+
 #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_VM)
 #define vm_dbg drm_dbg
 #else
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index f097fe318a74..0bba5543ac28 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -194,6 +194,8 @@ struct xe_vma_op {
 	struct list_head link;
 	/** @flags: operation flags */
 	enum xe_vma_op_flags flags;
+	/** @tile_mask: Tile mask for operation */
+	u8 tile_mask;
 
 	union {
 		/** @map: VMA map operation specific data */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 08/30] drm/xe: s/xe_tile_migrate_engine/xe_tile_migrate_exec_queue
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (6 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 07/30] drm/xe: Update pagefaults to use dummy VMA operations Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-25 16:05   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 09/30] drm/xe: Add some members to xe_vma_ops Matthew Brost
                   ` (28 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

xe_engine is now xe_exec_queue, adjust this function's name to reflect.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_gt_pagefault.c | 2 +-
 drivers/gpu/drm/xe/xe_migrate.c      | 8 ++++----
 drivers/gpu/drm/xe/xe_migrate.h      | 3 ++-
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c
index 3c7d6e4e3917..878e234166aa 100644
--- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
+++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
@@ -210,7 +210,7 @@ static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf)
 	trace_xe_vma_pf_bind(vma);
 	xe_vm_populate_dummy_rebind(vm, vma);
 	vm->dummy_ops.op.tile_mask = BIT(tile->id);
-	vm->dummy_ops.op.q = xe_tile_migrate_engine(tile);
+	vm->dummy_ops.op.q = xe_tile_migrate_exec_queue(tile);
 	fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
 	if (IS_ERR(fence)) {
 		ret = PTR_ERR(fence);
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index ee1bb938c493..3fd76f912fda 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -84,15 +84,15 @@ struct xe_migrate {
 #define MAX_PTE_PER_SDI 0x1FE
 
 /**
- * xe_tile_migrate_engine() - Get this tile's migrate engine.
+ * xe_tile_migrate_exec_queue() - Get this tile's migrate exec queue.
  * @tile: The tile.
  *
- * Returns the default migrate engine of this tile.
+ * Returns the default migrate exec queue of this tile.
  * TODO: Perhaps this function is slightly misplaced, and even unneeded?
  *
- * Return: The default migrate engine
+ * Return: The default migrate exec queue
  */
-struct xe_exec_queue *xe_tile_migrate_engine(struct xe_tile *tile)
+struct xe_exec_queue *xe_tile_migrate_exec_queue(struct xe_tile *tile)
 {
 	return tile->migrate->q;
 }
diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h
index 951f19318ea4..9935ce336bae 100644
--- a/drivers/gpu/drm/xe/xe_migrate.h
+++ b/drivers/gpu/drm/xe/xe_migrate.h
@@ -106,5 +106,6 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
 
 void xe_migrate_wait(struct xe_migrate *m);
 
-struct xe_exec_queue *xe_tile_migrate_engine(struct xe_tile *tile);
+struct xe_exec_queue *xe_tile_migrate_exec_queue(struct xe_tile *tile);
+
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 09/30] drm/xe: Add some members to xe_vma_ops
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (7 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 08/30] drm/xe: s/xe_tile_migrate_engine/xe_tile_migrate_exec_queue Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-25 16:10   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 10/30] drm/xe: Add vm_bind_ioctl_ops_install_fences helper Matthew Brost
                   ` (27 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

This will help with moving to single jobs for many bind operations.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c       | 13 ++++++++++---
 drivers/gpu/drm/xe/xe_vm_types.h |  8 ++++++++
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index a6bae2f5e296..f8b27746e5a7 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1307,9 +1307,16 @@ static void xe_vm_free_scratch(struct xe_vm *vm)
 	}
 }
 
-static void xe_vma_ops_init(struct xe_vma_ops *vops)
+static void xe_vma_ops_init(struct xe_vma_ops *vops, struct xe_vm *vm,
+			    struct xe_exec_queue *q,
+			    struct xe_sync_entry *syncs, u32 num_syncs)
 {
+	memset(vops, 0, sizeof(*vops));
 	INIT_LIST_HEAD(&vops->list);
+	vops->vm = vm;
+	vops->q = q;
+	vops->syncs = syncs;
+	vops->num_syncs = num_syncs;
 }
 
 struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
@@ -1333,7 +1340,7 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
 	init_rwsem(&vm->lock);
 	mutex_init(&vm->snap_mutex);
 
-	xe_vma_ops_init(&vm->dummy_ops.vops);
+	xe_vma_ops_init(&vm->dummy_ops.vops, vm, NULL, NULL, 0);
 	INIT_LIST_HEAD(&vm->dummy_ops.op.link);
 	list_add(&vm->dummy_ops.op.link, &vm->dummy_ops.vops.list);
 
@@ -3176,7 +3183,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 		goto free_syncs;
 	}
 
-	xe_vma_ops_init(&vops);
+	xe_vma_ops_init(&vops, vm, q, syncs, num_syncs);
 	for (i = 0; i < args->num_binds; ++i) {
 		u64 range = bind_ops[i].range;
 		u64 addr = bind_ops[i].addr;
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index 0bba5543ac28..f6ea4df64e79 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -211,6 +211,14 @@ struct xe_vma_op {
 struct xe_vma_ops {
 	/** @list: list of VMA operations */
 	struct list_head list;
+	/** @vm: VM */
+	struct xe_vm *vm;
+	/** @q: exec queue these operations */
+	struct xe_exec_queue *q;
+	/** @syncs: syncs these operation */
+	struct xe_sync_entry *syncs;
+	/** @num_syncs: number of syncs */
+	u32 num_syncs;
 };
 
 struct xe_vm {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 10/30] drm/xe: Add vm_bind_ioctl_ops_install_fences helper
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (8 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 09/30] drm/xe: Add some members to xe_vma_ops Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-25 16:51   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 11/30] drm/xe: Move setting last fence to vm_bind_ioctl_ops_install_fences Matthew Brost
                   ` (26 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Simplify VM bind code by signaling out-fences / destroying VMAs in a
single location. Will help with transition single job for many bind ops.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c | 55 ++++++++++++++++----------------------
 1 file changed, 23 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index f8b27746e5a7..8c96c98cba37 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1658,7 +1658,7 @@ xe_vm_unbind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
 	struct dma_fence *fence = NULL;
 	struct dma_fence **fences = NULL;
 	struct dma_fence_array *cf = NULL;
-	int cur_fence = 0, i;
+	int cur_fence = 0;
 	int number_tiles = hweight8(vma->tile_present);
 	int err;
 	u8 id;
@@ -1716,10 +1716,6 @@ xe_vm_unbind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
 
 	fence = cf ? &cf->base : !fence ?
 		xe_exec_queue_last_fence_get(wait_exec_queue, vm) : fence;
-	if (last_op) {
-		for (i = 0; i < num_syncs; i++)
-			xe_sync_entry_signal(&syncs[i], NULL, fence);
-	}
 
 	return fence;
 
@@ -1743,7 +1739,7 @@ xe_vm_bind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
 	struct dma_fence **fences = NULL;
 	struct dma_fence_array *cf = NULL;
 	struct xe_vm *vm = xe_vma_vm(vma);
-	int cur_fence = 0, i;
+	int cur_fence = 0;
 	int number_tiles = hweight8(vma->tile_mask);
 	int err;
 	u8 id;
@@ -1790,12 +1786,6 @@ xe_vm_bind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
 		}
 	}
 
-	if (last_op) {
-		for (i = 0; i < num_syncs; i++)
-			xe_sync_entry_signal(&syncs[i], NULL,
-					     cf ? &cf->base : fence);
-	}
-
 	return cf ? &cf->base : fence;
 
 err_fences:
@@ -1847,15 +1837,8 @@ xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue *q,
 		if (IS_ERR(fence))
 			return fence;
 	} else {
-		int i;
-
 		xe_assert(vm->xe, xe_vm_in_fault_mode(vm));
-
 		fence = xe_exec_queue_last_fence_get(wait_exec_queue, vm);
-		if (last_op) {
-			for (i = 0; i < num_syncs; i++)
-				xe_sync_entry_signal(&syncs[i], NULL, fence);
-		}
 	}
 
 	if (last_op)
@@ -1879,7 +1862,6 @@ xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
 	if (IS_ERR(fence))
 		return fence;
 
-	xe_vma_destroy(vma, fence);
 	if (last_op)
 		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
 
@@ -2037,17 +2019,7 @@ xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
 		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs, num_syncs,
 				  vma->tile_mask, true, first_op, last_op);
 	} else {
-		struct dma_fence *fence =
-			xe_exec_queue_last_fence_get(wait_exec_queue, vm);
-		int i;
-
-		/* Nothing to do, signal fences now */
-		if (last_op) {
-			for (i = 0; i < num_syncs; i++)
-				xe_sync_entry_signal(&syncs[i], NULL, fence);
-		}
-
-		return fence;
+		return xe_exec_queue_last_fence_get(wait_exec_queue, vm);
 	}
 }
 
@@ -2844,6 +2816,25 @@ struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops *vops)
 	return fence;
 }
 
+static void vm_bind_ioctl_ops_install_fences(struct xe_vm *vm,
+					     struct xe_vma_ops *vops,
+					     struct dma_fence *fence)
+{
+	struct xe_vma_op *op;
+	int i;
+
+	list_for_each_entry(op, &vops->list, link) {
+		if (op->base.op == DRM_GPUVA_OP_UNMAP)
+			xe_vma_destroy(gpuva_to_vma(op->base.unmap.va), fence);
+		else if (op->base.op == DRM_GPUVA_OP_REMAP)
+			xe_vma_destroy(gpuva_to_vma(op->base.remap.unmap->va),
+				       fence);
+	}
+	for (i = 0; i < vops->num_syncs; i++)
+		xe_sync_entry_signal(vops->syncs + i, NULL, fence);
+	dma_fence_put(fence);
+}
+
 static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
 				     struct xe_vma_ops *vops)
 {
@@ -2868,7 +2859,7 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
 			xe_vm_kill(vm, false);
 			goto unlock;
 		} else {
-			dma_fence_put(fence);
+			vm_bind_ioctl_ops_install_fences(vm, vops, fence);
 		}
 	}
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 11/30] drm/xe: Move setting last fence to vm_bind_ioctl_ops_install_fences
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (9 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 10/30] drm/xe: Add vm_bind_ioctl_ops_install_fences helper Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-25 17:02   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 12/30] drm/xe: Move ufence check to op_lock Matthew Brost
                   ` (25 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

This moves setting of the last fence to a single location.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 8c96c98cba37..4432531f39fe 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1841,9 +1841,6 @@ xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue *q,
 		fence = xe_exec_queue_last_fence_get(wait_exec_queue, vm);
 	}
 
-	if (last_op)
-		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
-
 	return fence;
 }
 
@@ -1853,7 +1850,6 @@ xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
 	     u32 num_syncs, bool first_op, bool last_op)
 {
 	struct dma_fence *fence;
-	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, q);
 
 	xe_vm_assert_held(vm);
 	xe_bo_assert_held(xe_vma_bo(vma));
@@ -1862,9 +1858,6 @@ xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
 	if (IS_ERR(fence))
 		return fence;
 
-	if (last_op)
-		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
-
 	return fence;
 }
 
@@ -2820,6 +2813,7 @@ static void vm_bind_ioctl_ops_install_fences(struct xe_vm *vm,
 					     struct xe_vma_ops *vops,
 					     struct dma_fence *fence)
 {
+	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, vops->q);
 	struct xe_vma_op *op;
 	int i;
 
@@ -2832,6 +2826,7 @@ static void vm_bind_ioctl_ops_install_fences(struct xe_vm *vm,
 	}
 	for (i = 0; i < vops->num_syncs; i++)
 		xe_sync_entry_signal(vops->syncs + i, NULL, fence);
+	xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
 	dma_fence_put(fence);
 }
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 12/30] drm/xe: Move ufence check to op_lock
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (10 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 11/30] drm/xe: Move setting last fence to vm_bind_ioctl_ops_install_fences Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-25 20:37   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 13/30] drm/xe: Move ufence add to vm_bind_ioctl_ops_install_fences Matthew Brost
                   ` (24 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Rather than checking for an unsignaled ufence ay unbind time, check for
this during the op_lock function. This will help with the transition to
job 1 per VM bind IOCTL.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c | 33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 4432531f39fe..5767955529dd 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1665,16 +1665,6 @@ xe_vm_unbind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
 
 	trace_xe_vma_unbind(vma);
 
-	if (vma->ufence) {
-		struct xe_user_fence * const f = vma->ufence;
-
-		if (!xe_sync_ufence_get_status(f))
-			return ERR_PTR(-EBUSY);
-
-		vma->ufence = NULL;
-		xe_sync_ufence_put(f);
-	}
-
 	if (number_tiles > 1) {
 		fences = kmalloc_array(number_tiles, sizeof(*fences),
 				       GFP_KERNEL);
@@ -2721,6 +2711,21 @@ static int vma_lock(struct drm_exec *exec, struct xe_vma *vma, bool validate)
 	return err;
 }
 
+static int check_ufence(struct xe_vma *vma)
+{
+	if (vma->ufence) {
+		struct xe_user_fence * const f = vma->ufence;
+
+		if (!xe_sync_ufence_get_status(f))
+			return -EBUSY;
+
+		vma->ufence = NULL;
+		xe_sync_ufence_put(f);
+	}
+
+	return 0;
+}
+
 static int op_lock(struct drm_exec *exec, struct xe_vm *vm,
 		   struct xe_vma_op *op)
 {
@@ -2731,6 +2736,10 @@ static int op_lock(struct drm_exec *exec, struct xe_vm *vm,
 		err = vma_lock(exec, op->map.vma, !xe_vm_in_fault_mode(vm));
 		break;
 	case DRM_GPUVA_OP_REMAP:
+		err = check_ufence(gpuva_to_vma(op->base.remap.unmap->va));
+		if (err)
+			break;
+
 		err = vma_lock(exec, gpuva_to_vma(op->base.remap.unmap->va),
 			       false);
 		if (!err && op->remap.prev)
@@ -2739,6 +2748,10 @@ static int op_lock(struct drm_exec *exec, struct xe_vm *vm,
 			err = vma_lock(exec, op->remap.next, true);
 		break;
 	case DRM_GPUVA_OP_UNMAP:
+		err = check_ufence(gpuva_to_vma(op->base.unmap.va));
+		if (err)
+			break;
+
 		err = vma_lock(exec, gpuva_to_vma(op->base.unmap.va), false);
 		break;
 	case DRM_GPUVA_OP_PREFETCH:
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 13/30] drm/xe: Move ufence add to vm_bind_ioctl_ops_install_fences
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (11 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 12/30] drm/xe: Move ufence check to op_lock Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-25 20:54   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 14/30] drm/xe: Add xe_gt_tlb_invalidation_range and convert PT layer to use this Matthew Brost
                   ` (23 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Rather than adding a ufence to a VMA in the bind function, add the
ufence to all VMAs in the IOCTL that require binds in
vm_bind_ioctl_ops_install_fences. This will help with the transition to
job 1 per VM bind IOCTL.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_sync.c | 15 ++++++++++++
 drivers/gpu/drm/xe/xe_sync.h |  1 +
 drivers/gpu/drm/xe/xe_vm.c   | 44 ++++++++++++++++++++++++++++++------
 3 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_sync.c b/drivers/gpu/drm/xe/xe_sync.c
index 02c9577fe418..07aa65d9bcab 100644
--- a/drivers/gpu/drm/xe/xe_sync.c
+++ b/drivers/gpu/drm/xe/xe_sync.c
@@ -343,6 +343,21 @@ xe_sync_in_fence_get(struct xe_sync_entry *sync, int num_sync,
 	return ERR_PTR(-ENOMEM);
 }
 
+/**
+ * __xe_sync_ufence_get() - Get user fence from user fence
+ * @ufence: input user fence
+ *
+ * Get a user fence reference from user fence
+ *
+ * Return: xe_user_fence pointer with reference
+ */
+struct xe_user_fence *__xe_sync_ufence_get(struct xe_user_fence *ufence)
+{
+	user_fence_get(ufence);
+
+	return ufence;
+}
+
 /**
  * xe_sync_ufence_get() - Get user fence from sync
  * @sync: input sync
diff --git a/drivers/gpu/drm/xe/xe_sync.h b/drivers/gpu/drm/xe/xe_sync.h
index 0fd0d51208e6..26e9ec9de1a8 100644
--- a/drivers/gpu/drm/xe/xe_sync.h
+++ b/drivers/gpu/drm/xe/xe_sync.h
@@ -38,6 +38,7 @@ static inline bool xe_sync_is_ufence(struct xe_sync_entry *sync)
 	return !!sync->ufence;
 }
 
+struct xe_user_fence *__xe_sync_ufence_get(struct xe_user_fence *ufence);
 struct xe_user_fence *xe_sync_ufence_get(struct xe_sync_entry *sync);
 void xe_sync_ufence_put(struct xe_user_fence *ufence);
 int xe_sync_ufence_get_status(struct xe_user_fence *ufence);
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 5767955529dd..5b93c71fc5e9 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1810,17 +1810,10 @@ xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue *q,
 {
 	struct dma_fence *fence;
 	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, q);
-	struct xe_user_fence *ufence;
 
 	xe_vm_assert_held(vm);
 	xe_bo_assert_held(bo);
 
-	ufence = find_ufence_get(syncs, num_syncs);
-	if (vma->ufence && ufence)
-		xe_sync_ufence_put(vma->ufence);
-
-	vma->ufence = ufence ?: vma->ufence;
-
 	if (immediate) {
 		fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, tile_mask,
 				       first_op, last_op);
@@ -2822,21 +2815,58 @@ struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops *vops)
 	return fence;
 }
 
+static void vma_add_ufence(struct xe_vma *vma, struct xe_user_fence *ufence)
+{
+	if (vma->ufence)
+		xe_sync_ufence_put(vma->ufence);
+	vma->ufence = __xe_sync_ufence_get(ufence);
+}
+
+static void op_add_ufence(struct xe_vm *vm, struct xe_vma_op *op,
+			  struct xe_user_fence *ufence)
+{
+	switch (op->base.op) {
+	case DRM_GPUVA_OP_MAP:
+		vma_add_ufence(op->map.vma, ufence);
+		break;
+	case DRM_GPUVA_OP_REMAP:
+		if (op->remap.prev)
+			vma_add_ufence(op->remap.prev, ufence);
+		if (op->remap.next)
+			vma_add_ufence(op->remap.next, ufence);
+		break;
+	case DRM_GPUVA_OP_UNMAP:
+		break;
+	case DRM_GPUVA_OP_PREFETCH:
+		vma_add_ufence(gpuva_to_vma(op->base.prefetch.va), ufence);
+		break;
+	default:
+		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
+	}
+}
+
 static void vm_bind_ioctl_ops_install_fences(struct xe_vm *vm,
 					     struct xe_vma_ops *vops,
 					     struct dma_fence *fence)
 {
 	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, vops->q);
+	struct xe_user_fence *ufence;
 	struct xe_vma_op *op;
 	int i;
 
+	ufence = find_ufence_get(vops->syncs, vops->num_syncs);
 	list_for_each_entry(op, &vops->list, link) {
+		if (ufence)
+			op_add_ufence(vm, op, ufence);
+
 		if (op->base.op == DRM_GPUVA_OP_UNMAP)
 			xe_vma_destroy(gpuva_to_vma(op->base.unmap.va), fence);
 		else if (op->base.op == DRM_GPUVA_OP_REMAP)
 			xe_vma_destroy(gpuva_to_vma(op->base.remap.unmap->va),
 				       fence);
 	}
+	if (ufence)
+		xe_sync_ufence_put(ufence);
 	for (i = 0; i < vops->num_syncs; i++)
 		xe_sync_entry_signal(vops->syncs + i, NULL, fence);
 	xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 14/30] drm/xe: Add xe_gt_tlb_invalidation_range and convert PT layer to use this
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (12 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 13/30] drm/xe: Move ufence add to vm_bind_ioctl_ops_install_fences Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-25 21:35   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 15/30] drm/xe: Add xe_vm_pgtable_update_op to xe_vma_ops Matthew Brost
                   ` (22 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

xe_gt_tlb_invalidation_range accepts a start and end address rather than
a VMA. This will enable multiple VMAs to be invalidated in a single
invalidation. Update the PT layer to use this new function.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c | 59 +++++++++++++++------
 drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h |  3 ++
 drivers/gpu/drm/xe/xe_pt.c                  | 25 ++++++---
 3 files changed, 65 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
index a3c4ffba679d..ac2bf86de39a 100644
--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
+++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
@@ -264,11 +264,15 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt)
 }
 
 /**
- * xe_gt_tlb_invalidation_vma - Issue a TLB invalidation on this GT for a VMA
+ * xe_gt_tlb_invalidation_range - Issue a TLB invalidation on this GT for an
+ * address range
+ *
  * @gt: graphics tile
  * @fence: invalidation fence which will be signal on TLB invalidation
  * completion, can be NULL
- * @vma: VMA to invalidate
+ * @start: start address
+ * @end: end address
+ * @asid: address space id
  *
  * Issue a range based TLB invalidation if supported, if not fallback to a full
  * TLB invalidation. Completion of TLB is asynchronous and caller can either use
@@ -278,17 +282,15 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt)
  * Return: Seqno which can be passed to xe_gt_tlb_invalidation_wait on success,
  * negative error code on error.
  */
-int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
-			       struct xe_gt_tlb_invalidation_fence *fence,
-			       struct xe_vma *vma)
+int xe_gt_tlb_invalidation_range(struct xe_gt *gt,
+				 struct xe_gt_tlb_invalidation_fence *fence,
+				 u64 start, u64 end, u32 asid)
 {
 	struct xe_device *xe = gt_to_xe(gt);
 #define MAX_TLB_INVALIDATION_LEN	7
 	u32 action[MAX_TLB_INVALIDATION_LEN];
 	int len = 0;
 
-	xe_gt_assert(gt, vma);
-
 	/* Execlists not supported */
 	if (gt_to_xe(gt)->info.force_execlist) {
 		if (fence)
@@ -302,8 +304,8 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
 	if (!xe->info.has_range_tlb_invalidation) {
 		action[len++] = MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL);
 	} else {
-		u64 start = xe_vma_start(vma);
-		u64 length = xe_vma_size(vma);
+		u64 orig_start = start;
+		u64 length = end - start;
 		u64 align, end;
 
 		if (length < SZ_4K)
@@ -316,12 +318,12 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
 		 * address mask covering the required range.
 		 */
 		align = roundup_pow_of_two(length);
-		start = ALIGN_DOWN(xe_vma_start(vma), align);
-		end = ALIGN(xe_vma_end(vma), align);
+		start = ALIGN_DOWN(start, align);
+		end = ALIGN(end, align);
 		length = align;
 		while (start + length < end) {
 			length <<= 1;
-			start = ALIGN_DOWN(xe_vma_start(vma), length);
+			start = ALIGN_DOWN(orig_start, length);
 		}
 
 		/*
@@ -330,16 +332,17 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
 		 */
 		if (length >= SZ_2M) {
 			length = max_t(u64, SZ_16M, length);
-			start = ALIGN_DOWN(xe_vma_start(vma), length);
+			start = ALIGN_DOWN(orig_start, length);
 		}
 
 		xe_gt_assert(gt, length >= SZ_4K);
 		xe_gt_assert(gt, is_power_of_2(length));
-		xe_gt_assert(gt, !(length & GENMASK(ilog2(SZ_16M) - 1, ilog2(SZ_2M) + 1)));
+		xe_gt_assert(gt, !(length & GENMASK(ilog2(SZ_16M) - 1,
+						    ilog2(SZ_2M) + 1)));
 		xe_gt_assert(gt, IS_ALIGNED(start, length));
 
 		action[len++] = MAKE_INVAL_OP(XE_GUC_TLB_INVAL_PAGE_SELECTIVE);
-		action[len++] = xe_vma_vm(vma)->usm.asid;
+		action[len++] = asid;
 		action[len++] = lower_32_bits(start);
 		action[len++] = upper_32_bits(start);
 		action[len++] = ilog2(length) - ilog2(SZ_4K);
@@ -350,6 +353,32 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
 	return send_tlb_invalidation(&gt->uc.guc, fence, action, len);
 }
 
+/**
+ * xe_gt_tlb_invalidation_vma - Issue a TLB invalidation on this GT for a VMA
+ * @gt: graphics tile
+ * @fence: invalidation fence which will be signal on TLB invalidation
+ * completion, can be NULL
+ * @vma: VMA to invalidate
+ *
+ * Issue a range based TLB invalidation if supported, if not fallback to a full
+ * TLB invalidation. Completion of TLB is asynchronous and caller can either use
+ * the invalidation fence or seqno + xe_gt_tlb_invalidation_wait to wait for
+ * completion.
+ *
+ * Return: Seqno which can be passed to xe_gt_tlb_invalidation_wait on success,
+ * negative error code on error.
+ */
+int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
+			       struct xe_gt_tlb_invalidation_fence *fence,
+			       struct xe_vma *vma)
+{
+	xe_gt_assert(gt, vma);
+
+	return xe_gt_tlb_invalidation_range(gt, fence, xe_vma_start(vma),
+					    xe_vma_end(vma),
+					    xe_vma_vm(vma)->usm.asid);
+}
+
 /**
  * xe_gt_tlb_invalidation_wait - Wait for TLB to complete
  * @gt: graphics tile
diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
index fbb743d80d2c..bf3bebd9f985 100644
--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
+++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
@@ -20,6 +20,9 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt);
 int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
 			       struct xe_gt_tlb_invalidation_fence *fence,
 			       struct xe_vma *vma);
+int xe_gt_tlb_invalidation_range(struct xe_gt *gt,
+				 struct xe_gt_tlb_invalidation_fence *fence,
+				 u64 start, u64 end, u32 asid);
 int xe_gt_tlb_invalidation_wait(struct xe_gt *gt, int seqno);
 int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len);
 
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 7f54bc3e389d..110d6917089b 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -1074,10 +1074,12 @@ static const struct xe_migrate_pt_update_ops userptr_bind_ops = {
 struct invalidation_fence {
 	struct xe_gt_tlb_invalidation_fence base;
 	struct xe_gt *gt;
-	struct xe_vma *vma;
 	struct dma_fence *fence;
 	struct dma_fence_cb cb;
 	struct work_struct work;
+	u64 start;
+	u64 end;
+	u32 asid;
 };
 
 static const char *
@@ -1120,13 +1122,14 @@ static void invalidation_fence_work_func(struct work_struct *w)
 		container_of(w, struct invalidation_fence, work);
 
 	trace_xe_gt_tlb_invalidation_fence_work_func(&ifence->base);
-	xe_gt_tlb_invalidation_vma(ifence->gt, &ifence->base, ifence->vma);
+	xe_gt_tlb_invalidation_range(ifence->gt, &ifence->base, ifence->start,
+				     ifence->end, ifence->asid);
 }
 
 static int invalidation_fence_init(struct xe_gt *gt,
 				   struct invalidation_fence *ifence,
 				   struct dma_fence *fence,
-				   struct xe_vma *vma)
+				   u64 start, u64 end, u32 asid)
 {
 	int ret;
 
@@ -1144,7 +1147,9 @@ static int invalidation_fence_init(struct xe_gt *gt,
 	dma_fence_get(&ifence->base.base);	/* Ref for caller */
 	ifence->fence = fence;
 	ifence->gt = gt;
-	ifence->vma = vma;
+	ifence->start = start;
+	ifence->end = end;
+	ifence->asid = asid;
 
 	INIT_WORK(&ifence->work, invalidation_fence_work_func);
 	ret = dma_fence_add_callback(fence, &ifence->cb, invalidation_fence_cb);
@@ -1286,8 +1291,11 @@ __xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue
 
 		/* TLB invalidation must be done before signaling rebind */
 		if (ifence) {
-			int err = invalidation_fence_init(tile->primary_gt, ifence, fence,
-							  vma);
+			int err = invalidation_fence_init(tile->primary_gt,
+							  ifence, fence,
+							  xe_vma_start(vma),
+							  xe_vma_end(vma),
+							  xe_vma_vm(vma)->usm.asid);
 			if (err) {
 				dma_fence_put(fence);
 				kfree(ifence);
@@ -1625,7 +1633,10 @@ __xe_pt_unbind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queu
 			dma_fence_wait(fence, false);
 
 		/* TLB invalidation must be done before signaling unbind */
-		err = invalidation_fence_init(tile->primary_gt, ifence, fence, vma);
+		err = invalidation_fence_init(tile->primary_gt, ifence, fence,
+					      xe_vma_start(vma),
+					      xe_vma_end(vma),
+					      xe_vma_vm(vma)->usm.asid);
 		if (err) {
 			dma_fence_put(fence);
 			kfree(ifence);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 15/30] drm/xe: Add xe_vm_pgtable_update_op to xe_vma_ops
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (13 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 14/30] drm/xe: Add xe_gt_tlb_invalidation_range and convert PT layer to use this Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-25 21:58   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 16/30] drm/xe: Use ordered WQ for TLB invalidation fences Matthew Brost
                   ` (21 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Will help with the converstion to 1 job per VM bind IOCTL. Allocation
only implemented in this patch.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_pt_types.h | 12 ++++++
 drivers/gpu/drm/xe/xe_vm.c       | 66 +++++++++++++++++++++++++++++---
 drivers/gpu/drm/xe/xe_vm_types.h |  8 ++++
 3 files changed, 81 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_pt_types.h b/drivers/gpu/drm/xe/xe_pt_types.h
index cee70cb0f014..2093150f461e 100644
--- a/drivers/gpu/drm/xe/xe_pt_types.h
+++ b/drivers/gpu/drm/xe/xe_pt_types.h
@@ -74,4 +74,16 @@ struct xe_vm_pgtable_update {
 	u32 flags;
 };
 
+/** struct xe_vm_pgtable_update_op - Page table update operation */
+struct xe_vm_pgtable_update_op {
+	/** @entries: entries to update for this operation */
+	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
+	/** @num_entries: number of entries for this update operation */
+	u32 num_entries;
+	/** @bind: is a bind */
+	bool bind;
+	/** @rebind: is a rebind */
+	bool rebind;
+};
+
 #endif
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 5b93c71fc5e9..72e9bdab79d5 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1319,6 +1319,42 @@ static void xe_vma_ops_init(struct xe_vma_ops *vops, struct xe_vm *vm,
 	vops->num_syncs = num_syncs;
 }
 
+static int xe_vma_ops_alloc(struct xe_vma_ops *vops)
+{
+	int i;
+
+	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) {
+		if (!vops->pt_update_ops[i].num_ops)
+			continue;
+
+		vops->pt_update_ops[i].ops =
+			kmalloc_array(vops->pt_update_ops[i].num_ops,
+				      sizeof(*vops->pt_update_ops[i].ops),
+				      GFP_KERNEL);
+		if (!vops->pt_update_ops[i].ops)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void xe_vma_ops_fini(struct xe_vma_ops *vops)
+{
+	int i;
+
+	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i)
+		kfree(vops->pt_update_ops[i].ops);
+}
+
+static void xe_vma_ops_incr_pt_update_ops(struct xe_vma_ops *vops, u8 tile_mask)
+{
+	int i;
+
+	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i)
+		if (BIT(i) & tile_mask)
+			++vops->pt_update_ops[i].num_ops;
+}
+
 struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
 {
 	struct drm_gem_object *vm_resv_obj;
@@ -1343,6 +1379,11 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
 	xe_vma_ops_init(&vm->dummy_ops.vops, vm, NULL, NULL, 0);
 	INIT_LIST_HEAD(&vm->dummy_ops.op.link);
 	list_add(&vm->dummy_ops.op.link, &vm->dummy_ops.vops.list);
+	for (id = 0; id < XE_MAX_TILES_PER_DEVICE; ++id)
+		vm->dummy_ops.vops.pt_update_ops[id].num_ops = 1;
+	err = xe_vma_ops_alloc(&vm->dummy_ops.vops);
+	if (err)
+		goto err_free;
 
 	INIT_LIST_HEAD(&vm->rebind_list);
 
@@ -1468,12 +1509,14 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
 	return ERR_PTR(err);
 
 err_no_resv:
-	mutex_destroy(&vm->snap_mutex);
+	if (!(flags & XE_VM_FLAG_MIGRATION))
+		xe_device_mem_access_put(xe);
 	for_each_tile(tile, xe, id)
 		xe_range_fence_tree_fini(&vm->rftree[id]);
+err_free:
+	mutex_destroy(&vm->snap_mutex);
+	xe_vma_ops_fini(&vm->dummy_ops.vops);
 	kfree(vm);
-	if (!(flags & XE_VM_FLAG_MIGRATION))
-		xe_device_mem_access_put(xe);
 	return ERR_PTR(err);
 }
 
@@ -1611,6 +1654,7 @@ static void vm_destroy_work_func(struct work_struct *w)
 
 	trace_xe_vm_free(vm);
 	dma_fence_put(vm->rebind_fence);
+	xe_vma_ops_fini(&vm->dummy_ops.vops);
 	kfree(vm);
 }
 
@@ -2284,7 +2328,6 @@ static int xe_vma_op_commit(struct xe_vm *vm, struct xe_vma_op *op)
 	return err;
 }
 
-
 static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 				   struct drm_gpuva_ops *ops,
 				   struct xe_sync_entry *syncs, u32 num_syncs,
@@ -2334,6 +2377,9 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 				return PTR_ERR(vma);
 
 			op->map.vma = vma;
+			if (op->map.immediate || !xe_vm_in_fault_mode(vm))
+				xe_vma_ops_incr_pt_update_ops(vops,
+							      op->tile_mask);
 			break;
 		}
 		case DRM_GPUVA_OP_REMAP:
@@ -2378,6 +2424,8 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 					vm_dbg(&xe->drm, "REMAP:SKIP_PREV: addr=0x%016llx, range=0x%016llx",
 					       (ULL)op->remap.start,
 					       (ULL)op->remap.range);
+				} else {
+					xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask);
 				}
 			}
 
@@ -2414,13 +2462,16 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 					vm_dbg(&xe->drm, "REMAP:SKIP_NEXT: addr=0x%016llx, range=0x%016llx",
 					       (ULL)op->remap.start,
 					       (ULL)op->remap.range);
+				} else {
+					xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask);
 				}
 			}
+			xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask);
 			break;
 		}
 		case DRM_GPUVA_OP_UNMAP:
 		case DRM_GPUVA_OP_PREFETCH:
-			/* Nothing to do */
+			xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask);
 			break;
 		default:
 			drm_warn(&vm->xe->drm, "NOT POSSIBLE");
@@ -3243,11 +3294,16 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 		goto unwind_ops;
 	}
 
+	err = xe_vma_ops_alloc(&vops);
+	if (err)
+		goto unwind_ops;
+
 	err = vm_bind_ioctl_ops_execute(vm, &vops);
 
 unwind_ops:
 	if (err && err != -ENODATA)
 		vm_bind_ioctl_ops_unwind(vm, ops, args->num_binds);
+	xe_vma_ops_fini(&vops);
 	for (i = args->num_binds - 1; i >= 0; --i)
 		if (ops[i])
 			drm_gpuva_ops_free(&vm->gpuvm, ops[i]);
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index f6ea4df64e79..f5d740dcbba3 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -22,6 +22,7 @@ struct xe_device;
 struct xe_sync_entry;
 struct xe_user_fence;
 struct xe_vm;
+struct xe_vm_pgtable_update_op;
 
 #define XE_VMA_READ_ONLY	DRM_GPUVA_USERBITS
 #define XE_VMA_DESTROYED	(DRM_GPUVA_USERBITS << 1)
@@ -219,6 +220,13 @@ struct xe_vma_ops {
 	struct xe_sync_entry *syncs;
 	/** @num_syncs: number of syncs */
 	u32 num_syncs;
+	/** @pt_update_ops: page table update operations */
+	struct {
+		/** @ops: operations */
+		struct xe_vm_pgtable_update_op *ops;
+		/** @num_ops: number of operations */
+		u32 num_ops;
+	} pt_update_ops[XE_MAX_TILES_PER_DEVICE];
 };
 
 struct xe_vm {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 16/30] drm/xe: Use ordered WQ for TLB invalidation fences
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (14 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 15/30] drm/xe: Add xe_vm_pgtable_update_op to xe_vma_ops Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-25 22:30   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 17/30] drm/xe: Delete PT update selftest Matthew Brost
                   ` (20 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

TLB invalidation fences need to be ordered within an exec queue and if
an unordered WQ is used TLB invalidation fences could be reordered. Use
an ordered WQ to fix this.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_pt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 110d6917089b..a878e2217c7f 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -1107,7 +1107,7 @@ static void invalidation_fence_cb(struct dma_fence *fence,
 
 	trace_xe_gt_tlb_invalidation_fence_cb(&ifence->base);
 	if (!ifence->fence->error) {
-		queue_work(system_wq, &ifence->work);
+		queue_work(ifence->gt->ordered_wq, &ifence->work);
 	} else {
 		ifence->base.base.error = ifence->fence->error;
 		dma_fence_signal(&ifence->base.base);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 17/30] drm/xe: Delete PT update selftest
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (15 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 16/30] drm/xe: Use ordered WQ for TLB invalidation fences Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-25 22:31   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 18/30] drm/xe: Convert multiple bind ops into single job Matthew Brost
                   ` (19 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

IGTs (e.g. xe_vm) can provide the exact same coverage as the PT update
selftest. The PT update selftest is dependent on internal functions
which can change thus maintaining this test is costly and provide no
extra coverage. Delete this test.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/tests/xe_migrate.c | 86 ---------------------------
 1 file changed, 86 deletions(-)

diff --git a/drivers/gpu/drm/xe/tests/xe_migrate.c b/drivers/gpu/drm/xe/tests/xe_migrate.c
index ce531498f57f..de2c1b7ec371 100644
--- a/drivers/gpu/drm/xe/tests/xe_migrate.c
+++ b/drivers/gpu/drm/xe/tests/xe_migrate.c
@@ -62,36 +62,6 @@ static int run_sanity_job(struct xe_migrate *m, struct xe_device *xe,
 	return 0;
 }
 
-static void
-sanity_populate_cb(struct xe_migrate_pt_update *pt_update,
-		   struct xe_tile *tile, struct iosys_map *map, void *dst,
-		   u32 qword_ofs, u32 num_qwords,
-		   const struct xe_vm_pgtable_update *update)
-{
-	struct migrate_test_params *p =
-		to_migrate_test_params(xe_cur_kunit_priv(XE_TEST_LIVE_MIGRATE));
-	int i;
-	u64 *ptr = dst;
-	u64 value;
-
-	for (i = 0; i < num_qwords; i++) {
-		value = (qword_ofs + i - update->ofs) * 0x1111111111111111ULL;
-		if (map)
-			xe_map_wr(tile_to_xe(tile), map, (qword_ofs + i) *
-				  sizeof(u64), u64, value);
-		else
-			ptr[i] = value;
-	}
-
-	kunit_info(xe_cur_kunit(), "Used %s.\n", map ? "CPU" : "GPU");
-	if (p->force_gpu && map)
-		KUNIT_FAIL(xe_cur_kunit(), "GPU pagetable update used CPU.\n");
-}
-
-static const struct xe_migrate_pt_update_ops sanity_ops = {
-	.populate = sanity_populate_cb,
-};
-
 #define check(_retval, _expected, str, _test)				\
 	do { if ((_retval) != (_expected)) {				\
 			KUNIT_FAIL(_test, "Sanity check failed: " str	\
@@ -209,57 +179,6 @@ static void test_copy_vram(struct xe_migrate *m, struct xe_bo *bo,
 	test_copy(m, bo, test, region);
 }
 
-static void test_pt_update(struct xe_migrate *m, struct xe_bo *pt,
-			   struct kunit *test, bool force_gpu)
-{
-	struct xe_device *xe = tile_to_xe(m->tile);
-	struct dma_fence *fence;
-	u64 retval, expected;
-	ktime_t then, now;
-	int i;
-
-	struct xe_vm_pgtable_update update = {
-		.ofs = 1,
-		.qwords = 0x10,
-		.pt_bo = pt,
-	};
-	struct xe_migrate_pt_update pt_update = {
-		.ops = &sanity_ops,
-	};
-	struct migrate_test_params p = {
-		.base.id = XE_TEST_LIVE_MIGRATE,
-		.force_gpu = force_gpu,
-	};
-
-	test->priv = &p;
-	/* Test xe_migrate_update_pgtables() updates the pagetable as expected */
-	expected = 0xf0f0f0f0f0f0f0f0ULL;
-	xe_map_memset(xe, &pt->vmap, 0, (u8)expected, pt->size);
-
-	then = ktime_get();
-	fence = xe_migrate_update_pgtables(m, m->q->vm, NULL, m->q, &update, 1,
-					   NULL, 0, &pt_update);
-	now = ktime_get();
-	if (sanity_fence_failed(xe, fence, "Migration pagetable update", test))
-		return;
-
-	kunit_info(test, "Updating without syncing took %llu us,\n",
-		   (unsigned long long)ktime_to_us(ktime_sub(now, then)));
-
-	dma_fence_put(fence);
-	retval = xe_map_rd(xe, &pt->vmap, 0, u64);
-	check(retval, expected, "PTE[0] must stay untouched", test);
-
-	for (i = 0; i < update.qwords; i++) {
-		retval = xe_map_rd(xe, &pt->vmap, (update.ofs + i) * 8, u64);
-		check(retval, i * 0x1111111111111111ULL, "PTE update", test);
-	}
-
-	retval = xe_map_rd(xe, &pt->vmap, 8 * (update.ofs + update.qwords),
-			   u64);
-	check(retval, expected, "PTE[0x11] must stay untouched", test);
-}
-
 static void xe_migrate_sanity_test(struct xe_migrate *m, struct kunit *test)
 {
 	struct xe_tile *tile = m->tile;
@@ -398,11 +317,6 @@ static void xe_migrate_sanity_test(struct xe_migrate *m, struct kunit *test)
 		test_copy_vram(m, big, test);
 	}
 
-	kunit_info(test, "Testing page table update using CPU if GPU idle.\n");
-	test_pt_update(m, pt, test, false);
-	kunit_info(test, "Testing page table update using GPU\n");
-	test_pt_update(m, pt, test, true);
-
 out:
 	xe_bb_free(bb, NULL);
 free_tiny:
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 18/30] drm/xe: Convert multiple bind ops into single job
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (16 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 17/30] drm/xe: Delete PT update selftest Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-27  2:40   ` Zeng, Oak
  2024-03-08  5:07 ` [PATCH v4 19/30] drm/xe: Remove old functions defs in xe_pt.h Matthew Brost
                   ` (18 subsequent siblings)
  36 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

This aligns with the uAPI of an array of binds or single bind that
results in multiple GPUVA ops to be considered a single atomic
operations.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_bo_types.h     |    2 +
 drivers/gpu/drm/xe/xe_exec.c         |   25 +-
 drivers/gpu/drm/xe/xe_gt_pagefault.c |    6 +-
 drivers/gpu/drm/xe/xe_migrate.c      |  298 ++++----
 drivers/gpu/drm/xe/xe_migrate.h      |   32 +-
 drivers/gpu/drm/xe/xe_pt.c           | 1018 ++++++++++++++++----------
 drivers/gpu/drm/xe/xe_pt.h           |    7 +
 drivers/gpu/drm/xe/xe_pt_types.h     |   34 +
 drivers/gpu/drm/xe/xe_vm.c           |  533 ++++----------
 drivers/gpu/drm/xe/xe_vm.h           |    5 +-
 drivers/gpu/drm/xe/xe_vm_types.h     |   29 +-
 11 files changed, 969 insertions(+), 1020 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h
index 14ef13b7b421..1ff5b5a68adc 100644
--- a/drivers/gpu/drm/xe/xe_bo_types.h
+++ b/drivers/gpu/drm/xe/xe_bo_types.h
@@ -77,6 +77,8 @@ struct xe_bo {
 	} props;
 	/** @freed: List node for delayed put. */
 	struct llist_node freed;
+	/** @update_index: Update index if PT BO */
+	int update_index;
 	/** @created: Whether the bo has passed initial creation */
 	bool created;
 
diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
index 952496c6260d..4feff67620c4 100644
--- a/drivers/gpu/drm/xe/xe_exec.c
+++ b/drivers/gpu/drm/xe/xe_exec.c
@@ -294,30 +294,9 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 		err = PTR_ERR(rebind_fence);
 		goto err_put_job;
 	}
+	dma_fence_put(rebind_fence);
 
-	/*
-	 * We store the rebind_fence in the VM so subsequent execs don't get
-	 * scheduled before the rebinds of userptrs / evicted BOs is complete.
-	 */
-	if (rebind_fence) {
-		dma_fence_put(vm->rebind_fence);
-		vm->rebind_fence = rebind_fence;
-	}
-	if (vm->rebind_fence) {
-		if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
-			     &vm->rebind_fence->flags)) {
-			dma_fence_put(vm->rebind_fence);
-			vm->rebind_fence = NULL;
-		} else {
-			dma_fence_get(vm->rebind_fence);
-			err = drm_sched_job_add_dependency(&job->drm,
-							   vm->rebind_fence);
-			if (err)
-				goto err_put_job;
-		}
-	}
-
-	/* Wait behind munmap style rebinds */
+	/* Wait for rebinds */
 	if (!xe_vm_in_lr_mode(vm)) {
 		err = drm_sched_job_add_resv_dependencies(&job->drm,
 							  xe_vm_resv(vm),
diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c
index 878e234166aa..bd8688b2f462 100644
--- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
+++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
@@ -208,9 +208,9 @@ static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf)
 
 	/* Bind VMA only to the GT that has faulted */
 	trace_xe_vma_pf_bind(vma);
-	xe_vm_populate_dummy_rebind(vm, vma);
-	vm->dummy_ops.op.tile_mask = BIT(tile->id);
-	vm->dummy_ops.op.q = xe_tile_migrate_exec_queue(tile);
+	xe_vm_populate_dummy_rebind(vm, vma, BIT(tile->id));
+	vm->dummy_ops.vops.pt_update_ops[tile->id].q =
+		xe_tile_migrate_exec_queue(tile);
 	fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
 	if (IS_ERR(fence)) {
 		ret = PTR_ERR(fence);
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index 3fd76f912fda..cc0499f3702c 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -1106,6 +1106,7 @@ struct dma_fence *xe_migrate_clear(struct xe_migrate *m,
 }
 
 static void write_pgtable(struct xe_tile *tile, struct xe_bb *bb, u64 ppgtt_ofs,
+			  const struct xe_vm_pgtable_update_op *pt_op,
 			  const struct xe_vm_pgtable_update *update,
 			  struct xe_migrate_pt_update *pt_update)
 {
@@ -1140,8 +1141,12 @@ static void write_pgtable(struct xe_tile *tile, struct xe_bb *bb, u64 ppgtt_ofs,
 		bb->cs[bb->len++] = MI_STORE_DATA_IMM | MI_SDI_NUM_QW(chunk);
 		bb->cs[bb->len++] = lower_32_bits(addr);
 		bb->cs[bb->len++] = upper_32_bits(addr);
-		ops->populate(pt_update, tile, NULL, bb->cs + bb->len, ofs, chunk,
-			      update);
+		if (pt_op->bind)
+			ops->populate(pt_update, tile, NULL, bb->cs + bb->len,
+				      ofs, chunk, update);
+		else
+			ops->clear(pt_update, tile, NULL, bb->cs + bb->len,
+				   ofs, chunk, update);
 
 		bb->len += chunk * 2;
 		ofs += chunk;
@@ -1166,114 +1171,58 @@ struct migrate_test_params {
 
 static struct dma_fence *
 xe_migrate_update_pgtables_cpu(struct xe_migrate *m,
-			       struct xe_vm *vm, struct xe_bo *bo,
-			       const struct  xe_vm_pgtable_update *updates,
-			       u32 num_updates, bool wait_vm,
 			       struct xe_migrate_pt_update *pt_update)
 {
 	XE_TEST_DECLARE(struct migrate_test_params *test =
 			to_migrate_test_params
 			(xe_cur_kunit_priv(XE_TEST_LIVE_MIGRATE));)
 	const struct xe_migrate_pt_update_ops *ops = pt_update->ops;
-	struct dma_fence *fence;
+	struct xe_vm *vm = pt_update->vops->vm;
+	struct xe_vm_pgtable_update_ops *pt_update_ops =
+		&pt_update->vops->pt_update_ops[pt_update->tile_id];
 	int err;
-	u32 i;
+	u32 j, i;
 
 	if (XE_TEST_ONLY(test && test->force_gpu))
 		return ERR_PTR(-ETIME);
 
-	if (bo && !dma_resv_test_signaled(bo->ttm.base.resv,
-					  DMA_RESV_USAGE_KERNEL))
-		return ERR_PTR(-ETIME);
-
-	if (wait_vm && !dma_resv_test_signaled(xe_vm_resv(vm),
-					       DMA_RESV_USAGE_BOOKKEEP))
-		return ERR_PTR(-ETIME);
-
 	if (ops->pre_commit) {
 		pt_update->job = NULL;
 		err = ops->pre_commit(pt_update);
 		if (err)
 			return ERR_PTR(err);
 	}
-	for (i = 0; i < num_updates; i++) {
-		const struct xe_vm_pgtable_update *update = &updates[i];
-
-		ops->populate(pt_update, m->tile, &update->pt_bo->vmap, NULL,
-			      update->ofs, update->qwords, update);
-	}
-
-	if (vm) {
-		trace_xe_vm_cpu_bind(vm);
-		xe_device_wmb(vm->xe);
-	}
-
-	fence = dma_fence_get_stub();
-
-	return fence;
-}
-
-static bool no_in_syncs(struct xe_vm *vm, struct xe_exec_queue *q,
-			struct xe_sync_entry *syncs, u32 num_syncs)
-{
-	struct dma_fence *fence;
-	int i;
 
-	for (i = 0; i < num_syncs; i++) {
-		fence = syncs[i].fence;
-
-		if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
-				       &fence->flags))
-			return false;
-	}
-	if (q) {
-		fence = xe_exec_queue_last_fence_get(q, vm);
-		if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
-			dma_fence_put(fence);
-			return false;
+	for (j = 0; j < pt_update_ops->num_ops; ++j) {
+		const struct xe_vm_pgtable_update_op *pt_op =
+			&pt_update_ops->ops[j];
+
+		for (i = 0; i < pt_op->num_entries; i++) {
+			const struct xe_vm_pgtable_update *update =
+				&pt_op->entries[i];
+
+			if (pt_op->bind)
+				ops->populate(pt_update, m->tile,
+					      &update->pt_bo->vmap, NULL,
+					      update->ofs, update->qwords,
+					      update);
+			else
+				ops->clear(pt_update, m->tile,
+					   &update->pt_bo->vmap, NULL,
+					   update->ofs, update->qwords, update);
 		}
-		dma_fence_put(fence);
 	}
 
-	return true;
+	trace_xe_vm_cpu_bind(vm);
+	xe_device_wmb(vm->xe);
+
+	return dma_fence_get_stub();
 }
 
-/**
- * xe_migrate_update_pgtables() - Pipelined page-table update
- * @m: The migrate context.
- * @vm: The vm we'll be updating.
- * @bo: The bo whose dma-resv we will await before updating, or NULL if userptr.
- * @q: The exec queue to be used for the update or NULL if the default
- * migration engine is to be used.
- * @updates: An array of update descriptors.
- * @num_updates: Number of descriptors in @updates.
- * @syncs: Array of xe_sync_entry to await before updating. Note that waits
- * will block the engine timeline.
- * @num_syncs: Number of entries in @syncs.
- * @pt_update: Pointer to a struct xe_migrate_pt_update, which contains
- * pointers to callback functions and, if subclassed, private arguments to
- * those.
- *
- * Perform a pipelined page-table update. The update descriptors are typically
- * built under the same lock critical section as a call to this function. If
- * using the default engine for the updates, they will be performed in the
- * order they grab the job_mutex. If different engines are used, external
- * synchronization is needed for overlapping updates to maintain page-table
- * consistency. Note that the meaing of "overlapping" is that the updates
- * touch the same page-table, which might be a higher-level page-directory.
- * If no pipelining is needed, then updates may be performed by the cpu.
- *
- * Return: A dma_fence that, when signaled, indicates the update completion.
- */
-struct dma_fence *
-xe_migrate_update_pgtables(struct xe_migrate *m,
-			   struct xe_vm *vm,
-			   struct xe_bo *bo,
-			   struct xe_exec_queue *q,
-			   const struct xe_vm_pgtable_update *updates,
-			   u32 num_updates,
-			   struct xe_sync_entry *syncs, u32 num_syncs,
-			   struct xe_migrate_pt_update *pt_update)
+static struct dma_fence *
+__xe_migrate_update_pgtables(struct xe_migrate *m,
+			     struct xe_migrate_pt_update *pt_update,
+			     struct xe_vm_pgtable_update_ops *pt_update_ops)
 {
 	const struct xe_migrate_pt_update_ops *ops = pt_update->ops;
 	struct xe_tile *tile = m->tile;
@@ -1282,59 +1231,45 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
 	struct xe_sched_job *job;
 	struct dma_fence *fence;
 	struct drm_suballoc *sa_bo = NULL;
-	struct xe_vma *vma = pt_update->vma;
 	struct xe_bb *bb;
-	u32 i, batch_size, ppgtt_ofs, update_idx, page_ofs = 0;
+	u32 i, j, batch_size = 0, ppgtt_ofs, update_idx, page_ofs = 0;
+	u32 num_updates = 0, current_update = 0;
 	u64 addr;
 	int err = 0;
-	bool usm = !q && xe->info.has_usm;
-	bool first_munmap_rebind = vma &&
-		vma->gpuva.flags & XE_VMA_FIRST_REBIND;
-	struct xe_exec_queue *q_override = !q ? m->q : q;
-	u16 pat_index = xe->pat.idx[XE_CACHE_WB];
+	bool is_migrate = pt_update_ops->q == m->q;
+	bool usm = is_migrate && xe->info.has_usm;
 
-	/* Use the CPU if no in syncs and engine is idle */
-	if (no_in_syncs(vm, q, syncs, num_syncs) && xe_exec_queue_is_idle(q_override)) {
-		fence =  xe_migrate_update_pgtables_cpu(m, vm, bo, updates,
-							num_updates,
-							first_munmap_rebind,
-							pt_update);
-		if (!IS_ERR(fence) || fence == ERR_PTR(-EAGAIN))
-			return fence;
+	for (i = 0; i < pt_update_ops->num_ops; ++i) {
+		struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[i];
+		struct xe_vm_pgtable_update *updates = pt_op->entries;
+
+		num_updates += pt_op->num_entries;
+		for (j = 0; j < pt_op->num_entries; ++j) {
+			u32 num_cmds = DIV_ROUND_UP(updates[j].qwords, 0x1ff);
+
+			/* align noop + MI_STORE_DATA_IMM cmd prefix */
+			batch_size += 4 * num_cmds + updates[j].qwords * 2;
+		}
 	}
 
 	/* fixed + PTE entries */
 	if (IS_DGFX(xe))
-		batch_size = 2;
+		batch_size += 2;
 	else
-		batch_size = 6 + num_updates * 2;
+		batch_size += 6 + num_updates * 2;
 
-	for (i = 0; i < num_updates; i++) {
-		u32 num_cmds = DIV_ROUND_UP(updates[i].qwords, MAX_PTE_PER_SDI);
-
-		/* align noop + MI_STORE_DATA_IMM cmd prefix */
-		batch_size += 4 * num_cmds + updates[i].qwords * 2;
-	}
-
-	/*
-	 * XXX: Create temp bo to copy from, if batch_size becomes too big?
-	 *
-	 * Worst case: Sum(2 * (each lower level page size) + (top level page size))
-	 * Should be reasonably bound..
-	 */
-	xe_tile_assert(tile, batch_size < SZ_128K);
-
-	bb = xe_bb_new(gt, batch_size, !q && xe->info.has_usm);
+	bb = xe_bb_new(gt, batch_size, usm);
 	if (IS_ERR(bb))
 		return ERR_CAST(bb);
 
 	/* For sysmem PTE's, need to map them in our hole.. */
 	if (!IS_DGFX(xe)) {
 		ppgtt_ofs = NUM_KERNEL_PDE - 1;
-		if (q) {
-			xe_tile_assert(tile, num_updates <= NUM_VMUSA_WRITES_PER_UNIT);
+		if (!is_migrate) {
+			u32 num_units = DIV_ROUND_UP(num_updates,
+						     NUM_VMUSA_WRITES_PER_UNIT);
 
-			sa_bo = drm_suballoc_new(&m->vm_update_sa, 1,
+			sa_bo = drm_suballoc_new(&m->vm_update_sa, num_units,
 						 GFP_KERNEL, true, 0);
 			if (IS_ERR(sa_bo)) {
 				err = PTR_ERR(sa_bo);
@@ -1354,14 +1289,26 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
 		bb->cs[bb->len++] = ppgtt_ofs * XE_PAGE_SIZE + page_ofs;
 		bb->cs[bb->len++] = 0; /* upper_32_bits */
 
-		for (i = 0; i < num_updates; i++) {
-			struct xe_bo *pt_bo = updates[i].pt_bo;
+		for (i = 0; i < pt_update_ops->num_ops; ++i) {
+			struct xe_vm_pgtable_update_op *pt_op =
+				&pt_update_ops->ops[i];
+			struct xe_vm_pgtable_update *updates = pt_op->entries;
 
-			xe_tile_assert(tile, pt_bo->size == SZ_4K);
+			for (j = 0; j < pt_op->num_entries; ++j, ++current_update) {
+				struct xe_vm *vm = pt_update->vops->vm;
+				struct xe_bo *pt_bo = updates[j].pt_bo;
 
-			addr = vm->pt_ops->pte_encode_bo(pt_bo, 0, pat_index, 0);
-			bb->cs[bb->len++] = lower_32_bits(addr);
-			bb->cs[bb->len++] = upper_32_bits(addr);
+				xe_tile_assert(tile, pt_bo->size == SZ_4K);
+
+				/* Map a PT at most once */
+				if (pt_bo->update_index < 0)
+					pt_bo->update_index = current_update;
+
+				addr = vm->pt_ops->pte_encode_bo(pt_bo, 0,
+								 XE_CACHE_WB, 0);
+				bb->cs[bb->len++] = lower_32_bits(addr);
+				bb->cs[bb->len++] = upper_32_bits(addr);
+			}
 		}
 
 		bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
@@ -1369,22 +1316,39 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
 
 		addr = xe_migrate_vm_addr(ppgtt_ofs, 0) +
 			(page_ofs / sizeof(u64)) * XE_PAGE_SIZE;
-		for (i = 0; i < num_updates; i++)
-			write_pgtable(tile, bb, addr + i * XE_PAGE_SIZE,
-				      &updates[i], pt_update);
+		for (i = 0; i < pt_update_ops->num_ops; ++i) {
+			struct xe_vm_pgtable_update_op *pt_op =
+				&pt_update_ops->ops[i];
+			struct xe_vm_pgtable_update *updates = pt_op->entries;
+
+			for (j = 0; j < pt_op->num_entries; ++j) {
+				struct xe_bo *pt_bo = updates[j].pt_bo;
+
+				write_pgtable(tile, bb, addr +
+					      pt_bo->update_index * XE_PAGE_SIZE,
+					      pt_op, &updates[j], pt_update);
+			}
+		}
 	} else {
 		/* phys pages, no preamble required */
 		bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
 		update_idx = bb->len;
 
-		for (i = 0; i < num_updates; i++)
-			write_pgtable(tile, bb, 0, &updates[i], pt_update);
+		for (i = 0; i < pt_update_ops->num_ops; ++i) {
+			struct xe_vm_pgtable_update_op *pt_op =
+				&pt_update_ops->ops[i];
+			struct xe_vm_pgtable_update *updates = pt_op->entries;
+
+			for (j = 0; j < pt_op->num_entries; ++j)
+				write_pgtable(tile, bb, 0, pt_op, &updates[j],
+					      pt_update);
+		}
 	}
 
-	if (!q)
+	if (is_migrate)
 		mutex_lock(&m->job_mutex);
 
-	job = xe_bb_create_migration_job(q ?: m->q, bb,
+	job = xe_bb_create_migration_job(pt_update_ops->q, bb,
 					 xe_migrate_batch_base(m, usm),
 					 update_idx);
 	if (IS_ERR(job)) {
@@ -1392,32 +1356,6 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
 		goto err_bb;
 	}
 
-	/* Wait on BO move */
-	if (bo) {
-		err = job_add_deps(job, bo->ttm.base.resv,
-				   DMA_RESV_USAGE_KERNEL);
-		if (err)
-			goto err_job;
-	}
-
-	/*
-	 * Munmap style VM unbind, need to wait for all jobs to be complete /
-	 * trigger preempts before moving forward
-	 */
-	if (first_munmap_rebind) {
-		err = job_add_deps(job, xe_vm_resv(vm),
-				   DMA_RESV_USAGE_BOOKKEEP);
-		if (err)
-			goto err_job;
-	}
-
-	err = xe_sched_job_last_fence_add_dep(job, vm);
-	for (i = 0; !err && i < num_syncs; i++)
-		err = xe_sync_entry_add_deps(&syncs[i], job);
-
-	if (err)
-		goto err_job;
-
 	if (ops->pre_commit) {
 		pt_update->job = job;
 		err = ops->pre_commit(pt_update);
@@ -1428,7 +1366,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
 	fence = dma_fence_get(&job->drm.s_fence->finished);
 	xe_sched_job_push(job);
 
-	if (!q)
+	if (is_migrate)
 		mutex_unlock(&m->job_mutex);
 
 	xe_bb_free(bb, fence);
@@ -1439,7 +1377,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
 err_job:
 	xe_sched_job_put(job);
 err_bb:
-	if (!q)
+	if (is_migrate)
 		mutex_unlock(&m->job_mutex);
 	xe_bb_free(bb, NULL);
 err:
@@ -1447,6 +1385,38 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
 	return ERR_PTR(err);
 }
 
+/**
+ * xe_migrate_update_pgtables() - Pipelined page-table update
+ * @m: The migrate context.
+ * @pt_update: PT update arguments
+ *
+ * Perform a pipelined page-table update. The update descriptors are typically
+ * built under the same lock critical section as a call to this function. If
+ * using the default engine for the updates, they will be performed in the
+ * order they grab the job_mutex. If different engines are used, external
+ * synchronization is needed for overlapping updates to maintain page-table
+ * consistency. Note that the meaing of "overlapping" is that the updates
+ * touch the same page-table, which might be a higher-level page-directory.
+ * If no pipelining is needed, then updates may be performed by the cpu.
+ *
+ * Return: A dma_fence that, when signaled, indicates the update completion.
+ */
+struct dma_fence *
+xe_migrate_update_pgtables(struct xe_migrate *m,
+			   struct xe_migrate_pt_update *pt_update)
+
+{
+	struct xe_vm_pgtable_update_ops *pt_update_ops =
+		&pt_update->vops->pt_update_ops[pt_update->tile_id];
+	struct dma_fence *fence;
+
+	fence =  xe_migrate_update_pgtables_cpu(m, pt_update);
+	if (!IS_ERR(fence))
+		return fence;
+
+	return __xe_migrate_update_pgtables(m, pt_update, pt_update_ops);
+}
+
 /**
  * xe_migrate_wait() - Complete all operations using the xe_migrate context
  * @m: Migrate context to wait for.
diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h
index 9935ce336bae..bd8eba1d3552 100644
--- a/drivers/gpu/drm/xe/xe_migrate.h
+++ b/drivers/gpu/drm/xe/xe_migrate.h
@@ -47,6 +47,24 @@ struct xe_migrate_pt_update_ops {
 			 struct xe_tile *tile, struct iosys_map *map,
 			 void *pos, u32 ofs, u32 num_qwords,
 			 const struct xe_vm_pgtable_update *update);
+	/**
+	 * @clear: Clear a command buffer or page-table with ptes.
+	 * @pt_update: Embeddable callback argument.
+	 * @tile: The tile for the current operation.
+	 * @map: struct iosys_map into the memory to be populated.
+	 * @pos: If @map is NULL, map into the memory to be populated.
+	 * @ofs: qword offset into @map, unused if @map is NULL.
+	 * @num_qwords: Number of qwords to write.
+	 * @update: Information about the PTEs to be inserted.
+	 *
+	 * This interface is intended to be used as a callback into the
+	 * page-table system to populate command buffers or shared
+	 * page-tables with PTEs.
+	 */
+	void (*clear)(struct xe_migrate_pt_update *pt_update,
+		      struct xe_tile *tile, struct iosys_map *map,
+		      void *pos, u32 ofs, u32 num_qwords,
+		      const struct xe_vm_pgtable_update *update);
 
 	/**
 	 * @pre_commit: Callback to be called just before arming the
@@ -67,14 +85,10 @@ struct xe_migrate_pt_update_ops {
 struct xe_migrate_pt_update {
 	/** @ops: Pointer to the struct xe_migrate_pt_update_ops callbacks */
 	const struct xe_migrate_pt_update_ops *ops;
-	/** @vma: The vma we're updating the pagetable for. */
-	struct xe_vma *vma;
+	/** @vops: VMA operations */
+	struct xe_vma_ops *vops;
 	/** @job: The job if a GPU page-table update. NULL otherwise */
 	struct xe_sched_job *job;
-	/** @start: Start of update for the range fence */
-	u64 start;
-	/** @last: Last of update for the range fence */
-	u64 last;
 	/** @tile_id: Tile ID of the update */
 	u8 tile_id;
 };
@@ -96,12 +110,6 @@ struct xe_vm *xe_migrate_get_vm(struct xe_migrate *m);
 
 struct dma_fence *
 xe_migrate_update_pgtables(struct xe_migrate *m,
-			   struct xe_vm *vm,
-			   struct xe_bo *bo,
-			   struct xe_exec_queue *q,
-			   const struct xe_vm_pgtable_update *updates,
-			   u32 num_updates,
-			   struct xe_sync_entry *syncs, u32 num_syncs,
 			   struct xe_migrate_pt_update *pt_update);
 
 void xe_migrate_wait(struct xe_migrate *m);
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index a878e2217c7f..5a8523d0a049 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -8,12 +8,14 @@
 #include "xe_bo.h"
 #include "xe_device.h"
 #include "xe_drm_client.h"
+#include "xe_exec_queue.h"
 #include "xe_gt.h"
 #include "xe_gt_tlb_invalidation.h"
 #include "xe_migrate.h"
 #include "xe_pt_types.h"
 #include "xe_pt_walk.h"
 #include "xe_res_cursor.h"
+#include "xe_sync.h"
 #include "xe_trace.h"
 #include "xe_ttm_stolen_mgr.h"
 #include "xe_vm.h"
@@ -324,6 +326,7 @@ xe_pt_new_shared(struct xe_walk_update *wupd, struct xe_pt *parent,
 	entry->pt = parent;
 	entry->flags = 0;
 	entry->qwords = 0;
+	entry->pt_bo->update_index = -1;
 
 	if (alloc_entries) {
 		entry->pt_entries = kmalloc_array(XE_PDES,
@@ -831,9 +834,7 @@ static void xe_pt_commit_locks_assert(struct xe_vma *vma)
 
 	lockdep_assert_held(&vm->lock);
 
-	if (xe_vma_is_userptr(vma))
-		lockdep_assert_held_read(&vm->userptr.notifier_lock);
-	else if (!xe_vma_is_null(vma))
+	if (!xe_vma_is_userptr(vma) && !xe_vma_is_null(vma))
 		dma_resv_assert_held(xe_vma_bo(vma)->ttm.base.resv);
 
 	xe_vm_assert_held(vm);
@@ -855,10 +856,8 @@ static void xe_pt_commit_bind(struct xe_vma *vma,
 		if (!rebind)
 			pt->num_live += entries[i].qwords;
 
-		if (!pt->level) {
-			kfree(entries[i].pt_entries);
+		if (!pt->level)
 			continue;
-		}
 
 		pt_dir = as_xe_pt_dir(pt);
 		for (j = 0; j < entries[i].qwords; j++) {
@@ -871,10 +870,18 @@ static void xe_pt_commit_bind(struct xe_vma *vma,
 
 			pt_dir->children[j_] = &newpte->base;
 		}
-		kfree(entries[i].pt_entries);
 	}
 }
 
+static void xe_pt_free_bind(struct xe_vm_pgtable_update *entries,
+			    u32 num_entries)
+{
+	u32 i;
+
+	for (i = 0; i < num_entries; i++)
+		kfree(entries[i].pt_entries);
+}
+
 static int
 xe_pt_prepare_bind(struct xe_tile *tile, struct xe_vma *vma,
 		   struct xe_vm_pgtable_update *entries, u32 *num_entries)
@@ -893,12 +900,13 @@ xe_pt_prepare_bind(struct xe_tile *tile, struct xe_vma *vma,
 
 static void xe_vm_dbg_print_entries(struct xe_device *xe,
 				    const struct xe_vm_pgtable_update *entries,
-				    unsigned int num_entries)
+				    unsigned int num_entries, bool bind)
 #if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_VM))
 {
 	unsigned int i;
 
-	vm_dbg(&xe->drm, "%u entries to update\n", num_entries);
+	vm_dbg(&xe->drm, "%s: %u entries to update\n", bind ? "bind" : "unbind",
+	       num_entries);
 	for (i = 0; i < num_entries; i++) {
 		const struct xe_vm_pgtable_update *entry = &entries[i];
 		struct xe_pt *xe_pt = entry->pt;
@@ -919,66 +927,122 @@ static void xe_vm_dbg_print_entries(struct xe_device *xe,
 {}
 #endif
 
-#ifdef CONFIG_DRM_XE_USERPTR_INVAL_INJECT
+static int job_add_deps(struct xe_sched_job *job, struct dma_resv *resv,
+			enum dma_resv_usage usage)
+{
+	return drm_sched_job_add_resv_dependencies(&job->drm, resv, usage);
+}
 
-static int xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma)
+static bool no_in_syncs(struct xe_sync_entry *syncs, u32 num_syncs)
 {
-	u32 divisor = uvma->userptr.divisor ? uvma->userptr.divisor : 2;
-	static u32 count;
+	int i;
 
-	if (count++ % divisor == divisor - 1) {
-		struct xe_vm *vm = xe_vma_vm(&uvma->vma);
+	for (i = 0; i < num_syncs; i++) {
+		struct dma_fence *fence = syncs[i].fence;
 
-		uvma->userptr.divisor = divisor << 1;
-		spin_lock(&vm->userptr.invalidated_lock);
-		list_move_tail(&uvma->userptr.invalidate_link,
-			       &vm->userptr.invalidated);
-		spin_unlock(&vm->userptr.invalidated_lock);
-		return true;
+		if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
+				       &fence->flags))
+			return false;
 	}
 
-	return false;
+	return true;
 }
 
-#else
-
-static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma)
+static int vma_add_deps(struct xe_vma *vma, struct xe_sched_job *job)
 {
-	return false;
+	struct xe_bo *bo = xe_vma_bo(vma);
+
+	xe_bo_assert_held(bo);
+
+	if (bo && !bo->vm) {
+		if (!job) {
+			if (!dma_resv_test_signaled(bo->ttm.base.resv,
+						    DMA_RESV_USAGE_KERNEL))
+				return -ETIME;
+		} else {
+			return job_add_deps(job, bo->ttm.base.resv,
+					    DMA_RESV_USAGE_KERNEL);
+		}
+	}
+
+	return 0;
 }
 
-#endif
+static int op_add_deps(struct xe_vm *vm, struct xe_vma_op *op,
+		       struct xe_sched_job *job)
+{
+	int err = 0;
 
-/**
- * struct xe_pt_migrate_pt_update - Callback argument for pre-commit callbacks
- * @base: Base we derive from.
- * @bind: Whether this is a bind or an unbind operation. A bind operation
- *        makes the pre-commit callback error with -EAGAIN if it detects a
- *        pending invalidation.
- * @locked: Whether the pre-commit callback locked the userptr notifier lock
- *          and it needs unlocking.
- */
-struct xe_pt_migrate_pt_update {
-	struct xe_migrate_pt_update base;
-	bool bind;
-	bool locked;
-};
+	switch (op->base.op) {
+	case DRM_GPUVA_OP_MAP:
+		if (!op->map.immediate && xe_vm_in_fault_mode(vm))
+			break;
+
+		err = vma_add_deps(op->map.vma, job);
+		break;
+	case DRM_GPUVA_OP_REMAP:
+		if (op->remap.prev)
+			err = vma_add_deps(op->remap.prev, job);
+		if (!err && op->remap.next)
+			err = vma_add_deps(op->remap.next, job);
+		break;
+	case DRM_GPUVA_OP_UNMAP:
+		break;
+	case DRM_GPUVA_OP_PREFETCH:
+		err = vma_add_deps(gpuva_to_vma(op->base.prefetch.va), job);
+		break;
+	default:
+		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
+	}
+
+	return err;
+}
 
-/*
- * This function adds the needed dependencies to a page-table update job
- * to make sure racing jobs for separate bind engines don't race writing
- * to the same page-table range, wreaking havoc. Initially use a single
- * fence for the entire VM. An optimization would use smaller granularity.
- */
 static int xe_pt_vm_dependencies(struct xe_sched_job *job,
-				 struct xe_range_fence_tree *rftree,
-				 u64 start, u64 last)
+				 struct xe_vm *vm,
+				 struct xe_vma_ops *vops,
+				 struct xe_vm_pgtable_update_ops *pt_update_ops,
+				 struct xe_range_fence_tree *rftree)
 {
 	struct xe_range_fence *rtfence;
 	struct dma_fence *fence;
-	int err;
+	struct xe_vma_op *op;
+	int err = 0, i;
+
+	xe_vm_assert_held(vm);
+
+	if (!job && !no_in_syncs(vops->syncs, vops->num_syncs))
+		return -ETIME;
+
+	if (!job && !xe_exec_queue_is_idle(pt_update_ops->q))
+		return -ETIME;
 
-	rtfence = xe_range_fence_tree_first(rftree, start, last);
+	if (pt_update_ops->wait_vm_bookkeep) {
+		if (!job) {
+			if (!dma_resv_test_signaled(xe_vm_resv(vm),
+						    DMA_RESV_USAGE_BOOKKEEP))
+				return -ETIME;
+		} else {
+			err = job_add_deps(job, xe_vm_resv(vm),
+					   DMA_RESV_USAGE_BOOKKEEP);
+			if (err)
+				return err;
+		}
+	} else if (pt_update_ops->wait_vm_kernel) {
+		if (!job) {
+			if (!dma_resv_test_signaled(xe_vm_resv(vm),
+						    DMA_RESV_USAGE_KERNEL))
+				return -ETIME;
+		} else {
+			err = job_add_deps(job, xe_vm_resv(vm),
+					   DMA_RESV_USAGE_KERNEL);
+			if (err)
+				return err;
+		}
+	}
+
+	rtfence = xe_range_fence_tree_first(rftree, pt_update_ops->start,
+					    pt_update_ops->last);
 	while (rtfence) {
 		fence = rtfence->fence;
 
@@ -996,80 +1060,136 @@ static int xe_pt_vm_dependencies(struct xe_sched_job *job,
 				return err;
 		}
 
-		rtfence = xe_range_fence_tree_next(rtfence, start, last);
+		rtfence = xe_range_fence_tree_next(rtfence,
+						   pt_update_ops->start,
+						   pt_update_ops->last);
 	}
 
-	return 0;
+	list_for_each_entry(op, &vops->list, link) {
+		err = op_add_deps(vm, op, job);
+		if (err)
+			return err;
+	}
+
+	for (i = 0; job && !err && i < vops->num_syncs; i++)
+		err = xe_sync_entry_add_deps(&vops->syncs[i], job);
+
+	return err;
 }
 
 static int xe_pt_pre_commit(struct xe_migrate_pt_update *pt_update)
 {
-	struct xe_range_fence_tree *rftree =
-		&xe_vma_vm(pt_update->vma)->rftree[pt_update->tile_id];
+	struct xe_vma_ops *vops = pt_update->vops;
+	struct xe_vm *vm = vops->vm;
+	struct xe_range_fence_tree *rftree = &vm->rftree[pt_update->tile_id];
+	struct xe_vm_pgtable_update_ops *pt_update_ops =
+		&vops->pt_update_ops[pt_update->tile_id];
+
+	return xe_pt_vm_dependencies(pt_update->job, vm, pt_update->vops,
+				     pt_update_ops, rftree);
+}
+
+#ifdef CONFIG_DRM_XE_USERPTR_INVAL_INJECT
+
+static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma)
+{
+	u32 divisor = uvma->userptr.divisor ? uvma->userptr.divisor : 2;
+	static u32 count;
+
+	if (count++ % divisor == divisor - 1) {
+		uvma->userptr.divisor = divisor << 1;
+		return true;
+	}
 
-	return xe_pt_vm_dependencies(pt_update->job, rftree,
-				     pt_update->start, pt_update->last);
+	return false;
 }
 
-static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
+#else
+
+static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma)
 {
-	struct xe_pt_migrate_pt_update *userptr_update =
-		container_of(pt_update, typeof(*userptr_update), base);
-	struct xe_userptr_vma *uvma = to_userptr_vma(pt_update->vma);
-	unsigned long notifier_seq = uvma->userptr.notifier_seq;
-	struct xe_vm *vm = xe_vma_vm(&uvma->vma);
-	int err = xe_pt_vm_dependencies(pt_update->job,
-					&vm->rftree[pt_update->tile_id],
-					pt_update->start,
-					pt_update->last);
+	return false;
+}
 
-	if (err)
-		return err;
+#endif
 
-	userptr_update->locked = false;
+static void vma_check_userptr(struct xe_vm *vm, struct xe_vma *vma)
+{
+	struct xe_userptr_vma *uvma = to_userptr_vma(vma);
+	unsigned long notifier_seq = uvma->userptr.notifier_seq;
 
-	/*
-	 * Wait until nobody is running the invalidation notifier, and
-	 * since we're exiting the loop holding the notifier lock,
-	 * nobody can proceed invalidating either.
-	 *
-	 * Note that we don't update the vma->userptr.notifier_seq since
-	 * we don't update the userptr pages.
-	 */
-	do {
-		down_read(&vm->userptr.notifier_lock);
-		if (!mmu_interval_read_retry(&uvma->userptr.notifier,
-					     notifier_seq))
-			break;
+	lockdep_assert_held_read(&vm->userptr.notifier_lock);
 
-		up_read(&vm->userptr.notifier_lock);
+	if (uvma->userptr.initial_bind || xe_vm_in_fault_mode(vm))
+		return;
 
-		if (userptr_update->bind)
-			return -EAGAIN;
+	if (!mmu_interval_read_retry(&uvma->userptr.notifier,
+				     notifier_seq) &&
+	    !xe_pt_userptr_inject_eagain(uvma))
+		return;
 
-		notifier_seq = mmu_interval_read_begin(&uvma->userptr.notifier);
-	} while (true);
+	spin_lock(&vm->userptr.invalidated_lock);
+	list_move_tail(&uvma->userptr.invalidate_link,
+		       &vm->userptr.invalidated);
+	spin_unlock(&vm->userptr.invalidated_lock);
 
-	/* Inject errors to test_whether they are handled correctly */
-	if (userptr_update->bind && xe_pt_userptr_inject_eagain(uvma)) {
-		up_read(&vm->userptr.notifier_lock);
-		return -EAGAIN;
+	if (xe_vm_in_preempt_fence_mode(vm)) {
+		struct dma_resv_iter cursor;
+		struct dma_fence *fence;
+
+		dma_resv_iter_begin(&cursor, xe_vm_resv(vm),
+				    DMA_RESV_USAGE_BOOKKEEP);
+		dma_resv_for_each_fence_unlocked(&cursor, fence)
+			dma_fence_enable_sw_signaling(fence);
+		dma_resv_iter_end(&cursor);
 	}
+}
 
-	userptr_update->locked = true;
+static void op_check_userptr(struct xe_vm *vm, struct xe_vma_op *op)
+{
+	lockdep_assert_held_read(&vm->userptr.notifier_lock);
 
-	return 0;
+	switch (op->base.op) {
+	case DRM_GPUVA_OP_MAP:
+		if (!op->map.immediate && xe_vm_in_fault_mode(vm))
+			break;
+
+		vma_check_userptr(vm, op->map.vma);
+		break;
+	case DRM_GPUVA_OP_REMAP:
+		if (op->remap.prev)
+			vma_check_userptr(vm, op->remap.prev);
+		if (op->remap.next)
+			vma_check_userptr(vm, op->remap.next);
+		break;
+	case DRM_GPUVA_OP_UNMAP:
+		break;
+	case DRM_GPUVA_OP_PREFETCH:
+		vma_check_userptr(vm, gpuva_to_vma(op->base.prefetch.va));
+		break;
+	default:
+		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
+	}
 }
 
-static const struct xe_migrate_pt_update_ops bind_ops = {
-	.populate = xe_vm_populate_pgtable,
-	.pre_commit = xe_pt_pre_commit,
-};
+static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
+{
+	struct xe_vm *vm = pt_update->vops->vm;
+	struct xe_vma_ops *vops = pt_update->vops;
+	struct xe_vma_op *op;
+	int err;
 
-static const struct xe_migrate_pt_update_ops userptr_bind_ops = {
-	.populate = xe_vm_populate_pgtable,
-	.pre_commit = xe_pt_userptr_pre_commit,
-};
+	err = xe_pt_pre_commit(pt_update);
+	if (err)
+		return err;
+
+	down_read(&vm->userptr.notifier_lock);
+
+	list_for_each_entry(op, &vops->list, link)
+		op_check_userptr(vm, op);
+
+	return 0;
+}
 
 struct invalidation_fence {
 	struct xe_gt_tlb_invalidation_fence base;
@@ -1166,181 +1286,6 @@ static int invalidation_fence_init(struct xe_gt *gt,
 	return ret && ret != -ENOENT ? ret : 0;
 }
 
-static void xe_pt_calc_rfence_interval(struct xe_vma *vma,
-				       struct xe_pt_migrate_pt_update *update,
-				       struct xe_vm_pgtable_update *entries,
-				       u32 num_entries)
-{
-	int i, level = 0;
-
-	for (i = 0; i < num_entries; i++) {
-		const struct xe_vm_pgtable_update *entry = &entries[i];
-
-		if (entry->pt->level > level)
-			level = entry->pt->level;
-	}
-
-	/* Greedy (non-optimal) calculation but simple */
-	update->base.start = ALIGN_DOWN(xe_vma_start(vma),
-					0x1ull << xe_pt_shift(level));
-	update->base.last = ALIGN(xe_vma_end(vma),
-				  0x1ull << xe_pt_shift(level)) - 1;
-}
-
-/**
- * __xe_pt_bind_vma() - Build and connect a page-table tree for the vma
- * address range.
- * @tile: The tile to bind for.
- * @vma: The vma to bind.
- * @q: The exec_queue with which to do pipelined page-table updates.
- * @syncs: Entries to sync on before binding the built tree to the live vm tree.
- * @num_syncs: Number of @sync entries.
- * @rebind: Whether we're rebinding this vma to the same address range without
- * an unbind in-between.
- *
- * This function builds a page-table tree (see xe_pt_stage_bind() for more
- * information on page-table building), and the xe_vm_pgtable_update entries
- * abstracting the operations needed to attach it to the main vm tree. It
- * then takes the relevant locks and updates the metadata side of the main
- * vm tree and submits the operations for pipelined attachment of the
- * gpu page-table to the vm main tree, (which can be done either by the
- * cpu and the GPU).
- *
- * Return: A valid dma-fence representing the pipelined attachment operation
- * on success, an error pointer on error.
- */
-struct dma_fence *
-__xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue *q,
-		 struct xe_sync_entry *syncs, u32 num_syncs,
-		 bool rebind)
-{
-	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
-	struct xe_pt_migrate_pt_update bind_pt_update = {
-		.base = {
-			.ops = xe_vma_is_userptr(vma) ? &userptr_bind_ops : &bind_ops,
-			.vma = vma,
-			.tile_id = tile->id,
-		},
-		.bind = true,
-	};
-	struct xe_vm *vm = xe_vma_vm(vma);
-	u32 num_entries;
-	struct dma_fence *fence;
-	struct invalidation_fence *ifence = NULL;
-	struct xe_range_fence *rfence;
-	int err;
-
-	bind_pt_update.locked = false;
-	xe_bo_assert_held(xe_vma_bo(vma));
-	xe_vm_assert_held(vm);
-
-	vm_dbg(&xe_vma_vm(vma)->xe->drm,
-	       "Preparing bind, with range [%llx...%llx) engine %p.\n",
-	       xe_vma_start(vma), xe_vma_end(vma), q);
-
-	err = xe_pt_prepare_bind(tile, vma, entries, &num_entries);
-	if (err)
-		goto err;
-	xe_tile_assert(tile, num_entries <= ARRAY_SIZE(entries));
-
-	xe_vm_dbg_print_entries(tile_to_xe(tile), entries, num_entries);
-	xe_pt_calc_rfence_interval(vma, &bind_pt_update, entries,
-				   num_entries);
-
-	/*
-	 * If rebind, we have to invalidate TLB on !LR vms to invalidate
-	 * cached PTEs point to freed memory. on LR vms this is done
-	 * automatically when the context is re-enabled by the rebind worker,
-	 * or in fault mode it was invalidated on PTE zapping.
-	 *
-	 * If !rebind, and scratch enabled VMs, there is a chance the scratch
-	 * PTE is already cached in the TLB so it needs to be invalidated.
-	 * on !LR VMs this is done in the ring ops preceding a batch, but on
-	 * non-faulting LR, in particular on user-space batch buffer chaining,
-	 * it needs to be done here.
-	 */
-	if ((rebind && !xe_vm_in_lr_mode(vm) && !vm->batch_invalidate_tlb) ||
-	    (!rebind && xe_vm_has_scratch(vm) && xe_vm_in_preempt_fence_mode(vm))) {
-		ifence = kzalloc(sizeof(*ifence), GFP_KERNEL);
-		if (!ifence)
-			return ERR_PTR(-ENOMEM);
-	}
-
-	rfence = kzalloc(sizeof(*rfence), GFP_KERNEL);
-	if (!rfence) {
-		kfree(ifence);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	fence = xe_migrate_update_pgtables(tile->migrate,
-					   vm, xe_vma_bo(vma), q,
-					   entries, num_entries,
-					   syncs, num_syncs,
-					   &bind_pt_update.base);
-	if (!IS_ERR(fence)) {
-		bool last_munmap_rebind = vma->gpuva.flags & XE_VMA_LAST_REBIND;
-		LLIST_HEAD(deferred);
-		int err;
-
-		err = xe_range_fence_insert(&vm->rftree[tile->id], rfence,
-					    &xe_range_fence_kfree_ops,
-					    bind_pt_update.base.start,
-					    bind_pt_update.base.last, fence);
-		if (err)
-			dma_fence_wait(fence, false);
-
-		/* TLB invalidation must be done before signaling rebind */
-		if (ifence) {
-			int err = invalidation_fence_init(tile->primary_gt,
-							  ifence, fence,
-							  xe_vma_start(vma),
-							  xe_vma_end(vma),
-							  xe_vma_vm(vma)->usm.asid);
-			if (err) {
-				dma_fence_put(fence);
-				kfree(ifence);
-				return ERR_PTR(err);
-			}
-			fence = &ifence->base.base;
-		}
-
-		/* add shared fence now for pagetable delayed destroy */
-		dma_resv_add_fence(xe_vm_resv(vm), fence, !rebind &&
-				   last_munmap_rebind ?
-				   DMA_RESV_USAGE_KERNEL :
-				   DMA_RESV_USAGE_BOOKKEEP);
-
-		if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm)
-			dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence,
-					   DMA_RESV_USAGE_BOOKKEEP);
-		xe_pt_commit_bind(vma, entries, num_entries, rebind,
-				  bind_pt_update.locked ? &deferred : NULL);
-
-		/* This vma is live (again?) now */
-		vma->tile_present |= BIT(tile->id);
-
-		if (bind_pt_update.locked) {
-			to_userptr_vma(vma)->userptr.initial_bind = true;
-			up_read(&vm->userptr.notifier_lock);
-			xe_bo_put_commit(&deferred);
-		}
-		if (!rebind && last_munmap_rebind &&
-		    xe_vm_in_preempt_fence_mode(vm))
-			xe_vm_queue_rebind_worker(vm);
-	} else {
-		kfree(rfence);
-		kfree(ifence);
-		if (bind_pt_update.locked)
-			up_read(&vm->userptr.notifier_lock);
-		xe_pt_abort_bind(vma, entries, num_entries);
-	}
-
-	return fence;
-
-err:
-	return ERR_PTR(err);
-}
-
 struct xe_pt_stage_unbind_walk {
 	/** @base: The pagewalk base-class. */
 	struct xe_pt_walk base;
@@ -1491,8 +1436,8 @@ xe_migrate_clear_pgtable_callback(struct xe_migrate_pt_update *pt_update,
 				  void *ptr, u32 qword_ofs, u32 num_qwords,
 				  const struct xe_vm_pgtable_update *update)
 {
-	struct xe_vma *vma = pt_update->vma;
-	u64 empty = __xe_pt_empty_pte(tile, xe_vma_vm(vma), update->pt->level);
+	struct xe_vm *vm = pt_update->vops->vm;
+	u64 empty = __xe_pt_empty_pte(tile, vm, update->pt->level);
 	int i;
 
 	if (map && map->is_iomem)
@@ -1536,144 +1481,443 @@ xe_pt_commit_unbind(struct xe_vma *vma,
 	}
 }
 
-static const struct xe_migrate_pt_update_ops unbind_ops = {
-	.populate = xe_migrate_clear_pgtable_callback,
+static void
+xe_pt_update_ops_rfence_interval(struct xe_vm_pgtable_update_ops *pt_update_ops,
+				 struct xe_vma *vma)
+{
+	u32 current_op = pt_update_ops->current_op;
+	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op];
+	int i, level = 0;
+	u64 start, last;
+
+	for (i = 0; i < pt_op->num_entries; i++) {
+		const struct xe_vm_pgtable_update *entry = &pt_op->entries[i];
+
+		if (entry->pt->level > level)
+			level = entry->pt->level;
+	}
+
+	/* Greedy (non-optimal) calculation but simple */
+	start = ALIGN_DOWN(xe_vma_start(vma), 0x1ull << xe_pt_shift(level));
+	last = ALIGN(xe_vma_end(vma), 0x1ull << xe_pt_shift(level)) - 1;
+
+	if (start < pt_update_ops->start)
+		pt_update_ops->start = start;
+	if (last > pt_update_ops->last)
+		pt_update_ops->last = last;
+}
+
+static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile,
+			   struct xe_vm_pgtable_update_ops *pt_update_ops,
+			   struct xe_vma *vma)
+{
+	u32 current_op = pt_update_ops->current_op;
+	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op];
+	struct llist_head *deferred = &pt_update_ops->deferred;
+	int err;
+
+	xe_bo_assert_held(xe_vma_bo(vma));
+
+	vm_dbg(&xe_vma_vm(vma)->xe->drm,
+	       "Preparing bind, with range [%llx...%llx)\n",
+	       xe_vma_start(vma), xe_vma_end(vma) - 1);
+
+	pt_op->bind = true;
+	pt_op->rebind = BIT(tile->id) & vma->tile_present;
+
+	err = xe_pt_prepare_bind(tile, vma, pt_op->entries,
+				 &pt_op->num_entries);
+	if (!err) {
+		xe_tile_assert(tile, pt_op->num_entries <=
+			       ARRAY_SIZE(pt_op->entries));
+		xe_vm_dbg_print_entries(tile_to_xe(tile), pt_op->entries,
+					pt_op->num_entries, true);
+
+		xe_pt_update_ops_rfence_interval(pt_update_ops, vma);
+		++pt_update_ops->current_op;
+		pt_update_ops->needs_userptr_lock |= xe_vma_is_userptr(vma);
+
+		/*
+		 * If rebind, we have to invalidate TLB on !LR vms to invalidate
+		 * cached PTEs point to freed memory. on LR vms this is done
+		 * automatically when the context is re-enabled by the rebind
+		 * worker, or in fault mode it was invalidated on PTE zapping.
+		 *
+		 * If !rebind, and scratch enabled VMs, there is a chance the
+		 * scratch PTE is already cached in the TLB so it needs to be
+		 * invalidated. on !LR VMs this is done in the ring ops
+		 * preceding a batch, but on non-faulting LR, in particular on
+		 * user-space batch buffer chaining, it needs to be done here.
+		 */
+		pt_update_ops->needs_invalidation |=
+			(pt_op->rebind && xe_vm_in_lr_mode(vm) &&
+			!vm->batch_invalidate_tlb) ||
+			(!pt_op->rebind && vm->scratch_pt[tile->id] &&
+			 xe_vm_in_preempt_fence_mode(vm));
+
+		/* FIXME: Don't commit right away */
+		xe_pt_commit_bind(vma, pt_op->entries, pt_op->num_entries,
+				  pt_op->rebind, deferred);
+	}
+
+	return err;
+}
+
+static int unbind_op_prepare(struct xe_tile *tile,
+			     struct xe_vm_pgtable_update_ops *pt_update_ops,
+			     struct xe_vma *vma)
+{
+	u32 current_op = pt_update_ops->current_op;
+	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op];
+	struct llist_head *deferred = &pt_update_ops->deferred;
+
+	xe_bo_assert_held(xe_vma_bo(vma));
+
+	vm_dbg(&xe_vma_vm(vma)->xe->drm,
+	       "Preparing unbind, with range [%llx...%llx)\n",
+	       xe_vma_start(vma), xe_vma_end(vma) - 1);
+
+	pt_op->bind = false;
+	pt_op->rebind = false;
+
+	pt_op->num_entries = xe_pt_stage_unbind(tile, vma, pt_op->entries);
+
+	xe_vm_dbg_print_entries(tile_to_xe(tile), pt_op->entries,
+				pt_op->num_entries, false);
+	xe_pt_update_ops_rfence_interval(pt_update_ops, vma);
+	++pt_update_ops->current_op;
+	pt_update_ops->needs_userptr_lock |= xe_vma_is_userptr(vma);
+	pt_update_ops->needs_invalidation = true;
+
+	/* FIXME: Don't commit right away */
+	xe_pt_commit_unbind(vma, pt_op->entries, pt_op->num_entries,
+			    deferred);
+
+	return 0;
+}
+
+static int op_prepare(struct xe_vm *vm,
+		      struct xe_tile *tile,
+		      struct xe_vm_pgtable_update_ops *pt_update_ops,
+		      struct xe_vma_op *op)
+{
+	int err = 0;
+
+	xe_vm_assert_held(vm);
+
+	switch (op->base.op) {
+	case DRM_GPUVA_OP_MAP:
+		if (!op->map.immediate && xe_vm_in_fault_mode(vm))
+			break;
+
+		err = bind_op_prepare(vm, tile, pt_update_ops, op->map.vma);
+		pt_update_ops->wait_vm_kernel = true;
+		break;
+	case DRM_GPUVA_OP_REMAP:
+		err = unbind_op_prepare(tile, pt_update_ops,
+					gpuva_to_vma(op->base.remap.unmap->va));
+
+		if (!err && op->remap.prev) {
+			err = bind_op_prepare(vm, tile, pt_update_ops,
+					      op->remap.prev);
+			pt_update_ops->wait_vm_bookkeep = true;
+		}
+		if (!err && op->remap.next) {
+			err = bind_op_prepare(vm, tile, pt_update_ops,
+					      op->remap.next);
+			pt_update_ops->wait_vm_bookkeep = true;
+		}
+		break;
+	case DRM_GPUVA_OP_UNMAP:
+		err = unbind_op_prepare(tile, pt_update_ops,
+					gpuva_to_vma(op->base.unmap.va));
+		break;
+	case DRM_GPUVA_OP_PREFETCH:
+		err = bind_op_prepare(vm, tile, pt_update_ops,
+				      gpuva_to_vma(op->base.prefetch.va));
+		pt_update_ops->wait_vm_kernel = true;
+		break;
+	default:
+		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
+	}
+
+	return err;
+}
+
+static void
+xe_pt_update_ops_init(struct xe_vm_pgtable_update_ops *pt_update_ops)
+{
+	init_llist_head(&pt_update_ops->deferred);
+	pt_update_ops->start = ~0x0ull;
+	pt_update_ops->last = 0x0ull;
+}
+
+/**
+ * xe_pt_update_ops_prepare() - Prepare PT update operations
+ * @tile: Tile of PT update operations
+ * @vops: VMA operationa
+ *
+ * Prepare PT update operations which includes updating internal PT state,
+ * allocate memory for page tables, populate page table being pruned in, and
+ * create PT update operations for leaf insertion / removal.
+ *
+ * Return: 0 on success, negative error code on error.
+ */
+int xe_pt_update_ops_prepare(struct xe_tile *tile, struct xe_vma_ops *vops)
+{
+	struct xe_vm_pgtable_update_ops *pt_update_ops =
+		&vops->pt_update_ops[tile->id];
+	struct xe_vma_op *op;
+	int err;
+
+	lockdep_assert_held(&vops->vm->lock);
+	xe_vm_assert_held(vops->vm);
+
+	xe_pt_update_ops_init(pt_update_ops);
+
+	list_for_each_entry(op, &vops->list, link) {
+		err = op_prepare(vops->vm, tile, pt_update_ops, op);
+
+		if (err)
+			return err;
+	}
+
+	xe_tile_assert(tile, pt_update_ops->current_op ==
+		       pt_update_ops->num_ops);
+
+	return 0;
+}
+
+static void bind_op_commit(struct xe_vm *vm, struct xe_tile *tile,
+			   struct xe_vm_pgtable_update_ops *pt_update_ops,
+			   struct xe_vma *vma, struct dma_fence *fence)
+{
+	if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm)
+		dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence,
+				   pt_update_ops->wait_vm_bookkeep ?
+				   DMA_RESV_USAGE_KERNEL :
+				   DMA_RESV_USAGE_BOOKKEEP);
+	vma->tile_present |= BIT(tile->id);
+	if (xe_vma_is_userptr(vma)) {
+		lockdep_assert_held_read(&vm->userptr.notifier_lock);
+		to_userptr_vma(vma)->userptr.initial_bind = true;
+	}
+
+	/*
+	 * Kick rebind worker if this bind triggers preempt fences and not in
+	 * the rebind worker
+	 */
+	if (pt_update_ops->wait_vm_bookkeep &&
+	    xe_vm_in_preempt_fence_mode(vm) &&
+	    !current->mm)
+		xe_vm_queue_rebind_worker(vm);
+}
+
+static void unbind_op_commit(struct xe_vm *vm, struct xe_tile *tile,
+			     struct xe_vm_pgtable_update_ops *pt_update_ops,
+			     struct xe_vma *vma, struct dma_fence *fence)
+{
+	if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm)
+		dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence,
+				   pt_update_ops->wait_vm_bookkeep ?
+				   DMA_RESV_USAGE_KERNEL :
+				   DMA_RESV_USAGE_BOOKKEEP);
+	vma->tile_present &= ~BIT(tile->id);
+	if (!vma->tile_present) {
+		list_del_init(&vma->combined_links.rebind);
+		if (xe_vma_is_userptr(vma)) {
+			lockdep_assert_held_read(&vm->userptr.notifier_lock);
+
+			spin_lock(&vm->userptr.invalidated_lock);
+			list_del_init(&to_userptr_vma(vma)->userptr.invalidate_link);
+			spin_unlock(&vm->userptr.invalidated_lock);
+		}
+	}
+}
+
+static void op_commit(struct xe_vm *vm,
+		      struct xe_tile *tile,
+		      struct xe_vm_pgtable_update_ops *pt_update_ops,
+		      struct xe_vma_op *op, struct dma_fence *fence)
+{
+	xe_vm_assert_held(vm);
+
+	switch (op->base.op) {
+	case DRM_GPUVA_OP_MAP:
+		if (!op->map.immediate && xe_vm_in_fault_mode(vm))
+			break;
+
+		bind_op_commit(vm, tile, pt_update_ops, op->map.vma, fence);
+		break;
+	case DRM_GPUVA_OP_REMAP:
+		unbind_op_commit(vm, tile, pt_update_ops,
+				 gpuva_to_vma(op->base.remap.unmap->va), fence);
+
+		if (op->remap.prev)
+			bind_op_commit(vm, tile, pt_update_ops, op->remap.prev,
+				       fence);
+		if (op->remap.next)
+			bind_op_commit(vm, tile, pt_update_ops, op->remap.next,
+				       fence);
+		break;
+	case DRM_GPUVA_OP_UNMAP:
+		unbind_op_commit(vm, tile, pt_update_ops,
+				 gpuva_to_vma(op->base.unmap.va), fence);
+		break;
+	case DRM_GPUVA_OP_PREFETCH:
+		bind_op_commit(vm, tile, pt_update_ops,
+			       gpuva_to_vma(op->base.prefetch.va), fence);
+		break;
+	default:
+		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
+	}
+}
+
+static const struct xe_migrate_pt_update_ops migrate_ops = {
+	.populate = xe_vm_populate_pgtable,
+	.clear = xe_migrate_clear_pgtable_callback,
 	.pre_commit = xe_pt_pre_commit,
 };
 
-static const struct xe_migrate_pt_update_ops userptr_unbind_ops = {
-	.populate = xe_migrate_clear_pgtable_callback,
+static const struct xe_migrate_pt_update_ops userptr_migrate_ops = {
+	.populate = xe_vm_populate_pgtable,
+	.clear = xe_migrate_clear_pgtable_callback,
 	.pre_commit = xe_pt_userptr_pre_commit,
 };
 
 /**
- * __xe_pt_unbind_vma() - Disconnect and free a page-table tree for the vma
- * address range.
- * @tile: The tile to unbind for.
- * @vma: The vma to unbind.
- * @q: The exec_queue with which to do pipelined page-table updates.
- * @syncs: Entries to sync on before disconnecting the tree to be destroyed.
- * @num_syncs: Number of @sync entries.
+ * xe_pt_update_ops_run() - Run PT update operations
+ * @tile: Tile of PT update operations
+ * @vops: VMA operationa
  *
- * This function builds a the xe_vm_pgtable_update entries abstracting the
- * operations needed to detach the page-table tree to be destroyed from the
- * man vm tree.
- * It then takes the relevant locks and submits the operations for
- * pipelined detachment of the gpu page-table from  the vm main tree,
- * (which can be done either by the cpu and the GPU), Finally it frees the
- * detached page-table tree.
+ * Run PT update operations which includes committing internal PT state changes,
+ * creating job for PT update operations for leaf insertion / removal, and
+ * installing job fence in various places.
  *
- * Return: A valid dma-fence representing the pipelined detachment operation
- * on success, an error pointer on error.
+ * Return: fence on success, negative ERR_PTR on error.
  */
 struct dma_fence *
-__xe_pt_unbind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue *q,
-		   struct xe_sync_entry *syncs, u32 num_syncs)
+xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
 {
-	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
-	struct xe_pt_migrate_pt_update unbind_pt_update = {
-		.base = {
-			.ops = xe_vma_is_userptr(vma) ? &userptr_unbind_ops :
-			&unbind_ops,
-			.vma = vma,
-			.tile_id = tile->id,
-		},
-	};
-	struct xe_vm *vm = xe_vma_vm(vma);
-	u32 num_entries;
-	struct dma_fence *fence = NULL;
-	struct invalidation_fence *ifence;
+	struct xe_vm *vm = vops->vm;
+	struct xe_vm_pgtable_update_ops *pt_update_ops =
+		&vops->pt_update_ops[tile->id];
+	struct dma_fence *fence;
+	struct invalidation_fence *ifence = NULL;
 	struct xe_range_fence *rfence;
+	struct xe_vma_op *op;
+	int err = 0;
+	struct xe_migrate_pt_update update = {
+		.ops = pt_update_ops->needs_userptr_lock ?
+			&userptr_migrate_ops :
+			&migrate_ops,
+		.vops = vops,
+		.tile_id = tile->id
+	};
 
-	LLIST_HEAD(deferred);
-
-	xe_bo_assert_held(xe_vma_bo(vma));
+	lockdep_assert_held(&vm->lock);
 	xe_vm_assert_held(vm);
 
-	vm_dbg(&xe_vma_vm(vma)->xe->drm,
-	       "Preparing unbind, with range [%llx...%llx) engine %p.\n",
-	       xe_vma_start(vma), xe_vma_end(vma), q);
-
-	num_entries = xe_pt_stage_unbind(tile, vma, entries);
-	xe_tile_assert(tile, num_entries <= ARRAY_SIZE(entries));
-
-	xe_vm_dbg_print_entries(tile_to_xe(tile), entries, num_entries);
-	xe_pt_calc_rfence_interval(vma, &unbind_pt_update, entries,
-				   num_entries);
-
-	ifence = kzalloc(sizeof(*ifence), GFP_KERNEL);
-	if (!ifence)
-		return ERR_PTR(-ENOMEM);
+	if (pt_update_ops->needs_invalidation) {
+		ifence = kzalloc(sizeof(*ifence), GFP_KERNEL);
+		if (!ifence)
+			return ERR_PTR(-ENOMEM);
+	}
 
 	rfence = kzalloc(sizeof(*rfence), GFP_KERNEL);
 	if (!rfence) {
-		kfree(ifence);
-		return ERR_PTR(-ENOMEM);
+		err = -ENOMEM;
+		goto free_ifence;
 	}
 
-	/*
-	 * Even if we were already evicted and unbind to destroy, we need to
-	 * clear again here. The eviction may have updated pagetables at a
-	 * lower level, because it needs to be more conservative.
-	 */
-	fence = xe_migrate_update_pgtables(tile->migrate,
-					   vm, NULL, q ? q :
-					   vm->q[tile->id],
-					   entries, num_entries,
-					   syncs, num_syncs,
-					   &unbind_pt_update.base);
-	if (!IS_ERR(fence)) {
-		int err;
-
-		err = xe_range_fence_insert(&vm->rftree[tile->id], rfence,
-					    &xe_range_fence_kfree_ops,
-					    unbind_pt_update.base.start,
-					    unbind_pt_update.base.last, fence);
-		if (err)
-			dma_fence_wait(fence, false);
+	fence = xe_migrate_update_pgtables(tile->migrate, &update);
+	if (IS_ERR(fence)) {
+		err = PTR_ERR(fence);
+		goto free_rfence;
+	}
+
+	err = xe_range_fence_insert(&vm->rftree[tile->id], rfence,
+				    &xe_range_fence_kfree_ops,
+				    pt_update_ops->start,
+				    pt_update_ops->last, fence);
+	if (err)
+		dma_fence_wait(fence, false);
 
-		/* TLB invalidation must be done before signaling unbind */
+	/* tlb invalidation must be done before signaling rebind */
+	if (ifence) {
 		err = invalidation_fence_init(tile->primary_gt, ifence, fence,
-					      xe_vma_start(vma),
-					      xe_vma_end(vma),
-					      xe_vma_vm(vma)->usm.asid);
-		if (err) {
-			dma_fence_put(fence);
-			kfree(ifence);
-			return ERR_PTR(err);
-		}
+					      pt_update_ops->start,
+					      pt_update_ops->last,
+					      vm->usm.asid);
+		if (err)
+			goto put_fence;
 		fence = &ifence->base.base;
+	}
 
-		/* add shared fence now for pagetable delayed destroy */
-		dma_resv_add_fence(xe_vm_resv(vm), fence,
-				   DMA_RESV_USAGE_BOOKKEEP);
+	dma_resv_add_fence(xe_vm_resv(vm), fence,
+			   pt_update_ops->wait_vm_bookkeep ?
+			   DMA_RESV_USAGE_KERNEL :
+			   DMA_RESV_USAGE_BOOKKEEP);
 
-		/* This fence will be installed by caller when doing eviction */
-		if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm)
-			dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence,
-					   DMA_RESV_USAGE_BOOKKEEP);
-		xe_pt_commit_unbind(vma, entries, num_entries,
-				    unbind_pt_update.locked ? &deferred : NULL);
-		vma->tile_present &= ~BIT(tile->id);
-	} else {
-		kfree(rfence);
-		kfree(ifence);
-	}
+	list_for_each_entry(op, &vops->list, link)
+		op_commit(vops->vm, tile, pt_update_ops, op, fence);
 
-	if (!vma->tile_present)
-		list_del_init(&vma->combined_links.rebind);
+	if (pt_update_ops->needs_userptr_lock)
+		up_read(&vm->userptr.notifier_lock);
 
-	if (unbind_pt_update.locked) {
-		xe_tile_assert(tile, xe_vma_is_userptr(vma));
+	return fence;
 
-		if (!vma->tile_present) {
-			spin_lock(&vm->userptr.invalidated_lock);
-			list_del_init(&to_userptr_vma(vma)->userptr.invalidate_link);
-			spin_unlock(&vm->userptr.invalidated_lock);
-		}
+put_fence:
+	if (pt_update_ops->needs_userptr_lock)
 		up_read(&vm->userptr.notifier_lock);
-		xe_bo_put_commit(&deferred);
+	dma_fence_put(fence);
+free_rfence:
+	kfree(rfence);
+free_ifence:
+	kfree(ifence);
+
+	return ERR_PTR(err);
+}
+
+/**
+ * xe_pt_update_ops_fini() - Finish PT update operations
+ * @tile: Tile of PT update operations
+ * @vops: VMA operations
+ *
+ * Finish PT update operations by committing to destroy page table memory
+ */
+void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops)
+{
+	struct xe_vm_pgtable_update_ops *pt_update_ops =
+		&vops->pt_update_ops[tile->id];
+	int i;
+
+	lockdep_assert_held(&vops->vm->lock);
+	xe_vm_assert_held(vops->vm);
+
+	/* FIXME: Not 100% correct */
+	for (i = 0; i < pt_update_ops->num_ops; ++i) {
+		struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[i];
+
+		if (pt_op->bind)
+			xe_pt_free_bind(pt_op->entries, pt_op->num_entries);
 	}
+	xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred);
+}
 
-	return fence;
+/**
+ * xe_pt_update_ops_abort() - Abort PT update operations
+ * @tile: Tile of PT update operations
+ * @vops: VMA operationa
+ *
+ *  Abort PT update operations by unwinding internal PT state
+ */
+void xe_pt_update_ops_abort(struct xe_tile *tile, struct xe_vma_ops *vops)
+{
+	lockdep_assert_held(&vops->vm->lock);
+	xe_vm_assert_held(vops->vm);
+
+	/* FIXME: Just kill VM for now + cleanup PTs */
+	xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred);
+	xe_vm_kill(vops->vm, false);
 }
diff --git a/drivers/gpu/drm/xe/xe_pt.h b/drivers/gpu/drm/xe/xe_pt.h
index 71a4fbfcff43..cbf8170d89cc 100644
--- a/drivers/gpu/drm/xe/xe_pt.h
+++ b/drivers/gpu/drm/xe/xe_pt.h
@@ -17,6 +17,7 @@ struct xe_sync_entry;
 struct xe_tile;
 struct xe_vm;
 struct xe_vma;
+struct xe_vma_ops;
 
 /* Largest huge pte is currently 1GiB. May become device dependent. */
 #define MAX_HUGEPTE_LEVEL 2
@@ -34,6 +35,12 @@ void xe_pt_populate_empty(struct xe_tile *tile, struct xe_vm *vm,
 
 void xe_pt_destroy(struct xe_pt *pt, u32 flags, struct llist_head *deferred);
 
+int xe_pt_update_ops_prepare(struct xe_tile *tile, struct xe_vma_ops *vops);
+struct dma_fence *xe_pt_update_ops_run(struct xe_tile *tile,
+				       struct xe_vma_ops *vops);
+void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops);
+void xe_pt_update_ops_abort(struct xe_tile *tile, struct xe_vma_ops *vops);
+
 struct dma_fence *
 __xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue *q,
 		 struct xe_sync_entry *syncs, u32 num_syncs,
diff --git a/drivers/gpu/drm/xe/xe_pt_types.h b/drivers/gpu/drm/xe/xe_pt_types.h
index 2093150f461e..16252f1be055 100644
--- a/drivers/gpu/drm/xe/xe_pt_types.h
+++ b/drivers/gpu/drm/xe/xe_pt_types.h
@@ -86,4 +86,38 @@ struct xe_vm_pgtable_update_op {
 	bool rebind;
 };
 
+/** struct xe_vm_pgtable_update_ops: page table update operations */
+struct xe_vm_pgtable_update_ops {
+	/** @ops: operations */
+	struct xe_vm_pgtable_update_op *ops;
+	/** @deferred: deferred list to destroy PT entries */
+	struct llist_head deferred;
+	/** @q: exec queue for PT operations */
+	struct xe_exec_queue *q;
+	/** @start: start address of ops */
+	u64 start;
+	/** @last: last address of ops */
+	u64 last;
+	/** @num_ops: number of operations */
+	u32 num_ops;
+	/** @current_op: current operations */
+	u32 current_op;
+	/** @needs_userptr_lock: Needs userptr lock */
+	bool needs_userptr_lock;
+	/** @needs_invalidation: Needs invalidation */
+	bool needs_invalidation;
+	/**
+	 * @wait_vm_bookkeep: PT operations need to wait until VM is idle
+	 * (bookkeep dma-resv slots are idle) and stage all future VM activity
+	 * behind these operations (install PT operations into VM kernel
+	 * dma-resv slot).
+	 */
+	bool wait_vm_bookkeep;
+	/**
+	 * @wait_vm_kernel: PT operations need to wait until VM kernel dma-resv
+	 * slots are idle.
+	 */
+	bool wait_vm_kernel;
+};
+
 #endif
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 72e9bdab79d5..47658465b735 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -413,7 +413,7 @@ int __xe_vm_userptr_needs_repin(struct xe_vm *vm)
 
 #define XE_VM_REBIND_RETRY_TIMEOUT_MS 1000
 
-static void xe_vm_kill(struct xe_vm *vm, bool unlocked)
+void xe_vm_kill(struct xe_vm *vm, bool unlocked)
 {
 	struct xe_exec_queue *q;
 
@@ -577,13 +577,9 @@ static void preempt_rebind_work_func(struct work_struct *w)
 		err = PTR_ERR(rebind_fence);
 		goto out_unlock;
 	}
+	dma_fence_put(rebind_fence);
 
-	if (rebind_fence) {
-		dma_fence_wait(rebind_fence, false);
-		dma_fence_put(rebind_fence);
-	}
-
-	/* Wait on munmap style VM unbinds */
+	/* Wait on rebinds */
 	wait = dma_resv_wait_timeout(xe_vm_resv(vm),
 				     DMA_RESV_USAGE_KERNEL,
 				     false, MAX_SCHEDULE_TIMEOUT);
@@ -759,11 +755,35 @@ int xe_vm_userptr_check_repin(struct xe_vm *vm)
  * xe_vm_populate_dummy_rebind() - Populate dummy rebind VMA ops
  * @vm: The VM.
  * @vma: VMA to populate dummy VMA ops
+ * @tile_mask: tile mask for VMA ops
  *
  * Populate dummy VMA ops which can be used to issue a rebind for the VMA
  */
-void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma)
+void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma,
+				 u8 tile_mask)
 {
+	int i;
+
+	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) {
+		if (BIT(i) & tile_mask) {
+			struct xe_vm_pgtable_update_op *pt_op =
+				vm->dummy_ops.vops.pt_update_ops[i].ops;
+
+			memset(&vm->dummy_ops.vops.pt_update_ops[i], 0,
+			       sizeof(vm->dummy_ops.vops.pt_update_ops[i]));
+			vm->dummy_ops.vops.pt_update_ops[i].ops = pt_op;
+			vm->dummy_ops.vops.pt_update_ops[i].num_ops = 1;
+
+			/*
+			 * Wait for VM to be idle / schedule execs + resume
+			 * behind rebinds
+			 */
+			vm->dummy_ops.vops.pt_update_ops[i].wait_vm_bookkeep =
+				true;
+		} else {
+			vm->dummy_ops.vops.pt_update_ops[i].num_ops = 0;
+		}
+	}
 	vm->dummy_ops.op.base.op = DRM_GPUVA_OP_MAP;
 	vm->dummy_ops.op.base.map.va.addr = vma->gpuva.va.addr;
 	vm->dummy_ops.op.base.map.va.range = vma->gpuva.va.range;
@@ -797,7 +817,7 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
 		else
 			trace_xe_vma_rebind_exec(vma);
 
-		xe_vm_populate_dummy_rebind(vm, vma);
+		xe_vm_populate_dummy_rebind(vm, vma, vma->tile_present);
 		fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
 		if (IS_ERR(fence))
 			return fence;
@@ -1653,7 +1673,6 @@ static void vm_destroy_work_func(struct work_struct *w)
 		XE_WARN_ON(vm->pt_root[id]);
 
 	trace_xe_vm_free(vm);
-	dma_fence_put(vm->rebind_fence);
 	xe_vma_ops_fini(&vm->dummy_ops.vops);
 	kfree(vm);
 }
@@ -1691,147 +1710,6 @@ to_wait_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q)
 	return q ? q : vm->q[0];
 }
 
-static struct dma_fence *
-xe_vm_unbind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
-		 struct xe_sync_entry *syncs, u32 num_syncs,
-		 bool first_op, bool last_op)
-{
-	struct xe_vm *vm = xe_vma_vm(vma);
-	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, q);
-	struct xe_tile *tile;
-	struct dma_fence *fence = NULL;
-	struct dma_fence **fences = NULL;
-	struct dma_fence_array *cf = NULL;
-	int cur_fence = 0;
-	int number_tiles = hweight8(vma->tile_present);
-	int err;
-	u8 id;
-
-	trace_xe_vma_unbind(vma);
-
-	if (number_tiles > 1) {
-		fences = kmalloc_array(number_tiles, sizeof(*fences),
-				       GFP_KERNEL);
-		if (!fences)
-			return ERR_PTR(-ENOMEM);
-	}
-
-	for_each_tile(tile, vm->xe, id) {
-		if (!(vma->tile_present & BIT(id)))
-			goto next;
-
-		fence = __xe_pt_unbind_vma(tile, vma, q ? q : vm->q[id],
-					   first_op ? syncs : NULL,
-					   first_op ? num_syncs : 0);
-		if (IS_ERR(fence)) {
-			err = PTR_ERR(fence);
-			goto err_fences;
-		}
-
-		if (fences)
-			fences[cur_fence++] = fence;
-
-next:
-		if (q && vm->pt_root[id] && !list_empty(&q->multi_gt_list))
-			q = list_next_entry(q, multi_gt_list);
-	}
-
-	if (fences) {
-		cf = dma_fence_array_create(number_tiles, fences,
-					    vm->composite_fence_ctx,
-					    vm->composite_fence_seqno++,
-					    false);
-		if (!cf) {
-			--vm->composite_fence_seqno;
-			err = -ENOMEM;
-			goto err_fences;
-		}
-	}
-
-	fence = cf ? &cf->base : !fence ?
-		xe_exec_queue_last_fence_get(wait_exec_queue, vm) : fence;
-
-	return fence;
-
-err_fences:
-	if (fences) {
-		while (cur_fence)
-			dma_fence_put(fences[--cur_fence]);
-		kfree(fences);
-	}
-
-	return ERR_PTR(err);
-}
-
-static struct dma_fence *
-xe_vm_bind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
-	       struct xe_sync_entry *syncs, u32 num_syncs,
-	       u8 tile_mask, bool first_op, bool last_op)
-{
-	struct xe_tile *tile;
-	struct dma_fence *fence;
-	struct dma_fence **fences = NULL;
-	struct dma_fence_array *cf = NULL;
-	struct xe_vm *vm = xe_vma_vm(vma);
-	int cur_fence = 0;
-	int number_tiles = hweight8(vma->tile_mask);
-	int err;
-	u8 id;
-
-	trace_xe_vma_bind(vma);
-
-	if (number_tiles > 1) {
-		fences = kmalloc_array(number_tiles, sizeof(*fences),
-				       GFP_KERNEL);
-		if (!fences)
-			return ERR_PTR(-ENOMEM);
-	}
-
-	for_each_tile(tile, vm->xe, id) {
-		if (!(tile_mask & BIT(id)))
-			goto next;
-
-		fence = __xe_pt_bind_vma(tile, vma, q ? q : vm->q[id],
-					 first_op ? syncs : NULL,
-					 first_op ? num_syncs : 0,
-					 vma->tile_present & BIT(id));
-		if (IS_ERR(fence)) {
-			err = PTR_ERR(fence);
-			goto err_fences;
-		}
-
-		if (fences)
-			fences[cur_fence++] = fence;
-
-next:
-		if (q && vm->pt_root[id] && !list_empty(&q->multi_gt_list))
-			q = list_next_entry(q, multi_gt_list);
-	}
-
-	if (fences) {
-		cf = dma_fence_array_create(number_tiles, fences,
-					    vm->composite_fence_ctx,
-					    vm->composite_fence_seqno++,
-					    false);
-		if (!cf) {
-			--vm->composite_fence_seqno;
-			err = -ENOMEM;
-			goto err_fences;
-		}
-	}
-
-	return cf ? &cf->base : fence;
-
-err_fences:
-	if (fences) {
-		while (cur_fence)
-			dma_fence_put(fences[--cur_fence]);
-		kfree(fences);
-	}
-
-	return ERR_PTR(err);
-}
-
 static struct xe_user_fence *
 find_ufence_get(struct xe_sync_entry *syncs, u32 num_syncs)
 {
@@ -1847,47 +1725,6 @@ find_ufence_get(struct xe_sync_entry *syncs, u32 num_syncs)
 	return NULL;
 }
 
-static struct dma_fence *
-xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue *q,
-	   struct xe_bo *bo, struct xe_sync_entry *syncs, u32 num_syncs,
-	   u8 tile_mask, bool immediate, bool first_op, bool last_op)
-{
-	struct dma_fence *fence;
-	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, q);
-
-	xe_vm_assert_held(vm);
-	xe_bo_assert_held(bo);
-
-	if (immediate) {
-		fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, tile_mask,
-				       first_op, last_op);
-		if (IS_ERR(fence))
-			return fence;
-	} else {
-		xe_assert(vm->xe, xe_vm_in_fault_mode(vm));
-		fence = xe_exec_queue_last_fence_get(wait_exec_queue, vm);
-	}
-
-	return fence;
-}
-
-static struct dma_fence *
-xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
-	     struct xe_exec_queue *q, struct xe_sync_entry *syncs,
-	     u32 num_syncs, bool first_op, bool last_op)
-{
-	struct dma_fence *fence;
-
-	xe_vm_assert_held(vm);
-	xe_bo_assert_held(xe_vma_bo(vma));
-
-	fence = xe_vm_unbind_vma(vma, q, syncs, num_syncs, first_op, last_op);
-	if (IS_ERR(fence))
-		return fence;
-
-	return fence;
-}
-
 #define ALL_DRM_XE_VM_CREATE_FLAGS (DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE | \
 				    DRM_XE_VM_CREATE_FLAG_LR_MODE | \
 				    DRM_XE_VM_CREATE_FLAG_FAULT_MODE)
@@ -2028,21 +1865,6 @@ static const u32 region_to_mem_type[] = {
 	XE_PL_VRAM1,
 };
 
-static struct dma_fence *
-xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
-	       struct xe_exec_queue *q, struct xe_sync_entry *syncs,
-	       u32 num_syncs, bool first_op, bool last_op)
-{
-	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, q);
-
-	if (vma->tile_mask != (vma->tile_present & ~vma->usm.tile_invalidated)) {
-		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs, num_syncs,
-				  vma->tile_mask, true, first_op, last_op);
-	} else {
-		return xe_exec_queue_last_fence_get(wait_exec_queue, vm);
-	}
-}
-
 static void prep_vma_destroy(struct xe_vm *vm, struct xe_vma *vma,
 			     bool post_commit)
 {
@@ -2334,7 +2156,6 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 				   struct xe_vma_ops *vops, bool last)
 {
 	struct xe_device *xe = vm->xe;
-	struct xe_vma_op *last_op = NULL;
 	struct drm_gpuva_op *__op;
 	struct xe_tile *tile;
 	u8 id, tile_mask = 0;
@@ -2348,19 +2169,10 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 	drm_gpuva_for_each_op(__op, ops) {
 		struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
 		struct xe_vma *vma;
-		bool first = list_empty(&vops->list);
 		unsigned int flags = 0;
 
 		INIT_LIST_HEAD(&op->link);
 		list_add_tail(&op->link, &vops->list);
-
-		if (first) {
-			op->flags |= XE_VMA_OP_FIRST;
-			op->num_syncs = num_syncs;
-			op->syncs = syncs;
-		}
-
-		op->q = q;
 		op->tile_mask = tile_mask;
 
 		switch (op->base.op) {
@@ -2471,196 +2283,21 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 		}
 		case DRM_GPUVA_OP_UNMAP:
 		case DRM_GPUVA_OP_PREFETCH:
+			/* FIXME: Need to skip some prefetch ops */
 			xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask);
 			break;
 		default:
 			drm_warn(&vm->xe->drm, "NOT POSSIBLE");
 		}
 
-		last_op = op;
-
 		err = xe_vma_op_commit(vm, op);
 		if (err)
 			return err;
 	}
 
-	/* FIXME: Unhandled corner case */
-	XE_WARN_ON(!last_op && last && !list_empty(&vops->list));
-
-	if (!last_op)
-		return 0;
-
-	if (last) {
-		last_op->flags |= XE_VMA_OP_LAST;
-		last_op->num_syncs = num_syncs;
-		last_op->syncs = syncs;
-	}
-
 	return 0;
 }
 
-static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma *vma,
-				    struct xe_vma_op *op)
-{
-	struct dma_fence *fence = NULL;
-
-	lockdep_assert_held(&vm->lock);
-	xe_vm_assert_held(vm);
-	xe_bo_assert_held(xe_vma_bo(vma));
-
-	switch (op->base.op) {
-	case DRM_GPUVA_OP_MAP:
-		/* FIXME: Override vma->tile_mask for page faults */
-		fence = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
-				   op->syncs, op->num_syncs,
-				   op->map.immediate,
-				   op->tile_mask,
-				   op->flags & XE_VMA_OP_FIRST,
-				   op->flags & XE_VMA_OP_LAST);
-		break;
-	case DRM_GPUVA_OP_REMAP:
-	{
-		bool prev = !!op->remap.prev;
-		bool next = !!op->remap.next;
-
-		if (!op->remap.unmap_done) {
-			if (prev || next)
-				vma->gpuva.flags |= XE_VMA_FIRST_REBIND;
-			fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
-					     op->num_syncs,
-					     op->flags & XE_VMA_OP_FIRST,
-					     op->flags & XE_VMA_OP_LAST &&
-					     !prev && !next);
-			if (IS_ERR(fence))
-				break;
-			op->remap.unmap_done = true;
-		}
-
-		if (prev) {
-			op->remap.prev->gpuva.flags |= XE_VMA_LAST_REBIND;
-			dma_fence_put(fence);
-			fence = xe_vm_bind(vm, op->remap.prev, op->q,
-					   xe_vma_bo(op->remap.prev), op->syncs,
-					   op->num_syncs, op->remap.prev->tile_mask,
-					   true, false,
-					   op->flags & XE_VMA_OP_LAST && !next);
-			op->remap.prev->gpuva.flags &= ~XE_VMA_LAST_REBIND;
-			if (IS_ERR(fence))
-				break;
-			op->remap.prev = NULL;
-		}
-
-		if (next) {
-			op->remap.next->gpuva.flags |= XE_VMA_LAST_REBIND;
-			dma_fence_put(fence);
-			fence = xe_vm_bind(vm, op->remap.next, op->q,
-					   xe_vma_bo(op->remap.next),
-					   op->syncs, op->num_syncs,
-					   op->remap.next->tile_mask, true, false,
-					   op->flags & XE_VMA_OP_LAST);
-			op->remap.next->gpuva.flags &= ~XE_VMA_LAST_REBIND;
-			if (IS_ERR(fence))
-				break;
-			op->remap.next = NULL;
-		}
-
-		break;
-	}
-	case DRM_GPUVA_OP_UNMAP:
-		fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
-				     op->num_syncs, op->flags & XE_VMA_OP_FIRST,
-				     op->flags & XE_VMA_OP_LAST);
-		break;
-	case DRM_GPUVA_OP_PREFETCH:
-		fence = xe_vm_prefetch(vm, vma, op->q, op->syncs, op->num_syncs,
-				       op->flags & XE_VMA_OP_FIRST,
-				       op->flags & XE_VMA_OP_LAST);
-		break;
-	default:
-		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
-	}
-
-	if (IS_ERR(fence))
-		trace_xe_vma_fail(vma);
-
-	return fence;
-}
-
-static struct dma_fence *
-__xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
-		    struct xe_vma_op *op)
-{
-	struct dma_fence *fence;
-	int err;
-
-retry_userptr:
-	fence = op_execute(vm, vma, op);
-	if (IS_ERR(fence) && PTR_ERR(fence) == -EAGAIN) {
-		lockdep_assert_held(&vm->lock);
-
-		if (op->base.op == DRM_GPUVA_OP_REMAP) {
-			if (!op->remap.unmap_done)
-				vma = gpuva_to_vma(op->base.remap.unmap->va);
-			else if (op->remap.prev)
-				vma = op->remap.prev;
-			else
-				vma = op->remap.next;
-		}
-
-		if (xe_vma_is_userptr(vma)) {
-			err = xe_vma_userptr_pin_pages(to_userptr_vma(vma));
-			if (!err)
-				goto retry_userptr;
-
-			fence = ERR_PTR(err);
-			trace_xe_vma_fail(vma);
-		}
-	}
-
-	return fence;
-}
-
-static struct dma_fence *
-xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
-{
-	struct dma_fence *fence = ERR_PTR(-ENOMEM);
-
-	lockdep_assert_held(&vm->lock);
-
-	switch (op->base.op) {
-	case DRM_GPUVA_OP_MAP:
-		fence = __xe_vma_op_execute(vm, op->map.vma, op);
-		break;
-	case DRM_GPUVA_OP_REMAP:
-	{
-		struct xe_vma *vma;
-
-		if (!op->remap.unmap_done)
-			vma = gpuva_to_vma(op->base.remap.unmap->va);
-		else if (op->remap.prev)
-			vma = op->remap.prev;
-		else
-			vma = op->remap.next;
-
-		fence = __xe_vma_op_execute(vm, vma, op);
-		break;
-	}
-	case DRM_GPUVA_OP_UNMAP:
-		fence = __xe_vma_op_execute(vm, gpuva_to_vma(op->base.unmap.va),
-					    op);
-		break;
-	case DRM_GPUVA_OP_PREFETCH:
-		fence = __xe_vma_op_execute(vm,
-					    gpuva_to_vma(op->base.prefetch.va),
-					    op);
-		break;
-	default:
-		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
-	}
-
-	return fence;
-}
-
 static void xe_vma_op_unwind(struct xe_vm *vm, struct xe_vma_op *op,
 			     bool post_commit, bool prev_post_commit,
 			     bool next_post_commit)
@@ -2837,6 +2474,32 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
 	return 0;
 }
 
+static int vm_ops_setup_tile_args(struct xe_vm *vm, struct xe_vma_ops *vops)
+{
+	struct xe_exec_queue *q = vops->q;
+	struct xe_tile *tile;
+	int number_tiles = 0;
+	u8 id;
+
+	for_each_tile(tile, vm->xe, id) {
+		if (vops->pt_update_ops[id].num_ops)
+			++number_tiles;
+
+		if (vops->pt_update_ops[id].q)
+			continue;
+
+		if (q) {
+			vops->pt_update_ops[id].q = q;
+			if (vm->pt_root[id] && !list_empty(&q->multi_gt_list))
+				q = list_next_entry(q, multi_gt_list);
+		} else {
+			vops->pt_update_ops[id].q = vm->q[id];
+		}
+	}
+
+	return number_tiles;
+}
+
 /**
  * xe_vm_ops_execute() - Execute VMA ops
  * @vm: The VM.
@@ -2848,21 +2511,81 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
  */
 struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops *vops)
 {
-	struct xe_vma_op *op, *next;
+	struct xe_tile *tile;
 	struct dma_fence *fence = NULL;
+	struct dma_fence **fences = NULL;
+	struct dma_fence_array *cf = NULL;
+	int number_tiles = 0, current_fence = 0, err;
+	u8 id;
+
+	number_tiles = vm_ops_setup_tile_args(vm, vops);
+	if (number_tiles == 0)
+		return ERR_PTR(-ENODATA);
+
+	if (number_tiles > 1) {
+		fences = kmalloc_array(number_tiles, sizeof(*fences),
+				       GFP_KERNEL);
+		if (!fences)
+			return ERR_PTR(-ENOMEM);
+	}
+
+	for_each_tile(tile, vm->xe, id) {
+		if (!vops->pt_update_ops[id].num_ops)
+			continue;
 
-	list_for_each_entry_safe(op, next, &vops->list, link) {
-		if (!IS_ERR(fence)) {
-			dma_fence_put(fence);
-			fence = xe_vma_op_execute(vm, op);
+		err = xe_pt_update_ops_prepare(tile, vops);
+		if (err) {
+			fence = ERR_PTR(err);
+			goto err_out;
 		}
-		if (IS_ERR(fence)) {
-			drm_warn(&vm->xe->drm, "VM op(%d) failed with %ld",
-				 op->base.op, PTR_ERR(fence));
-			fence = ERR_PTR(-ENOSPC);
+	}
+
+	for_each_tile(tile, vm->xe, id) {
+		if (!vops->pt_update_ops[id].num_ops)
+			continue;
+
+		fence = xe_pt_update_ops_run(tile, vops);
+		if (IS_ERR(fence))
+			goto err_out;
+
+		if (fences)
+			fences[current_fence++] = fence;
+	}
+
+	if (fences) {
+		cf = dma_fence_array_create(number_tiles, fences,
+					    vm->composite_fence_ctx,
+					    vm->composite_fence_seqno++,
+					    false);
+		if (!cf) {
+			--vm->composite_fence_seqno;
+			fence = ERR_PTR(-ENOMEM);
+			goto err_out;
 		}
+		fence = &cf->base;
+	}
+
+	for_each_tile(tile, vm->xe, id) {
+		if (!vops->pt_update_ops[id].num_ops)
+			continue;
+
+		xe_pt_update_ops_fini(tile, vops);
 	}
 
+	return fence;
+
+err_out:
+	for_each_tile(tile, vm->xe, id) {
+		if (!vops->pt_update_ops[id].num_ops)
+			continue;
+
+		xe_pt_update_ops_abort(tile, vops);
+	}
+	while (current_fence)
+		dma_fence_put(fences[--current_fence]);
+	kfree(fences);
+	kfree(cf);
+
 	return fence;
 }
 
@@ -2944,12 +2667,10 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
 		fence = xe_vm_ops_execute(vm, vops);
 		if (IS_ERR(fence)) {
 			err = PTR_ERR(fence);
-			/* FIXME: Killing VM rather than proper error handling */
-			xe_vm_kill(vm, false);
 			goto unlock;
-		} else {
-			vm_bind_ioctl_ops_install_fences(vm, vops, fence);
 		}
+
+		vm_bind_ioctl_ops_install_fences(vm, vops, fence);
 	}
 
 unlock:
diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
index b40160b1be01..8201ecb8f05a 100644
--- a/drivers/gpu/drm/xe/xe_vm.h
+++ b/drivers/gpu/drm/xe/xe_vm.h
@@ -262,9 +262,12 @@ static inline struct dma_resv *xe_vm_resv(struct xe_vm *vm)
  */
 #define xe_vm_assert_held(vm) dma_resv_assert_held(xe_vm_resv(vm))
 
-void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma);
+void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma,
+				 u8 tile_mask);
 struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops *vops);
 
+void xe_vm_kill(struct xe_vm *vm, bool unlocked);
+
 #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_VM)
 #define vm_dbg drm_dbg
 #else
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index f5d740dcbba3..83cb13275904 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -166,29 +166,18 @@ struct xe_vma_op_prefetch {
 
 /** enum xe_vma_op_flags - flags for VMA operation */
 enum xe_vma_op_flags {
-	/** @XE_VMA_OP_FIRST: first VMA operation for a set of syncs */
-	XE_VMA_OP_FIRST			= BIT(0),
-	/** @XE_VMA_OP_LAST: last VMA operation for a set of syncs */
-	XE_VMA_OP_LAST			= BIT(1),
 	/** @XE_VMA_OP_COMMITTED: VMA operation committed */
-	XE_VMA_OP_COMMITTED		= BIT(2),
+	XE_VMA_OP_COMMITTED		= BIT(0),
 	/** @XE_VMA_OP_PREV_COMMITTED: Previous VMA operation committed */
-	XE_VMA_OP_PREV_COMMITTED	= BIT(3),
+	XE_VMA_OP_PREV_COMMITTED	= BIT(1),
 	/** @XE_VMA_OP_NEXT_COMMITTED: Next VMA operation committed */
-	XE_VMA_OP_NEXT_COMMITTED	= BIT(4),
+	XE_VMA_OP_NEXT_COMMITTED	= BIT(2),
 };
 
 /** struct xe_vma_op - VMA operation */
 struct xe_vma_op {
 	/** @base: GPUVA base operation */
 	struct drm_gpuva_op base;
-	/** @q: exec queue for this operation */
-	struct xe_exec_queue *q;
-	/**
-	 * @syncs: syncs for this operation, only used on first and last
-	 * operation
-	 */
-	struct xe_sync_entry *syncs;
 	/** @num_syncs: number of syncs */
 	u32 num_syncs;
 	/** @link: async operation link */
@@ -214,19 +203,14 @@ struct xe_vma_ops {
 	struct list_head list;
 	/** @vm: VM */
 	struct xe_vm *vm;
-	/** @q: exec queue these operations */
+	/** @q: exec queue for VMA operations */
 	struct xe_exec_queue *q;
 	/** @syncs: syncs these operation */
 	struct xe_sync_entry *syncs;
 	/** @num_syncs: number of syncs */
 	u32 num_syncs;
 	/** @pt_update_ops: page table update operations */
-	struct {
-		/** @ops: operations */
-		struct xe_vm_pgtable_update_op *ops;
-		/** @num_ops: number of operations */
-		u32 num_ops;
-	} pt_update_ops[XE_MAX_TILES_PER_DEVICE];
+	struct xe_vm_pgtable_update_ops pt_update_ops[XE_MAX_TILES_PER_DEVICE];
 };
 
 struct xe_vm {
@@ -283,9 +267,6 @@ struct xe_vm {
 	 */
 	struct list_head rebind_list;
 
-	/** @rebind_fence: rebind fence from execbuf */
-	struct dma_fence *rebind_fence;
-
 	/**
 	 * @destroy_work: worker to destroy VM, needed as a dma_fence signaling
 	 * from an irq context can be last put and the destroy needs to be able
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 19/30] drm/xe: Remove old functions defs in xe_pt.h
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (17 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 18/30] drm/xe: Convert multiple bind ops into single job Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-08  5:07 ` [PATCH v4 20/30] drm/xe: Update PT layer with better error handling Matthew Brost
                   ` (17 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

__xe_pt_bind_vma and __xe_pt_unbind_vma are unused, remove these.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_pt.h | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_pt.h b/drivers/gpu/drm/xe/xe_pt.h
index cbf8170d89cc..9ab386431cad 100644
--- a/drivers/gpu/drm/xe/xe_pt.h
+++ b/drivers/gpu/drm/xe/xe_pt.h
@@ -41,15 +41,6 @@ struct dma_fence *xe_pt_update_ops_run(struct xe_tile *tile,
 void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops);
 void xe_pt_update_ops_abort(struct xe_tile *tile, struct xe_vma_ops *vops);
 
-struct dma_fence *
-__xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue *q,
-		 struct xe_sync_entry *syncs, u32 num_syncs,
-		 bool rebind);
-
-struct dma_fence *
-__xe_pt_unbind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue *q,
-		   struct xe_sync_entry *syncs, u32 num_syncs);
-
 bool xe_pt_zap_ptes(struct xe_tile *tile, struct xe_vma *vma);
 
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 20/30] drm/xe: Update PT layer with better error handling
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (18 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 19/30] drm/xe: Remove old functions defs in xe_pt.h Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-08  5:07 ` [PATCH v4 21/30] drm/xe: Update xe_vm_rebind to return int Matthew Brost
                   ` (16 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Update PT layer so if a memory allocation for a PTE fails the error can
be propagated to the user without requiring to be killed.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_pt.c       | 211 ++++++++++++++++++++++++-------
 drivers/gpu/drm/xe/xe_pt_types.h |   2 +
 2 files changed, 165 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 5a8523d0a049..6691efd13911 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -812,19 +812,27 @@ xe_vm_populate_pgtable(struct xe_migrate_pt_update *pt_update, struct xe_tile *t
 	}
 }
 
-static void xe_pt_abort_bind(struct xe_vma *vma,
-			     struct xe_vm_pgtable_update *entries,
-			     u32 num_entries)
+static void xe_pt_cancel_bind(struct xe_vma *vma,
+			      struct xe_vm_pgtable_update *entries,
+			      u32 num_entries)
 {
 	u32 i, j;
 
 	for (i = 0; i < num_entries; i++) {
-		if (!entries[i].pt_entries)
+		struct xe_pt *pt = entries[i].pt;
+
+		if (!pt)
 			continue;
 
-		for (j = 0; j < entries[i].qwords; j++)
-			xe_pt_destroy(entries[i].pt_entries[j].pt, xe_vma_vm(vma)->flags, NULL);
+		if (pt->level) {
+			for (j = 0; j < entries[i].qwords; j++)
+				xe_pt_destroy(entries[i].pt_entries[j].pt,
+					      xe_vma_vm(vma)->flags, NULL);
+		}
+
 		kfree(entries[i].pt_entries);
+		entries[i].pt_entries = NULL;
+		entries[i].qwords = 0;
 	}
 }
 
@@ -840,10 +848,61 @@ static void xe_pt_commit_locks_assert(struct xe_vma *vma)
 	xe_vm_assert_held(vm);
 }
 
-static void xe_pt_commit_bind(struct xe_vma *vma,
-			      struct xe_vm_pgtable_update *entries,
-			      u32 num_entries, bool rebind,
-			      struct llist_head *deferred)
+static void xe_pt_commit(struct xe_vma *vma,
+			 struct xe_vm_pgtable_update *entries,
+			 u32 num_entries, struct llist_head *deferred)
+{
+	u32 i, j;
+
+	xe_pt_commit_locks_assert(vma);
+
+	for (i = 0; i < num_entries; i++) {
+		struct xe_pt *pt = entries[i].pt;
+
+		if (!pt->level)
+			continue;
+
+		for (j = 0; j < entries[i].qwords; j++) {
+			struct xe_pt *oldpte = entries[i].pt_entries[j].pt;
+
+			xe_pt_destroy(oldpte, xe_vma_vm(vma)->flags, deferred);
+		}
+	}
+}
+
+static void xe_pt_abort_bind(struct xe_vma *vma,
+			     struct xe_vm_pgtable_update *entries,
+			     u32 num_entries, bool rebind)
+{
+	int i, j;
+
+	xe_pt_commit_locks_assert(vma);
+
+	for (i = num_entries - 1; i >= 0; --i) {
+		struct xe_pt *pt = entries[i].pt;
+		struct xe_pt_dir *pt_dir;
+
+		if (!rebind)
+			pt->num_live -= entries[i].qwords;
+
+		if (!pt->level)
+			continue;
+
+		pt_dir = as_xe_pt_dir(pt);
+		for (j = 0; j < entries[i].qwords; j++) {
+			u32 j_ = j + entries[i].ofs;
+			struct xe_pt *newpte = xe_pt_entry(pt_dir, j_);
+			struct xe_pt *oldpte = entries[i].pt_entries[j].pt;
+
+			pt_dir->children[j_] = oldpte ? &oldpte->base : 0;
+			xe_pt_destroy(newpte, xe_vma_vm(vma)->flags, NULL);
+		}
+	}
+}
+
+static void xe_pt_commit_prepare_bind(struct xe_vma *vma,
+				      struct xe_vm_pgtable_update *entries,
+				      u32 num_entries, bool rebind)
 {
 	u32 i, j;
 
@@ -863,12 +922,13 @@ static void xe_pt_commit_bind(struct xe_vma *vma,
 		for (j = 0; j < entries[i].qwords; j++) {
 			u32 j_ = j + entries[i].ofs;
 			struct xe_pt *newpte = entries[i].pt_entries[j].pt;
+			struct xe_pt *oldpte = NULL;
 
 			if (xe_pt_entry(pt_dir, j_))
-				xe_pt_destroy(xe_pt_entry(pt_dir, j_),
-					      xe_vma_vm(vma)->flags, deferred);
+				oldpte = xe_pt_entry(pt_dir, j_);
 
 			pt_dir->children[j_] = &newpte->base;
+			entries[i].pt_entries[j].pt = oldpte;
 		}
 	}
 }
@@ -892,8 +952,6 @@ xe_pt_prepare_bind(struct xe_tile *tile, struct xe_vma *vma,
 	err = xe_pt_stage_bind(tile, vma, entries, num_entries);
 	if (!err)
 		xe_tile_assert(tile, *num_entries);
-	else /* abort! */
-		xe_pt_abort_bind(vma, entries, *num_entries);
 
 	return err;
 }
@@ -1383,7 +1441,7 @@ xe_pt_stage_unbind_post_descend(struct xe_ptw *parent, pgoff_t offset,
 				     &end_offset))
 		return 0;
 
-	(void)xe_pt_new_shared(&xe_walk->wupd, xe_child, offset, false);
+	(void)xe_pt_new_shared(&xe_walk->wupd, xe_child, offset, true);
 	xe_walk->wupd.updates[level].update->qwords = end_offset - offset;
 
 	return 0;
@@ -1451,32 +1509,57 @@ xe_migrate_clear_pgtable_callback(struct xe_migrate_pt_update *pt_update,
 		memset64(ptr, empty, num_qwords);
 }
 
+static void xe_pt_abort_unbind(struct xe_vma *vma,
+			       struct xe_vm_pgtable_update *entries,
+			       u32 num_entries)
+{
+	int j, i;
+
+	xe_pt_commit_locks_assert(vma);
+
+	for (j = num_entries - 1; j >= 0; --j) {
+		struct xe_vm_pgtable_update *entry = &entries[j];
+		struct xe_pt *pt = entry->pt;
+		struct xe_pt_dir *pt_dir = as_xe_pt_dir(pt);
+
+		pt->num_live += entry->qwords;
+
+		if (!pt->level)
+			continue;
+
+		for (i = entry->ofs; i < entry->ofs + entry->qwords; i++)
+			pt_dir->children[i] =
+				entries[j].pt_entries[i - entry->ofs].pt ?
+				&entries[j].pt_entries[i - entry->ofs].pt->base : 0;
+	}
+}
+
 static void
-xe_pt_commit_unbind(struct xe_vma *vma,
-		    struct xe_vm_pgtable_update *entries, u32 num_entries,
-		    struct llist_head *deferred)
+xe_pt_commit_prepare_unbind(struct xe_vma *vma,
+			    struct xe_vm_pgtable_update *entries,
+			    u32 num_entries)
 {
-	u32 j;
+	int j, i;
 
 	xe_pt_commit_locks_assert(vma);
 
 	for (j = 0; j < num_entries; ++j) {
 		struct xe_vm_pgtable_update *entry = &entries[j];
 		struct xe_pt *pt = entry->pt;
+		struct xe_pt_dir *pt_dir;
 
 		pt->num_live -= entry->qwords;
-		if (pt->level) {
-			struct xe_pt_dir *pt_dir = as_xe_pt_dir(pt);
-			u32 i;
-
-			for (i = entry->ofs; i < entry->ofs + entry->qwords;
-			     i++) {
-				if (xe_pt_entry(pt_dir, i))
-					xe_pt_destroy(xe_pt_entry(pt_dir, i),
-						      xe_vma_vm(vma)->flags, deferred);
+		if (!pt->level)
+			continue;
 
-				pt_dir->children[i] = NULL;
-			}
+		pt_dir = as_xe_pt_dir(pt);
+		for (i = entry->ofs; i < entry->ofs + entry->qwords; i++) {
+			if (xe_pt_entry(pt_dir, i))
+				entries[j].pt_entries[i - entry->ofs].pt =
+					xe_pt_entry(pt_dir, i);
+			else
+				entries[j].pt_entries[i - entry->ofs].pt = NULL;
+			pt_dir->children[i] = NULL;
 		}
 	}
 }
@@ -1513,7 +1596,6 @@ static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile,
 {
 	u32 current_op = pt_update_ops->current_op;
 	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op];
-	struct llist_head *deferred = &pt_update_ops->deferred;
 	int err;
 
 	xe_bo_assert_held(xe_vma_bo(vma));
@@ -1522,6 +1604,7 @@ static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile,
 	       "Preparing bind, with range [%llx...%llx)\n",
 	       xe_vma_start(vma), xe_vma_end(vma) - 1);
 
+	pt_op->vma = NULL;
 	pt_op->bind = true;
 	pt_op->rebind = BIT(tile->id) & vma->tile_present;
 
@@ -1555,9 +1638,11 @@ static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile,
 			(!pt_op->rebind && vm->scratch_pt[tile->id] &&
 			 xe_vm_in_preempt_fence_mode(vm));
 
-		/* FIXME: Don't commit right away */
-		xe_pt_commit_bind(vma, pt_op->entries, pt_op->num_entries,
-				  pt_op->rebind, deferred);
+		pt_op->vma = vma;
+		xe_pt_commit_prepare_bind(vma, pt_op->entries,
+					  pt_op->num_entries, pt_op->rebind);
+	} else {
+		xe_pt_cancel_bind(vma, pt_op->entries, pt_op->num_entries);
 	}
 
 	return err;
@@ -1569,7 +1654,6 @@ static int unbind_op_prepare(struct xe_tile *tile,
 {
 	u32 current_op = pt_update_ops->current_op;
 	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op];
-	struct llist_head *deferred = &pt_update_ops->deferred;
 
 	xe_bo_assert_held(xe_vma_bo(vma));
 
@@ -1577,6 +1661,7 @@ static int unbind_op_prepare(struct xe_tile *tile,
 	       "Preparing unbind, with range [%llx...%llx)\n",
 	       xe_vma_start(vma), xe_vma_end(vma) - 1);
 
+	pt_op->vma = vma;
 	pt_op->bind = false;
 	pt_op->rebind = false;
 
@@ -1589,9 +1674,7 @@ static int unbind_op_prepare(struct xe_tile *tile,
 	pt_update_ops->needs_userptr_lock |= xe_vma_is_userptr(vma);
 	pt_update_ops->needs_invalidation = true;
 
-	/* FIXME: Don't commit right away */
-	xe_pt_commit_unbind(vma, pt_op->entries, pt_op->num_entries,
-			    deferred);
+	xe_pt_commit_prepare_unbind(vma, pt_op->entries, pt_op->num_entries);
 
 	return 0;
 }
@@ -1806,7 +1889,7 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
 	struct invalidation_fence *ifence = NULL;
 	struct xe_range_fence *rfence;
 	struct xe_vma_op *op;
-	int err = 0;
+	int err = 0, i;
 	struct xe_migrate_pt_update update = {
 		.ops = pt_update_ops->needs_userptr_lock ?
 			&userptr_migrate_ops :
@@ -1820,8 +1903,10 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
 
 	if (pt_update_ops->needs_invalidation) {
 		ifence = kzalloc(sizeof(*ifence), GFP_KERNEL);
-		if (!ifence)
-			return ERR_PTR(-ENOMEM);
+		if (!ifence) {
+			err = -ENOMEM;
+			goto kill_vm_tile1;
+		}
 	}
 
 	rfence = kzalloc(sizeof(*rfence), GFP_KERNEL);
@@ -1830,10 +1915,19 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
 		goto free_ifence;
 	}
 
+	/* FIXME: Point of no return - VM killed if failure after this */
+	for (i = 0; i < pt_update_ops->num_ops; ++i) {
+		struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[i];
+
+		xe_pt_commit(pt_op->vma, pt_op->entries,
+			     pt_op->num_entries, &pt_update_ops->deferred);
+		pt_op->vma = NULL;	/* skip in xe_pt_update_ops_abort */
+	}
+
 	fence = xe_migrate_update_pgtables(tile->migrate, &update);
 	if (IS_ERR(fence)) {
 		err = PTR_ERR(fence);
-		goto free_rfence;
+		goto kill_vm_tile0;
 	}
 
 	err = xe_range_fence_insert(&vm->rftree[tile->id], rfence,
@@ -1871,10 +1965,15 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
 	if (pt_update_ops->needs_userptr_lock)
 		up_read(&vm->userptr.notifier_lock);
 	dma_fence_put(fence);
-free_rfence:
+kill_vm_tile0:
+	if (!tile->id)
+		xe_vm_kill(vops->vm, false);
 	kfree(rfence);
 free_ifence:
 	kfree(ifence);
+kill_vm_tile1:
+	if (tile->id)
+		xe_vm_kill(vops->vm, false);
 
 	return ERR_PTR(err);
 }
@@ -1895,12 +1994,10 @@ void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops)
 	lockdep_assert_held(&vops->vm->lock);
 	xe_vm_assert_held(vops->vm);
 
-	/* FIXME: Not 100% correct */
 	for (i = 0; i < pt_update_ops->num_ops; ++i) {
 		struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[i];
 
-		if (pt_op->bind)
-			xe_pt_free_bind(pt_op->entries, pt_op->num_entries);
+		xe_pt_free_bind(pt_op->entries, pt_op->num_entries);
 	}
 	xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred);
 }
@@ -1914,10 +2011,28 @@ void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops)
  */
 void xe_pt_update_ops_abort(struct xe_tile *tile, struct xe_vma_ops *vops)
 {
+	struct xe_vm_pgtable_update_ops *pt_update_ops =
+		&vops->pt_update_ops[tile->id];
+	int i;
+
 	lockdep_assert_held(&vops->vm->lock);
 	xe_vm_assert_held(vops->vm);
 
-	/* FIXME: Just kill VM for now + cleanup PTs */
+	for (i = pt_update_ops->num_ops - 1; i >= 0; --i) {
+		struct xe_vm_pgtable_update_op *pt_op =
+			&pt_update_ops->ops[i];
+
+		if (!pt_op->vma || i >= pt_update_ops->current_op)
+			continue;
+
+		if (pt_op->bind)
+			xe_pt_abort_bind(pt_op->vma, pt_op->entries,
+					 pt_op->num_entries,
+					 pt_op->rebind);
+		else
+			xe_pt_abort_unbind(pt_op->vma, pt_op->entries,
+					   pt_op->num_entries);
+	}
+
 	xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred);
-	xe_vm_kill(vops->vm, false);
 }
diff --git a/drivers/gpu/drm/xe/xe_pt_types.h b/drivers/gpu/drm/xe/xe_pt_types.h
index 16252f1be055..384cc04de719 100644
--- a/drivers/gpu/drm/xe/xe_pt_types.h
+++ b/drivers/gpu/drm/xe/xe_pt_types.h
@@ -78,6 +78,8 @@ struct xe_vm_pgtable_update {
 struct xe_vm_pgtable_update_op {
 	/** @entries: entries to update for this operation */
 	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
+	/** @vma: VMA for operation, operation not valid if NULL */
+	struct xe_vma *vma;
 	/** @num_entries: number of entries for this update operation */
 	u32 num_entries;
 	/** @bind: is a bind */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 21/30] drm/xe: Update xe_vm_rebind to return int
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (19 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 20/30] drm/xe: Update PT layer with better error handling Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-08  5:07 ` [PATCH v4 22/30] drm/xe: Move vma rebinding to the drm_exec locking loop Matthew Brost
                   ` (15 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Thomas Hellström, Matthew Brost

From: Thomas Hellström <thomas.hellstrom@linux.intel.com>

Now that rebinds are installed in the kernel dma-resv slot the fence
returned from xe_vm_rebind is unused aside from error checking. Update
to xe_vm_rebind to return int.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
 drivers/gpu/drm/xe/xe_exec.c |  8 ++------
 drivers/gpu/drm/xe/xe_vm.c   | 17 +++++++----------
 drivers/gpu/drm/xe/xe_vm.h   |  2 +-
 3 files changed, 10 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
index 4feff67620c4..7d676e3610fa 100644
--- a/drivers/gpu/drm/xe/xe_exec.c
+++ b/drivers/gpu/drm/xe/xe_exec.c
@@ -152,7 +152,6 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 	struct drm_exec *exec = &vm_exec.exec;
 	u32 i, num_syncs = 0, num_ufence = 0;
 	struct xe_sched_job *job;
-	struct dma_fence *rebind_fence;
 	struct xe_vm *vm;
 	bool write_locked, skip_retry = false;
 	ktime_t end = 0;
@@ -289,12 +288,9 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 	 * Rebind any invalidated userptr or evicted BOs in the VM, non-compute
 	 * VM mode only.
 	 */
-	rebind_fence = xe_vm_rebind(vm, false);
-	if (IS_ERR(rebind_fence)) {
-		err = PTR_ERR(rebind_fence);
+	err = xe_vm_rebind(vm, false);
+	if (err)
 		goto err_put_job;
-	}
-	dma_fence_put(rebind_fence);
 
 	/* Wait for rebinds */
 	if (!xe_vm_in_lr_mode(vm)) {
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 47658465b735..47a0d3a6cda5 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -526,7 +526,6 @@ static void preempt_rebind_work_func(struct work_struct *w)
 {
 	struct xe_vm *vm = container_of(w, struct xe_vm, preempt.rebind_work);
 	struct drm_exec exec;
-	struct dma_fence *rebind_fence;
 	unsigned int fence_count = 0;
 	LIST_HEAD(preempt_fences);
 	ktime_t end = 0;
@@ -572,12 +571,9 @@ static void preempt_rebind_work_func(struct work_struct *w)
 	if (err)
 		goto out_unlock;
 
-	rebind_fence = xe_vm_rebind(vm, true);
-	if (IS_ERR(rebind_fence)) {
-		err = PTR_ERR(rebind_fence);
+	err = xe_vm_rebind(vm, true);
+	if (err)
 		goto out_unlock;
-	}
-	dma_fence_put(rebind_fence);
 
 	/* Wait on rebinds */
 	wait = dma_resv_wait_timeout(xe_vm_resv(vm),
@@ -796,14 +792,14 @@ void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma,
 	vm->dummy_ops.op.map.is_null = xe_vma_is_null(vma);
 }
 
-struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
+int xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
 {
 	struct dma_fence *fence = NULL;
 	struct xe_vma *vma, *next;
 
 	lockdep_assert_held(&vm->lock);
 	if (xe_vm_in_lr_mode(vm) && !rebind_worker)
-		return NULL;
+		return 0;
 
 	xe_vm_assert_held(vm);
 	list_for_each_entry_safe(vma, next, &vm->rebind_list,
@@ -820,10 +816,11 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
 		xe_vm_populate_dummy_rebind(vm, vma, vma->tile_present);
 		fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
 		if (IS_ERR(fence))
-			return fence;
+			return PTR_ERR(fence);
 	}
 
-	return fence;
+	dma_fence_put(fence);
+	return 0;
 }
 
 static void xe_vma_free(struct xe_vma *vma)
diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
index 8201ecb8f05a..c849ad0d44b5 100644
--- a/drivers/gpu/drm/xe/xe_vm.h
+++ b/drivers/gpu/drm/xe/xe_vm.h
@@ -207,7 +207,7 @@ int __xe_vm_userptr_needs_repin(struct xe_vm *vm);
 
 int xe_vm_userptr_check_repin(struct xe_vm *vm);
 
-struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker);
+int xe_vm_rebind(struct xe_vm *vm, bool rebind_worker);
 
 int xe_vm_invalidate_vma(struct xe_vma *vma);
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 22/30] drm/xe: Move vma rebinding to the drm_exec locking loop
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (20 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 21/30] drm/xe: Update xe_vm_rebind to return int Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-08  5:07 ` [PATCH v4 23/30] drm/xe: Update VM trace events Matthew Brost
                   ` (14 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Thomas Hellström, Matthew Brost

From: Thomas Hellström <thomas.hellstrom@linux.intel.com>

Rebinding might allocate page-table bos, causing evictions.
To support blocking locking during these evictions,
perform the rebinding in the drm_exec locking loop.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
 drivers/gpu/drm/xe/xe_exec.c | 12 ++++--------
 drivers/gpu/drm/xe/xe_vm.c   | 12 +++++++-----
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
index 7d676e3610fa..7f91b4b13634 100644
--- a/drivers/gpu/drm/xe/xe_exec.c
+++ b/drivers/gpu/drm/xe/xe_exec.c
@@ -106,6 +106,10 @@ static int xe_exec_fn(struct drm_gpuvm_exec *vm_exec)
 	if (ret)
 		return ret;
 
+	ret = xe_vm_rebind(vm, false);
+	if (ret)
+		return ret;
+
 	/*
 	 * 1 fence slot for the final submit, and 1 more for every per-tile for
 	 * GPU bind and 1 extra for CPU bind. Note that there are potentially
@@ -284,14 +288,6 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 		goto err_exec;
 	}
 
-	/*
-	 * Rebind any invalidated userptr or evicted BOs in the VM, non-compute
-	 * VM mode only.
-	 */
-	err = xe_vm_rebind(vm, false);
-	if (err)
-		goto err_put_job;
-
 	/* Wait for rebinds */
 	if (!xe_vm_in_lr_mode(vm)) {
 		err = drm_sched_job_add_resv_dependencies(&job->drm,
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 47a0d3a6cda5..e7bc9c3a8a83 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -519,7 +519,13 @@ static int xe_preempt_work_begin(struct drm_exec *exec, struct xe_vm *vm,
 	if (err)
 		return err;
 
-	return drm_gpuvm_validate(&vm->gpuvm, exec);
+	err = drm_gpuvm_validate(&vm->gpuvm, exec);
+	if (err)
+		return err;
+
+	err = xe_vm_rebind(vm, true);
+
+	return err;
 }
 
 static void preempt_rebind_work_func(struct work_struct *w)
@@ -571,10 +577,6 @@ static void preempt_rebind_work_func(struct work_struct *w)
 	if (err)
 		goto out_unlock;
 
-	err = xe_vm_rebind(vm, true);
-	if (err)
-		goto out_unlock;
-
 	/* Wait on rebinds */
 	wait = dma_resv_wait_timeout(xe_vm_resv(vm),
 				     DMA_RESV_USAGE_KERNEL,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 23/30] drm/xe: Update VM trace events
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (21 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 22/30] drm/xe: Move vma rebinding to the drm_exec locking loop Matthew Brost
@ 2024-03-08  5:07 ` Matthew Brost
  2024-03-08  5:08 ` [PATCH v4 24/30] drm/xe: Update clear / populate arguments Matthew Brost
                   ` (13 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:07 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

The trace events have changed moving to a single job per VM bind IOCTL,
update the trace events align with old behavior as much as possible.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_trace.h | 10 ++++-----
 drivers/gpu/drm/xe/xe_vm.c    | 42 +++++++++++++++++++++++++++++++++--
 2 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h
index 4ddc55527f9a..b7a0e6c1918d 100644
--- a/drivers/gpu/drm/xe/xe_trace.h
+++ b/drivers/gpu/drm/xe/xe_trace.h
@@ -423,11 +423,6 @@ DEFINE_EVENT(xe_vma, xe_vma_acc,
 	     TP_ARGS(vma)
 );
 
-DEFINE_EVENT(xe_vma, xe_vma_fail,
-	     TP_PROTO(struct xe_vma *vma),
-	     TP_ARGS(vma)
-);
-
 DEFINE_EVENT(xe_vma, xe_vma_bind,
 	     TP_PROTO(struct xe_vma *vma),
 	     TP_ARGS(vma)
@@ -541,6 +536,11 @@ DEFINE_EVENT(xe_vm, xe_vm_rebind_worker_exit,
 	     TP_ARGS(vm)
 );
 
+DEFINE_EVENT(xe_vm, xe_vm_ops_fail,
+	     TP_PROTO(struct xe_vm *vm),
+	     TP_ARGS(vm)
+);
+
 /* GuC */
 DECLARE_EVENT_CLASS(xe_guc_ct_flow_control,
 		    TP_PROTO(u32 _head, u32 _tail, u32 size, u32 space, u32 len),
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index e7bc9c3a8a83..cee90302b28d 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -2473,6 +2473,38 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
 	return 0;
 }
 
+static void op_trace(struct xe_vma_op *op)
+{
+	switch (op->base.op) {
+	case DRM_GPUVA_OP_MAP:
+		trace_xe_vma_bind(op->map.vma);
+		break;
+	case DRM_GPUVA_OP_REMAP:
+		trace_xe_vma_unbind(gpuva_to_vma(op->base.remap.unmap->va));
+		if (op->remap.prev)
+			trace_xe_vma_bind(op->remap.prev);
+		if (op->remap.next)
+			trace_xe_vma_bind(op->remap.next);
+		break;
+	case DRM_GPUVA_OP_UNMAP:
+		trace_xe_vma_unbind(gpuva_to_vma(op->base.unmap.va));
+		break;
+	case DRM_GPUVA_OP_PREFETCH:
+		trace_xe_vma_bind(gpuva_to_vma(op->base.prefetch.va));
+		break;
+	default:
+		XE_WARN_ON("NOT POSSIBLE");
+	}
+}
+
+static void trace_xe_vm_ops_execute(struct xe_vma_ops *vops)
+{
+	struct xe_vma_op *op;
+
+	list_for_each_entry(op, &vops->list, link)
+		op_trace(op);
+}
+
 static int vm_ops_setup_tile_args(struct xe_vm *vm, struct xe_vma_ops *vops)
 {
 	struct xe_exec_queue *q = vops->q;
@@ -2524,8 +2556,10 @@ struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops *vops)
 	if (number_tiles > 1) {
 		fences = kmalloc_array(number_tiles, sizeof(*fences),
 				       GFP_KERNEL);
-		if (!fences)
-			return ERR_PTR(-ENOMEM);
+		if (!fences) {
+			fence = ERR_PTR(-ENOMEM);
+			goto err_trace;
+		}
 	}
 
 	for_each_tile(tile, vm->xe, id) {
@@ -2539,6 +2573,8 @@ struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops *vops)
 		}
 	}
 
+	trace_xe_vm_ops_execute(vops);
+
 	for_each_tile(tile, vm->xe, id) {
 		if (!vops->pt_update_ops[id].num_ops)
 			continue;
@@ -2585,6 +2621,8 @@ struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops *vops)
 	kfree(fences);
 	kfree(cf);
 
+err_trace:
+	trace_xe_vm_ops_fail(vm);
 	return fence;
 }
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 24/30] drm/xe: Update clear / populate arguments
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (22 preceding siblings ...)
  2024-03-08  5:07 ` [PATCH v4 23/30] drm/xe: Update VM trace events Matthew Brost
@ 2024-03-08  5:08 ` Matthew Brost
  2024-03-08  5:08 ` [PATCH v4 25/30] drm/xe: Add __xe_migrate_update_pgtables_cpu helper Matthew Brost
                   ` (12 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:08 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

This will help implement CPU binds in run_job() as 'struct
xe_migrate_pt_update' is not available at the time of run_job().

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_migrate.c |  9 +++++----
 drivers/gpu/drm/xe/xe_migrate.h | 12 +++++-------
 drivers/gpu/drm/xe/xe_pt.c      | 12 +++++-------
 3 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index cc0499f3702c..c8cf0a71a1a9 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -1111,6 +1111,7 @@ static void write_pgtable(struct xe_tile *tile, struct xe_bb *bb, u64 ppgtt_ofs,
 			  struct xe_migrate_pt_update *pt_update)
 {
 	const struct xe_migrate_pt_update_ops *ops = pt_update->ops;
+	struct xe_vm *vm = pt_update->vops->vm;
 	u32 chunk;
 	u32 ofs = update->ofs, size = update->qwords;
 
@@ -1142,10 +1143,10 @@ static void write_pgtable(struct xe_tile *tile, struct xe_bb *bb, u64 ppgtt_ofs,
 		bb->cs[bb->len++] = lower_32_bits(addr);
 		bb->cs[bb->len++] = upper_32_bits(addr);
 		if (pt_op->bind)
-			ops->populate(pt_update, tile, NULL, bb->cs + bb->len,
+			ops->populate(tile, NULL, bb->cs + bb->len,
 				      ofs, chunk, update);
 		else
-			ops->clear(pt_update, tile, NULL, bb->cs + bb->len,
+			ops->clear(vm, tile, NULL, bb->cs + bb->len,
 				   ofs, chunk, update);
 
 		bb->len += chunk * 2;
@@ -1202,12 +1203,12 @@ xe_migrate_update_pgtables_cpu(struct xe_migrate *m,
 				&pt_op->entries[i];
 
 			if (pt_op->bind)
-				ops->populate(pt_update, m->tile,
+				ops->populate(m->tile,
 					      &update->pt_bo->vmap, NULL,
 					      update->ofs, update->qwords,
 					      update);
 			else
-				ops->clear(pt_update, m->tile,
+				ops->clear(vm, m->tile,
 					   &update->pt_bo->vmap, NULL,
 					   update->ofs, update->qwords, update);
 		}
diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h
index bd8eba1d3552..18f5a8e40b5c 100644
--- a/drivers/gpu/drm/xe/xe_migrate.h
+++ b/drivers/gpu/drm/xe/xe_migrate.h
@@ -31,7 +31,6 @@ struct xe_vma;
 struct xe_migrate_pt_update_ops {
 	/**
 	 * @populate: Populate a command buffer or page-table with ptes.
-	 * @pt_update: Embeddable callback argument.
 	 * @tile: The tile for the current operation.
 	 * @map: struct iosys_map into the memory to be populated.
 	 * @pos: If @map is NULL, map into the memory to be populated.
@@ -43,13 +42,12 @@ struct xe_migrate_pt_update_ops {
 	 * page-table system to populate command buffers or shared
 	 * page-tables with PTEs.
 	 */
-	void (*populate)(struct xe_migrate_pt_update *pt_update,
-			 struct xe_tile *tile, struct iosys_map *map,
+	void (*populate)(struct xe_tile *tile, struct iosys_map *map,
 			 void *pos, u32 ofs, u32 num_qwords,
 			 const struct xe_vm_pgtable_update *update);
 	/**
 	 * @clear: Clear a command buffer or page-table with ptes.
-	 * @pt_update: Embeddable callback argument.
+	 * @vm: VM being updated
 	 * @tile: The tile for the current operation.
 	 * @map: struct iosys_map into the memory to be populated.
 	 * @pos: If @map is NULL, map into the memory to be populated.
@@ -61,9 +59,9 @@ struct xe_migrate_pt_update_ops {
 	 * page-table system to populate command buffers or shared
 	 * page-tables with PTEs.
 	 */
-	void (*clear)(struct xe_migrate_pt_update *pt_update,
-		      struct xe_tile *tile, struct iosys_map *map,
-		      void *pos, u32 ofs, u32 num_qwords,
+	void (*clear)(struct xe_vm *vm, struct xe_tile *tile,
+		      struct iosys_map *map, void *pos, u32 ofs,
+		      u32 num_qwords,
 		      const struct xe_vm_pgtable_update *update);
 
 	/**
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 6691efd13911..c963ed48cf3b 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -794,9 +794,8 @@ bool xe_pt_zap_ptes(struct xe_tile *tile, struct xe_vma *vma)
 }
 
 static void
-xe_vm_populate_pgtable(struct xe_migrate_pt_update *pt_update, struct xe_tile *tile,
-		       struct iosys_map *map, void *data,
-		       u32 qword_ofs, u32 num_qwords,
+xe_vm_populate_pgtable(struct xe_tile *tile, struct iosys_map *map,
+		       void *data, u32 qword_ofs, u32 num_qwords,
 		       const struct xe_vm_pgtable_update *update)
 {
 	struct xe_pt_entry *ptes = update->pt_entries;
@@ -1489,12 +1488,11 @@ static unsigned int xe_pt_stage_unbind(struct xe_tile *tile, struct xe_vma *vma,
 }
 
 static void
-xe_migrate_clear_pgtable_callback(struct xe_migrate_pt_update *pt_update,
-				  struct xe_tile *tile, struct iosys_map *map,
-				  void *ptr, u32 qword_ofs, u32 num_qwords,
+xe_migrate_clear_pgtable_callback(struct xe_vm *vm, struct xe_tile *tile,
+				  struct iosys_map *map, void *ptr,
+				  u32 qword_ofs, u32 num_qwords,
 				  const struct xe_vm_pgtable_update *update)
 {
-	struct xe_vm *vm = pt_update->vops->vm;
 	u64 empty = __xe_pt_empty_pte(tile, vm, update->pt->level);
 	int i;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 25/30] drm/xe: Add __xe_migrate_update_pgtables_cpu helper
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (23 preceding siblings ...)
  2024-03-08  5:08 ` [PATCH v4 24/30] drm/xe: Update clear / populate arguments Matthew Brost
@ 2024-03-08  5:08 ` Matthew Brost
  2024-03-08  5:08 ` [PATCH v4 26/30] drm/xe: CPU binds for jobs Matthew Brost
                   ` (11 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:08 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

This will help implement CPU binds as the submision backend can call
this helper when a bind jobs dependencies are resolved.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_migrate.c | 54 +++++++++++++++++++--------------
 1 file changed, 31 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index c8cf0a71a1a9..cb0d94c8debb 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -1170,6 +1170,34 @@ struct migrate_test_params {
 	container_of(_priv, struct migrate_test_params, base)
 #endif
 
+static void
+__xe_migrate_update_pgtables_cpu(struct xe_vm *vm, struct xe_tile *tile,
+				 const struct xe_migrate_pt_update_ops *ops,
+				 struct xe_vm_pgtable_update_op *pt_op,
+				 int num_ops)
+{
+	u32 j, i;
+
+	for (j = 0; j < num_ops; ++j, ++pt_op) {
+		for (i = 0; i < pt_op->num_entries; i++) {
+			const struct xe_vm_pgtable_update *update =
+				&pt_op->entries[i];
+
+			if (pt_op->bind)
+				ops->populate(tile, &update->pt_bo->vmap,
+					      NULL, update->ofs, update->qwords,
+					      update);
+			else
+				ops->clear(vm, tile, &update->pt_bo->vmap,
+					   NULL, update->ofs, update->qwords,
+					   update);
+		}
+	}
+
+	trace_xe_vm_cpu_bind(vm);
+	xe_device_wmb(vm->xe);
+}
+
 static struct dma_fence *
 xe_migrate_update_pgtables_cpu(struct xe_migrate *m,
 			       struct xe_migrate_pt_update *pt_update)
@@ -1182,7 +1210,6 @@ xe_migrate_update_pgtables_cpu(struct xe_migrate *m,
 	struct xe_vm_pgtable_update_ops *pt_update_ops =
 		&pt_update->vops->pt_update_ops[pt_update->tile_id];
 	int err;
-	u32 j, i;
 
 	if (XE_TEST_ONLY(test && test->force_gpu))
 		return ERR_PTR(-ETIME);
@@ -1194,28 +1221,9 @@ xe_migrate_update_pgtables_cpu(struct xe_migrate *m,
 			return ERR_PTR(err);
 	}
 
-	for (j = 0; j < pt_update_ops->num_ops; ++j) {
-		const struct xe_vm_pgtable_update_op *pt_op =
-			&pt_update_ops->ops[j];
-
-		for (i = 0; i < pt_op->num_entries; i++) {
-			const struct xe_vm_pgtable_update *update =
-				&pt_op->entries[i];
-
-			if (pt_op->bind)
-				ops->populate(m->tile,
-					      &update->pt_bo->vmap, NULL,
-					      update->ofs, update->qwords,
-					      update);
-			else
-				ops->clear(vm, m->tile,
-					   &update->pt_bo->vmap, NULL,
-					   update->ofs, update->qwords, update);
-		}
-	}
-
-	trace_xe_vm_cpu_bind(vm);
-	xe_device_wmb(vm->xe);
+	__xe_migrate_update_pgtables_cpu(vm, m->tile, ops,
+					 pt_update_ops->ops,
+					 pt_update_ops->num_ops);
 
 	return dma_fence_get_stub();
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 26/30] drm/xe: CPU binds for jobs
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (24 preceding siblings ...)
  2024-03-08  5:08 ` [PATCH v4 25/30] drm/xe: Add __xe_migrate_update_pgtables_cpu helper Matthew Brost
@ 2024-03-08  5:08 ` Matthew Brost
  2024-03-08  5:08 ` [PATCH v4 27/30] drm/xe: Don't use migrate exec queue for page fault binds Matthew Brost
                   ` (10 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:08 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

No reason to use the GPU for binds. In run_job use the CPU to do binds
once the bind job dependencies are resolved.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_bo.c              |   7 +-
 drivers/gpu/drm/xe/xe_bo.h              |   4 +-
 drivers/gpu/drm/xe/xe_bo_types.h        |   2 -
 drivers/gpu/drm/xe/xe_device.c          |  35 +++++
 drivers/gpu/drm/xe/xe_device.h          |   2 +
 drivers/gpu/drm/xe/xe_device_types.h    |   4 +
 drivers/gpu/drm/xe/xe_gt_pagefault.c    |   5 +-
 drivers/gpu/drm/xe/xe_guc_submit.c      |  47 +++++-
 drivers/gpu/drm/xe/xe_migrate.c         | 198 +++---------------------
 drivers/gpu/drm/xe/xe_migrate.h         |   6 +
 drivers/gpu/drm/xe/xe_pt.c              |  36 +++--
 drivers/gpu/drm/xe/xe_pt.h              |   1 +
 drivers/gpu/drm/xe/xe_pt_types.h        |   5 +
 drivers/gpu/drm/xe/xe_sched_job.c       |  37 +++--
 drivers/gpu/drm/xe/xe_sched_job_types.h |  31 +++-
 drivers/gpu/drm/xe/xe_vm.c              | 101 ++++++------
 drivers/gpu/drm/xe/xe_vm.h              |   5 +-
 17 files changed, 254 insertions(+), 272 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index b89ac6db68a1..7a90d269d4dd 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -2265,16 +2265,16 @@ void __xe_bo_release_dummy(struct kref *kref)
 
 /**
  * xe_bo_put_commit() - Put bos whose put was deferred by xe_bo_put_deferred().
+ * @xe: Xe device
  * @deferred: The lockless list used for the call to xe_bo_put_deferred().
  *
  * Puts all bos whose put was deferred by xe_bo_put_deferred().
  * The @deferred list can be either an onstack local list or a global
  * shared list used by a workqueue.
  */
-void xe_bo_put_commit(struct llist_head *deferred)
+void xe_bo_put_commit(struct xe_device *xe, struct llist_head *deferred)
 {
 	struct llist_node *freed;
-	struct xe_bo *bo, *next;
 
 	if (!deferred)
 		return;
@@ -2283,8 +2283,7 @@ void xe_bo_put_commit(struct llist_head *deferred)
 	if (!freed)
 		return;
 
-	llist_for_each_entry_safe(bo, next, freed, freed)
-		drm_gem_object_free(&bo->ttm.base.refcount);
+	xe_device_put_deferred(xe, freed);
 }
 
 /**
diff --git a/drivers/gpu/drm/xe/xe_bo.h b/drivers/gpu/drm/xe/xe_bo.h
index c59ad15961ce..10b2b14b4c0d 100644
--- a/drivers/gpu/drm/xe/xe_bo.h
+++ b/drivers/gpu/drm/xe/xe_bo.h
@@ -10,7 +10,6 @@
 
 #include "xe_bo_types.h"
 #include "xe_macros.h"
-#include "xe_vm_types.h"
 #include "xe_vm.h"
 
 /**
@@ -309,10 +308,11 @@ xe_bo_put_deferred(struct xe_bo *bo, struct llist_head *deferred)
 	if (!kref_put(&bo->ttm.base.refcount, __xe_bo_release_dummy))
 		return false;
 
+	xe_vm_get(bo->vm);
 	return llist_add(&bo->freed, deferred);
 }
 
-void xe_bo_put_commit(struct llist_head *deferred);
+void xe_bo_put_commit(struct xe_device *xe, struct llist_head *deferred);
 
 struct sg_table *xe_bo_sg(struct xe_bo *bo);
 
diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h
index 1ff5b5a68adc..14ef13b7b421 100644
--- a/drivers/gpu/drm/xe/xe_bo_types.h
+++ b/drivers/gpu/drm/xe/xe_bo_types.h
@@ -77,8 +77,6 @@ struct xe_bo {
 	} props;
 	/** @freed: List node for delayed put. */
 	struct llist_node freed;
-	/** @update_index: Update index if PT BO */
-	int update_index;
 	/** @created: Whether the bo has passed initial creation */
 	bool created;
 
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 919ad88f0495..80628bdcfd48 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -226,6 +226,9 @@ static void xe_device_destroy(struct drm_device *dev, void *dummy)
 {
 	struct xe_device *xe = to_xe_device(dev);
 
+	flush_work(&xe->mem.deferred_work);
+	xe_assert(xe, !llist_del_all(&xe->mem.deferred));
+
 	if (xe->ordered_wq)
 		destroy_workqueue(xe->ordered_wq);
 
@@ -235,6 +238,35 @@ static void xe_device_destroy(struct drm_device *dev, void *dummy)
 	ttm_device_fini(&xe->ttm);
 }
 
+void xe_device_put_deferred(struct xe_device *xe, struct llist_node *deferred)
+{
+	struct xe_bo *bo, *next;
+
+	llist_for_each_entry_safe(bo, next, deferred, freed) {
+		init_llist_node(&bo->freed);
+		llist_add(&bo->freed, &xe->mem.deferred);
+	}
+	queue_work(system_wq, &xe->mem.deferred_work);
+}
+
+static void deferred_work(struct work_struct *w)
+{
+	struct xe_device *xe = container_of(w, struct xe_device,
+					    mem.deferred_work);
+	struct llist_node *freed = llist_del_all(&xe->mem.deferred);
+	struct xe_bo *bo, *next;
+
+	if (!freed)
+		return;
+
+	llist_for_each_entry_safe(bo, next, freed, freed) {
+		struct xe_vm *vm = bo->vm;
+
+		drm_gem_object_free(&bo->ttm.base.refcount);
+		xe_vm_put(vm);
+	}
+}
+
 struct xe_device *xe_device_create(struct pci_dev *pdev,
 				   const struct pci_device_id *ent)
 {
@@ -299,6 +331,9 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
 		goto err;
 	}
 
+	init_llist_head(&xe->mem.deferred);
+	INIT_WORK(&xe->mem.deferred_work, deferred_work);
+
 	err = xe_display_create(xe);
 	if (WARN_ON(err))
 		goto err;
diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h
index 14be34d9f543..74eb9833d4d8 100644
--- a/drivers/gpu/drm/xe/xe_device.h
+++ b/drivers/gpu/drm/xe/xe_device.h
@@ -176,4 +176,6 @@ void xe_device_snapshot_print(struct xe_device *xe, struct drm_printer *p);
 u64 xe_device_canonicalize_addr(struct xe_device *xe, u64 address);
 u64 xe_device_uncanonicalize_addr(struct xe_device *xe, u64 address);
 
+void xe_device_put_deferred(struct xe_device *xe, struct llist_node *deferred);
+
 #endif
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 9785eef2e5a4..3d86ab07a5cd 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -315,6 +315,10 @@ struct xe_device {
 		struct xe_mem_region vram;
 		/** @mem.sys_mgr: system TTM manager */
 		struct ttm_resource_manager sys_mgr;
+		/** @mem.deferred: deferred list to destroy PT entries */
+		struct llist_head deferred;
+		/** @mem.deferred_work: worker to destroy PT entries */
+		struct work_struct deferred_work;
 	} mem;
 
 	/** @sriov: device level virtualization data */
diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c
index bd8688b2f462..b4320dba7d03 100644
--- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
+++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
@@ -208,10 +208,13 @@ static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf)
 
 	/* Bind VMA only to the GT that has faulted */
 	trace_xe_vma_pf_bind(vma);
-	xe_vm_populate_dummy_rebind(vm, vma, BIT(tile->id));
+	ret = xe_vm_populate_dummy_rebind(vm, vma, BIT(tile->id));
+	if (ret)
+		goto unlock_dma_resv;
 	vm->dummy_ops.vops.pt_update_ops[tile->id].q =
 		xe_tile_migrate_exec_queue(tile);
 	fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
+	xe_vma_ops_free(&vm->dummy_ops.vops);
 	if (IS_ERR(fence)) {
 		ret = PTR_ERR(fence);
 		goto unlock_dma_resv;
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 19efdb2f881f..09775b1044f4 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -17,6 +17,7 @@
 #include "abi/guc_klvs_abi.h"
 #include "regs/xe_lrc_layout.h"
 #include "xe_assert.h"
+#include "xe_bo.h"
 #include "xe_devcoredump.h"
 #include "xe_device.h"
 #include "xe_exec_queue.h"
@@ -33,7 +34,9 @@
 #include "xe_lrc.h"
 #include "xe_macros.h"
 #include "xe_map.h"
+#include "xe_migrate.h"
 #include "xe_mocs.h"
+#include "xe_pt.h"
 #include "xe_ring_ops_types.h"
 #include "xe_sched_job.h"
 #include "xe_trace.h"
@@ -719,6 +722,29 @@ static void submit_exec_queue(struct xe_exec_queue *q)
 	}
 }
 
+static bool is_pt_job(struct xe_sched_job *job)
+{
+	return test_bit(JOB_FLAG_PT, &job->fence->flags);
+}
+
+static void cleanup_pt_job(struct xe_device *xe, struct xe_sched_job *job)
+{
+	xe_pt_update_ops_free(job->pt_update[0].pt_op,
+			      job->pt_update[0].num_ops);
+	xe_bo_put_commit(xe, &job->pt_update[0].deferred);
+	kfree(job->pt_update[0].pt_op);
+}
+
+static void run_pt_job(struct xe_device *xe, struct xe_sched_job *job)
+{
+	__xe_migrate_update_pgtables_cpu(job->pt_update[0].vm,
+					 job->pt_update[0].tile,
+					 job->pt_update[0].ops,
+					 job->pt_update[0].pt_op,
+					 job->pt_update[0].num_ops);
+	cleanup_pt_job(xe, job);
+}
+
 static struct dma_fence *
 guc_exec_queue_run_job(struct drm_sched_job *drm_job)
 {
@@ -734,15 +760,22 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job)
 	trace_xe_sched_job_run(job);
 
 	if (!exec_queue_killed_or_banned(q) && !xe_sched_job_is_error(job)) {
-		if (!exec_queue_registered(q))
-			register_engine(q);
-		if (!lr)	/* LR jobs are emitted in the exec IOCTL */
-			q->ring_ops->emit_job(job);
-		submit_exec_queue(q);
+		if (is_pt_job(job)) {
+			run_pt_job(xe, job);
+		} else {
+			if (!exec_queue_registered(q))
+				register_engine(q);
+			if (!lr)	/* LR jobs are emitted in the exec IOCTL */
+				q->ring_ops->emit_job(job);
+			submit_exec_queue(q);
+		}
+	} else if (is_pt_job(job)) {
+		cleanup_pt_job(xe, job);
 	}
 
-	if (lr) {
-		xe_sched_job_set_error(job, -EOPNOTSUPP);
+	if (lr || is_pt_job(job)) {
+		if (lr)
+			xe_sched_job_set_error(job, -EOPNOTSUPP);
 		return NULL;
 	} else if (test_and_set_bit(JOB_FLAG_SUBMIT, &job->fence->flags)) {
 		return job->fence;
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index cb0d94c8debb..949e015250af 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -1105,56 +1105,6 @@ struct dma_fence *xe_migrate_clear(struct xe_migrate *m,
 	return fence;
 }
 
-static void write_pgtable(struct xe_tile *tile, struct xe_bb *bb, u64 ppgtt_ofs,
-			  const struct xe_vm_pgtable_update_op *pt_op,
-			  const struct xe_vm_pgtable_update *update,
-			  struct xe_migrate_pt_update *pt_update)
-{
-	const struct xe_migrate_pt_update_ops *ops = pt_update->ops;
-	struct xe_vm *vm = pt_update->vops->vm;
-	u32 chunk;
-	u32 ofs = update->ofs, size = update->qwords;
-
-	/*
-	 * If we have 512 entries (max), we would populate it ourselves,
-	 * and update the PDE above it to the new pointer.
-	 * The only time this can only happen if we have to update the top
-	 * PDE. This requires a BO that is almost vm->size big.
-	 *
-	 * This shouldn't be possible in practice.. might change when 16K
-	 * pages are used. Hence the assert.
-	 */
-	xe_tile_assert(tile, update->qwords < MAX_NUM_PTE);
-	if (!ppgtt_ofs)
-		ppgtt_ofs = xe_migrate_vram_ofs(tile_to_xe(tile),
-						xe_bo_addr(update->pt_bo, 0,
-							   XE_PAGE_SIZE));
-
-	do {
-		u64 addr = ppgtt_ofs + ofs * 8;
-
-		chunk = min(size, MAX_PTE_PER_SDI);
-
-		/* Ensure populatefn can do memset64 by aligning bb->cs */
-		if (!(bb->len & 1))
-			bb->cs[bb->len++] = MI_NOOP;
-
-		bb->cs[bb->len++] = MI_STORE_DATA_IMM | MI_SDI_NUM_QW(chunk);
-		bb->cs[bb->len++] = lower_32_bits(addr);
-		bb->cs[bb->len++] = upper_32_bits(addr);
-		if (pt_op->bind)
-			ops->populate(tile, NULL, bb->cs + bb->len,
-				      ofs, chunk, update);
-		else
-			ops->clear(vm, tile, NULL, bb->cs + bb->len,
-				   ofs, chunk, update);
-
-		bb->len += chunk * 2;
-		ofs += chunk;
-		size -= chunk;
-	} while (size);
-}
-
 struct xe_vm *xe_migrate_get_vm(struct xe_migrate *m)
 {
 	return xe_vm_get(m->q->vm);
@@ -1170,11 +1120,10 @@ struct migrate_test_params {
 	container_of(_priv, struct migrate_test_params, base)
 #endif
 
-static void
-__xe_migrate_update_pgtables_cpu(struct xe_vm *vm, struct xe_tile *tile,
-				 const struct xe_migrate_pt_update_ops *ops,
-				 struct xe_vm_pgtable_update_op *pt_op,
-				 int num_ops)
+void __xe_migrate_update_pgtables_cpu(struct xe_vm *vm, struct xe_tile *tile,
+				      const struct xe_migrate_pt_update_ops *ops,
+				      struct xe_vm_pgtable_update_op *pt_op,
+				      int num_ops)
 {
 	u32 j, i;
 
@@ -1235,131 +1184,15 @@ __xe_migrate_update_pgtables(struct xe_migrate *m,
 {
 	const struct xe_migrate_pt_update_ops *ops = pt_update->ops;
 	struct xe_tile *tile = m->tile;
-	struct xe_gt *gt = tile->primary_gt;
-	struct xe_device *xe = tile_to_xe(tile);
 	struct xe_sched_job *job;
 	struct dma_fence *fence;
-	struct drm_suballoc *sa_bo = NULL;
-	struct xe_bb *bb;
-	u32 i, j, batch_size = 0, ppgtt_ofs, update_idx, page_ofs = 0;
-	u32 num_updates = 0, current_update = 0;
-	u64 addr;
-	int err = 0;
 	bool is_migrate = pt_update_ops->q == m->q;
-	bool usm = is_migrate && xe->info.has_usm;
-
-	for (i = 0; i < pt_update_ops->num_ops; ++i) {
-		struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[i];
-		struct xe_vm_pgtable_update *updates = pt_op->entries;
-
-		num_updates += pt_op->num_entries;
-		for (j = 0; j < pt_op->num_entries; ++j) {
-			u32 num_cmds = DIV_ROUND_UP(updates[j].qwords, 0x1ff);
-
-			/* align noop + MI_STORE_DATA_IMM cmd prefix */
-			batch_size += 4 * num_cmds + updates[j].qwords * 2;
-		}
-	}
-
-	/* fixed + PTE entries */
-	if (IS_DGFX(xe))
-		batch_size += 2;
-	else
-		batch_size += 6 + num_updates * 2;
-
-	bb = xe_bb_new(gt, batch_size, usm);
-	if (IS_ERR(bb))
-		return ERR_CAST(bb);
-
-	/* For sysmem PTE's, need to map them in our hole.. */
-	if (!IS_DGFX(xe)) {
-		ppgtt_ofs = NUM_KERNEL_PDE - 1;
-		if (!is_migrate) {
-			u32 num_units = DIV_ROUND_UP(num_updates,
-						     NUM_VMUSA_WRITES_PER_UNIT);
-
-			sa_bo = drm_suballoc_new(&m->vm_update_sa, num_units,
-						 GFP_KERNEL, true, 0);
-			if (IS_ERR(sa_bo)) {
-				err = PTR_ERR(sa_bo);
-				goto err;
-			}
-
-			ppgtt_ofs = NUM_KERNEL_PDE +
-				(drm_suballoc_soffset(sa_bo) /
-				 NUM_VMUSA_UNIT_PER_PAGE);
-			page_ofs = (drm_suballoc_soffset(sa_bo) %
-				    NUM_VMUSA_UNIT_PER_PAGE) *
-				VM_SA_UPDATE_UNIT_SIZE;
-		}
-
-		/* Map our PT's to gtt */
-		bb->cs[bb->len++] = MI_STORE_DATA_IMM | MI_SDI_NUM_QW(num_updates);
-		bb->cs[bb->len++] = ppgtt_ofs * XE_PAGE_SIZE + page_ofs;
-		bb->cs[bb->len++] = 0; /* upper_32_bits */
-
-		for (i = 0; i < pt_update_ops->num_ops; ++i) {
-			struct xe_vm_pgtable_update_op *pt_op =
-				&pt_update_ops->ops[i];
-			struct xe_vm_pgtable_update *updates = pt_op->entries;
-
-			for (j = 0; j < pt_op->num_entries; ++j, ++current_update) {
-				struct xe_vm *vm = pt_update->vops->vm;
-				struct xe_bo *pt_bo = updates[j].pt_bo;
-
-				xe_tile_assert(tile, pt_bo->size == SZ_4K);
-
-				/* Map a PT at most once */
-				if (pt_bo->update_index < 0)
-					pt_bo->update_index = current_update;
-
-				addr = vm->pt_ops->pte_encode_bo(pt_bo, 0,
-								 XE_CACHE_WB, 0);
-				bb->cs[bb->len++] = lower_32_bits(addr);
-				bb->cs[bb->len++] = upper_32_bits(addr);
-			}
-		}
-
-		bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
-		update_idx = bb->len;
-
-		addr = xe_migrate_vm_addr(ppgtt_ofs, 0) +
-			(page_ofs / sizeof(u64)) * XE_PAGE_SIZE;
-		for (i = 0; i < pt_update_ops->num_ops; ++i) {
-			struct xe_vm_pgtable_update_op *pt_op =
-				&pt_update_ops->ops[i];
-			struct xe_vm_pgtable_update *updates = pt_op->entries;
-
-			for (j = 0; j < pt_op->num_entries; ++j) {
-				struct xe_bo *pt_bo = updates[j].pt_bo;
-
-				write_pgtable(tile, bb, addr +
-					      pt_bo->update_index * XE_PAGE_SIZE,
-					      pt_op, &updates[j], pt_update);
-			}
-		}
-	} else {
-		/* phys pages, no preamble required */
-		bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
-		update_idx = bb->len;
-
-		for (i = 0; i < pt_update_ops->num_ops; ++i) {
-			struct xe_vm_pgtable_update_op *pt_op =
-				&pt_update_ops->ops[i];
-			struct xe_vm_pgtable_update *updates = pt_op->entries;
-
-			for (j = 0; j < pt_op->num_entries; ++j)
-				write_pgtable(tile, bb, 0, pt_op, &updates[j],
-					      pt_update);
-		}
-	}
+	int err;
 
 	if (is_migrate)
 		mutex_lock(&m->job_mutex);
 
-	job = xe_bb_create_migration_job(pt_update_ops->q, bb,
-					 xe_migrate_batch_base(m, usm),
-					 update_idx);
+	job = xe_sched_job_create(pt_update_ops->q, NULL);
 	if (IS_ERR(job)) {
 		err = PTR_ERR(job);
 		goto err_bb;
@@ -1371,6 +1204,19 @@ __xe_migrate_update_pgtables(struct xe_migrate *m,
 		if (err)
 			goto err_job;
 	}
+
+	set_bit(JOB_FLAG_PT, &job->fence->flags);
+	job->pt_update[0].vm = pt_update->vops->vm;
+	job->pt_update[0].tile = tile;
+	job->pt_update[0].ops = ops;
+	job->pt_update[0].pt_op = pt_update_ops->ops;
+	job->pt_update[0].num_ops = pt_update_ops->num_ops;
+	job->pt_update[0].deferred = pt_update_ops->deferred;
+
+	/* Submission backend now owns freeing of pt_update_ops->ops */
+	init_llist_head(&pt_update_ops->deferred);
+	pt_update_ops->skip_free = true;
+
 	xe_sched_job_arm(job);
 	fence = dma_fence_get(&job->drm.s_fence->finished);
 	xe_sched_job_push(job);
@@ -1378,9 +1224,6 @@ __xe_migrate_update_pgtables(struct xe_migrate *m,
 	if (is_migrate)
 		mutex_unlock(&m->job_mutex);
 
-	xe_bb_free(bb, fence);
-	drm_suballoc_free(sa_bo, fence);
-
 	return fence;
 
 err_job:
@@ -1388,9 +1231,6 @@ __xe_migrate_update_pgtables(struct xe_migrate *m,
 err_bb:
 	if (is_migrate)
 		mutex_unlock(&m->job_mutex);
-	xe_bb_free(bb, NULL);
-err:
-	drm_suballoc_free(sa_bo, NULL);
 	return ERR_PTR(err);
 }
 
diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h
index 18f5a8e40b5c..f80c94bb8f4c 100644
--- a/drivers/gpu/drm/xe/xe_migrate.h
+++ b/drivers/gpu/drm/xe/xe_migrate.h
@@ -22,6 +22,7 @@ struct xe_pt;
 struct xe_tile;
 struct xe_vm;
 struct xe_vm_pgtable_update;
+struct xe_vm_pgtable_update_op;
 struct xe_vma;
 
 /**
@@ -106,6 +107,11 @@ struct dma_fence *xe_migrate_clear(struct xe_migrate *m,
 
 struct xe_vm *xe_migrate_get_vm(struct xe_migrate *m);
 
+void __xe_migrate_update_pgtables_cpu(struct xe_vm *vm, struct xe_tile *tile,
+				      const struct xe_migrate_pt_update_ops *ops,
+				      struct xe_vm_pgtable_update_op *pt_op,
+				      int num_ops);
+
 struct dma_fence *
 xe_migrate_update_pgtables(struct xe_migrate *m,
 			   struct xe_migrate_pt_update *pt_update);
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index c963ed48cf3b..c941a73d408a 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -326,7 +326,7 @@ xe_pt_new_shared(struct xe_walk_update *wupd, struct xe_pt *parent,
 	entry->pt = parent;
 	entry->flags = 0;
 	entry->qwords = 0;
-	entry->pt_bo->update_index = -1;
+	entry->level = parent->level;
 
 	if (alloc_entries) {
 		entry->pt_entries = kmalloc_array(XE_PDES,
@@ -1493,7 +1493,7 @@ xe_migrate_clear_pgtable_callback(struct xe_vm *vm, struct xe_tile *tile,
 				  u32 qword_ofs, u32 num_qwords,
 				  const struct xe_vm_pgtable_update *update)
 {
-	u64 empty = __xe_pt_empty_pte(tile, vm, update->pt->level);
+	u64 empty = __xe_pt_empty_pte(tile, vm, update->level);
 	int i;
 
 	if (map && map->is_iomem)
@@ -1913,7 +1913,7 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
 		goto free_ifence;
 	}
 
-	/* FIXME: Point of no return - VM killed if failure after this */
+	/* Point of no return - VM killed if failure after this */
 	for (i = 0; i < pt_update_ops->num_ops; ++i) {
 		struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[i];
 
@@ -1976,6 +1976,21 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
 	return ERR_PTR(err);
 }
 
+/**
+ * xe_pt_update_ops_free() - Free PT update operations
+ * @pt_op: Array of PT update operations
+ * @num_ops: Number of PT update operations
+ *
+ * Free PT update operations
+ */
+void xe_pt_update_ops_free(struct xe_vm_pgtable_update_op *pt_op, u32 num_ops)
+{
+	u32 i;
+
+	for (i = 0; i < num_ops; ++i, ++pt_op)
+		xe_pt_free_bind(pt_op->entries, pt_op->num_entries);
+}
+
 /**
  * xe_pt_update_ops_fini() - Finish PT update operations
  * @tile: Tile of PT update operations
@@ -1987,17 +2002,16 @@ void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops)
 {
 	struct xe_vm_pgtable_update_ops *pt_update_ops =
 		&vops->pt_update_ops[tile->id];
-	int i;
 
 	lockdep_assert_held(&vops->vm->lock);
 	xe_vm_assert_held(vops->vm);
 
-	for (i = 0; i < pt_update_ops->num_ops; ++i) {
-		struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[i];
-
-		xe_pt_free_bind(pt_op->entries, pt_op->num_entries);
-	}
-	xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred);
+	xe_bo_put_commit(tile_to_xe(tile), &pt_update_ops->deferred);
+	if (!pt_update_ops->skip_free)
+		xe_pt_update_ops_free(pt_update_ops->ops,
+				      pt_update_ops->num_ops);
+	else
+		pt_update_ops->ops = NULL;
 }
 
 /**
@@ -2032,5 +2046,5 @@ void xe_pt_update_ops_abort(struct xe_tile *tile, struct xe_vma_ops *vops)
 					   pt_op->num_entries);
 	}
 
-	xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred);
+	xe_pt_update_ops_fini(tile, vops);
 }
diff --git a/drivers/gpu/drm/xe/xe_pt.h b/drivers/gpu/drm/xe/xe_pt.h
index 9ab386431cad..989c9b190fa0 100644
--- a/drivers/gpu/drm/xe/xe_pt.h
+++ b/drivers/gpu/drm/xe/xe_pt.h
@@ -40,6 +40,7 @@ struct dma_fence *xe_pt_update_ops_run(struct xe_tile *tile,
 				       struct xe_vma_ops *vops);
 void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops);
 void xe_pt_update_ops_abort(struct xe_tile *tile, struct xe_vma_ops *vops);
+void xe_pt_update_ops_free(struct xe_vm_pgtable_update_op *pt_op, u32 num_ops);
 
 bool xe_pt_zap_ptes(struct xe_tile *tile, struct xe_vma *vma);
 
diff --git a/drivers/gpu/drm/xe/xe_pt_types.h b/drivers/gpu/drm/xe/xe_pt_types.h
index 384cc04de719..cfd0d35408a5 100644
--- a/drivers/gpu/drm/xe/xe_pt_types.h
+++ b/drivers/gpu/drm/xe/xe_pt_types.h
@@ -70,6 +70,9 @@ struct xe_vm_pgtable_update {
 	/** @pt_entries: Newly added pagetable entries */
 	struct xe_pt_entry *pt_entries;
 
+	/** @level: level of update */
+	unsigned int level;
+
 	/** @flags: Target flags */
 	u32 flags;
 };
@@ -120,6 +123,8 @@ struct xe_vm_pgtable_update_ops {
 	 * slots are idle.
 	 */
 	bool wait_vm_kernel;
+	/** @skip_free: Free @ops in submission backend rather than in IOCTL */
+	bool skip_free;
 };
 
 #endif
diff --git a/drivers/gpu/drm/xe/xe_sched_job.c b/drivers/gpu/drm/xe/xe_sched_job.c
index 8151ddafb940..373033d9ebd6 100644
--- a/drivers/gpu/drm/xe/xe_sched_job.c
+++ b/drivers/gpu/drm/xe/xe_sched_job.c
@@ -23,19 +23,22 @@ static struct kmem_cache *xe_sched_job_parallel_slab;
 
 int __init xe_sched_job_module_init(void)
 {
+	struct xe_sched_job *job;
+	size_t size;
+
+	size = struct_size(job, batch_addr, 1);
 	xe_sched_job_slab =
-		kmem_cache_create("xe_sched_job",
-				  sizeof(struct xe_sched_job) +
-				  sizeof(u64), 0,
+		kmem_cache_create("xe_sched_job", size, 0,
 				  SLAB_HWCACHE_ALIGN, NULL);
 	if (!xe_sched_job_slab)
 		return -ENOMEM;
 
+	size = max_t(size_t,
+		     struct_size(job, batch_addr,
+				 XE_HW_ENGINE_MAX_INSTANCE),
+		     struct_size(job, pt_update, 1));
 	xe_sched_job_parallel_slab =
-		kmem_cache_create("xe_sched_job_parallel",
-				  sizeof(struct xe_sched_job) +
-				  sizeof(u64) *
-				  XE_HW_ENGINE_MAX_INSTANCE, 0,
+		kmem_cache_create("xe_sched_job_parallel", size, 0,
 				  SLAB_HWCACHE_ALIGN, NULL);
 	if (!xe_sched_job_parallel_slab) {
 		kmem_cache_destroy(xe_sched_job_slab);
@@ -108,7 +111,13 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,
 	if (err)
 		goto err_free;
 
-	if (!xe_exec_queue_is_parallel(q)) {
+	if (!batch_addr) {
+		job->fence = dma_fence_allocate_private_stub(ktime_get());
+		if (!job->fence) {
+			err = -ENOMEM;
+			goto err_sched_job;
+		}
+	} else if (!xe_exec_queue_is_parallel(q)) {
 		job->fence = xe_lrc_create_seqno_fence(q->lrc);
 		if (IS_ERR(job->fence)) {
 			err = PTR_ERR(job->fence);
@@ -148,12 +157,14 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,
 		job->fence = &cf->base;
 	}
 
-	width = q->width;
-	if (is_migration)
-		width = 2;
+	if (batch_addr) {
+		width = q->width;
+		if (is_migration)
+			width = 2;
 
-	for (i = 0; i < width; ++i)
-		job->batch_addr[i] = batch_addr[i];
+		for (i = 0; i < width; ++i)
+			job->batch_addr[i] = batch_addr[i];
+	}
 
 	/* All other jobs require a VM to be open which has a ref */
 	if (unlikely(q->flags & EXEC_QUEUE_FLAG_KERNEL))
diff --git a/drivers/gpu/drm/xe/xe_sched_job_types.h b/drivers/gpu/drm/xe/xe_sched_job_types.h
index b1d83da50a53..29ca43d1eb65 100644
--- a/drivers/gpu/drm/xe/xe_sched_job_types.h
+++ b/drivers/gpu/drm/xe/xe_sched_job_types.h
@@ -11,6 +11,28 @@
 #include <drm/gpu_scheduler.h>
 
 struct xe_exec_queue;
+struct xe_migrate_pt_update_ops;
+struct xe_tile;
+struct xe_vm;
+struct xe_vm_pgtable_update_op;
+
+/**
+ * struct pt_update_args - PT update arguments
+ */
+struct pt_update_args {
+	/** @vm: VM */
+	struct xe_vm *vm;
+	/** @tile: Tile */
+	struct xe_tile *tile;
+	/** @ops: Migrate PT update ops */
+	const struct xe_migrate_pt_update_ops *ops;
+	/** @pt_op: PT update ops */
+	struct xe_vm_pgtable_update_op *pt_op;
+	/** @deferred: deferred list to destroy PT entries */
+	struct llist_head deferred;
+	/** @num_ops: number of PT update ops */
+	int num_ops;
+};
 
 /**
  * struct xe_sched_job - XE schedule job (batch buffer tracking)
@@ -27,6 +49,7 @@ struct xe_sched_job {
 	 * can safely reference fence, fence cannot safely reference job.
 	 */
 #define JOB_FLAG_SUBMIT		DMA_FENCE_FLAG_USER_BITS
+#define JOB_FLAG_PT		(DMA_FENCE_FLAG_USER_BITS << 1)
 	struct dma_fence *fence;
 	/** @user_fence: write back value when BB is complete */
 	struct {
@@ -39,8 +62,12 @@ struct xe_sched_job {
 	} user_fence;
 	/** @migrate_flush_flags: Additional flush flags for migration jobs */
 	u32 migrate_flush_flags;
-	/** @batch_addr: batch buffer address of job */
-	u64 batch_addr[];
+	union {
+		/** @batch_addr: batch buffer address of job */
+		DECLARE_FLEX_ARRAY(u64, batch_addr);
+		/** @pt_update: PT update arguments */
+		DECLARE_FLEX_ARRAY(struct pt_update_args, pt_update);
+	};
 };
 
 struct xe_sched_job_snapshot {
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index cee90302b28d..dad8bd10d900 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -749,6 +749,45 @@ int xe_vm_userptr_check_repin(struct xe_vm *vm)
 		list_empty_careful(&vm->userptr.invalidated)) ? 0 : -EAGAIN;
 }
 
+static void xe_vma_ops_init(struct xe_vma_ops *vops, struct xe_vm *vm,
+			    struct xe_exec_queue *q,
+			    struct xe_sync_entry *syncs, u32 num_syncs)
+{
+	memset(vops, 0, sizeof(*vops));
+	INIT_LIST_HEAD(&vops->list);
+	vops->vm = vm;
+	vops->q = q;
+	vops->syncs = syncs;
+	vops->num_syncs = num_syncs;
+}
+
+static int xe_vma_ops_alloc(struct xe_vma_ops *vops)
+{
+	int i;
+
+	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) {
+		if (!vops->pt_update_ops[i].num_ops)
+			continue;
+
+		vops->pt_update_ops[i].ops =
+			kmalloc_array(vops->pt_update_ops[i].num_ops,
+				      sizeof(*vops->pt_update_ops[i].ops),
+				      GFP_KERNEL);
+		if (!vops->pt_update_ops[i].ops)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void xe_vma_ops_free(struct xe_vma_ops *vops)
+{
+	int i;
+
+	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i)
+		kfree(vops->pt_update_ops[i].ops);
+}
+
 /**
  * xe_vm_populate_dummy_rebind() - Populate dummy rebind VMA ops
  * @vm: The VM.
@@ -756,9 +795,11 @@ int xe_vm_userptr_check_repin(struct xe_vm *vm)
  * @tile_mask: tile mask for VMA ops
  *
  * Populate dummy VMA ops which can be used to issue a rebind for the VMA
+ *
+ * Return: 0 on success, -ENOMEM on failure
  */
-void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma,
-				 u8 tile_mask)
+int xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma,
+				u8 tile_mask)
 {
 	int i;
 
@@ -792,12 +833,15 @@ void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma,
 	vm->dummy_ops.op.map.immediate = true;
 	vm->dummy_ops.op.map.dumpable = vma->gpuva.flags & XE_VMA_DUMPABLE;
 	vm->dummy_ops.op.map.is_null = xe_vma_is_null(vma);
+
+	return xe_vma_ops_alloc(&vm->dummy_ops.vops);
 }
 
 int xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
 {
 	struct dma_fence *fence = NULL;
 	struct xe_vma *vma, *next;
+	int err;
 
 	lockdep_assert_held(&vm->lock);
 	if (xe_vm_in_lr_mode(vm) && !rebind_worker)
@@ -815,8 +859,12 @@ int xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
 		else
 			trace_xe_vma_rebind_exec(vma);
 
-		xe_vm_populate_dummy_rebind(vm, vma, vma->tile_present);
+		err = xe_vm_populate_dummy_rebind(vm, vma, vma->tile_present);
+		if (err)
+			return err;
+
 		fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
+		xe_vma_ops_free(&vm->dummy_ops.vops);
 		if (IS_ERR(fence))
 			return PTR_ERR(fence);
 	}
@@ -1326,45 +1374,6 @@ static void xe_vm_free_scratch(struct xe_vm *vm)
 	}
 }
 
-static void xe_vma_ops_init(struct xe_vma_ops *vops, struct xe_vm *vm,
-			    struct xe_exec_queue *q,
-			    struct xe_sync_entry *syncs, u32 num_syncs)
-{
-	memset(vops, 0, sizeof(*vops));
-	INIT_LIST_HEAD(&vops->list);
-	vops->vm = vm;
-	vops->q = q;
-	vops->syncs = syncs;
-	vops->num_syncs = num_syncs;
-}
-
-static int xe_vma_ops_alloc(struct xe_vma_ops *vops)
-{
-	int i;
-
-	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) {
-		if (!vops->pt_update_ops[i].num_ops)
-			continue;
-
-		vops->pt_update_ops[i].ops =
-			kmalloc_array(vops->pt_update_ops[i].num_ops,
-				      sizeof(*vops->pt_update_ops[i].ops),
-				      GFP_KERNEL);
-		if (!vops->pt_update_ops[i].ops)
-			return -ENOMEM;
-	}
-
-	return 0;
-}
-
-static void xe_vma_ops_fini(struct xe_vma_ops *vops)
-{
-	int i;
-
-	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i)
-		kfree(vops->pt_update_ops[i].ops);
-}
-
 static void xe_vma_ops_incr_pt_update_ops(struct xe_vma_ops *vops, u8 tile_mask)
 {
 	int i;
@@ -1400,9 +1409,6 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
 	list_add(&vm->dummy_ops.op.link, &vm->dummy_ops.vops.list);
 	for (id = 0; id < XE_MAX_TILES_PER_DEVICE; ++id)
 		vm->dummy_ops.vops.pt_update_ops[id].num_ops = 1;
-	err = xe_vma_ops_alloc(&vm->dummy_ops.vops);
-	if (err)
-		goto err_free;
 
 	INIT_LIST_HEAD(&vm->rebind_list);
 
@@ -1532,9 +1538,7 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
 		xe_device_mem_access_put(xe);
 	for_each_tile(tile, xe, id)
 		xe_range_fence_tree_fini(&vm->rftree[id]);
-err_free:
 	mutex_destroy(&vm->snap_mutex);
-	xe_vma_ops_fini(&vm->dummy_ops.vops);
 	kfree(vm);
 	return ERR_PTR(err);
 }
@@ -1672,7 +1676,6 @@ static void vm_destroy_work_func(struct work_struct *w)
 		XE_WARN_ON(vm->pt_root[id]);
 
 	trace_xe_vm_free(vm);
-	xe_vma_ops_fini(&vm->dummy_ops.vops);
 	kfree(vm);
 }
 
@@ -3061,7 +3064,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 unwind_ops:
 	if (err && err != -ENODATA)
 		vm_bind_ioctl_ops_unwind(vm, ops, args->num_binds);
-	xe_vma_ops_fini(&vops);
+	xe_vma_ops_free(&vops);
 	for (i = args->num_binds - 1; i >= 0; --i)
 		if (ops[i])
 			drm_gpuva_ops_free(&vm->gpuvm, ops[i]);
diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
index c849ad0d44b5..492237b60341 100644
--- a/drivers/gpu/drm/xe/xe_vm.h
+++ b/drivers/gpu/drm/xe/xe_vm.h
@@ -262,8 +262,9 @@ static inline struct dma_resv *xe_vm_resv(struct xe_vm *vm)
  */
 #define xe_vm_assert_held(vm) dma_resv_assert_held(xe_vm_resv(vm))
 
-void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma,
-				 u8 tile_mask);
+int xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma,
+				u8 tile_mask);
+void xe_vma_ops_free(struct xe_vma_ops *vops);
 struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops *vops);
 
 void xe_vm_kill(struct xe_vm *vm, bool unlocked);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 27/30] drm/xe: Don't use migrate exec queue for page fault binds
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (25 preceding siblings ...)
  2024-03-08  5:08 ` [PATCH v4 26/30] drm/xe: CPU binds for jobs Matthew Brost
@ 2024-03-08  5:08 ` Matthew Brost
  2024-03-08  5:08 ` [PATCH v4 28/30] drm/xe: Add VM bind IOCTL error injection Matthew Brost
                   ` (9 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:08 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Now that the CPU is always used for binds even in jobs, CPU bind jobs
can pass GPU jobs in the same exec queue resulting dma-fences signaling
out-of-order. Use a dedicated exec queue for binds issued from page
faults to avoid ordering issues.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_gt_pagefault.c |  2 +-
 drivers/gpu/drm/xe/xe_migrate.c      | 22 +++++++++++++++++++++-
 drivers/gpu/drm/xe/xe_migrate.h      |  1 +
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c
index b4320dba7d03..e4f5a80a46fc 100644
--- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
+++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
@@ -212,7 +212,7 @@ static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf)
 	if (ret)
 		goto unlock_dma_resv;
 	vm->dummy_ops.vops.pt_update_ops[tile->id].q =
-		xe_tile_migrate_exec_queue(tile);
+		xe_tile_migrate_bind_exec_queue(tile);
 	fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
 	xe_vma_ops_free(&vm->dummy_ops.vops);
 	if (IS_ERR(fence)) {
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index 949e015250af..00a3c87cc93c 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -41,6 +41,8 @@
 struct xe_migrate {
 	/** @q: Default exec queue used for migration */
 	struct xe_exec_queue *q;
+	/** @bind_q: Default exec queue used for binds */
+	struct xe_exec_queue *bind_q;
 	/** @tile: Backpointer to the tile this struct xe_migrate belongs to. */
 	struct xe_tile *tile;
 	/** @job_mutex: Timeline mutex for @eng. */
@@ -97,6 +99,11 @@ struct xe_exec_queue *xe_tile_migrate_exec_queue(struct xe_tile *tile)
 	return tile->migrate->q;
 }
 
+struct xe_exec_queue *xe_tile_migrate_bind_exec_queue(struct xe_tile *tile)
+{
+	return tile->migrate->bind_q;
+}
+
 static void xe_migrate_fini(struct drm_device *dev, void *arg)
 {
 	struct xe_migrate *m = arg;
@@ -111,6 +118,8 @@ static void xe_migrate_fini(struct drm_device *dev, void *arg)
 	mutex_destroy(&m->job_mutex);
 	xe_vm_close_and_put(m->q->vm);
 	xe_exec_queue_put(m->q);
+	if (m->bind_q)
+		xe_exec_queue_put(m->bind_q);
 }
 
 static u64 xe_migrate_vm_addr(u64 slot, u32 level)
@@ -368,6 +377,15 @@ struct xe_migrate *xe_migrate_init(struct xe_tile *tile)
 		if (!hwe || !logical_mask)
 			return ERR_PTR(-EINVAL);
 
+		m->bind_q = xe_exec_queue_create(xe, vm, logical_mask, 1, hwe,
+						 EXEC_QUEUE_FLAG_KERNEL |
+						 EXEC_QUEUE_FLAG_PERMANENT |
+						 EXEC_QUEUE_FLAG_HIGH_PRIORITY, 0);
+		if (IS_ERR(m->bind_q)) {
+			xe_vm_close_and_put(vm);
+			return ERR_CAST(m->bind_q);
+		}
+
 		m->q = xe_exec_queue_create(xe, vm, logical_mask, 1, hwe,
 					    EXEC_QUEUE_FLAG_KERNEL |
 					    EXEC_QUEUE_FLAG_PERMANENT |
@@ -379,6 +397,8 @@ struct xe_migrate *xe_migrate_init(struct xe_tile *tile)
 						  EXEC_QUEUE_FLAG_PERMANENT);
 	}
 	if (IS_ERR(m->q)) {
+		if (m->bind_q)
+			xe_exec_queue_put(m->bind_q);
 		xe_vm_close_and_put(vm);
 		return ERR_CAST(m->q);
 	}
@@ -1186,7 +1206,7 @@ __xe_migrate_update_pgtables(struct xe_migrate *m,
 	struct xe_tile *tile = m->tile;
 	struct xe_sched_job *job;
 	struct dma_fence *fence;
-	bool is_migrate = pt_update_ops->q == m->q;
+	bool is_migrate = pt_update_ops->q == m->bind_q;
 	int err;
 
 	if (is_migrate)
diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h
index f80c94bb8f4c..701bb27349b0 100644
--- a/drivers/gpu/drm/xe/xe_migrate.h
+++ b/drivers/gpu/drm/xe/xe_migrate.h
@@ -119,5 +119,6 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
 void xe_migrate_wait(struct xe_migrate *m);
 
 struct xe_exec_queue *xe_tile_migrate_exec_queue(struct xe_tile *tile);
+struct xe_exec_queue *xe_tile_migrate_bind_exec_queue(struct xe_tile *tile);
 
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 28/30] drm/xe: Add VM bind IOCTL error injection
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (26 preceding siblings ...)
  2024-03-08  5:08 ` [PATCH v4 27/30] drm/xe: Don't use migrate exec queue for page fault binds Matthew Brost
@ 2024-03-08  5:08 ` Matthew Brost
  2024-03-08  5:08 ` [PATCH v4 29/30] drm/xe/guc: Assert time'd out jobs are not from a VM exec queue Matthew Brost
                   ` (8 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:08 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Add VM bind IOCTL error injection which steals MSB of the bind flags
field which if set injects errors at various points in the VM bind
IOCTL. Intended to validate error paths. Enabled by CONFIG_DRM_XE_DEBUG.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_device_types.h | 12 ++++++++++++
 drivers/gpu/drm/xe/xe_pt.c           | 12 ++++++++++++
 drivers/gpu/drm/xe/xe_vm.c           | 20 ++++++++++++++++++++
 drivers/gpu/drm/xe/xe_vm_types.h     | 14 ++++++++++++++
 4 files changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 3d86ab07a5cd..e73b9a086718 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -22,6 +22,10 @@
 #include "xe_sriov_types.h"
 #include "xe_step_types.h"
 
+#if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
+#define TEST_VM_OPS_ERROR
+#endif
+
 #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
 #include "soc/intel_pch.h"
 #include "intel_display_core.h"
@@ -459,6 +463,14 @@ struct xe_device {
 	/** @needs_flr_on_fini: requests function-reset on fini */
 	bool needs_flr_on_fini;
 
+#ifdef TEST_VM_OPS_ERROR
+	/**
+	 * @vm_inject_error_position: inject errors at different places in VM
+	 * bind IOCTL based on this value
+	 */
+	u8 vm_inject_error_position;
+#endif
+
 	/* private: */
 
 #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index c941a73d408a..e0b0f6593ddc 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -1766,6 +1766,12 @@ int xe_pt_update_ops_prepare(struct xe_tile *tile, struct xe_vma_ops *vops)
 	xe_tile_assert(tile, pt_update_ops->current_op ==
 		       pt_update_ops->num_ops);
 
+#ifdef TEST_VM_OPS_ERROR
+	if (vops->inject_error &&
+	    vops->vm->xe->vm_inject_error_position == FORCE_OP_ERROR_PREPARE)
+		return -ENOSPC;
+#endif
+
 	return 0;
 }
 
@@ -1899,6 +1905,12 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
 	lockdep_assert_held(&vm->lock);
 	xe_vm_assert_held(vm);
 
+#ifdef TEST_VM_OPS_ERROR
+	if (vops->inject_error &&
+	    vm->xe->vm_inject_error_position == FORCE_OP_ERROR_RUN)
+		return ERR_PTR(-ENOSPC);
+#endif
+
 	if (pt_update_ops->needs_invalidation) {
 		ifence = kzalloc(sizeof(*ifence), GFP_KERNEL);
 		if (!ifence) {
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index dad8bd10d900..906734b423c5 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -2473,6 +2473,12 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
 			return err;
 	}
 
+#ifdef TEST_VM_OPS_ERROR
+	if (vops->inject_error &&
+	    vm->xe->vm_inject_error_position == FORCE_OP_ERROR_LOCK)
+		return -ENOSPC;
+#endif
+
 	return 0;
 }
 
@@ -2718,8 +2724,13 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
 	return err;
 }
 
+#ifdef TEST_VM_OPS_ERROR
+#define SUPPORTED_FLAGS	(FORCE_OP_ERROR | DRM_XE_VM_BIND_FLAG_NULL | \
+	 DRM_XE_VM_BIND_FLAG_DUMPABLE)
+#else
 #define SUPPORTED_FLAGS	(DRM_XE_VM_BIND_FLAG_NULL | \
 	 DRM_XE_VM_BIND_FLAG_DUMPABLE)
+#endif
 #define XE_64K_PAGE_MASK 0xffffull
 #define ALL_DRM_XE_SYNCS_FLAGS (DRM_XE_SYNCS_FLAG_WAIT_FOR_OP)
 
@@ -3047,6 +3058,15 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 					      &vops, i == args->num_binds - 1);
 		if (err)
 			goto unwind_ops;
+
+#ifdef TEST_VM_OPS_ERROR
+		if (flags & FORCE_OP_ERROR) {
+			vops.inject_error = true;
+			vm->xe->vm_inject_error_position =
+				(vm->xe->vm_inject_error_position + 1) %
+				FORCE_OP_ERROR_COUNT;
+		}
+#endif
 	}
 
 	/* Nothing to do */
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index 83cb13275904..a069989fd82c 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -24,6 +24,16 @@ struct xe_user_fence;
 struct xe_vm;
 struct xe_vm_pgtable_update_op;
 
+#if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
+#define TEST_VM_OPS_ERROR
+#define FORCE_OP_ERROR	BIT(31)
+
+#define FORCE_OP_ERROR_LOCK	0
+#define FORCE_OP_ERROR_PREPARE	1
+#define FORCE_OP_ERROR_RUN	2
+#define FORCE_OP_ERROR_COUNT	3
+#endif
+
 #define XE_VMA_READ_ONLY	DRM_GPUVA_USERBITS
 #define XE_VMA_DESTROYED	(DRM_GPUVA_USERBITS << 1)
 #define XE_VMA_ATOMIC_PTE_BIT	(DRM_GPUVA_USERBITS << 2)
@@ -211,6 +221,10 @@ struct xe_vma_ops {
 	u32 num_syncs;
 	/** @pt_update_ops: page table update operations */
 	struct xe_vm_pgtable_update_ops pt_update_ops[XE_MAX_TILES_PER_DEVICE];
+#ifdef TEST_VM_OPS_ERROR
+	/** @inject_error: inject error to test error handling */
+	bool inject_error;
+#endif
 };
 
 struct xe_vm {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 29/30] drm/xe/guc: Assert time'd out jobs are not from a VM exec queue
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (27 preceding siblings ...)
  2024-03-08  5:08 ` [PATCH v4 28/30] drm/xe: Add VM bind IOCTL error injection Matthew Brost
@ 2024-03-08  5:08 ` Matthew Brost
  2024-03-08  5:08 ` [PATCH v4 30/30] drm/xe: Add PT exec queues Matthew Brost
                   ` (7 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:08 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

With CPU binds jobs cannot timeout, assert this is not happening.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_guc_submit.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 09775b1044f4..c5a88a039afd 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -962,6 +962,8 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
 	int err = -ETIME;
 	int i = 0;
 
+	xe_assert(xe, !(q->flags & EXEC_QUEUE_FLAG_VM));
+
 	/*
 	 * TDR has fired before free job worker. Common if exec queue
 	 * immediately closed after last fence signaled.
@@ -976,8 +978,6 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
 		   xe_sched_job_seqno(job), q->guc->id, q->flags);
 	xe_gt_WARN(q->gt, q->flags & EXEC_QUEUE_FLAG_KERNEL,
 		   "Kernel-submitted job timed out\n");
-	xe_gt_WARN(q->gt, q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q),
-		   "VM job timed out on non-killed execqueue\n");
 
 	simple_error_capture(q);
 	xe_devcoredump(job);
@@ -991,8 +991,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
 	 * Kernel jobs should never fail, nor should VM jobs if they do
 	 * somethings has gone wrong and the GT needs a reset
 	 */
-	if (q->flags & EXEC_QUEUE_FLAG_KERNEL ||
-	    (q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q))) {
+	if (q->flags & EXEC_QUEUE_FLAG_KERNEL) {
 		if (!xe_sched_invalidate_job(job, 2)) {
 			xe_sched_add_pending_job(sched, job);
 			xe_sched_submission_start(sched);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 30/30] drm/xe: Add PT exec queues
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (28 preceding siblings ...)
  2024-03-08  5:08 ` [PATCH v4 29/30] drm/xe/guc: Assert time'd out jobs are not from a VM exec queue Matthew Brost
@ 2024-03-08  5:08 ` Matthew Brost
  2024-03-08  5:42 ` ✓ CI.Patch_applied: success for Refactor VM bind code (rev5) Patchwork
                   ` (6 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-08  5:08 UTC (permalink / raw)
  To: intel-xe; +Cc: Matthew Brost

Add PT exec queues which are used to implement VM bind / unbind
operations. PT exec queues use a different DRM scheduler backend
(compared GuC / execlist submission backends) which use the CPU to
update page tables once all dependecies for a job are resolved.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/Makefile              |   1 +
 drivers/gpu/drm/xe/xe_exec.c             |   2 +-
 drivers/gpu/drm/xe/xe_exec_queue.c       | 120 ++++-----------
 drivers/gpu/drm/xe/xe_exec_queue_types.h |  20 +--
 drivers/gpu/drm/xe/xe_guc_submit.c       |  52 ++-----
 drivers/gpu/drm/xe/xe_migrate.c          |   6 +-
 drivers/gpu/drm/xe/xe_pt_exec_queue.c    | 180 +++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_pt_exec_queue.h    |  14 ++
 drivers/gpu/drm/xe/xe_sched_job.c        |  31 ++--
 drivers/gpu/drm/xe/xe_trace.h            |  11 +-
 drivers/gpu/drm/xe/xe_vm.c               |  58 +++-----
 drivers/gpu/drm/xe/xe_vm_types.h         |   2 +-
 12 files changed, 288 insertions(+), 209 deletions(-)
 create mode 100644 drivers/gpu/drm/xe/xe_pt_exec_queue.c
 create mode 100644 drivers/gpu/drm/xe/xe_pt_exec_queue.h

diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 3c3e67885559..bf43a3690e13 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -118,6 +118,7 @@ xe-y += xe_bb.o \
 	xe_pm.o \
 	xe_preempt_fence.o \
 	xe_pt.o \
+	xe_pt_exec_queue.o \
 	xe_pt_walk.o \
 	xe_query.o \
 	xe_range_fence.o \
diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
index 7f91b4b13634..851d7a261078 100644
--- a/drivers/gpu/drm/xe/xe_exec.c
+++ b/drivers/gpu/drm/xe/xe_exec.c
@@ -170,7 +170,7 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 	if (XE_IOCTL_DBG(xe, !q))
 		return -ENOENT;
 
-	if (XE_IOCTL_DBG(xe, q->flags & EXEC_QUEUE_FLAG_VM))
+	if (XE_IOCTL_DBG(xe, q->flags & EXEC_QUEUE_FLAG_PT))
 		return -EINVAL;
 
 	if (XE_IOCTL_DBG(xe, args->num_batch_buffer &&
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index 6a83bc57826a..149b6ffcda6e 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -19,6 +19,7 @@
 #include "xe_macros.h"
 #include "xe_migrate.h"
 #include "xe_pm.h"
+#include "xe_pt_exec_queue.h"
 #include "xe_ring_ops_types.h"
 #include "xe_trace.h"
 #include "xe_vm.h"
@@ -43,6 +44,8 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
 	struct xe_gt *gt = hwe->gt;
 	int err;
 
+	xe_assert(xe, !(flags & EXEC_QUEUE_FLAG_PT));
+
 	/* only kernel queues can be permanent */
 	XE_WARN_ON((flags & EXEC_QUEUE_FLAG_PERMANENT) && !(flags & EXEC_QUEUE_FLAG_KERNEL));
 
@@ -53,6 +56,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
 	kref_init(&q->refcount);
 	q->flags = flags;
 	q->hwe = hwe;
+	q->xe = xe;
 	q->gt = gt;
 	q->class = hwe->class;
 	q->width = width;
@@ -61,7 +65,6 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
 	q->ring_ops = gt->ring_ops[hwe->class];
 	q->ops = gt->exec_queue_ops;
 	INIT_LIST_HEAD(&q->compute.link);
-	INIT_LIST_HEAD(&q->multi_gt_link);
 
 	q->sched_props.timeslice_us = hwe->eclass->sched_props.timeslice_us;
 	q->sched_props.preempt_timeout_us =
@@ -106,7 +109,7 @@ static void __xe_exec_queue_free(struct xe_exec_queue *q)
 
 static int __xe_exec_queue_init(struct xe_exec_queue *q)
 {
-	struct xe_device *xe = gt_to_xe(q->gt);
+	struct xe_device *xe = q->xe;
 	int i, err;
 
 	for (i = 0; i < q->width; ++i) {
@@ -127,7 +130,7 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q)
 	 * can perform GuC CT actions when needed. Caller is expected to have
 	 * already grabbed the rpm ref outside any sensitive locks.
 	 */
-	if (!(q->flags & EXEC_QUEUE_FLAG_PERMANENT) && (q->flags & EXEC_QUEUE_FLAG_VM || !q->vm))
+	if (!(q->flags & EXEC_QUEUE_FLAG_PERMANENT) && !q->vm)
 		drm_WARN_ON(&xe->drm, !xe_device_mem_access_get_if_ongoing(xe));
 
 	return 0;
@@ -198,15 +201,8 @@ struct xe_exec_queue *xe_exec_queue_create_class(struct xe_device *xe, struct xe
 void xe_exec_queue_destroy(struct kref *ref)
 {
 	struct xe_exec_queue *q = container_of(ref, struct xe_exec_queue, refcount);
-	struct xe_exec_queue *eq, *next;
 
 	xe_exec_queue_last_fence_put_unlocked(q);
-	if (!(q->flags & EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD)) {
-		list_for_each_entry_safe(eq, next, &q->multi_gt_list,
-					 multi_gt_link)
-			xe_exec_queue_put(eq);
-	}
-
 	q->ops->fini(q);
 }
 
@@ -216,7 +212,7 @@ void xe_exec_queue_fini(struct xe_exec_queue *q)
 
 	for (i = 0; i < q->width; ++i)
 		xe_lrc_finish(q->lrc + i);
-	if (!(q->flags & EXEC_QUEUE_FLAG_PERMANENT) && (q->flags & EXEC_QUEUE_FLAG_VM || !q->vm))
+	if (q->gt && !(q->flags & EXEC_QUEUE_FLAG_PERMANENT) && !q->vm)
 		xe_device_mem_access_put(gt_to_xe(q->gt));
 	__xe_exec_queue_free(q);
 }
@@ -454,35 +450,6 @@ find_hw_engine(struct xe_device *xe,
 			       eci.engine_instance, true);
 }
 
-static u32 bind_exec_queue_logical_mask(struct xe_device *xe, struct xe_gt *gt,
-					struct drm_xe_engine_class_instance *eci,
-					u16 width, u16 num_placements)
-{
-	struct xe_hw_engine *hwe;
-	enum xe_hw_engine_id id;
-	u32 logical_mask = 0;
-
-	if (XE_IOCTL_DBG(xe, width != 1))
-		return 0;
-	if (XE_IOCTL_DBG(xe, num_placements != 1))
-		return 0;
-	if (XE_IOCTL_DBG(xe, eci[0].engine_instance != 0))
-		return 0;
-
-	eci[0].engine_class = DRM_XE_ENGINE_CLASS_COPY;
-
-	for_each_hw_engine(hwe, gt, id) {
-		if (xe_hw_engine_is_reserved(hwe))
-			continue;
-
-		if (hwe->class ==
-		    user_to_xe_engine_class[DRM_XE_ENGINE_CLASS_COPY])
-			logical_mask |= BIT(hwe->logical_instance);
-	}
-
-	return logical_mask;
-}
-
 static u32 calc_validate_logical_mask(struct xe_device *xe, struct xe_gt *gt,
 				      struct drm_xe_engine_class_instance *eci,
 				      u16 width, u16 num_placements)
@@ -544,7 +511,7 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
 	struct drm_xe_engine_class_instance __user *user_eci =
 		u64_to_user_ptr(args->instances);
 	struct xe_hw_engine *hwe;
-	struct xe_vm *vm, *migrate_vm;
+	struct xe_vm *vm;
 	struct xe_gt *gt;
 	struct xe_exec_queue *q = NULL;
 	u32 logical_mask;
@@ -570,48 +537,15 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
 		return -EINVAL;
 
 	if (eci[0].engine_class == DRM_XE_ENGINE_CLASS_VM_BIND) {
-		for_each_gt(gt, xe, id) {
-			struct xe_exec_queue *new;
-			u32 flags;
-
-			if (xe_gt_is_media_type(gt))
-				continue;
-
-			eci[0].gt_id = gt->info.id;
-			logical_mask = bind_exec_queue_logical_mask(xe, gt, eci,
-								    args->width,
-								    args->num_placements);
-			if (XE_IOCTL_DBG(xe, !logical_mask))
-				return -EINVAL;
+		if (XE_IOCTL_DBG(xe, args->extensions))
+			return -EINVAL;
 
-			hwe = find_hw_engine(xe, eci[0]);
-			if (XE_IOCTL_DBG(xe, !hwe))
-				return -EINVAL;
-
-			/* The migration vm doesn't hold rpm ref */
-			xe_device_mem_access_get(xe);
-
-			flags = EXEC_QUEUE_FLAG_VM | (id ? EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD : 0);
-
-			migrate_vm = xe_migrate_get_vm(gt_to_tile(gt)->migrate);
-			new = xe_exec_queue_create(xe, migrate_vm, logical_mask,
-						   args->width, hwe, flags,
-						   args->extensions);
-
-			xe_device_mem_access_put(xe); /* now held by engine */
-
-			xe_vm_put(migrate_vm);
-			if (IS_ERR(new)) {
-				err = PTR_ERR(new);
-				if (q)
-					goto put_exec_queue;
-				return err;
-			}
-			if (id == 0)
-				q = new;
-			else
-				list_add_tail(&new->multi_gt_list,
-					      &q->multi_gt_link);
+		xe_device_mem_access_get(xe);
+		q = xe_pt_exec_queue_create(xe);
+		xe_device_mem_access_put(xe); /* now held by exec queue */
+		if (IS_ERR(q)) {
+			err = PTR_ERR(q);
+			return err;
 		}
 	} else {
 		gt = xe_device_get_gt(xe, eci[0].gt_id);
@@ -714,8 +648,7 @@ int xe_exec_queue_get_property_ioctl(struct drm_device *dev, void *data,
  */
 bool xe_exec_queue_is_lr(struct xe_exec_queue *q)
 {
-	return q->vm && xe_vm_in_lr_mode(q->vm) &&
-		!(q->flags & EXEC_QUEUE_FLAG_VM);
+	return q->vm && xe_vm_in_lr_mode(q->vm);
 }
 
 static s32 xe_exec_queue_num_job_inflight(struct xe_exec_queue *q)
@@ -753,6 +686,12 @@ bool xe_exec_queue_ring_full(struct xe_exec_queue *q)
  */
 bool xe_exec_queue_is_idle(struct xe_exec_queue *q)
 {
+	if (q->flags & EXEC_QUEUE_FLAG_PT) {
+		struct dma_fence *fence = q->last_fence ?: dma_fence_get_stub();
+
+		return test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags);
+	}
+
 	if (xe_exec_queue_is_parallel(q)) {
 		int i;
 
@@ -771,16 +710,9 @@ bool xe_exec_queue_is_idle(struct xe_exec_queue *q)
 
 void xe_exec_queue_kill(struct xe_exec_queue *q)
 {
-	struct xe_exec_queue *eq = q, *next;
-
-	list_for_each_entry_safe(eq, next, &eq->multi_gt_list,
-				 multi_gt_link) {
-		q->ops->kill(eq);
-		xe_vm_remove_compute_exec_queue(q->vm, eq);
-	}
-
 	q->ops->kill(q);
-	xe_vm_remove_compute_exec_queue(q->vm, q);
+	if (q->vm)
+		xe_vm_remove_compute_exec_queue(q->vm, q);
 }
 
 int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data,
@@ -812,7 +744,7 @@ int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data,
 static void xe_exec_queue_last_fence_lockdep_assert(struct xe_exec_queue *q,
 						    struct xe_vm *vm)
 {
-	if (q->flags & EXEC_QUEUE_FLAG_VM)
+	if (q->flags & EXEC_QUEUE_FLAG_PT)
 		lockdep_assert_held(&vm->lock);
 	else
 		xe_vm_assert_held(vm);
diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
index 62b3d9d1d7cd..3a2dcaed561f 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
@@ -19,6 +19,7 @@ struct xe_execlist_exec_queue;
 struct xe_gt;
 struct xe_guc_exec_queue;
 struct xe_hw_engine;
+struct xe_pt_exec_queue;
 struct xe_vm;
 
 enum xe_exec_queue_priority {
@@ -38,6 +39,8 @@ enum xe_exec_queue_priority {
  * a kernel object.
  */
 struct xe_exec_queue {
+	/** @xe: Xe device */
+	struct xe_device *xe;
 	/** @gt: graphics tile this exec queue can submit to */
 	struct xe_gt *gt;
 	/**
@@ -78,12 +81,10 @@ struct xe_exec_queue {
 #define EXEC_QUEUE_FLAG_PERMANENT		BIT(2)
 /* queue keeps running pending jobs after destroy ioctl */
 #define EXEC_QUEUE_FLAG_PERSISTENT		BIT(3)
-/* for VM jobs. Caller needs to hold rpm ref when creating queue with this flag */
-#define EXEC_QUEUE_FLAG_VM			BIT(4)
-/* child of VM queue for multi-tile VM jobs */
-#define EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD	BIT(5)
+/* for PT jobs. Caller needs to hold rpm ref when creating queue with this flag */
+#define EXEC_QUEUE_FLAG_PT			BIT(4)
 /* kernel exec_queue only, set priority to highest level */
-#define EXEC_QUEUE_FLAG_HIGH_PRIORITY		BIT(6)
+#define EXEC_QUEUE_FLAG_HIGH_PRIORITY		BIT(5)
 
 	/**
 	 * @flags: flags for this exec queue, should statically setup aside from ban
@@ -91,18 +92,13 @@ struct xe_exec_queue {
 	 */
 	unsigned long flags;
 
-	union {
-		/** @multi_gt_list: list head for VM bind engines if multi-GT */
-		struct list_head multi_gt_list;
-		/** @multi_gt_link: link for VM bind engines if multi-GT */
-		struct list_head multi_gt_link;
-	};
-
 	union {
 		/** @execlist: execlist backend specific state for exec queue */
 		struct xe_execlist_exec_queue *execlist;
 		/** @guc: GuC backend specific state for exec queue */
 		struct xe_guc_exec_queue *guc;
+		/** @pt: PT backend specific state for exec queue */
+		struct xe_pt_exec_queue *pt;
 	};
 
 	/**
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index c5a88a039afd..83dc799589db 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -34,9 +34,7 @@
 #include "xe_lrc.h"
 #include "xe_macros.h"
 #include "xe_map.h"
-#include "xe_migrate.h"
 #include "xe_mocs.h"
-#include "xe_pt.h"
 #include "xe_ring_ops_types.h"
 #include "xe_sched_job.h"
 #include "xe_trace.h"
@@ -727,24 +725,6 @@ static bool is_pt_job(struct xe_sched_job *job)
 	return test_bit(JOB_FLAG_PT, &job->fence->flags);
 }
 
-static void cleanup_pt_job(struct xe_device *xe, struct xe_sched_job *job)
-{
-	xe_pt_update_ops_free(job->pt_update[0].pt_op,
-			      job->pt_update[0].num_ops);
-	xe_bo_put_commit(xe, &job->pt_update[0].deferred);
-	kfree(job->pt_update[0].pt_op);
-}
-
-static void run_pt_job(struct xe_device *xe, struct xe_sched_job *job)
-{
-	__xe_migrate_update_pgtables_cpu(job->pt_update[0].vm,
-					 job->pt_update[0].tile,
-					 job->pt_update[0].ops,
-					 job->pt_update[0].pt_op,
-					 job->pt_update[0].num_ops);
-	cleanup_pt_job(xe, job);
-}
-
 static struct dma_fence *
 guc_exec_queue_run_job(struct drm_sched_job *drm_job)
 {
@@ -754,28 +734,23 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job)
 	struct xe_device *xe = guc_to_xe(guc);
 	bool lr = xe_exec_queue_is_lr(q);
 
+	xe_assert(xe, !is_pt_job(job));
+	xe_assert(xe, !(q->flags & EXEC_QUEUE_FLAG_PT));
 	xe_assert(xe, !(exec_queue_destroyed(q) || exec_queue_pending_disable(q)) ||
 		  exec_queue_banned(q) || exec_queue_suspended(q));
 
 	trace_xe_sched_job_run(job);
 
 	if (!exec_queue_killed_or_banned(q) && !xe_sched_job_is_error(job)) {
-		if (is_pt_job(job)) {
-			run_pt_job(xe, job);
-		} else {
-			if (!exec_queue_registered(q))
-				register_engine(q);
-			if (!lr)	/* LR jobs are emitted in the exec IOCTL */
-				q->ring_ops->emit_job(job);
-			submit_exec_queue(q);
-		}
-	} else if (is_pt_job(job)) {
-		cleanup_pt_job(xe, job);
+		if (!exec_queue_registered(q))
+			register_engine(q);
+		if (!lr)	/* LR jobs are emitted in the exec IOCTL */
+			q->ring_ops->emit_job(job);
+		submit_exec_queue(q);
 	}
 
-	if (lr || is_pt_job(job)) {
-		if (lr)
-			xe_sched_job_set_error(job, -EOPNOTSUPP);
+	if (lr) {
+		xe_sched_job_set_error(job, -EOPNOTSUPP);
 		return NULL;
 	} else if (test_and_set_bit(JOB_FLAG_SUBMIT, &job->fence->flags)) {
 		return job->fence;
@@ -962,7 +937,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
 	int err = -ETIME;
 	int i = 0;
 
-	xe_assert(xe, !(q->flags & EXEC_QUEUE_FLAG_VM));
+	xe_assert(xe, !(q->flags & EXEC_QUEUE_FLAG_PT));
 
 	/*
 	 * TDR has fired before free job worker. Common if exec queue
@@ -1471,11 +1446,10 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q)
 	trace_xe_exec_queue_stop(q);
 
 	/*
-	 * Ban any engine (aside from kernel and engines used for VM ops) with a
-	 * started but not complete job or if a job has gone through a GT reset
-	 * more than twice.
+	 * Ban any engine (aside from kernel) with a started but not complete
+	 * job or if a job has gone through a GT reset more than twice.
 	 */
-	if (!(q->flags & (EXEC_QUEUE_FLAG_KERNEL | EXEC_QUEUE_FLAG_VM))) {
+	if (!(q->flags & EXEC_QUEUE_FLAG_KERNEL)) {
 		struct xe_sched_job *job = xe_sched_first_pending_job(sched);
 
 		if (job) {
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index 00a3c87cc93c..82b63bdb9c47 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -28,6 +28,7 @@
 #include "xe_map.h"
 #include "xe_mocs.h"
 #include "xe_pt.h"
+#include "xe_pt_exec_queue.h"
 #include "xe_res_cursor.h"
 #include "xe_sched_job.h"
 #include "xe_sync.h"
@@ -377,10 +378,7 @@ struct xe_migrate *xe_migrate_init(struct xe_tile *tile)
 		if (!hwe || !logical_mask)
 			return ERR_PTR(-EINVAL);
 
-		m->bind_q = xe_exec_queue_create(xe, vm, logical_mask, 1, hwe,
-						 EXEC_QUEUE_FLAG_KERNEL |
-						 EXEC_QUEUE_FLAG_PERMANENT |
-						 EXEC_QUEUE_FLAG_HIGH_PRIORITY, 0);
+		m->bind_q = xe_pt_exec_queue_create(xe);
 		if (IS_ERR(m->bind_q)) {
 			xe_vm_close_and_put(vm);
 			return ERR_CAST(m->bind_q);
diff --git a/drivers/gpu/drm/xe/xe_pt_exec_queue.c b/drivers/gpu/drm/xe/xe_pt_exec_queue.c
new file mode 100644
index 000000000000..2a6ae6267594
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_pt_exec_queue.c
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#include <drm/gpu_scheduler.h>
+
+#include "xe_bo.h"
+#include "xe_device.h"
+#include "xe_exec_queue.h"
+#include "xe_migrate.h"
+#include "xe_pt.h"
+#include "xe_pt_exec_queue.h"
+#include "xe_sched_job.h"
+#include "xe_trace.h"
+
+/**
+ * struct xe_pt_exec_queue - PT specific state for an xe_exec_queue
+ */
+struct xe_pt_exec_queue {
+	/** @q: Backpointer to parent xe_exec_queue */
+	struct xe_exec_queue *q;
+	/** @sched: GPU scheduler for this xe_exec_queue */
+	struct drm_gpu_scheduler sched;
+	/** @entity: Scheduler entity for this xe_exec_queue */
+	struct drm_sched_entity entity;
+	/** @fini_async: do final fini async from this worker */
+	struct work_struct fini_async;
+};
+
+static bool is_pt_job(struct xe_sched_job *job)
+{
+	return test_bit(JOB_FLAG_PT, &job->fence->flags);
+}
+
+static void cleanup_pt_job(struct xe_device *xe, struct xe_sched_job *job)
+{
+	xe_pt_update_ops_free(job->pt_update[0].pt_op,
+			      job->pt_update[0].num_ops);
+	xe_bo_put_commit(xe, &job->pt_update[0].deferred);
+	kfree(job->pt_update[0].pt_op);
+}
+
+static void run_pt_job(struct xe_device *xe, struct xe_sched_job *job)
+{
+	__xe_migrate_update_pgtables_cpu(job->pt_update[0].vm,
+					 job->pt_update[0].tile,
+					 job->pt_update[0].ops,
+					 job->pt_update[0].pt_op,
+					 job->pt_update[0].num_ops);
+	cleanup_pt_job(xe, job);
+}
+
+static struct dma_fence *
+pt_exec_queue_run_job(struct drm_sched_job *drm_job)
+{
+	struct xe_sched_job *job = to_xe_sched_job(drm_job);
+	struct xe_exec_queue *q = job->q;
+	struct xe_device *xe = q->xe;
+
+	xe_assert(xe, is_pt_job(job));
+	xe_assert(xe, q->flags & EXEC_QUEUE_FLAG_PT);
+
+	trace_xe_sched_job_run(job);
+	run_pt_job(xe, job);
+
+	return NULL;
+}
+
+static void pt_exec_queue_free_job(struct drm_sched_job *drm_job)
+{
+	struct xe_sched_job *job = to_xe_sched_job(drm_job);
+
+	trace_xe_sched_job_free(job);
+	xe_sched_job_put(job);
+}
+
+static const struct drm_sched_backend_ops drm_sched_ops = {
+	.run_job = pt_exec_queue_run_job,
+	.free_job = pt_exec_queue_free_job,
+};
+
+static void pt_exec_queue_kill(struct xe_exec_queue *q)
+{
+}
+
+static void __pt_exec_queue_fini_async(struct work_struct *w)
+{
+	struct xe_pt_exec_queue *pe =
+		container_of(w, struct xe_pt_exec_queue, fini_async);
+	struct xe_exec_queue *q = pe->q;
+
+	trace_xe_exec_queue_destroy(q);
+
+	drm_sched_entity_fini(&pe->entity);
+	drm_sched_fini(&pe->sched);
+
+	kfree(pe);
+
+	xe_device_mem_access_put(q->xe);
+	xe_exec_queue_fini(q);
+}
+
+static void pt_exec_queue_fini(struct xe_exec_queue *q)
+{
+	INIT_WORK(&q->pt->fini_async, __pt_exec_queue_fini_async);
+	queue_work(system_wq, &q->pt->fini_async);
+}
+
+static bool pt_exec_queue_reset_status(struct xe_exec_queue *q)
+{
+	return false;
+}
+
+static const struct xe_exec_queue_ops pt_exec_queue_ops = {
+	.kill = pt_exec_queue_kill,
+	.fini = pt_exec_queue_fini,
+	.reset_status = pt_exec_queue_reset_status,
+};
+
+struct xe_exec_queue *xe_pt_exec_queue_create(struct xe_device *xe)
+{
+	struct drm_gpu_scheduler *sched;
+	struct xe_exec_queue *q;
+	struct xe_pt_exec_queue *pe;
+	int err;
+
+	q = kzalloc(sizeof(*q), GFP_KERNEL);
+	if (!q)
+		return ERR_PTR(-ENOMEM);
+
+	kref_init(&q->refcount);
+	q->flags = EXEC_QUEUE_FLAG_PT;
+	q->ops = &pt_exec_queue_ops;
+
+	pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+	if (!pe) {
+		err = -ENOMEM;
+		goto err_free;
+	}
+
+	err = drm_sched_init(&pe->sched, &drm_sched_ops, system_wq, 1, 64, 64,
+			     MAX_SCHEDULE_TIMEOUT, system_wq, NULL,
+			     q->name, xe->drm.dev);
+	if (err)
+		goto err_free;
+
+	sched = &pe->sched;
+	err = drm_sched_entity_init(&pe->entity, 0, &sched, 1, NULL);
+	if (err)
+		goto err_sched;
+
+	q->xe = xe;
+	q->pt = pe;
+	pe->q = q;
+	q->entity = &pe->entity;
+
+	xe_exec_queue_assign_name(q, 0);
+	trace_xe_exec_queue_create(q);
+
+	/*
+	 * Normally the user vm holds an rpm ref to keep the device
+	 * awake, and the context holds a ref for the vm, however for
+	 * some engines we use the kernels migrate vm underneath which offers no
+	 * such rpm ref, or we lack a vm. Make sure we keep a ref here, so we
+	 * can perform GuC CT actions when needed. Caller is expected to have
+	 * already grabbed the rpm ref outside any sensitive locks.
+	 */
+	drm_WARN_ON(&xe->drm, !xe_device_mem_access_get_if_ongoing(xe));
+
+	return q;
+
+err_sched:
+	drm_sched_fini(&pe->sched);
+err_free:
+	kfree(pe);
+	kfree(q);
+
+	return ERR_PTR(err);
+}
diff --git a/drivers/gpu/drm/xe/xe_pt_exec_queue.h b/drivers/gpu/drm/xe/xe_pt_exec_queue.h
new file mode 100644
index 000000000000..a4d16b845418
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_pt_exec_queue.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#ifndef _XE_PT_EXEC_QUEUE_H_
+#define _XE_PT_EXEC_QUEUE_H_
+
+struct xe_device;
+struct xe_exec_queue;
+
+struct xe_exec_queue *xe_pt_exec_queue_create(struct xe_device *xe);
+
+#endif
diff --git a/drivers/gpu/drm/xe/xe_sched_job.c b/drivers/gpu/drm/xe/xe_sched_job.c
index 373033d9ebd6..fc24e675f922 100644
--- a/drivers/gpu/drm/xe/xe_sched_job.c
+++ b/drivers/gpu/drm/xe/xe_sched_job.c
@@ -65,18 +65,21 @@ bool xe_sched_job_is_migration(struct xe_exec_queue *q)
 	return q->vm && (q->vm->flags & XE_VM_FLAG_MIGRATION);
 }
 
-static void job_free(struct xe_sched_job *job)
+static bool parallel_slab(struct xe_exec_queue *q)
 {
-	struct xe_exec_queue *q = job->q;
-	bool is_migration = xe_sched_job_is_migration(q);
+	return !q->width || xe_exec_queue_is_parallel(q) ||
+		xe_sched_job_is_migration(q);
+}
 
-	kmem_cache_free(xe_exec_queue_is_parallel(job->q) || is_migration ?
-			xe_sched_job_parallel_slab : xe_sched_job_slab, job);
+static void job_free(struct xe_sched_job *job)
+{
+	kmem_cache_free(parallel_slab(job->q) ? xe_sched_job_parallel_slab :
+			xe_sched_job_slab, job);
 }
 
 static struct xe_device *job_to_xe(struct xe_sched_job *job)
 {
-	return gt_to_xe(job->q->gt);
+	return job->q->xe;
 }
 
 struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,
@@ -89,17 +92,19 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,
 	int i, j;
 	u32 width;
 
-	/* only a kernel context can submit a vm-less job */
-	XE_WARN_ON(!q->vm && !(q->flags & EXEC_QUEUE_FLAG_KERNEL));
+	/* only a kernel and pt exec queue can submit a vm-less job */
+	XE_WARN_ON(!q->vm && !(q->flags & EXEC_QUEUE_FLAG_KERNEL) &&
+		   !(q->flags & EXEC_QUEUE_FLAG_PT));
 
-	/* Migration and kernel engines have their own locking */
-	if (!(q->flags & (EXEC_QUEUE_FLAG_KERNEL | EXEC_QUEUE_FLAG_VM))) {
+	/* Kernel and pt exec queues have their own locking */
+	if (!(q->flags & EXEC_QUEUE_FLAG_KERNEL) &&
+	    !(q->flags & EXEC_QUEUE_FLAG_PT)) {
 		lockdep_assert_held(&q->vm->lock);
 		if (!xe_vm_in_lr_mode(q->vm))
 			xe_vm_assert_held(q->vm);
 	}
 
-	job = job_alloc(xe_exec_queue_is_parallel(q) || is_migration);
+	job = job_alloc(parallel_slab(q));
 	if (!job)
 		return ERR_PTR(-ENOMEM);
 
@@ -112,6 +117,8 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,
 		goto err_free;
 
 	if (!batch_addr) {
+		xe_assert(q->xe, q->flags & EXEC_QUEUE_FLAG_PT);
+
 		job->fence = dma_fence_allocate_private_stub(ktime_get());
 		if (!job->fence) {
 			err = -ENOMEM;
@@ -293,7 +300,7 @@ struct xe_sched_job_snapshot *
 xe_sched_job_snapshot_capture(struct xe_sched_job *job)
 {
 	struct xe_exec_queue *q = job->q;
-	struct xe_device *xe = q->gt->tile->xe;
+	struct xe_device *xe = job_to_xe(job);
 	struct xe_sched_job_snapshot *snapshot;
 	size_t len = sizeof(*snapshot) + (sizeof(u64) * q->width);
 	u16 i;
diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h
index b7a0e6c1918d..c4704c5f3c72 100644
--- a/drivers/gpu/drm/xe/xe_trace.h
+++ b/drivers/gpu/drm/xe/xe_trace.h
@@ -147,8 +147,9 @@ DECLARE_EVENT_CLASS(xe_exec_queue,
 			   __entry->logical_mask = q->logical_mask;
 			   __entry->gt_id = q->gt->info.id;
 			   __entry->width = q->width;
-			   __entry->guc_id = q->guc->id;
-			   __entry->guc_state = atomic_read(&q->guc->state);
+			   __entry->guc_id = q->guc ? q->guc->id : 0;
+			   __entry->guc_state = q->guc ?
+			   atomic_read(&q->guc->state) : 0;
 			   __entry->flags = q->flags;
 			   ),
 
@@ -264,9 +265,9 @@ DECLARE_EVENT_CLASS(xe_sched_job,
 
 		    TP_fast_assign(
 			   __entry->seqno = xe_sched_job_seqno(job);
-			   __entry->guc_id = job->q->guc->id;
-			   __entry->guc_state =
-			   atomic_read(&job->q->guc->state);
+			   __entry->guc_id = job->q->guc ? job->q->guc->id : 0;
+			   __entry->guc_state = job->q->guc ?
+			   atomic_read(&job->q->guc->state) : 0;
 			   __entry->flags = job->q->flags;
 			   __entry->error = job->fence->error;
 			   __entry->fence = (unsigned long)job->fence;
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 906734b423c5..8ba037e7ce5c 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -34,6 +34,7 @@
 #include "xe_pm.h"
 #include "xe_preempt_fence.h"
 #include "xe_pt.h"
+#include "xe_pt_exec_queue.h"
 #include "xe_res_cursor.h"
 #include "xe_sync.h"
 #include "xe_trace.h"
@@ -1485,32 +1486,20 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
 			continue;
 
 		xe_pt_populate_empty(tile, vm, vm->pt_root[id]);
+		number_tiles++;
 	}
 	dma_resv_unlock(xe_vm_resv(vm));
 
 	/* Kernel migration VM shouldn't have a circular loop.. */
 	if (!(flags & XE_VM_FLAG_MIGRATION)) {
-		for_each_tile(tile, xe, id) {
-			struct xe_gt *gt = tile->primary_gt;
-			struct xe_vm *migrate_vm;
-			struct xe_exec_queue *q;
-			u32 create_flags = EXEC_QUEUE_FLAG_VM;
-
-			if (!vm->pt_root[id])
-				continue;
+		struct xe_exec_queue *q;
 
-			migrate_vm = xe_migrate_get_vm(tile->migrate);
-			q = xe_exec_queue_create_class(xe, gt, migrate_vm,
-						       XE_ENGINE_CLASS_COPY,
-						       create_flags);
-			xe_vm_put(migrate_vm);
-			if (IS_ERR(q)) {
-				err = PTR_ERR(q);
-				goto err_close;
-			}
-			vm->q[id] = q;
-			number_tiles++;
+		q = xe_pt_exec_queue_create(xe);
+		if (IS_ERR(q)) {
+			err = PTR_ERR(q);
+			goto err_close;
 		}
+		vm->q = q;
 	}
 
 	if (number_tiles > 1)
@@ -1565,19 +1554,13 @@ void xe_vm_close_and_put(struct xe_vm *vm)
 	if (xe_vm_in_preempt_fence_mode(vm))
 		flush_work(&vm->preempt.rebind_work);
 
-	down_write(&vm->lock);
-	for_each_tile(tile, xe, id) {
-		if (vm->q[id])
-			xe_exec_queue_last_fence_put(vm->q[id], vm);
-	}
-	up_write(&vm->lock);
+	if (vm->q) {
+		down_write(&vm->lock);
+		xe_exec_queue_last_fence_put(vm->q, vm);
+		up_write(&vm->lock);
 
-	for_each_tile(tile, xe, id) {
-		if (vm->q[id]) {
-			xe_exec_queue_kill(vm->q[id]);
-			xe_exec_queue_put(vm->q[id]);
-			vm->q[id] = NULL;
-		}
+		xe_exec_queue_kill(vm->q);
+		xe_exec_queue_put(vm->q);
 	}
 
 	down_write(&vm->lock);
@@ -1709,7 +1692,7 @@ u64 xe_vm_pdp4_descriptor(struct xe_vm *vm, struct xe_tile *tile)
 static struct xe_exec_queue *
 to_wait_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q)
 {
-	return q ? q : vm->q[0];
+	return q ? q : vm->q;
 }
 
 static struct xe_user_fence *
@@ -2516,7 +2499,6 @@ static void trace_xe_vm_ops_execute(struct xe_vma_ops *vops)
 
 static int vm_ops_setup_tile_args(struct xe_vm *vm, struct xe_vma_ops *vops)
 {
-	struct xe_exec_queue *q = vops->q;
 	struct xe_tile *tile;
 	int number_tiles = 0;
 	u8 id;
@@ -2528,13 +2510,7 @@ static int vm_ops_setup_tile_args(struct xe_vm *vm, struct xe_vma_ops *vops)
 		if (vops->pt_update_ops[id].q)
 			continue;
 
-		if (q) {
-			vops->pt_update_ops[id].q = q;
-			if (vm->pt_root[id] && !list_empty(&q->multi_gt_list))
-				q = list_next_entry(q, multi_gt_list);
-		} else {
-			vops->pt_update_ops[id].q = vm->q[id];
-		}
+		vops->pt_update_ops[id].q = vops->q ?: vm->q;
 	}
 
 	return number_tiles;
@@ -2899,7 +2875,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 			goto free_objs;
 		}
 
-		if (XE_IOCTL_DBG(xe, !(q->flags & EXEC_QUEUE_FLAG_VM))) {
+		if (XE_IOCTL_DBG(xe, !(q->flags & EXEC_QUEUE_FLAG_PT))) {
 			err = -EINVAL;
 			goto put_exec_queue;
 		}
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index a069989fd82c..d0a08e927db7 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -234,7 +234,7 @@ struct xe_vm {
 	struct xe_device *xe;
 
 	/* exec queue used for (un)binding vma's */
-	struct xe_exec_queue *q[XE_MAX_TILES_PER_DEVICE];
+	struct xe_exec_queue *q;
 
 	/** @lru_bulk_move: Bulk LRU move list for this VM's BOs */
 	struct ttm_lru_bulk_move lru_bulk_move;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* ✓ CI.Patch_applied: success for Refactor VM bind code (rev5)
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (29 preceding siblings ...)
  2024-03-08  5:08 ` [PATCH v4 30/30] drm/xe: Add PT exec queues Matthew Brost
@ 2024-03-08  5:42 ` Patchwork
  2024-03-08  5:43 ` ✗ CI.checkpatch: warning " Patchwork
                   ` (5 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Patchwork @ 2024-03-08  5:42 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe

== Series Details ==

Series: Refactor VM bind code (rev5)
URL   : https://patchwork.freedesktop.org/series/125608/
State : success

== Summary ==

=== Applying kernel patches on branch 'drm-tip' with base: ===
Base commit: ee6e5c86f4d5 drm-tip: 2024y-03m-08d-03h-42m-43s UTC integration manifest
=== git am output follows ===
Applying: drm/xe: Lock all gpuva ops during VM bind IOCTL
Applying: drm/xe: Add ops_execute function which returns a fence
Applying: drm/xe: Move migrate to prefetch to op_lock function
Applying: drm/xe: Add struct xe_vma_ops abstraction
Applying: drm/xe: Update xe_vm_rebind to use dummy VMA operations
Applying: drm/xe: Simplify VM bind IOCTL error handling and cleanup
Applying: drm/xe: Update pagefaults to use dummy VMA operations
Applying: drm/xe: s/xe_tile_migrate_engine/xe_tile_migrate_exec_queue
Applying: drm/xe: Add some members to xe_vma_ops
Applying: drm/xe: Add vm_bind_ioctl_ops_install_fences helper
Applying: drm/xe: Move setting last fence to vm_bind_ioctl_ops_install_fences
Applying: drm/xe: Move ufence check to op_lock
Applying: drm/xe: Move ufence add to vm_bind_ioctl_ops_install_fences
Applying: drm/xe: Add xe_gt_tlb_invalidation_range and convert PT layer to use this
Applying: drm/xe: Add xe_vm_pgtable_update_op to xe_vma_ops
Applying: drm/xe: Use ordered WQ for TLB invalidation fences
Applying: drm/xe: Delete PT update selftest
Applying: drm/xe: Convert multiple bind ops into single job
Applying: drm/xe: Remove old functions defs in xe_pt.h
Applying: drm/xe: Update PT layer with better error handling
Applying: drm/xe: Update xe_vm_rebind to return int
Applying: drm/xe: Move vma rebinding to the drm_exec locking loop
Applying: drm/xe: Update VM trace events
Applying: drm/xe: Update clear / populate arguments
Applying: drm/xe: Add __xe_migrate_update_pgtables_cpu helper
Applying: drm/xe: CPU binds for jobs
Applying: drm/xe: Don't use migrate exec queue for page fault binds
Applying: drm/xe: Add VM bind IOCTL error injection
Applying: drm/xe/guc: Assert time'd out jobs are not from a VM exec queue
Applying: drm/xe: Add PT exec queues



^ permalink raw reply	[flat|nested] 76+ messages in thread

* ✗ CI.checkpatch: warning for Refactor VM bind code (rev5)
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (30 preceding siblings ...)
  2024-03-08  5:42 ` ✓ CI.Patch_applied: success for Refactor VM bind code (rev5) Patchwork
@ 2024-03-08  5:43 ` Patchwork
  2024-03-08  5:44 ` ✓ CI.KUnit: success " Patchwork
                   ` (4 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Patchwork @ 2024-03-08  5:43 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe

== Series Details ==

Series: Refactor VM bind code (rev5)
URL   : https://patchwork.freedesktop.org/series/125608/
State : warning

== Summary ==

+ KERNEL=/kernel
+ git clone https://gitlab.freedesktop.org/drm/maintainer-tools mt
Cloning into 'mt'...
warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
+ git -C mt rev-list -n1 origin/master
a9bb2a8a17457065eb398a81e8fd9aec2b519fd6
+ cd /kernel
+ git config --global --add safe.directory /kernel
+ git log -n1
commit 963ac62414c11d8147c0cf1ba3472815d9dac11f
Author: Matthew Brost <matthew.brost@intel.com>
Date:   Thu Mar 7 21:08:06 2024 -0800

    drm/xe: Add PT exec queues
    
    Add PT exec queues which are used to implement VM bind / unbind
    operations. PT exec queues use a different DRM scheduler backend
    (compared GuC / execlist submission backends) which use the CPU to
    update page tables once all dependecies for a job are resolved.
    
    Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+ /mt/dim checkpatch ee6e5c86f4d587b4ce1093eceae7d50e3f3a7c6b drm-intel
b0359b62ff4f drm/xe: Lock all gpuva ops during VM bind IOCTL
5c2bb244cc83 drm/xe: Add ops_execute function which returns a fence
c25dddd2f21f drm/xe: Move migrate to prefetch to op_lock function
3c4329f6998c drm/xe: Add struct xe_vma_ops abstraction
a152641ffa1e drm/xe: Update xe_vm_rebind to use dummy VMA operations
52836c487a33 drm/xe: Simplify VM bind IOCTL error handling and cleanup
9d3583625484 drm/xe: Update pagefaults to use dummy VMA operations
8a4469265798 drm/xe: s/xe_tile_migrate_engine/xe_tile_migrate_exec_queue
a5d05a4b6b32 drm/xe: Add some members to xe_vma_ops
702c1328de9b drm/xe: Add vm_bind_ioctl_ops_install_fences helper
c3622e636aca drm/xe: Move setting last fence to vm_bind_ioctl_ops_install_fences
bc13f68d562f drm/xe: Move ufence check to op_lock
56f9f18c8675 drm/xe: Move ufence add to vm_bind_ioctl_ops_install_fences
f9838167e688 drm/xe: Add xe_gt_tlb_invalidation_range and convert PT layer to use this
1b46c3e40cc3 drm/xe: Add xe_vm_pgtable_update_op to xe_vma_ops
83453581d188 drm/xe: Use ordered WQ for TLB invalidation fences
3fceac50f83d drm/xe: Delete PT update selftest
d6d37941b3d3 drm/xe: Convert multiple bind ops into single job
1649e2f1820f drm/xe: Remove old functions defs in xe_pt.h
3a558d597a84 drm/xe: Update PT layer with better error handling
eac579e57853 drm/xe: Update xe_vm_rebind to return int
18d8618cf404 drm/xe: Move vma rebinding to the drm_exec locking loop
860b89bffac5 drm/xe: Update VM trace events
e289a054215d drm/xe: Update clear / populate arguments
74ffccb2f205 drm/xe: Add __xe_migrate_update_pgtables_cpu helper
e81db6fd1720 drm/xe: CPU binds for jobs
7e7df13f7d1f drm/xe: Don't use migrate exec queue for page fault binds
1c6f5a5f5400 drm/xe: Add VM bind IOCTL error injection
c81b1259db7e drm/xe/guc: Assert time'd out jobs are not from a VM exec queue
963ac62414c1 drm/xe: Add PT exec queues
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
-:455: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#455: 
new file mode 100644

total: 0 errors, 1 warnings, 0 checks, 789 lines checked



^ permalink raw reply	[flat|nested] 76+ messages in thread

* ✓ CI.KUnit: success for Refactor VM bind code (rev5)
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (31 preceding siblings ...)
  2024-03-08  5:43 ` ✗ CI.checkpatch: warning " Patchwork
@ 2024-03-08  5:44 ` Patchwork
  2024-03-08  5:55 ` ✓ CI.Build: " Patchwork
                   ` (3 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Patchwork @ 2024-03-08  5:44 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe

== Series Details ==

Series: Refactor VM bind code (rev5)
URL   : https://patchwork.freedesktop.org/series/125608/
State : success

== Summary ==

+ trap cleanup EXIT
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig
[05:43:33] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[05:43:37] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make ARCH=um O=.kunit --jobs=48
../arch/x86/um/user-offsets.c:17:6: warning: no previous prototype for ‘foo’ [-Wmissing-prototypes]
   17 | void foo(void)
      |      ^~~
In file included from ../arch/um/kernel/asm-offsets.c:1:
../arch/x86/um/shared/sysdep/kernel-offsets.h:9:6: warning: no previous prototype for ‘foo’ [-Wmissing-prototypes]
    9 | void foo(void)
      |      ^~~
../arch/x86/um/fault.c:18:5: warning: no previous prototype for ‘arch_fixup’ [-Wmissing-prototypes]
   18 | int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
      |     ^~~~~~~~~~
../arch/x86/um/bugs_64.c:9:6: warning: no previous prototype for ‘arch_check_bugs’ [-Wmissing-prototypes]
    9 | void arch_check_bugs(void)
      |      ^~~~~~~~~~~~~~~
../arch/x86/um/bugs_64.c:13:6: warning: no previous prototype for ‘arch_examine_signal’ [-Wmissing-prototypes]
   13 | void arch_examine_signal(int sig, struct uml_pt_regs *regs)
      |      ^~~~~~~~~~~~~~~~~~~
../arch/x86/um/os-Linux/registers.c:146:15: warning: no previous prototype for ‘get_thread_reg’ [-Wmissing-prototypes]
  146 | unsigned long get_thread_reg(int reg, jmp_buf *buf)
      |               ^~~~~~~~~~~~~~
../arch/x86/um/vdso/um_vdso.c:16:5: warning: no previous prototype for ‘__vdso_clock_gettime’ [-Wmissing-prototypes]
   16 | int __vdso_clock_gettime(clockid_t clock, struct __kernel_old_timespec *ts)
      |     ^~~~~~~~~~~~~~~~~~~~
../arch/x86/um/vdso/um_vdso.c:30:5: warning: no previous prototype for ‘__vdso_gettimeofday’ [-Wmissing-prototypes]
   30 | int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
      |     ^~~~~~~~~~~~~~~~~~~
../arch/x86/um/vdso/um_vdso.c:44:21: warning: no previous prototype for ‘__vdso_time’ [-Wmissing-prototypes]
   44 | __kernel_old_time_t __vdso_time(__kernel_old_time_t *t)
      |                     ^~~~~~~~~~~
../arch/x86/um/vdso/um_vdso.c:57:1: warning: no previous prototype for ‘__vdso_getcpu’ [-Wmissing-prototypes]
   57 | __vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
      | ^~~~~~~~~~~~~
../arch/x86/um/os-Linux/mcontext.c:7:6: warning: no previous prototype for ‘get_regs_from_mc’ [-Wmissing-prototypes]
    7 | void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc)
      |      ^~~~~~~~~~~~~~~~
../arch/um/os-Linux/skas/process.c:107:6: warning: no previous prototype for ‘wait_stub_done’ [-Wmissing-prototypes]
  107 | void wait_stub_done(int pid)
      |      ^~~~~~~~~~~~~~
../arch/um/os-Linux/skas/process.c:683:6: warning: no previous prototype for ‘__switch_mm’ [-Wmissing-prototypes]
  683 | void __switch_mm(struct mm_id *mm_idp)
      |      ^~~~~~~~~~~
../arch/x86/um/ptrace_64.c:111:5: warning: no previous prototype for ‘poke_user’ [-Wmissing-prototypes]
  111 | int poke_user(struct task_struct *child, long addr, long data)
      |     ^~~~~~~~~
../arch/x86/um/ptrace_64.c:171:5: warning: no previous prototype for ‘peek_user’ [-Wmissing-prototypes]
  171 | int peek_user(struct task_struct *child, long addr, long data)
      |     ^~~~~~~~~
../arch/um/kernel/skas/process.c:36:12: warning: no previous prototype for ‘start_uml’ [-Wmissing-prototypes]
   36 | int __init start_uml(void)
      |            ^~~~~~~~~
../arch/um/kernel/skas/mmu.c:17:5: warning: no previous prototype for ‘init_new_context’ [-Wmissing-prototypes]
   17 | int init_new_context(struct task_struct *task, struct mm_struct *mm)
      |     ^~~~~~~~~~~~~~~~
../arch/um/kernel/skas/mmu.c:60:6: warning: no previous prototype for ‘destroy_context’ [-Wmissing-prototypes]
   60 | void destroy_context(struct mm_struct *mm)
      |      ^~~~~~~~~~~~~~~
../arch/um/kernel/mem.c:202:8: warning: no previous prototype for ‘pgd_alloc’ [-Wmissing-prototypes]
  202 | pgd_t *pgd_alloc(struct mm_struct *mm)
      |        ^~~~~~~~~
../arch/um/kernel/mem.c:215:7: warning: no previous prototype for ‘uml_kmalloc’ [-Wmissing-prototypes]
  215 | void *uml_kmalloc(int size, int flags)
      |       ^~~~~~~~~~~
../arch/um/os-Linux/main.c:187:7: warning: no previous prototype for ‘__wrap_malloc’ [-Wmissing-prototypes]
  187 | void *__wrap_malloc(int size)
      |       ^~~~~~~~~~~~~
../arch/um/os-Linux/main.c:208:7: warning: no previous prototype for ‘__wrap_calloc’ [-Wmissing-prototypes]
  208 | void *__wrap_calloc(int n, int size)
      |       ^~~~~~~~~~~~~
../arch/um/os-Linux/main.c:222:6: warning: no previous prototype for ‘__wrap_free’ [-Wmissing-prototypes]
  222 | void __wrap_free(void *ptr)
      |      ^~~~~~~~~~~
../arch/x86/um/signal.c:560:6: warning: no previous prototype for ‘sys_rt_sigreturn’ [-Wmissing-prototypes]
  560 | long sys_rt_sigreturn(void)
      |      ^~~~~~~~~~~~~~~~
../arch/um/kernel/process.c:51:5: warning: no previous prototype for ‘pid_to_processor_id’ [-Wmissing-prototypes]
   51 | int pid_to_processor_id(int pid)
      |     ^~~~~~~~~~~~~~~~~~~
../arch/um/kernel/process.c:87:7: warning: no previous prototype for ‘__switch_to’ [-Wmissing-prototypes]
   87 | void *__switch_to(struct task_struct *from, struct task_struct *to)
      |       ^~~~~~~~~~~
../arch/um/kernel/process.c:140:6: warning: no previous prototype for ‘fork_handler’ [-Wmissing-prototypes]
  140 | void fork_handler(void)
      |      ^~~~~~~~~~~~
../arch/um/kernel/process.c:217:6: warning: no previous prototype for ‘arch_cpu_idle’ [-Wmissing-prototypes]
  217 | void arch_cpu_idle(void)
      |      ^~~~~~~~~~~~~
../arch/um/kernel/process.c:253:5: warning: no previous prototype for ‘copy_to_user_proc’ [-Wmissing-prototypes]
  253 | int copy_to_user_proc(void __user *to, void *from, int size)
      |     ^~~~~~~~~~~~~~~~~
../arch/um/kernel/process.c:263:5: warning: no previous prototype for ‘clear_user_proc’ [-Wmissing-prototypes]
  263 | int clear_user_proc(void __user *buf, int size)
      |     ^~~~~~~~~~~~~~~
../arch/um/kernel/process.c:271:6: warning: no previous prototype for ‘set_using_sysemu’ [-Wmissing-prototypes]
  271 | void set_using_sysemu(int value)
      |      ^~~~~~~~~~~~~~~~
../arch/um/kernel/process.c:278:5: warning: no previous prototype for ‘get_using_sysemu’ [-Wmissing-prototypes]
  278 | int get_using_sysemu(void)
      |     ^~~~~~~~~~~~~~~~
../arch/um/kernel/process.c:316:12: warning: no previous prototype for ‘make_proc_sysemu’ [-Wmissing-prototypes]
  316 | int __init make_proc_sysemu(void)
      |            ^~~~~~~~~~~~~~~~
../arch/um/kernel/process.c:348:15: warning: no previous prototype for ‘arch_align_stack’ [-Wmissing-prototypes]
  348 | unsigned long arch_align_stack(unsigned long sp)
      |               ^~~~~~~~~~~~~~~~
../arch/um/os-Linux/mem.c:28:6: warning: no previous prototype for ‘kasan_map_memory’ [-Wmissing-prototypes]
   28 | void kasan_map_memory(void *start, size_t len)
      |      ^~~~~~~~~~~~~~~~
../arch/um/os-Linux/mem.c:212:13: warning: no previous prototype for ‘check_tmpexec’ [-Wmissing-prototypes]
  212 | void __init check_tmpexec(void)
      |             ^~~~~~~~~~~~~
../arch/um/kernel/reboot.c:45:6: warning: no previous prototype for ‘machine_restart’ [-Wmissing-prototypes]
   45 | void machine_restart(char * __unused)
      |      ^~~~~~~~~~~~~~~
../arch/um/kernel/reboot.c:51:6: warning: no previous prototype for ‘machine_power_off’ [-Wmissing-prototypes]
   51 | void machine_power_off(void)
      |      ^~~~~~~~~~~~~~~~~
../arch/um/kernel/reboot.c:57:6: warning: no previous prototype for ‘machine_halt’ [-Wmissing-prototypes]
   57 | void machine_halt(void)
      |      ^~~~~~~~~~~~
../arch/um/kernel/tlb.c:579:6: warning: no previous prototype for ‘flush_tlb_mm_range’ [-Wmissing-prototypes]
  579 | void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
      |      ^~~~~~~~~~~~~~~~~~
../arch/um/kernel/tlb.c:594:6: warning: no previous prototype for ‘force_flush_all’ [-Wmissing-prototypes]
  594 | void force_flush_all(void)
      |      ^~~~~~~~~~~~~~~
../arch/um/os-Linux/signal.c:75:6: warning: no previous prototype for ‘sig_handler’ [-Wmissing-prototypes]
   75 | void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
      |      ^~~~~~~~~~~
../arch/um/os-Linux/signal.c:111:6: warning: no previous prototype for ‘timer_alarm_handler’ [-Wmissing-prototypes]
  111 | void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
      |      ^~~~~~~~~~~~~~~~~~~
../arch/um/kernel/um_arch.c:408:19: warning: no previous prototype for ‘read_initrd’ [-Wmissing-prototypes]
  408 | int __init __weak read_initrd(void)
      |                   ^~~~~~~~~~~
../arch/um/kernel/um_arch.c:461:7: warning: no previous prototype for ‘text_poke’ [-Wmissing-prototypes]
  461 | void *text_poke(void *addr, const void *opcode, size_t len)
      |       ^~~~~~~~~
../arch/um/kernel/um_arch.c:473:6: warning: no previous prototype for ‘text_poke_sync’ [-Wmissing-prototypes]
  473 | void text_poke_sync(void)
      |      ^~~~~~~~~~~~~~
../arch/um/os-Linux/start_up.c:301:12: warning: no previous prototype for ‘parse_iomem’ [-Wmissing-prototypes]
  301 | int __init parse_iomem(char *str, int *add)
      |            ^~~~~~~~~~~
../arch/um/kernel/kmsg_dump.c:60:12: warning: no previous prototype for ‘kmsg_dumper_stdout_init’ [-Wmissing-prototypes]
   60 | int __init kmsg_dumper_stdout_init(void)
      |            ^~~~~~~~~~~~~~~~~~~~~~~
../arch/x86/um/syscalls_64.c:48:6: warning: no previous prototype for ‘arch_switch_to’ [-Wmissing-prototypes]
   48 | void arch_switch_to(struct task_struct *to)
      |      ^~~~~~~~~~~~~~
../lib/iomap.c:156:5: warning: no previous prototype for ‘ioread64_lo_hi’ [-Wmissing-prototypes]
  156 | u64 ioread64_lo_hi(const void __iomem *addr)
      |     ^~~~~~~~~~~~~~
../lib/iomap.c:163:5: warning: no previous prototype for ‘ioread64_hi_lo’ [-Wmissing-prototypes]
  163 | u64 ioread64_hi_lo(const void __iomem *addr)
      |     ^~~~~~~~~~~~~~
../lib/iomap.c:170:5: warning: no previous prototype for ‘ioread64be_lo_hi’ [-Wmissing-prototypes]
  170 | u64 ioread64be_lo_hi(const void __iomem *addr)
      |     ^~~~~~~~~~~~~~~~
../lib/iomap.c:178:5: warning: no previous prototype for ‘ioread64be_hi_lo’ [-Wmissing-prototypes]
  178 | u64 ioread64be_hi_lo(const void __iomem *addr)
      |     ^~~~~~~~~~~~~~~~
../lib/iomap.c:264:6: warning: no previous prototype for ‘iowrite64_lo_hi’ [-Wmissing-prototypes]
  264 | void iowrite64_lo_hi(u64 val, void __iomem *addr)
      |      ^~~~~~~~~~~~~~~
../lib/iomap.c:272:6: warning: no previous prototype for ‘iowrite64_hi_lo’ [-Wmissing-prototypes]
  272 | void iowrite64_hi_lo(u64 val, void __iomem *addr)
      |      ^~~~~~~~~~~~~~~
../lib/iomap.c:280:6: warning: no previous prototype for ‘iowrite64be_lo_hi’ [-Wmissing-prototypes]
  280 | void iowrite64be_lo_hi(u64 val, void __iomem *addr)
      |      ^~~~~~~~~~~~~~~~~
../lib/iomap.c:288:6: warning: no previous prototype for ‘iowrite64be_hi_lo’ [-Wmissing-prototypes]
  288 | void iowrite64be_hi_lo(u64 val, void __iomem *addr)
      |      ^~~~~~~~~~~~~~~~~
stty: 'standard input': Inappropriate ioctl for device

[05:44:00] Starting KUnit Kernel (1/1)...
[05:44:00] ============================================================
[05:44:00] =================== guc_dbm (7 subtests) ===================
[05:44:00] [PASSED] test_empty
[05:44:00] [PASSED] test_default
[05:44:00] ======================== test_size  ========================
[05:44:00] [PASSED] 4
[05:44:00] [PASSED] 8
[05:44:00] [PASSED] 32
[05:44:00] [PASSED] 256
[05:44:00] ==================== [PASSED] test_size ====================
[05:44:00] ======================= test_reuse  ========================
[05:44:00] [PASSED] 4
[05:44:00] [PASSED] 8
[05:44:00] [PASSED] 32
[05:44:00] [PASSED] 256
[05:44:00] =================== [PASSED] test_reuse ====================
[05:44:00] =================== test_range_overlap  ====================
[05:44:00] [PASSED] 4
[05:44:00] [PASSED] 8
[05:44:00] [PASSED] 32
[05:44:00] [PASSED] 256
[05:44:00] =============== [PASSED] test_range_overlap ================
[05:44:00] =================== test_range_compact  ====================
[05:44:00] [PASSED] 4
[05:44:00] [PASSED] 8
[05:44:00] [PASSED] 32
[05:44:00] [PASSED] 256
[05:44:00] =============== [PASSED] test_range_compact ================
[05:44:00] ==================== test_range_spare  =====================
[05:44:00] [PASSED] 4
[05:44:00] [PASSED] 8
[05:44:00] [PASSED] 32
[05:44:00] [PASSED] 256
[05:44:00] ================ [PASSED] test_range_spare =================
[05:44:00] ===================== [PASSED] guc_dbm =====================
[05:44:00] ================== no_relay (3 subtests) ===================
[05:44:00] [PASSED] xe_drops_guc2pf_if_not_ready
[05:44:00] [PASSED] xe_drops_guc2vf_if_not_ready
[05:44:00] [PASSED] xe_rejects_send_if_not_ready
[05:44:00] ==================== [PASSED] no_relay =====================
[05:44:00] ================== pf_relay (14 subtests) ==================
[05:44:00] [PASSED] pf_rejects_guc2pf_too_short
[05:44:00] [PASSED] pf_rejects_guc2pf_too_long
[05:44:00] [PASSED] pf_rejects_guc2pf_no_payload
[05:44:00] [PASSED] pf_fails_no_payload
[05:44:00] [PASSED] pf_fails_bad_origin
[05:44:00] [PASSED] pf_fails_bad_type
[05:44:00] [PASSED] pf_txn_reports_error
[05:44:00] [PASSED] pf_txn_sends_pf2guc
[05:44:00] [PASSED] pf_sends_pf2guc
[05:44:00] [SKIPPED] pf_loopback_nop
[05:44:00] [SKIPPED] pf_loopback_echo
[05:44:00] [SKIPPED] pf_loopback_fail
[05:44:00] [SKIPPED] pf_loopback_busy
[05:44:00] [SKIPPED] pf_loopback_retry
[05:44:00] ==================== [PASSED] pf_relay =====================
[05:44:00] ================== vf_relay (3 subtests) ===================
[05:44:00] [PASSED] vf_rejects_guc2vf_too_short
[05:44:00] [PASSED] vf_rejects_guc2vf_too_long
[05:44:00] [PASSED] vf_rejects_guc2vf_no_payload
[05:44:00] ==================== [PASSED] vf_relay =====================
[05:44:00] ===================== lmtt (1 subtest) =====================
[05:44:00] ======================== test_ops  =========================
[05:44:00] [PASSED] 2-level
[05:44:00] [PASSED] multi-level
[05:44:00] ==================== [PASSED] test_ops =====================
[05:44:00] ====================== [PASSED] lmtt =======================
[05:44:00] ==================== xe_bo (2 subtests) ====================
[05:44:00] [SKIPPED] xe_ccs_migrate_kunit
[05:44:00] [SKIPPED] xe_bo_evict_kunit
[05:44:00] ===================== [SKIPPED] xe_bo ======================
[05:44:00] ================== xe_dma_buf (1 subtest) ==================
[05:44:00] [SKIPPED] xe_dma_buf_kunit
[05:44:00] =================== [SKIPPED] xe_dma_buf ===================
[05:44:00] ================== xe_migrate (1 subtest) ==================
[05:44:00] [SKIPPED] xe_migrate_sanity_kunit
[05:44:00] =================== [SKIPPED] xe_migrate ===================
[05:44:00] =================== xe_mocs (2 subtests) ===================
[05:44:00] [SKIPPED] xe_live_mocs_kernel_kunit
[05:44:00] [SKIPPED] xe_live_mocs_reset_kunit
[05:44:00] ==================== [SKIPPED] xe_mocs =====================
[05:44:00] =================== xe_pci (2 subtests) ====================
[05:44:00] [PASSED] xe_gmdid_graphics_ip
[05:44:00] [PASSED] xe_gmdid_media_ip
[05:44:00] ===================== [PASSED] xe_pci ======================
[05:44:00] ==================== xe_rtp (1 subtest) ====================
[05:44:00] ================== xe_rtp_process_tests  ===================
[05:44:00] [PASSED] coalesce-same-reg
[05:44:00] [PASSED] no-match-no-add
[05:44:00] [PASSED] no-match-no-add-multiple-rules
[05:44:00] [PASSED] two-regs-two-entries
[05:44:00] [PASSED] clr-one-set-other
[05:44:00] [PASSED] set-field
[05:44:00] [PASSED] conflict-duplicate
[05:44:00] [PASSED] conflict-not-disjoint
[05:44:00] [PASSED] conflict-reg-type
[05:44:00] ============== [PASSED] xe_rtp_process_tests ===============
[05:44:00] ===================== [PASSED] xe_rtp ======================
[05:44:00] ==================== xe_wa (1 subtest) =====================
[05:44:00] ======================== xe_wa_gt  =========================
[05:44:00] [PASSED] TIGERLAKE (B0)
[05:44:00] [PASSED] DG1 (A0)
[05:44:00] [PASSED] DG1 (B0)
[05:44:00] [PASSED] ALDERLAKE_S (A0)
[05:44:00] [PASSED] ALDERLAKE_S (B0)
[05:44:00] [PASSED] ALDERLAKE_S (C0)
[05:44:00] [PASSED] ALDERLAKE_S (D0)
[05:44:00] [PASSED] ALDERLAKE_P (A0)
[05:44:00] [PASSED] ALDERLAKE_P (B0)
[05:44:00] [PASSED] ALDERLAKE_P (C0)
[05:44:00] [PASSED] ALDERLAKE_S_RPLS (D0)
[05:44:00] [PASSED] ALDERLAKE_P_RPLU (E0)
[05:44:00] [PASSED] DG2_G10 (C0)
[05:44:00] [PASSED] DG2_G11 (B1)
[05:44:00] [PASSED] DG2_G12 (A1)
[05:44:00] [PASSED] METEORLAKE (g:A0, m:A0)
[05:44:00] [PASSED] METEORLAKE (g:A0, m:A0)
[05:44:00] [PASSED] METEORLAKE (g:A0, m:A0)
[05:44:00] [PASSED] LUNARLAKE (g:A0, m:A0)
[05:44:00] [PASSED] LUNARLAKE (g:B0, m:A0)
[05:44:00] ==================== [PASSED] xe_wa_gt =====================
[05:44:00] ====================== [PASSED] xe_wa ======================
[05:44:00] ============================================================
[05:44:00] Testing complete. Ran 81 tests: passed: 70, skipped: 11
[05:44:00] Elapsed time: 27.663s total, 4.166s configuring, 23.276s building, 0.177s running

+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/tests/.kunitconfig
[05:44:00] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[05:44:02] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make ARCH=um O=.kunit --jobs=48
In file included from ../arch/um/kernel/asm-offsets.c:1:
../arch/x86/um/shared/sysdep/kernel-offsets.h:9:6: warning: no previous prototype for ‘foo’ [-Wmissing-prototypes]
    9 | void foo(void)
      |      ^~~
../arch/x86/um/ptrace_64.c:111:5: warning: no previous prototype for ‘poke_user’ [-Wmissing-prototypes]
  111 | int poke_user(struct task_struct *child, long addr, long data)
      |     ^~~~~~~~~
../arch/x86/um/ptrace_64.c:171:5: warning: no previous prototype for ‘peek_user’ [-Wmissing-prototypes]
  171 | int peek_user(struct task_struct *child, long addr, long data)
      |     ^~~~~~~~~
../arch/x86/um/signal.c:560:6: warning: no previous prototype for ‘sys_rt_sigreturn’ [-Wmissing-prototypes]
  560 | long sys_rt_sigreturn(void)
      |      ^~~~~~~~~~~~~~~~
../arch/um/kernel/mem.c:202:8: warning: no previous prototype for ‘pgd_alloc’ [-Wmissing-prototypes]
  202 | pgd_t *pgd_alloc(struct mm_struct *mm)
      |        ^~~~~~~~~
../arch/um/kernel/mem.c:215:7: warning: no previous prototype for ‘uml_kmalloc’ [-Wmissing-prototypes]
  215 | void *uml_kmalloc(int size, int flags)
      |       ^~~~~~~~~~~
../arch/um/kernel/process.c:51:5: warning: no previous prototype for ‘pid_to_processor_id’ [-Wmissing-prototypes]
   51 | int pid_to_processor_id(int pid)
      |     ^~~~~~~~~~~~~~~~~~~
../arch/um/kernel/process.c:87:7: warning: no previous prototype for ‘__switch_to’ [-Wmissing-prototypes]
   87 | void *__switch_to(struct task_struct *from, struct task_struct *to)
      |       ^~~~~~~~~~~
../arch/um/kernel/process.c:140:6: warning: no previous prototype for ‘fork_handler’ [-Wmissing-prototypes]
  140 | void fork_handler(void)
      |      ^~~~~~~~~~~~
../arch/um/kernel/process.c:217:6: warning: no previous prototype for ‘arch_cpu_idle’ [-Wmissing-prototypes]
  217 | void arch_cpu_idle(void)
      |      ^~~~~~~~~~~~~
../arch/um/kernel/process.c:253:5: warning: no previous prototype for ‘copy_to_user_proc’ [-Wmissing-prototypes]
  253 | int copy_to_user_proc(void __user *to, void *from, int size)
      |     ^~~~~~~~~~~~~~~~~
../arch/um/kernel/process.c:263:5: warning: no previous prototype for ‘clear_user_proc’ [-Wmissing-prototypes]
  263 | int clear_user_proc(void __user *buf, int size)
      |     ^~~~~~~~~~~~~~~
../arch/um/kernel/process.c:271:6: warning: no previous prototype for ‘set_using_sysemu’ [-Wmissing-prototypes]
  271 | void set_using_sysemu(int value)
      |      ^~~~~~~~~~~~~~~~
../arch/um/kernel/process.c:278:5: warning: no previous prototype for ‘get_using_sysemu’ [-Wmissing-prototypes]
  278 | int get_using_sysemu(void)
      |     ^~~~~~~~~~~~~~~~
../arch/um/kernel/process.c:316:12: warning: no previous prototype for ‘make_proc_sysemu’ [-Wmissing-prototypes]
  316 | int __init make_proc_sysemu(void)
      |            ^~~~~~~~~~~~~~~~
../arch/um/kernel/process.c:348:15: warning: no previous prototype for ‘arch_align_stack’ [-Wmissing-prototypes]
  348 | unsigned long arch_align_stack(unsigned long sp)
      |               ^~~~~~~~~~~~~~~~
../arch/um/kernel/reboot.c:45:6: warning: no previous prototype for ‘machine_restart’ [-Wmissing-prototypes]
   45 | void machine_restart(char * __unused)
      |      ^~~~~~~~~~~~~~~
../arch/um/kernel/reboot.c:51:6: warning: no previous prototype for ‘machine_power_off’ [-Wmissing-prototypes]
   51 | void machine_power_off(void)
      |      ^~~~~~~~~~~~~~~~~
../arch/um/kernel/reboot.c:57:6: warning: no previous prototype for ‘machine_halt’ [-Wmissing-prototypes]
   57 | void machine_halt(void)
      |      ^~~~~~~~~~~~
../arch/x86/um/syscalls_64.c:48:6: warning: no previous prototype for ‘arch_switch_to’ [-Wmissing-prototypes]
   48 | void arch_switch_to(struct task_struct *to)
      |      ^~~~~~~~~~~~~~
../arch/um/kernel/tlb.c:579:6: warning: no previous prototype for ‘flush_tlb_mm_range’ [-Wmissing-prototypes]
  579 | void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
      |      ^~~~~~~~~~~~~~~~~~
../arch/um/kernel/tlb.c:594:6: warning: no previous prototype for ‘force_flush_all’ [-Wmissing-prototypes]
  594 | void force_flush_all(void)
      |      ^~~~~~~~~~~~~~~
../arch/um/kernel/um_arch.c:408:19: warning: no previous prototype for ‘read_initrd’ [-Wmissing-prototypes]
  408 | int __init __weak read_initrd(void)
      |                   ^~~~~~~~~~~
../arch/um/kernel/um_arch.c:461:7: warning: no previous prototype for ‘text_poke’ [-Wmissing-prototypes]
  461 | void *text_poke(void *addr, const void *opcode, size_t len)
      |       ^~~~~~~~~
../arch/um/kernel/um_arch.c:473:6: warning: no previous prototype for ‘text_poke_sync’ [-Wmissing-prototypes]
  473 | void text_poke_sync(void)
      |      ^~~~~~~~~~~~~~
../arch/um/kernel/kmsg_dump.c:60:12: warning: no previous prototype for ‘kmsg_dumper_stdout_init’ [-Wmissing-prototypes]
   60 | int __init kmsg_dumper_stdout_init(void)
      |            ^~~~~~~~~~~~~~~~~~~~~~~
../arch/um/kernel/skas/mmu.c:17:5: warning: no previous prototype for ‘init_new_context’ [-Wmissing-prototypes]
   17 | int init_new_context(struct task_struct *task, struct mm_struct *mm)
      |     ^~~~~~~~~~~~~~~~
../arch/um/kernel/skas/mmu.c:60:6: warning: no previous prototype for ‘destroy_context’ [-Wmissing-prototypes]
   60 | void destroy_context(struct mm_struct *mm)
      |      ^~~~~~~~~~~~~~~
../arch/um/kernel/skas/process.c:36:12: warning: no previous prototype for ‘start_uml’ [-Wmissing-prototypes]
   36 | int __init start_uml(void)
      |            ^~~~~~~~~
../lib/iomap.c:156:5: warning: no previous prototype for ‘ioread64_lo_hi’ [-Wmissing-prototypes]
  156 | u64 ioread64_lo_hi(const void __iomem *addr)
      |     ^~~~~~~~~~~~~~
../lib/iomap.c:163:5: warning: no previous prototype for ‘ioread64_hi_lo’ [-Wmissing-prototypes]
  163 | u64 ioread64_hi_lo(const void __iomem *addr)
      |     ^~~~~~~~~~~~~~
../lib/iomap.c:170:5: warning: no previous prototype for ‘ioread64be_lo_hi’ [-Wmissing-prototypes]
  170 | u64 ioread64be_lo_hi(const void __iomem *addr)
      |     ^~~~~~~~~~~~~~~~
../lib/iomap.c:178:5: warning: no previous prototype for ‘ioread64be_hi_lo’ [-Wmissing-prototypes]
  178 | u64 ioread64be_hi_lo(const void __iomem *addr)
      |     ^~~~~~~~~~~~~~~~
../lib/iomap.c:264:6: warning: no previous prototype for ‘iowrite64_lo_hi’ [-Wmissing-prototypes]
  264 | void iowrite64_lo_hi(u64 val, void __iomem *addr)
      |      ^~~~~~~~~~~~~~~
../lib/iomap.c:272:6: warning: no previous prototype for ‘iowrite64_hi_lo’ [-Wmissing-prototypes]
  272 | void iowrite64_hi_lo(u64 val, void __iomem *addr)
      |      ^~~~~~~~~~~~~~~
../lib/iomap.c:280:6: warning: no previous prototype for ‘iowrite64be_lo_hi’ [-Wmissing-prototypes]
  280 | void iowrite64be_lo_hi(u64 val, void __iomem *addr)
      |      ^~~~~~~~~~~~~~~~~
../lib/iomap.c:288:6: warning: no previous prototype for ‘iowrite64be_hi_lo’ [-Wmissing-prototypes]
  288 | void iowrite64be_hi_lo(u64 val, void __iomem *addr)
      |      ^~~~~~~~~~~~~~~~~

[05:44:22] Starting KUnit Kernel (1/1)...
[05:44:22] ============================================================
[05:44:22] ============ drm_test_pick_cmdline (2 subtests) ============
[05:44:22] [PASSED] drm_test_pick_cmdline_res_1920_1080_60
[05:44:22] =============== drm_test_pick_cmdline_named  ===============
[05:44:22] [PASSED] NTSC
[05:44:22] [PASSED] NTSC-J
[05:44:22] [PASSED] PAL
[05:44:22] [PASSED] PAL-M
[05:44:22] =========== [PASSED] drm_test_pick_cmdline_named ===========
[05:44:22] ============== [PASSED] drm_test_pick_cmdline ==============
[05:44:22] ================== drm_buddy (6 subtests) ==================
[05:44:22] [PASSED] drm_test_buddy_alloc_limit
[05:44:22] [PASSED] drm_test_buddy_alloc_optimistic
[05:44:22] [PASSED] drm_test_buddy_alloc_pessimistic
[05:44:22] [PASSED] drm_test_buddy_alloc_pathological
[05:44:22] [PASSED] drm_test_buddy_alloc_contiguous
[05:44:22] [PASSED] drm_test_buddy_alloc_range_bias
[05:44:22] ==================== [PASSED] drm_buddy ====================
[05:44:22] ============= drm_cmdline_parser (40 subtests) =============
[05:44:22] [PASSED] drm_test_cmdline_force_d_only
[05:44:22] [PASSED] drm_test_cmdline_force_D_only_dvi
[05:44:22] [PASSED] drm_test_cmdline_force_D_only_hdmi
[05:44:22] [PASSED] drm_test_cmdline_force_D_only_not_digital
[05:44:22] [PASSED] drm_test_cmdline_force_e_only
[05:44:22] [PASSED] drm_test_cmdline_res
[05:44:22] [PASSED] drm_test_cmdline_res_vesa
[05:44:22] [PASSED] drm_test_cmdline_res_vesa_rblank
[05:44:22] [PASSED] drm_test_cmdline_res_rblank
[05:44:22] [PASSED] drm_test_cmdline_res_bpp
[05:44:22] [PASSED] drm_test_cmdline_res_refresh
[05:44:22] [PASSED] drm_test_cmdline_res_bpp_refresh
[05:44:22] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced
[05:44:22] [PASSED] drm_test_cmdline_res_bpp_refresh_margins
[05:44:22] [PASSED] drm_test_cmdline_res_bpp_refresh_force_off
[05:44:22] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on
[05:44:22] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_analog
[05:44:22] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_digital
[05:44:22] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced_margins_force_on
[05:44:22] [PASSED] drm_test_cmdline_res_margins_force_on
[05:44:22] [PASSED] drm_test_cmdline_res_vesa_margins
[05:44:22] [PASSED] drm_test_cmdline_name
[05:44:22] [PASSED] drm_test_cmdline_name_bpp
[05:44:22] [PASSED] drm_test_cmdline_name_option
[05:44:22] [PASSED] drm_test_cmdline_name_bpp_option
[05:44:22] [PASSED] drm_test_cmdline_rotate_0
[05:44:22] [PASSED] drm_test_cmdline_rotate_90
[05:44:22] [PASSED] drm_test_cmdline_rotate_180
[05:44:22] [PASSED] drm_test_cmdline_rotate_270
[05:44:22] [PASSED] drm_test_cmdline_hmirror
[05:44:22] [PASSED] drm_test_cmdline_vmirror
[05:44:22] [PASSED] drm_test_cmdline_margin_options
[05:44:22] [PASSED] drm_test_cmdline_multiple_options
[05:44:22] [PASSED] drm_test_cmdline_bpp_extra_and_option
[05:44:22] [PASSED] drm_test_cmdline_extra_and_option
[05:44:22] [PASSED] drm_test_cmdline_freestanding_options
[05:44:22] [PASSED] drm_test_cmdline_freestanding_force_e_and_options
[05:44:22] [PASSED] drm_test_cmdline_panel_orientation
[05:44:22] ================ drm_test_cmdline_invalid  =================
[05:44:22] [PASSED] margin_only
[05:44:22] [PASSED] interlace_only
[05:44:22] [PASSED] res_missing_x
[05:44:22] [PASSED] res_missing_y
[05:44:22] [PASSED] res_bad_y
[05:44:22] [PASSED] res_missing_y_bpp
[05:44:22] [PASSED] res_bad_bpp
[05:44:22] [PASSED] res_bad_refresh
[05:44:22] [PASSED] res_bpp_refresh_force_on_off
[05:44:22] [PASSED] res_invalid_mode
[05:44:22] [PASSED] res_bpp_wrong_place_mode
[05:44:22] [PASSED] name_bpp_refresh
[05:44:22] [PASSED] name_refresh
[05:44:22] [PASSED] name_refresh_wrong_mode
[05:44:22] [PASSED] name_refresh_invalid_mode
[05:44:22] [PASSED] rotate_multiple
[05:44:22] [PASSED] rotate_invalid_val
[05:44:22] [PASSED] rotate_truncated
[05:44:22] [PASSED] invalid_option
[05:44:22] [PASSED] invalid_tv_option
[05:44:22] [PASSED] truncated_tv_option
[05:44:22] ============ [PASSED] drm_test_cmdline_invalid =============
[05:44:22] =============== drm_test_cmdline_tv_options  ===============
[05:44:22] [PASSED] NTSC
[05:44:22] [PASSED] NTSC_443
[05:44:22] [PASSED] NTSC_J
[05:44:22] [PASSED] PAL
[05:44:22] [PASSED] PAL_M
[05:44:22] [PASSED] PAL_N
[05:44:22] [PASSED] SECAM
[05:44:22] =========== [PASSED] drm_test_cmdline_tv_options ===========
[05:44:22] =============== [PASSED] drm_cmdline_parser ================
[05:44:22] ============= drmm_connector_init (3 subtests) =============
[05:44:22] [PASSED] drm_test_drmm_connector_init
[05:44:22] [PASSED] drm_test_drmm_connector_init_null_ddc
[05:44:22] ========= drm_test_drmm_connector_init_type_valid  =========
[05:44:22] [PASSED] Unknown
[05:44:22] [PASSED] VGA
[05:44:22] [PASSED] DVI-I
[05:44:22] [PASSED] DVI-D
[05:44:22] [PASSED] DVI-A
[05:44:22] [PASSED] Composite
[05:44:22] [PASSED] SVIDEO
[05:44:22] [PASSED] LVDS
[05:44:22] [PASSED] Component
[05:44:22] [PASSED] DIN
[05:44:22] [PASSED] DP
[05:44:22] [PASSED] HDMI-A
[05:44:22] [PASSED] HDMI-B
[05:44:22] [PASSED] TV
[05:44:22] [PASSED] eDP
[05:44:22] [PASSED] Virtual
[05:44:22] [PASSED] DSI
[05:44:22] [PASSED] DPI
[05:44:22] [PASSED] Writeback
[05:44:22] [PASSED] SPI
[05:44:22] [PASSED] USB
[05:44:22] ===== [PASSED] drm_test_drmm_connector_init_type_valid =====
[05:44:22] =============== [PASSED] drmm_connector_init ===============
[05:44:22] ========== drm_get_tv_mode_from_name (2 subtests) ==========
[05:44:22] ========== drm_test_get_tv_mode_from_name_valid  ===========
[05:44:22] [PASSED] NTSC
[05:44:22] [PASSED] NTSC-443
[05:44:22] [PASSED] NTSC-J
[05:44:22] [PASSED] PAL
[05:44:22] [PASSED] PAL-M
[05:44:22] [PASSED] PAL-N
[05:44:22] [PASSED] SECAM
[05:44:22] ====== [PASSED] drm_test_get_tv_mode_from_name_valid =======
[05:44:22] [PASSED] drm_test_get_tv_mode_from_name_truncated
[05:44:22] ============ [PASSED] drm_get_tv_mode_from_name ============
[05:44:22] ============= drm_damage_helper (21 subtests) ==============
[05:44:22] [PASSED] drm_test_damage_iter_no_damage
[05:44:22] [PASSED] drm_test_damage_iter_no_damage_fractional_src
[05:44:22] [PASSED] drm_test_damage_iter_no_damage_src_moved
[05:44:22] [PASSED] drm_test_damage_iter_no_damage_fractional_src_moved
[05:44:22] [PASSED] drm_test_damage_iter_no_damage_not_visible
[05:44:22] [PASSED] drm_test_damage_iter_no_damage_no_crtc
[05:44:22] [PASSED] drm_test_damage_iter_no_damage_no_fb
[05:44:22] [PASSED] drm_test_damage_iter_simple_damage
[05:44:22] [PASSED] drm_test_damage_iter_single_damage
[05:44:22] [PASSED] drm_test_damage_iter_single_damage_intersect_src
[05:44:22] [PASSED] drm_test_damage_iter_single_damage_outside_src
[05:44:22] [PASSED] drm_test_damage_iter_single_damage_fractional_src
[05:44:22] [PASSED] drm_test_damage_iter_single_damage_intersect_fractional_src
[05:44:22] [PASSED] drm_test_damage_iter_single_damage_outside_fractional_src
[05:44:22] [PASSED] drm_test_damage_iter_single_damage_src_moved
[05:44:22] [PASSED] drm_test_damage_iter_single_damage_fractional_src_moved
[05:44:22] [PASSED] drm_test_damage_iter_damage
[05:44:22] [PASSED] drm_test_damage_iter_damage_one_intersect
[05:44:22] [PASSED] drm_test_damage_iter_damage_one_outside
[05:44:22] [PASSED] drm_test_damage_iter_damage_src_moved
[05:44:22] [PASSED] drm_test_damage_iter_damage_not_visible
[05:44:22] ================ [PASSED] drm_damage_helper ================
[05:44:22] ============== drm_dp_mst_helper (3 subtests) ==============
[05:44:22] ============== drm_test_dp_mst_calc_pbn_mode  ==============
[05:44:22] [PASSED] Clock 154000 BPP 30 DSC disabled
[05:44:22] [PASSED] Clock 234000 BPP 30 DSC disabled
[05:44:22] [PASSED] Clock 297000 BPP 24 DSC disabled
[05:44:22] [PASSED] Clock 332880 BPP 24 DSC enabled
[05:44:22] [PASSED] Clock 324540 BPP 24 DSC enabled
[05:44:22] ========== [PASSED] drm_test_dp_mst_calc_pbn_mode ==========
[05:44:22] ============== drm_test_dp_mst_calc_pbn_div  ===============
[05:44:22] [PASSED] Link rate 2000000 lane count 4
[05:44:22] [PASSED] Link rate 2000000 lane count 2
[05:44:22] [PASSED] Link rate 2000000 lane count 1
[05:44:22] [PASSED] Link rate 1350000 lane count 4
[05:44:22] [PASSED] Link rate 1350000 lane count 2
[05:44:22] [PASSED] Link rate 1350000 lane count 1
[05:44:22] [PASSED] Link rate 1000000 lane count 4
[05:44:22] [PASSED] Link rate 1000000 lane count 2
[05:44:22] [PASSED] Link rate 1000000 lane count 1
[05:44:22] [PASSED] Link rate 810000 lane count 4
[05:44:22] [PASSED] Link rate 810000 lane count 2
[05:44:22] [PASSED] Link rate 810000 lane count 1
[05:44:22] [PASSED] Link rate 540000 lane count 4
[05:44:22] [PASSED] Link rate 540000 lane count 2
[05:44:22] [PASSED] Link rate 540000 lane count 1
[05:44:22] [PASSED] Link rate 270000 lane count 4
[05:44:22] [PASSED] Link rate 270000 lane count 2
[05:44:22] [PASSED] Link rate 270000 lane count 1
[05:44:22] [PASSED] Link rate 162000 lane count 4
[05:44:22] [PASSED] Link rate 162000 lane count 2
[05:44:22] [PASSED] Link rate 162000 lane count 1
[05:44:22] ========== [PASSED] drm_test_dp_mst_calc_pbn_div ===========
[05:44:22] ========= drm_test_dp_mst_sideband_msg_req_decode  =========
[05:44:22] [PASSED] DP_ENUM_PATH_RESOURCES with port number
[05:44:22] [PASSED] DP_POWER_UP_PHY with port number
[05:44:22] [PASSED] DP_POWER_DOWN_PHY with port number
[05:44:22] [PASSED] DP_ALLOCATE_PAYLOAD with SDP stream sinks
[05:44:22] [PASSED] DP_ALLOCATE_PAYLOAD with port number
[05:44:22] [PASSED] DP_ALLOCATE_PAYLOAD with VCPI
[05:44:22] [PASSED] DP_ALLOCATE_PAYLOAD with PBN
[05:44:22] [PASSED] DP_QUERY_PAYLOAD with port number
[05:44:22] [PASSED] DP_QUERY_PAYLOAD with VCPI
[05:44:22] [PASSED] DP_REMOTE_DPCD_READ with port number
[05:44:22] [PASSED] DP_REMOTE_DPCD_READ with DPCD address
[05:44:22] [PASSED] DP_REMOTE_DPCD_READ with max number of bytes
[05:44:22] [PASSED] DP_REMOTE_DPCD_WRITE with port number
[05:44:22] [PASSED] DP_REMOTE_DPCD_WRITE with DPCD address
[05:44:22] [PASSED] DP_REMOTE_DPCD_WRITE with data array
[05:44:22] [PASSED] DP_REMOTE_I2C_READ with port number
[05:44:22] [PASSED] DP_REMOTE_I2C_READ with I2C device ID
[05:44:22] [PASSED] DP_REMOTE_I2C_READ with transactions array
[05:44:22] [PASSED] DP_REMOTE_I2C_WRITE with port number
[05:44:22] [PASSED] DP_REMOTE_I2C_WRITE with I2C device ID
[05:44:22] [PASSED] DP_REMOTE_I2C_WRITE with data array
[05:44:22] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream ID
[05:44:22] [PASSED] DP_QUERY_STREAM_ENC_STATUS with client ID
[05:44:22] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream event
[05:44:22] [PASSED] DP_QUERY_STREAM_ENC_STATUS with valid stream event
[05:44:22] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream behavior
[05:44:22] [PASSED] DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior
[05:44:22] ===== [PASSED] drm_test_dp_mst_sideband_msg_req_decode =====
[05:44:22] ================ [PASSED] drm_dp_mst_helper ================
[05:44:22] ================== drm_exec (7 subtests) ===================
[05:44:22] [PASSED] sanitycheck
[05:44:22] [PASSED] test_lock
[05:44:22] [PASSED] test_lock_unlock
[05:44:22] [PASSED] test_duplicates
[05:44:22] [PASSED] test_prepare
[05:44:22] [PASSED] test_prepare_array
[05:44:22] [PASSED] test_multiple_loops
[05:44:22] ==================== [PASSED] drm_exec =====================
[05:44:22] =========== drm_format_helper_test (17 subtests) ===========
[05:44:22] ============== drm_test_fb_xrgb8888_to_gray8  ==============
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ========== [PASSED] drm_test_fb_xrgb8888_to_gray8 ==========
[05:44:22] ============= drm_test_fb_xrgb8888_to_rgb332  ==============
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb332 ==========
[05:44:22] ============= drm_test_fb_xrgb8888_to_rgb565  ==============
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb565 ==========
[05:44:22] ============ drm_test_fb_xrgb8888_to_xrgb1555  =============
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ======== [PASSED] drm_test_fb_xrgb8888_to_xrgb1555 =========
[05:44:22] ============ drm_test_fb_xrgb8888_to_argb1555  =============
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ======== [PASSED] drm_test_fb_xrgb8888_to_argb1555 =========
[05:44:22] ============ drm_test_fb_xrgb8888_to_rgba5551  =============
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ======== [PASSED] drm_test_fb_xrgb8888_to_rgba5551 =========
[05:44:22] ============= drm_test_fb_xrgb8888_to_rgb888  ==============
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb888 ==========
[05:44:22] ============ drm_test_fb_xrgb8888_to_argb8888  =============
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ======== [PASSED] drm_test_fb_xrgb8888_to_argb8888 =========
[05:44:22] =========== drm_test_fb_xrgb8888_to_xrgb2101010  ===========
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ======= [PASSED] drm_test_fb_xrgb8888_to_xrgb2101010 =======
[05:44:22] =========== drm_test_fb_xrgb8888_to_argb2101010  ===========
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ======= [PASSED] drm_test_fb_xrgb8888_to_argb2101010 =======
[05:44:22] ============== drm_test_fb_xrgb8888_to_mono  ===============
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ========== [PASSED] drm_test_fb_xrgb8888_to_mono ===========
[05:44:22] ==================== drm_test_fb_swab  =====================
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ================ [PASSED] drm_test_fb_swab =================
[05:44:22] ============ drm_test_fb_xrgb8888_to_xbgr8888  =============
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ======== [PASSED] drm_test_fb_xrgb8888_to_xbgr8888 =========
[05:44:22] ============ drm_test_fb_xrgb8888_to_abgr8888  =============
[05:44:22] [PASSED] single_pixel_source_buffer
[05:44:22] [PASSED] single_pixel_clip_rectangle
[05:44:22] [PASSED] well_known_colors
[05:44:22] [PASSED] destination_pitch
[05:44:22] ======== [PASSED] drm_test_fb_xrgb8888_to_abgr8888 =========
[05:44:22] ================= drm_test_fb_clip_offset  =================
[05:44:22] [PASSED] pass through
[05:44:22] [PASSED] horizontal offset
[05:44:22] [PASSED] vertical offset
[05:44:22] [PASSED] horizontal and vertical offset
[05:44:22] [PASSED] horizontal offset (custom pitch)
[05:44:22] [PASSED] vertical offset (custom pitch)
[05:44:22] [PASSED] horizontal and vertical offset (custom pitch)
[05:44:22] ============= [PASSED] drm_test_fb_clip_offset =============
[05:44:22] ============== drm_test_fb_build_fourcc_list  ==============
[05:44:22] [PASSED] no native formats
[05:44:22] [PASSED] XRGB8888 as native format
[05:44:22] [PASSED] remove duplicates
[05:44:22] [PASSED] convert alpha formats
[05:44:22] [PASSED] random formats
[05:44:22] ========== [PASSED] drm_test_fb_build_fourcc_list ==========
[05:44:22] =================== drm_test_fb_memcpy  ====================
[05:44:22] [PASSED] single_pixel_source_buffer: XR24 little-endian (0x34325258)
[05:44:22] [PASSED] single_pixel_source_buffer: XRA8 little-endian (0x38415258)
[05:44:22] [PASSED] single_pixel_source_buffer: YU24 little-endian (0x34325559)
[05:44:22] [PASSED] single_pixel_clip_rectangle: XB24 little-endian (0x34324258)
[05:44:22] [PASSED] single_pixel_clip_rectangle: XRA8 little-endian (0x38415258)
[05:44:22] [PASSED] single_pixel_clip_rectangle: YU24 little-endian (0x34325559)
[05:44:22] [PASSED] well_known_colors: XB24 little-endian (0x34324258)
[05:44:22] [PASSED] well_known_colors: XRA8 little-endian (0x38415258)
[05:44:22] [PASSED] well_known_colors: YU24 little-endian (0x34325559)
[05:44:22] [PASSED] destination_pitch: XB24 little-endian (0x34324258)
[05:44:22] [PASSED] destination_pitch: XRA8 little-endian (0x38415258)
[05:44:22] [PASSED] destination_pitch: YU24 little-endian (0x34325559)
[05:44:22] =============== [PASSED] drm_test_fb_memcpy ================
[05:44:22] ============= [PASSED] drm_format_helper_test ==============
[05:44:22] ================= drm_format (18 subtests) =================
[05:44:22] [PASSED] drm_test_format_block_width_invalid
[05:44:22] [PASSED] drm_test_format_block_width_one_plane
[05:44:22] [PASSED] drm_test_format_block_width_two_plane
[05:44:22] [PASSED] drm_test_format_block_width_three_plane
[05:44:22] [PASSED] drm_test_format_block_width_tiled
[05:44:22] [PASSED] drm_test_format_block_height_invalid
[05:44:22] [PASSED] drm_test_format_block_height_one_plane
[05:44:22] [PASSED] drm_test_format_block_height_two_plane
[05:44:22] [PASSED] drm_test_format_block_height_three_plane
[05:44:22] [PASSED] drm_test_format_block_height_tiled
[05:44:22] [PASSED] drm_test_format_min_pitch_invalid
[05:44:22] [PASSED] drm_test_format_min_pitch_one_plane_8bpp
[05:44:22] [PASSED] drm_test_format_min_pitch_one_plane_16bpp
[05:44:22] [PASSED] drm_test_format_min_pitch_one_plane_24bpp
[05:44:22] [PASSED] drm_test_format_min_pitch_one_plane_32bpp
[05:44:22] [PASSED] drm_test_format_min_pitch_two_plane
[05:44:22] [PASSED] drm_test_format_min_pitch_three_plane_8bpp
[05:44:22] [PASSED] drm_test_format_min_pitch_tiled
[05:44:22] =================== [PASSED] drm_format ====================
[05:44:22] =============== drm_framebuffer (1 subtest) ================
[05:44:22] =============== drm_test_framebuffer_create  ===============
[05:44:22] [PASSED] ABGR8888 normal sizes
[05:44:22] [PASSED] ABGR8888 max sizes
[05:44:22] [PASSED] ABGR8888 pitch greater than min required
[05:44:22] [PASSED] ABGR8888 pitch less than min required
[05:44:22] [PASSED] ABGR8888 Invalid width
[05:44:22] [PASSED] ABGR8888 Invalid buffer handle
[05:44:22] [PASSED] No pixel format
[05:44:22] [PASSED] ABGR8888 Width 0
[05:44:22] [PASSED] ABGR8888 Height 0
[05:44:22] [PASSED] ABGR8888 Out of bound height * pitch combination
[05:44:22] [PASSED] ABGR8888 Large buffer offset
[05:44:22] [PASSED] ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers
[05:44:22] [PASSED] ABGR8888 Valid buffer modifier
[05:44:22] [PASSED] ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
[05:44:22] [PASSED] ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS
[05:44:22] [PASSED] ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS
[05:44:22] [PASSED] NV12 Normal sizes
[05:44:22] [PASSED] NV12 Max sizes
[05:44:22] [PASSED] NV12 Invalid pitch
[05:44:22] [PASSED] NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag
[05:44:22] [PASSED] NV12 different  modifier per-plane
[05:44:22] [PASSED] NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE
[05:44:22] [PASSED] NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS
[05:44:22] [PASSED] NV12 Modifier for inexistent plane
[05:44:22] [PASSED] NV12 Handle for inexistent plane
[05:44:22] [PASSED] NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS
[05:44:22] [PASSED] YVU420 DRM_MODE_FB_MODIFIERS set without modifier
[05:44:22] [PASSED] YVU420 Normal sizes
[05:44:22] [PASSED] YVU420 Max sizes
[05:44:22] [PASSED] YVU420 Invalid pitch
[05:44:22] [PASSED] YVU420 Different pitches
[05:44:22] [PASSED] YVU420 Different buffer offsets/pitches
[05:44:22] [PASSED] YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS
[05:44:22] [PASSED] YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS
[05:44:22] [PASSED] YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS
[05:44:22] [PASSED] YVU420 Valid modifier
[05:44:22] [PASSED] YVU420 Different modifiers per plane
[05:44:22] [PASSED] YVU420 Modifier for inexistent plane
[05:44:22] [PASSED] X0L2 Normal sizes
[05:44:22] [PASSED] X0L2 Max sizes
[05:44:22] [PASSED] X0L2 Invalid pitch
[05:44:22] [PASSED] X0L2 Pitch greater than minimum required
[05:44:22] [PASSED] X0L2 Handle for inexistent plane
[05:44:22] [PASSED] X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set
[05:44:22] [PASSED] X0L2 Modifier without DRM_MODE_FB_MODIFIERS set
[05:44:22] [PASSED] X0L2 Valid modifier
[05:44:22] [PASSED] X0L2 Modifier for inexistent plane
[05:44:22] =========== [PASSED] drm_test_framebuffer_create ===========
[05:44:22] ================= [PASSED] drm_framebuffer =================
[05:44:22] ================ drm_gem_shmem (8 subtests) ================
[05:44:22] [PASSED] drm_gem_shmem_test_obj_create
[05:44:22] [PASSED] drm_gem_shmem_test_obj_create_private
[05:44:22] [PASSED] drm_gem_shmem_test_pin_pages
[05:44:22] [PASSED] drm_gem_shmem_test_vmap
[05:44:22] [PASSED] drm_gem_shmem_test_get_pages_sgt
[05:44:22] [PASSED] drm_gem_shmem_test_get_sg_table
[05:44:22] [PASSED] drm_gem_shmem_test_madvise
[05:44:22] [PASSED] drm_gem_shmem_test_purge
[05:44:22] ================== [PASSED] drm_gem_shmem ==================
[05:44:22] ================= drm_managed (2 subtests) =================
[05:44:22] [PASSED] drm_test_managed_release_action
[05:44:22] [PASSED] drm_test_managed_run_action
[05:44:22] =================== [PASSED] drm_managed ===================
[05:44:22] =================== drm_mm (6 subtests) ====================
[05:44:22] [PASSED] drm_test_mm_init
[05:44:22] [PASSED] drm_test_mm_debug
[05:44:22] [PASSED] drm_test_mm_align32
[05:44:22] [PASSED] drm_test_mm_align64
[05:44:22] [PASSED] drm_test_mm_lowest
[05:44:22] [PASSED] drm_test_mm_highest
[05:44:22] ===================== [PASSED] drm_mm ======================
[05:44:22] ============= drm_modes_analog_tv (4 subtests) =============
[05:44:22] [PASSED] drm_test_modes_analog_tv_ntsc_480i
[05:44:22] [PASSED] drm_test_modes_analog_tv_ntsc_480i_inlined
[05:44:22] [PASSED] drm_test_modes_analog_tv_pal_576i
[05:44:22] [PASSED] drm_test_modes_analog_tv_pal_576i_inlined
[05:44:22] =============== [PASSED] drm_modes_analog_tv ===============
[05:44:22] ============== drm_plane_helper (2 subtests) ===============
[05:44:22] =============== drm_test_check_plane_state  ================
[05:44:22] [PASSED] clipping_simple
[05:44:22] [PASSED] clipping_rotate_reflect
[05:44:22] [PASSED] positioning_simple
[05:44:22] [PASSED] upscaling
[05:44:22] [PASSED] downscaling
[05:44:22] [PASSED] rounding1
[05:44:22] [PASSED] rounding2
[05:44:22] [PASSED] rounding3
[05:44:22] [PASSED] rounding4
[05:44:22] =========== [PASSED] drm_test_check_plane_state ============
[05:44:22] =========== drm_test_check_invalid_plane_state  ============
[05:44:22] [PASSED] positioning_invalid
[05:44:22] [PASSED] upscaling_invalid
[05:44:22] [PASSED] downscaling_invalid
[05:44:22] ======= [PASSED] drm_test_check_invalid_plane_state ========
[05:44:22] ================ [PASSED] drm_plane_helper =================
[05:44:22] ====== drm_connector_helper_tv_get_modes (1 subtest) =======
[05:44:22] ====== drm_test_connector_helper_tv_get_modes_check  =======
[05:44:22] [PASSED] None
[05:44:22] [PASSED] PAL
[05:44:22] [PASSED] NTSC
[05:44:22] [PASSED] Both, NTSC Default
[05:44:22] [PASSED] Both, PAL Default
[05:44:22] [PASSED] Both, NTSC Default, with PAL on command-line
[05:44:22] [PASSED] Both, PAL Default, with NTSC on command-line
[05:44:22] == [PASSED] drm_test_connector_helper_tv_get_modes_check ===
[05:44:22] ======== [PASSED] drm_connector_helper_tv_get_modes ========
[05:44:22] ================== drm_rect (9 subtests) ===================
[05:44:22] [PASSED] drm_test_rect_clip_scaled_div_by_zero
[05:44:22] [PASSED] drm_test_rect_clip_scaled_not_clipped
[05:44:22] [PASSED] drm_test_rect_clip_scaled_clipped
[05:44:22] [PASSED] drm_test_rect_clip_scaled_signed_vs_unsigned
[05:44:22] ================= drm_test_rect_intersect  =================
[05:44:22] [PASSED] top-left x bottom-right: 2x2+1+1 x 2x2+0+0
stty: 'standard input': Inappropriate ioctl for device
[05:44:22] [PASSED] top-right x bottom-left: 2x2+0+0 x 2x2+1-1
[05:44:22] [PASSED] bottom-left x top-right: 2x2+1-1 x 2x2+0+0
[05:44:22] [PASSED] bottom-right x top-left: 2x2+0+0 x 2x2+1+1
[05:44:22] [PASSED] right x left: 2x1+0+0 x 3x1+1+0
[05:44:22] [PASSED] left x right: 3x1+1+0 x 2x1+0+0
[05:44:22] [PASSED] up x bottom: 1x2+0+0 x 1x3+0-1
[05:44:22] [PASSED] bottom x up: 1x3+0-1 x 1x2+0+0
[05:44:22] [PASSED] touching corner: 1x1+0+0 x 2x2+1+1
[05:44:22] [PASSED] touching side: 1x1+0+0 x 1x1+1+0
[05:44:22] [PASSED] equal rects: 2x2+0+0 x 2x2+0+0
[05:44:22] [PASSED] inside another: 2x2+0+0 x 1x1+1+1
[05:44:22] [PASSED] far away: 1x1+0+0 x 1x1+3+6
[05:44:22] [PASSED] points intersecting: 0x0+5+10 x 0x0+5+10
[05:44:22] [PASSED] points not intersecting: 0x0+0+0 x 0x0+5+10
[05:44:22] ============= [PASSED] drm_test_rect_intersect =============
[05:44:22] ================ drm_test_rect_calc_hscale  ================
[05:44:22] [PASSED] normal use
[05:44:22] [PASSED] out of max range
[05:44:22] [PASSED] out of min range
[05:44:22] [PASSED] zero dst
[05:44:22] [PASSED] negative src
[05:44:22] [PASSED] negative dst
[05:44:22] ============ [PASSED] drm_test_rect_calc_hscale ============
[05:44:22] ================ drm_test_rect_calc_vscale  ================
[05:44:22] [PASSED] normal use
[05:44:22] [PASSED] out of max range
[05:44:22] [PASSED] out of min range
[05:44:22] [PASSED] zero dst
[05:44:22] [PASSED] negative src
[05:44:22] [PASSED] negative dst
[05:44:22] ============ [PASSED] drm_test_rect_calc_vscale ============
[05:44:22] ================== drm_test_rect_rotate  ===================
[05:44:22] [PASSED] reflect-x
[05:44:22] [PASSED] reflect-y
[05:44:22] [PASSED] rotate-0
[05:44:22] [PASSED] rotate-90
[05:44:22] [PASSED] rotate-180
[05:44:22] [PASSED] rotate-270
[05:44:22] ============== [PASSED] drm_test_rect_rotate ===============
[05:44:22] ================ drm_test_rect_rotate_inv  =================
[05:44:22] [PASSED] reflect-x
[05:44:22] [PASSED] reflect-y
[05:44:22] [PASSED] rotate-0
[05:44:22] [PASSED] rotate-90
[05:44:22] [PASSED] rotate-180
[05:44:22] [PASSED] rotate-270
[05:44:22] ============ [PASSED] drm_test_rect_rotate_inv =============
[05:44:22] ==================== [PASSED] drm_rect =====================
[05:44:22] ============================================================
[05:44:22] Testing complete. Ran 416 tests: passed: 416
[05:44:22] Elapsed time: 21.883s total, 1.664s configuring, 20.092s building, 0.125s running

+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel



^ permalink raw reply	[flat|nested] 76+ messages in thread

* ✓ CI.Build: success for Refactor VM bind code (rev5)
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (32 preceding siblings ...)
  2024-03-08  5:44 ` ✓ CI.KUnit: success " Patchwork
@ 2024-03-08  5:55 ` Patchwork
  2024-03-08  5:55 ` ✗ CI.Hooks: failure " Patchwork
                   ` (2 subsequent siblings)
  36 siblings, 0 replies; 76+ messages in thread
From: Patchwork @ 2024-03-08  5:55 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe

== Series Details ==

Series: Refactor VM bind code (rev5)
URL   : https://patchwork.freedesktop.org/series/125608/
State : success

== Summary ==

+ trap cleanup EXIT
+ cd /kernel
+ git clone https://gitlab.freedesktop.org/drm/xe/ci.git .ci
Cloning into '.ci'...
+ '[' -n '' ']'
++ date +%s
+ echo -e '\e[0Ksection_start:1709876673:build_x86_64[collapsed=true]\r\e[0KBuild x86-64'
+ mkdir -p build64-default
^[[0Ksection_start:1709876673:build_x86_64[collapsed=true]
^[[0KBuild x86-64
+ cp .ci/kernel/kconfig build64-default/.config
+ make O=build64-default olddefconfig
make[1]: Entering directory '/kernel/build64-default'
  GEN     Makefile
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/confdata.o
  HOSTCC  scripts/kconfig/expr.o
  LEX     scripts/kconfig/lexer.lex.c
  YACC    scripts/kconfig/parser.tab.[ch]
  HOSTCC  scripts/kconfig/lexer.lex.o
  HOSTCC  scripts/kconfig/menu.o
  HOSTCC  scripts/kconfig/parser.tab.o
  HOSTCC  scripts/kconfig/preprocess.o
  HOSTCC  scripts/kconfig/symbol.o
  HOSTCC  scripts/kconfig/util.o
  HOSTLD  scripts/kconfig/conf
#
# configuration written to .config
#
make[1]: Leaving directory '/kernel/build64-default'
++ nproc
+ make O=build64-default -j48
make[1]: Entering directory '/kernel/build64-default'
  GEN     Makefile
  WRAP    arch/x86/include/generated/uapi/asm/bpf_perf_event.h
  UPD     include/generated/uapi/linux/version.h
  WRAP    arch/x86/include/generated/uapi/asm/errno.h
  WRAP    arch/x86/include/generated/uapi/asm/fcntl.h
  WRAP    arch/x86/include/generated/uapi/asm/ioctl.h
  WRAP    arch/x86/include/generated/uapi/asm/ioctls.h
  WRAP    arch/x86/include/generated/uapi/asm/ipcbuf.h
  WRAP    arch/x86/include/generated/uapi/asm/param.h
  WRAP    arch/x86/include/generated/uapi/asm/poll.h
  WRAP    arch/x86/include/generated/uapi/asm/resource.h
  WRAP    arch/x86/include/generated/uapi/asm/socket.h
  WRAP    arch/x86/include/generated/uapi/asm/sockios.h
  WRAP    arch/x86/include/generated/uapi/asm/termbits.h
  WRAP    arch/x86/include/generated/uapi/asm/termios.h
  WRAP    arch/x86/include/generated/uapi/asm/types.h
  SYSHDR  arch/x86/include/generated/uapi/asm/unistd_64.h
  SYSHDR  arch/x86/include/generated/uapi/asm/unistd_32.h
  SYSHDR  arch/x86/include/generated/uapi/asm/unistd_x32.h
  UPD     include/config/kernel.release
  SYSTBL  arch/x86/include/generated/asm/syscalls_32.h
  SYSHDR  arch/x86/include/generated/asm/unistd_32_ia32.h
  UPD     include/generated/compile.h
  SYSHDR  arch/x86/include/generated/asm/unistd_64_x32.h
  SYSTBL  arch/x86/include/generated/asm/syscalls_64.h
  HYPERCALLS arch/x86/include/generated/asm/xen-hypercalls.h
  HOSTCC  arch/x86/tools/relocs_64.o
  HOSTCC  arch/x86/tools/relocs_32.o
  HOSTCC  arch/x86/tools/relocs_common.o
  WRAP    arch/x86/include/generated/asm/early_ioremap.h
  WRAP    arch/x86/include/generated/asm/mcs_spinlock.h
  WRAP    arch/x86/include/generated/asm/irq_regs.h
  WRAP    arch/x86/include/generated/asm/kmap_size.h
  WRAP    arch/x86/include/generated/asm/local64.h
  HOSTCC  scripts/unifdef
  WRAP    arch/x86/include/generated/asm/mmiowb.h
  WRAP    arch/x86/include/generated/asm/module.lds.h
  WRAP    arch/x86/include/generated/asm/rwonce.h
  WRAP    arch/x86/include/generated/asm/unaligned.h
  UPD     include/generated/utsrelease.h
mkdir -p /kernel/build64-default/tools/objtool && make O=/kernel/build64-default subdir=tools/objtool --no-print-directory -C objtool 
  HOSTCC  scripts/kallsyms
  HOSTCC  scripts/sorttable
  HOSTCC  scripts/asn1_compiler
  HOSTCC  scripts/genksyms/genksyms.o
  YACC    scripts/genksyms/parse.tab.[ch]
  LEX     scripts/genksyms/lex.lex.c
  HOSTCC  scripts/selinux/genheaders/genheaders
  HOSTCC  scripts/selinux/mdp/mdp
  HOSTCC  scripts/sign-file
  HOSTCC  scripts/insert-sys-cert
  HOSTCC  /kernel/build64-default/tools/objtool/fixdep.o
  HOSTLD  /kernel/build64-default/tools/objtool/fixdep-in.o
  LINK    /kernel/build64-default/tools/objtool/fixdep
  HOSTCC  scripts/genksyms/parse.tab.o
  HOSTCC  scripts/genksyms/lex.lex.o
  INSTALL /kernel/build64-default/tools/objtool/libsubcmd/include/subcmd/exec-cmd.h
  INSTALL /kernel/build64-default/tools/objtool/libsubcmd/include/subcmd/help.h
  INSTALL /kernel/build64-default/tools/objtool/libsubcmd/include/subcmd/pager.h
  INSTALL /kernel/build64-default/tools/objtool/libsubcmd/include/subcmd/parse-options.h
  INSTALL /kernel/build64-default/tools/objtool/libsubcmd/include/subcmd/run-command.h
  CC      /kernel/build64-default/tools/objtool/libsubcmd/exec-cmd.o
  CC      /kernel/build64-default/tools/objtool/libsubcmd/help.o
  CC      /kernel/build64-default/tools/objtool/libsubcmd/pager.o
  CC      /kernel/build64-default/tools/objtool/libsubcmd/parse-options.o
  INSTALL libsubcmd_headers
  CC      /kernel/build64-default/tools/objtool/libsubcmd/run-command.o
  CC      /kernel/build64-default/tools/objtool/libsubcmd/sigchain.o
  CC      /kernel/build64-default/tools/objtool/libsubcmd/subcmd-config.o
  HOSTLD  arch/x86/tools/relocs
  HDRINST usr/include/video/edid.h
  HDRINST usr/include/video/sisfb.h
  HDRINST usr/include/video/uvesafb.h
  HDRINST usr/include/drm/amdgpu_drm.h
  HDRINST usr/include/drm/qaic_accel.h
  HDRINST usr/include/drm/i915_drm.h
  HDRINST usr/include/drm/pvr_drm.h
  HDRINST usr/include/drm/vgem_drm.h
  HDRINST usr/include/drm/virtgpu_drm.h
  HDRINST usr/include/drm/xe_drm.h
  HDRINST usr/include/drm/omap_drm.h
  HDRINST usr/include/drm/radeon_drm.h
  HDRINST usr/include/drm/tegra_drm.h
  HDRINST usr/include/drm/drm_mode.h
  HDRINST usr/include/drm/ivpu_accel.h
  HDRINST usr/include/drm/exynos_drm.h
  HDRINST usr/include/drm/drm_sarea.h
  HDRINST usr/include/drm/v3d_drm.h
  HDRINST usr/include/drm/qxl_drm.h
  HDRINST usr/include/drm/drm_fourcc.h
  HDRINST usr/include/drm/nouveau_drm.h
  HDRINST usr/include/drm/habanalabs_accel.h
  HDRINST usr/include/drm/vmwgfx_drm.h
  HDRINST usr/include/drm/msm_drm.h
  HDRINST usr/include/drm/etnaviv_drm.h
  HDRINST usr/include/drm/vc4_drm.h
  HDRINST usr/include/drm/panfrost_drm.h
  HDRINST usr/include/drm/lima_drm.h
  HDRINST usr/include/drm/drm.h
  HDRINST usr/include/drm/panthor_drm.h
  HDRINST usr/include/drm/armada_drm.h
  HDRINST usr/include/mtd/inftl-user.h
  HDRINST usr/include/mtd/nftl-user.h
  HDRINST usr/include/mtd/mtd-user.h
  HDRINST usr/include/mtd/ubi-user.h
  HDRINST usr/include/mtd/mtd-abi.h
  HDRINST usr/include/xen/gntdev.h
  HDRINST usr/include/xen/gntalloc.h
  HDRINST usr/include/xen/evtchn.h
  HDRINST usr/include/xen/privcmd.h
  HDRINST usr/include/asm-generic/auxvec.h
  HDRINST usr/include/asm-generic/bitsperlong.h
  HDRINST usr/include/asm-generic/posix_types.h
  HDRINST usr/include/asm-generic/ioctls.h
  HDRINST usr/include/asm-generic/mman.h
  HDRINST usr/include/asm-generic/shmbuf.h
  HDRINST usr/include/asm-generic/bpf_perf_event.h
  HDRINST usr/include/asm-generic/types.h
  HDRINST usr/include/asm-generic/poll.h
  HDRINST usr/include/asm-generic/swab.h
  HDRINST usr/include/asm-generic/msgbuf.h
  HDRINST usr/include/asm-generic/statfs.h
  HDRINST usr/include/asm-generic/unistd.h
  HDRINST usr/include/asm-generic/hugetlb_encode.h
  HDRINST usr/include/asm-generic/resource.h
  HDRINST usr/include/asm-generic/param.h
  HDRINST usr/include/asm-generic/termbits-common.h
  HDRINST usr/include/asm-generic/sockios.h
  HDRINST usr/include/asm-generic/kvm_para.h
  HDRINST usr/include/asm-generic/errno.h
  HDRINST usr/include/asm-generic/termios.h
  HDRINST usr/include/asm-generic/mman-common.h
  HDRINST usr/include/asm-generic/ioctl.h
  HDRINST usr/include/asm-generic/socket.h
  HDRINST usr/include/asm-generic/signal-defs.h
  HDRINST usr/include/asm-generic/termbits.h
  HDRINST usr/include/asm-generic/int-ll64.h
  HDRINST usr/include/asm-generic/signal.h
  HDRINST usr/include/asm-generic/siginfo.h
  HDRINST usr/include/asm-generic/stat.h
  HDRINST usr/include/asm-generic/int-l64.h
  HDRINST usr/include/asm-generic/errno-base.h
  HDRINST usr/include/asm-generic/fcntl.h
  HDRINST usr/include/asm-generic/setup.h
  HDRINST usr/include/asm-generic/ipcbuf.h
  HDRINST usr/include/asm-generic/sembuf.h
  HDRINST usr/include/asm-generic/ucontext.h
  HDRINST usr/include/rdma/mlx5_user_ioctl_cmds.h
  HDRINST usr/include/rdma/irdma-abi.h
  HDRINST usr/include/rdma/mana-abi.h
  HDRINST usr/include/rdma/hfi/hfi1_user.h
  HDRINST usr/include/rdma/hfi/hfi1_ioctl.h
  HDRINST usr/include/rdma/rdma_user_rxe.h
  HDRINST usr/include/rdma/rdma_user_ioctl.h
  HDRINST usr/include/rdma/mlx5_user_ioctl_verbs.h
  HDRINST usr/include/rdma/bnxt_re-abi.h
  HDRINST usr/include/rdma/hns-abi.h
  HDRINST usr/include/rdma/qedr-abi.h
  HDRINST usr/include/rdma/ib_user_ioctl_cmds.h
  HDRINST usr/include/rdma/vmw_pvrdma-abi.h
  HDRINST usr/include/rdma/ib_user_sa.h
  HDRINST usr/include/rdma/ib_user_ioctl_verbs.h
  HDRINST usr/include/rdma/rvt-abi.h
  HDRINST usr/include/rdma/mlx5-abi.h
  HDRINST usr/include/rdma/rdma_netlink.h
  HDRINST usr/include/rdma/erdma-abi.h
  HDRINST usr/include/rdma/rdma_user_ioctl_cmds.h
  HDRINST usr/include/rdma/rdma_user_cm.h
  HDRINST usr/include/rdma/ib_user_verbs.h
  HDRINST usr/include/rdma/efa-abi.h
  HDRINST usr/include/rdma/siw-abi.h
  HDRINST usr/include/rdma/mlx4-abi.h
  HDRINST usr/include/rdma/mthca-abi.h
  HDRINST usr/include/rdma/ib_user_mad.h
  HDRINST usr/include/rdma/ocrdma-abi.h
  HDRINST usr/include/rdma/cxgb4-abi.h
  HDRINST usr/include/misc/xilinx_sdfec.h
  HDRINST usr/include/misc/uacce/hisi_qm.h
  HDRINST usr/include/misc/uacce/uacce.h
  HDRINST usr/include/misc/cxl.h
  HDRINST usr/include/misc/ocxl.h
  HDRINST usr/include/misc/fastrpc.h
  HDRINST usr/include/misc/pvpanic.h
  HDRINST usr/include/linux/i8k.h
  HDRINST usr/include/linux/acct.h
  HDRINST usr/include/linux/atmmpc.h
  HDRINST usr/include/linux/fs.h
  HDRINST usr/include/linux/cifs/cifs_mount.h
  HDRINST usr/include/linux/cifs/cifs_netlink.h
  HDRINST usr/include/linux/if_packet.h
  HDRINST usr/include/linux/route.h
  HDRINST usr/include/linux/patchkey.h
  HDRINST usr/include/linux/tc_ematch/tc_em_cmp.h
  HDRINST usr/include/linux/tc_ematch/tc_em_ipt.h
  HDRINST usr/include/linux/tc_ematch/tc_em_meta.h
  HDRINST usr/include/linux/tc_ematch/tc_em_nbyte.h
  HDRINST usr/include/linux/tc_ematch/tc_em_text.h
  HDRINST usr/include/linux/virtio_pmem.h
  HDRINST usr/include/linux/rkisp1-config.h
  HDRINST usr/include/linux/vhost.h
  HDRINST usr/include/linux/cec-funcs.h
  HDRINST usr/include/linux/ppdev.h
  HDRINST usr/include/linux/isdn/capicmd.h
  HDRINST usr/include/linux/virtio_fs.h
  HDRINST usr/include/linux/netfilter_ipv6.h
  HDRINST usr/include/linux/lirc.h
  HDRINST usr/include/linux/mroute6.h
  HDRINST usr/include/linux/nl80211-vnd-intel.h
  HDRINST usr/include/linux/ivtvfb.h
  HDRINST usr/include/linux/auxvec.h
  HDRINST usr/include/linux/dm-log-userspace.h
  HDRINST usr/include/linux/dccp.h
  HDRINST usr/include/linux/virtio_scmi.h
  HDRINST usr/include/linux/atmarp.h
  HDRINST usr/include/linux/arcfb.h
  HDRINST usr/include/linux/nbd-netlink.h
  HDRINST usr/include/linux/sched/types.h
  HDRINST usr/include/linux/tcp.h
  HDRINST usr/include/linux/neighbour.h
  HDRINST usr/include/linux/dlm_device.h
  HDRINST usr/include/linux/wmi.h
  HDRINST usr/include/linux/btrfs_tree.h
  HDRINST usr/include/linux/virtio_crypto.h
  HDRINST usr/include/linux/vbox_err.h
  HDRINST usr/include/linux/edd.h
  HDRINST usr/include/linux/loop.h
  HDRINST usr/include/linux/nvme_ioctl.h
  HDRINST usr/include/linux/mmtimer.h
  HDRINST usr/include/linux/if_pppol2tp.h
  HDRINST usr/include/linux/mtio.h
  HDRINST usr/include/linux/if_arcnet.h
  HDRINST usr/include/linux/romfs_fs.h
  HDRINST usr/include/linux/posix_types.h
  HDRINST usr/include/linux/rtc.h
  HDRINST usr/include/linux/landlock.h
  HDRINST usr/include/linux/gpio.h
  HDRINST usr/include/linux/selinux_netlink.h
  HDRINST usr/include/linux/pps.h
  HDRINST usr/include/linux/ndctl.h
  HDRINST usr/include/linux/virtio_gpu.h
  HDRINST usr/include/linux/android/binderfs.h
  HDRINST usr/include/linux/android/binder.h
  HDRINST usr/include/linux/virtio_vsock.h
  HDRINST usr/include/linux/sound.h
  HDRINST usr/include/linux/vtpm_proxy.h
  HDRINST usr/include/linux/nfs_fs.h
  HDRINST usr/include/linux/elf-fdpic.h
  HDRINST usr/include/linux/adfs_fs.h
  HDRINST usr/include/linux/target_core_user.h
  HDRINST usr/include/linux/netlink_diag.h
  HDRINST usr/include/linux/const.h
  HDRINST usr/include/linux/firewire-cdev.h
  HDRINST usr/include/linux/vdpa.h
  HDRINST usr/include/linux/if_infiniband.h
  HDRINST usr/include/linux/serial.h
  HDRINST usr/include/linux/iio/types.h
  HDRINST usr/include/linux/iio/buffer.h
  HDRINST usr/include/linux/iio/events.h
  HDRINST usr/include/linux/baycom.h
  HDRINST usr/include/linux/major.h
  HDRINST usr/include/linux/atmppp.h
  HDRINST usr/include/linux/lsm.h
  HDRINST usr/include/linux/ipv6_route.h
  HDRINST usr/include/linux/spi/spidev.h
  HDRINST usr/include/linux/spi/spi.h
  HDRINST usr/include/linux/virtio_ring.h
  HDRINST usr/include/linux/hdlc/ioctl.h
  HDRINST usr/include/linux/remoteproc_cdev.h
  HDRINST usr/include/linux/hyperv.h
  HDRINST usr/include/linux/rpl_iptunnel.h
  HDRINST usr/include/linux/sync_file.h
  HDRINST usr/include/linux/igmp.h
  HDRINST usr/include/linux/v4l2-dv-timings.h
  HDRINST usr/include/linux/virtio_i2c.h
  HDRINST usr/include/linux/xfrm.h
  HDRINST usr/include/linux/capability.h
  HDRINST usr/include/linux/gtp.h
  HDRINST usr/include/linux/xdp_diag.h
  HDRINST usr/include/linux/pkt_cls.h
  HDRINST usr/include/linux/suspend_ioctls.h
  HDRINST usr/include/linux/vt.h
  HDRINST usr/include/linux/loadpin.h
  HDRINST usr/include/linux/dlm_plock.h
  HDRINST usr/include/linux/fb.h
  HDRINST usr/include/linux/max2175.h
  HDRINST usr/include/linux/sunrpc/debug.h
  HDRINST usr/include/linux/gsmmux.h
  HDRINST usr/include/linux/watchdog.h
  HDRINST usr/include/linux/vhost_types.h
  HDRINST usr/include/linux/vduse.h
  HDRINST usr/include/linux/ila.h
  HDRINST usr/include/linux/tdx-guest.h
  HDRINST usr/include/linux/close_range.h
  HDRINST usr/include/linux/ivtv.h
  HDRINST usr/include/linux/cryptouser.h
  HDRINST usr/include/linux/netfilter/xt_string.h
  HDRINST usr/include/linux/netfilter/nfnetlink_compat.h
  HDRINST usr/include/linux/netfilter/nf_nat.h
  HDRINST usr/include/linux/netfilter/xt_recent.h
  HDRINST usr/include/linux/netfilter/xt_addrtype.h
  HDRINST usr/include/linux/netfilter/nf_conntrack_tcp.h
  HDRINST usr/include/linux/netfilter/xt_MARK.h
  HDRINST usr/include/linux/netfilter/xt_SYNPROXY.h
  HDRINST usr/include/linux/netfilter/xt_multiport.h
  HDRINST usr/include/linux/netfilter/nfnetlink.h
  HDRINST usr/include/linux/netfilter/xt_cgroup.h
  HDRINST usr/include/linux/netfilter/nf_synproxy.h
  HDRINST usr/include/linux/netfilter/xt_TCPOPTSTRIP.h
  HDRINST usr/include/linux/netfilter/nfnetlink_log.h
  HDRINST usr/include/linux/netfilter/xt_TPROXY.h
  HDRINST usr/include/linux/netfilter/xt_u32.h
  HDRINST usr/include/linux/netfilter/nfnetlink_osf.h
  HDRINST usr/include/linux/netfilter/xt_ecn.h
  HDRINST usr/include/linux/netfilter/xt_esp.h
  HDRINST usr/include/linux/netfilter/nfnetlink_hook.h
  HDRINST usr/include/linux/netfilter/xt_mac.h
  HDRINST usr/include/linux/netfilter/xt_comment.h
  HDRINST usr/include/linux/netfilter/xt_NFQUEUE.h
  HDRINST usr/include/linux/netfilter/xt_osf.h
  HDRINST usr/include/linux/netfilter/xt_hashlimit.h
  HDRINST usr/include/linux/netfilter/nf_conntrack_sctp.h
  HDRINST usr/include/linux/netfilter/xt_socket.h
  HDRINST usr/include/linux/netfilter/xt_connmark.h
  HDRINST usr/include/linux/netfilter/xt_sctp.h
  HDRINST usr/include/linux/netfilter/xt_tcpudp.h
  HDRINST usr/include/linux/netfilter/xt_DSCP.h
  HDRINST usr/include/linux/netfilter/xt_time.h
  HDRINST usr/include/linux/netfilter/xt_IDLETIMER.h
  HDRINST usr/include/linux/netfilter/xt_policy.h
  HDRINST usr/include/linux/netfilter/xt_rpfilter.h
  HDRINST usr/include/linux/netfilter/xt_nfacct.h
  HDRINST usr/include/linux/netfilter/xt_SECMARK.h
  HDRINST usr/include/linux/netfilter/xt_length.h
  HDRINST usr/include/linux/netfilter/nfnetlink_cthelper.h
  HDRINST usr/include/linux/netfilter/xt_quota.h
  HDRINST usr/include/linux/netfilter/xt_CLASSIFY.h
  HDRINST usr/include/linux/netfilter/xt_ipcomp.h
  HDRINST usr/include/linux/netfilter/xt_iprange.h
  HDRINST usr/include/linux/netfilter/xt_bpf.h
  HDRINST usr/include/linux/netfilter/xt_LOG.h
  HDRINST usr/include/linux/netfilter/xt_rateest.h
  HDRINST usr/include/linux/netfilter/xt_CONNSECMARK.h
  HDRINST usr/include/linux/netfilter/xt_HMARK.h
  HDRINST usr/include/linux/netfilter/xt_CONNMARK.h
  HDRINST usr/include/linux/netfilter/xt_pkttype.h
  HDRINST usr/include/linux/netfilter/xt_ipvs.h
  HDRINST usr/include/linux/netfilter/xt_devgroup.h
  HDRINST usr/include/linux/netfilter/xt_AUDIT.h
  HDRINST usr/include/linux/netfilter/xt_realm.h
  HDRINST usr/include/linux/netfilter/nf_conntrack_common.h
  HDRINST usr/include/linux/netfilter/xt_set.h
  HDRINST usr/include/linux/netfilter/xt_LED.h
  HDRINST usr/include/linux/netfilter/xt_connlabel.h
  HDRINST usr/include/linux/netfilter/xt_owner.h
  HDRINST usr/include/linux/netfilter/xt_dccp.h
  HDRINST usr/include/linux/netfilter/xt_limit.h
  HDRINST usr/include/linux/netfilter/xt_conntrack.h
  HDRINST usr/include/linux/netfilter/xt_TEE.h
  HDRINST usr/include/linux/netfilter/xt_RATEEST.h
  HDRINST usr/include/linux/netfilter/xt_connlimit.h
  HDRINST usr/include/linux/netfilter/ipset/ip_set.h
  HDRINST usr/include/linux/netfilter/ipset/ip_set_list.h
  HDRINST usr/include/linux/netfilter/ipset/ip_set_hash.h
  HDRINST usr/include/linux/netfilter/ipset/ip_set_bitmap.h
  HDRINST usr/include/linux/netfilter/x_tables.h
  HDRINST usr/include/linux/netfilter/xt_dscp.h
  HDRINST usr/include/linux/netfilter/nf_conntrack_ftp.h
  HDRINST usr/include/linux/netfilter/xt_cluster.h
  HDRINST usr/include/linux/netfilter/nf_conntrack_tuple_common.h
  HDRINST usr/include/linux/netfilter/nf_log.h
  HDRINST usr/include/linux/netfilter/xt_tcpmss.h
  HDRINST usr/include/linux/netfilter/xt_NFLOG.h
  HDRINST usr/include/linux/netfilter/xt_l2tp.h
  HDRINST usr/include/linux/netfilter/xt_helper.h
  HDRINST usr/include/linux/netfilter/xt_statistic.h
  HDRINST usr/include/linux/netfilter/nfnetlink_queue.h
  HDRINST usr/include/linux/netfilter/nfnetlink_cttimeout.h
  HDRINST usr/include/linux/netfilter/xt_CT.h
  HDRINST usr/include/linux/netfilter/xt_CHECKSUM.h
  HDRINST usr/include/linux/netfilter/xt_connbytes.h
  HDRINST usr/include/linux/netfilter/xt_state.h
  HDRINST usr/include/linux/netfilter/nf_tables.h
  HDRINST usr/include/linux/netfilter/xt_mark.h
  HDRINST usr/include/linux/netfilter/xt_cpu.h
  HDRINST usr/include/linux/netfilter/nf_tables_compat.h
  HDRINST usr/include/linux/netfilter/xt_physdev.h
  HDRINST usr/include/linux/netfilter/nfnetlink_conntrack.h
  HDRINST usr/include/linux/netfilter/nfnetlink_acct.h
  HDRINST usr/include/linux/netfilter/xt_TCPMSS.h
  HDRINST usr/include/linux/tty_flags.h
  HDRINST usr/include/linux/if_phonet.h
  HDRINST usr/include/linux/vm_sockets.h
  HDRINST usr/include/linux/elf-em.h
  HOSTLD  scripts/genksyms/genksyms
  HDRINST usr/include/linux/dlmconstants.h
  HDRINST usr/include/linux/bsg.h
  HDRINST usr/include/linux/sysctl.h
  HDRINST usr/include/linux/matroxfb.h
  HDRINST usr/include/linux/unix_diag.h
  HDRINST usr/include/linux/pcitest.h
  HDRINST usr/include/linux/mman.h
  HDRINST usr/include/linux/if_plip.h
  HDRINST usr/include/linux/virtio_balloon.h
  HDRINST usr/include/linux/pidfd.h
  HDRINST usr/include/linux/f2fs.h
  HDRINST usr/include/linux/x25.h
  HDRINST usr/include/linux/if_cablemodem.h
  HDRINST usr/include/linux/utsname.h
  HDRINST usr/include/linux/counter.h
  HDRINST usr/include/linux/atm_tcp.h
  HDRINST usr/include/linux/atalk.h
  HDRINST usr/include/linux/virtio_rng.h
  HDRINST usr/include/linux/bpf_perf_event.h
  HDRINST usr/include/linux/vboxguest.h
  HDRINST usr/include/linux/ipmi_ssif_bmc.h
  HDRINST usr/include/linux/nfs_mount.h
  HDRINST usr/include/linux/sonet.h
  HDRINST usr/include/linux/netfilter.h
  HDRINST usr/include/linux/keyctl.h
  HDRINST usr/include/linux/nl80211.h
  HDRINST usr/include/linux/misc/bcm_vk.h
  HDRINST usr/include/linux/audit.h
  HDRINST usr/include/linux/tipc_config.h
  HDRINST usr/include/linux/tipc_sockets_diag.h
  HDRINST usr/include/linux/futex.h
  HDRINST usr/include/linux/sev-guest.h
  HDRINST usr/include/linux/ublk_cmd.h
  HDRINST usr/include/linux/types.h
  HDRINST usr/include/linux/virtio_input.h
  HDRINST usr/include/linux/if_slip.h
  HDRINST usr/include/linux/personality.h
  HDRINST usr/include/linux/openat2.h
  HDRINST usr/include/linux/poll.h
  HDRINST usr/include/linux/posix_acl.h
  HDRINST usr/include/linux/smc_diag.h
  HDRINST usr/include/linux/snmp.h
  HDRINST usr/include/linux/errqueue.h
  HDRINST usr/include/linux/if_tunnel.h
  HDRINST usr/include/linux/fanotify.h
  HDRINST usr/include/linux/kernel.h
  HDRINST usr/include/linux/rtnetlink.h
  HDRINST usr/include/linux/rpl.h
  HDRINST usr/include/linux/memfd.h
  HDRINST usr/include/linux/serial_core.h
  HDRINST usr/include/linux/dns_resolver.h
  HDRINST usr/include/linux/pr.h
  HDRINST usr/include/linux/atm_eni.h
  HDRINST usr/include/linux/lp.h
  HDRINST usr/include/linux/virtio_mem.h
  HDRINST usr/include/linux/ultrasound.h
  HDRINST usr/include/linux/sctp.h
  HDRINST usr/include/linux/uio.h
  HDRINST usr/include/linux/tcp_metrics.h
  HDRINST usr/include/linux/wwan.h
  HDRINST usr/include/linux/atmbr2684.h
  LD      /kernel/build64-default/tools/objtool/libsubcmd/libsubcmd-in.o
  HDRINST usr/include/linux/in_route.h
  HDRINST usr/include/linux/qemu_fw_cfg.h
  HDRINST usr/include/linux/usb/charger.h
  HDRINST usr/include/linux/if_macsec.h
  HDRINST usr/include/linux/usb/g_uvc.h
  HDRINST usr/include/linux/usb/gadgetfs.h
  HDRINST usr/include/linux/usb/raw_gadget.h
  HDRINST usr/include/linux/usb/cdc-wdm.h
  CC      scripts/mod/empty.o
  HDRINST usr/include/linux/usb/g_printer.h
  HOSTCC  scripts/mod/mk_elfconfig
  HDRINST usr/include/linux/usb/midi.h
  HDRINST usr/include/linux/usb/tmc.h
  HDRINST usr/include/linux/usb/video.h
  CC      scripts/mod/devicetable-offsets.s
  HDRINST usr/include/linux/usb/functionfs.h
  HDRINST usr/include/linux/usb/audio.h
  HDRINST usr/include/linux/usb/ch11.h
  HDRINST usr/include/linux/usb/ch9.h
  HDRINST usr/include/linux/usb/cdc.h
  HDRINST usr/include/linux/jffs2.h
  HDRINST usr/include/linux/ax25.h
  HDRINST usr/include/linux/auto_fs.h
  HDRINST usr/include/linux/tiocl.h
  HDRINST usr/include/linux/scc.h
  HDRINST usr/include/linux/psci.h
  HDRINST usr/include/linux/swab.h
  HDRINST usr/include/linux/cec.h
  HDRINST usr/include/linux/kfd_ioctl.h
  HDRINST usr/include/linux/smc.h
  HDRINST usr/include/linux/qrtr.h
  HDRINST usr/include/linux/screen_info.h
  HDRINST usr/include/linux/nfsacl.h
  HDRINST usr/include/linux/seg6_hmac.h
  AR      /kernel/build64-default/tools/objtool/libsubcmd/libsubcmd.a
  HDRINST usr/include/linux/gameport.h
  HDRINST usr/include/linux/wireless.h
  HDRINST usr/include/linux/fdreg.h
  HDRINST usr/include/linux/cciss_defs.h
  HDRINST usr/include/linux/serial_reg.h
  HDRINST usr/include/linux/perf_event.h
  HDRINST usr/include/linux/in6.h
  HDRINST usr/include/linux/hid.h
  HDRINST usr/include/linux/thp7312.h
  HDRINST usr/include/linux/netlink.h
  HDRINST usr/include/linux/fuse.h
  HDRINST usr/include/linux/magic.h
  HDRINST usr/include/linux/ioam6_iptunnel.h
  HDRINST usr/include/linux/stm.h
  HDRINST usr/include/linux/vsockmon.h
  HDRINST usr/include/linux/seg6.h
  HDRINST usr/include/linux/idxd.h
  HDRINST usr/include/linux/nitro_enclaves.h
  HDRINST usr/include/linux/ptrace.h
  HDRINST usr/include/linux/ioam6_genl.h
  HDRINST usr/include/linux/qnx4_fs.h
  HDRINST usr/include/linux/fsl_mc.h
  HDRINST usr/include/linux/net_tstamp.h
  HDRINST usr/include/linux/msg.h
  HDRINST usr/include/linux/netfilter_ipv4/ipt_TTL.h
  HDRINST usr/include/linux/netfilter_ipv4/ipt_ttl.h
  HDRINST usr/include/linux/netfilter_ipv4/ipt_ah.h
  HDRINST usr/include/linux/netfilter_ipv4/ipt_ECN.h
  HDRINST usr/include/linux/netfilter_ipv4/ip_tables.h
  HDRINST usr/include/linux/netfilter_ipv4/ipt_ecn.h
  HDRINST usr/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
  HDRINST usr/include/linux/netfilter_ipv4/ipt_REJECT.h
  HDRINST usr/include/linux/netfilter_ipv4/ipt_LOG.h
  HDRINST usr/include/linux/sem.h
  HDRINST usr/include/linux/net_namespace.h
  HDRINST usr/include/linux/radeonfb.h
  HDRINST usr/include/linux/tee.h
  HDRINST usr/include/linux/virtio_bt.h
  HDRINST usr/include/linux/udp.h
  HDRINST usr/include/linux/v4l2-subdev.h
  HDRINST usr/include/linux/posix_acl_xattr.h
  HDRINST usr/include/linux/v4l2-mediabus.h
  HDRINST usr/include/linux/atmapi.h
  HDRINST usr/include/linux/raid/md_p.h
  HDRINST usr/include/linux/raid/md_u.h
  HDRINST usr/include/linux/zorro_ids.h
  HDRINST usr/include/linux/nbd.h
  HDRINST usr/include/linux/isst_if.h
  HDRINST usr/include/linux/rxrpc.h
  CC      /kernel/build64-default/tools/objtool/weak.o
  HDRINST usr/include/linux/unistd.h
  CC      /kernel/build64-default/tools/objtool/check.o
  HDRINST usr/include/linux/if_arp.h
  CC      /kernel/build64-default/tools/objtool/special.o
  CC      /kernel/build64-default/tools/objtool/builtin-check.o
  HDRINST usr/include/linux/atm_zatm.h
  HDRINST usr/include/linux/io_uring.h
  CC      /kernel/build64-default/tools/objtool/elf.o
  HDRINST usr/include/linux/if_fddi.h
  HDRINST usr/include/linux/bpqether.h
  MKDIR   /kernel/build64-default/tools/objtool/arch/x86/
  CC      /kernel/build64-default/tools/objtool/objtool.o
  HDRINST usr/include/linux/sysinfo.h
  CC      /kernel/build64-default/tools/objtool/orc_gen.o
  HDRINST usr/include/linux/auto_dev-ioctl.h
  CC      /kernel/build64-default/tools/objtool/orc_dump.o
  MKDIR   /kernel/build64-default/tools/objtool/arch/x86/lib/
  CC      /kernel/build64-default/tools/objtool/libstring.o
  CC      /kernel/build64-default/tools/objtool/arch/x86/special.o
  CC      /kernel/build64-default/tools/objtool/libctype.o
  HDRINST usr/include/linux/nfs4_mount.h
  GEN     /kernel/build64-default/tools/objtool/arch/x86/lib/inat-tables.c
  CC      /kernel/build64-default/tools/objtool/str_error_r.o
  CC      /kernel/build64-default/tools/objtool/librbtree.o
  HDRINST usr/include/linux/keyboard.h
  HDRINST usr/include/linux/virtio_mmio.h
  HDRINST usr/include/linux/input.h
  HDRINST usr/include/linux/qnxtypes.h
  HDRINST usr/include/linux/mdio.h
  HDRINST usr/include/linux/lwtunnel.h
  HDRINST usr/include/linux/gfs2_ondisk.h
  HDRINST usr/include/linux/eventfd.h
  HDRINST usr/include/linux/nfs4.h
  HDRINST usr/include/linux/ptp_clock.h
  HDRINST usr/include/linux/nubus.h
  HDRINST usr/include/linux/if_bonding.h
  HDRINST usr/include/linux/kcov.h
  HDRINST usr/include/linux/fadvise.h
  HDRINST usr/include/linux/taskstats.h
  HDRINST usr/include/linux/veth.h
  HDRINST usr/include/linux/atm.h
  HDRINST usr/include/linux/ipmi.h
  HDRINST usr/include/linux/kdev_t.h
  HDRINST usr/include/linux/mount.h
  HDRINST usr/include/linux/shm.h
  HDRINST usr/include/linux/resource.h
  HDRINST usr/include/linux/prctl.h
  HDRINST usr/include/linux/watch_queue.h
  HDRINST usr/include/linux/sched.h
  HDRINST usr/include/linux/phonet.h
  HDRINST usr/include/linux/random.h
  HDRINST usr/include/linux/tty.h
  HDRINST usr/include/linux/apm_bios.h
  HDRINST usr/include/linux/fd.h
  MKELF   scripts/mod/elfconfig.h
  HDRINST usr/include/linux/um_timetravel.h
  UPD     scripts/mod/devicetable-offsets.h
  HDRINST usr/include/linux/tls.h
  HDRINST usr/include/linux/rpmsg_types.h
  HDRINST usr/include/linux/pfrut.h
  HDRINST usr/include/linux/mei.h
  HOSTCC  scripts/mod/modpost.o
  HDRINST usr/include/linux/fsi.h
  HDRINST usr/include/linux/rds.h
  HOSTCC  scripts/mod/sumversion.o
  HDRINST usr/include/linux/if_x25.h
  HOSTCC  scripts/mod/symsearch.o
  HDRINST usr/include/linux/param.h
  HOSTCC  scripts/mod/file2alias.o
  HDRINST usr/include/linux/netdevice.h
  HDRINST usr/include/linux/binfmts.h
  HDRINST usr/include/linux/if_pppox.h
  HDRINST usr/include/linux/sockios.h
  HDRINST usr/include/linux/kcm.h
  HDRINST usr/include/linux/virtio_9p.h
  HDRINST usr/include/linux/genwqe/genwqe_card.h
  HDRINST usr/include/linux/if_tun.h
  HDRINST usr/include/linux/ext4.h
  HDRINST usr/include/linux/if_ether.h
  HDRINST usr/include/linux/kvm_para.h
  HDRINST usr/include/linux/kernel-page-flags.h
  HDRINST usr/include/linux/cdrom.h
  HDRINST usr/include/linux/un.h
  CC      /kernel/build64-default/tools/objtool/arch/x86/decode.o
  HDRINST usr/include/linux/module.h
  HDRINST usr/include/linux/mqueue.h
  HDRINST usr/include/linux/a.out.h
  HDRINST usr/include/linux/input-event-codes.h
  HDRINST usr/include/linux/coda.h
  HDRINST usr/include/linux/rio_mport_cdev.h
  HDRINST usr/include/linux/ipsec.h
  HDRINST usr/include/linux/blkpg.h
  HDRINST usr/include/linux/blkzoned.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_arpreply.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_redirect.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_nflog.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_802_3.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_nat.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_mark_m.h
  HDRINST usr/include/linux/netfilter_bridge/ebtables.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_vlan.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_limit.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_log.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_stp.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_pkttype.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_ip.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_ip6.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_arp.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_mark_t.h
  HDRINST usr/include/linux/netfilter_bridge/ebt_among.h
  HDRINST usr/include/linux/reiserfs_fs.h
  HDRINST usr/include/linux/cciss_ioctl.h
  HDRINST usr/include/linux/fsmap.h
  HDRINST usr/include/linux/smiapp.h
  HDRINST usr/include/linux/switchtec_ioctl.h
  HDRINST usr/include/linux/atmdev.h
  HDRINST usr/include/linux/hpet.h
  HDRINST usr/include/linux/virtio_config.h
  HDRINST usr/include/linux/string.h
  HDRINST usr/include/linux/nsm.h
  HDRINST usr/include/linux/kfd_sysfs.h
  HDRINST usr/include/linux/inet_diag.h
  HDRINST usr/include/linux/netdev.h
  HDRINST usr/include/linux/xattr.h
  HDRINST usr/include/linux/iommufd.h
  HDRINST usr/include/linux/user_events.h
  HDRINST usr/include/linux/errno.h
  HDRINST usr/include/linux/icmp.h
  HDRINST usr/include/linux/i2o-dev.h
  HDRINST usr/include/linux/pg.h
  HDRINST usr/include/linux/if_bridge.h
  HDRINST usr/include/linux/thermal.h
  HDRINST usr/include/linux/uinput.h
  HDRINST usr/include/linux/handshake.h
  HDRINST usr/include/linux/dqblk_xfs.h
  HDRINST usr/include/linux/v4l2-common.h
  HDRINST usr/include/linux/nvram.h
  HDRINST usr/include/linux/if_vlan.h
  HDRINST usr/include/linux/uhid.h
  HDRINST usr/include/linux/omap3isp.h
  HDRINST usr/include/linux/rose.h
  HDRINST usr/include/linux/phantom.h
  HDRINST usr/include/linux/dpll.h
  HDRINST usr/include/linux/ipmi_msgdefs.h
  HDRINST usr/include/linux/bcm933xx_hcs.h
  HDRINST usr/include/linux/bpf.h
  HDRINST usr/include/linux/mempolicy.h
  HDRINST usr/include/linux/efs_fs_sb.h
  HDRINST usr/include/linux/nexthop.h
  HDRINST usr/include/linux/net_dropmon.h
  HDRINST usr/include/linux/surface_aggregator/cdev.h
  HDRINST usr/include/linux/surface_aggregator/dtx.h
  HDRINST usr/include/linux/net.h
  HDRINST usr/include/linux/mii.h
  HDRINST usr/include/linux/virtio_pcidev.h
  HDRINST usr/include/linux/termios.h
  HDRINST usr/include/linux/cgroupstats.h
  HDRINST usr/include/linux/mpls.h
  HDRINST usr/include/linux/iommu.h
  HDRINST usr/include/linux/toshiba.h
  HDRINST usr/include/linux/virtio_scsi.h
  HDRINST usr/include/linux/zorro.h
  HDRINST usr/include/linux/chio.h
  HDRINST usr/include/linux/pkt_sched.h
  HDRINST usr/include/linux/cramfs_fs.h
  HDRINST usr/include/linux/nfs3.h
  HDRINST usr/include/linux/vfio_ccw.h
  HDRINST usr/include/linux/atm_nicstar.h
  HDRINST usr/include/linux/ncsi.h
  HDRINST usr/include/linux/virtio_net.h
  HDRINST usr/include/linux/ioctl.h
  HDRINST usr/include/linux/stddef.h
  HDRINST usr/include/linux/limits.h
  HDRINST usr/include/linux/ipmi_bmc.h
  HDRINST usr/include/linux/netfilter_arp.h
  HDRINST usr/include/linux/if_addr.h
  HDRINST usr/include/linux/rpmsg.h
  HDRINST usr/include/linux/media-bus-format.h
  HDRINST usr/include/linux/kernelcapi.h
  HDRINST usr/include/linux/ppp_defs.h
  HDRINST usr/include/linux/ethtool.h
  HDRINST usr/include/linux/aspeed-video.h
  HDRINST usr/include/linux/hdlc.h
  HDRINST usr/include/linux/fscrypt.h
  HDRINST usr/include/linux/batadv_packet.h
  HDRINST usr/include/linux/uuid.h
  HDRINST usr/include/linux/capi.h
  HDRINST usr/include/linux/mptcp.h
  HDRINST usr/include/linux/hidraw.h
  HDRINST usr/include/linux/virtio_console.h
  HDRINST usr/include/linux/irqnr.h
  HDRINST usr/include/linux/coresight-stm.h
  HDRINST usr/include/linux/cxl_mem.h
  HDRINST usr/include/linux/iso_fs.h
  HDRINST usr/include/linux/virtio_blk.h
  HDRINST usr/include/linux/udf_fs_i.h
  HDRINST usr/include/linux/coff.h
  HDRINST usr/include/linux/dma-buf.h
  HDRINST usr/include/linux/ife.h
  HDRINST usr/include/linux/agpgart.h
  HDRINST usr/include/linux/socket.h
  HDRINST usr/include/linux/nilfs2_ondisk.h
  HDRINST usr/include/linux/connector.h
  HDRINST usr/include/linux/auto_fs4.h
  HDRINST usr/include/linux/bt-bmc.h
  HDRINST usr/include/linux/map_to_7segment.h
  HDRINST usr/include/linux/tc_act/tc_skbedit.h
  HDRINST usr/include/linux/tc_act/tc_ctinfo.h
  HDRINST usr/include/linux/tc_act/tc_defact.h
  HDRINST usr/include/linux/tc_act/tc_gact.h
  HDRINST usr/include/linux/tc_act/tc_vlan.h
  HDRINST usr/include/linux/tc_act/tc_skbmod.h
  HDRINST usr/include/linux/tc_act/tc_sample.h
  HDRINST usr/include/linux/tc_act/tc_tunnel_key.h
  HDRINST usr/include/linux/tc_act/tc_gate.h
  HDRINST usr/include/linux/tc_act/tc_mirred.h
  HDRINST usr/include/linux/tc_act/tc_nat.h
  HDRINST usr/include/linux/tc_act/tc_csum.h
  HDRINST usr/include/linux/tc_act/tc_connmark.h
  HDRINST usr/include/linux/tc_act/tc_ife.h
  HDRINST usr/include/linux/tc_act/tc_mpls.h
  HDRINST usr/include/linux/tc_act/tc_ct.h
  HDRINST usr/include/linux/tc_act/tc_pedit.h
  HDRINST usr/include/linux/tc_act/tc_bpf.h
  HDRINST usr/include/linux/netrom.h
  HDRINST usr/include/linux/joystick.h
  HDRINST usr/include/linux/falloc.h
  HDRINST usr/include/linux/cycx_cfm.h
  HDRINST usr/include/linux/omapfb.h
  HDRINST usr/include/linux/msdos_fs.h
  HDRINST usr/include/linux/virtio_types.h
  HDRINST usr/include/linux/mroute.h
  HDRINST usr/include/linux/psample.h
  HDRINST usr/include/linux/ipv6.h
  HDRINST usr/include/linux/nfsd_netlink.h
  HDRINST usr/include/linux/dw100.h
  HDRINST usr/include/linux/psp-sev.h
  HDRINST usr/include/linux/vfio.h
  HDRINST usr/include/linux/if_ppp.h
  HDRINST usr/include/linux/byteorder/big_endian.h
  HDRINST usr/include/linux/byteorder/little_endian.h
  HDRINST usr/include/linux/comedi.h
  HDRINST usr/include/linux/scif_ioctl.h
  HDRINST usr/include/linux/timerfd.h
  HDRINST usr/include/linux/time_types.h
  HDRINST usr/include/linux/firewire-constants.h
  HDRINST usr/include/linux/virtio_snd.h
  HDRINST usr/include/linux/ppp-ioctl.h
  HDRINST usr/include/linux/fib_rules.h
  HDRINST usr/include/linux/gen_stats.h
  HDRINST usr/include/linux/virtio_iommu.h
  HDRINST usr/include/linux/genetlink.h
  HDRINST usr/include/linux/uvcvideo.h
  HDRINST usr/include/linux/pfkeyv2.h
  HDRINST usr/include/linux/soundcard.h
  HDRINST usr/include/linux/times.h
  HDRINST usr/include/linux/nfc.h
  HDRINST usr/include/linux/affs_hardblocks.h
  HDRINST usr/include/linux/nilfs2_api.h
  HDRINST usr/include/linux/rseq.h
  HDRINST usr/include/linux/caif/caif_socket.h
  HDRINST usr/include/linux/i2c-dev.h
  HDRINST usr/include/linux/caif/if_caif.h
  HDRINST usr/include/linux/cuda.h
  HDRINST usr/include/linux/mei_uuid.h
  HDRINST usr/include/linux/cn_proc.h
  HDRINST usr/include/linux/parport.h
  HDRINST usr/include/linux/v4l2-controls.h
  HDRINST usr/include/linux/hsi/cs-protocol.h
  HDRINST usr/include/linux/hsi/hsi_char.h
  HDRINST usr/include/linux/seg6_genl.h
  HDRINST usr/include/linux/am437x-vpfe.h
  HDRINST usr/include/linux/amt.h
  HDRINST usr/include/linux/netconf.h
  HDRINST usr/include/linux/erspan.h
  HDRINST usr/include/linux/nsfs.h
  HDRINST usr/include/linux/xilinx-v4l2-controls.h
  HDRINST usr/include/linux/aspeed-p2a-ctrl.h
  HDRINST usr/include/linux/vfio_zdev.h
  HDRINST usr/include/linux/serio.h
  HDRINST usr/include/linux/acrn.h
  HDRINST usr/include/linux/nfs2.h
  HDRINST usr/include/linux/mptcp_pm.h
  HDRINST usr/include/linux/virtio_pci.h
  HDRINST usr/include/linux/ipc.h
  HDRINST usr/include/linux/ethtool_netlink.h
  HDRINST usr/include/linux/kd.h
  HDRINST usr/include/linux/elf.h
  HDRINST usr/include/linux/videodev2.h
  HDRINST usr/include/linux/if_alg.h
  HDRINST usr/include/linux/sonypi.h
  HDRINST usr/include/linux/fsverity.h
  HDRINST usr/include/linux/if.h
  HDRINST usr/include/linux/btrfs.h
  HDRINST usr/include/linux/vm_sockets_diag.h
  HDRINST usr/include/linux/netfilter_bridge.h
  HDRINST usr/include/linux/packet_diag.h
  HDRINST usr/include/linux/netfilter_ipv4.h
  HDRINST usr/include/linux/kvm.h
  HDRINST usr/include/linux/pci.h
  HDRINST usr/include/linux/if_addrlabel.h
  HDRINST usr/include/linux/hdlcdrv.h
  HDRINST usr/include/linux/cfm_bridge.h
  HDRINST usr/include/linux/fiemap.h
  HDRINST usr/include/linux/dm-ioctl.h
  HDRINST usr/include/linux/aspeed-lpc-ctrl.h
  HDRINST usr/include/linux/atmioc.h
  HDRINST usr/include/linux/dlm.h
  HDRINST usr/include/linux/pci_regs.h
  HDRINST usr/include/linux/cachefiles.h
  HDRINST usr/include/linux/membarrier.h
  HDRINST usr/include/linux/nfs_idmap.h
  HDRINST usr/include/linux/ip.h
  HDRINST usr/include/linux/atm_he.h
  HDRINST usr/include/linux/nfsd/export.h
  HDRINST usr/include/linux/nfsd/stats.h
  HDRINST usr/include/linux/nfsd/debug.h
  HDRINST usr/include/linux/nfsd/cld.h
  HDRINST usr/include/linux/ip_vs.h
  HDRINST usr/include/linux/vmcore.h
  HDRINST usr/include/linux/vbox_vmmdev_types.h
  HDRINST usr/include/linux/dvb/osd.h
  HDRINST usr/include/linux/dvb/dmx.h
  HDRINST usr/include/linux/dvb/net.h
  HDRINST usr/include/linux/dvb/frontend.h
  HDRINST usr/include/linux/dvb/ca.h
  HDRINST usr/include/linux/dvb/version.h
  HDRINST usr/include/linux/dvb/video.h
  HDRINST usr/include/linux/dvb/audio.h
  HDRINST usr/include/linux/nfs.h
  HDRINST usr/include/linux/if_link.h
  HDRINST usr/include/linux/wait.h
  HDRINST usr/include/linux/icmpv6.h
  HDRINST usr/include/linux/media.h
  HDRINST usr/include/linux/seg6_local.h
  HDRINST usr/include/linux/tps6594_pfsm.h
  HDRINST usr/include/linux/openvswitch.h
  HDRINST usr/include/linux/atmsap.h
  HDRINST usr/include/linux/fpga-dfl.h
  HDRINST usr/include/linux/signal.h
  HDRINST usr/include/linux/userio.h
  HDRINST usr/include/linux/map_to_14segment.h
  HDRINST usr/include/linux/hdreg.h
  HDRINST usr/include/linux/utime.h
  HDRINST usr/include/linux/usbdevice_fs.h
  HDRINST usr/include/linux/timex.h
  HDRINST usr/include/linux/if_fc.h
  HDRINST usr/include/linux/reiserfs_xattr.h
  HDRINST usr/include/linux/hw_breakpoint.h
  HDRINST usr/include/linux/quota.h
  HDRINST usr/include/linux/ioprio.h
  HDRINST usr/include/linux/eventpoll.h
  HDRINST usr/include/linux/atmclip.h
  HDRINST usr/include/linux/can.h
  HDRINST usr/include/linux/if_team.h
  HDRINST usr/include/linux/usbip.h
  HDRINST usr/include/linux/stat.h
  HDRINST usr/include/linux/fou.h
  HDRINST usr/include/linux/hash_info.h
  HDRINST usr/include/linux/ppp-comp.h
  HDRINST usr/include/linux/ip6_tunnel.h
  HDRINST usr/include/linux/tipc_netlink.h
  HDRINST usr/include/linux/in.h
  HDRINST usr/include/linux/wireguard.h
  HDRINST usr/include/linux/btf.h
  HDRINST usr/include/linux/batman_adv.h
  HDRINST usr/include/linux/fcntl.h
  HDRINST usr/include/linux/if_ltalk.h
  HDRINST usr/include/linux/i2c.h
  HDRINST usr/include/linux/atm_idt77105.h
  HDRINST usr/include/linux/arm_sdei.h
  HDRINST usr/include/linux/kexec.h
  HDRINST usr/include/linux/netfilter_ipv6/ip6_tables.h
  HDRINST usr/include/linux/netfilter_ipv6/ip6t_ah.h
  HDRINST usr/include/linux/netfilter_ipv6/ip6t_NPT.h
  HDRINST usr/include/linux/netfilter_ipv6/ip6t_rt.h
  HDRINST usr/include/linux/netfilter_ipv6/ip6t_REJECT.h
  HDRINST usr/include/linux/netfilter_ipv6/ip6t_opts.h
  HDRINST usr/include/linux/netfilter_ipv6/ip6t_srh.h
  HDRINST usr/include/linux/netfilter_ipv6/ip6t_LOG.h
  HDRINST usr/include/linux/netfilter_ipv6/ip6t_mh.h
  HDRINST usr/include/linux/netfilter_ipv6/ip6t_HL.h
  HDRINST usr/include/linux/netfilter_ipv6/ip6t_hl.h
  HDRINST usr/include/linux/netfilter_ipv6/ip6t_frag.h
  HDRINST usr/include/linux/netfilter_ipv6/ip6t_ipv6header.h
  HDRINST usr/include/linux/minix_fs.h
  HDRINST usr/include/linux/aio_abi.h
  HDRINST usr/include/linux/pktcdvd.h
  HDRINST usr/include/linux/libc-compat.h
  HDRINST usr/include/linux/atmlec.h
  HDRINST usr/include/linux/signalfd.h
  HDRINST usr/include/linux/bpf_common.h
  HDRINST usr/include/linux/seg6_iptunnel.h
  HDRINST usr/include/linux/synclink.h
  HDRINST usr/include/linux/mpls_iptunnel.h
  HDRINST usr/include/linux/mctp.h
  HDRINST usr/include/linux/if_xdp.h
  HDRINST usr/include/linux/llc.h
  HDRINST usr/include/linux/atmsvc.h
  HDRINST usr/include/linux/sed-opal.h
  HDRINST usr/include/linux/sock_diag.h
  HDRINST usr/include/linux/time.h
  HDRINST usr/include/linux/securebits.h
  HDRINST usr/include/linux/fsl_hypervisor.h
  HDRINST usr/include/linux/if_hippi.h
  HDRINST usr/include/linux/seccomp.h
  HDRINST usr/include/linux/oom.h
  HDRINST usr/include/linux/filter.h
  HDRINST usr/include/linux/inotify.h
  HDRINST usr/include/linux/rfkill.h
  HDRINST usr/include/linux/reboot.h
  HDRINST usr/include/linux/can/vxcan.h
  HDRINST usr/include/linux/can/j1939.h
  HDRINST usr/include/linux/can/netlink.h
  HDRINST usr/include/linux/can/bcm.h
  HDRINST usr/include/linux/can/raw.h
  HDRINST usr/include/linux/can/gw.h
  HDRINST usr/include/linux/can/error.h
  HDRINST usr/include/linux/can/isotp.h
  HDRINST usr/include/linux/if_eql.h
  HDRINST usr/include/linux/psp-dbc.h
  HDRINST usr/include/linux/hiddev.h
  HDRINST usr/include/linux/blktrace_api.h
  HDRINST usr/include/linux/ccs.h
  HDRINST usr/include/linux/ioam6.h
  HDRINST usr/include/linux/hsr_netlink.h
  HDRINST usr/include/linux/mmc/ioctl.h
  HDRINST usr/include/linux/bfs_fs.h
  HDRINST usr/include/linux/npcm-video.h
  HDRINST usr/include/linux/rio_cm_cdev.h
  HDRINST usr/include/linux/uleds.h
  HDRINST usr/include/linux/mrp_bridge.h
  HDRINST usr/include/linux/adb.h
  HDRINST usr/include/linux/pmu.h
  HDRINST usr/include/linux/udmabuf.h
  HDRINST usr/include/linux/kcmp.h
  HDRINST usr/include/linux/dma-heap.h
  HDRINST usr/include/linux/userfaultfd.h
  HDRINST usr/include/linux/netfilter_arp/arpt_mangle.h
  HDRINST usr/include/linux/netfilter_arp/arp_tables.h
  HDRINST usr/include/linux/tipc.h
  HDRINST usr/include/linux/virtio_ids.h
  HDRINST usr/include/linux/l2tp.h
  HDRINST usr/include/linux/devlink.h
  HDRINST usr/include/linux/virtio_gpio.h
  HDRINST usr/include/linux/dcbnl.h
  HDRINST usr/include/linux/cyclades.h
  HDRINST usr/include/regulator/regulator.h
  HDRINST usr/include/sound/intel/avs/tokens.h
  HDRINST usr/include/sound/sof/fw.h
  HDRINST usr/include/sound/sof/abi.h
  HDRINST usr/include/sound/sof/tokens.h
  HDRINST usr/include/sound/sof/header.h
  HDRINST usr/include/sound/usb_stream.h
  HDRINST usr/include/sound/sfnt_info.h
  HDRINST usr/include/sound/asequencer.h
  HDRINST usr/include/sound/tlv.h
  HDRINST usr/include/sound/scarlett2.h
  HDRINST usr/include/sound/asound.h
  HDRINST usr/include/sound/asoc.h
  HDRINST usr/include/sound/sb16_csp.h
  HDRINST usr/include/sound/compress_offload.h
  HDRINST usr/include/sound/hdsp.h
  HDRINST usr/include/sound/emu10k1.h
  HDRINST usr/include/sound/snd_ar_tokens.h
  HDRINST usr/include/sound/snd_sst_tokens.h
  HDRINST usr/include/sound/asound_fm.h
  HDRINST usr/include/sound/hdspm.h
  HDRINST usr/include/sound/compress_params.h
  HDRINST usr/include/sound/firewire.h
  HDRINST usr/include/sound/skl-tplg-interface.h
  HDRINST usr/include/scsi/scsi_bsg_ufs.h
  HDRINST usr/include/scsi/scsi_netlink_fc.h
  HDRINST usr/include/scsi/scsi_bsg_mpi3mr.h
  HDRINST usr/include/scsi/fc/fc_ns.h
  HDRINST usr/include/scsi/fc/fc_fs.h
  HDRINST usr/include/scsi/fc/fc_els.h
  HDRINST usr/include/scsi/fc/fc_gs.h
  HDRINST usr/include/scsi/scsi_bsg_fc.h
  HDRINST usr/include/scsi/cxlflash_ioctl.h
  HDRINST usr/include/scsi/scsi_netlink.h
  HDRINST usr/include/linux/version.h
  HDRINST usr/include/asm/processor-flags.h
  HDRINST usr/include/asm/auxvec.h
  HDRINST usr/include/asm/svm.h
  HDRINST usr/include/asm/bitsperlong.h
  HDRINST usr/include/asm/kvm_perf.h
  HDRINST usr/include/asm/mce.h
  HDRINST usr/include/asm/posix_types.h
  HDRINST usr/include/asm/msr.h
  HDRINST usr/include/asm/sigcontext32.h
  HDRINST usr/include/asm/mman.h
  HDRINST usr/include/asm/shmbuf.h
  HDRINST usr/include/asm/e820.h
  HDRINST usr/include/asm/posix_types_64.h
  HDRINST usr/include/asm/vsyscall.h
  HDRINST usr/include/asm/msgbuf.h
  HDRINST usr/include/asm/swab.h
  HDRINST usr/include/asm/statfs.h
  HDRINST usr/include/asm/posix_types_x32.h
  HDRINST usr/include/asm/ptrace.h
  HDRINST usr/include/asm/unistd.h
  HDRINST usr/include/asm/ist.h
  HDRINST usr/include/asm/boot.h
  HDRINST usr/include/asm/prctl.h
  HDRINST usr/include/asm/sigcontext.h
  HDRINST usr/include/asm/posix_types_32.h
  HDRINST usr/include/asm/kvm_para.h
  HDRINST usr/include/asm/a.out.h
  HDRINST usr/include/asm/mtrr.h
  HDRINST usr/include/asm/amd_hsmp.h
  HDRINST usr/include/asm/hwcap2.h
  HDRINST usr/include/asm/ptrace-abi.h
  HDRINST usr/include/asm/vm86.h
  HDRINST usr/include/asm/vmx.h
  HDRINST usr/include/asm/ldt.h
  HDRINST usr/include/asm/perf_regs.h
  HDRINST usr/include/asm/kvm.h
  HDRINST usr/include/asm/debugreg.h
  HDRINST usr/include/asm/signal.h
  HDRINST usr/include/asm/bootparam.h
  HDRINST usr/include/asm/siginfo.h
  HDRINST usr/include/asm/hw_breakpoint.h
  HDRINST usr/include/asm/stat.h
  HDRINST usr/include/asm/setup.h
  HDRINST usr/include/asm/sembuf.h
  HDRINST usr/include/asm/sgx.h
  HDRINST usr/include/asm/ucontext.h
  HDRINST usr/include/asm/byteorder.h
  HDRINST usr/include/asm/unistd_64.h
  HDRINST usr/include/asm/ioctls.h
  HDRINST usr/include/asm/bpf_perf_event.h
  HDRINST usr/include/asm/types.h
  HDRINST usr/include/asm/poll.h
  HDRINST usr/include/asm/resource.h
  HDRINST usr/include/asm/param.h
  HDRINST usr/include/asm/sockios.h
  HDRINST usr/include/asm/errno.h
  HDRINST usr/include/asm/unistd_x32.h
  HDRINST usr/include/asm/termios.h
  HDRINST usr/include/asm/ioctl.h
  HDRINST usr/include/asm/socket.h
  HDRINST usr/include/asm/unistd_32.h
  HDRINST usr/include/asm/termbits.h
  HDRINST usr/include/asm/fcntl.h
  HDRINST usr/include/asm/ipcbuf.h
  LD      /kernel/build64-default/tools/objtool/arch/x86/objtool-in.o
  HOSTLD  scripts/mod/modpost
  CHKSHA1 ../include/linux/atomic/atomic-arch-fallback.h
  CC      kernel/bounds.s
  CHKSHA1 ../include/linux/atomic/atomic-instrumented.h
  CHKSHA1 ../include/linux/atomic/atomic-long.h
  UPD     include/generated/timeconst.h
  UPD     include/generated/bounds.h
  CC      arch/x86/kernel/asm-offsets.s
  UPD     include/generated/asm-offsets.h
  CALL    ../scripts/checksyscalls.sh
  SYMLINK scripts/gdb/linux/clk.py
  SYMLINK scripts/gdb/linux/config.py
  SYMLINK scripts/gdb/linux/vmalloc.py
  SYMLINK scripts/gdb/linux/genpd.py
  SYMLINK scripts/gdb/linux/tasks.py
  SYMLINK scripts/gdb/linux/modules.py
  SYMLINK scripts/gdb/linux/proc.py
  SYMLINK scripts/gdb/linux/utils.py
  SYMLINK scripts/gdb/linux/timerlist.py
  SYMLINK scripts/gdb/linux/vfs.py
  SYMLINK scripts/gdb/linux/stackdepot.py
  SYMLINK scripts/gdb/linux/pgtable.py
  SYMLINK scripts/gdb/linux/radixtree.py
  SYMLINK scripts/gdb/linux/lists.py
  SYMLINK scripts/gdb/linux/symbols.py
  SYMLINK scripts/gdb/linux/interrupts.py
  SYMLINK scripts/gdb/linux/__init__.py
  SYMLINK scripts/gdb/linux/mm.py
  SYMLINK scripts/gdb/linux/cpus.py
  SYMLINK scripts/gdb/linux/rbtree.py
  SYMLINK scripts/gdb/linux/page_owner.py
  SYMLINK scripts/gdb/linux/device.py
  SYMLINK scripts/gdb/linux/dmesg.py
  SYMLINK scripts/gdb/linux/slab.py
  GEN     scripts/gdb/linux/constants.py
  LD      /kernel/build64-default/tools/objtool/objtool-in.o
  LINK    /kernel/build64-default/tools/objtool/objtool
  LDS     scripts/module.lds
  HOSTCC  usr/gen_init_cpio
  AS      arch/x86/lib/clear_page_64.o
  CC      block/bdev.o
  CC      init/main.o
  CC      arch/x86/lib/cmdline.o
  CC      certs/system_keyring.o
  AS      arch/x86/lib/cmpxchg16b_emu.o
  CC      io_uring/io_uring.o
  CC      block/fops.o
  CC      arch/x86/pci/i386.o
  CC      arch/x86/video/fbdev.o
  CC      ipc/compat.o
  CC      arch/x86/xen/enlighten.o
  CC      arch/x86/power/cpu.o
  UPD     init/utsversion-tmp.h
  GEN     security/selinux/flask.h security/selinux/av_permissions.h
  AR      samples/vfio-mdev/built-in.a
  CC      block/partitions/core.o
  CC      arch/x86/platform/pvh/enlighten.o
  CC      arch/x86/ia32/audit.o
  AR      arch/x86/virt/vmx/built-in.a
  CC      fs/quota/dquot.o
  CC      fs/crypto/crypto.o
  AR      drivers/cache/built-in.a
  CC      fs/verity/enable.o
  CC      arch/x86/coco/tdx/tdx.o
  CC      arch/x86/realmode/init.o
  AS      arch/x86/crypto/blake2s-core.o
  AR      fs/nfs_common/built-in.a
  AR      virt/lib/built-in.a
  CC      fs/iomap/trace.o
  CC      arch/x86/events/amd/core.o
  CC      security/smack/smack_lsm.o
  CC      fs/crypto/fname.o
  CC      security/selinux/avc.o
  AR      samples/built-in.a
  CC      net/ethernet/eth.o
  CC      net/core/sock.o
  CC      arch/x86/mm/pat/set_memory.o
  CC      mm/kfence/core.o
  CC [M]  fs/nfs_common/grace.o
  AR      arch/x86/virt/built-in.a
  CC      security/tomoyo/audit.o
  CC [M]  virt/lib/irqbypass.o
  CC      fs/notify/dnotify/dnotify.o
  ASN.1   security/keys/trusted-keys/tpm2key.asn1.[ch]
  CC      arch/x86/kernel/fpu/init.o
  CC      security/keys/trusted-keys/trusted_core.o
  AR      arch/x86/platform/atom/built-in.a
  CC      arch/x86/lib/copy_mc.o
  AR      drivers/irqchip/built-in.a
  CC      lib/kunit/hooks.o
  CC [M]  sound/core/seq/seq.o
  CC [M]  sound/core/seq/seq_lock.o
  AR      arch/x86/platform/ce4100/built-in.a
  CC      arch/x86/entry/vdso/vma.o
  CC      arch/x86/net/bpf_jit_comp.o
  CC      arch/x86/crypto/blake2s-glue.o
  CC      arch/x86/platform/efi/memmap.o
  AR      drivers/bus/mhi/built-in.a
  CC      kernel/sched/core.o
  AR      drivers/bus/built-in.a
  AR      arch/x86/ia32/built-in.a
  CC      crypto/asymmetric_keys/asymmetric_type.o
  CC      kernel/sched/fair.o
  AR      drivers/phy/allwinner/built-in.a
  CC      kernel/sched/build_policy.o
  AR      drivers/phy/amlogic/built-in.a
  CC      fs/proc/task_mmu.o
  AR      drivers/phy/broadcom/built-in.a
  AR      drivers/phy/cadence/built-in.a
  AR      drivers/phy/freescale/built-in.a
  AR      drivers/phy/hisilicon/built-in.a
  AR      drivers/phy/ingenic/built-in.a
  GEN     usr/initramfs_data.cpio
  AR      drivers/phy/intel/built-in.a
  COPY    usr/initramfs_inc_data
  AR      drivers/phy/lantiq/built-in.a
  AS      usr/initramfs_data.o
  AR      drivers/phy/marvell/built-in.a
  AR      drivers/phy/mediatek/built-in.a
  CC      arch/x86/crypto/crc32c-intel_glue.o
  CC [M]  lib/kunit/test.o
  CC      init/do_mounts.o
  AR      usr/built-in.a
  AR      drivers/phy/microchip/built-in.a
  CC      fs/quota/quota.o
  AR      drivers/phy/motorola/built-in.a
  AR      drivers/phy/mscc/built-in.a
  AR      drivers/phy/qualcomm/built-in.a
  AR      drivers/phy/ralink/built-in.a
  AR      drivers/phy/renesas/built-in.a
  AR      drivers/phy/rockchip/built-in.a
  AR      drivers/phy/samsung/built-in.a
  AR      drivers/phy/socionext/built-in.a
  AR      drivers/phy/st/built-in.a
  AR      drivers/phy/starfive/built-in.a
  AR      drivers/phy/sunplus/built-in.a
  AR      drivers/phy/tegra/built-in.a
  AR      drivers/phy/ti/built-in.a
  AR      drivers/phy/xilinx/built-in.a
  CC      drivers/phy/phy-core.o
  CC      fs/quota/kqid.o
  AS      arch/x86/lib/copy_mc_64.o
  CC      arch/x86/kernel/fpu/bugs.o
  AS      arch/x86/platform/pvh/head.o
  HOSTCC  certs/extract-cert
  AS      arch/x86/realmode/rm/header.o
  AS      arch/x86/lib/copy_page_64.o
  CC      ipc/util.o
  AR      arch/x86/platform/pvh/built-in.a
  CC      arch/x86/power/hibernate_64.o
  AS      arch/x86/realmode/rm/trampoline_64.o
  AR      fs/notify/dnotify/built-in.a
  AS      arch/x86/realmode/rm/stack.o
  CC      fs/notify/inotify/inotify_fsnotify.o
  AS      arch/x86/realmode/rm/reboot.o
  AS      arch/x86/realmode/rm/wakeup_asm.o
  CC      arch/x86/kernel/fpu/core.o
  CC [M]  sound/core/seq/seq_clientmgr.o
  COPY    certs/x509.genkey
  CC      certs/blacklist.o
  CC      arch/x86/realmode/rm/wakemain.o
  AR      virt/built-in.a
  CC      arch/x86/platform/efi/quirks.o
  CC      arch/x86/entry/vdso/extable.o
  CC      arch/x86/platform/efi/efi.o
  AS      arch/x86/lib/copy_user_64.o
  CC      fs/verity/hash_algs.o
  AS      arch/x86/crypto/crc32c-pcl-intel-asm_64.o
  CC      arch/x86/coco/tdx/tdx-shared.o
  CC      arch/x86/realmode/rm/video-mode.o
  CC      arch/x86/pci/init.o
  AS      arch/x86/lib/copy_user_uncached_64.o
  CC      arch/x86/platform/efi/efi_64.o
  CC      crypto/asymmetric_keys/restrict.o
  AS [M]  arch/x86/crypto/aesni-intel_asm.o
  CC      fs/iomap/iter.o
  CC      security/keys/trusted-keys/trusted_tpm1.o
  CC      kernel/sched/build_utility.o
  AS      arch/x86/realmode/rm/copy.o
  CC [M]  arch/x86/crypto/aesni-intel_glue.o
  CC      fs/quota/netlink.o
  POLICY  security/tomoyo/builtin-policy.h
  AS      arch/x86/realmode/rm/bioscall.o
  CC      security/tomoyo/condition.o
  CC      fs/notify/inotify/inotify_user.o
  CC      fs/crypto/hkdf.o
  CC      arch/x86/realmode/rm/regs.o
  AR      arch/x86/video/built-in.a
  CC      arch/x86/xen/mmu.o
  CC      arch/x86/realmode/rm/video-vga.o
  CC      arch/x86/events/amd/lbr.o
  AS      arch/x86/coco/tdx/tdcall.o
  CC      arch/x86/events/amd/brs.o
  CC [M]  lib/kunit/resource.o
  CC      kernel/locking/mutex.o
  AS      arch/x86/power/hibernate_asm_64.o
  AR      arch/x86/coco/tdx/built-in.a
  CC      arch/x86/coco/core.o
  CC      arch/x86/lib/cpu.o
  CC      arch/x86/realmode/rm/video-vesa.o
  CC      arch/x86/events/amd/ibs.o
  CC      block/partitions/amiga.o
  CC      kernel/power/qos.o
  CC      arch/x86/power/hibernate.o
  CC      security/selinux/hooks.o
  CC      arch/x86/realmode/rm/video-bios.o
  CC      fs/verity/init.o
  CC      arch/x86/kernel/cpu/mce/core.o
  CC      mm/kfence/report.o
  CC      crypto/asymmetric_keys/signature.o
  CC      arch/x86/kernel/cpu/mce/severity.o
  CC      arch/x86/pci/mmconfig_64.o
  CC      arch/x86/entry/vdso/vdso32-setup.o
  PASYMS  arch/x86/realmode/rm/pasyms.h
  LDS     arch/x86/realmode/rm/realmode.lds
  LD      arch/x86/realmode/rm/realmode.elf
  CC      ipc/msgutil.o
  GEN     certs/blacklist_hash_list
  RELOCS  arch/x86/realmode/rm/realmode.relocs
  CERT    certs/x509_revocation_list
  OBJCOPY arch/x86/realmode/rm/realmode.bin
  CERT    certs/x509_certificate_list
  AR      arch/x86/coco/built-in.a
  GENKEY  certs/signing_key.pem
Generating a RSA private key
..  AS      arch/x86/realmode/rmpiggy.o
..  CC      certs/blacklist_hashes.o
.++++
..........  CC      fs/iomap/buffered-io.o
..  AR      arch/x86/realmode/built-in.a
..  CC      mm/filemap.o
  AR      net/ethernet/built-in.a
...  CC      fs/iomap/direct-io.o
....  CC [M]  lib/kunit/static_stub.o
...  CC      security/selinux/selinuxfs.o
++++
writing new private key to 'certs/signing_key.pem'
-----
  AS      certs/revocation_certificates.o
  AR      drivers/phy/built-in.a
  CC      fs/crypto/hooks.o
  CC      arch/x86/mm/pat/memtype.o
  AR      drivers/pinctrl/actions/built-in.a
  CERT    certs/signing_key.x509
  AS      certs/system_certificates.o
  AR      drivers/pinctrl/bcm/built-in.a
  CC      init/do_mounts_initrd.o
  AR      drivers/pinctrl/cirrus/built-in.a
  AS [M]  arch/x86/crypto/aesni-intel_avx-x86_64.o
  CC      init/initramfs.o
  AR      certs/built-in.a
  AR      drivers/pinctrl/freescale/built-in.a
  AR      arch/x86/net/built-in.a
  LDS     arch/x86/entry/vdso/vdso.lds
  CC      arch/x86/purgatory/purgatory.o
  CC      drivers/pinctrl/intel/pinctrl-baytrail.o
  AS      arch/x86/entry/vdso/vdso-note.o
  CC      security/smack/smack_access.o
  CC      security/smack/smackfs.o
  CC      fs/verity/measure.o
  AS      arch/x86/purgatory/stack.o
  CC      fs/kernfs/mount.o
  CC      arch/x86/entry/vdso/vclock_gettime.o
  AS      arch/x86/purgatory/setup-x86_64.o
  AS      arch/x86/platform/efi/efi_stub_64.o
  AR      fs/quota/built-in.a
  AR      fs/notify/inotify/built-in.a
  AS      arch/x86/lib/csum-copy_64.o
  CC      arch/x86/pci/direct.o
  CC      arch/x86/purgatory/sha256.o
  CC      block/partitions/atari.o
  CC [M]  sound/core/seq/seq_memory.o
  CC      fs/notify/fanotify/fanotify.o
  CC      fs/proc/inode.o
  CC      fs/kernfs/inode.o
  AR      arch/x86/power/built-in.a
  AS      arch/x86/platform/efi/efi_thunk_64.o
  CC      arch/x86/platform/efi/runtime-map.o
  CC      arch/x86/lib/csum-partial_64.o
  CC      arch/x86/lib/csum-wrappers_64.o
  CC      ipc/msg.o
  AS [M]  arch/x86/crypto/aes_ctrby8_avx-x86_64.o
  CC      fs/notify/fsnotify.o
  AR      mm/kfence/built-in.a
  CC      kernel/power/main.o
  CC      mm/mempool.o
  CC      security/keys/trusted-keys/trusted_tpm2.o
  CC      mm/oom_kill.o
  CC      crypto/asymmetric_keys/public_key.o
  CC      arch/x86/xen/time.o
  CC      fs/proc/root.o
  AS [M]  arch/x86/crypto/sha1_avx2_x86_64_asm.o
  CC      arch/x86/kernel/fpu/regset.o
  CC      security/tomoyo/domain.o
  AS [M]  arch/x86/crypto/sha1_ssse3_asm.o
  CC      kernel/printk/printk.o
  CC [M]  arch/x86/crypto/sha1_ssse3_glue.o
  CC      arch/x86/entry/vdso/vgetcpu.o
  AS      arch/x86/entry/vdso/vsgx.o
  HOSTCC  arch/x86/entry/vdso/vdso2c
  AS [M]  arch/x86/crypto/sha1_ni_asm.o
  CC [M]  lib/kunit/string-stream.o
  AS      arch/x86/purgatory/entry64.o
  CC      arch/x86/lib/delay.o
  CC      arch/x86/events/amd/iommu.o
  CC      arch/x86/mm/pat/memtype_interval.o
  CC      arch/x86/kernel/cpu/mce/genpool.o
  CC [M]  arch/x86/kvm/../../../virt/kvm/kvm_main.o
  CC      arch/x86/purgatory/string.o
  CC      arch/x86/pci/mmconfig-shared.o
  CC      fs/kernfs/dir.o
  LD      arch/x86/purgatory/purgatory.ro
  LD      arch/x86/purgatory/purgatory.chk
  CC      net/core/request_sock.o
  AS      arch/x86/purgatory/kexec-purgatory.o
  CC      drivers/pinctrl/intel/pinctrl-cherryview.o
  CC      fs/crypto/keyring.o
  CC      block/partitions/aix.o
  LDS     arch/x86/entry/vdso/vdso32/vdso32.lds
  ASN.1   crypto/asymmetric_keys/x509.asn1.[ch]
  AR      arch/x86/purgatory/built-in.a
  AR      arch/x86/platform/efi/built-in.a
  AS      arch/x86/entry/vdso/vdso32/note.o
  CC      ipc/sem.o
  CC      security/smack/smack_netfilter.o
  AR      arch/x86/platform/geode/built-in.a
  CC      fs/proc/base.o
  CC      fs/notify/fanotify/fanotify_user.o
  AS      arch/x86/entry/vdso/vdso32/system_call.o
  AR      arch/x86/platform/iris/built-in.a
  CC      arch/x86/platform/intel/iosf_mbi.o
  CC      arch/x86/kernel/fpu/signal.o
  CC      arch/x86/lib/error-inject.o
  CC      drivers/gpio/gpiolib.o
  AS      arch/x86/entry/vdso/vdso32/sigreturn.o
  CC      init/calibrate.o
  CC      security/keys/trusted-keys/tpm2key.asn1.o
  CC [M]  sound/core/seq/seq_queue.o
  CC      arch/x86/xen/grant-table.o
  CC      init/init_task.o
  AS [M]  arch/x86/crypto/sha256-ssse3-asm.o
  CC      fs/verity/open.o
  CC      arch/x86/entry/vdso/vdso32/vclock_gettime.o
  CC [M]  lib/kunit/assert.o
  AR      security/keys/trusted-keys/built-in.a
  CC      kernel/locking/semaphore.o
  CC      security/keys/encrypted-keys/encrypted.o
  AS [M]  arch/x86/crypto/sha256-avx-asm.o
  CC      security/selinux/netlink.o
  ASN.1   crypto/asymmetric_keys/x509_akid.asn1.[ch]
  CC      crypto/asymmetric_keys/x509_loader.o
  AR      arch/x86/mm/pat/built-in.a
  CC      ipc/shm.o
  CC      fs/proc/generic.o
  AS [M]  arch/x86/crypto/sha256-avx2-asm.o
  CC      arch/x86/mm/init.o
  CC      security/selinux/nlmsgtab.o
  CC      io_uring/xattr.o
  CC [M]  arch/x86/crypto/sha256_ssse3_glue.o
  AR      arch/x86/events/amd/built-in.a
  CC      arch/x86/events/intel/core.o
  CC      security/selinux/netif.o
  CC      arch/x86/kernel/cpu/mce/intel.o
  CC      arch/x86/events/intel/bts.o
  CC      arch/x86/xen/suspend.o
  CC      crypto/asymmetric_keys/x509_public_key.o
  CC      security/tomoyo/environ.o
  CC      arch/x86/pci/xen.o
  CC      kernel/power/console.o
  CC      block/partitions/cmdline.o
  CC      kernel/power/process.o
  CC      arch/x86/entry/vdso/vdso32/vgetcpu.o
  AS      arch/x86/lib/getuser.o
  CC      net/core/skbuff.o
  CC      drivers/pinctrl/intel/pinctrl-intel.o
  CC [M]  sound/core/seq/seq_fifo.o
  VDSO    arch/x86/entry/vdso/vdso64.so.dbg
  CC      arch/x86/kernel/fpu/xstate.o
  CC      fs/iomap/fiemap.o
  CC      init/version.o
  CC      security/selinux/netnode.o
  VDSO    arch/x86/entry/vdso/vdso32.so.dbg
  CC      fs/verity/read_metadata.o
  OBJCOPY arch/x86/entry/vdso/vdso64.so
  OBJCOPY arch/x86/entry/vdso/vdso32.so
  VDSO2C  arch/x86/entry/vdso/vdso-image-64.c
  VDSO2C  arch/x86/entry/vdso/vdso-image-32.c
  CC [M]  lib/kunit/try-catch.o
  CC      arch/x86/entry/vdso/vdso-image-64.o
  GEN     arch/x86/lib/inat-tables.c
  CC      fs/kernfs/file.o
  AS [M]  arch/x86/crypto/sha256_ni_asm.o
  AR      security/smack/built-in.a
  AR      arch/x86/platform/intel/built-in.a
  CC      security/selinux/netport.o
  CC      io_uring/nop.o
  CC      arch/x86/lib/insn-eval.o
  CC      security/selinux/status.o
  CC      arch/x86/kernel/cpu/mce/amd.o
  CC      fs/crypto/keysetup.o
  AR      arch/x86/platform/intel-mid/built-in.a
  AS [M]  arch/x86/crypto/sha512-ssse3-asm.o
  CC      fs/crypto/keysetup_v1.o
  AS [M]  arch/x86/crypto/sha512-avx-asm.o
  AR      arch/x86/platform/intel-quark/built-in.a
  ASN.1   crypto/asymmetric_keys/pkcs7.asn1.[ch]
  CC      crypto/asymmetric_keys/pkcs7_trust.o
  AR      arch/x86/platform/olpc/built-in.a
  CC      fs/kernfs/symlink.o
  AR      fs/notify/fanotify/built-in.a
  AR      arch/x86/platform/scx200/built-in.a
  CC      fs/notify/notification.o
  AS [M]  arch/x86/crypto/sha512-avx2-asm.o
  AR      init/built-in.a
  AR      arch/x86/platform/ts5500/built-in.a
  CC      arch/x86/platform/uv/bios_uv.o
  CC      arch/x86/xen/enlighten_hvm.o
  CC      arch/x86/xen/mmu_hvm.o
  CC [M]  arch/x86/crypto/sha512_ssse3_glue.o
  CC      security/keys/encrypted-keys/ecryptfs_format.o
  CC      arch/x86/entry/vdso/vdso-image-32.o
  CC      arch/x86/platform/uv/uv_irq.o
  CC      kernel/locking/rwsem.o
  CC      mm/fadvise.o
  CC      security/keys/encrypted-keys/masterkey_trusted.o
  CC      block/partitions/mac.o
  CC [M]  sound/core/seq/seq_prioq.o
  CC      arch/x86/platform/uv/uv_time.o
  CC      kernel/power/suspend.o
  AR      arch/x86/entry/vdso/built-in.a
  CC      security/tomoyo/file.o
  CC      arch/x86/pci/fixup.o
  CC      arch/x86/entry/vsyscall/vsyscall_64.o
  AS      arch/x86/entry/entry.o
  CC      kernel/printk/printk_safe.o
  AS      arch/x86/entry/vsyscall/vsyscall_emu_64.o
  CC      ipc/syscall.o
  CC      crypto/asymmetric_keys/pkcs7_verify.o
  CC      security/tomoyo/gc.o
  CC [M]  lib/kunit/executor.o
  CC      security/tomoyo/group.o
  CC [M]  lib/kunit/attributes.o
  CC      arch/x86/mm/init_64.o
  CC      io_uring/fs.o
  CC      io_uring/splice.o
  CC      fs/iomap/seek.o
  CC      arch/x86/lib/insn.o
  CC      fs/proc/array.o
  CC [M]  drivers/pinctrl/intel/pinctrl-alderlake.o
  AS [M]  arch/x86/crypto/ghash-clmulni-intel_asm.o
  CC      io_uring/sync.o
  CC      arch/x86/platform/uv/uv_nmi.o
  CC      fs/crypto/policy.o
  AR      security/keys/encrypted-keys/built-in.a
  CC [M]  arch/x86/crypto/ghash-clmulni-intel_glue.o
  CC [M]  sound/core/seq/seq_timer.o
  CC      security/keys/gc.o
  CC      fs/verity/verify.o
  CC      fs/verity/signature.o
  CC      fs/notify/group.o
  CC      security/selinux/ss/ebitmap.o
  CC      block/partitions/ldm.o
  CC      kernel/locking/percpu-rwsem.o
  AR      fs/kernfs/built-in.a
  CC      crypto/asymmetric_keys/verify_pefile.o
  CC      mm/maccess.o
  CC      security/apparmor/apparmorfs.o
  AS      arch/x86/lib/memcpy_64.o
  CC      security/apparmor/audit.o
  CC      drivers/gpio/gpiolib-devres.o
  CC      ipc/ipc_sysctl.o
  CC      arch/x86/kernel/cpu/mce/threshold.o
  CC [M]  lib/kunit/device.o
  CC      security/yama/yama_lsm.o
  AR      arch/x86/entry/vsyscall/built-in.a
  CC      arch/x86/pci/acpi.o
  CC      kernel/printk/nbcon.o
  CC [M]  arch/x86/kvm/../../../virt/kvm/eventfd.o
  AS      arch/x86/entry/entry_64.o
  CC      arch/x86/kernel/cpu/mce/apei.o
  CC [M]  drivers/pinctrl/intel/pinctrl-meteorlake.o
  AR      arch/x86/kernel/fpu/built-in.a
  CC      arch/x86/pci/legacy.o
  CC      kernel/irq/irqdesc.o
  AS      arch/x86/lib/memmove_64.o
  CC      kernel/rcu/update.o
  CC      kernel/rcu/sync.o
  CC      io_uring/advise.o
  CC      kernel/rcu/srcutree.o
  CC      security/keys/key.o
  AS [M]  arch/x86/crypto/polyval-clmulni_asm.o
  CC [M]  sound/core/seq/seq_system.o
  ASN.1   crypto/asymmetric_keys/mscode.asn1.[ch]
  CC      io_uring/filetable.o
  CC      arch/x86/events/intel/ds.o
  CC [M]  arch/x86/crypto/polyval-clmulni_glue.o
  CC      security/tomoyo/load_policy.o
  CC      kernel/locking/irqflag-debug.o
  CC      fs/iomap/swapfile.o
  CC      arch/x86/xen/suspend_hvm.o
  CC      ipc/mqueue.o
  CC      crypto/asymmetric_keys/x509.asn1.o
  CC      arch/x86/entry/syscall_64.o
  CC      arch/x86/events/zhaoxin/core.o
  CC      io_uring/openclose.o
  CC      crypto/asymmetric_keys/x509_akid.asn1.o
  CC      crypto/asymmetric_keys/x509_cert_parser.o
  CC      kernel/power/hibernate.o
  AS      arch/x86/lib/memset_64.o
  CC      mm/page-writeback.o
  AR      arch/x86/platform/uv/built-in.a
  CC [M]  sound/core/seq/seq_ports.o
  CC      fs/proc/fd.o
  AR      arch/x86/platform/built-in.a
  CC      io_uring/uring_cmd.o
  CC      kernel/locking/mutex-debug.o
  CC [M]  drivers/pinctrl/intel/pinctrl-tigerlake.o
  CC      kernel/printk/printk_ringbuffer.o
  AR      fs/verity/built-in.a
  CC      fs/crypto/bio.o
  CC      io_uring/epoll.o
  CC      security/selinux/ss/hashtab.o
  CC      fs/crypto/inline_crypt.o
  CC      drivers/gpio/gpiolib-legacy.o
  CC      arch/x86/lib/misc.o
  CC      fs/notify/mark.o
  CC      block/partitions/msdos.o
  AR      security/yama/built-in.a
  CC      arch/x86/events/intel/knc.o
  CC      fs/notify/fdinfo.o
  AS [M]  arch/x86/crypto/crc32-pclmul_asm.o
  CC [M]  lib/kunit/debugfs.o
  CC      arch/x86/events/core.o
  CC      drivers/gpio/gpiolib-cdev.o
  CC      arch/x86/events/intel/lbr.o
  CC      arch/x86/lib/pc-conf-reg.o
  CC [M]  arch/x86/crypto/crc32-pclmul_glue.o
  CC      arch/x86/events/intel/p4.o
  CC      arch/x86/xen/platform-pci-unplug.o
  CC      arch/x86/kernel/cpu/mce/dev-mcelog.o
  CC [M]  arch/x86/kvm/../../../virt/kvm/binary_stats.o
  CC      arch/x86/pci/irq.o
  CC      arch/x86/xen/setup.o
  CC      arch/x86/entry/common.o
  AS      arch/x86/lib/putuser.o
  CC      security/selinux/ss/symtab.o
  AR      arch/x86/events/zhaoxin/built-in.a
  CC      crypto/asymmetric_keys/pkcs7.asn1.o
  AS      arch/x86/lib/retpoline.o
  CC      crypto/asymmetric_keys/pkcs7_parser.o
  CC      security/tomoyo/memory.o
  CC      crypto/asymmetric_keys/mscode_parser.o
  CC      kernel/irq/handle.o
  AR      drivers/pinctrl/intel/built-in.a
  CC      kernel/printk/sysctl.o
  AR      drivers/pinctrl/mediatek/built-in.a
  AR      drivers/pinctrl/mvebu/built-in.a
  CC      fs/proc/proc_tty.o
  AR      lib/kunit/built-in.a
  CC      arch/x86/lib/usercopy.o
  LD [M]  lib/kunit/kunit.o
  AR      drivers/pinctrl/nuvoton/built-in.a
  AR      drivers/pinctrl/nomadik/built-in.a
  CC      security/keys/keyring.o
  CC      security/selinux/ss/sidtab.o
  CC      arch/x86/mm/fault.o
  AR      fs/iomap/built-in.a
  AS [M]  arch/x86/crypto/crct10dif-pcl-asm_64.o
  CC      security/keys/keyctl.o
  CC      lib/math/div64.o
  CC      io_uring/statx.o
  CC      fs/proc/cmdline.o
  CC      crypto/asymmetric_keys/mscode.asn1.o
  AR      drivers/pinctrl/nxp/built-in.a
  CC      kernel/locking/lockdep.o
  CC      kernel/irq/manage.o
  CC      lib/math/gcd.o
  CC      drivers/gpio/gpiolib-sysfs.o
  AR      drivers/pinctrl/qcom/built-in.a
  CC      arch/x86/xen/apic.o
  CC [M]  arch/x86/crypto/crct10dif-pclmul_glue.o
  CC      lib/crypto/mpi/generic_mpih-lshift.o
  CC      lib/crypto/mpi/generic_mpih-mul1.o
  AR      drivers/pinctrl/sprd/built-in.a
  AR      kernel/printk/built-in.a
  CC      ipc/namespace.o
  CC      lib/math/lcm.o
  CC      block/bio.o
  AR      drivers/pinctrl/sunplus/built-in.a
  CC      block/elevator.o
  CC [M]  sound/core/seq/seq_info.o
  CC [M]  arch/x86/kvm/../../../virt/kvm/vfio.o
  AR      drivers/pinctrl/ti/built-in.a
  CC      drivers/pinctrl/core.o
  CC      io_uring/net.o
  CC      lib/math/int_log.o
  CC      kernel/irq/spurious.o
  CC      block/partitions/osf.o
  LD [M]  arch/x86/crypto/aesni-intel.o
  CC      kernel/irq/resend.o
  CC      security/tomoyo/mount.o
  AR      kernel/sched/built-in.a
  AR      fs/crypto/built-in.a
  CC      arch/x86/kernel/cpu/mtrr/mtrr.o
  CC      arch/x86/kernel/cpu/microcode/core.o
  CC      kernel/power/snapshot.o
  CC      arch/x86/kernel/cpu/resctrl/core.o
  CC      arch/x86/lib/usercopy_64.o
  AS      arch/x86/entry/thunk_64.o
  AR      arch/x86/kernel/cpu/mce/built-in.a
  CC      lib/math/int_pow.o
  CC      fs/proc/consoles.o
  CC      kernel/power/swap.o
  AR      fs/notify/built-in.a
  CC      arch/x86/kernel/cpu/microcode/intel.o
  CC [M]  crypto/async_tx/async_tx.o
  CC      lib/math/int_sqrt.o
  CC      lib/math/reciprocal_div.o
  GEN     security/apparmor/capability_names.h
  LD [M]  arch/x86/crypto/sha1-ssse3.o
  LD [M]  arch/x86/crypto/sha256-ssse3.o
  CC      security/apparmor/task.o
  LD [M]  arch/x86/crypto/sha512-ssse3.o
  CC      arch/x86/pci/numachip.o
  CC      lib/crypto/mpi/generic_mpih-mul2.o
  CC      arch/x86/pci/common.o
  CC      kernel/rcu/tree.o
  LD [M]  arch/x86/crypto/ghash-clmulni-intel.o
  CC      ipc/mq_sysctl.o
  AR      crypto/asymmetric_keys/built-in.a
  LD [M]  arch/x86/crypto/polyval-clmulni.o
  LD [M]  arch/x86/crypto/crc32-pclmul.o
  LD [M]  sound/core/seq/snd-seq.o
  CC      kernel/rcu/rcu_segcblist.o
  LD [M]  arch/x86/crypto/crct10dif-pclmul.o
  CC [M]  arch/x86/kvm/../../../virt/kvm/coalesced_mmio.o
  AR      arch/x86/crypto/built-in.a
  CC [M]  sound/core/sound.o
  CC      io_uring/msg_ring.o
  CC      lib/math/rational.o
  CC      lib/crypto/mpi/generic_mpih-mul3.o
  CC      io_uring/timeout.o
  CC      io_uring/sqpoll.o
  CC      drivers/gpio/gpiolib-acpi.o
  CC      io_uring/fdinfo.o
  CC      arch/x86/events/intel/p6.o
  AS      arch/x86/entry/entry_64_compat.o
  CC      arch/x86/entry/syscall_32.o
  CC      io_uring/tctx.o
  CC      kernel/irq/chip.o
  CC [M]  sound/pci/hda/hda_bind.o
  CC      arch/x86/kernel/cpu/resctrl/rdtgroup.o
  CC      fs/proc/cpuinfo.o
  CC      security/keys/permission.o
  CC      block/partitions/sgi.o
  AR      ipc/built-in.a
  CC      crypto/api.o
  CC      security/keys/process_keys.o
  CC      security/selinux/ss/avtab.o
  CC      arch/x86/kernel/cpu/sgx/driver.o
  CC      arch/x86/mm/ioremap.o
  CC      drivers/pinctrl/pinctrl-utils.o
  CC      kernel/power/user.o
  CC      arch/x86/kernel/cpu/sgx/encl.o
  CC      security/tomoyo/network.o
  CC      lib/crypto/mpi/generic_mpih-rshift.o
  CC      security/apparmor/ipc.o
  CC      arch/x86/lib/msr-smp.o
  CC      security/apparmor/lib.o
  CC      arch/x86/pci/early.o
  CC      mm/folio-compat.o
  CC      arch/x86/kernel/cpu/mtrr/if.o
  CC      lib/crypto/mpi/generic_mpih-sub1.o
  CC [M]  arch/x86/kvm/../../../virt/kvm/async_pf.o
  CC      arch/x86/events/intel/pt.o
  AR      arch/x86/entry/built-in.a
  CC      security/tomoyo/realpath.o
  CC [M]  crypto/async_tx/async_memcpy.o
  CC      fs/proc/devices.o
  CC [M]  lib/math/prime_numbers.o
  CC      arch/x86/kernel/cpu/microcode/amd.o
  CC [M]  sound/core/init.o
  CC      fs/proc/interrupts.o
  CC [M]  arch/x86/kvm/../../../virt/kvm/irqchip.o
  CC      block/partitions/sun.o
  CC      lib/crypto/mpi/generic_mpih-add1.o
  CC      security/tomoyo/securityfs_if.o
  CC      security/tomoyo/tomoyo.o
  CC      arch/x86/mm/extable.o
  CC      crypto/cipher.o
  CC      arch/x86/lib/cache-smp.o
  CC [M]  sound/core/memory.o
  CC [M]  arch/x86/kvm/../../../virt/kvm/dirty_ring.o
  CC      io_uring/poll.o
  CC      net/core/datagram.o
  CC      fs/proc/loadavg.o
  CC      security/selinux/ss/policydb.o
  CC      kernel/locking/lockdep_proc.o
  CC      kernel/locking/spinlock.o
  CC      drivers/gpio/gpiolib-swnode.o
  CC      kernel/power/wakelock.o
  CC [M]  sound/pci/hda/hda_codec.o
  CC      kernel/locking/osq_lock.o
  CC      security/keys/request_key.o
  CC      arch/x86/kernel/cpu/mtrr/generic.o
  CC      arch/x86/pci/bus_numa.o
  CC      arch/x86/lib/msr.o
  CC      drivers/pinctrl/pinmux.o
  CC      security/apparmor/match.o
  AS      arch/x86/lib/msr-reg.o
  CC      kernel/irq/dummychip.o
  CC      lib/crypto/mpi/ec.o
  CC      arch/x86/kernel/cpu/mtrr/cleanup.o
  CC      security/selinux/ss/services.o
  CC      kernel/livepatch/core.o
  CC [M]  arch/x86/kvm/../../../virt/kvm/pfncache.o
  CC      arch/x86/mm/mmap.o
  CC      arch/x86/mm/pgtable.o
  CC      arch/x86/events/probe.o
  CC      block/partitions/ultrix.o
  CC      fs/proc/meminfo.o
  CC      arch/x86/kernel/acpi/boot.o
  CC      block/blk-core.o
  CC      arch/x86/kernel/apic/apic.o
  CC [M]  crypto/async_tx/async_xor.o
  AR      arch/x86/kernel/cpu/microcode/built-in.a
  CC      arch/x86/kernel/cpu/sgx/ioctl.o
  AR      lib/math/built-in.a
  CC      arch/x86/kernel/apic/apic_common.o
  CC      arch/x86/kernel/apic/apic_noop.o
  CC      kernel/power/poweroff.o
  CC [M]  arch/x86/kvm/x86.o
  CC      kernel/locking/qspinlock.o
  CC      drivers/gpio/gpio-mmio.o
  CC      kernel/locking/rtmutex_api.o
  CC      security/apparmor/path.o
  CC      security/tomoyo/util.o
  CC      fs/proc/stat.o
  CC      arch/x86/events/intel/uncore.o
  CC      arch/x86/kernel/cpu/resctrl/monitor.o
  CC      kernel/locking/spinlock_debug.o
  CC      arch/x86/pci/amd_bus.o
  CC      mm/readahead.o
  CC      arch/x86/events/utils.o
  CC      io_uring/cancel.o
  CC      io_uring/kbuf.o
  CC      kernel/power/energy_model.o
  CC [M]  sound/core/control.o
  CC      drivers/pinctrl/pinconf.o
  CC      arch/x86/lib/msr-reg-export.o
  CC      arch/x86/kernel/apic/ipi.o
  CC      arch/x86/kernel/apic/vector.o
  CC      arch/x86/mm/physaddr.o
  CC      block/blk-sysfs.o
  CC [M]  arch/x86/kvm/emulate.o
  CC      kernel/irq/devres.o
  AS      arch/x86/lib/hweight.o
  CC      block/partitions/efi.o
  CC [M]  arch/x86/kvm/i8259.o
  CC [M]  arch/x86/kvm/irq.o
  CC      fs/proc/uptime.o
  CC      drivers/gpio/gpio-crystalcove.o
  CC      arch/x86/kernel/acpi/sleep.o
  CC      security/keys/request_key_auth.o
  CC      arch/x86/mm/tlb.o
  AR      arch/x86/pci/built-in.a
  CC      arch/x86/kernel/apic/init.o
  CC      arch/x86/lib/iomem.o
  CC      arch/x86/mm/cpu_entry_area.o
  AR      arch/x86/kernel/cpu/mtrr/built-in.a
  CC      arch/x86/kernel/cpu/resctrl/ctrlmondata.o
  CC      arch/x86/mm/maccess.o
  CC      lib/crypto/mpi/mpicoder.o
  CC      drivers/pinctrl/pinconf-generic.o
  CC      arch/x86/mm/pgprot.o
  CC [M]  crypto/async_tx/async_pq.o
  CC      mm/swap.o
  CC      arch/x86/kernel/apic/hw_nmi.o
  CC      arch/x86/kernel/cpu/sgx/main.o
  CC      security/apparmor/domain.o
  CC [M]  arch/x86/kvm/lapic.o
  CC      io_uring/rsrc.o
  CC      kernel/livepatch/patch.o
  CC      drivers/pinctrl/pinctrl-amd.o
  CC      fs/proc/util.o
  CC      security/tomoyo/common.o
  CC      io_uring/rw.o
  CC      drivers/pwm/core.o
  CC      drivers/pwm/sysfs.o
  AR      kernel/power/built-in.a
  CC      arch/x86/kernel/cpu/cacheinfo.o
  CC      drivers/gpio/gpio-palmas.o
  CC      arch/x86/kernel/kprobes/core.o
  CC      arch/x86/events/intel/uncore_nhmex.o
  CC      security/keys/user_defined.o
  CC      kernel/irq/autoprobe.o
  CC      arch/x86/mm/hugetlbpage.o
  CC      arch/x86/events/intel/uncore_snb.o
  CC      net/core/stream.o
  CC      kernel/locking/qrwlock.o
  CC      net/core/scm.o
  AS      arch/x86/kernel/acpi/wakeup_64.o
  CC      block/partitions/karma.o
  CC      arch/x86/kernel/acpi/apei.o
  AS      arch/x86/lib/iomap_copy_64.o
  CC [M]  sound/pci/hda/hda_jack.o
  CC      fs/proc/version.o
  CC      block/blk-flush.o
  CC      drivers/pinctrl/pinctrl-sx150x.o
  CC      mm/truncate.o
  CC      arch/x86/kernel/cpu/resctrl/pseudo_lock.o
  CC      arch/x86/lib/inat.o
  CC      drivers/pci/msi/pcidev_msi.o
  CC      kernel/livepatch/shadow.o
  CC      kernel/dma/mapping.o
  CC      kernel/entry/common.o
  AR      arch/x86/lib/built-in.a
  CC      kernel/dma/direct.o
  AR      arch/x86/lib/lib.a
  CC      kernel/entry/syscall_user_dispatch.o
  CC      block/partitions/sysv68.o
  CC      drivers/gpio/gpio-rc5t583.o
  CC [M]  sound/core/misc.o
  CC      arch/x86/kernel/apic/io_apic.o
  CC      arch/x86/kernel/apic/msi.o
  CC      lib/crypto/mpi/mpi-add.o
  CC      fs/proc/softirqs.o
  CC      arch/x86/mm/dump_pagetables.o
  CC      security/selinux/ss/conditional.o
  CC      arch/x86/kernel/acpi/cppc.o
  CC [M]  crypto/async_tx/async_raid6_recov.o
  CC      arch/x86/kernel/acpi/cstate.o
  CC      arch/x86/mm/kmmio.o
  CC      kernel/irq/irqdomain.o
  CC [M]  sound/core/device.o
  CC      arch/x86/kernel/kprobes/opt.o
  CC      drivers/pci/msi/api.o
  CC      arch/x86/kernel/kprobes/ftrace.o
  CC      security/keys/compat.o
  CC      arch/x86/events/intel/uncore_snbep.o
  AR      kernel/locking/built-in.a
  AR      drivers/rapidio/switches/built-in.a
  CC      crypto/compress.o
  AR      drivers/rapidio/devices/built-in.a
  CC      drivers/rapidio/rio.o
  CC      drivers/video/console/dummycon.o
  CC      arch/x86/kernel/cpu/scattered.o
  CC      drivers/rapidio/rio-access.o
  CC      drivers/gpio/gpio-tps6586x.o
  AR      kernel/rcu/built-in.a
  CC      arch/x86/kernel/apic/apic_numachip.o
  CC      kernel/dma/ops_helpers.o
  AR      drivers/pinctrl/built-in.a
  CC      arch/x86/kernel/cpu/sgx/virt.o
  CC      io_uring/opdef.o
  AR      block/partitions/built-in.a
  CC      kernel/dma/dummy.o
  CC      drivers/pwm/pwm-crc.o
  CC      fs/proc/namespaces.o
  CC      drivers/idle/intel_idle.o
  AR      arch/x86/kernel/cpu/resctrl/built-in.a
  CC      arch/x86/kernel/apic/x2apic_uv_x.o
  CC      drivers/char/ipmi/ipmi_dmi.o
  CC      kernel/livepatch/state.o
  CC      kernel/entry/kvm.o
  CC      arch/x86/kernel/apic/x2apic_phys.o
  CC [M]  sound/pci/hda/hda_auto_parser.o
  CC      drivers/rapidio/rio-driver.o
  CC      block/blk-settings.o
  CC      arch/x86/kernel/cpu/topology.o
  CC      kernel/livepatch/transition.o
  CC      lib/crypto/memneq.o
  CC      net/core/gen_stats.o
  CC      security/keys/compat_dh.o
  CC      drivers/gpio/gpio-tps65910.o
  CC      lib/crypto/mpi/mpi-bit.o
  AR      arch/x86/kernel/kprobes/built-in.a
  CC      lib/crypto/mpi/mpi-cmp.o
  CC [M]  sound/core/info.o
  CC      lib/zlib_inflate/inffast.o
  CC      arch/x86/events/msr.o
  CC      arch/x86/events/intel/uncore_discovery.o
  AR      security/tomoyo/built-in.a
  AR      arch/x86/kernel/acpi/built-in.a
  CC      kernel/irq/proc.o
  CC      block/blk-ioc.o
  CC      kernel/irq/migration.o
  LDS     arch/x86/kernel/vmlinux.lds
  CC      kernel/irq/cpuhotplug.o
  CC [M]  sound/core/info_oss.o
  CC      drivers/pwm/pwm-lpss.o
  CC      arch/x86/mm/pf_in.o
  CC      kernel/dma/swiotlb.o
  CC      security/selinux/ss/mls.o
  CC      arch/x86/mm/mmio-mod.o
  CC      drivers/rapidio/rio-sysfs.o
  CC      lib/zlib_inflate/inflate.o
  CC      security/apparmor/policy.o
  CC      drivers/pci/msi/msi.o
  CC      drivers/video/console/vgacon.o
  CC      fs/proc/self.o
  CC      lib/crypto/utils.o
  CC      crypto/algapi.o
  CC      io_uring/notif.o
  CC      mm/vmscan.o
  CC      mm/shrinker.o
  CC      security/keys/proc.o
  CC      lib/crypto/mpi/mpi-sub-ui.o
  CC      drivers/char/ipmi/ipmi_plat_data.o
  CC      drivers/video/backlight/backlight.o
  CC      fs/sysfs/file.o
  AR      drivers/idle/built-in.a
  CC      fs/sysfs/dir.o
  CC [M]  arch/x86/events/rapl.o
  CC      fs/sysfs/symlink.o
  CC      arch/x86/kernel/cpu/common.o
  CC      fs/sysfs/mount.o
  CC [M]  drivers/char/ipmi/ipmi_msghandler.o
  AR      drivers/gpio/built-in.a
  CC      security/selinux/ss/context.o
  AR      arch/x86/kernel/cpu/sgx/built-in.a
  CC      security/selinux/xfrm.o
  CC      lib/zlib_inflate/infutil.o
  CC      kernel/irq/pm.o
  CC      drivers/pci/pcie/portdrv.o
  CC      drivers/pci/hotplug/pci_hotplug_core.o
  CC      drivers/pci/hotplug/cpci_hotplug_core.o
  CC      crypto/scatterwalk.o
  CC      lib/crypto/mpi/mpi-div.o
  CC      fs/proc/thread_self.o
  AR      drivers/rapidio/built-in.a
  CC      crypto/proc.o
  CC      crypto/aead.o
  AR      kernel/entry/built-in.a
  CC      lib/crypto/mpi/mpi-inv.o
  AR      drivers/pci/endpoint/functions/built-in.a
  CC      drivers/pci/controller/dwc/pcie-designware.o
  CC      drivers/pci/endpoint/pci-ep-cfs.o
  CC [M]  sound/pci/hda/hda_sysfs.o
  AR      kernel/livepatch/built-in.a
  CC [M]  arch/x86/events/intel/cstate.o
  CC      drivers/pci/controller/dwc/pcie-designware-host.o
  CC      drivers/pwm/pwm-lpss-pci.o
  CC      lib/zlib_inflate/inftrees.o
  CC      drivers/pci/controller/dwc/pcie-designware-ep.o
  CC [M]  sound/core/isadma.o
  CC      security/keys/sysctl.o
  CC      arch/x86/mm/numa.o
  CC      arch/x86/kernel/apic/x2apic_cluster.o
  CC      security/selinux/netlabel.o
  CC      kernel/dma/pool.o
  CC      net/core/gen_estimator.o
  CC      lib/zlib_inflate/inflate_syms.o
  CC      block/blk-map.o
  CC      io_uring/waitid.o
  CC      io_uring/register.o
  CC      drivers/pci/controller/dwc/pcie-designware-plat.o
  CC      fs/proc/proc_sysctl.o
  CC      drivers/video/fbdev/core/fb_notify.o
  CC      drivers/pci/msi/irqdomain.o
  CC      lib/crypto/mpi/mpi-mod.o
  AR      drivers/video/fbdev/omap/built-in.a
  AR      drivers/video/fbdev/omap2/omapfb/dss/built-in.a
  CC      mm/shmem.o
  CC      kernel/irq/msi.o
  AR      drivers/video/fbdev/omap2/omapfb/displays/built-in.a
  CC      drivers/pwm/pwm-lpss-platform.o
  AR      drivers/video/fbdev/omap2/omapfb/built-in.a
  AR      drivers/video/console/built-in.a
  CC      net/core/net_namespace.o
  CC      fs/sysfs/group.o
  AR      drivers/video/fbdev/omap2/built-in.a
  CC      security/selinux/ima.o
  CC      arch/x86/kernel/cpu/rdrand.o
  CC      drivers/video/fbdev/imsttfb.o
  CC      crypto/geniv.o
  CC [M]  sound/core/sound_oss.o
  CC      security/keys/persistent.o
  CC [M]  sound/core/vmaster.o
  AR      arch/x86/events/intel/built-in.a
  LD [M]  arch/x86/events/intel/intel-cstate.o
  CC [M]  sound/core/ctljack.o
  CC      crypto/lskcipher.o
  CC      mm/util.o
  AR      drivers/video/backlight/built-in.a
  CC [M]  sound/core/jack.o
  CC      kernel/dma/remap.o
  CC      arch/x86/kernel/apic/apic_flat_64.o
  AR      arch/x86/events/built-in.a
  CC      security/apparmor/policy_unpack.o
  CC      drivers/pci/pcie/rcec.o
  CC      arch/x86/kernel/apic/probe_64.o
  CC      arch/x86/xen/pmu.o
  CC      drivers/pci/hotplug/cpci_hotplug_pci.o
  CC      drivers/pci/hotplug/acpi_pcihp.o
  CC      arch/x86/xen/suspend_pv.o
  AR      drivers/pci/controller/mobiveil/built-in.a
  CC      lib/crypto/mpi/mpi-mul.o
  CC      drivers/pci/controller/vmd.o
  AR      lib/zlib_inflate/built-in.a
  CC      io_uring/io-wq.o
  CC      arch/x86/xen/p2m.o
  CC      arch/x86/xen/enlighten_pv.o
  AR      drivers/pwm/built-in.a
  CC      drivers/pci/endpoint/pci-epc-core.o
  CC      io_uring/futex.o
  CC [M]  sound/pci/hda/hda_controller.o
  CC      arch/x86/xen/mmu_pv.o
  CC      net/core/secure_seq.o
  CC      security/keys/dh.o
  CC [M]  sound/core/hwdep.o
  AR      security/selinux/built-in.a
  AR      drivers/pci/controller/dwc/built-in.a
  CC      lib/zlib_deflate/deflate.o
  CC      drivers/video/fbdev/core/fb_info.o
  CC      lib/zlib_deflate/deftree.o
  CC      security/safesetid/lsm.o
  AR      kernel/dma/built-in.a
  CC      lib/zlib_deflate/deflate_syms.o
  AR      drivers/pci/msi/built-in.a
  CC [M]  sound/pci/hda/hda_proc.o
  CC      arch/x86/mm/numa_64.o
  CC      arch/x86/mm/amdtopology.o
  AR      fs/sysfs/built-in.a
  CC      arch/x86/kernel/cpu/match.o
  CC      drivers/video/fbdev/asiliantfb.o
  CC      drivers/pci/pcie/aspm.o
  CC      arch/x86/kernel/cpu/bugs.o
  CC      arch/x86/xen/irq.o
  CC      arch/x86/xen/multicalls.o
  AS      arch/x86/xen/xen-asm.o
  CC      block/blk-merge.o
  CC      kernel/module/main.o
  CC      block/blk-timeout.o
  CC      block/blk-lib.o
  CC      drivers/video/fbdev/vesafb.o
  AR      arch/x86/kernel/apic/built-in.a
  CC      drivers/video/fbdev/efifb.o
  CC      fs/proc/proc_net.o
  CC      security/keys/keyctl_pkey.o
  CC      drivers/pci/hotplug/pciehp_core.o
  CC      crypto/skcipher.o
  CC      lib/crypto/mpi/mpih-cmp.o
  CC      kernel/irq/affinity.o
  AR      drivers/pci/controller/built-in.a
  CC      arch/x86/xen/enlighten_pvh.o
  CC      drivers/pci/hotplug/pciehp_ctrl.o
  CC      security/safesetid/securityfs.o
  CC      block/blk-mq.o
  CC [M]  drivers/char/ipmi/ipmi_devintf.o
  CC      drivers/video/fbdev/core/fbmem.o
  CC      block/blk-mq-tag.o
  CC      net/802/fc.o
  CC      arch/x86/mm/srat.o
  CC      mm/mmzone.o
  CC      block/blk-stat.o
  CC      net/802/fddi.o
  AR      lib/zlib_deflate/built-in.a
  CC      drivers/video/fbdev/core/fbcmap.o
  CC      drivers/pci/endpoint/pci-epf-core.o
  CC      net/sched/sch_generic.o
  CC [M]  sound/core/timer.o
  CC      net/core/flow_dissector.o
  CC      fs/proc/kcore.o
  AR      io_uring/built-in.a
  CC      fs/proc/vmcore.o
  CC      drivers/video/fbdev/core/modedb.o
  CC      drivers/video/fbdev/core/fbcvt.o
  CC      arch/x86/xen/trace.o
  CC      block/blk-mq-sysfs.o
  AR      security/keys/built-in.a
  CC [M]  arch/x86/kvm/i8254.o
  CC      lib/crypto/mpi/mpih-div.o
  CC      net/sched/sch_mq.o
  CC      kernel/irq/matrix.o
  CC      net/sched/sch_frag.o
  CC      security/apparmor/procattr.o
  CC      drivers/pci/hotplug/pciehp_pci.o
  CC      security/apparmor/lsm.o
  AR      security/safesetid/built-in.a
  GEN     security/apparmor/rlim_names.h
  CC      drivers/video/aperture.o
  CC [M]  sound/pci/hda/hda_hwdep.o
  CC      drivers/acpi/acpica/dsargs.o
  CC      drivers/acpi/numa/srat.o
  CC      drivers/video/fbdev/core/fb_cmdline.o
  CC      drivers/acpi/numa/hmat.o
  CC [M]  drivers/char/ipmi/ipmi_si_intf.o
  CC      drivers/pci/pcie/aer.o
  CC      arch/x86/mm/numa_emulation.o
  CC      arch/x86/kernel/cpu/aperfmperf.o
  CC [M]  net/802/p8022.o
  CC [M]  net/802/psnap.o
  CC      drivers/video/fbdev/core/fb_backlight.o
  CC      block/blk-mq-cpumap.o
  CC      arch/x86/mm/pkeys.o
  CC [M]  net/802/stp.o
  CC      drivers/video/fbdev/core/fbmon.o
  CC      drivers/acpi/acpica/dscontrol.o
  CC      crypto/seqiv.o
  CC      drivers/pci/hotplug/pciehp_hpc.o
  CC      lib/crypto/mpi/mpih-mul.o
  CC      crypto/ahash.o
  CC      drivers/pci/pcie/err.o
  CC [M]  sound/core/pcm.o
  CC      security/apparmor/secid.o
  CC      drivers/video/fbdev/core/fb_defio.o
  CC [M]  sound/pci/hda/hda_beep.o
  CC      drivers/pci/endpoint/pci-epc-mem.o
  CC      arch/x86/xen/smp.o
  CC      arch/x86/xen/smp_pv.o
  AR      kernel/irq/built-in.a
  CC [M]  sound/core/pcm_native.o
  CC [M]  arch/x86/kvm/ioapic.o
  CC      kernel/time/time.o
  CC      net/core/sysctl_net_core.o
  CC      drivers/acpi/acpica/dsdebug.o
  CC      kernel/time/timer.o
  CC      kernel/time/hrtimer.o
  CC      kernel/time/timekeeping.o
  CC      drivers/video/fbdev/core/fb_chrdev.o
  CC      fs/proc/kmsg.o
  CC      drivers/acpi/acpica/dsfield.o
  CC      arch/x86/mm/pti.o
  CC      crypto/shash.o
  CC      drivers/video/fbdev/core/fb_procfs.o
  CC      mm/vmstat.o
  CC [M]  drivers/char/ipmi/ipmi_kcs_sm.o
  CC      mm/backing-dev.o
  AR      drivers/acpi/numa/built-in.a
  CC      arch/x86/kernel/cpu/cpuid-deps.o
  CC      drivers/pci/hotplug/shpchp_core.o
  CC      drivers/pnp/pnpacpi/core.o
  CC      drivers/pnp/core.o
  CC      drivers/acpi/acpica/dsinit.o
  CC      net/sched/sch_api.o
  CC      block/blk-mq-sched.o
  CC      drivers/acpi/acpica/dsmethod.o
  CC      lib/crypto/mpi/mpi-pow.o
  CC      kernel/module/strict_rwx.o
  CC      net/core/dev.o
  CC      drivers/pci/hotplug/shpchp_ctrl.o
  CC      arch/x86/kernel/cpu/umwait.o
  CC      fs/proc/page.o
  AR      drivers/amba/built-in.a
  CC      drivers/pci/hotplug/shpchp_pci.o
  CC      arch/x86/xen/smp_hvm.o
  CC      drivers/pci/pcie/pme.o
  CC      lib/crypto/mpi/mpiutil.o
  AR      net/802/built-in.a
  CC      crypto/akcipher.o
  CC      drivers/pci/pcie/dpc.o
  CC      crypto/sig.o
  CC      security/apparmor/file.o
  CC      drivers/acpi/acpica/dsmthdat.o
  AR      drivers/pci/endpoint/built-in.a
  CC      drivers/acpi/acpica/dsobject.o
  CC      security/bpf/hooks.o
  CC      security/landlock/setup.o
  CC [M]  sound/pci/hda/hda_intel.o
  CC [M]  drivers/char/ipmi/ipmi_smic_sm.o
  CC      arch/x86/mm/mem_encrypt.o
  CC      security/integrity/ima/ima_fs.o
  CC [M]  arch/x86/kvm/irq_comm.o
  CC      kernel/module/kmod.o
  CC      security/integrity/ima/ima_queue.o
  CC [M]  arch/x86/kvm/cpuid.o
  CC      security/integrity/ima/ima_init.o
  CC      security/landlock/syscalls.o
  CC      drivers/video/fbdev/core/fbsysfs.o
  CC      kernel/futex/core.o
  CC      kernel/futex/syscalls.o
  CC      drivers/pnp/card.o
  CC      arch/x86/kernel/cpu/proc.o
  CC      mm/mm_init.o
  CC      mm/percpu.o
  CC      mm/slab_common.o
  CC      drivers/pci/hotplug/shpchp_sysfs.o
  CC      arch/x86/xen/spinlock.o
  MKCAP   arch/x86/kernel/cpu/capflags.c
  CC      drivers/acpi/acpica/dsopcode.o
  CC      drivers/pnp/pnpacpi/rsparser.o
  CC      drivers/pnp/driver.o
  CC      fs/proc/bootconfig.o
  CC      mm/compaction.o
  CC      security/integrity/evm/evm_main.o
  CC      drivers/pci/pcie/ptm.o
  CC      arch/x86/mm/mem_encrypt_amd.o
  CC      mm/show_mem.o
  AR      security/bpf/built-in.a
  CC      mm/shmem_quota.o
  CC      security/landlock/object.o
  CC [M]  drivers/char/ipmi/ipmi_bt_sm.o
  AR      lib/crypto/mpi/built-in.a
  CC      lib/crypto/chacha.o
  CC      security/integrity/evm/evm_crypto.o
  CC      drivers/pci/pcie/edr.o
  CC      fs/configfs/inode.o
  CC      fs/configfs/file.o
  CC      security/integrity/ima/ima_main.o
  CC      arch/x86/kernel/cpu/powerflags.o
  CC [M]  drivers/char/ipmi/ipmi_si_hotmod.o
  CC [M]  drivers/char/ipmi/ipmi_si_hardcode.o
  CC      drivers/acpi/acpica/dspkginit.o
  CC      crypto/kpp.o
  CC      crypto/dh.o
  CC      drivers/video/fbdev/core/fbcon.o
  CC      block/ioctl.o
  CC      lib/crypto/aes.o
  CC      lib/crypto/gf128mul.o
  CC      net/core/dev_addr_lists.o
  AR      fs/proc/built-in.a
  CC      security/landlock/ruleset.o
  CC      drivers/pci/hotplug/shpchp_hpc.o
  CC      drivers/pnp/resource.o
  CC      security/integrity/ima/ima_crypto.o
  CC      security/integrity/ima/ima_api.o
  CC      security/apparmor/policy_ns.o
  CC      net/sched/sch_blackhole.o
  CC      kernel/futex/pi.o
  CC      security/landlock/cred.o
  CC      net/sched/cls_api.o
  CC      kernel/module/livepatch.o
  AR      drivers/pnp/pnpacpi/built-in.a
  CC      kernel/time/ntp.o
  CC      kernel/time/clocksource.o
  CC      mm/interval_tree.o
  LD [M]  sound/pci/hda/snd-hda-codec.o
  CC      net/netlink/af_netlink.o
  CC      drivers/acpi/acpica/dsutils.o
  LD [M]  sound/pci/hda/snd-hda-intel.o
  CC      fs/devpts/inode.o
  CC      lib/lzo/lzo1x_compress.o
  CC      mm/list_lru.o
  CC      lib/lzo/lzo1x_decompress_safe.o
  CC      arch/x86/kernel/cpu/feat_ctl.o
  CC      fs/configfs/dir.o
  CC [M]  drivers/char/ipmi/ipmi_si_platform.o
  CC [M]  drivers/char/ipmi/ipmi_si_port_io.o
  AR      drivers/pci/pcie/built-in.a
  CC [M]  drivers/char/ipmi/ipmi_si_mem_io.o
  CC      kernel/time/jiffies.o
  CC      mm/workingset.o
  CC [M]  drivers/char/ipmi/ipmi_si_pci.o
  CC [M]  sound/core/pcm_lib.o
  CC      arch/x86/mm/mem_encrypt_identity.o
  CC      lib/crypto/blake2s.o
  CC      security/integrity/evm/evm_secfs.o
  CC      security/landlock/ptrace.o
  CC      kernel/module/tree_lookup.o
  CC      security/apparmor/label.o
  CC      drivers/acpi/acpica/dswexec.o
  CC      kernel/futex/requeue.o
  CC      security/integrity/iint.o
  CC      drivers/pci/hotplug/acpiphp_core.o
  CC      mm/debug.o
  CC      kernel/futex/waitwake.o
  CC      crypto/dh_helper.o
  CC [M]  arch/x86/kvm/pmu.o
  CC      block/genhd.o
  CC      drivers/video/fbdev/core/bitblit.o
  AR      drivers/clk/actions/built-in.a
  AR      drivers/clk/analogbits/built-in.a
  AR      fs/devpts/built-in.a
  CC      drivers/pnp/manager.o
  AR      drivers/clk/bcm/built-in.a
  CC      drivers/pnp/support.o
  CC      block/ioprio.o
  CC      kernel/time/timer_list.o
  CC      security/integrity/ima/ima_policy.o
  AR      drivers/clk/imgtec/built-in.a
  CC      fs/ext4/balloc.o
  CC      security/integrity/ima/ima_template.o
  AR      drivers/clk/imx/built-in.a
  CC      fs/ext4/bitmap.o
  AR      drivers/clk/ingenic/built-in.a
  CC      security/integrity/evm/evm_posix_acl.o
  AR      drivers/clk/mediatek/built-in.a
  CC [M]  drivers/char/ipmi/ipmi_ssif.o
  AS      arch/x86/mm/mem_encrypt_boot.o
  AR      drivers/clk/microchip/built-in.a
  CC      kernel/time/timeconv.o
  CC      block/badblocks.o
  CC      drivers/acpi/acpica/dswload.o
  AR      drivers/clk/mstar/built-in.a
  AR      lib/lzo/built-in.a
  CC      drivers/acpi/acpica/dswload2.o
  AR      arch/x86/mm/built-in.a
  AR      drivers/clk/mvebu/built-in.a
  CC      security/landlock/fs.o
  CC      net/bpf/test_run.o
  AR      drivers/clk/ralink/built-in.a
  CC      kernel/module/debug_kmemleak.o
  CC      mm/gup.o
  CC [M]  sound/core/pcm_misc.o
  CC [M]  sound/core/pcm_memory.o
  AR      drivers/clk/renesas/built-in.a
  AR      drivers/clk/socfpga/built-in.a
  CC      net/bpf/bpf_dummy_struct_ops.o
  AR      drivers/clk/sprd/built-in.a
  CC      lib/crypto/blake2s-generic.o
  CC [M]  arch/x86/kvm/mtrr.o
  CC [M]  sound/core/memalloc.o
  ASN.1   crypto/rsapubkey.asn1.[ch]
  AR      drivers/clk/starfive/built-in.a
  ASN.1   crypto/rsaprivkey.asn1.[ch]
  CC      crypto/rsa.o
  AR      drivers/clk/sunxi-ng/built-in.a
  CC      drivers/pci/hotplug/acpiphp_glue.o
  CC      lib/lz4/lz4_decompress.o
  CC [M]  sound/core/pcm_timer.o
  AR      drivers/clk/ti/built-in.a
  AR      drivers/clk/versatile/built-in.a
  CC      drivers/clk/x86/clk-fch.o
  AS      arch/x86/kernel/head_64.o
  AR      kernel/futex/built-in.a
  CC      mm/mmap_lock.o
  CC      arch/x86/kernel/head64.o
  CC      security/integrity/integrity_audit.o
  AR      security/integrity/evm/built-in.a
  CC      drivers/acpi/acpica/dswscope.o
  CC      fs/jbd2/transaction.o
  CC      fs/squashfs/block.o
  CC      fs/configfs/symlink.o
  CC      fs/squashfs/cache.o
  CC      fs/squashfs/dir.o
  CC      drivers/pnp/interface.o
  CC      kernel/module/kallsyms.o
  CC      drivers/video/fbdev/core/softcursor.o
  CC      lib/crypto/sha1.o
  CC      drivers/pnp/quirks.o
  CC      net/core/dst.o
  CC      kernel/module/procfs.o
  CC      lib/zstd/zstd_compress_module.o
  CC      lib/zstd/compress/fse_compress.o
  CC [M]  sound/core/seq_device.o
  CC      crypto/rsa_helper.o
  CC      kernel/time/timecounter.o
  CC      kernel/module/sysfs.o
  CC      kernel/module/kdb.o
  CC      drivers/clk/x86/clk-lpss-atom.o
  CC      security/landlock/net.o
  CC      kernel/time/alarmtimer.o
  CC      drivers/acpi/acpica/dswstate.o
  CC      crypto/rsa-pkcs1pad.o
  CC      crypto/acompress.o
  CC      kernel/time/posix-timers.o
  CC      kernel/time/posix-cpu-timers.o
  CC      drivers/video/fbdev/core/tileblit.o
  CC      drivers/pnp/system.o
  CC      security/integrity/ima/ima_template_lib.o
  CC      kernel/module/version.o
  AR      drivers/pci/hotplug/built-in.a
  CC      fs/configfs/mount.o
  CC      drivers/pci/access.o
  AR      drivers/pci/switch/built-in.a
  LD [M]  drivers/char/ipmi/ipmi_si.o
  CC      fs/ramfs/inode.o
  AR      drivers/char/ipmi/built-in.a
  CC      fs/squashfs/export.o
  CC      security/integrity/ima/ima_appraise.o
  CC      security/commoncap.o
  CC      fs/hugetlbfs/inode.o
  CC      security/lsm_syscalls.o
  CC      lib/zstd/compress/hist.o
  CC      lib/zstd/compress/huf_compress.o
  CC      fs/ext4/block_validity.o
  CC      block/blk-rq-qos.o
  CC      drivers/video/fbdev/core/fbcon_rotate.o
  CC      block/disk-events.o
  CC      net/sched/act_api.o
  CC      fs/squashfs/file.o
  CC      drivers/acpi/acpica/evevent.o
  CC      fs/configfs/item.o
  CC      fs/squashfs/fragment.o
  CC      lib/crypto/sha256.o
  CC      drivers/clk/x86/clk-pmc-atom.o
  CC      security/apparmor/mount.o
  CC [M]  arch/x86/kvm/debugfs.o
  CC      lib/zstd/compress/zstd_compress.o
  CC      drivers/pci/bus.o
  AR      lib/lz4/built-in.a
  CC      block/blk-ia-ranges.o
  CC      block/early-lookup.o
  AR      drivers/pnp/built-in.a
  CC [M]  sound/core/compress_offload.o
  CC      lib/zstd/compress/zstd_compress_literals.o
  LD [M]  sound/core/snd.o
  CC      lib/zstd/compress/zstd_compress_sequences.o
  CC      arch/x86/kernel/cpu/intel.o
  CC      crypto/scompress.o
  CC      arch/x86/kernel/cpu/intel_pconfig.o
  CC      drivers/acpi/acpica/evgpe.o
  AR      security/landlock/built-in.a
  CC      fs/ramfs/file-mmu.o
  GEN     security/apparmor/net_names.h
  CC      kernel/cgroup/cgroup.o
  GEN     security/apparmor/net_names.h
  CC      kernel/debug/kdb/kdb_io.o
  CC      kernel/debug/debug_core.o
  CC      kernel/cgroup/rstat.o
  CC      kernel/debug/kdb/kdb_main.o
  CC      kernel/cgroup/namespace.o
  CC      kernel/cgroup/cgroup-v1.o
  AR      kernel/module/built-in.a
  CC      mm/highmem.o
  AR      drivers/clk/x86/built-in.a
  CC      drivers/pci/probe.o
  CC      security/integrity/ima/ima_modsig.o
  LD [M]  sound/core/snd-hwdep.o
  CC      drivers/clk/clk-devres.o
  CC      kernel/trace/rv/rv.o
  AR      drivers/clk/xilinx/built-in.a
  CC      fs/ext4/dir.o
  CC      drivers/video/fbdev/core/fbcon_cw.o
  CC      drivers/video/fbdev/core/fbcon_ud.o
  CC      net/netlink/genetlink.o
  CC      kernel/trace/trace_clock.o
  CC      kernel/time/posix-clock.o
  CC      lib/zstd/compress/zstd_compress_superblock.o
  CC      drivers/acpi/acpica/evgpeblk.o
  CC      lib/zstd/compress/zstd_double_fast.o
  CC      fs/jbd2/commit.o
  CC      security/integrity/ima/ima_kexec.o
  CC      fs/jbd2/recovery.o
  CC [M]  arch/x86/kvm/mmu/mmu.o
  CC      fs/squashfs/id.o
  CC      drivers/pci/host-bridge.o
  AR      fs/configfs/built-in.a
  CC      fs/squashfs/inode.o
  CC      net/core/netevent.o
  AR      net/bpf/built-in.a
  AR      lib/crypto/built-in.a
  AR      fs/ramfs/built-in.a
  CC      kernel/trace/rv/monitors/wwnr/wwnr.o
  CC      kernel/bpf/core.o
  CC      fs/fat/cache.o
  CC      kernel/trace/rv/rv_reactors.o
  AR      fs/hugetlbfs/built-in.a
  CC      fs/ecryptfs/dentry.o
  LD [M]  sound/core/snd-timer.o
  CC      fs/ecryptfs/file.o
  CC      kernel/cgroup/freezer.o
  CC      kernel/debug/gdbstub.o
  CC      kernel/bpf/syscall.o
  CC      security/integrity/ima/ima_asymmetric_keys.o
  CC      drivers/acpi/acpica/evgpeinit.o
  CC      security/apparmor/policy_compat.o
  CC      crypto/algboss.o
  CC      security/apparmor/crypto.o
  CC      block/bsg.o
  CC      kernel/debug/kdb/kdb_support.o
  CC      mm/memory.o
  CC      kernel/cgroup/legacy_freezer.o
  LD [M]  sound/core/snd-pcm.o
  CC      drivers/clk/clk-bulk.o
  LD [M]  sound/core/snd-seq-device.o
  CC      kernel/cgroup/pids.o
  LD [M]  sound/core/snd-compress.o
  CC      arch/x86/xen/vga.o
  CC      fs/ecryptfs/inode.o
  CC      fs/squashfs/namei.o
  CC      arch/x86/xen/efi.o
  CC      fs/ext4/ext4_jbd2.o
  CC [M]  arch/x86/kvm/mmu/page_track.o
  CC      drivers/video/fbdev/core/fbcon_ccw.o
  CC      mm/mincore.o
  CC      net/ethtool/ioctl.o
  CC      fs/fat/dir.o
  CC      drivers/acpi/acpica/evgpeutil.o
  CC      net/ethtool/common.o
  CC      fs/exportfs/expfs.o
  CC      kernel/trace/rv/reactor_printk.o
  CC [M]  arch/x86/kvm/mmu/spte.o
  CC      kernel/time/itimer.o
  CC      fs/jbd2/checkpoint.o
  CC      kernel/cgroup/rdma.o
  CC      fs/fat/fatent.o
  CC      security/integrity/ima/ima_queue_keys.o
  CC      security/integrity/ima/ima_efi.o
  CC [M]  sound/soc/codecs/hdac_hda.o
  CC      kernel/cgroup/cpuset.o
  CC      kernel/cgroup/misc.o
  CC      fs/fat/file.o
  CC      security/min_addr.o
  CC      net/netfilter/core.o
  CC      crypto/testmgr.o
  CC      fs/squashfs/super.o
  CC      lib/xz/xz_dec_syms.o
  CC      lib/raid6/algos.o
  CC      net/sched/sch_fifo.o
  CC      fs/nls/nls_base.o
  CC      drivers/acpi/acpica/evglock.o
  CC      fs/nls/nls_cp437.o
  AR      arch/x86/xen/built-in.a
  CC      security/integrity/digsig.o
  CC      lib/raid6/recov.o
  CC      drivers/clk/clkdev.o
  CC      kernel/trace/rv/reactor_panic.o
  CC [M]  fs/nls/nls_iso8859-1.o
  CC      security/apparmor/capability.o
  CC      block/bsg-lib.o
  CC      fs/ecryptfs/main.o
  CC      drivers/pci/remove.o
  CC      net/core/neighbour.o
  CC      drivers/video/fbdev/core/cfbfillrect.o
  CC      kernel/debug/kdb/kdb_bt.o
  CC      net/sched/ematch.o
  CC      drivers/acpi/acpica/evhandler.o
  CC [M]  net/sched/sch_fq_codel.o
  CC      lib/xz/xz_dec_stream.o
  AR      security/integrity/ima/built-in.a
  CC      kernel/time/clockevents.o
  CC      kernel/time/tick-common.o
  CC      net/netlink/policy.o
  CC      fs/jbd2/revoke.o
  AR      fs/exportfs/built-in.a
  CC [M]  arch/x86/kvm/mmu/tdp_iter.o
  CC      fs/ext4/extents.o
  CC [M]  arch/x86/kvm/mmu/tdp_mmu.o
  CC      arch/x86/kernel/cpu/tsx.o
  HOSTCC  lib/raid6/mktables
  CC      fs/squashfs/symlink.o
  UNROLL  lib/raid6/int1.c
  CC      arch/x86/kernel/cpu/intel_epb.o
  CC      arch/x86/kernel/cpu/amd.o
  CC      security/integrity/digsig_asymmetric.o
  CC      crypto/hmac.o
  CC      drivers/acpi/acpica/evmisc.o
  AR      kernel/trace/rv/built-in.a
  CC      crypto/crypto_null.o
  CC      kernel/trace/ftrace.o
  CC      kernel/trace/ring_buffer.o
  CC [M]  fs/nls/nls_ucs2_utils.o
  CC      kernel/bpf/verifier.o
  LD [M]  sound/soc/codecs/snd-soc-hdac-hda.o
  CC      lib/xz/xz_dec_lzma2.o
  CC      kernel/bpf/inode.o
  CC      kernel/bpf/helpers.o
  GENKDB  kernel/debug/kdb/gen-kdb_cmds.c
  CC      kernel/debug/kdb/kdb_bp.o
  CC [M]  sound/soc/amd/acp-config.o
  UNROLL  lib/raid6/int2.c
  UNROLL  lib/raid6/int4.c
  UNROLL  lib/raid6/int8.c
  CC      lib/raid6/recov_ssse3.o
  CC      mm/mlock.o
  CC      lib/zstd/compress/zstd_fast.o
  CC      drivers/pci/pci.o
  CC      fs/ecryptfs/super.o
  CC      fs/fat/inode.o
  CC      drivers/acpi/acpica/evregion.o
  CC      drivers/clk/clk.o
  CC      drivers/pci/pci-driver.o
  AR      net/netlink/built-in.a
  CC      fs/squashfs/decompressor.o
  CC      security/apparmor/resource.o
  CC      fs/squashfs/page_actor.o
  CC      security/security.o
  CC      fs/fat/misc.o
  CC      fs/fat/nfs.o
  CC      security/integrity/platform_certs/platform_keyring.o
  CC      fs/jbd2/journal.o
  CC      fs/fat/namei_vfat.o
  CC      net/core/rtnetlink.o
  CC      block/blk-cgroup.o
  CC      net/core/utils.o
  CC      lib/xz/xz_dec_bcj.o
  AR      net/sched/built-in.a
  CC      drivers/acpi/acpica/evrgnini.o
  CC      kernel/time/tick-broadcast.o
  CC      drivers/acpi/acpica/evsci.o
  AR      fs/nls/built-in.a
  CC      drivers/video/fbdev/core/cfbcopyarea.o
  CC      kernel/debug/kdb/kdb_debugger.o
  CC      kernel/debug/kdb/kdb_keyboard.o
  CC      fs/fat/namei_msdos.o
  CC      lib/raid6/recov_avx2.o
  CC      fs/ecryptfs/mmap.o
  CC      crypto/md5.o
  CC      lib/raid6/mmx.o
  CC      security/integrity/platform_certs/machine_keyring.o
  CC      lib/raid6/sse1.o
  CC      net/core/link_watch.o
  CC      fs/squashfs/file_direct.o
  CC      security/inode.o
  CC      net/netfilter/nf_log.o
  CC      net/netfilter/nf_queue.o
  AR      lib/xz/built-in.a
  CC      fs/ext4/extents_status.o
  CC      lib/dim/dim.o
  CC      lib/fonts/fonts.o
  CC      drivers/acpi/acpica/evxface.o
  LD [M]  sound/soc/amd/snd-acp-config.o
  CC      net/ethtool/netlink.o
  CC      lib/fonts/font_8x8.o
  CC      security/apparmor/net.o
  CC      lib/dim/net_dim.o
  CC      crypto/sha1_generic.o
  CC      lib/raid6/sse2.o
  CC      security/integrity/platform_certs/efi_parser.o
  CC [M]  arch/x86/kvm/hyperv.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-byt-match.o
  CC      security/integrity/platform_certs/load_uefi.o
  CC      kernel/bpf/tnum.o
  CC [M]  sound/soc/intel/atom/sst/sst.o
  CC      fs/squashfs/decompressor_single.o
  CC      lib/fonts/font_8x16.o
  CC      kernel/debug/kdb/gen-kdb_cmds.o
  CC      block/blk-cgroup-rwstat.o
  CC      drivers/pci/search.o
  CC      kernel/time/tick-broadcast-hrtimer.o
  CC      lib/fonts/font_acorn_8x8.o
  AR      kernel/debug/kdb/built-in.a
  AR      fs/fat/built-in.a
  CC      kernel/trace/trace.o
  CC      mm/mmap.o
  AR      kernel/debug/built-in.a
  CC      fs/ecryptfs/read_write.o
  CC      fs/ext4/file.o
  CC      drivers/video/screen_info_generic.o
  CC      net/netfilter/nf_sockopt.o
  CC      drivers/acpi/acpica/evxfevnt.o
  CC      security/integrity/platform_certs/keyring_handler.o
  AR      kernel/cgroup/built-in.a
  CC      kernel/trace/trace_output.o
  CC      drivers/video/fbdev/core/cfbimgblt.o
  CC      drivers/clk/clk-divider.o
  CC [M]  sound/soc/intel/atom/sst-mfld-platform-pcm.o
  CC      drivers/clk/clk-fixed-factor.o
  CC [M]  sound/soc/intel/atom/sst-mfld-platform-compress.o
  CC      crypto/sha256_generic.o
  CC      lib/zstd/compress/zstd_lazy.o
  CC      drivers/clk/clk-fixed-rate.o
  CC      lib/dim/rdma_dim.o
  CC      lib/raid6/avx2.o
  CC      fs/squashfs/decompressor_multi.o
  CC [M]  sound/soc/intel/atom/sst/sst_ipc.o
  CC      kernel/time/tick-oneshot.o
  AR      net/ipv4/netfilter/built-in.a
  CC [M]  net/ipv4/netfilter/nf_defrag_ipv4.o
  CC      drivers/clk/clk-gate.o
  CC [M]  sound/soc/intel/atom/sst/sst_stream.o
  CC      drivers/pci/pci-sysfs.o
  CC      drivers/acpi/acpica/evxfgpe.o
  AR      security/integrity/built-in.a
  CC      lib/fonts/font_6x10.o
  AR      security/apparmor/built-in.a
  CC      fs/ecryptfs/crypto.o
  CC      crypto/sha512_generic.o
  CC      fs/ecryptfs/keystore.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-cht-match.o
  CC      drivers/pci/rom.o
  CC      lib/fonts/font_ter16x32.o
  CC      drivers/dma/hsu/hsu.o
  CC      net/core/filter.o
  AR      drivers/dma/idxd/built-in.a
  CC      drivers/dma/lgm/lgm-dma.o
  CC      fs/ext4/fsmap.o
  CC      mm/mmu_gather.o
  CC      net/netfilter/utils.o
  CC      net/netfilter/nf_bpf_link.o
  CC      kernel/time/tick-sched.o
  CC      net/ethtool/bitset.o
  CC      kernel/fork.o
  CC      kernel/events/core.o
  CC      kernel/events/ring_buffer.o
  CC      lib/raid6/avx512.o
  CC      fs/squashfs/decompressor_multi_percpu.o
  CC      block/blk-throttle.o
  CC      net/ethtool/strset.o
  CC      net/netfilter/nf_hooks_lwtunnel.o
  AR      lib/dim/built-in.a
  CC      net/ethtool/linkinfo.o
  CC      net/ethtool/linkmodes.o
  CC      drivers/video/fbdev/core/fb_io_fops.o
  AR      fs/jbd2/built-in.a
  CC      kernel/trace/trace_seq.o
  CC      security/lsm_audit.o
  CC      kernel/events/callchain.o
  CC      fs/ext4/fsync.o
  AR      lib/fonts/built-in.a
  CC      drivers/acpi/acpica/evxfregn.o
  CC [M]  sound/soc/intel/atom/sst/sst_drv_interface.o
  CC      drivers/acpi/acpica/exconcat.o
  CC      kernel/trace/trace_stat.o
  CC      security/device_cgroup.o
  CC      kernel/events/hw_breakpoint.o
  CC      drivers/clk/clk-multiplier.o
  CC [M]  net/ipv4/netfilter/ip_tables.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.o
  CC      drivers/pci/setup-res.o
  CC      mm/mprotect.o
  CC      drivers/video/fbdev/core/sysfillrect.o
  CC      mm/mremap.o
  CC      drivers/video/fbdev/core/syscopyarea.o
  CC      crypto/sha3_generic.o
  CC      lib/raid6/recov_avx512.o
  CC      drivers/video/fbdev/core/sysimgblt.o
  CC      fs/squashfs/xattr.o
  CC      kernel/trace/trace_printk.o
  AR      drivers/dma/hsu/built-in.a
  CC      net/ethtool/rss.o
  CC      drivers/acpi/acpica/exconfig.o
  AR      drivers/dma/mediatek/built-in.a
  AR      drivers/dma/qcom/built-in.a
  CC      fs/ecryptfs/kthread.o
  CC      net/core/sock_diag.o
  CC      lib/zstd/compress/zstd_ldm.o
  AR      drivers/dma/lgm/built-in.a
  AR      drivers/dma/ti/built-in.a
  CC      kernel/events/uprobes.o
  AR      drivers/dma/xilinx/built-in.a
  CC      drivers/clk/clk-mux.o
  CC [M]  drivers/dma/ioat/init.o
  CC [M]  drivers/dma/dw/core.o
  CC      arch/x86/kernel/cpu/hygon.o
  CC [M]  drivers/dma/dw/dw.o
  CC      drivers/acpi/acpica/exconvrt.o
  CC      drivers/acpi/acpica/excreate.o
  CC      kernel/bpf/log.o
  CC [M]  arch/x86/kvm/xen.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-skl-match.o
  CC [M]  sound/soc/intel/atom/sst/sst_loader.o
  CC      kernel/time/vsyscall.o
  CC      fs/ext4/hash.o
  CC      lib/zstd/compress/zstd_opt.o
  CC [M]  arch/x86/kvm/smm.o
  CC      kernel/time/timekeeping_debug.o
  CC [M]  sound/soc/intel/atom/sst/sst_pvt.o
  TABLE   lib/raid6/tables.c
  CC      crypto/blake2b_generic.o
  CC      lib/raid6/int1.o
  CC      fs/squashfs/xattr_id.o
  CC      net/xfrm/xfrm_policy.o
  CC      drivers/acpi/acpica/exdebug.o
  CC      drivers/acpi/acpica/exdump.o
  CC [M]  drivers/dma/ioat/dma.o
  CC      fs/ecryptfs/debug.o
  CC      crypto/ecb.o
  CC      net/core/dev_ioctl.o
  CC [M]  net/netfilter/nfnetlink.o
  CC      drivers/pci/irq.o
  CC      drivers/pci/vpd.o
  CC      mm/msync.o
  CC      net/ethtool/linkstate.o
  CC [M]  drivers/dma/dw/idma32.o
  CC      net/ethtool/debug.o
  CC      drivers/pci/setup-bus.o
  CC      fs/squashfs/lz4_wrapper.o
  CC      kernel/exec_domain.o
  CC [M]  net/netfilter/nf_conntrack_core.o
  CC [M]  sound/soc/intel/atom/sst/sst_acpi.o
  CC [M]  lib/reed_solomon/reed_solomon.o
  CC      block/blk-ioprio.o
  CC      drivers/clk/clk-composite.o
  AR      security/built-in.a
  CC      mm/page_vma_mapped.o
  CC      kernel/time/namespace.o
  CC      kernel/bpf/bpf_iter.o
  CC      drivers/video/screen_info_pci.o
  CC      drivers/video/fbdev/core/fb_sys_fops.o
  CC      fs/ext4/ialloc.o
  CC      drivers/acpi/acpica/exfield.o
  CC      net/xfrm/xfrm_state.o
  CC      lib/raid6/int2.o
  CC [M]  net/ipv4/netfilter/iptable_filter.o
  CC [M]  drivers/dma/dw/acpi.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-kbl-match.o
  CC      fs/ecryptfs/messaging.o
  CC      drivers/pci/vc.o
  CC      drivers/pci/mmap.o
  CC [M]  arch/x86/kvm/vmx/vmx.o
  CC      drivers/acpi/acpica/exfldio.o
  CC [M]  net/ipv4/netfilter/iptable_nat.o
  CC      crypto/cbc.o
  CC      drivers/acpi/acpica/exmisc.o
  CC      fs/squashfs/lzo_wrapper.o
  CC      drivers/acpi/acpica/exmutex.o
  CC [M]  drivers/dma/ioat/prep.o
  CC      kernel/panic.o
  LD [M]  sound/soc/intel/atom/sst/snd-intel-sst-core.o
  CC      block/blk-iocost.o
  CC      drivers/video/cmdline.o
  AR      kernel/time/built-in.a
  LD [M]  sound/soc/intel/atom/sst/snd-intel-sst-acpi.o
  CC [M]  sound/soc/intel/atom/sst-atom-controls.o
  CC      kernel/cpu.o
  CC      net/ethtool/wol.o
  CC      net/core/tso.o
  CC      kernel/trace/pid_list.o
  CC      net/core/sock_reuseport.o
  CC      lib/raid6/int4.o
  CC      drivers/acpi/acpica/exnames.o
  AR      drivers/soc/apple/built-in.a
  CC      net/core/fib_notifier.o
  AR      drivers/soc/aspeed/built-in.a
  AR      drivers/soc/bcm/built-in.a
  CC      drivers/clk/clk-fractional-divider.o
  AR      drivers/soc/fsl/built-in.a
  CC      mm/pagewalk.o
  CC      crypto/cts.o
  CC      crypto/xts.o
  AR      drivers/soc/fujitsu/built-in.a
  CC      crypto/ctr.o
  AR      drivers/soc/hisilicon/built-in.a
  CC      fs/ext4/indirect.o
  CC      drivers/acpi/acpica/exoparg1.o
  CC      drivers/pci/setup-irq.o
  CC      crypto/gcm.o
  AR      drivers/soc/imx/built-in.a
  CC      fs/ecryptfs/miscdev.o
  CC      drivers/acpi/acpica/exoparg2.o
  CC      kernel/bpf/map_iter.o
  CC      drivers/acpi/acpica/exoparg3.o
  AR      drivers/soc/ixp4xx/built-in.a
  CC      drivers/clk/clk-gpio.o
  AR      drivers/soc/loongson/built-in.a
  CC      fs/ext4/inline.o
  AR      drivers/soc/mediatek/built-in.a
  AR      drivers/video/fbdev/core/built-in.a
  AR      drivers/video/fbdev/built-in.a
  CC [M]  drivers/dma/dw/platform.o
  AR      drivers/soc/microchip/built-in.a
  CC      fs/squashfs/xz_wrapper.o
  CC      kernel/bpf/task_iter.o
  AR      drivers/soc/nuvoton/built-in.a
  AR      drivers/soc/pxa/built-in.a
  CC      lib/raid6/int8.o
  AR      drivers/soc/amlogic/built-in.a
  CC [M]  sound/soc/intel/common/soc-acpi-intel-bxt-match.o
  AR      drivers/soc/qcom/built-in.a
  CC      drivers/acpi/acpica/exoparg6.o
  AR      drivers/soc/renesas/built-in.a
  CC      drivers/pci/proc.o
  AR      drivers/soc/rockchip/built-in.a
  AR      drivers/soc/sunxi/built-in.a
  AR      drivers/soc/ti/built-in.a
  CC      net/ethtool/features.o
  AR      drivers/soc/xilinx/built-in.a
  CC      kernel/trace/tracing_map.o
  LD [M]  drivers/dma/dw/dw_dmac_core.o
  AR      drivers/soc/built-in.a
  CC [M]  sound/soc/intel/common/soc-acpi-intel-glk-match.o
  CC      arch/x86/kernel/ebda.o
  CC      kernel/bpf/prog_iter.o
  CC      net/core/xdp.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-cnl-match.o
  CC      net/ipv4/route.o
  CC      net/core/flow_offload.o
  CC [M]  drivers/dma/ioat/dca.o
  AR      drivers/pmdomain/actions/built-in.a
  AR      drivers/pmdomain/amlogic/built-in.a
  AR      drivers/pmdomain/apple/built-in.a
  AR      drivers/pmdomain/arm/built-in.a
  CC      crypto/aes_generic.o
  CC [M]  net/netfilter/nf_conntrack_standalone.o
  CC      drivers/virtio/virtio.o
  AR      drivers/pmdomain/bcm/built-in.a
  AR      drivers/pmdomain/imx/built-in.a
  CC      crypto/deflate.o
  CC [M]  net/netfilter/nf_conntrack_expect.o
  AR      drivers/pmdomain/mediatek/built-in.a
  AR      drivers/pmdomain/qcom/built-in.a
  LD [M]  sound/soc/intel/atom/snd-soc-sst-atom-hifi2-platform.o
  AR      drivers/pmdomain/renesas/built-in.a
  CC      drivers/acpi/acpica/exprep.o
  CC [M]  net/netfilter/nf_conntrack_helper.o
  CC [M]  sound/hda/ext/hdac_ext_bus.o
  AR      drivers/pmdomain/rockchip/built-in.a
  AR      drivers/pmdomain/samsung/built-in.a
  CC [M]  drivers/dma/ioat/sysfs.o
  AR      drivers/pmdomain/st/built-in.a
  AR      fs/ecryptfs/built-in.a
  CC      drivers/video/nomodeset.o
  AR      drivers/pmdomain/starfive/built-in.a
  CC      fs/unicode/utf8-norm.o
  AR      drivers/pmdomain/sunxi/built-in.a
  CC      mm/pgtable-generic.o
  CC [M]  drivers/clk/clk-tps68470.o
  AR      drivers/pmdomain/tegra/built-in.a
  CC      fs/squashfs/zlib_wrapper.o
  LD [M]  drivers/dma/dw/dw_dmac.o
  AR      drivers/pmdomain/ti/built-in.a
  AR      drivers/pmdomain/xilinx/built-in.a
  CC      drivers/pmdomain/core.o
  CC      drivers/pci/slot.o
  CC      drivers/pci/pci-acpi.o
  CC      lib/raid6/tables.o
  CC      arch/x86/kernel/cpu/centaur.o
  CC      drivers/xen/events/events_base.o
  CC      drivers/pci/quirks.o
  CC      drivers/xen/xenbus/xenbus_client.o
  CC      drivers/acpi/acpica/exregion.o
  CC      drivers/pci/ats.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-cfl-match.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-cml-match.o
  CC [M]  net/netfilter/nf_conntrack_proto.o
  CC [M]  net/netfilter/nf_conntrack_proto_generic.o
  CC      net/ethtool/privflags.o
  CC      drivers/virtio/virtio_ring.o
  CC      arch/x86/kernel/platform-quirks.o
  CC      drivers/pci/iov.o
  CC      kernel/trace/trace_sched_switch.o
  LD [M]  drivers/dma/ioat/ioatdma.o
  CC      drivers/dma/dmaengine.o
  CC      fs/unicode/utf8-core.o
  CC      fs/squashfs/zstd_wrapper.o
  CC      fs/ext4/inode.o
  CC      drivers/video/hdmi.o
  CC      arch/x86/kernel/cpu/zhaoxin.o
  CC      kernel/trace/trace_functions.o
  CC      net/core/gro.o
  AR      drivers/clk/built-in.a
  CC      drivers/acpi/acpica/exresnte.o
  CC      drivers/dma/virt-dma.o
  CC      lib/argv_split.o
  CC      mm/rmap.o
  CC [M]  sound/hda/ext/hdac_ext_controller.o
  CC [M]  net/netfilter/nf_conntrack_proto_tcp.o
  CC      crypto/crc32c_generic.o
  CC      block/mq-deadline.o
  CC      net/core/netdev-genl.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-icl-match.o
  CC      drivers/acpi/acpica/exresolv.o
  CC      net/xfrm/xfrm_hash.o
  CC      lib/bug.o
  CC [M]  arch/x86/kvm/kvm-asm-offsets.s
  AR      fs/squashfs/built-in.a
  CC [M]  arch/x86/kvm/vmx/pmu_intel.o
  AR      lib/raid6/built-in.a
  CC [M]  arch/x86/kvm/vmx/vmcs12.o
  CC [M]  sound/hda/hda_bus_type.o
  CC      net/xfrm/xfrm_input.o
  CC      drivers/regulator/core.o
  CC      kernel/bpf/link_iter.o
  CC [M]  sound/hda/hdac_bus.o
  CC      net/core/netdev-genl-gen.o
  CC      net/ethtool/rings.o
  CC      net/ethtool/channels.o
  CC      net/ethtool/coalesce.o
  CC      net/xfrm/xfrm_output.o
  CC      net/ethtool/pause.o
  COPY    fs/unicode/utf8data.c
  CC      fs/unicode/utf8data.o
  CC      crypto/crct10dif_common.o
  CC      net/core/gso.o
  CC      kernel/trace/trace_preemptirq.o
  CC      drivers/xen/xenbus/xenbus_comms.o
  CC      drivers/acpi/acpica/exresop.o
  CC      net/ipv4/inetpeer.o
  CC      drivers/pmdomain/governor.o
  CC      net/ipv4/protocol.o
  CC      drivers/acpi/apei/apei-base.o
  CC [M]  net/netfilter/nf_conntrack_proto_udp.o
  CC      drivers/acpi/apei/hest.o
  CC      net/ipv4/ip_input.o
  CC      net/ethtool/eee.o
  AR      drivers/video/built-in.a
  CC [M]  sound/hda/ext/hdac_ext_stream.o
  CC      net/ethtool/tsinfo.o
  CC      net/ethtool/cabletest.o
  CC      drivers/dma/acpi-dma.o
  CC      drivers/xen/xenbus/xenbus_xs.o
  CC      crypto/crct10dif_generic.o
  CC      drivers/acpi/acpica/exserial.o
  AR      kernel/events/built-in.a
  CC [M]  arch/x86/kvm/vmx/nested.o
  CC [M]  arch/x86/kvm/vmx/posted_intr.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-tgl-match.o
  CC      crypto/crc64_rocksoft_generic.o
  CC      block/bio-integrity.o
  CC      kernel/bpf/hashtab.o
  CC [M]  sound/hda/hdac_device.o
  CC      crypto/lzo.o
  CC [M]  sound/hda/hdac_sysfs.o
  CC      net/ipv4/ip_fragment.o
  CC      crypto/lzo-rle.o
  CC      net/ipv4/ip_forward.o
  AR      fs/unicode/built-in.a
  AR      drivers/pmdomain/built-in.a
  CC      drivers/xen/events/events_2l.o
  CC      drivers/xen/events/events_fifo.o
  CC      block/blk-integrity.o
  CC      block/t10-pi.o
  CC      fs/ntfs/aops.o
  CC      drivers/xen/xenbus/xenbus_probe.o
  CC      block/blk-mq-pci.o
  CC      drivers/pci/pci-label.o
  CC      drivers/acpi/apei/erst.o
  CC      drivers/virtio/virtio_anchor.o
  CC      drivers/acpi/acpica/exstore.o
  CC      drivers/acpi/acpica/exstoren.o
  CC      kernel/trace/trace_sched_wakeup.o
  CC [M]  drivers/dma/idma64.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-ehl-match.o
  CC      drivers/acpi/pmic/intel_pmic.o
  CC      drivers/xen/xenbus/xenbus_probe_backend.o
  CC      drivers/acpi/apei/bert.o
  CC      drivers/acpi/pmic/intel_pmic_bytcrc.o
  LD [M]  sound/hda/ext/snd-hda-ext-core.o
  CC      net/ethtool/tunnels.o
  CC      drivers/acpi/pmic/intel_pmic_chtcrc.o
  CC [M]  net/netfilter/nf_conntrack_proto_icmp.o
  CC      crypto/xxhash_generic.o
  CC [M]  net/netfilter/nf_conntrack_extend.o
  CC      drivers/acpi/acpica/exstorob.o
  CC      drivers/acpi/acpica/exsystem.o
  CC      net/xfrm/xfrm_sysctl.o
  CC      kernel/trace/trace_hwlat.o
  CC      net/core/net-sysfs.o
  CC      drivers/pci/p2pdma.o
  CC [M]  sound/hda/hdac_regmap.o
  CC      net/core/page_pool.o
  CC      drivers/pci/vgaarb.o
  CC      arch/x86/kernel/process_64.o
  CC      drivers/acpi/dptf/int340x_thermal.o
  CC [M]  sound/hda/hdac_controller.o
  CC      net/ipv4/ip_options.o
  AR      drivers/xen/events/built-in.a
  CC      drivers/xen/cpu_hotplug.o
  CC      mm/vmalloc.o
  CC      fs/ntfs/attrib.o
  CC [M]  sound/hda/hdac_stream.o
  CC      drivers/virtio/virtio_pci_modern_dev.o
  CC      drivers/virtio/virtio_pci_legacy_dev.o
  CC      drivers/acpi/apei/ghes.o
  CC      drivers/acpi/acpica/extrace.o
  CC      fs/fuse/dev.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-jsl-match.o
  CC      drivers/xen/xenbus/xenbus_dev_frontend.o
  CC [M]  drivers/acpi/nfit/core.o
  AR      drivers/dma/built-in.a
  CC      crypto/rng.o
  CC      kernel/exit.o
  CC      kernel/softirq.o
  CC      drivers/regulator/dummy.o
  AR      drivers/reset/hisilicon/built-in.a
  AR      drivers/acpi/dptf/built-in.a
  CC      drivers/tty/vt/vt_ioctl.o
  CC      kernel/trace/trace_osnoise.o
  AR      drivers/reset/starfive/built-in.a
  CC      drivers/tty/vt/vc_screen.o
  CC      drivers/acpi/pmic/intel_pmic_chtwc.o
  CC      drivers/tty/vt/selection.o
  CC      drivers/reset/core.o
  CC [M]  net/netfilter/nf_conntrack_acct.o
  CC      drivers/reset/reset-simple.o
  CC [M]  net/netfilter/nf_conntrack_seqadj.o
  CC      drivers/acpi/acpica/exutils.o
  CC      drivers/xen/xenbus/xenbus_dev_backend.o
  AR      fs/hostfs/built-in.a
  CC      fs/debugfs/inode.o
  CC      fs/fuse/dir.o
  CC      kernel/resource.o
  CC      block/blk-mq-virtio.o
  CC      kernel/sysctl.o
  CC      net/xfrm/xfrm_replay.o
  CC      fs/ext4/ioctl.o
  CC      net/ethtool/fec.o
  CC      arch/x86/kernel/cpu/perfctr-watchdog.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-adl-match.o
  CC      mm/process_vm_access.o
  CC      drivers/acpi/acpica/hwacpi.o
  CC      fs/ntfs/collate.o
  CC      mm/page_alloc.o
  CC      lib/zstd/zstd_decompress_module.o
  CC      drivers/virtio/virtio_mmio.o
  CC [M]  sound/hda/array.o
  CC      drivers/acpi/pmic/tps68470_pmic.o
  CC      drivers/pci/doe.o
  CC      net/ethtool/eeprom.o
  CC      net/ipv4/ip_output.o
  CC      net/ipv4/ip_sockglue.o
  CC [M]  sound/hda/hdmi_chmap.o
  CC      fs/debugfs/file.o
  CC [M]  sound/hda/trace.o
  CC      crypto/drbg.o
  CC [M]  net/netfilter/nf_conntrack_proto_icmpv6.o
  CC      drivers/regulator/fixed-helper.o
  CC      drivers/acpi/acpica/hwesleep.o
  CC      kernel/bpf/arraymap.o
  CC      kernel/bpf/percpu_freelist.o
  CC      drivers/xen/xenbus/xenbus_probe_frontend.o
  CC      arch/x86/kernel/cpu/vmware.o
  CC      drivers/tty/vt/keyboard.o
  CC      net/ipv4/inet_hashtables.o
  AR      drivers/acpi/apei/built-in.a
  CC      fs/ntfs/compress.o
  CC      net/ipv4/inet_timewait_sock.o
  CC [M]  sound/hda/hdac_component.o
  CC      fs/fuse/file.o
  CC [M]  sound/hda/hdac_i915.o
  AR      drivers/reset/built-in.a
  CC      kernel/capability.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-rpl-match.o
  CC      kernel/bpf/bpf_lru_list.o
  CC      block/blk-zoned.o
  AR      drivers/acpi/pmic/built-in.a
  CC [M]  sound/soc/intel/common/soc-acpi-intel-mtl-match.o
  CC      drivers/acpi/tables.o
  CC      drivers/acpi/acpica/hwgpe.o
  CC      drivers/acpi/acpica/hwregs.o
  CC      drivers/acpi/acpica/hwsleep.o
  CC      lib/zstd/decompress/huf_decompress.o
  CC      drivers/virtio/virtio_pci_modern.o
  CC      arch/x86/kernel/cpu/hypervisor.o
  CC      drivers/acpi/acpica/hwvalid.o
  CC      crypto/jitterentropy.o
  CC      net/core/page_pool_user.o
  CC      drivers/regulator/helpers.o
  CC      net/ethtool/stats.o
  CC      drivers/regulator/devres.o
  CC      net/xfrm/xfrm_device.o
  CC      drivers/virtio/virtio_pci_common.o
  CC [M]  drivers/acpi/nfit/intel.o
  CC      net/xfrm/xfrm_proc.o
  CC [M]  net/xfrm/xfrm_algo.o
  CC      drivers/regulator/irq_helpers.o
  CC      fs/ext4/mballoc.o
  CC      kernel/bpf/lpm_trie.o
  CC [M]  drivers/pci/pci-stub.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-arl-match.o
  CC      kernel/ptrace.o
  CC      net/unix/af_unix.o
  CC      drivers/acpi/acpica/hwxface.o
  CC      kernel/trace/trace_nop.o
  CC [M]  net/netfilter/nf_conntrack_timeout.o
  CC      arch/x86/kernel/cpu/mshyperv.o
  CC      fs/fuse/inode.o
  CC [M]  arch/x86/kvm/vmx/sgx.o
  CC [M]  net/xfrm/xfrm_user.o
  AR      fs/debugfs/built-in.a
  CC      crypto/jitterentropy-kcapi.o
  CC      net/packet/af_packet.o
  AR      net/ipv6/netfilter/built-in.a
  CC [M]  net/ipv6/netfilter/nf_defrag_ipv6_hooks.o
  CC      block/blk-wbt.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-lnl-match.o
  CC [M]  drivers/acpi/nfit/mce.o
  CC      mm/shuffle.o
  AR      drivers/xen/xenbus/built-in.a
  CC [M]  sound/hda/intel-dsp-config.o
  CC      fs/ntfs/debug.o
  CC      drivers/xen/grant-table.o
  CC      fs/tracefs/inode.o
  CC      fs/tracefs/event_inode.o
  AR      drivers/pci/built-in.a
  CC      fs/ntfs/dir.o
  CC [M]  drivers/regulator/tps68470-regulator.o
  CC      drivers/virtio/virtio_pci_legacy.o
  CC      net/ipv4/inet_connection_sock.o
  CC      net/core/net-procfs.o
  CC      net/devlink/core.o
  CC      drivers/char/hw_random/core.o
  CC      drivers/acpi/acpica/hwxfsleep.o
  CC      kernel/trace/trace_stack.o
  CC      drivers/char/agp/backend.o
  CC      kernel/trace/trace_mmiotrace.o
  CC      drivers/char/tpm/tpm-chip.o
  CC      drivers/char/agp/generic.o
  CC      crypto/ghash-generic.o
  CC      net/ethtool/phc_vclocks.o
  CC      net/unix/garbage.o
  CC      drivers/acpi/blacklist.o
  CC      drivers/tty/vt/consolemap.o
  AR      net/dsa/built-in.a
  CC      mm/init-mm.o
  CC      drivers/acpi/osi.o
  CC      lib/buildid.o
  LD [M]  drivers/acpi/nfit/nfit.o
  CC      net/unix/sysctl_net_unix.o
  CC      fs/ext4/migrate.o
  CC      kernel/bpf/map_in_map.o
  CC [M]  arch/x86/kvm/vmx/hyperv.o
  CC      net/ipv4/tcp.o
  AR      fs/tracefs/built-in.a
  CC [M]  sound/soc/intel/common/soc-acpi-intel-hda-match.o
  CC [M]  sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.o
  AR      drivers/regulator/built-in.a
  CC      drivers/iommu/amd/iommu.o
  CC      drivers/virtio/virtio_pci_admin_legacy_io.o
  CC      drivers/iommu/amd/init.o
  CC      drivers/iommu/intel/dmar.o
  CC      drivers/acpi/acpica/hwpci.o
  CC      drivers/acpi/acpica/nsaccess.o
  CC      fs/fuse/control.o
  CC      crypto/xor.o
  CC      lib/zstd/decompress/zstd_ddict.o
  CC [M]  sound/hda/intel-nhlt.o
  CC      mm/memblock.o
  CC      arch/x86/kernel/cpu/acrn.o
  CC      net/core/netpoll.o
  CC      net/core/fib_rules.o
  CC      crypto/hash_info.o
  CC      arch/x86/kernel/cpu/debugfs.o
  CC      kernel/trace/trace_functions_graph.o
  CC      fs/ntfs/file.o
  CC      kernel/trace/blktrace.o
  CC      lib/zstd/decompress/zstd_decompress.o
  CC      fs/fuse/xattr.o
  CC      drivers/iommu/amd/quirks.o
  CC [M]  net/netfilter/nf_conntrack_timestamp.o
  CC      block/blk-mq-debugfs.o
  CC      net/ethtool/mm.o
  CC      drivers/xen/features.o
  CC      fs/fuse/acl.o
  CC      kernel/bpf/bloom_filter.o
  CC      block/blk-mq-debugfs-zoned.o
  AR      drivers/char/hw_random/built-in.a
  CC      drivers/virtio/virtio_balloon.o
  CC      fs/fuse/readdir.o
  CC      drivers/acpi/acpica/nsalloc.o
  CC      drivers/char/tpm/tpm-dev-common.o
  CC      net/core/net-traces.o
  CC      net/core/drop_monitor.o
  CC      kernel/trace/fgraph.o
  CC      kernel/trace/trace_events.o
  CC      crypto/kdf_sp800108.o
  CC [M]  net/ipv6/netfilter/nf_conntrack_reasm.o
  CC [M]  crypto/cmac.o
  HOSTCC  drivers/tty/vt/conmakehash
  CC [M]  arch/x86/kvm/vmx/hyperv_evmcs.o
  CC [M]  crypto/ccm.o
  CC      drivers/xen/balloon.o
  CC      drivers/char/agp/isoch.o
  CC [M]  drivers/virtio/virtio_mem.o
  CC      lib/zstd/decompress/zstd_decompress_block.o
  CC      drivers/acpi/acpica/nsarguments.o
  LD [M]  sound/soc/intel/common/snd-soc-acpi-intel-match.o
  LD [M]  arch/x86/kvm/kvm.o
  CC      drivers/tty/vt/vt.o
  CC      net/ipv4/tcp_input.o
  CC      fs/ntfs/index.o
  CC [M]  sound/soc/sof/intel/hda.o
  CC      lib/zstd/zstd_common_module.o
  CC [M]  sound/soc/sof/amd/acp.o
  CC      lib/zstd/common/debug.o
  CC [M]  sound/hda/intel-sdw-acpi.o
  CC      net/ipv4/tcp_output.o
  CC      drivers/char/tpm/tpm-dev.o
  CC      drivers/char/tpm/tpm-interface.o
  CC      kernel/bpf/local_storage.o
  AR      drivers/iommu/arm/arm-smmu/built-in.a
  CC      lib/zstd/common/entropy_common.o
  CC [M]  net/netfilter/nf_conntrack_ecache.o
  CC      mm/memory_hotplug.o
  AR      drivers/iommu/arm/arm-smmu-v3/built-in.a
  AR      drivers/iommu/arm/built-in.a
  CC      arch/x86/kernel/cpu/capflags.o
  CC      fs/fuse/ioctl.o
  CC      drivers/acpi/acpica/nsconvert.o
  CC      mm/slub.o
  CC [M]  sound/soc/sof/amd/acp-loader.o
  CC      net/unix/unix_bpf.o
  AR      drivers/iommu/iommufd/built-in.a
  AR      arch/x86/kernel/cpu/built-in.a
  CC [M]  sound/soc/sof/amd/acp-ipc.o
  CC      arch/x86/kernel/signal.o
  CC      lib/zstd/common/error_private.o
  CC      drivers/iommu/intel/iommu.o
  CC      block/sed-opal.o
  CC      net/strparser/strparser.o
  UPD     arch/x86/kvm/kvm-asm-offsets.h
  CC [M]  crypto/cryptd.o
  AS [M]  arch/x86/kvm/vmx/vmenter.o
  CC      drivers/char/agp/amd64-agp.o
  AR      net/xfrm/built-in.a
  CC      fs/ntfs/inode.o
  LD [M]  arch/x86/kvm/kvm-intel.o
  CC      arch/x86/kernel/signal_64.o
  CC      net/ipv6/af_inet6.o
  CC      arch/x86/kernel/traps.o
  AR      drivers/virtio/built-in.a
  LD [M]  sound/hda/snd-hda-core.o
  CC      net/devlink/netlink.o
  CC      fs/ext4/mmp.o
  CC      drivers/acpi/acpica/nsdump.o
  CC      fs/pstore/inode.o
  CC      drivers/char/tpm/tpm1-cmd.o
  CC      net/ethtool/module.o
  CC      fs/pstore/platform.o
  CC      fs/efivarfs/inode.o
  CC      fs/ntfs/mft.o
  CC      drivers/iommu/amd/io_pgtable.o
  CC      fs/btrfs/super.o
  CC      drivers/acpi/acpica/nseval.o
  LD [M]  sound/hda/snd-intel-dspcfg.o
  LD [M]  sound/hda/snd-intel-sdw-acpi.o
  CC      drivers/acpi/acpica/nsinit.o
  AR      drivers/gpu/host1x/built-in.a
  CC      lib/zstd/common/fse_decompress.o
  CC      fs/btrfs/ctree.o
  CC      drivers/acpi/acpica/nsload.o
  CC      drivers/xen/manage.o
  CC      kernel/bpf/queue_stack_maps.o
  AR      net/packet/built-in.a
  COPY    drivers/tty/vt/defkeymap.c
  CC [M]  sound/soc/sof/intel/hda-loader.o
  CC      kernel/trace/trace_export.o
  CC      fs/pstore/pmsg.o
  CC      drivers/char/agp/intel-agp.o
  CC      fs/ext4/move_extent.o
  CC [M]  fs/netfs/buffered_read.o
  CC      fs/efivarfs/file.o
  CC      fs/efivarfs/super.o
  AR      drivers/gpu/drm/tests/built-in.a
  CC      fs/ext4/namei.o
  AR      fs/fuse/built-in.a
  CC [M]  drivers/gpu/drm/tests/drm_kunit_helpers.o
  CC [M]  fs/pstore/ram.o
  CONMK   drivers/tty/vt/consolemap_deftbl.c
  CC [M]  drivers/gpu/drm/tests/drm_buddy_test.o
  CC [M]  drivers/gpu/drm/tests/drm_cmdline_parser_test.o
  CC [M]  fs/nfs/client.o
  CC      net/unix/scm.o
  CC [M]  fs/nfs/dir.o
  CC [M]  sound/soc/sof/amd/acp-pcm.o
  CC      drivers/acpi/acpica/nsnames.o
  CC      drivers/acpi/acpica/nsobject.o
  LD [M]  net/ipv6/netfilter/nf_defrag_ipv6.o
  CC [M]  crypto/polyval-generic.o
  CC      net/ipv4/tcp_timer.o
  CC      fs/ntfs/mst.o
  CC      net/ethtool/pse-pd.o
  CC      arch/x86/kernel/idt.o
  CC      drivers/iommu/amd/io_pgtable_v2.o
  CC      block/blk-pm.o
  CC [M]  net/netfilter/nf_conntrack_labels.o
  CC [M]  fs/pstore/ram_core.o
  CC      lib/zstd/common/zstd_common.o
  CC      drivers/char/tpm/tpm2-cmd.o
  CC      drivers/tty/vt/defkeymap.o
  CC [M]  sound/soc/sof/intel/hda-stream.o
  CC      net/devlink/netlink_gen.o
  CC      kernel/trace/trace_syscalls.o
  CC [M]  sound/soc/sof/intel/hda-trace.o
  CC      drivers/char/tpm/tpmrm-dev.o
  CC      kernel/bpf/ringbuf.o
  AR      lib/zstd/built-in.a
  CC      lib/clz_tab.o
  CC      drivers/acpi/acpica/nsparse.o
  CC      drivers/char/agp/intel-gtt.o
  AR      net/wireless/tests/built-in.a
  AR      net/wireless/built-in.a
  CC      lib/cmdline.o
  CC [M]  drivers/gpu/drm/tests/drm_connector_test.o
  CC      lib/cpumask.o
  CC      fs/efivarfs/vars.o
  CC      kernel/trace/trace_event_perf.o
  AR      net/strparser/built-in.a
  CC      drivers/char/agp/via-agp.o
  CC [M]  sound/soc/sof/amd/acp-stream.o
  CC      net/netlabel/netlabel_user.o
  CC [M]  fs/nfs/file.o
  CC      drivers/tty/vt/consolemap_deftbl.o
  CC [M]  drivers/gpu/drm/tests/drm_damage_helper_test.o
  CC [M]  fs/nfs/getroot.o
  CC      fs/ntfs/namei.o
  CC [M]  drivers/gpu/drm/tests/drm_dp_mst_helper_test.o
  AR      drivers/tty/vt/built-in.a
  CC      drivers/xen/time.o
  CC      drivers/tty/hvc/hvc_console.o
  CC      net/netlabel/netlabel_kapi.o
  CC      drivers/acpi/acpica/nspredef.o
  CC      arch/x86/kernel/irq.o
  CC      net/netlabel/netlabel_domainhash.o
  CC      net/devlink/dev.o
  AR      drivers/iommu/amd/built-in.a
  CC [M]  crypto/simd.o
  CC [M]  drivers/gpu/drm/tests/drm_exec_test.o
  CC      net/ipv4/tcp_ipv4.o
  CC [M]  fs/pstore/zone.o
  CC      net/ethtool/plca.o
  CC [M]  sound/soc/sof/xtensa/core.o
  CC [M]  sound/soc/sof/intel/hda-dsp.o
  CC      net/ipv6/anycast.o
  AR      fs/efivarfs/built-in.a
  CC      kernel/trace/trace_events_filter.o
  CC      kernel/trace/trace_events_trigger.o
  CC [M]  fs/netfs/buffered_write.o
  CC      kernel/trace/trace_eprobe.o
  CC      drivers/acpi/acpica/nsprepkg.o
  CC      fs/ntfs/runlist.o
  CC      kernel/trace/trace_events_inject.o
  CC      block/blk-crypto.o
  CC [M]  sound/soc/sof/intel/hda-ipc.o
  CC      lib/ctype.o
  AR      net/unix/built-in.a
  CC      kernel/bpf/bpf_local_storage.o
  CC [M]  sound/soc/sof/intel/hda-ctrl.o
  CC      net/rfkill/core.o
  CC      lib/dec_and_lock.o
  CC [M]  fs/nfs/inode.o
  CC      lib/decompress.o
  CC      drivers/xen/mem-reservation.o
  CC      drivers/char/tpm/tpm2-space.o
  CC      block/blk-crypto-profile.o
  CC      lib/decompress_bunzip2.o
  CC      lib/decompress_inflate.o
  CC      drivers/iommu/intel/pasid.o
  AR      drivers/char/agp/built-in.a
  CC [M]  drivers/gpu/drm/tests/drm_format_helper_test.o
  CC [M]  net/netfilter/nf_conntrack_proto_dccp.o
  CC      drivers/iommu/intel/nested.o
  CC      drivers/acpi/acpica/nsrepair.o
  CC [M]  fs/lockd/clntlock.o
  CC [M]  sound/soc/sof/amd/acp-trace.o
  CC [M]  fs/lockd/clntproc.o
  LD [M]  crypto/crypto_simd.o
  AR      net/ethtool/built-in.a
  CC      crypto/rsapubkey.asn1.o
  CC [M]  sound/soc/sof/amd/acp-common.o
  CC [M]  sound/soc/sof/amd/acp-probes.o
  CC      drivers/tty/hvc/hvc_irq.o
  CC      crypto/rsaprivkey.asn1.o
  AR      crypto/built-in.a
  CC      fs/ext4/page-io.o
  CC      drivers/tty/serial/8250/8250_core.o
  CC      mm/madvise.o
  CC [M]  sound/soc/sof/amd/pci-rn.o
  CC      drivers/tty/serdev/core.o
  CC      drivers/xen/pci.o
  CC      mm/page_io.o
  CC [M]  fs/netfs/direct_read.o
  CC      fs/ntfs/super.o
  CC      drivers/acpi/acpica/nsrepair2.o
  CC [M]  sound/soc/sof/intel/hda-pcm.o
  CC      drivers/acpi/acpica/nssearch.o
  CC      drivers/tty/serdev/serdev-ttyport.o
  CC      lib/decompress_unlz4.o
  LD [M]  sound/soc/sof/xtensa/snd-sof-xtensa-dsp.o
  CC      net/ipv6/ip6_output.o
  CC      drivers/char/tpm/tpm-sysfs.o
  CC      drivers/iommu/iommu.o
  CC      fs/btrfs/extent-tree.o
  CC [M]  fs/pstore/blk.o
  CC      net/netlabel/netlabel_addrlist.o
  AR      drivers/tty/ipwireless/built-in.a
  CC      drivers/tty/hvc/hvc_xen.o
  CC      drivers/tty/tty_io.o
  CC      drivers/iommu/intel/trace.o
  CC      mm/swap_state.o
  CC      kernel/bpf/bpf_task_storage.o
  CC      kernel/bpf/bpf_inode_storage.o
  CC      lib/decompress_unlzma.o
  CC      net/rfkill/input.o
  CC [M]  fs/netfs/direct_write.o
  CC [M]  sound/soc/sof/amd/renoir.o
  CC      drivers/acpi/acpica/nsutils.o
  CC [M]  drivers/gpu/drm/tests/drm_format_test.o
  CC [M]  drivers/gpu/drm/tests/drm_framebuffer_test.o
  CC      net/devlink/port.o
  CC      net/core/selftests.o
  CC [M]  net/netfilter/nf_conntrack_proto_sctp.o
  CC      drivers/tty/n_tty.o
  CC      fs/ntfs/sysctl.o
  CC [M]  fs/netfs/io.o
  CC      kernel/trace/trace_events_synth.o
  CC      block/blk-crypto-sysfs.o
  CC      kernel/trace/trace_events_hist.o
  CC      fs/ntfs/unistr.o
  CC      net/devlink/sb.o
  CC [M]  sound/soc/sof/intel/hda-dai.o
  CC      kernel/trace/bpf_trace.o
  CC [M]  fs/lockd/clntxdr.o
  CC      arch/x86/kernel/irq_64.o
  CC      drivers/char/tpm/eventlog/common.o
  CC      drivers/tty/serial/8250/8250_pnp.o
  CC      net/devlink/dpipe.o
  AR      drivers/gpu/drm/arm/built-in.a
  CC      fs/ext4/readpage.o
  CC      fs/ext4/resize.o
  AR      drivers/tty/serdev/built-in.a
  CC      drivers/char/tpm/eventlog/tpm1.o
  AR      net/rfkill/built-in.a
  CC      drivers/acpi/acpica/nswalk.o
  CC      fs/ext4/super.o
  CC      net/ipv6/ip6_input.o
  CC      lib/decompress_unlzo.o
  CC      net/ipv6/addrconf.o
  CC      net/ipv6/addrlabel.o
  CC [M]  fs/nfs/super.o
  CC      drivers/iommu/intel/cap_audit.o
  CC      kernel/bpf/disasm.o
  CC      drivers/xen/dbgp.o
  AR      drivers/tty/hvc/built-in.a
  CC      kernel/bpf/mprog.o
  LD [M]  fs/pstore/ramoops.o
  LD [M]  fs/pstore/pstore_zone.o
  LD [M]  fs/pstore/pstore_blk.o
  CC      net/netlabel/netlabel_mgmt.o
  AR      fs/pstore/built-in.a
  CC      fs/ntfs/upcase.o
  CC      kernel/bpf/trampoline.o
  CC      kernel/user.o
  CC [M]  drivers/gpu/drm/tests/drm_gem_shmem_test.o
  CC      block/blk-crypto-fallback.o
  CC      block/holder.o
  CC [M]  net/netfilter/nf_conntrack_netlink.o
  CC      drivers/iommu/iommu-traces.o
  CC      drivers/acpi/acpica/nsxfeval.o
  CC      mm/swapfile.o
  CC      arch/x86/kernel/dumpstack_64.o
  CC      drivers/iommu/iommu-sysfs.o
  CC      drivers/tty/serial/8250/8250_port.o
  LD [M]  sound/soc/sof/amd/snd-sof-amd-acp.o
  LD [M]  sound/soc/sof/amd/snd-sof-amd-renoir.o
  CC      drivers/tty/serial/8250/8250_dma.o
  CC      lib/decompress_unxz.o
  CC      net/dcb/dcbnl.o
  CC      net/dcb/dcbevent.o
  CC      drivers/char/tpm/eventlog/tpm2.o
  CC [M]  fs/lockd/host.o
  CC      drivers/tty/tty_ioctl.o
  CC      kernel/signal.o
  CC      drivers/xen/acpi.o
  CC      net/devlink/resource.o
  CC      drivers/xen/xen-acpi-pad.o
  AR      fs/ntfs/built-in.a
  CC      net/core/timestamping.o
  CC      net/netlabel/netlabel_unlabeled.o
  CC [M]  sound/soc/sof/intel/hda-dai-ops.o
  CC [M]  fs/netfs/iterator.o
  CC      drivers/acpi/acpica/nsxfname.o
  CC      arch/x86/kernel/time.o
  CC [M]  drivers/gpu/drm/tests/drm_managed_test.o
  CC      drivers/iommu/intel/svm.o
  CC [M]  sound/soc/sof/intel/hda-bus.o
  CC      net/netlabel/netlabel_cipso_v4.o
  CC      lib/decompress_unzstd.o
  CC      drivers/iommu/dma-iommu.o
  CC      drivers/iommu/intel/irq_remapping.o
  CC      net/ipv4/tcp_minisocks.o
  CC      net/ipv4/tcp_cong.o
  CC      net/ipv4/tcp_metrics.o
  CC      drivers/tty/serial/8250/8250_dwlib.o
  CC      kernel/trace/trace_kprobe.o
  CC      net/netlabel/netlabel_calipso.o
  AR      block/built-in.a
  CC      drivers/char/tpm/tpm_ppi.o
  CC [M]  fs/nfs/io.o
  CC      net/core/ptp_classifier.o
  CC      net/core/netprio_cgroup.o
  CC      net/ipv4/tcp_fastopen.o
  CC      net/ipv6/route.o
  CC      kernel/bpf/btf.o
  CC      net/devlink/param.o
  CC [M]  drivers/gpu/drm/tests/drm_mm_test.o
  CC      fs/ext4/symlink.o
  CC      drivers/xen/pcpu.o
  CC [M]  fs/netfs/locking.o
  CC      arch/x86/kernel/ioport.o
  CC      lib/dump_stack.o
  CC [M]  drivers/gpu/drm/tests/drm_modes_test.o
  CC      drivers/acpi/acpica/nsxfobj.o
  CC      net/devlink/region.o
  CC      net/devlink/health.o
  CC [M]  sound/soc/sof/intel/skl.o
  CC      arch/x86/kernel/dumpstack.o
  CC [M]  fs/lockd/svc.o
  CC [M]  fs/nfs/direct.o
  CC      net/devlink/trap.o
  CC      fs/btrfs/print-tree.o
  CC      drivers/char/tpm/eventlog/acpi.o
  CC [M]  fs/netfs/main.o
  CC [M]  fs/nfs/pagelist.o
  AR      sound/built-in.a
  CC      kernel/trace/error_report-traces.o
  CC      fs/btrfs/root-tree.o
  CC      kernel/trace/power-traces.o
  CC [M]  fs/nfs/read.o
  CC      kernel/trace/rpm-traces.o
  CC      kernel/trace/trace_kdb.o
  CC [M]  fs/nfs/symlink.o
  CC [M]  drivers/gpu/drm/tests/drm_plane_helper_test.o
  CC      fs/btrfs/dir-item.o
  CC      drivers/iommu/intel/perfmon.o
  CC [M]  net/netfilter/nf_nat_core.o
  CC      drivers/tty/serial/8250/8250_fintek.o
  CC      drivers/xen/biomerge.o
  CC      drivers/tty/serial/8250/8250_pcilib.o
  CC      drivers/acpi/acpica/psargs.o
  CC [M]  fs/nfs/unlink.o
  AR      drivers/gpu/drm/display/built-in.a
  CC [M]  drivers/gpu/drm/display/drm_display_helper_mod.o
  AR      net/dcb/built-in.a
  CC      kernel/trace/trace_dynevent.o
  CC      arch/x86/kernel/nmi.o
  CC      lib/earlycpio.o
  CC      arch/x86/kernel/ldt.o
  CC      lib/extable.o
  CC      net/ipv4/tcp_rate.o
  CC      drivers/char/tpm/eventlog/efi.o
  CC [M]  fs/netfs/misc.o
  CC      lib/flex_proportions.o
  CC      drivers/acpi/acpica/psloop.o
  CC      mm/swap_slots.o
  CC      lib/idr.o
  AR      net/netlabel/built-in.a
  CC      drivers/acpi/acpica/psobject.o
  CC [M]  drivers/gpu/drm/tests/drm_probe_helper_test.o
  CC      drivers/xen/xen-balloon.o
  CC      mm/zswap.o
  CC      drivers/iommu/io-pgtable.o
  CC [M]  drivers/gpu/drm/display/drm_dp_dual_mode_helper.o
  CC      net/core/netclassid_cgroup.o
  CC [M]  sound/soc/sof/intel/hda-loader-skl.o
  CC      net/devlink/rate.o
  CC      net/ipv4/tcp_recovery.o
  CC      drivers/xen/sys-hypervisor.o
  CC [M]  drivers/gpu/drm/display/drm_dp_helper.o
  CC      kernel/sys.o
  CC      arch/x86/kernel/setup.o
  AR      drivers/gpu/drm/renesas/rcar-du/built-in.a
  CC      drivers/acpi/acpica/psopcode.o
  AR      drivers/gpu/drm/renesas/rz-du/built-in.a
  AR      drivers/gpu/drm/renesas/built-in.a
  AR      drivers/iommu/intel/built-in.a
  CC      drivers/tty/serial/8250/8250_early.o
  CC      drivers/char/tpm/tpm_tis_core.o
  CC      drivers/tty/serial/8250/8250_dw.o
  CC      drivers/tty/serial/8250/8250_mid.o
  CC      net/devlink/linecard.o
  CC      fs/btrfs/file-item.o
  CC      net/core/lwtunnel.o
  CC [M]  drivers/gpu/drm/display/drm_dp_mst_topology.o
  CC      drivers/char/tpm/tpm_tis.o
  CC      net/ipv4/tcp_ulp.o
  CC      drivers/iommu/iova.o
  CC      arch/x86/kernel/x86_init.o
  CC [M]  fs/lockd/svclock.o
  CC [M]  drivers/gpu/drm/tests/drm_rect_test.o
  CC      drivers/iommu/irq_remapping.o
  CC      drivers/iommu/virtio-iommu.o
  CC      kernel/trace/trace_probe.o
  CC      lib/irq_regs.o
  CC      drivers/xen/platform-pci.o
  CC      kernel/umh.o
  CC      drivers/acpi/acpica/psopinfo.o
  CC [M]  fs/nfs/write.o
  CC [M]  fs/nfs/namespace.o
  CC [M]  sound/soc/sof/intel/apl.o
  CC [M]  fs/netfs/objects.o
  CC      mm/dmapool.o
  CC      lib/is_single_threaded.o
  CC      mm/hugetlb.o
  CC      lib/klist.o
  CC      fs/ext4/sysfs.o
  CC      net/ipv4/tcp_offload.o
  CC      net/ipv4/tcp_plb.o
  CC      net/core/lwt_bpf.o
  CC [M]  fs/netfs/output.o
  CC      kernel/workqueue.o
  CC      drivers/acpi/acpica/psparse.o
  CC      drivers/tty/serial/8250/8250_pci.o
  CC      kernel/trace/trace_uprobe.o
  CC [M]  fs/smb/common/cifs_arc4.o
  CC      arch/x86/kernel/i8259.o
  CC [M]  net/netfilter/nf_nat_proto.o
  CC [M]  fs/smb/client/trace.o
  CC [M]  fs/smb/client/cifsfs.o
  CC      drivers/char/tpm/tpm_crb.o
  CC      net/ipv6/ip6_fib.o
  CC      drivers/tty/serial/8250/8250_rt288x.o
  CC      drivers/xen/swiotlb-xen.o
  CC      drivers/xen/mcelog.o
  CC [M]  sound/sound_core.o
  CC      drivers/connector/cn_queue.o
  CC      lib/kobject.o
  CC      drivers/connector/connector.o
  CC      drivers/connector/cn_proc.o
  CC      mm/hugetlb_vmemmap.o
  CC      drivers/acpi/acpica/psscope.o
  CC [M]  drivers/gpu/drm/display/drm_dsc_helper.o
  CC      drivers/iommu/iommu-sva.o
  CC [M]  fs/smb/common/cifs_md4.o
  CC      arch/x86/kernel/irqinit.o
  CC      drivers/iommu/io-pgfault.o
  CC [M]  fs/lockd/svcshare.o
  CC [M]  fs/nfs/mount_clnt.o
  CC      fs/ext4/xattr.o
  CC      fs/btrfs/inode-item.o
  CC      fs/btrfs/disk-io.o
  CC [M]  sound/soc/sof/intel/cnl.o
  CC      fs/btrfs/transaction.o
  CC      kernel/pid.o
  CC      drivers/acpi/acpica/pstree.o
  CC      kernel/task_work.o
  AR      drivers/char/tpm/built-in.a
  AR      net/devlink/built-in.a
  CC      net/dns_resolver/dns_key.o
  CC      drivers/char/mem.o
  CC      lib/kobject_uevent.o
  CC      net/dns_resolver/dns_query.o
  CC [M]  sound/soc/sof/intel/tgl.o
  CC      net/core/dst_cache.o
  CC      drivers/xen/xen-acpi-processor.o
  CC [M]  drivers/gpu/drm/display/drm_dp_tunnel.o
  CC      drivers/char/random.o
  CC [M]  drivers/gpu/drm/display/drm_hdcp_helper.o
  CC      net/ipv4/datagram.o
  LD [M]  fs/netfs/netfs.o
  CC      drivers/xen/efi.o
  AR      drivers/gpu/drm/omapdrm/built-in.a
  CC      drivers/acpi/acpica/psutils.o
  CC [M]  sound/soc/sof/core.o
  CC      arch/x86/kernel/jump_label.o
  CC      mm/mempolicy.o
  CC      net/ipv6/ipv6_sockglue.o
  CC [M]  sound/soc/sof/ops.o
  AR      drivers/tty/serial/8250/built-in.a
  CC      net/ipv6/ndisc.o
  CC      fs/ext4/xattr_hurd.o
  CC      drivers/tty/serial/serial_core.o
  CC [M]  fs/lockd/svcproc.o
  CC      arch/x86/kernel/irq_work.o
  CC      arch/x86/kernel/probe_roms.o
  CC      kernel/trace/trace_boot.o
  CC      drivers/acpi/acpica/pswalk.o
  CC      net/ipv4/raw.o
  AR      drivers/iommu/built-in.a
  CC [M]  fs/nfs/nfstrace.o
  CC [M]  drivers/gpu/drm/display/drm_hdmi_helper.o
  CC      arch/x86/kernel/sys_ia32.o
  AR      drivers/connector/built-in.a
  CC [M]  drivers/gpu/drm/display/drm_scdc_helper.o
  CC      net/core/gro_cells.o
  CC [M]  fs/lockd/svcsubs.o
  CC      mm/sparse.o
  CC      kernel/bpf/memalloc.o
  CC      arch/x86/kernel/signal_32.o
  CC [M]  fs/autofs/init.o
  CC [M]  drivers/gpu/drm/display/drm_dp_aux_dev.o
  CC      kernel/extable.o
  CC      drivers/xen/xlate_mmu.o
  CC      lib/logic_pio.o
  CC      drivers/acpi/acpica/psxface.o
  CC [M]  net/netfilter/nf_nat_helper.o
  AR      net/dns_resolver/built-in.a
  CC      net/ipv6/udp.o
  CC      net/ipv6/udplite.o
  CC      kernel/trace/fprobe.o
  CC      mm/sparse-vmemmap.o
  CC [M]  fs/smb/client/cifs_debug.o
  CC      drivers/tty/serial/serial_base_bus.o
  CC      fs/ext4/xattr_trusted.o
  CC [M]  sound/soc/sof/intel/icl.o
  CC [M]  drivers/gpu/drm/display/drm_dp_cec.o
  CC [M]  fs/nfs/export.o
  CC [M]  fs/autofs/inode.o
  CC      net/ipv4/udp.o
  CC [M]  sound/soc/sof/loader.o
  CC [M]  fs/nfs/sysfs.o
  CC      drivers/acpi/acpica/rsaddr.o
  CC      arch/x86/kernel/sys_x86_64.o
  CC [M]  sound/soc/sof/ipc.o
  CC [M]  sound/soc/sof/intel/mtl.o
  CC      kernel/params.o
  CC [M]  fs/lockd/mon.o
  CC      fs/btrfs/inode.o
  CC      net/core/failover.o
  CC      net/core/skmsg.o
  CC      lib/maple_tree.o
  CC      drivers/base/power/sysfs.o
  CC      drivers/base/firmware_loader/builtin/main.o
  CC      drivers/base/regmap/regmap.o
  AR      drivers/base/test/built-in.a
  CC      drivers/base/power/generic_ops.o
  CC      net/ipv6/raw.o
  CC      drivers/base/power/common.o
  CC [M]  fs/lockd/trace.o
  CC      drivers/acpi/acpica/rscalc.o
  CC      drivers/base/power/qos.o
  CC      drivers/char/ttyprintk.o
  CC      kernel/bpf/dispatcher.o
  CC      fs/ext4/xattr_user.o
  CC      kernel/trace/rethook.o
  CC      kernel/trace/trace_fprobe.o
  CC      drivers/base/firmware_loader/fallback_table.o
  CC [M]  fs/autofs/root.o
  CC [M]  net/netfilter/nf_nat_masquerade.o
  CC      drivers/xen/unpopulated-alloc.o
  CC      arch/x86/kernel/espfix_64.o
  CC      drivers/char/misc.o
  LD [M]  sound/soundcore.o
  CC      drivers/xen/grant-dma-ops.o
  AR      drivers/base/firmware_loader/builtin/built-in.a
  CC      drivers/tty/serial/serial_ctrl.o
  CC      drivers/tty/serial/serial_port.o
  CC      kernel/bpf/devmap.o
  CC      fs/btrfs/file.o
  CC      drivers/acpi/acpica/rscreate.o
  CC      kernel/bpf/cpumap.o
  CC      drivers/base/power/runtime.o
  CC [M]  fs/smb/client/connect.o
  CC      drivers/acpi/osl.o
  CC [M]  fs/overlayfs/super.o
  LD [M]  drivers/gpu/drm/display/drm_display_helper.o
  CC      fs/ext4/fast_commit.o
  CC      drivers/char/virtio_console.o
  CC [M]  sound/soc/sof/pcm.o
  CC      drivers/base/component.o
  CC      drivers/base/power/wakeirq.o
  CC      fs/btrfs/defrag.o
  CC      drivers/block/loop.o
  CC      drivers/tty/serial/earlycon.o
  AR      drivers/gpu/drm/tilcdc/built-in.a
  CC      drivers/base/power/main.o
  AR      drivers/gpu/drm/imx/built-in.a
  CC [M]  fs/nfs/fs_context.o
  AR      drivers/gpu/drm/i2c/built-in.a
  CC      drivers/base/power/wakeup.o
  CC [M]  sound/soc/sof/intel/lnl.o
  CC      kernel/bpf/offload.o
  CC [M]  fs/autofs/symlink.o
  AR      drivers/gpu/drm/panel/built-in.a
  CC [M]  fs/lockd/xdr.o
  CC      arch/x86/kernel/ksysfs.o
  CC      mm/mmu_notifier.o
  CC      mm/ksm.o
  AR      drivers/gpu/drm/bridge/analogix/built-in.a
  CC      mm/page_poison.o
  CC [M]  net/netfilter/nf_tables_core.o
  AR      drivers/xen/built-in.a
  CC [M]  net/netfilter/nf_tables_api.o
  AR      drivers/gpu/drm/bridge/cadence/built-in.a
  CC [M]  net/netfilter/nft_chain_filter.o
  CC      net/ipv6/icmp.o
  AR      drivers/gpu/drm/hisilicon/built-in.a
  AR      drivers/gpu/drm/bridge/imx/built-in.a
  CC      drivers/base/firmware_loader/main.o
  CC [M]  fs/nfs/sysctl.o
  CC      net/core/sock_map.o
  AR      drivers/gpu/drm/bridge/synopsys/built-in.a
  AR      drivers/gpu/drm/bridge/built-in.a
  CC      drivers/acpi/acpica/rsdumpinfo.o
  CC      lib/memcat_p.o
  AR      kernel/trace/built-in.a
  CC      kernel/kthread.o
  AR      drivers/gpu/drm/mxsfb/built-in.a
  AR      drivers/gpu/drm/tiny/built-in.a
  CC      lib/nmi_backtrace.o
  CC [M]  net/netfilter/nf_tables_trace.o
  AR      drivers/gpu/drm/xlnx/built-in.a
  AR      drivers/gpu/drm/gud/built-in.a
  AR      drivers/gpu/drm/solomon/built-in.a
  CC [M]  fs/autofs/waitq.o
  CC      drivers/tty/serial/max310x.o
  CC [M]  drivers/gpu/drm/ttm/ttm_tt.o
  CC      arch/x86/kernel/bootflag.o
  CC      drivers/acpi/acpica/rsinfo.o
  CC      drivers/base/power/wakeup_stats.o
  CC      drivers/base/power/trace.o
  CC [M]  fs/overlayfs/namei.o
  CC [M]  sound/soc/sof/intel/hda-common-ops.o
  CC [M]  drivers/gpu/drm/ttm/ttm_bo.o
  CC      drivers/acpi/acpica/rsio.o
  CC      drivers/tty/tty_ldisc.o
  CC [M]  fs/lockd/procfs.o
  CC [M]  net/netfilter/nft_immediate.o
  CC [M]  net/netfilter/nft_cmp.o
  CC      drivers/char/hpet.o
  CC      drivers/base/power/clock_ops.o
  CC      kernel/bpf/net_namespace.o
  CC      drivers/base/regmap/regcache.o
  CC [M]  fs/autofs/expire.o
  AR      net/mpls/built-in.a
  CC [M]  net/netfilter/nft_range.o
  CC      drivers/tty/serial/sccnxp.o
  CC      arch/x86/kernel/e820.o
  CC      drivers/acpi/acpica/rsirq.o
  CC      arch/x86/kernel/pci-dma.o
  CC      arch/x86/kernel/quirks.o
  CC      drivers/tty/serial/serial_mctrl_gpio.o
  CC      drivers/base/regmap/regcache-rbtree.o
  CC      drivers/block/virtio_blk.o
  CC      drivers/tty/tty_buffer.o
  CC      drivers/block/xen-blkfront.o
  CC      drivers/tty/serial/kgdb_nmi.o
  CC      drivers/base/core.o
  CC [M]  sound/soc/sof/intel/telemetry.o
  CC [M]  sound/soc/sof/intel/hda-probes.o
  CC      fs/ext4/orphan.o
  CC      drivers/acpi/acpica/rslist.o
  CC      kernel/sys_ni.o
  CC [M]  net/netfilter/nft_bitwise.o
  LD [M]  fs/lockd/lockd.o
  CC      fs/open.o
  CC      drivers/tty/serial/kgdboc.o
  CC      drivers/base/firmware_loader/fallback.o
  CC      drivers/base/firmware_loader/sysfs.o
  CC [M]  fs/overlayfs/util.o
  CC [M]  fs/overlayfs/inode.o
  CC [M]  fs/autofs/dev-ioctl.o
  CC      mm/memtest.o
  CC [M]  drivers/char/lp.o
  CC      drivers/base/regmap/regcache-flat.o
  CC      mm/migrate.o
  CC      arch/x86/kernel/topology.o
  CC      net/ipv4/udplite.o
  CC      drivers/tty/tty_port.o
  CC      kernel/bpf/tcx.o
  CC      drivers/acpi/acpica/rsmemory.o
  CC      kernel/bpf/stackmap.o
  CC [M]  drivers/block/nbd.o
  CC      mm/memory-tiers.o
  CC [M]  drivers/gpu/drm/scheduler/sched_main.o
  CC      drivers/base/regmap/regcache-maple.o
  CC [M]  drivers/gpu/drm/ttm/ttm_bo_util.o
  CC [M]  drivers/gpu/drm/radeon/radeon_drv.o
  LD [M]  fs/nfs/nfs.o
  CC [M]  drivers/gpu/drm/radeon/radeon_device.o
  AR      drivers/base/power/built-in.a
  CC [M]  sound/soc/sof/intel/hda-mlink.o
  CC      fs/read_write.o
  CC      fs/file_table.o
  CC      net/ipv6/mcast.o
  CC      net/ipv6/reassembly.o
  CC      fs/super.o
  CC      drivers/base/regmap/regmap-debugfs.o
  CC      drivers/base/firmware_loader/sysfs_upload.o
  CC [M]  drivers/gpu/drm/radeon/radeon_asic.o
  CC      drivers/acpi/acpica/rsmisc.o
  CC [M]  drivers/gpu/drm/radeon/radeon_kms.o
  CC      mm/migrate_device.o
  CC      net/core/bpf_sk_storage.o
  CC      fs/ext4/acl.o
  CC      fs/ext4/xattr_security.o
  AR      drivers/tty/serial/built-in.a
  CC      drivers/acpi/utils.o
  CC      drivers/acpi/acpica/rsserial.o
  CC      drivers/base/regmap/regmap-i2c.o
  CC      drivers/acpi/reboot.o
  CC      net/ipv6/tcp_ipv6.o
  CC      drivers/acpi/acpica/rsutils.o
  LD [M]  fs/autofs/autofs4.o
  CC [M]  fs/smb/client/dir.o
  CC      arch/x86/kernel/kdebugfs.o
  CC      arch/x86/kernel/alternative.o
  CC [M]  drivers/char/ppdev.o
  CC [M]  fs/smb/client/file.o
  CC      kernel/nsproxy.o
  CC [M]  drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.o
  CC      net/ipv4/udp_offload.o
  CC [M]  fs/overlayfs/file.o
  CC      fs/btrfs/extent_map.o
  CC      drivers/acpi/acpica/rsxface.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.o
  CC [M]  drivers/gpu/drm/ttm/ttm_bo_vm.o
  CC [M]  fs/overlayfs/dir.o
  CC      drivers/tty/tty_mutex.o
  CC      kernel/bpf/cgroup_iter.o
  CC [M]  drivers/gpu/drm/radeon/radeon_atombios.o
  CC [M]  sound/soc/sof/intel/hda-codec.o
  CC [M]  fs/overlayfs/readdir.o
  CC      lib/objpool.o
  CC [M]  fs/smb/client/inode.o
  CC [M]  net/netfilter/nft_byteorder.o
  CC      fs/ext4/verity.o
  CC      fs/ext4/crypto.o
  AR      drivers/base/firmware_loader/built-in.a
  CC [M]  fs/smb/client/link.o
  CC      drivers/tty/tty_ldsem.o
  CC [M]  fs/smb/client/misc.o
  CC      net/ipv4/arp.o
  CC [M]  drivers/gpu/drm/ttm/ttm_module.o
  CC [M]  drivers/gpu/drm/ttm/ttm_execbuf_util.o
  CC      net/switchdev/switchdev.o
  CC      net/l3mdev/l3mdev.o
  CC      net/ipv6/ping.o
  CC      kernel/bpf/bpf_cgrp_storage.o
  CC      net/ncsi/ncsi-cmd.o
  CC [M]  fs/smb/client/netmisc.o
  AR      drivers/char/built-in.a
  CC      net/ncsi/ncsi-rsp.o
  CC [M]  net/netfilter/nft_payload.o
  CC      net/ncsi/ncsi-aen.o
  CC [M]  drivers/gpu/drm/scheduler/sched_fence.o
  LD [M]  drivers/gpu/drm/amd/amdxcp/amdxcp.o
  CC      drivers/acpi/acpica/tbdata.o
  CC      drivers/base/regmap/regmap-spi.o
  CC      fs/stat.o
  CC      fs/char_dev.o
  CC      lib/plist.o
  CC      lib/radix-tree.o
  CC      fs/exec.o
  CC      arch/x86/kernel/i8253.o
  CC [M]  drivers/gpu/drm/ttm/ttm_range_manager.o
  CC      drivers/tty/tty_baudrate.o
  CC      drivers/tty/tty_jobctrl.o
  CC [M]  drivers/gpu/drm/ttm/ttm_resource.o
  CC      kernel/notifier.o
  AR      drivers/block/built-in.a
  CC [M]  drivers/gpu/drm/radeon/radeon_agp.o
  AR      fs/ext4/built-in.a
  CC [M]  drivers/gpu/drm/scheduler/sched_entity.o
  CC [M]  fs/overlayfs/copy_up.o
  CC [M]  fs/overlayfs/export.o
  CC [M]  drivers/gpu/drm/ttm/ttm_pool.o
  CC [M]  fs/overlayfs/params.o
  CC      fs/btrfs/sysfs.o
  CC [M]  net/netfilter/nft_lookup.o
  CC      mm/huge_memory.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_device.o
  CC [M]  sound/soc/sof/intel/pci-tgl.o
  CC      mm/khugepaged.o
  AR      net/core/built-in.a
  CC      drivers/tty/n_null.o
  CC      arch/x86/kernel/hw_breakpoint.o
  CC      drivers/acpi/acpica/tbfadt.o
  CC      kernel/bpf/cgroup.o
  CC      drivers/base/regmap/regmap-mmio.o
  CC [M]  sound/soc/sof/intel/pci-mtl.o
  CC      net/ncsi/ncsi-manage.o
  CC      lib/ratelimit.o
  CC [M]  net/netfilter/nft_dynset.o
  CC      net/ncsi/ncsi-netlink.o
  CC [M]  drivers/gpu/drm/i915/i915_config.o
  CC      net/ipv6/exthdrs.o
  CC      drivers/tty/pty.o
  CC      lib/rbtree.o
  CC      mm/page_counter.o
  AR      net/l3mdev/built-in.a
  CC [M]  net/netfilter/nft_meta.o
  CC      net/xdp/xsk.o
  CC      net/xdp/xdp_umem.o
  CC [M]  drivers/gpu/drm/i915/i915_driver.o
  CC      net/ipv6/datagram.o
  CC      drivers/acpi/acpica/tbfind.o
  CC      drivers/tty/tty_audit.o
  CC      arch/x86/kernel/tsc.o
  CC      net/xdp/xsk_queue.o
  CC      arch/x86/kernel/tsc_msr.o
  CC      arch/x86/kernel/io_delay.o
  CC      fs/pipe.o
  CC [M]  fs/overlayfs/xattrs.o
  CC      lib/seq_buf.o
  CC [M]  net/netfilter/nft_rt.o
  CC [M]  drivers/gpu/drm/radeon/atombios_crtc.o
  CC      drivers/acpi/nvs.o
  CC      mm/memcontrol.o
  CC [M]  drivers/gpu/drm/ttm/ttm_device.o
  LD [M]  drivers/gpu/drm/scheduler/gpu-sched.o
  CC      arch/x86/kernel/rtc.o
  AR      net/switchdev/built-in.a
  CC      net/mptcp/protocol.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell_mgr.o
  CC [M]  sound/soc/sof/intel/pci-lnl.o
  LD [M]  sound/soc/sof/intel/snd-sof-intel-hda-common.o
  CC      kernel/ksysfs.o
  CC      net/mptcp/subflow.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_kms.o
  CC      drivers/acpi/acpica/tbinstal.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_bo_test.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_dma_buf_test.o
  CC      drivers/tty/sysrq.o
  CC      drivers/base/regmap/regmap-irq.o
  CC      lib/siphash.o
  CC      arch/x86/kernel/resource.o
  CC      net/mptcp/options.o
  CC      net/mptcp/token.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.o
  CC      net/ipv4/icmp.o
  CC      net/ipv4/devinet.o
  CC      net/ipv4/af_inet.o
  LD [M]  fs/overlayfs/overlay.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_migrate_test.o
  LD [M]  sound/soc/sof/intel/snd-sof-intel-hda-mlink.o
  CC      fs/btrfs/accessors.o
  CC      net/mctp/af_mctp.o
  CC      drivers/acpi/acpica/tbprint.o
  CC      net/mctp/device.o
  CC      kernel/bpf/reuseport_array.o
  CC [M]  sound/soc/soc-acpi.o
  CC [M]  sound/soc/soc-core.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_mocs_test.o
  CC [M]  drivers/gpu/drm/radeon/radeon_combios.o
  CC      drivers/base/bus.o
  CC      kernel/bpf/bpf_struct_ops.o
  LD [M]  sound/soc/sof/intel/snd-sof-intel-hda.o
  LD [M]  sound/soc/sof/intel/snd-sof-pci-intel-tgl.o
  LD [M]  sound/soc/sof/intel/snd-sof-pci-intel-mtl.o
  LD [M]  sound/soc/sof/intel/snd-sof-pci-intel-lnl.o
  CC      kernel/cred.o
  CC [M]  sound/soc/sof/pm.o
  CC      drivers/acpi/acpica/tbutils.o
  AS      arch/x86/kernel/irqflags.o
  TEST    lib/test_fortify/read_overflow2-memmove.log
  CC      fs/namei.o
  CC [M]  net/netfilter/nft_exthdr.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/atombios_crtc.o
  CC [M]  net/netfilter/nft_last.o
  CC [M]  drivers/gpu/drm/ttm/ttm_sys_manager.o
  CC [M]  drivers/gpu/drm/radeon/atom.o
  CC      arch/x86/kernel/static_call.o
  CC [M]  drivers/gpu/drm/i915/i915_drm_client.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_test_mod.o
  TEST    lib/test_fortify/read_overflow-memcmp.log
  CC [M]  sound/soc/soc-dapm.o
  CC      drivers/acpi/acpica/tbxface.o
  AR      net/ncsi/built-in.a
  CC [M]  net/netfilter/nft_counter.o
  CC      net/mptcp/crypto.o
  CC      fs/fcntl.o
  CC [M]  fs/smb/client/smbencrypt.o
  CC      net/xdp/xskmap.o
  AR      drivers/base/regmap/built-in.a
  TEST    lib/test_fortify/write_overflow-memmove.log
  CC [M]  drivers/gpu/drm/radeon/radeon_fence.o
  CC      net/ipv6/ip6_flowlabel.o
  CC [M]  drivers/gpu/drm/ttm/ttm_agp_backend.o
  CC      net/ipv6/inet6_connection_sock.o
  CC      kernel/bpf/cpumask.o
  CC      fs/btrfs/xattr.o
  CC [M]  net/netfilter/nft_objref.o
  TEST    lib/test_fortify/read_overflow2_field-memcpy.log
  CC [M]  drivers/gpu/drm/i915/i915_getparam.o
  CC [M]  drivers/gpu/drm/i915/i915_ioctl.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_pci_test.o
  CC      arch/x86/kernel/process.o
  CC [M]  drivers/gpu/drm/i915/i915_irq.o
  CC      net/mptcp/ctrl.o
  AR      drivers/tty/built-in.a
  CC      drivers/base/dd.o
  CC      drivers/acpi/acpica/tbxfload.o
  CC      drivers/base/syscore.o
  CC [M]  drivers/gpu/drm/i915/i915_mitigations.o
  CC      drivers/base/driver.o
  CC [M]  sound/soc/sof/debug.o
  CC      mm/vmpressure.o
  TEST    lib/test_fortify/read_overflow-memscan.log
  CC      net/ipv4/igmp.o
  CC      drivers/acpi/acpica/tbxfroot.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.o
  CC      arch/x86/kernel/ptrace.o
  CC      net/mctp/route.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/atom.o
  CC      net/xdp/xsk_buff_pool.o
  TEST    lib/test_fortify/write_overflow_field-memcpy.log
  CC      net/mctp/neigh.o
  CC      drivers/acpi/acpica/utaddress.o
  CC      net/ipv6/udp_offload.o
  CC [M]  drivers/gpu/drm/vgem/vgem_drv.o
  CC      kernel/bpf/bpf_lsm.o
  CC      net/ipv6/seg6.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_rtp_test.o
  CC      drivers/acpi/wakeup.o
  CC [M]  drivers/gpu/drm/i915/i915_module.o
  CC [M]  drivers/gpu/drm/vgem/vgem_fence.o
  CC [M]  sound/soc/soc-jack.o
  CC      fs/btrfs/ordered-data.o
  CC [M]  net/netfilter/nft_inner.o
  TEST    lib/test_fortify/read_overflow2-memcmp.log
  LD [M]  drivers/gpu/drm/ttm/ttm.o
  CC [M]  fs/smb/client/transport.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_wa_test.o
  CC [M]  drivers/gpu/drm/xe/xe_bb.o
  CC [M]  fs/smb/client/cached_dir.o
  CC [M]  net/netfilter/nft_chain_route.o
  CC      net/mptcp/pm.o
  CC [M]  drivers/gpu/drm/radeon/radeon_ttm.o
  CC      net/ipv4/fib_frontend.o
  CC [M]  net/netfilter/nf_tables_offload.o
  CC      drivers/acpi/acpica/utalloc.o
  TEST    lib/test_fortify/write_overflow-strcpy-lit.log
  CC      fs/ioctl.o
  CC [M]  net/netfilter/nft_set_hash.o
  CC      fs/btrfs/extent_io.o
  CC      net/ipv6/fib6_notifier.o
  CC [M]  sound/soc/soc-utils.o
  AR      drivers/misc/eeprom/built-in.a
  TEST    lib/test_fortify/read_overflow2-memcpy.log
  AR      drivers/misc/cb710/built-in.a
  CC      drivers/mfd/88pm860x-core.o
  AR      drivers/misc/ti-st/built-in.a
  AR      drivers/misc/lis3lv02d/built-in.a
  AR      drivers/nfc/built-in.a
  CC      drivers/mfd/88pm860x-i2c.o
  CC      drivers/nvdimm/core.o
  AR      drivers/misc/cardreader/built-in.a
  CC      drivers/mfd/wm8400-core.o
  CC      net/mptcp/diag.o
  CC      drivers/dax/hmem/device.o
  AR      drivers/misc/pvpanic/built-in.a
  LD [M]  drivers/gpu/drm/vgem/vgem.o
  CC      drivers/acpi/acpica/utascii.o
  CC      drivers/mfd/wm831x-core.o
  CC [M]  drivers/misc/mei/hdcp/mei_hdcp.o
  CC [M]  drivers/misc/mei/pxp/mei_pxp.o
  CC      drivers/acpi/acpica/utbuffer.o
  CC      drivers/base/class.o
  CC [M]  sound/soc/sof/topology.o
  CC [M]  sound/soc/sof/control.o
  TEST    lib/test_fortify/write_overflow-strscpy.log
  CC      drivers/nvdimm/bus.o
  CC      drivers/nvdimm/dimm_devs.o
  LD [M]  drivers/gpu/drm/xe/tests/xe_test.o
  CC [M]  sound/soc/soc-dai.o
  CC [M]  drivers/gpu/drm/xe/xe_bo.o
  CC      fs/readdir.o
  CC [M]  sound/soc/soc-component.o
  CC [M]  sound/soc/sof/trace.o
  CC [M]  drivers/gpu/drm/i915/i915_params.o
  CC      net/ipv6/rpl.o
  CC      kernel/bpf/relo_core.o
  AR      net/mctp/built-in.a
  CC [M]  fs/smb/client/cifs_unicode.o
  CC      net/ipv6/ioam6.o
  TEST    lib/test_fortify/write_overflow-memcpy.log
  CC      drivers/acpi/acpica/utcksum.o
  CC      drivers/acpi/acpica/utcopy.o
  CC      arch/x86/kernel/tls.o
  CC      arch/x86/kernel/step.o
  CC [M]  drivers/gpu/drm/radeon/radeon_object.o
  CC      net/ipv6/sysctl_net_ipv6.o
  CC      drivers/mfd/wm831x-irq.o
  TEST    lib/test_fortify/read_overflow-memchr.log
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_fence.o
  CC [M]  net/netfilter/nft_set_bitmap.o
  CC [M]  sound/soc/soc-pcm.o
  CC      net/handshake/alert.o
  CC      net/ipv6/ip6mr.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/object.o
  CC      drivers/acpi/acpica/utexcep.o
  CC      mm/swap_cgroup.o
  AR      net/xdp/built-in.a
  CC      drivers/nvdimm/nd_perf.o
  CC      drivers/nvdimm/dimm.o
  CC      drivers/acpi/acpica/utdebug.o
  CC [M]  drivers/misc/mei/init.o
  CC      net/ipv4/fib_semantics.o
  CC [M]  drivers/dax/hmem/hmem.o
  TEST    lib/test_fortify/write_overflow_field-memset.log
  CC [M]  drivers/gpu/drm/xe/xe_bo_evict.o
  CC [M]  drivers/misc/mei/hbm.o
  CC      drivers/base/platform.o
  CC      fs/select.o
  CC      net/mptcp/mib.o
  CC      drivers/mfd/wm831x-otp.o
  CC [M]  drivers/gpu/drm/ast/ast_drv.o
  CC      arch/x86/kernel/tboot.o
  CC [M]  sound/soc/soc-devres.o
  CC [M]  drivers/gpu/drm/i915/i915_pci.o
  CC [M]  drivers/gpu/drm/radeon/radeon_gart.o
  CC      fs/dcache.o
  CC      fs/inode.o
  TEST    lib/test_fortify/read_overflow-memchr_inv.log
  CC [M]  fs/smb/client/nterr.o
  CC [M]  fs/smb/client/cifsencrypt.o
  CC      net/ipv4/fib_trie.o
  CC [M]  fs/smb/client/readdir.o
  CC      fs/btrfs/volumes.o
  CC [M]  sound/soc/soc-ops.o
  CC      drivers/gpu/vga/vga_switcheroo.o
  CC [M]  sound/soc/soc-link.o
  AR      drivers/dax/hmem/built-in.a
  CC      fs/attr.o
  CC      drivers/acpi/acpica/utdecode.o
  CC      net/ipv6/xfrm6_policy.o
  TEST    lib/test_fortify/write_overflow-strcpy.log
  LD [M]  drivers/dax/hmem/dax_hmem.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/client.o
  CC      drivers/acpi/acpica/utdelete.o
  CC      drivers/dax/super.o
  AR      kernel/bpf/built-in.a
  CC [M]  drivers/gpu/drm/nouveau/nvif/conn.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/device.o
  CC      kernel/reboot.o
  CC [M]  drivers/misc/mei/interrupt.o
  CC [M]  net/netfilter/nft_set_rbtree.o
  CC      mm/hugetlb_cgroup.o
  CC [M]  sound/soc/soc-card.o
  CC      fs/bad_inode.o
  CC [M]  fs/smb/client/ioctl.o
  CC [M]  drivers/gpu/drm/xe/xe_debugfs.o
  CC [M]  sound/soc/sof/iomem-utils.o
  CC      drivers/mfd/wm831x-auxadc.o
  TEST    lib/test_fortify/read_overflow2_field-memmove.log
  CC      drivers/nvdimm/region_devs.o
  CC [M]  drivers/gpu/drm/xe/xe_devcoredump.o
  CC      drivers/acpi/acpica/uterror.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.o
  CC [M]  drivers/gpu/drm/ast/ast_i2c.o
  CC      drivers/acpi/acpica/uteval.o
  CC [M]  fs/smb/client/sess.o
  CC      arch/x86/kernel/i8237.o
  CC [M]  drivers/gpu/drm/radeon/radeon_legacy_crtc.o
  CC      drivers/mfd/wm831x-i2c.o
  CC      net/mptcp/pm_netlink.o
  TEST    lib/test_fortify/write_overflow_field-memmove.log
  CC      net/mptcp/sockopt.o
  CC [M]  drivers/gpu/drm/ast/ast_main.o
  CC [M]  drivers/gpu/drm/i915/i915_scatterlist.o
  CC [M]  sound/soc/soc-topology.o
  CC      drivers/base/cpu.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/disp.o
  CC      drivers/base/firmware.o
  CC      arch/x86/kernel/stacktrace.o
  CC      drivers/acpi/acpica/utglobal.o
  TEST    lib/test_fortify/write_overflow-strncpy.log
  CC      arch/x86/kernel/reboot.o
  CC      net/handshake/genl.o
  CC      fs/file.o
  CC      fs/btrfs/async-thread.o
  CC      fs/btrfs/ioctl.o
  CC      mm/memory-failure.o
  CC [M]  sound/soc/soc-compress.o
  LD [M]  sound/soc/snd-soc-acpi.o
  CC [M]  drivers/gpu/drm/xe/xe_device.o
  CC      drivers/dax/bus.o
  CC      net/handshake/netlink.o
  CC      net/handshake/request.o
  CC [M]  fs/smb/client/export.o
  CC      drivers/base/init.o
  CC [M]  drivers/misc/mei/client.o
  CC [M]  drivers/misc/mei/main.o
  TEST    lib/test_fortify/write_overflow-memset.log
  CC [M]  fs/smb/client/unc.o
  CC [M]  drivers/dax/device.o
  CC      drivers/gpu/drm/drm_panel_orientation_quirks.o
  CC      drivers/mfd/wm831x-spi.o
  CC      fs/filesystems.o
  CC      fs/namespace.o
  CC [M]  net/netfilter/nft_set_pipapo.o
  AR      drivers/gpu/vga/built-in.a
  CC      drivers/base/map.o
  CC      drivers/base/devres.o
  CC [M]  sound/soc/sof/sof-audio.o
  CC      kernel/async.o
  CC [M]  fs/smb/client/winucase.o
  CC [M]  drivers/gpu/drm/i915/i915_suspend.o
  CC [M]  drivers/gpu/drm/ast/ast_mm.o
  TEST    lib/test_fortify/write_overflow-strncpy-src.log
  CC [M]  fs/smb/client/smb2ops.o
  CC      drivers/acpi/acpica/uthex.o
  CC      drivers/nvdimm/region.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/driver.o
  CC      fs/seq_file.o
  CC [M]  drivers/gpu/drm/radeon/radeon_legacy_encoders.o
  CC      drivers/base/attribute_container.o
  CC      fs/xattr.o
  CC      lib/timerqueue.o
  CC [M]  drivers/misc/mei/dma-ring.o
  CC      arch/x86/kernel/early-quirks.o
  CC [M]  fs/smb/client/smb2maperror.o
  CC      drivers/mfd/wm8350-core.o
  CC      drivers/acpi/acpica/utids.o
  CC [M]  fs/smb/client/smb2transport.o
  CC      drivers/base/transport_class.o
  CC [M]  fs/smb/client/smb2misc.o
  CC      kernel/range.o
  CC      lib/vsprintf.o
  CC      net/mptcp/pm_userspace.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_object.o
  CC      net/handshake/tlshd.o
  CC      net/ipv4/fib_notifier.o
  CC      fs/libfs.o
  CC      fs/fs-writeback.o
  CC [M]  drivers/gpu/drm/xe/xe_device_sysfs.o
  CC      net/ipv6/xfrm6_state.o
  CC      drivers/base/topology.o
  LD [M]  sound/soc/snd-soc-core.o
  CC [M]  fs/smb/client/smb2pdu.o
  CC      drivers/base/container.o
  CC      drivers/nvdimm/namespace_devs.o
  CC [M]  fs/smb/client/smb2inode.o
  CC [M]  drivers/gpu/drm/ast/ast_mode.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/event.o
  CC      kernel/smpboot.o
  CC      drivers/acpi/acpica/utinit.o
  CC [M]  net/llc/llc_core.o
  LD [M]  drivers/dax/device_dax.o
  AR      drivers/dax/built-in.a
  CC [M]  drivers/misc/mei/bus.o
  CC [M]  net/llc/llc_input.o
  CC [M]  drivers/gpu/drm/i915/i915_switcheroo.o
  CC [M]  net/llc/llc_output.o
  CC      drivers/misc/sram.o
  CC      drivers/base/property.o
  CC      arch/x86/kernel/smp.o
  CC      net/mptcp/fastopen.o
  CC      drivers/acpi/acpica/utlock.o
  CC      drivers/base/cacheinfo.o
  CC      arch/x86/kernel/smpboot.o
  CC [M]  drivers/gpu/drm/ast/ast_post.o
  CC [M]  net/netfilter/nft_set_pipapo_avx2.o
  CC [M]  drivers/misc/mei/bus-fixup.o
  CC [M]  drivers/gpu/drm/i915/i915_sysfs.o
  CC      net/ipv6/xfrm6_input.o
  CC [M]  drivers/gpu/drm/xe/xe_dma_buf.o
  CC [M]  drivers/gpu/drm/radeon/radeon_connectors.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/fifo.o
  CC [M]  sound/soc/sof/stream-ipc.o
  CC [M]  drivers/gpu/drm/radeon/radeon_encoders.o
  CC      kernel/ucount.o
  CC      net/ipv4/inet_fragment.o
  CC      drivers/acpi/sleep.o
  CC      drivers/mfd/wm8350-regmap.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/head.o
  CC      net/ipv6/xfrm6_output.o
  CC      drivers/acpi/acpica/utmath.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/mem.o
  CC      mm/kmemleak.o
  CC      mm/page_isolation.o
  CC      mm/zpool.o
  CC [M]  net/sunrpc/clnt.o
  CC      mm/zbud.o
  CC [M]  net/netfilter/nft_compat.o
  CC      fs/btrfs/locking.o
  CC [M]  sound/soc/sof/fw-file-profile.o
  CC [M]  net/bridge/br.o
  CC      fs/btrfs/orphan.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_gart.o
  CC      kernel/regset.o
  CC [M]  drivers/gpu/drm/radeon/radeon_display.o
  CC      arch/x86/kernel/tsc_sync.o
  CC [M]  net/sunrpc/xprt.o
  CC      drivers/acpi/acpica/utmisc.o
  CC      drivers/base/swnode.o
  LD [M]  net/llc/llc.o
  CC      net/handshake/trace.o
  CC      drivers/nvdimm/label.o
  CC [M]  drivers/misc/enclosure.o
  CC [M]  drivers/misc/mei/debugfs.o
  CC      drivers/mfd/wm8350-gpio.o
  CC      drivers/base/auxiliary.o
  CC [M]  drivers/gpu/drm/i915/i915_utils.o
  CC      drivers/base/devtmpfs.o
  CC      drivers/base/node.o
  CC      net/mptcp/sched.o
  CC [M]  net/bridge/br_device.o
  CC      drivers/acpi/acpica/utmutex.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/mmu.o
  CC      drivers/acpi/acpica/utnonansi.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/outp.o
  CC [M]  sound/soc/sof/ipc3.o
  CC      drivers/base/memory.o
  CC [M]  sound/soc/sof/ipc3-loader.o
  CC [M]  sound/soc/sof/ipc3-topology.o
  CC [M]  drivers/gpu/drm/xe/xe_drm_client.o
  CC [M]  drivers/gpu/drm/ast/ast_dp501.o
  CC      mm/zsmalloc.o
  CC      drivers/acpi/acpica/utobject.o
  CC      kernel/ksyms_common.o
  CC [M]  drivers/misc/mei/mei-trace.o
  CC      mm/early_ioremap.o
  CC      net/mptcp/mptcp_pm_gen.o
  CC      arch/x86/kernel/setup_percpu.o
  CC      net/mptcp/syncookies.o
  CC      drivers/acpi/acpica/utosi.o
  CC      mm/balloon_compaction.o
  CC      net/ipv4/ping.o
  CC      arch/x86/kernel/mpparse.o
  CC      net/devres.o
  CC [M]  net/bridge/br_fdb.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.o
  CC      fs/btrfs/export.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_display.o
  CC      drivers/base/module.o
  CC      net/ipv6/xfrm6_protocol.o
  CC [M]  fs/smb/client/smb2file.o
  CC [M]  net/netfilter/nft_nat.o
  CC      lib/win_minmax.o
  CC [M]  net/netfilter/nft_chain_nat.o
  CC [M]  net/netfilter/x_tables.o
  CC      kernel/groups.o
  CC [M]  drivers/gpu/drm/i915/intel_clock_gating.o
  CC      drivers/acpi/acpica/utownerid.o
  CC [M]  net/netfilter/xt_tcpudp.o
  CC [M]  drivers/gpu/drm/radeon/radeon_cursor.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/timer.o
  CC      drivers/base/hypervisor.o
  CC      drivers/nvdimm/badrange.o
  AR      net/handshake/built-in.a
  CC      drivers/mfd/wm8350-irq.o
  CC [M]  net/netfilter/xt_nat.o
  CC [M]  net/netfilter/xt_MASQUERADE.o
  CC      drivers/acpi/acpica/utpredef.o
  CC [M]  drivers/misc/mei/pci-me.o
  CC [M]  drivers/gpu/drm/ast/ast_dp.o
  CC      net/mptcp/bpf.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/vmm.o
  CC [M]  drivers/gpu/drm/radeon/radeon_i2c.o
  CC [M]  drivers/gpu/drm/xe/xe_exec.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/user.o
  CC      mm/secretmem.o
  CC      drivers/base/pinctrl.o
  CC      drivers/acpi/acpica/utresdecode.o
  CC [M]  drivers/gpu/drm/xe/xe_execlist.o
  CC      drivers/acpi/acpica/utresrc.o
  CC      drivers/base/devcoredump.o
  CC      arch/x86/kernel/ftrace.o
  CC [M]  drivers/misc/mei/hw-me.o
  CC [M]  fs/smb/client/cifsacl.o
  CC [M]  drivers/gpu/drm/i915/intel_device_info.o
  CC [M]  drivers/gpu/drm/i915/intel_memory_region.o
  CC [M]  net/netfilter/xt_addrtype.o
  CC      fs/pnode.o
  CC      kernel/vhost_task.o
  CC      lib/xarray.o
  CC [M]  sound/soc/sof/ipc3-control.o
  CC      drivers/mfd/wm8350-i2c.o
  CC [M]  drivers/gpu/drm/nouveau/nvif/userc361.o
  CC [M]  drivers/gpu/drm/i915/intel_pcode.o
  CC [M]  sound/soc/sof/ipc3-pcm.o
  CC [M]  drivers/misc/mei/gsc-me.o
  CC      fs/btrfs/tree-log.o
  LD [M]  drivers/misc/mei/mei.o
  CC      drivers/acpi/acpica/utstate.o
  CC [M]  drivers/gpu/drm/i915/intel_region_ttm.o
  CC      drivers/acpi/acpica/utstring.o
  CC [M]  net/bridge/br_forward.o
  CC      fs/btrfs/free-space-cache.o
  CC [M]  net/bridge/br_if.o
  LD [M]  drivers/gpu/drm/ast/ast.o
  CC      drivers/dma-buf/dma-buf.o
  CC      drivers/dma-buf/heaps/system_heap.o
  AR      drivers/cxl/core/built-in.a
  CC [M]  drivers/cxl/core/port.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/client.o
  CC [M]  drivers/cxl/acpi.o
  CC [M]  drivers/gpu/drm/xe/xe_exec_queue.o
  CC      drivers/dma-buf/dma-fence.o
  CC      kernel/kcmp.o
  CC      drivers/acpi/acpica/utstrsuppt.o
  CC [M]  drivers/gpu/drm/i915/intel_runtime_pm.o
  CC [M]  net/netfilter/xt_conntrack.o
  CC [M]  fs/smb/client/fs_context.o
  CC      mm/userfaultfd.o
  AR      net/mptcp/built-in.a
  CC [M]  fs/smb/client/dns_resolve.o
  CC [M]  drivers/cxl/core/pmem.o
  CC      drivers/nvdimm/claim.o
  CC      lib/lockref.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.o
  AS      arch/x86/kernel/ftrace_64.o
  CC      drivers/base/platform-msi.o
  CC      lib/bcd.o
  CC [M]  drivers/gpu/drm/radeon/radeon_clocks.o
  CC [M]  drivers/gpu/drm/radeon/radeon_gem.o
  AR      drivers/macintosh/built-in.a
  CC      lib/sort.o
  CC [M]  drivers/macintosh/mac_hid.o
  CC [M]  net/sunrpc/socklib.o
  CC      drivers/acpi/acpica/utstrtoul64.o
  CC      net/ipv6/netfilter.o
  CC      drivers/mfd/tps65910.o
  CC      drivers/acpi/acpica/utxface.o
  CC      net/ipv6/fib6_rules.o
  ASN.1   fs/smb/client/cifs_spnego_negtokeninit.asn1.[ch]
  CC      lib/parser.o
  CC      kernel/freezer.o
  CC [M]  sound/soc/sof/ipc3-dtrace.o
  CC      lib/debug_locks.o
  CC      net/ipv4/ip_tunnel_core.o
  CC [M]  drivers/gpu/drm/radeon/radeon_ring.o
  CC      arch/x86/kernel/trace_clock.o
  CC      net/ipv4/gre_offload.o
  AR      drivers/dma-buf/heaps/built-in.a
  CC      drivers/base/physical_location.o
  CC      kernel/profile.o
  CC      drivers/gpu/drm/drm_mipi_dsi.o
  CC [M]  drivers/gpu/drm/i915/intel_sbi.o
  CC [M]  drivers/gpu/drm/i915/intel_step.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/engine.o
  AR      drivers/misc/built-in.a
  CC      drivers/nvdimm/btt_devs.o
  CC      arch/x86/kernel/trace.o
  CC      drivers/nvdimm/pfn_devs.o
  CC      drivers/dma-buf/dma-fence-array.o
  CC      drivers/base/trace.o
  CC      drivers/nvdimm/dax_devs.o
  CC      drivers/acpi/acpica/utxfinit.o
  CC [M]  drivers/gpu/drm/i915/intel_uncore.o
  CC [M]  drivers/gpu/drm/drm_aperture.o
  CC [M]  drivers/gpu/drm/i915/intel_wakeref.o
  CC [M]  net/bridge/br_input.o
  CC [M]  drivers/gpu/drm/xe/xe_force_wake.o
  CC      lib/random32.o
  CC [M]  net/bridge/br_ioctl.o
  CC      drivers/mfd/tps65912-core.o
  CC [M]  net/bridge/br_stp.o
  AR      drivers/scsi/device_handler/built-in.a
  LD [M]  drivers/misc/mei/mei-gsc.o
  CC [M]  fs/smb/client/namespace.o
  LD [M]  drivers/misc/mei/mei-me.o
  CC [M]  drivers/scsi/device_handler/scsi_dh_rdac.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.o
  CC [M]  drivers/cxl/core/regs.o
  CC [M]  net/bridge/br_stp_bpdu.o
  CC [M]  net/bridge/br_stp_if.o
  CC [M]  net/bridge/br_stp_timer.o
  CC      drivers/dma-buf/dma-fence-chain.o
  CC      drivers/acpi/acpica/utxferror.o
  CC      drivers/acpi/acpica/utxfmutex.o
  CC [M]  sound/soc/sof/ipc4.o
  CC      mm/page_idle.o
  CC      drivers/acpi/acpica/dbcmds.o
  CC      arch/x86/kernel/rethook.o
  CC [M]  drivers/gpu/drm/radeon/radeon_irq_kms.o
  LD [M]  net/netfilter/nf_conntrack.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/enum.o
  CC [M]  net/bridge/br_netlink.o
  AR      drivers/base/built-in.a
  LD [M]  net/netfilter/nf_nat.o
  CC [M]  drivers/gpu/drm/i915/vlv_sideband.o
  LD [M]  net/netfilter/nf_tables.o
  CC      fs/splice.o
  CC [M]  drivers/gpu/drm/drm_atomic.o
  CC [M]  drivers/gpu/drm/radeon/radeon_cs.o
  AR      net/netfilter/built-in.a
  CC      mm/usercopy.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/event.o
  CC      lib/bust_spinlocks.o
  CC      drivers/dma-buf/dma-fence-unwrap.o
  CC      lib/kasprintf.o
  CC      net/socket.o
  CC      drivers/mfd/tps65912-i2c.o
  CC      kernel/stacktrace.o
  CC      net/ipv6/proc.o
  CC      kernel/dma.o
  CC [M]  net/sunrpc/xprtsock.o
  CC [M]  drivers/gpu/drm/xe/xe_ggtt.o
  CC      net/ipv6/syncookies.o
  AR      drivers/nvme/common/built-in.a
  CC      drivers/ata/libata-core.o
  CC      drivers/nvme/host/core.o
  CC      drivers/spi/spi.o
  CC      arch/x86/kernel/crash_core_64.o
  CC [M]  drivers/scsi/device_handler/scsi_dh_emc.o
  CC      drivers/acpi/acpica/dbconvert.o
  CC      drivers/spi/spi-mem.o
  CC      drivers/acpi/acpica/dbdisply.o
  CC      drivers/acpi/acpica/dbexec.o
  AR      drivers/nvme/target/built-in.a
  CC      kernel/smp.o
  CC      drivers/nvdimm/security.o
  CC      kernel/uid16.o
  CC      drivers/nvdimm/e820.o
  CC [M]  net/sunrpc/sched.o
  CC [M]  drivers/scsi/device_handler/scsi_dh_alua.o
  CC      lib/bitmap.o
  CC      lib/scatterlist.o
  CC [M]  fs/smb/client/smb1ops.o
  AR      drivers/scsi/megaraid/built-in.a
  CC [M]  net/bridge/br_netlink_tunnel.o
  CC [M]  fs/smb/client/cifssmb.o
  CC      mm/memremap.o
  CC [M]  drivers/gpu/drm/radeon/radeon_bios.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_ring.o
  CC      drivers/dma-buf/dma-resv.o
  CC [M]  drivers/cxl/core/memdev.o
  CC      net/ipv6/calipso.o
  CC      drivers/mfd/tps65912-spi.o
  CC      net/ipv6/seg6_iptunnel.o
  CC [M]  drivers/cxl/core/mbox.o
  CC      net/ipv4/metrics.o
  CC      drivers/mfd/twl-core.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/firmware.o
  CC      fs/btrfs/zlib.o
  CC      arch/x86/kernel/machine_kexec_64.o
  CC [M]  sound/soc/sof/ipc4-loader.o
  AS      arch/x86/kernel/relocate_kernel_64.o
  CC      mm/hmm.o
  CC      drivers/acpi/acpica/dbhistry.o
  CC      kernel/module_signature.o
  CC      kernel/kallsyms.o
  CC      net/compat.o
  CC      drivers/ata/libata-scsi.o
  CC      mm/memfd.o
  CC [M]  drivers/gpu/drm/xe/xe_gpu_scheduler.o
  CC      net/ipv4/netlink.o
  CC      net/sysctl_net.o
  CC [M]  net/bridge/br_arp_nd_proxy.o
  CC [M]  net/bridge/br_sysfs_if.o
  CC      kernel/acct.o
  CC      lib/list_sort.o
  CC      drivers/dma-buf/dma-heap.o
  AR      drivers/nvdimm/built-in.a
  CC      lib/uuid.o
  CC      drivers/acpi/acpica/dbinput.o
  HOSTCC  drivers/gpu/drm/xe/xe_gen_wa_oob
  CC      drivers/net/phy/mdio-boardinfo.o
  CC [M]  drivers/net/phy/aquantia/aquantia_main.o
  CC [M]  fs/smb/client/cifs_spnego_negtokeninit.asn1.o
  CC [M]  fs/smb/client/asn1.o
  CC      lib/iov_iter.o
  CC [M]  drivers/gpu/drm/xe/xe_gsc_proxy.o
  CC [M]  drivers/gpu/drm/radeon/radeon_benchmark.o
  CC      drivers/acpi/acpica/dbmethod.o
  CC      fs/sync.o
  CC      fs/btrfs/lzo.o
  CC      fs/utimes.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/gpuobj.o
  CC [M]  drivers/gpu/drm/i915/vlv_suspend.o
  CC      net/ipv6/seg6_local.o
  CC [M]  drivers/scsi/mpt3sas/mpt3sas_base.o
  CC      arch/x86/kernel/crash.o
  CC [M]  drivers/scsi/mpt3sas/mpt3sas_config.o
  CC      drivers/scsi/scsi.o
  CC [M]  sound/soc/sof/ipc4-topology.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_cs.o
  CC      drivers/dma-buf/sync_file.o
  CC      kernel/crash_core.o
  CC      kernel/kexec_core.o
  CC [M]  drivers/gpu/drm/i915/soc/intel_dram.o
  CC      lib/clz_ctz.o
  CC      fs/d_path.o
  CC      fs/stack.o
  CC      drivers/acpi/acpica/dbnames.o
  CC [M]  drivers/gpu/drm/drm_atomic_uapi.o
  CC      drivers/mfd/twl4030-irq.o
  CC      kernel/kexec.o
  CC      lib/bsearch.o
  AR      drivers/message/fusion/built-in.a
  CC [M]  drivers/cxl/core/pci.o
  AR      drivers/message/built-in.a
  CC      net/ipv6/seg6_hmac.o
  AR      drivers/firewire/built-in.a
  CC [M]  drivers/net/phy/aquantia/aquantia_firmware.o
  CC      drivers/net/phy/stubs.o
  CC [M]  drivers/cxl/core/hdm.o
  CC [M]  net/sunrpc/auth.o
  CC      mm/ptdump.o
  CC [M]  net/bridge/br_sysfs_br.o
  CC [M]  drivers/gpu/drm/xe/xe_gsc_submit.o
  HOSTCC  drivers/gpu/drm/radeon/mkregtable
  CC [M]  drivers/gpu/drm/xe/xe_gt.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/intr.o
  CC      kernel/kexec_file.o
  CC      drivers/net/phy/mdio_devres.o
  CC      arch/x86/kernel/kexec-bzimage64.o
  CC      drivers/acpi/acpica/dbobject.o
  CC      net/ipv4/nexthop.o
  CC      drivers/mfd/twl6030-irq.o
  CC [M]  drivers/gpu/drm/radeon/rs400.o
  CC      kernel/compat.o
  CC      kernel/utsname.o
  CC      fs/fs_struct.o
  MKREG   drivers/gpu/drm/radeon/rs600_reg_safe.h
  CC      drivers/mfd/twl4030-audio.o
  CC      drivers/mfd/twl6040.o
  CC      fs/btrfs/zstd.o
  CC      lib/find_bit.o
  CC [M]  drivers/cxl/port.o
  CC      drivers/dma-buf/sw_sync.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.o
  CC      mm/page_reporting.o
  CC      drivers/acpi/acpica/dbstats.o
  CC      drivers/nvme/host/ioctl.o
  CC [M]  drivers/gpu/drm/i915/soc/intel_gmch.o
  CC      drivers/net/phy/phy.o
  CC      drivers/acpi/acpica/dbutils.o
  CC [M]  drivers/net/phy/aquantia/aquantia_hwmon.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/ioctl.o
  CC      drivers/acpi/acpica/dbxface.o
  CC      drivers/net/phy/phy-c45.o
  CC [M]  drivers/gpu/drm/drm_auth.o
  CC [M]  net/bridge/br_nf_core.o
  CC      net/ipv4/udp_tunnel_stub.o
  CC [M]  sound/soc/sof/ipc4-control.o
  CC [M]  drivers/spi/spi-intel.o
  CC      fs/statfs.o
  CC [M]  sound/soc/sof/ipc4-pcm.o
  CC      drivers/acpi/acpica/rsdump.o
  CC      drivers/net/phy/phy-core.o
  CC      arch/x86/kernel/crash_dump_64.o
  CC      lib/llist.o
  CC      lib/lwq.o
  LD [M]  fs/smb/client/cifs.o
  CC      kernel/user_namespace.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_ccs_mode.o
  CC [M]  drivers/gpu/drm/radeon/rs690.o
  CC      drivers/mfd/mfd-core.o
  CC [M]  drivers/gpu/drm/i915/soc/intel_pch.o
  CC      net/ipv6/ioam6_iptunnel.o
  CC      drivers/mfd/ezx-pcap.o
  CC      drivers/mfd/da903x.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_clock.o
  CC      fs/btrfs/compression.o
  CC [M]  drivers/spi/spi-intel-pci.o
  CC      lib/memweight.o
  CC      drivers/cdrom/cdrom.o
  CC      drivers/nvme/host/sysfs.o
  CC      drivers/nvme/host/pr.o
  CC      arch/x86/kernel/module.o
  CC      kernel/pid_namespace.o
  CC      drivers/dma-buf/sync_debug.o
  LD [M]  drivers/net/phy/aquantia/aquantia.o
  LD [M]  drivers/cxl/cxl_acpi.o
  LD [M]  drivers/cxl/cxl_port.o
  CC      net/ipv6/addrconf_core.o
  CC      lib/kfifo.o
  CC [M]  drivers/cxl/core/pmu.o
  CC      drivers/dma-buf/udmabuf.o
  CC [M]  net/sunrpc/auth_null.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.o
  AR      drivers/auxdisplay/built-in.a
  CC [M]  drivers/gpu/drm/i915/i915_memcpy.o
  AR      drivers/acpi/acpica/built-in.a
  CC [M]  drivers/cxl/core/cdat.o
  CC      drivers/ata/libata-eh.o
  CC      drivers/acpi/device_sysfs.o
  CC      drivers/acpi/device_pm.o
  CC [M]  drivers/gpu/drm/drm_blend.o
  CC      drivers/mfd/da9052-irq.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/memory.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/mm.o
  CC [M]  net/bridge/br_multicast.o
  CC [M]  drivers/gpu/drm/i915/i915_mm.o
  CC      mm/bootmem_info.o
  CC      drivers/net/phy/phy_device.o
  CC      drivers/net/phy/linkmode.o
  CC [M]  drivers/dma-buf/selftest.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_debugfs.o
  CC [M]  drivers/dma-buf/st-dma-fence.o
  CC [M]  drivers/dma-buf/st-dma-fence-chain.o
  CC      arch/x86/kernel/kgdb.o
  CC      arch/x86/kernel/early_printk.o
  CC [M]  net/sunrpc/auth_tls.o
  CC [M]  drivers/cxl/core/trace.o
  CC [M]  drivers/cxl/core/region.o
  MKREG   drivers/gpu/drm/radeon/rv515_reg_safe.h
  CC [M]  drivers/gpu/drm/radeon/r520.o
  CC [M]  drivers/gpu/drm/radeon/r600.o
  CC [M]  drivers/gpu/drm/i915/i915_sw_fence.o
  CC [M]  drivers/dma-buf/st-dma-fence-unwrap.o
  CC [M]  drivers/scsi/mpt3sas/mpt3sas_scsih.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_freq.o
  CC [M]  sound/soc/sof/ipc4-mtrace.o
  CC      net/ipv6/exthdrs_core.o
  CC      net/ipv6/ip6_checksum.o
  UPD     kernel/config_data
  CC [M]  drivers/gpu/drm/xe/xe_gt_idle.o
  CC      drivers/net/phy/mdio_bus.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/atombios_dp.o
  CC [M]  drivers/spi/spi-pxa2xx.o
  CC      lib/percpu-refcount.o
  CC      kernel/stop_machine.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_mcr.o
  CC      net/ipv6/ip6_icmp.o
  CC [M]  drivers/gpu/drm/drm_bridge.o
  CC      drivers/nvme/host/trace.o
  AR      mm/built-in.a
  CC      drivers/acpi/proc.o
  CC      drivers/nvme/host/multipath.o
  CC      drivers/acpi/bus.o
  CC      drivers/nvme/host/zns.o
  CC      drivers/acpi/glue.o
  CC      net/ipv4/sysctl_net_ipv4.o
  CC [M]  drivers/scsi/mpt3sas/mpt3sas_transport.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/object.o
  CC      fs/btrfs/delayed-ref.o
  CC      drivers/mfd/da9052-core.o
  CC      drivers/mfd/da9052-spi.o
  CC [M]  drivers/gpu/drm/drm_cache.o
  CC [M]  drivers/gpu/drm/i915/i915_sw_fence_work.o
  CC [M]  drivers/gpu/drm/drm_client.o
  CC [M]  drivers/scsi/mpt3sas/mpt3sas_ctl.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_afmt.o
  CC      arch/x86/kernel/hpet.o
  CC [M]  drivers/dma-buf/st-dma-resv.o
  CC      arch/x86/kernel/amd_nb.o
  CC      net/ipv4/proc.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_pagefault.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_sysfs.o
  CC [M]  net/sunrpc/auth_unix.o
  CC [M]  drivers/gpu/drm/radeon/rv770.o
  CC      drivers/net/phy/mdio_device.o
  CC      drivers/nvme/host/hwmon.o
  CC [M]  sound/soc/sof/ipc4-telemetry.o
  CC      drivers/scsi/hosts.o
  CC [M]  drivers/gpu/drm/i915/i915_syncmap.o
  CC      fs/btrfs/relocation.o
  CC      net/ipv6/output_core.o
  AR      drivers/dma-buf/built-in.a
  CC      lib/rhashtable.o
  LD [M]  drivers/dma-buf/dmabuf_selftests.o
  CC [M]  drivers/gpu/drm/i915/i915_user_extensions.o
  CC      drivers/acpi/scan.o
  AR      drivers/cdrom/built-in.a
  CC [M]  drivers/spi/spi-pxa2xx-dma.o
  CC      drivers/net/pse-pd/pse_core.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_trace_points.o
  CC      drivers/usb/common/common.o
  CC      kernel/audit.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/oproxy.o
  CC      drivers/mfd/da9052-i2c.o
  CC      drivers/usb/common/debug.o
  CC      drivers/acpi/mipi-disco-img.o
  CC      drivers/nvme/host/pci.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/atombios_encoders.o
  CC      drivers/input/serio/serio.o
  CC      drivers/usb/core/usb.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_sa.o
  CC      drivers/usb/core/hub.o
  CC      fs/fs_pin.o
  CC      drivers/net/phy/swphy.o
  CC      drivers/net/phy/phy_led_triggers.o
  CC      net/ipv4/fib_rules.o
  CC [M]  sound/soc/sof/sof-client.o
  CC [M]  drivers/scsi/mpt3sas/mpt3sas_trigger_diag.o
  CC      fs/btrfs/delayed-inode.o
  CC [M]  net/sunrpc/svc.o
  CC      drivers/input/serio/i8042.o
  CC      fs/btrfs/scrub.o
  CC      drivers/usb/common/led.o
  CC [M]  drivers/gpu/drm/i915/i915_ioc32.o
  CC      drivers/net/mdio/acpi_mdio.o
  CC      drivers/net/mdio/fwnode_mdio.o
  CC      fs/btrfs/backref.o
  CC [M]  net/sunrpc/svcsock.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_throttle_sysfs.o
  CC [M]  drivers/spi/spi-pxa2xx-pci.o
  LD [M]  drivers/cxl/core/cxl_core.o
  AR      drivers/cxl/built-in.a
  CC      arch/x86/kernel/kvm.o
  CC      fs/btrfs/ulist.o
  CC [M]  drivers/scsi/mpt3sas/mpt3sas_warpdrive.o
  CC [M]  drivers/gpu/drm/i915/i915_debugfs.o
  CC      drivers/mfd/lp8788.o
  CC      drivers/mfd/lp8788-irq.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/option.o
  CC      drivers/ata/libata-transport.o
  CC      drivers/input/keyboard/atkbd.o
  AR      drivers/input/mouse/built-in.a
  CC [M]  drivers/gpu/drm/amd/amdgpu/atombios_i2c.o
  CC [M]  drivers/gpu/drm/radeon/radeon_test.o
  CC      net/ipv4/ipmr.o
  CC [M]  drivers/gpu/drm/i915/i915_debugfs_params.o
  CC [M]  drivers/gpu/drm/i915/i915_pmu.o
  AR      drivers/net/pse-pd/built-in.a
  AR      drivers/net/pcs/built-in.a
  MKREG   drivers/gpu/drm/radeon/r200_reg_safe.h
  CC [M]  drivers/scsi/mpt3sas/mpt3sas_debugfs.o
  CC      fs/nsfs.o
  CC      drivers/acpi/resource.o
  CC      drivers/net/phy/mii_timestamper.o
  CC      drivers/net/phy/bcm84881.o
  CC      lib/base64.o
  CC      drivers/input/serio/libps2.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_tlb_invalidation.o
  CC      net/ipv6/protocol.o
  LD [M]  drivers/spi/spi-pxa2xx-platform.o
  AR      drivers/usb/common/built-in.a
  AR      drivers/spi/built-in.a
  CC [M]  drivers/gpu/drm/i915/gt/gen2_engine_cs.o
  CC      drivers/mfd/da9055-core.o
  CC      drivers/mfd/da9055-i2c.o
  CC      drivers/mfd/da9063-core.o
  AR      drivers/usb/phy/built-in.a
  CC      drivers/scsi/scsi_ioctl.o
  AR      drivers/net/ethernet/8390/built-in.a
  AR      drivers/net/ethernet/3com/built-in.a
  CC      lib/once.o
  AR      drivers/net/ethernet/adaptec/built-in.a
  CC      lib/refcount.o
  CC      drivers/mfd/da9063-irq.o
  AR      drivers/net/ethernet/adi/built-in.a
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/ramht.o
  AR      drivers/net/ethernet/agere/built-in.a
  CC      drivers/mfd/da9063-i2c.o
  CC      drivers/scsi/scsicam.o
  AR      drivers/net/ethernet/alacritech/built-in.a
  CC      lib/rcuref.o
  CC [M]  sound/soc/sof/sof-utils.o
  CC      drivers/acpi/acpi_processor.o
  AR      drivers/net/ethernet/alteon/built-in.a
  AR      drivers/net/mdio/built-in.a
  CC      drivers/acpi/processor_core.o
  AR      drivers/net/ethernet/amazon/built-in.a
  AR      drivers/net/ethernet/amd/built-in.a
  AR      drivers/net/ethernet/aquantia/built-in.a
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.o
  CC [M]  drivers/gpu/drm/radeon/radeon_legacy_tv.o
  CC      drivers/acpi/processor_pdc.o
  AR      drivers/input/keyboard/built-in.a
  AR      drivers/net/ethernet/arc/built-in.a
  CC      fs/fs_types.o
  AR      drivers/net/ethernet/asix/built-in.a
  AR      drivers/input/joystick/built-in.a
  CC      fs/fs_context.o
  CC      drivers/net/phy/fixed_phy.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/subdev.o
  AR      drivers/net/ethernet/atheros/built-in.a
  AR      drivers/input/tablet/built-in.a
  AR      drivers/net/ethernet/cadence/built-in.a
  CC      drivers/input/touchscreen/elants_i2c.o
  CC      drivers/acpi/ec.o
  AR      drivers/net/ethernet/broadcom/built-in.a
  CC [M]  net/sunrpc/svcauth.o
  CC      drivers/input/misc/uinput.o
  CC      drivers/mfd/max14577.o
  AR      drivers/net/ethernet/brocade/built-in.a
  AR      drivers/nvme/host/built-in.a
  CC      drivers/acpi/dock.o
  AR      drivers/nvme/built-in.a
  MKREG   drivers/gpu/drm/radeon/r600_reg_safe.h
  CC [M]  net/bridge/br_mdb.o
  AR      drivers/net/ethernet/cavium/common/built-in.a
  AR      drivers/net/ethernet/cavium/thunder/built-in.a
  CC      kernel/auditfilter.o
  CC [M]  net/sunrpc/svcauth_unix.o
  CC      net/ipv4/ipmr_base.o
  CC [M]  drivers/net/phy/bcm7xxx.o
  CC [M]  drivers/gpu/drm/i915/gt/gen6_engine_cs.o
  CC      drivers/acpi/pci_root.o
  CC [M]  net/sunrpc/addr.o
  AR      drivers/net/ethernet/cavium/liquidio/built-in.a
  CC      drivers/usb/dwc2/core.o
  CC      drivers/ata/libata-trace.o
  CC      drivers/usb/dwc2/core_intr.o
  AR      drivers/net/ethernet/cavium/octeon/built-in.a
  CC      drivers/usb/dwc2/platform.o
  AR      drivers/net/ethernet/cavium/built-in.a
  CC      arch/x86/kernel/kvmclock.o
  CC      fs/fs_parser.o
  CC      drivers/usb/host/pci-quirks.o
  AR      drivers/input/serio/built-in.a
  AR      drivers/net/ethernet/chelsio/built-in.a
  CC      drivers/usb/core/hcd.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_topology.o
  CC      drivers/usb/host/ehci-hcd.o
  AR      drivers/net/ethernet/cirrus/built-in.a
  CC      lib/usercopy.o
  CC      drivers/usb/host/ehci-pci.o
  CC      drivers/usb/dwc2/drd.o
  AR      drivers/net/ethernet/cisco/built-in.a
  CC      drivers/ata/libata-sata.o
  AR      drivers/net/ethernet/cortina/built-in.a
  CC [M]  sound/soc/sof/sof-pci-dev.o
  AR      drivers/net/ethernet/dec/tulip/built-in.a
  CC      drivers/usb/dwc2/params.o
  AR      drivers/net/ethernet/dec/built-in.a
  CC [M]  drivers/net/phy/bcm87xx.o
  CC      fs/btrfs/qgroup.o
  AR      drivers/net/ethernet/dlink/built-in.a
  LD [M]  drivers/scsi/mpt3sas/mpt3sas.o
  AR      drivers/net/ethernet/emulex/built-in.a
  CC      drivers/usb/core/urb.o
  CC      drivers/usb/core/message.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/core/uevent.o
  AR      drivers/net/ethernet/engleder/built-in.a
  CC [M]  drivers/gpu/drm/radeon/radeon_pm.o
  AR      drivers/net/ethernet/ezchip/built-in.a
  CC [M]  drivers/gpu/drm/radeon/atombios_dp.o
  CC      net/ipv6/ip6_offload.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.o
  AR      drivers/net/ethernet/fungible/built-in.a
  CC      drivers/scsi/scsi_error.o
  AR      drivers/input/misc/built-in.a
  CC      net/ipv6/tcpv6_offload.o
  CC      lib/errseq.o
  AR      drivers/net/ethernet/google/built-in.a
  AR      drivers/net/ethernet/huawei/built-in.a
  CC      drivers/acpi/pci_link.o
  CC      drivers/input/input.o
  CC [M]  drivers/net/ethernet/intel/e1000/e1000_main.o
  CC [M]  drivers/net/ethernet/intel/e1000e/82571.o
  AR      drivers/input/touchscreen/built-in.a
  GEN     xe_wa_oob.c xe_wa_oob.h
  CC [M]  drivers/gpu/drm/xe/xe_guc_ads.o
  CC [M]  drivers/net/ethernet/intel/e1000/e1000_hw.o
  CC      lib/bucket_locks.o
  CC      lib/generic-radix-tree.o
  CC      drivers/input/input-compat.o
  CC      net/ipv6/exthdrs_offload.o
  CC [M]  drivers/net/phy/bcm-phy-lib.o
  CC      drivers/usb/dwc2/hcd.o
  CC      fs/btrfs/send.o
  CC      drivers/rtc/lib.o
  CC      drivers/rtc/class.o
  CC [M]  drivers/gpu/drm/i915/gt/gen6_ppgtt.o
  CC      drivers/rtc/interface.o
  CC      drivers/mfd/max77693.o
  CC      fs/fsopen.o
  CC      fs/init.o
  CC      net/ipv4/syncookies.o
  CC      drivers/usb/dwc2/hcd_intr.o
  CC      arch/x86/kernel/paravirt.o
  CC      net/ipv4/netfilter.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/nvfw/fw.o
  CC      drivers/usb/host/ehci-platform.o
  CC      kernel/auditsc.o
  CC [M]  net/bridge/br_multicast_eht.o
  CC [M]  net/sunrpc/rpcb_clnt.o
  CC [M]  drivers/gpu/drm/drm_client_modeset.o
  CC [M]  sound/soc/sof/sof-client-probes.o
  CC [M]  drivers/gpu/drm/drm_color_mgmt.o
  CC      drivers/rtc/nvmem.o
  CC      drivers/acpi/pci_irq.o
  CC      drivers/usb/core/driver.o
  CC      net/ipv4/tcp_cubic.o
  CC      fs/kernel_read_file.o
  CC      lib/bitmap-str.o
  CC      lib/string_helpers.o
  CC      drivers/input/input-mt.o
  CC      lib/hexdump.o
  CC      kernel/audit_watch.o
  CC      drivers/ata/libata-sff.o
  CC      drivers/mfd/max77843.o
  CC      net/ipv6/inet6_hashtables.o
  CC [M]  net/bridge/br_switchdev.o
  CC [M]  drivers/gpu/drm/radeon/r600_hdmi.o
  CC      drivers/rtc/dev.o
  CC      fs/mnt_idmapping.o
  CC      drivers/rtc/proc.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_ct.o
  CC [M]  drivers/net/ethernet/intel/e1000e/ich8lan.o
  CC [M]  drivers/net/ethernet/intel/e1000e/80003es2lan.o
  CC [M]  net/bridge/br_mrp_switchdev.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/nvfw/hs.o
  CC [M]  drivers/net/ethernet/intel/igb/igb_main.o
  CC [M]  drivers/gpu/drm/i915/gt/gen7_renderclear.o
  CC      net/ipv6/mcast_snoop.o
  CC [M]  net/sunrpc/timer.o
  CC [M]  sound/soc/sof/sof-client-probes-ipc3.o
  AR      drivers/i2c/algos/built-in.a
  CC [M]  drivers/net/phy/bcm-phy-ptp.o
  CC      fs/remap_range.o
  CC [M]  drivers/i2c/algos/i2c-algo-bit.o
  CC      drivers/acpi/acpi_lpss.o
  CC [M]  sound/soc/sof/sof-client-probes-ipc4.o
  CC [M]  drivers/net/phy/broadcom.o
  LD [M]  sound/soc/sof/snd-sof.o
  CC      arch/x86/kernel/paravirt-spinlocks.o
  CC      drivers/scsi/scsi_lib.o
  CC      drivers/rtc/sysfs.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/nvfw/ls.o
  CC      drivers/rtc/rtc-mc146818-lib.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.o
  CC      drivers/mfd/max8925-core.o
  CC      drivers/rtc/rtc-cmos.o
  CC [M]  net/bridge/br_mrp.o
  CC [M]  net/sunrpc/xdr.o
  CC      drivers/scsi/constants.o
  CC      fs/buffer.o
  CC      arch/x86/kernel/pvclock.o
  CC      drivers/usb/host/ohci-hcd.o
  CC      drivers/input/input-poller.o
  CC [M]  drivers/net/ethernet/intel/e1000/e1000_ethtool.o
  CC      net/ipv4/tcp_sigpool.o
  CC      drivers/input/ff-core.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/nvfw/acr.o
  CC [M]  drivers/gpu/drm/radeon/dce3_1_afmt.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/nvfw/flcn.o
  CC      lib/kstrtox.o
  CC      net/ipv4/tcp_bpf.o
  CC      drivers/usb/core/config.o
  CC [M]  net/bridge/br_mrp_netlink.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/falcon/base.o
  CC      drivers/input/touchscreen.o
  CC      drivers/input/vivaldi-fmap.o
  CC      drivers/usb/dwc2/hcd_queue.o
  CC [M]  drivers/gpu/drm/i915/gt/gen8_engine_cs.o
  LD [M]  sound/soc/sof/snd-sof-utils.o
  LD [M]  sound/soc/sof/snd-sof-pci.o
  LD [M]  sound/soc/sof/snd-sof-probes.o
  CC [M]  net/sunrpc/sunrpc_syms.o
  CC      drivers/scsi/scsi_lib_dma.o
  CC      net/ipv4/udp_bpf.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_db_mgr.o
  CC      drivers/usb/core/file.o
  CC      drivers/acpi/acpi_apd.o
  CC      drivers/ata/libata-pmp.o
  CC      kernel/audit_fsnotify.o
  CC      drivers/mfd/max8925-i2c.o
  CC [M]  drivers/net/phy/lxt.o
  CC      drivers/acpi/acpi_platform.o
  CC      drivers/scsi/scsi_scan.o
  CC      drivers/input/mousedev.o
  AR      net/ipv6/built-in.a
  CC      drivers/usb/core/buffer.o
  CC      arch/x86/kernel/pmem.o
  CC      lib/debug_info.o
  AR      drivers/rtc/built-in.a
  CC [M]  drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.o
  CC      drivers/i2c/busses/i2c-designware-common.o
  AR      drivers/i3c/built-in.a
  CC [M]  net/sunrpc/cache.o
  CC [M]  drivers/net/ethernet/intel/e1000e/mac.o
  CC      lib/iomap.o
  CC      drivers/i2c/busses/i2c-designware-master.o
  CC [M]  drivers/gpu/drm/radeon/evergreen.o
  CC      drivers/ata/libata-acpi.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_ib.o
  CC [M]  drivers/net/ethernet/intel/e1000e/manage.o
  CC [M]  drivers/net/ethernet/intel/e1000e/nvm.o
  CC      drivers/usb/core/sysfs.o
  CC      drivers/usb/storage/scsiglue.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/falcon/fw.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/falcon/msgq.o
  GEN     drivers/scsi/scsi_devinfo_tbl.c
  CC [M]  net/sunrpc/rpc_pipe.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_pll.o
  AR      drivers/net/fddi/built-in.a
  CC      drivers/usb/core/endpoint.o
  CC      drivers/usb/storage/protocol.o
  CC      fs/btrfs/dev-replace.o
  CC      drivers/mfd/max8997.o
  CC [M]  net/bridge/br_cfm.o
  CC      drivers/usb/dwc2/hcd_ddma.o
  CC      arch/x86/kernel/jailhouse.o
  CC [M]  net/sunrpc/sysfs.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_debugfs.o
  CC [M]  drivers/net/ethernet/intel/e1000/e1000_param.o
  CC      kernel/audit_tree.o
  CC      arch/x86/kernel/eisa.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_hwconfig.o
  CC [M]  drivers/net/phy/realtek.o
  CC      drivers/input/evdev.o
  CC [M]  drivers/gpu/drm/i915/gt/gen8_ppgtt.o
  CC      drivers/ata/libata-zpodd.o
  CC [M]  drivers/net/phy/smsc.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.o
  CC      drivers/acpi/acpi_pnp.o
  CC      drivers/scsi/scsi_devinfo.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/falcon/v1.o
  CC [M]  net/sunrpc/svc_xprt.o
  CC      drivers/ata/libata-pata-timings.o
  CC [M]  drivers/net/ethernet/intel/e1000e/phy.o
  CC      drivers/usb/core/devio.o
  CC      drivers/acpi/power.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.o
  CC      drivers/usb/core/notify.o
  CC      arch/x86/kernel/pcspeaker.o
  CC      arch/x86/kernel/check.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_log.o
  AR      drivers/net/ethernet/i825xx/built-in.a
  CC      drivers/usb/host/ohci-pci.o
  CC      lib/pci_iomap.o
  CC      drivers/usb/host/ohci-platform.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.o
  CC      drivers/usb/host/uhci-hcd.o
  CC      drivers/ata/ahci.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.o
  CC      net/ipv4/cipso_ipv4.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_pc.o
  CC      drivers/i2c/busses/i2c-designware-platdrv.o
  AR      drivers/net/ethernet/microsoft/built-in.a
  AR      drivers/net/ethernet/litex/built-in.a
  CC      drivers/usb/dwc2/debugfs.o
  CC [M]  drivers/net/ethernet/intel/e1000e/param.o
  AR      drivers/net/ethernet/marvell/octeon_ep/built-in.a
  CC      fs/btrfs/raid56.o
  AR      drivers/net/ethernet/mellanox/built-in.a
  CC      arch/x86/kernel/uprobes.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/falcon/gm200.o
  CC      arch/x86/kernel/perf_regs.o
  AR      drivers/net/ethernet/marvell/octeontx2/built-in.a
  LD [M]  drivers/net/ethernet/intel/e1000/e1000.o
  CC      drivers/mfd/max8997-irq.o
  AR      drivers/net/ethernet/marvell/prestera/built-in.a
  CC      lib/iomap_copy.o
  AR      drivers/net/ethernet/marvell/built-in.a
  CC      kernel/kprobes.o
  CC [M]  net/sunrpc/xprtmultipath.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/falcon/gp102.o
  CC [M]  net/bridge/br_cfm_netlink.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/falcon/tu102.o
  CC      drivers/usb/storage/transport.o
  CC [M]  drivers/input/sparse-keymap.o
  CC      drivers/mfd/max8998.o
  AR      drivers/i2c/muxes/built-in.a
  CC [M]  net/bridge/br_netfilter_hooks.o
  CC      drivers/acpi/event.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_submit.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/falcon/ga100.o
  CC      arch/x86/kernel/tracepoint.o
  AR      drivers/net/ethernet/micrel/built-in.a
  CC      arch/x86/kernel/itmt.o
  CC      drivers/acpi/evged.o
  CC      lib/devres.o
  CC [M]  net/sunrpc/debugfs.o
  CC [M]  drivers/gpu/drm/xe/xe_heci_gsc.o
  MKREG   drivers/gpu/drm/radeon/evergreen_reg_safe.h
  CC [M]  drivers/gpu/drm/xe/xe_hw_engine.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_breadcrumbs.o
  CC      drivers/usb/core/generic.o
  CC      drivers/usb/core/quirks.o
  CC      arch/x86/kernel/umip.o
  CC      drivers/i2c/busses/i2c-designware-baytrail.o
  AR      drivers/net/phy/built-in.a
  AR      drivers/usb/dwc2/built-in.a
  AR      drivers/net/hamradio/built-in.a
  CC      drivers/scsi/scsi_sysctl.o
  CC      drivers/usb/serial/usb-serial.o
  AR      drivers/usb/misc/built-in.a
  CC      drivers/usb/serial/generic.o
  CC      drivers/usb/early/ehci-dbgp.o
  CC      arch/x86/kernel/unwind_frame.o
  CC      drivers/usb/early/xhci-dbc.o
  CC      drivers/usb/core/devices.o
  CC [M]  drivers/net/ethernet/intel/igb/igb_ethtool.o
  CC      drivers/ata/libahci.o
  CC [M]  drivers/input/input-leds.o
  CC      drivers/mfd/max8998-irq.o
  CC      drivers/net/ppp/ppp_generic.o
  CC      drivers/mfd/adp5520.o
  CC      drivers/acpi/sysfs.o
  CC      drivers/net/slip/slhc.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_sync.o
  MKREG   drivers/gpu/drm/radeon/cayman_reg_safe.h
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.o
  CC [M]  drivers/gpu/drm/radeon/evergreen_hdmi.o
  CC [M]  drivers/gpu/drm/radeon/radeon_trace_points.o
  CC      arch/x86/kernel/sev.o
  AR      drivers/net/wan/framer/built-in.a
  AR      drivers/net/wan/built-in.a
  CC      drivers/acpi/property.o
  CC      drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/falcon/ga102.o
  CC      drivers/net/ethernet/microchip/vcap/vcap_api.o
  CC [M]  net/bridge/br_netfilter_ipv6.o
  CC [M]  drivers/net/ethernet/intel/e1000e/ethtool.o
  CC [M]  drivers/gpu/drm/drm_connector.o
  CC [M]  drivers/i2c/busses/i2c-i801.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.o
  AR      drivers/media/i2c/built-in.a
  CC [M]  drivers/media/i2c/ov13858.o
  CC      drivers/acpi/acpi_cmos_rtc.o
  AR      drivers/media/tuners/built-in.a
  CC [M]  drivers/gpu/drm/drm_crtc.o
  CC [M]  drivers/gpu/drm/drm_displayid.o
  CC [M]  drivers/media/tuners/mc44s803.o
  CC [M]  drivers/input/joydev.o
  CC      drivers/acpi/x86/apple.o
  CC [M]  drivers/gpu/drm/drm_drv.o
  CC      net/ipv4/xfrm4_policy.o
  CC      drivers/usb/host/xhci.o
  CC      drivers/scsi/scsi_proc.o
  CC      drivers/scsi/scsi_debugfs.o
  CC      lib/check_signature.o
  CC [M]  drivers/gpu/drm/drm_dumb_buffers.o
  CC      drivers/usb/core/phy.o
  CC      drivers/usb/storage/usb.o
  CC      drivers/usb/serial/bus.o
  CC      drivers/usb/serial/console.o
  CC      fs/btrfs/uuid-tree.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_context.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.o
  CC      lib/interval_tree.o
  CC [M]  drivers/net/ethernet/intel/igc/igc_main.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_context_sseu.o
  CC [M]  drivers/net/ethernet/intel/igc/igc_mac.o
  CC      kernel/hung_task.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.o
  CC      drivers/acpi/x86/utils.o
  CC      drivers/usb/storage/initializers.o
  CC [M]  net/sunrpc/stats.o
  CC [M]  drivers/gpu/drm/radeon/ni.o
  CC      kernel/watchdog.o
  CC      drivers/usb/core/port.o
  CC      drivers/usb/core/hcd-pci.o
  CC [M]  drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.o
  AR      drivers/usb/early/built-in.a
  CC      drivers/mfd/tps6586x.o
  CC      lib/assoc_array.o
  CC      fs/btrfs/props.o
  CC      drivers/usb/serial/ftdi_sio.o
  CC [M]  drivers/media/i2c/ov13b10.o
  AR      drivers/pps/clients/built-in.a
  CC      drivers/usb/gadget/udc/core.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.o
  AR      drivers/pps/generators/built-in.a
  CC      drivers/pps/pps.o
  LD [M]  net/bridge/bridge.o
  CC      drivers/usb/gadget/udc/trace.o
  CC      drivers/pps/kapi.o
  CC      drivers/ata/ahci_platform.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_engine_cs.o
  CC      drivers/net/ethernet/microchip/vcap/vcap_tc.o
  LD [M]  net/bridge/br_netfilter.o
  CC      drivers/pps/sysfs.o
  AR      drivers/input/built-in.a
  CC      fs/mpage.o
  AR      drivers/i2c/busses/built-in.a
  CC      net/ipv4/xfrm4_state.o
  CC      drivers/i2c/i2c-boardinfo.o
  CC      drivers/usb/storage/sierra_ms.o
  CC      drivers/i2c/i2c-core-base.o
  CC [M]  drivers/media/tuners/mt20xx.o
  CC      drivers/i2c/i2c-core-smbus.o
  CC      drivers/scsi/scsi_trace.o
  CC [M]  drivers/net/ethernet/intel/e1000e/netdev.o
  CC [M]  drivers/net/ethernet/intel/e1000e/ptp.o
  CC [M]  net/sunrpc/sysctl.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_engine_heartbeat.o
  CC [M]  drivers/net/ethernet/intel/igb/e1000_82575.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_engine_pm.o
  CC [M]  drivers/net/ethernet/intel/igbvf/vf.o
  AR      drivers/net/slip/built-in.a
  CC [M]  drivers/net/ethernet/intel/igbvf/mbx.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_main.o
  CC      drivers/usb/core/usb-acpi.o
  CC      arch/x86/kernel/callthunks.o
  CC      lib/list_debug.o
  CC [M]  drivers/gpu/drm/xe/xe_hw_fence.o
  CC      drivers/acpi/x86/s2idle.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_common.o
  CC [M]  drivers/net/ethernet/intel/igbvf/ethtool.o
  CC      drivers/usb/storage/option_ms.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_virt.o
  AR      drivers/usb/gadget/function/built-in.a
  CC      drivers/ata/libahci_platform.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.o
  CC [M]  drivers/gpu/drm/drm_edid.o
  CC      drivers/usb/roles/class.o
  CC [M]  drivers/gpu/drm/drm_eld.o
  CC      drivers/i2c/i2c-core-acpi.o
  AR      drivers/pps/built-in.a
  CC      lib/debugobjects.o
  CC      kernel/watchdog_perf.o
  CC      kernel/seccomp.o
  CC      drivers/usb/storage/usual-tables.o
  CC      fs/btrfs/free-space-tree.o
  CC      drivers/usb/serial/pl2303.o
  CC [M]  drivers/net/ethernet/intel/igc/igc_i225.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_engine_user.o
  CC      drivers/scsi/scsi_logging.o
  CC      net/ipv4/xfrm4_input.o
  CC      drivers/mfd/tps65090.o
  CC [M]  drivers/gpu/drm/radeon/atombios_encoders.o
  AR      drivers/net/ppp/built-in.a
  CC [M]  drivers/net/ethernet/intel/igbvf/netdev.o
  CC      drivers/acpi/debugfs.o
  CC      arch/x86/kernel/audit_64.o
  CC      arch/x86/kernel/amd_gart_64.o
  CC [M]  drivers/media/tuners/tuner-simple.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.o
  CC      drivers/acpi/acpi_lpat.o
  CC [M]  drivers/gpu/drm/xe/xe_huc.o
  AR      drivers/usb/gadget/udc/built-in.a
  AR      drivers/usb/storage/built-in.a
  AR      drivers/usb/gadget/legacy/built-in.a
  CC      drivers/i2c/i2c-dev.o
  CC      drivers/usb/gadget/usbstring.o
  CC [M]  drivers/net/ethernet/intel/igc/igc_base.o
  CC [M]  drivers/net/ethernet/intel/igb/e1000_mac.o
  CC      fs/proc_namespace.o
  LD [M]  net/sunrpc/sunrpc.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_execlists_submission.o
  AR      drivers/usb/core/built-in.a
  CC [M]  drivers/gpu/drm/i915/gt/intel_ggtt.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_ggtt_fencing.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.o
  AR      drivers/net/wireless/admtek/built-in.a
  AR      drivers/net/mctp/built-in.a
  AR      drivers/net/ethernet/microchip/vcap/built-in.a
  AR      drivers/net/ethernet/microchip/built-in.a
  AR      drivers/net/wireless/atmel/built-in.a
  CC [M]  drivers/net/usb/pegasus.o
  AR      drivers/net/wireless/ath/built-in.a
  CC [M]  drivers/net/usb/rtl8150.o
  CC      drivers/net/loopback.o
  AR      drivers/net/wireless/intel/built-in.a
  AR      drivers/net/wireless/broadcom/built-in.a
  CC [M]  drivers/i2c/i2c-smbus.o
  AR      drivers/usb/roles/built-in.a
  CC      net/ipv4/xfrm4_output.o
  AR      drivers/net/wireless/intersil/built-in.a
  CC [M]  drivers/i2c/i2c-mux.o
  CC      drivers/mfd/aat2870-core.o
  AR      drivers/usb/serial/built-in.a
  CC [M]  drivers/usb/class/usbtmc.o
  AR      drivers/net/wireless/marvell/built-in.a
  CC      drivers/usb/host/xhci-mem.o
  CC [M]  drivers/net/ethernet/intel/igb/e1000_nvm.o
  AR      drivers/net/wireless/mediatek/built-in.a
  CC      arch/x86/kernel/aperture_64.o
  CC      kernel/relay.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.o
  AR      drivers/net/wireless/microchip/built-in.a
  AR      drivers/net/wireless/purelifi/built-in.a
  AR      drivers/net/wireless/quantenna/built-in.a
  CC      lib/bitrev.o
  CC      drivers/usb/gadget/config.o
  AR      drivers/net/wireless/ralink/built-in.a
  CC [M]  drivers/usb/typec/ucsi/ucsi.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_82599.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.o
  AR      drivers/net/wireless/realtek/built-in.a
  CC      drivers/net/netconsole.o
  CC      drivers/net/tun.o
  CC [M]  drivers/gpu/drm/xe/xe_huc_debugfs.o
  AR      drivers/net/wireless/rsi/built-in.a
  CC      drivers/ata/ata_piix.o
  AR      drivers/net/wireless/silabs/built-in.a
  AR      drivers/media/rc/keymaps/built-in.a
  AR      drivers/net/wireless/st/built-in.a
  CC [M]  drivers/media/rc/rc-main.o
  AR      drivers/net/wireless/ti/built-in.a
  CC      fs/btrfs/tree-checker.o
  AR      drivers/net/wireless/zydas/built-in.a
  AR      drivers/net/wireless/virtual/built-in.a
  CC      drivers/net/virtio_net.o
  CC      drivers/usb/gadget/epautoconf.o
  AR      drivers/net/wireless/built-in.a
  CC [M]  drivers/gpu/drm/i915/gt/intel_gt.o
  CC      drivers/acpi/acpi_fpdt.o
  CC [M]  drivers/gpu/drm/xe/xe_irq.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.o
  CC      drivers/scsi/scsi_pm.o
  CC [M]  drivers/gpu/drm/xe/xe_lrc.o
  CC [M]  drivers/media/rc/rc-ir-raw.o
  CC      drivers/net/xen-netfront.o
  CC [M]  drivers/net/ethernet/intel/igc/igc_nvm.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.o
  CC [M]  drivers/gpu/drm/radeon/radeon_semaphore.o
  CC      drivers/mfd/intel-lpss.o
  CC [M]  drivers/net/usb/r8152.o
  CC      arch/x86/kernel/mmconf-fam10h_64.o
  CC      arch/x86/kernel/vsmp_64.o
  CC [M]  arch/x86/kernel/msr.o
  CC      net/ipv4/xfrm4_protocol.o
  CC [M]  drivers/net/ethernet/intel/igb/e1000_phy.o
  CC      lib/linear_ranges.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_gt_clock_utils.o
  CC      drivers/usb/gadget/composite.o
  LD [M]  drivers/net/ethernet/intel/igbvf/igbvf.o
  CC [M]  drivers/media/tuners/tuner-types.o
  CC [M]  drivers/net/usb/cdc_ether.o
  CC [M]  drivers/net/usb/cdc_eem.o
  CC      drivers/usb/gadget/functions.o
  CC [M]  drivers/media/rc/lirc_dev.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_sched.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/acr/gv100.o
  CC      drivers/acpi/acpi_lpit.o
  AR      drivers/i2c/built-in.a
  CC      drivers/ptp/ptp_clock.o
  CC      drivers/ptp/ptp_chardev.o
  CC      kernel/utsname_sysctl.o
  CC      drivers/scsi/scsi_dh.o
  CC [M]  drivers/net/ethernet/intel/igc/igc_phy.o
  CC      drivers/scsi/scsi_bsg.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.o
  CC      net/ipv4/bpf_tcp_ca.o
  CC      drivers/net/net_failover.o
  CC [M]  drivers/net/mii.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.o
  CC      drivers/ata/pata_sis.o
  CC      drivers/usb/host/xhci-ext-caps.o
  CC [M]  drivers/gpu/drm/radeon/radeon_sa.o
  CC      kernel/delayacct.o
  CC [M]  arch/x86/kernel/cpuid.o
  CC      drivers/usb/host/xhci-ring.o
  CC [M]  drivers/usb/typec/ucsi/debugfs.o
  CC [M]  drivers/gpu/drm/radeon/atombios_i2c.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_gt_debugfs.o
  LD [M]  drivers/net/ethernet/intel/e1000e/e1000e.o
  CC      drivers/mfd/intel-lpss-pci.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_gt_engines_debugfs.o
  CC [M]  drivers/net/ethernet/intel/ixgbevf/vf.o
  CC      fs/btrfs/space-info.o
  CC      drivers/usb/gadget/configfs.o
  CC      drivers/scsi/scsi_common.o
  CC      lib/packing.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.o
  CC      lib/crc-ccitt.o
  CC      fs/btrfs/block-rsv.o
  CC [M]  drivers/media/rc/keymaps/rc-cec.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_gt_irq.o
  CC      drivers/ptp/ptp_sysfs.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.o
  CC      drivers/ptp/ptp_vclock.o
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_main.o
  CC      kernel/taskstats.o
  CC [M]  drivers/net/ethernet/intel/igb/e1000_mbx.o
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_ethtool.o
  CC      drivers/acpi/prmt.o
  AR      arch/x86/kernel/built-in.a
  CC [M]  drivers/usb/typec/ucsi/trace.o
  AR      arch/x86/built-in.a
  CC      drivers/ata/ata_generic.o
  CC [M]  drivers/net/ethernet/intel/igc/igc_diag.o
  CC [M]  drivers/ata/acard-ahci.o
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_adminq.o
  CC      drivers/mfd/intel-lpss-acpi.o
  AR      drivers/media/rc/built-in.a
  CC [M]  drivers/media/tuners/tda18271-maps.o
  AR      drivers/media/common/b2c2/built-in.a
  AR      drivers/media/common/saa7146/built-in.a
  CC      drivers/scsi/virtio_scsi.o
  CC      lib/crc16.o
  AR      drivers/media/common/siano/built-in.a
  CC [M]  drivers/gpu/drm/radeon/si.o
  CC      lib/crc-t10dif.o
  LD [M]  drivers/media/rc/rc-core.o
  AR      drivers/media/common/v4l2-tpg/built-in.a
  CC [M]  drivers/net/mdio.o
  CC      drivers/usb/host/xhci-hub.o
  AR      drivers/media/common/videobuf2/built-in.a
  CC      drivers/usb/host/xhci-dbg.o
  AR      drivers/media/common/built-in.a
  CC      drivers/usb/gadget/u_f.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.o
  CC [M]  drivers/gpu/drm/radeon/radeon_prime.o
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_common.o
  CC [M]  drivers/media/tuners/tda18271-common.o
  CC      drivers/acpi/acpi_pcc.o
  AR      net/ipv4/built-in.a
  AR      net/built-in.a
  CC      drivers/scsi/sd.o
  CC      drivers/scsi/sd_dif.o
  CC      drivers/power/reset/restart-poweroff.o
  CC [M]  drivers/net/ethernet/intel/ixgbevf/mbx.o
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_hmc.o
  CC      drivers/mfd/palmas.o
  CC [M]  drivers/gpu/drm/radeon/cik.o
  CC [M]  drivers/gpu/drm/radeon/r600_dpm.o
  HOSTCC  lib/gen_crc32table
  CC [M]  drivers/gpu/drm/radeon/rs780_dpm.o
  CC      drivers/acpi/acpi_ffh.o
  CC [M]  drivers/usb/typec/ucsi/psy.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_ids.o
  CC [M]  drivers/net/ethernet/intel/igb/e1000_i210.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_gt_mcr.o
  HOSTCC  lib/gen_crc64table
  CC      kernel/tsacct.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.o
  AR      drivers/ptp/built-in.a
  CC [M]  drivers/gpu/drm/xe/xe_migrate.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.o
  CC      drivers/mfd/rc5t583.o
  CC [M]  drivers/net/ethernet/intel/igc/igc_ethtool.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.o
  CC [M]  drivers/ata/ahci_dwc.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_82598.o
  AR      drivers/power/reset/built-in.a
  CC      fs/btrfs/delalloc-space.o
  AR      drivers/net/ethernet/intel/built-in.a
  CC      fs/btrfs/block-group.o
  CC      drivers/power/supply/power_supply_core.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_phy.o
  AR      drivers/media/platform/allegro-dvt/built-in.a
  CC      lib/libcrc32c.o
  AR      drivers/media/platform/amlogic/meson-ge2d/built-in.a
  AR      drivers/media/platform/amlogic/built-in.a
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.o
  CC      lib/crc64-rocksoft.o
  AR      drivers/usb/gadget/built-in.a
  CC      kernel/tracepoint.o
  CC      drivers/usb/host/xhci-trace.o
  CC      drivers/usb/host/xhci-dbgcap.o
  AR      drivers/media/platform/amphion/built-in.a
  AR      drivers/media/platform/aspeed/built-in.a
  CC      drivers/acpi/acpi_adxl.o
  CC [M]  drivers/media/tuners/tda18271-fe.o
  CC [M]  drivers/media/tuners/tda827x.o
  CC [M]  drivers/usb/typec/ucsi/ucsi_acpi.o
  AR      drivers/media/platform/atmel/built-in.a
  CC      drivers/power/supply/power_supply_sysfs.o
  AR      drivers/media/platform/cadence/built-in.a
  CC      drivers/usb/host/xhci-dbgtty.o
  CC      drivers/usb/host/xhci-debugfs.o
  AR      drivers/media/platform/chips-media/coda/built-in.a
  AR      drivers/media/platform/chips-media/wave5/built-in.a
  CC [M]  drivers/net/veth.o
  AR      drivers/media/platform/chips-media/built-in.a
  CC [M]  drivers/net/ethernet/intel/ixgbevf/ethtool.o
  AR      drivers/media/platform/intel/built-in.a
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_lan_hmc.o
  AR      drivers/media/platform/marvell/built-in.a
  AR      drivers/media/platform/mediatek/jpeg/built-in.a
  AR      drivers/media/platform/mediatek/mdp/built-in.a
  CC      lib/xxhash.o
  AR      drivers/media/platform/mediatek/vcodec/common/built-in.a
  CC [M]  drivers/net/ethernet/intel/igb/igb_ptp.o
  AR      drivers/media/platform/mediatek/vcodec/encoder/built-in.a
  AR      drivers/media/platform/mediatek/vcodec/decoder/built-in.a
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.o
  CC [M]  drivers/gpu/drm/xe/xe_mmio.o
  AR      drivers/media/platform/mediatek/vcodec/built-in.a
  AR      drivers/media/platform/mediatek/vpu/built-in.a
  AR      drivers/media/platform/mediatek/mdp3/built-in.a
  AR      drivers/media/platform/mediatek/built-in.a
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_nvm.o
  CC      lib/genalloc.o
  AR      drivers/media/platform/nuvoton/built-in.a
  AR      drivers/media/platform/microchip/built-in.a
  AR      drivers/ata/built-in.a
  CC      drivers/mfd/rc5t583-irq.o
  CC      drivers/acpi/ac.o
  CC [M]  drivers/gpu/drm/radeon/rv6xx_dpm.o
  AR      drivers/media/platform/nvidia/tegra-vde/built-in.a
  CC      drivers/hwmon/hwmon.o
  AR      drivers/media/platform/nvidia/built-in.a
  CC      drivers/power/supply/power_supply_leds.o
  AR      drivers/media/platform/nxp/dw100/built-in.a
  LD [M]  drivers/usb/typec/ucsi/typec_ucsi.o
  CC      drivers/power/supply/power_supply_hwmon.o
  CC      drivers/acpi/button.o
  AR      drivers/media/platform/nxp/imx-jpeg/built-in.a
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.o
  CC [M]  drivers/usb/typec/class.o
  AR      drivers/media/platform/nxp/imx8-isi/built-in.a
  AR      drivers/media/platform/nxp/built-in.a
  CC [M]  drivers/usb/typec/mux.o
  CC [M]  drivers/usb/typec/bus.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_x540.o
  CC [M]  drivers/usb/typec/pd.o
  AR      drivers/media/platform/qcom/camss/built-in.a
  CC      drivers/scsi/sd_zbc.o
  AR      drivers/media/platform/qcom/venus/built-in.a
  CC      lib/percpu_counter.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_x550.o
  AR      drivers/media/platform/qcom/built-in.a
  CC [M]  drivers/gpu/drm/radeon/rv770_dpm.o
  CC      fs/btrfs/discard.o
  CC      kernel/irq_work.o
  AR      drivers/media/platform/renesas/rcar-vin/built-in.a
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_csa.o
  CC      fs/btrfs/reflink.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_gt_pm.o
  AR      drivers/media/platform/renesas/rzg2l-cru/built-in.a
  CC      kernel/static_call.o
  CC      drivers/usb/host/xhci-pci.o
  AR      drivers/media/platform/renesas/vsp1/built-in.a
  AR      drivers/media/platform/renesas/built-in.a
  CC      lib/iommu-helper.o
  AR      drivers/media/platform/rockchip/rga/built-in.a
  AR      drivers/media/platform/rockchip/rkisp1/built-in.a
  AR      drivers/media/platform/rockchip/built-in.a
  CC [M]  drivers/net/usb/smsc75xx.o
  CC [M]  drivers/media/tuners/tda8290.o
  AR      drivers/media/platform/samsung/exynos-gsc/built-in.a
  CC [M]  drivers/net/ethernet/intel/igc/igc_ptp.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.o
  CC      drivers/acpi/fan_core.o
  AR      drivers/media/platform/samsung/exynos4-is/built-in.a
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_lib.o
  CC      drivers/mfd/syscon.o
  AR      drivers/media/platform/samsung/s3c-camif/built-in.a
  CC [M]  drivers/hwmon/acpi_power_meter.o
  AR      drivers/media/platform/samsung/s5p-g2d/built-in.a
  CC [M]  drivers/net/usb/smsc95xx.o
  CC      drivers/power/supply/samsung-sdi-battery.o
  CC      drivers/mfd/as3711.o
  AR      drivers/media/platform/samsung/s5p-jpeg/built-in.a
  CC      drivers/mfd/intel_soc_pmic_crc.o
  AR      drivers/media/platform/samsung/s5p-mfc/built-in.a
  AR      drivers/media/platform/samsung/built-in.a
  CC [M]  drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.o
  CC [M]  drivers/gpu/drm/drm_encoder.o
  CC [M]  drivers/gpu/drm/xe/xe_mocs.o
  AR      drivers/media/platform/st/sti/bdisp/built-in.a
  AR      drivers/media/platform/st/sti/c8sectpfe/built-in.a
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_debugfs.o
  CC [M]  drivers/gpu/drm/xe/xe_module.o
  AR      drivers/media/platform/st/sti/delta/built-in.a
  CC [M]  drivers/gpu/drm/xe/xe_pat.o
  AR      drivers/media/platform/st/sti/hva/built-in.a
  CC [M]  drivers/gpu/drm/xe/xe_pci.o
  CC [M]  drivers/media/tuners/tda9887.o
  CC [M]  drivers/gpu/drm/xe/xe_pcode.o
  AR      drivers/media/platform/st/stm32/built-in.a
  CC [M]  drivers/net/ethernet/intel/igc/igc_dump.o
  CC [M]  drivers/net/ethernet/intel/igb/igb_hwmon.o
  AR      drivers/media/platform/st/built-in.a
  CC [M]  drivers/usb/typec/retimer.o
  CC      drivers/mfd/intel_soc_pmic_chtwc.o
  CC      drivers/power/supply/charger-manager.o
  CC [M]  drivers/mfd/lpc_ich.o
  CC [M]  drivers/gpu/drm/drm_file.o
  AR      drivers/media/platform/sunxi/sun4i-csi/built-in.a
  CC      drivers/acpi/fan_attr.o
  CC      lib/fault-inject.o
  CC      drivers/acpi/pci_slot.o
  AR      drivers/media/platform/sunxi/sun6i-csi/built-in.a
  CC      kernel/static_call_inline.o
  AR      drivers/media/platform/sunxi/sun6i-mipi-csi2/built-in.a
  AR      drivers/media/pci/ttpci/built-in.a
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_ras.o
  CC      drivers/scsi/sr.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.o
  AR      drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/built-in.a
  AR      drivers/media/pci/b2c2/built-in.a
  AR      drivers/media/platform/sunxi/sun8i-di/built-in.a
  AR      drivers/media/platform/sunxi/sun8i-rotate/built-in.a
  AR      drivers/media/platform/sunxi/built-in.a
  AR      drivers/media/pci/pluto2/built-in.a
  CC      drivers/scsi/sr_ioctl.o
  AR      drivers/media/platform/verisilicon/built-in.a
  CC [M]  drivers/hwmon/coretemp.o
  CC      drivers/scsi/sr_vendor.o
  CC [M]  drivers/usb/typec/port-mapper.o
  AR      drivers/media/platform/ti/am437x/built-in.a
  CC      drivers/acpi/processor_driver.o
  AR      drivers/media/pci/dm1105/built-in.a
  AR      drivers/media/platform/ti/cal/built-in.a
  CC [M]  drivers/gpu/drm/xe/xe_pm.o
  AR      drivers/media/platform/ti/davinci/built-in.a
  AR      drivers/media/pci/pt1/built-in.a
  AR      drivers/media/platform/ti/vpe/built-in.a
  AR      drivers/media/platform/ti/omap/built-in.a
  AR      drivers/media/platform/ti/j721e-csi2rx/built-in.a
  CC [M]  drivers/net/usb/rndis_host.o
  CC [M]  drivers/net/usb/mcs7830.o
  AR      drivers/media/pci/pt3/built-in.a
  AR      drivers/media/platform/ti/omap3isp/built-in.a
  AR      drivers/media/usb/b2c2/built-in.a
  AR      drivers/media/platform/ti/built-in.a
  AR      drivers/media/usb/dvb-usb/built-in.a
  AR      drivers/usb/host/built-in.a
  AR      drivers/media/pci/mantis/built-in.a
  CC [M]  drivers/net/usb/usbnet.o
  AR      drivers/media/usb/dvb-usb-v2/built-in.a
  CC [M]  drivers/net/usb/r8153_ecm.o
  CC [M]  drivers/gpu/drm/xe/xe_preempt_fence.o
  AR      drivers/media/pci/ngene/built-in.a
  AR      drivers/media/usb/s2255/built-in.a
  AR      drivers/media/platform/via/built-in.a
  AR      drivers/usb/built-in.a
  AR      drivers/media/pci/ddbridge/built-in.a
  AR      drivers/media/platform/xilinx/built-in.a
  AR      drivers/media/usb/siano/built-in.a
  CC      fs/btrfs/subpage.o
  AR      drivers/media/platform/built-in.a
  CC [M]  drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.o
  AR      drivers/media/pci/saa7146/built-in.a
  AR      drivers/media/pci/smipcie/built-in.a
  CC      fs/btrfs/tree-mod-log.o
  AR      drivers/media/usb/ttusb-budget/built-in.a
  AR      drivers/media/usb/ttusb-dec/built-in.a
  AR      drivers/media/pci/netup_unidvb/built-in.a
  AR      drivers/media/usb/built-in.a
  AR      drivers/media/pci/intel/ipu3/built-in.a
  CC      fs/btrfs/extent-io-tree.o
  CC      fs/btrfs/fs.o
  AR      drivers/media/pci/intel/ivsc/built-in.a
  AR      drivers/media/pci/intel/built-in.a
  AR      drivers/media/pci/built-in.a
  CC      fs/btrfs/messages.o
  CC      fs/btrfs/bio.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.o
  CC      lib/error-inject.o
  CC [M]  drivers/gpu/drm/radeon/rv730_dpm.o
  CC [M]  drivers/gpu/drm/drm_fourcc.o
  CC [M]  drivers/gpu/drm/xe/xe_pt.o
  CC      drivers/acpi/processor_thermal.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.o
  CC [M]  drivers/gpu/drm/xe/xe_pt_exec_queue.o
  CC      kernel/numa.o
  CC [M]  drivers/gpu/drm/xe/xe_pt_walk.o
  CC [M]  drivers/net/ethernet/intel/igc/igc_tsn.o
  AR      drivers/mfd/built-in.a
  CC      lib/syscall.o
  CC      lib/dynamic_debug.o
  CC [M]  drivers/gpu/drm/radeon/rv740_dpm.o
  CC [M]  drivers/net/ethernet/intel/e100.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_gt_pm_irq.o
  LD [M]  drivers/usb/typec/typec.o
  CC      lib/errname.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm107.o
  LD [M]  drivers/net/ethernet/intel/igb/igb.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.o
  CC      drivers/scsi/sg.o
  CC [M]  drivers/gpu/drm/drm_framebuffer.o
  CC [M]  drivers/gpu/drm/drm_gem.o
  AR      drivers/media/firewire/built-in.a
  AR      drivers/media/mmc/siano/built-in.a
  AR      drivers/media/mmc/built-in.a
  CC      drivers/acpi/processor_idle.o
  CC      fs/direct-io.o
  AR      drivers/hwmon/built-in.a
  CC      kernel/user-return-notifier.o
  AR      drivers/power/supply/built-in.a
  AR      drivers/power/built-in.a
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_diag.o
  CC      kernel/crash_dump.o
  CC      lib/nlattr.o
  CC [M]  drivers/net/ethernet/intel/igc/igc_xdp.o
  AR      drivers/net/ethernet/mscc/built-in.a
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.o
  CC      lib/cpu_rmap.o
  CC [M]  drivers/scsi/raid_class.o
  CC      kernel/jump_label.o
  CC      fs/eventpoll.o
  CC      fs/anon_inodes.o
  CC [M]  drivers/gpu/drm/xe/xe_query.o
  CC [M]  drivers/gpu/drm/drm_ioctl.o
  CC [M]  drivers/gpu/drm/drm_lease.o
  CC [M]  drivers/gpu/drm/xe/xe_range_fence.o
  CC [M]  drivers/media/tuners/tea5761.o
  CC [M]  drivers/gpu/drm/xe/xe_reg_sr.o
  AR      drivers/thermal/broadcom/built-in.a
  CC [M]  drivers/media/tuners/tea5767.o
  AR      drivers/media/spi/built-in.a
  AR      drivers/thermal/samsung/built-in.a
  CC      lib/dynamic_queue_limits.o
  CC [M]  drivers/thermal/intel/int340x_thermal/int3400_thermal.o
  CC      drivers/thermal/intel/intel_tcc.o
  CC      kernel/context_tracking.o
  AR      drivers/media/test-drivers/built-in.a
  CC [M]  drivers/media/v4l2-core/v4l2-async.o
  CC [M]  drivers/media/mc/mc-device.o
  CC [M]  drivers/media/v4l2-core/v4l2-fwnode.o
  CC      drivers/thermal/intel/therm_throt.o
  CC [M]  drivers/scsi/scsi_transport_sas.o
  CC      drivers/watchdog/watchdog_core.o
  CC      fs/btrfs/lru_cache.o
  CC [M]  drivers/gpu/drm/drm_managed.o
  CC [M]  drivers/gpu/drm/xe/xe_reg_whitelist.o
  CC [M]  drivers/gpu/drm/radeon/rv770_smc.o
  CC [M]  drivers/gpu/drm/radeon/cypress_dpm.o
  CC      lib/glob.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bar/tu102.o
  CC      drivers/thermal/intel/intel_hfi.o
  CC      fs/btrfs/raid-stripe-tree.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_gt_requests.o
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_txrx.o
  CC [M]  drivers/media/dvb-core/dvbdev.o
  LD [M]  drivers/net/ethernet/intel/ixgbevf/ixgbevf.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.o
  CC      fs/btrfs/acl.o
  CC      drivers/md/md.o
  LD [M]  drivers/net/ethernet/intel/igc/igc.o
  CC      lib/digsig.o
  CC      drivers/acpi/processor_throttling.o
  CC      drivers/md/md-bitmap.o
  CC [M]  drivers/gpu/drm/drm_mm.o
  CC [M]  drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.o
  CC      lib/strncpy_from_user.o
  CC      kernel/iomem.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bar/r535.o
  CC      drivers/acpi/processor_perflib.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.o
  CC      drivers/acpi/container.o
  CC [M]  drivers/scsi/ses.o
  CC [M]  drivers/gpu/drm/drm_mode_config.o
  CC      drivers/acpi/thermal_lib.o
  CC [M]  drivers/gpu/drm/drm_mode_object.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.o
  CC      drivers/acpi/thermal.o
  CC [M]  drivers/gpu/drm/xe/xe_rtp.o
  CC      kernel/rseq.o
  CC [M]  drivers/gpu/drm/xe/xe_ring_ops.o
  CC [M]  drivers/gpu/drm/drm_modes.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.o
  AR      drivers/accessibility/braille/built-in.a
  AR      drivers/isdn/hardware/built-in.a
  AR      drivers/accessibility/built-in.a
  AR      drivers/isdn/built-in.a
  CC [M]  drivers/media/cec/core/cec-core.o
  CC [M]  drivers/media/cec/core/cec-adap.o
  CC [M]  drivers/media/cec/core/cec-api.o
  CC [M]  drivers/media/mc/mc-devnode.o
  CC [M]  drivers/media/v4l2-core/v4l2-dv-timings.o
  CC      lib/strnlen_user.o
  CC      lib/net_utils.o
  CC [M]  drivers/media/tuners/xc2028.o
  CC      drivers/md/md-autodetect.o
  CC [M]  drivers/media/mc/mc-entity.o
  CC      drivers/md/dm-init.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_gt_sysfs.o
  CC      drivers/md/dm-uevent.o
  CC      fs/signalfd.o
  CC      fs/timerfd.o
  CC      lib/sg_pool.o
  CC      fs/btrfs/zoned.o
  CC      drivers/watchdog/watchdog_dev.o
  CC      lib/memregion.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/bit.o
  CC [M]  drivers/thermal/intel/intel_powerclamp.o
  GEN     drivers/eisa/devlist.h
  CC      drivers/edac/edac_mc.o
  CC      drivers/watchdog/watchdog_pretimeout.o
  CC [M]  drivers/thermal/intel/int340x_thermal/int3402_thermal.o
  CC      drivers/eisa/pci_eisa.o
  CC      drivers/edac/edac_device.o
  CC [M]  drivers/media/mc/mc-request.o
  CC      fs/btrfs/verity.o
  CC [M]  drivers/gpu/drm/radeon/btc_dpm.o
  CC [M]  drivers/gpu/drm/radeon/sumo_dpm.o
  CC [M]  drivers/thermal/intel/x86_pkg_temp_thermal.o
  CC [M]  drivers/gpu/drm/drm_modeset_lock.o
  CC      kernel/watch_queue.o
  CC      drivers/opp/core.o
  CC      lib/irq_poll.o
  CC      drivers/opp/cpu.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.o
  CC      drivers/acpi/acpi_memhotplug.o
  CC      drivers/scsi/scsi_sysfs.o
  CC      drivers/opp/debugfs.o
  CC [M]  drivers/gpu/drm/xe/xe_sa.o
  CC      lib/stackdepot.o
  CC [M]  drivers/media/dvb-core/dmxdev.o
  CC [M]  drivers/media/tuners/xc4000.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.o
  CC [M]  drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.o
  AR      drivers/thermal/st/built-in.a
  CC [M]  drivers/media/mc/mc-dev-allocator.o
  CC      drivers/edac/edac_mc_sysfs.o
  CC      drivers/eisa/virtual_root.o
  CC [M]  drivers/gpu/drm/xe/xe_sched_job.o
  CC [M]  drivers/gpu/drm/xe/xe_step.o
  CC [M]  drivers/thermal/intel/int340x_thermal/int3403_thermal.o
  AR      drivers/thermal/qcom/built-in.a
  CC [M]  drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.o
  AR      drivers/thermal/tegra/built-in.a
  CC [M]  drivers/gpu/drm/i915/gt/intel_gtt.o
  AR      drivers/thermal/mediatek/built-in.a
  CC [M]  drivers/gpu/drm/radeon/sumo_smc.o
  CC [M]  drivers/thermal/intel/intel_soc_dts_iosf.o
  CC [M]  drivers/gpu/drm/radeon/trinity_dpm.o
  CC [M]  drivers/thermal/intel/intel_pch_thermal.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.o
  CC      drivers/eisa/eisa-bus.o
  CC [M]  drivers/media/v4l2-core/v4l2-dev.o
  CC      fs/eventfd.o
  CC      drivers/watchdog/pretimeout_noop.o
  CC      lib/ref_tracker.o
  CC      drivers/acpi/ioapic.o
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_ptp.o
  CC [M]  drivers/gpu/drm/drm_plane.o
  CC      drivers/watchdog/softdog.o
  CC      fs/userfaultfd.o
  CC      lib/bootconfig.o
  CC [M]  drivers/media/tuners/xc5000.o
  CC [M]  drivers/media/v4l2-core/v4l2-ioctl.o
  CC      drivers/acpi/battery.o
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_ddp.o
  CC [M]  drivers/thermal/intel/int340x_thermal/processor_thermal_device.o
  CC [M]  drivers/gpu/drm/radeon/trinity_smc.o
  CC [M]  drivers/thermal/intel/int340x_thermal/int3401_thermal.o
  CC      lib/asn1_decoder.o
  AR      drivers/net/ethernet/myricom/built-in.a
  AR      drivers/net/ethernet/natsemi/built-in.a
  CC [M]  drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.o
  CC      drivers/md/dm-zone.o
  LD [M]  drivers/media/cec/core/cec.o
  AR      drivers/net/ethernet/neterion/built-in.a
  CC [M]  drivers/gpu/drm/radeon/ni_dpm.o
  CC [M]  drivers/gpu/drm/radeon/si_smc.o
  CC [M]  drivers/gpu/drm/xe/xe_sync.o
  CC      drivers/edac/edac_module.o
  CC      drivers/edac/edac_device_sysfs.o
  CC      lib/asn1_encoder.o
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_client.o
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.o
  GZIP    kernel/config_data.gz
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_xsk.o
  CC [M]  drivers/gpu/drm/drm_prime.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/conn.o
  CC      kernel/configs.o
  CC [M]  drivers/gpu/drm/drm_print.o
  LD [M]  drivers/media/mc/mc.o
  LD [M]  drivers/net/ethernet/intel/ixgbe/ixgbe.o
  CC [M]  drivers/gpu/drm/drm_property.o
  CC      drivers/acpi/hed.o
  CC [M]  drivers/gpu/drm/drm_syncobj.o
  CC      drivers/acpi/bgrt.o
  CC [M]  drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.o
  CC      drivers/acpi/cppc_acpi.o
  AR      drivers/watchdog/built-in.a
  CC [M]  drivers/media/dvb-core/dvb_demux.o
  CC      drivers/cpufreq/cpufreq.o
  AR      drivers/eisa/built-in.a
  CC      drivers/cpuidle/cpuidle.o
  CC      drivers/cpuidle/governors/ladder.o
  CC      drivers/cpuidle/driver.o
  AR      fs/btrfs/built-in.a
  CC      drivers/mmc/core/core.o
  CC      drivers/mmc/host/sdhci.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_llc.o
  AR      drivers/opp/built-in.a
  CC [M]  drivers/gpu/drm/i915/gt/intel_lrc.o
  CC [M]  drivers/media/v4l2-core/v4l2-device.o
  CC [M]  drivers/media/v4l2-core/v4l2-fh.o
  CC [M]  drivers/media/v4l2-core/v4l2-event.o
  CC [M]  drivers/media/v4l2-core/v4l2-subdev.o
  AR      kernel/built-in.a
  CC [M]  drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.o
  CC      drivers/mmc/host/sdhci-pci-core.o
  AR      drivers/scsi/built-in.a
  CC      drivers/edac/wq.o
  AR      drivers/net/ethernet/netronome/built-in.a
  CC      drivers/mmc/host/sdhci-pci-o2micro.o
  AR      drivers/net/ethernet/ni/built-in.a
  CC      drivers/mmc/host/sdhci-pci-arasan.o
  AR      drivers/ufs/built-in.a
  CC      drivers/mmc/core/bus.o
  CC      drivers/cpuidle/governor.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.o
  GEN     lib/oid_registry_data.c
  CC      lib/ucs2_string.o
  CC      drivers/cpuidle/governors/menu.o
  CC [M]  drivers/gpu/drm/xe/xe_tile.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.o
  CC      drivers/md/dm-ima.o
  CC      drivers/md/dm-audit.o
  CC      fs/aio.o
  CC      lib/ubsan.o
  AR      drivers/net/ethernet/nvidia/built-in.a
  CC      drivers/cpuidle/sysfs.o
  CC      drivers/acpi/spcr.o
  CC [M]  drivers/gpu/drm/radeon/si_dpm.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_migrate.o
  CC      drivers/md/dm.o
  CC      drivers/acpi/acpi_dbg.o
  CC      drivers/cpufreq/freq_table.o
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_devlink.o
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_dcb.o
  CC      drivers/cpuidle/governors/teo.o
  CC [M]  drivers/media/dvb-core/dvb_ca_en50221.o
  CC      drivers/acpi/viot.o
  CC      lib/sbitmap.o
  CC      drivers/cpufreq/cpufreq_stats.o
  CC      drivers/leds/trigger/ledtrig-disk.o
  AR      drivers/firmware/arm_ffa/built-in.a
  CC [M]  drivers/gpu/drm/xe/xe_tile_sysfs.o
  AR      drivers/firmware/arm_scmi/built-in.a
  CC [M]  drivers/media/dvb-core/dvb_frontend.o
  AR      drivers/firmware/broadcom/built-in.a
  CC      drivers/cpuidle/governors/haltpoll.o
  CC      fs/dax.o
  LD [M]  drivers/media/tuners/tda18271.o
  CC      drivers/cpufreq/cpufreq_performance.o
  CC [M]  drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.o
  AR      drivers/firmware/cirrus/built-in.a
  CC      drivers/leds/trigger/ledtrig-mtd.o
  CC      drivers/leds/trigger/ledtrig-cpu.o
  CC [M]  drivers/gpu/drm/drm_sysfs.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/dcb.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_umc.o
  AR      drivers/firmware/meson/built-in.a
  CC [M]  drivers/gpu/drm/drm_trace_points.o
  AR      drivers/firmware/microchip/built-in.a
  CC      drivers/firmware/efi/efi-bgrt.o
  CC [M]  drivers/gpu/drm/drm_vblank.o
  CC      drivers/edac/edac_pci.o
  AR      drivers/leds/blink/built-in.a
  CC      drivers/firmware/efi/efi.o
  AR      drivers/media/built-in.a
  CC [M]  drivers/acpi/acpi_ipmi.o
  CC      drivers/cpuidle/poll_state.o
  CC      lib/group_cpus.o
  CC      drivers/firmware/efi/libstub/efi-stub-helper.o
  CC      drivers/firmware/efi/libstub/gop.o
  CC      drivers/mmc/host/sdhci-pci-dwc-mshc.o
  CC      drivers/mmc/core/host.o
  CC      drivers/md/dm-table.o
  CC      drivers/leds/led-core.o
  AR      drivers/leds/simple/built-in.a
  CC [M]  drivers/net/ethernet/intel/i40e/i40e_dcb_nl.o
  CC [M]  drivers/media/v4l2-core/v4l2-common.o
  CC      drivers/mmc/core/mmc.o
  CC [M]  drivers/acpi/acpi_video.o
  CC      drivers/leds/trigger/ledtrig-panic.o
  CC      drivers/cpufreq/cpufreq_powersave.o
  CC [M]  drivers/gpu/drm/xe/xe_trace.o
  CC      drivers/cpufreq/cpufreq_userspace.o
  AR      drivers/firmware/imx/built-in.a
  CC [M]  drivers/gpu/drm/drm_vblank_work.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/disp.o
  AR      drivers/cpuidle/governors/built-in.a
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.o
  AR      drivers/cpuidle/built-in.a
  CC [M]  drivers/media/dvb-core/dvb_net.o
  CC [M]  drivers/media/dvb-core/dvb_ringbuffer.o
  CC      fs/locks.o
  CC      drivers/thermal/thermal_core.o
  CC      drivers/mmc/core/mmc_ops.o
  CC      drivers/leds/led-class.o
  CC      drivers/leds/led-triggers.o
  CC [M]  drivers/gpu/drm/drm_vma_manager.o
  CC      drivers/edac/edac_pci_sysfs.o
  CC [M]  drivers/gpu/drm/radeon/kv_smc.o
  CC [M]  drivers/media/v4l2-core/v4l2-ctrls-core.o
  AR      drivers/firmware/psci/built-in.a
  CC      drivers/firmware/efi/vars.o
  CC [M]  drivers/media/v4l2-core/v4l2-ctrls-api.o
  AR      drivers/firmware/qcom/built-in.a
  AR      drivers/firmware/smccc/built-in.a
  CC [M]  drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.o
  CC      drivers/mmc/host/sdhci-pci-gli.o
  CC      drivers/mmc/host/sdhci-acpi.o
  CC      drivers/firmware/efi/libstub/secureboot.o
  CC      drivers/mmc/host/cqhci-core.o
  AR      drivers/leds/trigger/built-in.a
  CC [M]  drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.o
  CC      drivers/mmc/host/cqhci-crypto.o
  CC      drivers/firmware/efi/libstub/tpm.o
  CC      lib/fw_table.o
  CC      drivers/firmware/efi/reboot.o
  CC      drivers/cpufreq/cpufreq_ondemand.o
  CC      drivers/thermal/thermal_sysfs.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_mocs.o
  CC      drivers/thermal/thermal_trip.o
  AR      drivers/firmware/tegra/built-in.a
  CC      fs/binfmt_script.o
  CC [M]  drivers/gpu/drm/drm_writeback.o
  CC      drivers/firmware/efi/memattr.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.o
  CC      drivers/firmware/efi/tpm.o
  CC [M]  drivers/media/v4l2-core/v4l2-ctrls-request.o
  AR      drivers/net/ethernet/oki-semi/built-in.a
  AR      drivers/net/ethernet/packetengines/built-in.a
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.o
  CC      drivers/edac/ghes_edac.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.o
  CC [M]  drivers/gpu/drm/xe/xe_ttm_sys_mgr.o
  CC      drivers/mmc/core/sd.o
  CC [M]  drivers/gpu/drm/radeon/kv_dpm.o
  CC      drivers/md/dm-target.o
  CC      drivers/firmware/efi/libstub/file.o
  CC      drivers/firmware/efi/memmap.o
  CC [M]  drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_ppgtt.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/gpio.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_rap.o
  LD [M]  drivers/net/ethernet/intel/i40e/i40e.o
  CC [M]  drivers/gpu/drm/lib/drm_random.o
  CC [M]  drivers/gpu/drm/drm_ioc32.o
  CC [M]  drivers/edac/igen6_edac.o
  CC [M]  drivers/acpi/video_detect.o
  CC [M]  drivers/acpi/acpi_tad.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_rc6.o
  AR      drivers/leds/built-in.a
  CC [M]  drivers/mmc/host/sdhci-pltfm.o
  CC      drivers/firmware/efi/libstub/mem.o
  CC      drivers/mmc/core/sd_ops.o
  AR      drivers/net/ethernet/qlogic/built-in.a
  CC [M]  lib/crc-itu-t.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_region_lmem.o
  CC [M]  drivers/gpu/drm/xe/xe_ttm_stolen_mgr.o
  AR      drivers/net/ethernet/qualcomm/emac/built-in.a
  AR      drivers/net/ethernet/qualcomm/built-in.a
  CC      drivers/thermal/thermal_helpers.o
  CC      drivers/mmc/core/sdio.o
  CC      drivers/mmc/core/sdio_ops.o
  AR      drivers/net/ethernet/realtek/built-in.a
  CC [M]  lib/bch.o
  CC [M]  drivers/net/ethernet/realtek/8139cp.o
  CC [M]  drivers/gpu/drm/drm_panel.o
  CC [M]  drivers/net/ethernet/realtek/8139too.o
  CC [M]  drivers/gpu/drm/radeon/ci_smc.o
  CC      drivers/firmware/efi/esrt.o
  CC      drivers/cpufreq/cpufreq_conservative.o
  CC      drivers/md/dm-linear.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/i2c.o
  LD [M]  drivers/media/dvb-core/dvb-core.o
  CC [M]  drivers/gpu/drm/radeon/ci_dpm.o
  CC [M]  drivers/net/ethernet/realtek/r8169_main.o
  CC      drivers/thermal/thermal_netlink.o
  CC      drivers/thermal/thermal_hwmon.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_fw_attestation.o
  CC      fs/binfmt_elf.o
  CC      fs/compat_binfmt_elf.o
  CC [M]  drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.o
  CC [M]  drivers/gpu/drm/xe/xe_ttm_vram_mgr.o
  CC      fs/backing-file.o
  CC [M]  drivers/net/ethernet/realtek/r8169_firmware.o
  CC      drivers/firmware/efi/libstub/random.o
  AR      drivers/mmc/host/built-in.a
  CC      drivers/firmware/efi/cper.o
  CC [M]  drivers/acpi/acpi_pad.o
  CC      drivers/md/dm-stripe.o
  CC      drivers/mmc/core/sdio_bus.o
  CC      drivers/md/dm-ioctl.o
  CC [M]  drivers/media/v4l2-core/v4l2-ctrls-defs.o
  CC      drivers/md/dm-io.o
  CC [M]  drivers/edac/skx_common.o
  CC [M]  drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.o
  CC      drivers/firmware/efi/cper_cxl.o
  CC [M]  drivers/gpu/drm/drm_pci.o
  CC      drivers/firmware/efi/libstub/randomalloc.o
  CC      drivers/firmware/efi/runtime-wrappers.o
  AR      drivers/firmware/xilinx/built-in.a
  CC      drivers/cpufreq/cpufreq_governor.o
  CC      drivers/firmware/efi/dev-path-parser.o
  CC [M]  drivers/media/v4l2-core/v4l2-compat-ioctl32.o
  CC      drivers/firmware/efi/libstub/pci.o
  CC      fs/mbcache.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.o
  CC      fs/posix_acl.o
  CC [M]  drivers/gpu/drm/radeon/dce6_afmt.o
  CC      drivers/thermal/gov_fair_share.o
  AR      drivers/crypto/ccp/built-in.a
  CC [M]  drivers/edac/i10nm_base.o
  CC      drivers/md/dm-kcopyd.o
  CC      drivers/thermal/gov_bang_bang.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/image.o
  AR      drivers/crypto/stm32/built-in.a
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.o
  AR      drivers/crypto/xilinx/built-in.a
  AR      drivers/edac/built-in.a
  CC [M]  drivers/net/ethernet/realtek/r8169_phy_config.o
  AR      drivers/crypto/hisilicon/built-in.a
  AR      drivers/crypto/intel/keembay/built-in.a
  AR      drivers/crypto/intel/ixp4xx/built-in.a
  CC [M]  drivers/gpu/drm/i915/gt/intel_renderstate.o
  AR      drivers/crypto/intel/built-in.a
  CC [M]  drivers/gpu/drm/xe/xe_tuning.o
  CC [M]  drivers/gpu/drm/radeon/radeon_vm.o
  AR      drivers/crypto/starfive/built-in.a
  CC [M]  drivers/gpu/drm/drm_debugfs.o
  CC      drivers/thermal/gov_step_wise.o
  AR      drivers/crypto/built-in.a
  CC      drivers/thermal/gov_user_space.o
  AR      drivers/thermal/intel/built-in.a
  CC      drivers/mmc/core/sdio_cis.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/npde.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_reset.o
  CC      drivers/cpufreq/cpufreq_governor_attr_set.o
  CC      drivers/cpufreq/acpi-cpufreq.o
  CC [M]  drivers/gpu/drm/drm_debugfs_crc.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_ring.o
  CC [M]  drivers/media/v4l2-core/v4l2-mc.o
  GEN     lib/test_fortify.log
  GEN     lib/crc32table.h
  GEN     lib/crc64table.h
  CC      lib/oid_registry.o
  CC      drivers/mmc/core/sdio_io.o
  LD [M]  drivers/acpi/video.o
  AR      drivers/acpi/built-in.a
  CC      drivers/firmware/efi/apple-properties.o
  CC      drivers/mmc/core/sdio_irq.o
  CC      fs/coredump.o
  CC      drivers/mmc/core/slot-gpio.o
  CC      drivers/md/dm-sysfs.o
  CC      drivers/firmware/efi/libstub/skip_spaces.o
  CC      drivers/md/dm-stats.o
  CC      drivers/md/dm-rq.o
  CC [M]  drivers/gpu/drm/xe/xe_uc.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_mca.o
  CC [M]  drivers/media/v4l2-core/v4l2-spi.o
  CC      drivers/firmware/efi/libstub/lib-cmdline.o
  CC      drivers/firmware/efi/libstub/lib-ctype.o
  CC      drivers/mmc/core/regulator.o
  CC      drivers/thermal/gov_power_allocator.o
  CC      drivers/thermal/devfreq_cooling.o
  CC      drivers/firmware/efi/libstub/alignedmem.o
  CC      drivers/firmware/efi/rci2-table.o
  CC      drivers/mmc/core/debugfs.o
  CC      drivers/md/dm-io-rewind.o
  CC      drivers/md/dm-builtin.o
  CC [M]  drivers/media/v4l2-core/v4l2-trace.o
  CC      fs/drop_caches.o
  CC      drivers/cpufreq/amd-pstate.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.o
  CC [M]  drivers/md/raid0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/pcir.o
  LD [M]  drivers/edac/i10nm_edac.o
  CC      drivers/firmware/efi/mokvar-table.o
  CC [M]  drivers/gpu/drm/xe/xe_uc_debugfs.o
  CC      drivers/clocksource/acpi_pm.o
  CC      drivers/firmware/efi/sysfb_efi.o
  CC [M]  drivers/gpu/drm/xe/xe_uc_fw.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_ring_submission.o
  CC      drivers/firmware/efi/earlycon.o
  AR      drivers/net/ethernet/renesas/built-in.a
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.o
  CC [M]  drivers/gpu/drm/drm_edid_load.o
  CC [M]  drivers/media/v4l2-core/v4l2-i2c.o
  CC      drivers/clocksource/i8253.o
  CC [M]  drivers/hid/usbhid/hid-core.o
  CC      lib/string.o
  CC [M]  drivers/md/raid1.o
  AR      drivers/hid/built-in.a
  CC [M]  drivers/gpu/drm/i915/gt/intel_rps.o
  CC [M]  drivers/hid/intel-ish-hid/ishtp/init.o
  CC [M]  drivers/hid/intel-ish-hid/ishtp/hbm.o
  CC      drivers/firmware/efi/libstub/relocate.o
  CC [M]  drivers/hid/hid-core.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.o
  CC      fs/sysctls.o
  CC      fs/fhandle.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.o
  CC      lib/crc32.o
  CC      drivers/mmc/core/crypto.o
  LD [M]  drivers/net/ethernet/realtek/r8169.o
  AR      drivers/net/ethernet/rdc/built-in.a
  AR      drivers/net/ethernet/rocker/built-in.a
  CC [M]  drivers/md/raid10.o
  CC [M]  drivers/hid/hid-input.o
  AR      drivers/net/ethernet/samsung/built-in.a
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.o
  AR      drivers/net/ethernet/seeq/built-in.a
  AR      drivers/net/ethernet/silan/built-in.a
  CC      drivers/firmware/efi/cper-x86.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/power_budget.o
  CC      drivers/firmware/efi/unaccepted_memory.o
  AR      drivers/net/ethernet/sis/built-in.a
  AR      drivers/net/ethernet/sfc/built-in.a
  CC [M]  drivers/hid/hid-quirks.o
  CC [M]  drivers/gpu/drm/../../accel/drm_accel.o
  AR      drivers/net/ethernet/smsc/built-in.a
  CC      drivers/firmware/dmi_scan.o
  CC      drivers/firmware/dmi-sysfs.o
  CC [M]  drivers/gpu/drm/xe/xe_vm.o
  AR      drivers/net/ethernet/socionext/built-in.a
  AR      drivers/thermal/built-in.a
  AR      drivers/net/ethernet/sun/built-in.a
  AR      drivers/net/ethernet/stmicro/built-in.a
  AR      drivers/net/ethernet/tehuti/built-in.a
  CC      drivers/firmware/edd.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.o
  CC [M]  drivers/gpu/drm/radeon/radeon_ucode.o
  CC [M]  drivers/gpu/drm/xe/xe_vram_freq.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.o
  AR      drivers/net/ethernet/ti/built-in.a
  CC [M]  drivers/gpu/drm/xe/xe_wait_user_fence.o
  CC [M]  drivers/gpu/drm/radeon/radeon_ib.o
  AR      drivers/net/ethernet/vertexcom/built-in.a
  CC [M]  drivers/gpu/drm/xe/xe_wa.o
  AR      drivers/net/ethernet/via/built-in.a
  CC [M]  drivers/firmware/efi/efi-pstore.o
  CC      drivers/cpufreq/amd-pstate-trace.o
  AR      drivers/net/ethernet/wangxun/built-in.a
  CC [M]  drivers/hid/intel-ish-hid/ishtp/client.o
  AR      drivers/net/ethernet/wiznet/built-in.a
  AR      drivers/net/ethernet/xilinx/built-in.a
  CC      drivers/clocksource/numachip.o
  CC [M]  drivers/gpu/drm/radeon/radeon_sync.o
  CC      drivers/firmware/efi/libstub/printk.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.o
  AR      drivers/net/ethernet/synopsys/built-in.a
  CC      lib/crc64.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_aca.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.o
  CC [M]  drivers/md/raid5.o
  AR      drivers/net/ethernet/pensando/built-in.a
  AR      drivers/net/ethernet/built-in.a
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.o
  CC [M]  fs/binfmt_misc.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/cik.o
  CC [M]  drivers/gpu/drm/xe/xe_wopcm.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/ramcfg.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_sa_media.o
  CC      drivers/firmware/efi/libstub/vsprintf.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.o
  CC      drivers/firmware/efi/libstub/x86-stub.o
  AR      drivers/clocksource/built-in.a
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.o
  CC      drivers/firmware/dmi-id.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.o
  CC [M]  drivers/gpu/drm/xe/xe_hwmon.o
  AR      drivers/net/built-in.a
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.o
  LD [M]  drivers/media/v4l2-core/videodev.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/cik_ih.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_relay.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/dce_v8_0.o
  CC      drivers/firmware/efi/libstub/x86-5lvl.o
  AR      drivers/firmware/efi/built-in.a
  CC [M]  drivers/hid/usbhid/hiddev.o
  CC [M]  drivers/hid/usbhid/hid-pidff.o
  CC [M]  drivers/hid/intel-ish-hid/ishtp/bus.o
  CC      drivers/firmware/memmap.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_sseu.o
  CC      drivers/cpufreq/powernow-k8.o
  AR      drivers/mmc/core/built-in.a
  AR      fs/built-in.a
  AR      drivers/mmc/built-in.a
  AR      drivers/staging/media/built-in.a
  CC [M]  drivers/gpu/drm/xe/xe_memirq.o
  CC [M]  drivers/hid/intel-ish-hid/ishtp/dma-if.o
  CC      drivers/staging/vme_user/vme.o
  AR      lib/lib.a
  CC [M]  drivers/hid/intel-ish-hid/ishtp/client-buffers.o
  AR      lib/built-in.a
  CC [M]  drivers/gpu/drm/radeon/radeon_audio.o
  CC [M]  drivers/staging/iio/impedance-analyzer/ad5933.o
  CC [M]  drivers/hid/intel-ish-hid/ipc/ipc.o
  CC [M]  drivers/gpu/drm/drm_exec.o
  CC      drivers/mailbox/mailbox.o
  CC      drivers/mailbox/pcc.o
  AR      drivers/platform/x86/amd/built-in.a
  AR      drivers/platform/x86/dell/built-in.a
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfx_v7_0.o
  AR      drivers/platform/x86/hp/built-in.a
  CC [M]  drivers/platform/x86/intel/int3472/discrete.o
  CC      drivers/platform/x86/p2sb.o
  CC [M]  drivers/platform/x86/intel/int3472/clk_and_regulator.o
  CC      drivers/hwspinlock/hwspinlock_core.o
  CC [M]  drivers/platform/x86/intel/pmc/core.o
  CC [M]  drivers/platform/x86/intel/int3472/led.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.o
  CC [M]  drivers/md/raid5-cache.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_sseu_debugfs.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.o
  CC      drivers/firmware/efi/libstub/unaccepted_memory.o
  CC      drivers/firmware/efi/libstub/bitmap.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_timeline.o
  CC      drivers/firmware/efi/libstub/find.o
  CC [M]  drivers/platform/x86/intel/pmc/core_ssram.o
  CC [M]  drivers/platform/x86/intel/int3472/common.o
  CC [M]  drivers/hid/intel-ish-hid/ipc/pci-ish.o
  CC [M]  drivers/gpu/drm/drm_gpuvm.o
  CC [M]  drivers/hid/intel-ish-hid/ishtp-hid.o
  AR      drivers/platform/mellanox/built-in.a
  CC [M]  drivers/platform/x86/intel/pmt/class.o
  CC [M]  drivers/hid/intel-ish-hid/ishtp-hid-client.o
  CC      drivers/platform/x86/intel_scu_ipc.o
  CC      drivers/platform/x86/intel_scu_pcidrv.o
  CC [M]  drivers/hid/hid-debug.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.o
  CC [M]  drivers/md/raid5-ppl.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.o
  CC      drivers/cpufreq/pcc-cpufreq.o
  CC [M]  drivers/hid/hidraw.o
  CC [M]  drivers/gpu/drm/xe/xe_sriov.o
  CC [M]  drivers/hid/hid-generic.o
  CC [M]  drivers/hid/hid-sensor-hub.o
  CC [M]  drivers/gpu/drm/xe/xe_lmtt.o
  CC      drivers/firmware/sysfb.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_tlb.o
  STUBCPY drivers/firmware/efi/libstub/alignedmem.stub.o
  LD [M]  drivers/hid/intel-ish-hid/intel-ishtp.o
  STUBCPY drivers/firmware/efi/libstub/bitmap.stub.o
  CC [M]  drivers/gpu/drm/radeon/radeon_dp_auxch.o
  CC [M]  drivers/platform/x86/intel/pmc/spt.o
  CC      drivers/remoteproc/remoteproc_core.o
  STUBCPY drivers/firmware/efi/libstub/efi-stub-helper.stub.o
  CC      drivers/cpufreq/speedstep-centrino.o
  STUBCPY drivers/firmware/efi/libstub/file.stub.o
  AR      drivers/virt/vboxguest/built-in.a
  CC [M]  drivers/gpu/drm/i915/gt/intel_wopcm.o
  STUBCPY drivers/firmware/efi/libstub/find.stub.o
  AR      drivers/virt/coco/tdx-guest/built-in.a
  CC [M]  drivers/gpu/drm/i915/gt/intel_workarounds.o
  STUBCPY drivers/firmware/efi/libstub/gop.stub.o
  STUBCPY drivers/firmware/efi/libstub/lib-cmdline.stub.o
  CC      drivers/cpufreq/intel_pstate.o
  CC [M]  drivers/platform/x86/intel/pmc/cnp.o
  AR      drivers/platform/chrome/built-in.a
  LD [M]  drivers/hid/usbhid/usbhid.o
  AR      drivers/virt/coco/built-in.a
  CC [M]  drivers/platform/x86/intel/int3472/tps68470.o
  STUBCPY drivers/firmware/efi/libstub/lib-ctype.stub.o
  STUBCPY drivers/firmware/efi/libstub/mem.stub.o
  AR      drivers/virt/built-in.a
  AR      drivers/mailbox/built-in.a
  CC [M]  drivers/gpu/drm/xe/xe_lmtt_2l.o
  CC [M]  drivers/gpu/drm/i915/gt/shmem_utils.o
  CC [M]  drivers/gpu/drm/xe/xe_lmtt_ml.o
  STUBCPY drivers/firmware/efi/libstub/pci.stub.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/cik_sdma.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_kunit_helpers.o
  STUBCPY drivers/firmware/efi/libstub/printk.stub.o
  STUBCPY drivers/firmware/efi/libstub/random.stub.o
  CC [M]  drivers/hid/hid-sensor-custom.o
  AR      drivers/devfreq/event/built-in.a
  STUBCPY drivers/firmware/efi/libstub/randomalloc.stub.o
  CC      drivers/devfreq/devfreq.o
  STUBCPY drivers/firmware/efi/libstub/relocate.stub.o
  STUBCPY drivers/firmware/efi/libstub/secureboot.stub.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/uvd_v4_2.o
  AR      drivers/hwspinlock/built-in.a
  CC      drivers/devfreq/devfreq-event.o
  STUBCPY drivers/firmware/efi/libstub/skip_spaces.stub.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/vce_v2_0.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/si.o
  CC [M]  drivers/md/dm-path-selector.o
  STUBCPY drivers/firmware/efi/libstub/tpm.stub.o
  STUBCPY drivers/firmware/efi/libstub/unaccepted_memory.stub.o
  STUBCPY drivers/firmware/efi/libstub/vsprintf.stub.o
  STUBCPY drivers/firmware/efi/libstub/x86-5lvl.stub.o
  STUBCPY drivers/firmware/efi/libstub/x86-stub.stub.o
  CC [M]  drivers/platform/x86/intel/int3472/tps68470_board_data.o
  LD [M]  drivers/hid/intel-ish-hid/intel-ish-ipc.o
  CC [M]  drivers/gpu/drm/drm_buddy.o
  AR      drivers/firmware/efi/libstub/lib.a
  AR      drivers/staging/vme_user/built-in.a
  AR      drivers/staging/built-in.a
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.o
  CC      drivers/devfreq/governor_simpleondemand.o
  CC [M]  drivers/platform/x86/intel/pmc/icl.o
  LD [M]  drivers/hid/intel-ish-hid/intel-ishtp-hid.o
  CC [M]  drivers/platform/x86/intel/pmc/tgl.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gmc_v6_0.o
  CC [M]  drivers/platform/x86/intel/pmt/telemetry.o
  CC      drivers/extcon/extcon.o
  CC      drivers/extcon/devres.o
  LD [M]  drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.o
  AR      drivers/memory/built-in.a
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.o
  CC [M]  drivers/gpu/drm/xe/display/ext/i915_irq.o
  CC      drivers/powercap/powercap_sys.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfx_v6_0.o
  AR      drivers/platform/surface/built-in.a
  CC [M]  drivers/gpu/drm/amd/amdgpu/si_ih.o
  CC [M]  drivers/gpu/drm/xe/display/ext/i915_utils.o
  CC      drivers/powercap/idle_inject.o
  CC      drivers/devfreq/governor_performance.o
  CC [M]  drivers/powercap/intel_rapl_common.o
  CC      drivers/devfreq/governor_powersave.o
  AR      drivers/perf/built-in.a
  CC      drivers/ras/ras.o
  AR      drivers/android/built-in.a
  AR      drivers/hwtracing/intel_th/built-in.a
  CC [M]  drivers/gpu/drm/radeon/radeon_mn.o
  CC [M]  drivers/gpu/drm/radeon/r600_dma.o
  CC [M]  drivers/hwtracing/intel_th/core.o
  CC [M]  drivers/gpu/drm/radeon/rv770_dma.o
  CC [M]  drivers/gpu/drm/i915/gt/sysfs_engines.o
  CC [M]  drivers/platform/x86/intel/pmc/adl.o
  CC [M]  drivers/gpu/drm/radeon/evergreen_dma.o
  LD [M]  drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.o
  CC      drivers/devfreq/governor_userspace.o
  CC [M]  drivers/gpu/drm/radeon/ni_dma.o
  CC      drivers/devfreq/governor_passive.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_ggtt_gmch.o
  AR      drivers/firmware/built-in.a
  CC      drivers/platform/x86/pmc_atom.o
  CC [M]  drivers/platform/x86/wmi.o
  CC [M]  drivers/platform/x86/wmi-bmof.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/xpio.o
  CC      drivers/nvmem/core.o
  AR      drivers/nvmem/layouts/built-in.a
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0203.o
  LD [M]  drivers/hid/hid.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0205.o
  CC [M]  drivers/platform/x86/intel/speed_select_if/isst_if_common.o
  CC [M]  drivers/powercap/intel_rapl_msr.o
  CC      drivers/interconnect/core.o
  CC [M]  drivers/gpu/drm/xe/display/intel_fb_bo.o
  CC [M]  drivers/gpu/drm/xe/display/intel_fbdev_fb.o
  CC [M]  drivers/platform/x86/intel/uncore-frequency/uncore-frequency.o
  CC [M]  drivers/gpu/drm/xe/display/xe_display.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/si_dma.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0209.o
  CC      drivers/ras/debugfs.o
  CC [M]  drivers/platform/x86/mxm-wmi.o
  CC      drivers/ras/cec.o
  CC [M]  drivers/platform/x86/intel/pmt/crashlog.o
  CC      drivers/interconnect/bulk.o
  CC [M]  drivers/gpu/drm/xe/display/xe_display_misc.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bios/P0260.o
  CC [M]  drivers/gpu/drm/i915/gt/gen6_renderstate.o
  CC      drivers/remoteproc/remoteproc_coredump.o
  CC      drivers/platform/x86/intel/turbo_max_3.o
  CC [M]  drivers/platform/x86/intel/pmc/mtl.o
  CC [M]  drivers/platform/x86/intel/pmc/arl.o
  CC [M]  drivers/platform/x86/intel/hid.o
  CC [M]  drivers/platform/x86/intel/pmc/lnl.o
  AR      drivers/extcon/built-in.a
  CC [M]  drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.o
  CC [M]  drivers/platform/x86/intel/speed_select_if/isst_if_mmio.o
  AR      drivers/cpufreq/built-in.a
  CC      drivers/hte/hte.o
  CC      drivers/interconnect/debugfs-client.o
  CC [M]  drivers/gpu/drm/i915/gt/gen7_renderstate.o
  AR      drivers/powercap/built-in.a
  CC [M]  drivers/gpu/drm/i915/gt/gen8_renderstate.o
  CC [M]  drivers/gpu/drm/i915/gt/gen9_renderstate.o
  CC      drivers/remoteproc/remoteproc_debugfs.o
  AR      drivers/accel/built-in.a
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_busy.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_clflush.o
  CC [M]  drivers/gpu/drm/radeon/si_dma.o
  CC [M]  drivers/platform/x86/intel_ips.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bus/base.o
  CC [M]  drivers/gpu/drm/radeon/cik_sdma.o
  AR      drivers/devfreq/built-in.a
  CC [M]  drivers/gpu/drm/radeon/radeon_uvd.o
  CC [M]  drivers/parport/share.o
  CC [M]  drivers/mtd/parsers/cmdlinepart.o
  CC [M]  drivers/mtd/chips/chipreg.o
  CC [M]  drivers/gpu/drm/radeon/uvd_v1_0.o
  CC [M]  drivers/gpu/drm/radeon/uvd_v2_2.o
  CC [M]  drivers/mtd/maps/map_funcs.o
  LD [M]  drivers/platform/x86/intel/pmt/pmt_class.o
  LD [M]  drivers/platform/x86/intel/pmt/pmt_telemetry.o
  LD [M]  drivers/platform/x86/intel/pmt/pmt_crashlog.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_context.o
  CC [M]  drivers/gpu/drm/xe/display/xe_display_rps.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv04.o
  CC [M]  drivers/hwtracing/intel_th/pci.o
  LD [M]  drivers/platform/x86/intel/uncore-frequency/intel-uncore-frequency.o
  CC [M]  drivers/vfio/pci/vfio_pci_core.o
  CC [M]  drivers/platform/x86/intel/speed_select_if/isst_if_mbox_pci.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv31.o
  CC [M]  drivers/vfio/pci/vfio_pci_intrs.o
  CC [M]  drivers/platform/x86/intel/pmc/pltdrv.o
  CC [M]  drivers/vfio/vfio_main.o
  CC      drivers/remoteproc/remoteproc_sysfs.o
  CC [M]  drivers/platform/x86/intel/vsec.o
  CC [M]  drivers/vfio/group.o
  LD [M]  drivers/platform/x86/intel/pmc/intel_pmc_core.o
  CC      drivers/remoteproc/remoteproc_virtio.o
  CC [M]  drivers/gpu/drm/radeon/uvd_v3_1.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_create.o
  CC [M]  drivers/platform/x86/intel/rst.o
  CC [M]  drivers/gpu/drm/xe/display/xe_dsb_buffer.o
  CC [M]  drivers/vfio/pci/vfio_pci_rdwr.o
  AR      drivers/ras/built-in.a
  CC [M]  drivers/hwtracing/intel_th/gth.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv50.o
  CC [M]  drivers/gpu/drm/xe/display/xe_fb_pin.o
  LD [M]  drivers/hwtracing/intel_th/intel_th.o
  CC [M]  drivers/gpu/drm/xe/display/xe_hdcp_gsc.o
  CC [M]  drivers/vfio/pci/vfio_pci_config.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_dmabuf.o
  CC [M]  drivers/gpu/drm/radeon/uvd_v4_2.o
  LD [M]  drivers/platform/x86/intel/uncore-frequency/intel-uncore-frequency-common.o
  CC [M]  drivers/gpu/drm/radeon/radeon_vce.o
  AR      drivers/nvmem/built-in.a
  CC [M]  drivers/parport/ieee1284.o
  CC [M]  drivers/platform/x86/intel/speed_select_if/isst_if_mbox_msr.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/dce_v6_0.o
  CC      drivers/remoteproc/remoteproc_elf_loader.o
  CC [M]  drivers/md/dm-mpath.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_domain.o
  AR      drivers/hte/built-in.a
  LD [M]  drivers/platform/x86/intel/pmc/intel_pmc_core_pltdrv.o
  CC [M]  drivers/mtd/nand/core.o
  CC [M]  drivers/vhost/net.o
  CC [M]  drivers/dca/dca-core.o
  CC [M]  drivers/vhost/vhost.o
  AR      drivers/interconnect/built-in.a
  CC [M]  drivers/dca/dca-sysfs.o
  CC      drivers/remoteproc/remoteproc_cdev.o
  CC [M]  drivers/parport/ieee1284_ops.o
  AR      drivers/platform/x86/intel/built-in.a
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_execbuffer.o
  LD [M]  drivers/hwtracing/intel_th/intel_th_pci.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bus/g94.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/bus/gf100.o
  CC [M]  drivers/gpu/drm/radeon/vce_v1_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.o
  LD [M]  drivers/platform/x86/intel/intel-hid.o
  LD [M]  drivers/platform/x86/intel/intel-rst.o
  CC [M]  drivers/mtd/spi-nor/core.o
  CC [M]  drivers/mtd/spi-nor/sfdp.o
  CC [M]  drivers/md/dm-ps-round-robin.o
  CC [M]  drivers/mtd/spi-nor/swp.o
  CC [M]  drivers/soundwire/bus_type.o
  CC [M]  drivers/soundwire/bus.o
  CC [M]  drivers/vhost/iotlb.o
  CC [M]  drivers/soundwire/master.o
  CC [M]  drivers/vfio/pci/vfio_pci.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_internal.o
  LD [M]  drivers/hwtracing/intel_th/intel_th_gth.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_lmem.o
  CC [M]  drivers/mtd/nand/bbt.o
  CC [M]  drivers/gpu/drm/xe/display/xe_plane_initial.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/uvd_v3_1.o
  CC [M]  drivers/parport/procfs.o
  CC [M]  drivers/gpu/drm/xe/i915-soc/intel_dram.o
  CC [M]  drivers/gpu/drm/radeon/vce_v2_0.o
  CC [M]  drivers/gpu/drm/xe/i915-soc/intel_pch.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv04.o
  LD [M]  drivers/platform/x86/intel/intel_vsec.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_mman.o
  AR      drivers/platform/x86/built-in.a
  CC [M]  drivers/gpu/drm/amd/amdgpu/vi.o
  AR      drivers/platform/built-in.a
  CC [M]  drivers/gpu/drm/amd/amdgpu/mxgpu_vi.o
  CC [M]  drivers/parport/daisy.o
  CC [M]  drivers/parport/probe.o
  LD [M]  drivers/md/raid456.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/nbio_v6_1.o
  CC [M]  drivers/gpu/drm/drm_gem_shmem_helper.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/soc15.o
  AR      drivers/md/built-in.a
  CC [M]  drivers/gpu/drm/amd/amdgpu/emu_soc.o
  CC [M]  drivers/parport/parport_pc.o
  CC [M]  drivers/vfio/container.o
  CC [M]  drivers/soundwire/slave.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mxgpu_ai.o
  CC [M]  drivers/vfio/virqfd.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_object.o
  AR      drivers/remoteproc/built-in.a
  CC [M]  drivers/soundwire/mipi_disco.o
  CC [M]  drivers/gpu/drm/xe/i915-display/icl_dsi.o
  CC [M]  drivers/soundwire/stream.o
  CC [M]  drivers/mtd/spi-nor/otp.o
  CC [M]  drivers/mtd/nand/ecc.o
  CC [M]  drivers/iio/accel/hid-sensor-accel-3d.o
  LD [M]  drivers/vfio/pci/vfio-pci.o
  LD [M]  drivers/vfio/pci/vfio-pci-core.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv40.o
  LD [M]  drivers/vhost/vhost_iotlb.o
  CC [M]  drivers/mtd/nand/ecc-sw-hamming.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.o
  LD [M]  drivers/dca/dca.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.o
  CC [M]  drivers/mtd/spi-nor/sysfs.o
  CC [M]  drivers/mtd/spi-nor/atmel.o
  CC [M]  drivers/vfio/vfio_iommu_type1.o
  LD [M]  drivers/md/dm-round-robin.o
  CC [M]  drivers/soundwire/sysfs_slave.o
  CC [M]  drivers/thunderbolt/nhi.o
  LD [M]  drivers/md/dm-multipath.o
  CC [M]  drivers/soundwire/sysfs_slave_dpn.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_pages.o
  CC [M]  drivers/thunderbolt/nhi_ops.o
  CC [M]  drivers/mtd/nand/ecc-sw-bch.o
  CC [M]  drivers/mtd/nand/ecc-mxic.o
  CC [M]  drivers/soundwire/debugfs.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_atomic.o
  LD [M]  drivers/parport/parport.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/clk/mcp77.o
  CC [M]  drivers/gpu/drm/radeon/radeon_fbdev.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.o
  CC [M]  drivers/gpu/drm/radeon/radeon_atpx_handler.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/nbio_v7_0.o
  CC [M]  drivers/gpu/drm/radeon/radeon_acpi.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/vega10_reg_init.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/vega20_reg_init.o
  CC [M]  drivers/gpu/drm/drm_suballoc.o
  CC [M]  drivers/mtd/spi-nor/eon.o
  CC [M]  drivers/thunderbolt/ctl.o
  CC [M]  drivers/mtd/spi-nor/esmt.o
  CC [M]  drivers/mtd/spi-nor/everspin.o
  CC [M]  drivers/soundwire/irq.o
  CC [M]  drivers/thunderbolt/tb.o
  CC [M]  drivers/mtd/spi-nor/gigadevice.o
  CC [M]  drivers/mtd/mtdcore.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_atomic_plane.o
  CC [M]  drivers/iio/buffer/industrialio-triggered-buffer.o
  CC [M]  drivers/mtd/spi-nor/intel.o
  CC [M]  drivers/mtd/mtdsuper.o
  LD [M]  drivers/vfio/vfio.o
  LD [M]  drivers/vhost/vhost_net.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.o
  CC [M]  drivers/thunderbolt/switch.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/clk/gm20b.o
  MKREG   drivers/gpu/drm/radeon/r100_reg_safe.h
  CC [M]  drivers/gpu/drm/amd/amdgpu/nbio_v7_4.o
  MKREG   drivers/gpu/drm/radeon/rn50_reg_safe.h
  MKREG   drivers/gpu/drm/radeon/r300_reg_safe.h
  CC [M]  drivers/gpu/drm/amd/amdgpu/nbio_v2_3.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnv04.o
  CC [M]  drivers/mtd/spi-nor/issi.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_audio.o
  CC [M]  drivers/mtd/spi-nor/macronix.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_backlight.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_phys.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_pm.o
  CC [M]  drivers/mtd/mtdconcat.o
  CC [M]  drivers/mtd/mtdpart.o
  CC [M]  drivers/mtd/mtdchar.o
  MKREG   drivers/gpu/drm/radeon/r420_reg_safe.h
  CC [M]  drivers/mtd/spi-nor/micron-st.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_bios.o
  CC [M]  drivers/soundwire/generic_bandwidth_allocation.o
  CC [M]  drivers/gpu/drm/radeon/rs600.o
  CC [M]  drivers/mtd/spi-nor/spansion.o
  CC [M]  drivers/gpu/drm/radeon/rv515.o
  LD [M]  drivers/mtd/nand/nandcore.o
  CC [M]  drivers/gpu/drm/radeon/r200.o
  CC [M]  drivers/thunderbolt/cap.o
  CC [M]  drivers/mtd/spi-nor/sst.o
  CC [M]  drivers/gpu/drm/drm_gem_ttm_helper.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_region.o
  CC [M]  drivers/iio/buffer/kfifo_buf.o
  CC [M]  drivers/mtd/spi-nor/winbond.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_shmem.o
  CC [M]  drivers/mtd/spi-nor/xilinx.o
  CC [M]  drivers/mtd/spi-nor/xmc.o
  CC [M]  drivers/soundwire/cadence_master.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/nv.o
  CC [M]  drivers/mtd/spi-nor/debugfs.o
  CC [M]  drivers/thunderbolt/path.o
  CC [M]  drivers/gpu/drm/drm_atomic_helper.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_shrinker.o
  CC [M]  drivers/thunderbolt/tunnel.o
  CC [M]  drivers/gpu/drm/drm_atomic_state_helper.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/arct_reg_init.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mxgpu_nv.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_stolen.o
  CC [M]  drivers/iio/common/hid-sensors/hid-sensor-attributes.o
  CC [M]  drivers/gpu/drm/radeon/r600_cs.o
  CC [M]  drivers/iio/common/hid-sensors/hid-sensor-trigger.o
  CC [M]  drivers/iio/gyro/hid-sensor-gyro-3d.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/nbio_v7_2.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllgt215.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_throttle.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_tiling.o
  CC [M]  drivers/gpu/drm/drm_bridge_connector.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_ttm.o
  CC [M]  drivers/thunderbolt/eeprom.o
  CC [M]  drivers/thunderbolt/domain.o
  CC [M]  drivers/thunderbolt/dma_port.o
  CC [M]  drivers/soundwire/intel.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/hdp_v4_0.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_bw.o
  CC [M]  drivers/soundwire/intel_ace2x.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_cdclk.o
  CC [M]  drivers/gpu/drm/drm_crtc_helper.o
  CC [M]  drivers/gpu/drm/drm_damage_helper.o
  CC [M]  drivers/gpu/drm/drm_encoder_slave.o
  LD [M]  drivers/mtd/spi-nor/spi-nor.o
  CC [M]  drivers/gpu/drm/drm_flip_work.o
  CC [M]  drivers/gpu/drm/drm_format_helper.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_color.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/hdp_v5_0.o
  CC [M]  drivers/gpu/drm/radeon/evergreen_cs.o
  CC [M]  drivers/gpu/drm/drm_gem_atomic_helper.o
  CC [M]  drivers/thunderbolt/icm.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_ttm_move.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.o
  CC [M]  drivers/thunderbolt/property.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_userptr.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/aldebaran_reg_init.o
  CC [M]  drivers/gpu/drm/drm_gem_framebuffer_helper.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/aldebaran.o
  LD [M]  drivers/mtd/mtd.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gem_wait.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.o
  CC [M]  drivers/gpu/drm/drm_kms_helper_common.o
  CC [M]  drivers/gpu/drm/i915/gem/i915_gemfs.o
  CC [M]  drivers/gpu/drm/i915/i915_active.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/soc21.o
  CC [M]  drivers/gpu/drm/i915/i915_cmd_parser.o
  CC [M]  drivers/gpu/drm/drm_modeset_helper.o
  CC [M]  drivers/gpu/drm/drm_plane_helper.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/sienna_cichlid.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.o
  CC [M]  drivers/gpu/drm/radeon/r100.o
  CC [M]  drivers/soundwire/intel_ace2x_debugfs.o
  CC [M]  drivers/soundwire/intel_auxdevice.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.o
  CC [M]  drivers/thunderbolt/xdomain.o
  CC [M]  drivers/soundwire/intel_init.o
  CC [M]  drivers/thunderbolt/lc.o
  CC [M]  drivers/soundwire/dmi-quirks.o
  LD [M]  drivers/iio/common/hid-sensors/hid-sensor-iio-common.o
  CC [M]  drivers/soundwire/intel_bus_common.o
  LD [M]  drivers/soundwire/soundwire-bus.o
  CC [M]  drivers/iio/light/hid-sensor-als.o
  CC [M]  drivers/iio/magnetometer/hid-sensor-magn-3d.o
  LD [M]  drivers/soundwire/soundwire-generic-allocation.o
  CC [M]  drivers/thunderbolt/tmu.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/nbio_v4_3.o
  CC [M]  drivers/gpu/drm/drm_probe_helper.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/hdp_v6_0.o
  LD [M]  drivers/soundwire/soundwire-cadence.o
  CC [M]  drivers/gpu/drm/drm_rect.o
  CC [M]  drivers/gpu/drm/drm_self_refresh_helper.o
  CC [M]  drivers/gpu/drm/i915/i915_deps.o
  CC [M]  drivers/gpu/drm/drm_simple_kms_helper.o
  CC [M]  drivers/gpu/drm/radeon/r300.o
  CC [M]  drivers/gpu/drm/radeon/r420.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/nbio_v7_7.o
  CC [M]  drivers/gpu/drm/bridge/panel.o
  CC [M]  drivers/gpu/drm/i915/i915_gem.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/hdp_v5_2.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv05.o
  CC [M]  drivers/iio/light/hid-sensor-prox.o
  CC [M]  drivers/gpu/drm/i915/i915_gem_evict.o
  CC [M]  drivers/gpu/drm/drm_fbdev_generic.o
  CC [M]  drivers/gpu/drm/i915/i915_gem_gtt.o
  CC [M]  drivers/gpu/drm/drm_fb_helper.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv10.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/lsdma_v6_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv1a.o
  CC [M]  drivers/thunderbolt/usb4.o
  CC [M]  drivers/thunderbolt/usb4_port.o
  CC [M]  drivers/thunderbolt/nvm.o
  CC [M]  drivers/thunderbolt/retimer.o
  CC [M]  drivers/iio/orientation/hid-sensor-incl-3d.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/nbio_v7_9.o
  CC [M]  drivers/thunderbolt/quirks.o
  CC [M]  drivers/iio/position/hid-sensor-custom-intel-hinge.o
  CC [M]  drivers/thunderbolt/clx.o
  CC [M]  drivers/gpu/drm/i915/i915_gem_ww.o
  CC [M]  drivers/iio/orientation/hid-sensor-rotation.o
  LD [M]  drivers/gpu/drm/drm.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_combo_phy.o
  CC [M]  drivers/gpu/drm/i915/i915_query.o
  CC [M]  drivers/thunderbolt/acpi.o
  CC [M]  drivers/gpu/drm/i915/i915_request.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv20.o
  LD [M]  drivers/gpu/drm/drm_shmem_helper.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_connector.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_crtc.o
  LD [M]  drivers/gpu/drm/drm_suballoc_helper.o
  LD [M]  drivers/gpu/drm/drm_ttm_helper.o
  AR      drivers/gpu/drm/built-in.a
  CC [M]  drivers/gpu/drm/i915/i915_scheduler.o
  CC [M]  drivers/iio/industrialio-core.o
  LD [M]  drivers/soundwire/soundwire-intel.o
  CC [M]  drivers/iio/industrialio-event.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/nbio_v7_11.o
  CC [M]  drivers/iio/inkern.o
  CC [M]  drivers/iio/industrialio-buffer.o
  CC [M]  drivers/thunderbolt/debugfs.o
  CC [M]  drivers/iio/industrialio-trigger.o
  CC [M]  drivers/gpu/drm/i915/i915_trace_points.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g84.o
  CC [M]  drivers/gpu/drm/i915/i915_ttm_buddy_manager.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/lsdma_v7_0.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/hdp_v7_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g98.o
  CC [M]  drivers/gpu/drm/i915/i915_vma.o
  CC [M]  drivers/gpu/drm/i915/i915_vma_resource.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/df_v1_7.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/df_v3_6.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/df_v4_3.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gt215.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_crtc_state_dump.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/df_v4_6_2.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gmc_v7_0.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_cursor.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gmc_v8_0.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gf100.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_debugfs.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_cx0_phy.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_ddi.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gmc_v9_0.o
  LD [M]  drivers/gpu/drm/radeon/radeon.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gv100.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu102.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.o
  LD [M]  drivers/thunderbolt/thunderbolt.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_guc.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_ddi_buf_trans.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_guc_ads.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_guc_capture.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/ga100.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.o
  LD [M]  drivers/gpu/drm/drm_kms_helper.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gmc_v10_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp10b.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_guc_fw.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_guc_log.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_guc_log_debugfs.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_device.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_driver.o
  LD [M]  drivers/iio/industrialio.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_guc_rc.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_irq.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_guc_submission.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_huc.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_params.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gmc_v11_0.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_huc_debugfs.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_huc_fw.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_uc.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_uc_debugfs.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.o
  CC [M]  drivers/gpu/drm/i915/gt/uc/intel_uc_fw.o
  CC [M]  drivers/gpu/drm/i915/gt/intel_gsc.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_power.o
  CC [M]  drivers/gpu/drm/i915/i915_hwmon.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_power_map.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.o
  CC [M]  drivers/gpu/drm/i915/display/hsw_ips.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.o
  CC [M]  drivers/gpu/drm/i915/display/i9xx_plane.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_power_well.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.o
  CC [M]  drivers/gpu/drm/i915/display/i9xx_wm.o
  CC [M]  drivers/gpu/drm/i915/display/intel_atomic.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfxhub_v11_5_0.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_trace.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/umc_v6_0.o
  CC [M]  drivers/gpu/drm/i915/display/intel_atomic_plane.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/umc_v6_1.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/umc_v6_7.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.o
  CC [M]  drivers/gpu/drm/i915/display/intel_audio.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/umc_v8_7.o
  CC [M]  drivers/gpu/drm/i915/display/intel_bios.o
  CC [M]  drivers/gpu/drm/i915/display/intel_bw.o
  CC [M]  drivers/gpu/drm/i915/display/intel_cdclk.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.o
  CC [M]  drivers/gpu/drm/i915/display/intel_color.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_wa.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dkl_phy.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dmc.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/umc_v8_10.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/mcp77.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/umc_v12_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/mcp89.o
  CC [M]  drivers/gpu/drm/i915/display/intel_combo_phy.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.o
  CC [M]  drivers/gpu/drm/i915/display/intel_connector.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dp.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_irq.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_ih.o
  CC [M]  drivers/gpu/drm/i915/display/intel_crtc.o
  CC [M]  drivers/gpu/drm/i915/display/intel_crtc_state_dump.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dp_aux.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/iceland_ih.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/tonga_ih.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.o
  CC [M]  drivers/gpu/drm/i915/display/intel_cursor.o
  CC [M]  drivers/gpu/drm/i915/display/intel_display.o
  CC [M]  drivers/gpu/drm/i915/display/intel_display_driver.o
  CC [M]  drivers/gpu/drm/i915/display/intel_display_irq.o
  CC [M]  drivers/gpu/drm/i915/display/intel_display_params.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/cz_ih.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk110.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/vega10_ih.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dp_aux_backlight.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/vega20_ih.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/navi10_ih.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/ih_v6_0.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dp_hdcp.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/ih_v6_1.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/ih_v7_0.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dp_link_training.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_psp.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/psp_v3_1.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dp_mst.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dpll.o
  CC [M]  drivers/gpu/drm/i915/display/intel_display_power.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dpll_mgr.o
  CC [M]  drivers/gpu/drm/i915/display/intel_display_power_map.o
  CC [M]  drivers/gpu/drm/i915/display/intel_display_power_well.o
  CC [M]  drivers/gpu/drm/i915/display/intel_display_reset.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.o
  CC [M]  drivers/gpu/drm/i915/display/intel_display_rps.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/psp_v10_0.o
  CC [M]  drivers/gpu/drm/i915/display/intel_display_wa.o
  CC [M]  drivers/gpu/drm/i915/display/intel_dmc.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/psp_v11_0.o
  CC [M]  drivers/gpu/drm/i915/display/intel_dpio_phy.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/psp_v12_0.o
  CC [M]  drivers/gpu/drm/i915/display/intel_dpll.o
  CC [M]  drivers/gpu/drm/i915/display/intel_dpll_mgr.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/psp_v13_0.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.o
  CC [M]  drivers/gpu/drm/i915/display/intel_dpt.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dpt_common.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/psp_v14_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_drrs.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/dce_v10_0.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/dce_v11_0.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dsb.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dsi.o
  CC [M]  drivers/gpu/drm/i915/display/intel_dpt_common.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.o
  CC [M]  drivers/gpu/drm/i915/display/intel_drrs.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dsi_dcs_backlight.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dsi_vbt.o
  CC [M]  drivers/gpu/drm/i915/display/intel_dsb.o
  CC [M]  drivers/gpu/drm/i915/display/intel_dsb_buffer.o
  CC [M]  drivers/gpu/drm/i915/display/intel_fb.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfx_v8_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfx_v9_0.o
  CC [M]  drivers/gpu/drm/i915/display/intel_fb_bo.o
  CC [M]  drivers/gpu/drm/i915/display/intel_fb_pin.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_fb.o
  CC [M]  drivers/gpu/drm/i915/display/intel_fbc.o
  CC [M]  drivers/gpu/drm/i915/display/intel_fdi.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_fbc.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_fdi.o
  CC [M]  drivers/gpu/drm/i915/display/intel_fifo_underrun.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_fifo_underrun.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfx_v9_4.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.o
  CC [M]  drivers/gpu/drm/i915/display/intel_frontbuffer.o
  CC [M]  drivers/gpu/drm/i915/display/intel_global_state.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfx_v10_0.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_frontbuffer.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/imu_v11_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_global_state.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_gmbus.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfx_v11_0.o
  CC [M]  drivers/gpu/drm/i915/display/intel_hdcp.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_hdcp.o
  CC [M]  drivers/gpu/drm/i915/display/intel_hdcp_gsc.o
  CC [M]  drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.o
  CC [M]  drivers/gpu/drm/i915/display/intel_hotplug.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/imu_v11_0_3.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_hdcp_gsc_message.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/r535.o
  CC [M]  drivers/gpu/drm/i915/display/intel_hotplug_irq.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_hdmi.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.o
  CC [M]  drivers/gpu/drm/i915/display/intel_hti.o
  CC [M]  drivers/gpu/drm/i915/display/intel_link_bw.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/sdma_v2_4.o
  CC [M]  drivers/gpu/drm/i915/display/intel_load_detect.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/sdma_v3_0.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_hotplug.o
  CC [M]  drivers/gpu/drm/i915/display/intel_lpe_audio.o
  CC [M]  drivers/gpu/drm/i915/display/intel_modeset_lock.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/sdma_v4_0.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_hotplug_irq.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_hti.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/sdma_v4_4.o
  CC [M]  drivers/gpu/drm/i915/display/intel_modeset_setup.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_link_bw.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_lspcon.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_modeset_lock.o
  CC [M]  drivers/gpu/drm/i915/display/intel_modeset_verify.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.o
  CC [M]  drivers/gpu/drm/i915/display/intel_overlay.o
  CC [M]  drivers/gpu/drm/i915/display/intel_pch_display.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.o
  CC [M]  drivers/gpu/drm/i915/display/intel_pch_refclk.o
  CC [M]  drivers/gpu/drm/i915/display/intel_plane_initial.o
  CC [M]  drivers/gpu/drm/i915/display/intel_pmdemand.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_modeset_setup.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_modeset_verify.o
  CC [M]  drivers/gpu/drm/i915/display/intel_psr.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_panel.o
  CC [M]  drivers/gpu/drm/i915/display/intel_quirks.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_pmdemand.o
  CC [M]  drivers/gpu/drm/i915/display/intel_sprite.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/sdma_v5_0.o
  CC [M]  drivers/gpu/drm/i915/display/intel_sprite_uapi.o
  CC [M]  drivers/gpu/drm/i915/display/intel_tc.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.o
  CC [M]  drivers/gpu/drm/i915/display/intel_vblank.o
  CC [M]  drivers/gpu/drm/i915/display/intel_vga.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_pps.o
  CC [M]  drivers/gpu/drm/i915/display/intel_wm.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/sdma_v5_2.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_psr.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_qp_tables.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/sdma_v6_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.o
  CC [M]  drivers/gpu/drm/i915/display/skl_scaler.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_quirks.o
  CC [M]  drivers/gpu/drm/i915/display/skl_universal_plane.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_snps_phy.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_tc.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_mes.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mes_v10_1.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_vblank.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_vdsc.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_vga.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_vrr.o
  CC [M]  drivers/gpu/drm/i915/display/skl_watermark.o
  CC [M]  drivers/gpu/drm/i915/display/intel_acpi.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.o
  CC [M]  drivers/gpu/drm/i915/display/intel_opregion.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/mes_v11_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_wm.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.o
  CC [M]  drivers/gpu/drm/i915/display/intel_fbdev.o
  CC [M]  drivers/gpu/drm/xe/i915-display/skl_scaler.o
  CC [M]  drivers/gpu/drm/i915/display/intel_fbdev_fb.o
  CC [M]  drivers/gpu/drm/i915/display/intel_display_debugfs.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.o
  CC [M]  drivers/gpu/drm/i915/display/intel_display_debugfs_params.o
  CC [M]  drivers/gpu/drm/i915/display/intel_pipe_crc.o
  CC [M]  drivers/gpu/drm/i915/display/dvo_ch7017.o
  CC [M]  drivers/gpu/drm/i915/display/dvo_ch7xxx.o
  CC [M]  drivers/gpu/drm/i915/display/dvo_ivch.o
  CC [M]  drivers/gpu/drm/xe/i915-display/skl_universal_plane.o
  CC [M]  drivers/gpu/drm/i915/display/dvo_ns2501.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/uvd_v5_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/uvd_v6_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp102.o
  CC [M]  drivers/gpu/drm/i915/display/dvo_sil164.o
  CC [M]  drivers/gpu/drm/xe/i915-display/skl_watermark.o
  CC [M]  drivers/gpu/drm/i915/display/dvo_tfp410.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_acpi.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_opregion.o
  CC [M]  drivers/gpu/drm/i915/display/g4x_dp.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.o
  CC [M]  drivers/gpu/drm/i915/display/g4x_hdmi.o
  CC [M]  drivers/gpu/drm/i915/display/icl_dsi.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/uvd_v7_0.o
  CC [M]  drivers/gpu/drm/i915/display/intel_backlight.o
  CC [M]  drivers/gpu/drm/i915/display/intel_crt.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_vce.o
  CC [M]  drivers/gpu/drm/i915/display/intel_cx0_phy.o
  CC [M]  drivers/gpu/drm/i915/display/intel_ddi.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_fbdev.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_debugfs.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fuse/base.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fuse/nv50.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_debugfs_params.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/vce_v3_0.o
  CC [M]  drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gf100.o
  CC [M]  drivers/gpu/drm/i915/display/intel_



^ permalink raw reply	[flat|nested] 76+ messages in thread

* ✗ CI.Hooks: failure for Refactor VM bind code (rev5)
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (33 preceding siblings ...)
  2024-03-08  5:55 ` ✓ CI.Build: " Patchwork
@ 2024-03-08  5:55 ` Patchwork
  2024-03-08  5:56 ` ✓ CI.checksparse: success " Patchwork
  2024-03-08  6:26 ` ✗ CI.BAT: failure " Patchwork
  36 siblings, 0 replies; 76+ messages in thread
From: Patchwork @ 2024-03-08  5:55 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe

== Series Details ==

Series: Refactor VM bind code (rev5)
URL   : https://patchwork.freedesktop.org/series/125608/
State : failure

== Summary ==

run-parts: executing /workspace/ci/hooks/00-showenv
+ export
+ grep -Ei '(^|\W)CI_'
declare -x CI_KERNEL_BUILD_DIR="/workspace/kernel/build64-default"
declare -x CI_KERNEL_SRC_DIR="/workspace/kernel"
declare -x CI_TOOLS_SRC_DIR="/workspace/ci"
declare -x CI_WORKSPACE_DIR="/workspace"
run-parts: executing /workspace/ci/hooks/10-build-W1
+ SRC_DIR=/workspace/kernel
+ RESTORE_DISPLAY_CONFIG=0
+ '[' -n /workspace/kernel/build64-default ']'
+ BUILD_DIR=/workspace/kernel/build64-default
+ cd /workspace/kernel
++ nproc
+ make -j48 O=/workspace/kernel/build64-default modules_prepare
make[1]: Entering directory '/workspace/kernel/build64-default'
  GEN     Makefile
  UPD     include/generated/compile.h
mkdir -p /workspace/kernel/build64-default/tools/objtool && make O=/workspace/kernel/build64-default subdir=tools/objtool --no-print-directory -C objtool 
  UPD     include/config/kernel.release
  UPD     include/generated/utsrelease.h
  HOSTCC  /workspace/kernel/build64-default/tools/objtool/fixdep.o
  CALL    ../scripts/checksyscalls.sh
  HOSTLD  /workspace/kernel/build64-default/tools/objtool/fixdep-in.o
  LINK    /workspace/kernel/build64-default/tools/objtool/fixdep
  INSTALL libsubcmd_headers
  CC      /workspace/kernel/build64-default/tools/objtool/libsubcmd/exec-cmd.o
  CC      /workspace/kernel/build64-default/tools/objtool/libsubcmd/help.o
  CC      /workspace/kernel/build64-default/tools/objtool/libsubcmd/pager.o
  CC      /workspace/kernel/build64-default/tools/objtool/libsubcmd/parse-options.o
  CC      /workspace/kernel/build64-default/tools/objtool/libsubcmd/run-command.o
  CC      /workspace/kernel/build64-default/tools/objtool/libsubcmd/sigchain.o
  CC      /workspace/kernel/build64-default/tools/objtool/libsubcmd/subcmd-config.o
  LD      /workspace/kernel/build64-default/tools/objtool/libsubcmd/libsubcmd-in.o
  AR      /workspace/kernel/build64-default/tools/objtool/libsubcmd/libsubcmd.a
  CC      /workspace/kernel/build64-default/tools/objtool/weak.o
  CC      /workspace/kernel/build64-default/tools/objtool/check.o
  CC      /workspace/kernel/build64-default/tools/objtool/special.o
  CC      /workspace/kernel/build64-default/tools/objtool/builtin-check.o
  CC      /workspace/kernel/build64-default/tools/objtool/elf.o
  CC      /workspace/kernel/build64-default/tools/objtool/objtool.o
  CC      /workspace/kernel/build64-default/tools/objtool/orc_gen.o
  CC      /workspace/kernel/build64-default/tools/objtool/orc_dump.o
  CC      /workspace/kernel/build64-default/tools/objtool/libstring.o
  CC      /workspace/kernel/build64-default/tools/objtool/libctype.o
  CC      /workspace/kernel/build64-default/tools/objtool/str_error_r.o
  CC      /workspace/kernel/build64-default/tools/objtool/librbtree.o
  CC      /workspace/kernel/build64-default/tools/objtool/arch/x86/special.o
  CC      /workspace/kernel/build64-default/tools/objtool/arch/x86/decode.o
  LD      /workspace/kernel/build64-default/tools/objtool/arch/x86/objtool-in.o
  LD      /workspace/kernel/build64-default/tools/objtool/objtool-in.o
  LINK    /workspace/kernel/build64-default/tools/objtool/objtool
make[1]: Leaving directory '/workspace/kernel/build64-default'
++ nproc
+ make -j48 O=/workspace/kernel/build64-default M=drivers/gpu/drm/xe W=1
make[1]: Entering directory '/workspace/kernel/build64-default'
  CC [M]  drivers/gpu/drm/xe/xe_bb.o
  CC [M]  drivers/gpu/drm/xe/xe_bo.o
  CC [M]  drivers/gpu/drm/xe/xe_bo_evict.o
  CC [M]  drivers/gpu/drm/xe/xe_debugfs.o
  CC [M]  drivers/gpu/drm/xe/xe_devcoredump.o
  CC [M]  drivers/gpu/drm/xe/xe_device.o
  CC [M]  drivers/gpu/drm/xe/xe_device_sysfs.o
  CC [M]  drivers/gpu/drm/xe/xe_dma_buf.o
  CC [M]  drivers/gpu/drm/xe/xe_drm_client.o
  CC [M]  drivers/gpu/drm/xe/xe_exec.o
  CC [M]  drivers/gpu/drm/xe/xe_execlist.o
  CC [M]  drivers/gpu/drm/xe/xe_exec_queue.o
  CC [M]  drivers/gpu/drm/xe/xe_force_wake.o
  CC [M]  drivers/gpu/drm/xe/xe_ggtt.o
  CC [M]  drivers/gpu/drm/xe/xe_gpu_scheduler.o
  HOSTCC  drivers/gpu/drm/xe/xe_gen_wa_oob
  CC [M]  drivers/gpu/drm/xe/xe_gsc_proxy.o
  CC [M]  drivers/gpu/drm/xe/xe_gsc_submit.o
  CC [M]  drivers/gpu/drm/xe/xe_gt.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_ccs_mode.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_clock.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_debugfs.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_freq.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_idle.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_mcr.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_pagefault.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_sysfs.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_throttle_sysfs.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_tlb_invalidation.o
  CC [M]  drivers/gpu/drm/xe/xe_gt_topology.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_ads.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_ct.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_db_mgr.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_debugfs.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_hwconfig.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_log.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_pc.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_submit.o
  CC [M]  drivers/gpu/drm/xe/xe_heci_gsc.o
  CC [M]  drivers/gpu/drm/xe/xe_hw_engine.o
  CC [M]  drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.o
  CC [M]  drivers/gpu/drm/xe/xe_hw_fence.o
  CC [M]  drivers/gpu/drm/xe/xe_huc.o
  CC [M]  drivers/gpu/drm/xe/xe_huc_debugfs.o
  CC [M]  drivers/gpu/drm/xe/xe_irq.o
  CC [M]  drivers/gpu/drm/xe/xe_lrc.o
  CC [M]  drivers/gpu/drm/xe/xe_mmio.o
  CC [M]  drivers/gpu/drm/xe/xe_mocs.o
  CC [M]  drivers/gpu/drm/xe/xe_module.o
  CC [M]  drivers/gpu/drm/xe/xe_pat.o
  CC [M]  drivers/gpu/drm/xe/xe_pci.o
  CC [M]  drivers/gpu/drm/xe/xe_pcode.o
  CC [M]  drivers/gpu/drm/xe/xe_pm.o
  CC [M]  drivers/gpu/drm/xe/xe_preempt_fence.o
  CC [M]  drivers/gpu/drm/xe/xe_pt.o
  CC [M]  drivers/gpu/drm/xe/xe_pt_exec_queue.o
  CC [M]  drivers/gpu/drm/xe/xe_pt_walk.o
../drivers/gpu/drm/xe/xe_gsc_submit.c:50: warning: expecting prototype for xe_gsc_get_host_session_id(). Prototype was for xe_gsc_create_host_session_id() instead
  CC [M]  drivers/gpu/drm/xe/xe_query.o
  CC [M]  drivers/gpu/drm/xe/xe_range_fence.o
  CC [M]  drivers/gpu/drm/xe/xe_reg_sr.o
  CC [M]  drivers/gpu/drm/xe/xe_reg_whitelist.o
  CC [M]  drivers/gpu/drm/xe/xe_rtp.o
  GEN     xe_wa_oob.c xe_wa_oob.h
  CC [M]  drivers/gpu/drm/xe/xe_sa.o
  CC [M]  drivers/gpu/drm/xe/xe_sched_job.o
  CC [M]  drivers/gpu/drm/xe/xe_step.o
  CC [M]  drivers/gpu/drm/xe/xe_sync.o
  CC [M]  drivers/gpu/drm/xe/xe_tile.o
  CC [M]  drivers/gpu/drm/xe/xe_tile_sysfs.o
  CC [M]  drivers/gpu/drm/xe/xe_trace.o
  CC [M]  drivers/gpu/drm/xe/xe_ttm_sys_mgr.o
  CC [M]  drivers/gpu/drm/xe/xe_ttm_stolen_mgr.o
  CC [M]  drivers/gpu/drm/xe/xe_ttm_vram_mgr.o
  CC [M]  drivers/gpu/drm/xe/xe_tuning.o
  CC [M]  drivers/gpu/drm/xe/xe_uc.o
  CC [M]  drivers/gpu/drm/xe/xe_uc_debugfs.o
  CC [M]  drivers/gpu/drm/xe/xe_uc_fw.o
  CC [M]  drivers/gpu/drm/xe/xe_vm.o
  CC [M]  drivers/gpu/drm/xe/xe_vram_freq.o
  CC [M]  drivers/gpu/drm/xe/xe_wait_user_fence.o
  CC [M]  drivers/gpu/drm/xe/xe_wa.o
  CC [M]  drivers/gpu/drm/xe/xe_wopcm.o
  CC [M]  drivers/gpu/drm/xe/xe_hwmon.o
  CC [M]  drivers/gpu/drm/xe/xe_guc_relay.o
  CC [M]  drivers/gpu/drm/xe/xe_memirq.o
  CC [M]  drivers/gpu/drm/xe/xe_sriov.o
  CC [M]  drivers/gpu/drm/xe/xe_lmtt.o
  CC [M]  drivers/gpu/drm/xe/xe_lmtt_2l.o
  CC [M]  drivers/gpu/drm/xe/xe_lmtt_ml.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_kunit_helpers.o
  CC [M]  drivers/gpu/drm/xe/display/ext/i915_irq.o
  CC [M]  drivers/gpu/drm/xe/display/ext/i915_utils.o
  CC [M]  drivers/gpu/drm/xe/display/intel_fb_bo.o
  CC [M]  drivers/gpu/drm/xe/display/intel_fbdev_fb.o
  CC [M]  drivers/gpu/drm/xe/display/xe_display.o
  CC [M]  drivers/gpu/drm/xe/display/xe_display_misc.o
  CC [M]  drivers/gpu/drm/xe/display/xe_display_rps.o
  CC [M]  drivers/gpu/drm/xe/display/xe_dsb_buffer.o
  CC [M]  drivers/gpu/drm/xe/display/xe_fb_pin.o
  CC [M]  drivers/gpu/drm/xe/display/xe_hdcp_gsc.o
  CC [M]  drivers/gpu/drm/xe/display/xe_plane_initial.o
  CC [M]  drivers/gpu/drm/xe/i915-soc/intel_dram.o
  CC [M]  drivers/gpu/drm/xe/i915-soc/intel_pch.o
  CC [M]  drivers/gpu/drm/xe/i915-display/icl_dsi.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_atomic.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_atomic_plane.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_audio.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_backlight.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_bios.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_bw.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_cdclk.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_color.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_combo_phy.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_connector.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_crtc.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_crtc_state_dump.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_cursor.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_cx0_phy.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_ddi.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_ddi_buf_trans.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_device.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_driver.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_irq.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_params.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_power.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_power_map.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_power_well.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_trace.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_wa.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dkl_phy.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dmc.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dp.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dp_aux.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dp_aux_backlight.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dp_hdcp.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dp_link_training.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dp_mst.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dpll.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dpll_mgr.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dpt_common.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_drrs.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dsb.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dsi.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dsi_dcs_backlight.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_dsi_vbt.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_fb.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_fbc.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_fdi.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_fifo_underrun.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_frontbuffer.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_global_state.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_gmbus.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_hdcp.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_hdcp_gsc_message.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_hdmi.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_hotplug.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_hotplug_irq.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_hti.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_link_bw.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_lspcon.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_modeset_lock.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_modeset_setup.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_modeset_verify.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_panel.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_pmdemand.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_pps.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_psr.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_qp_tables.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_quirks.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_snps_phy.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_tc.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_vblank.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_vdsc.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_vga.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_vrr.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_wm.o
  CC [M]  drivers/gpu/drm/xe/i915-display/skl_scaler.o
  CC [M]  drivers/gpu/drm/xe/i915-display/skl_universal_plane.o
  CC [M]  drivers/gpu/drm/xe/i915-display/skl_watermark.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_acpi.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_opregion.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_fbdev.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_debugfs.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_display_debugfs_params.o
  CC [M]  drivers/gpu/drm/xe/i915-display/intel_pipe_crc.o
  HDRTEST drivers/gpu/drm/xe/abi/gsc_proxy_commands_abi.h
  HDRTEST drivers/gpu/drm/xe/abi/guc_klvs_abi.h
  HDRTEST drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
  HDRTEST drivers/gpu/drm/xe/abi/guc_actions_sriov_abi.h
  HDRTEST drivers/gpu/drm/xe/abi/guc_errors_abi.h
  HDRTEST drivers/gpu/drm/xe/abi/guc_actions_slpc_abi.h
  HDRTEST drivers/gpu/drm/xe/abi/guc_relay_actions_abi.h
  HDRTEST drivers/gpu/drm/xe/abi/gsc_mkhi_commands_abi.h
  CC [M]  drivers/gpu/drm/xe/tests/xe_bo_test.o
  HDRTEST drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h
  CC [M]  drivers/gpu/drm/xe/tests/xe_dma_buf_test.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_migrate_test.o
  HDRTEST drivers/gpu/drm/xe/abi/guc_relay_communication_abi.h
  CC [M]  drivers/gpu/drm/xe/tests/xe_mocs_test.o
  HDRTEST drivers/gpu/drm/xe/abi/guc_communication_mmio_abi.h
  HDRTEST drivers/gpu/drm/xe/abi/guc_actions_abi.h
  HDRTEST drivers/gpu/drm/xe/abi/guc_communication_ctb_abi.h
  HDRTEST drivers/gpu/drm/xe/abi/guc_messages_abi.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_gem.h
  CC [M]  drivers/gpu/drm/xe/tests/xe_test_mod.o
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_vma_types.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h
  CC [M]  drivers/gpu/drm/xe/tests/xe_pci_test.o
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband_reg.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/intel_wakeref.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/intel_pcode.h
  CC [M]  drivers/gpu/drm/xe/tests/xe_rtp_test.o
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
  CC [M]  drivers/gpu/drm/xe/tests/xe_wa_test.o
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_reg_defs.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_trace.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_reg.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_active_types.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_config.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_vma.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_gem_stolen.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/intel_mchbar_regs.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_debugfs.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_gpu_error.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/soc/intel_pch.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/soc/intel_gmch.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_fixed.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/intel_runtime_pm.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/intel_step.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/intel_uc_fw.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/intel_pci_config.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_lmem.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_mman.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object_frontbuffer.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/gt/intel_rps.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/intel_clock_gating.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/intel_gt_types.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h
  HDRTEST drivers/gpu/drm/xe/compat-i915-headers/i915_active.h
  HDRTEST drivers/gpu/drm/xe/display/xe_display.h
  HDRTEST drivers/gpu/drm/xe/display/intel_fb_bo.h
  HDRTEST drivers/gpu/drm/xe/display/intel_fbdev_fb.h
  HDRTEST drivers/gpu/drm/xe/instructions/xe_gfx_state_commands.h
  HDRTEST drivers/gpu/drm/xe/instructions/xe_instr_defs.h
  HDRTEST drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
  HDRTEST drivers/gpu/drm/xe/instructions/xe_gfxpipe_commands.h
  HDRTEST drivers/gpu/drm/xe/instructions/xe_mi_commands.h
  HDRTEST drivers/gpu/drm/xe/regs/xe_gsc_regs.h
  HDRTEST drivers/gpu/drm/xe/regs/xe_reg_defs.h
  HDRTEST drivers/gpu/drm/xe/regs/xe_guc_regs.h
  HDRTEST drivers/gpu/drm/xe/regs/xe_gt_regs.h
  HDRTEST drivers/gpu/drm/xe/regs/xe_regs.h
  HDRTEST drivers/gpu/drm/xe/regs/xe_pcode_regs.h
  HDRTEST drivers/gpu/drm/xe/regs/xe_gpu_commands.h
  HDRTEST drivers/gpu/drm/xe/regs/xe_sriov_regs.h
  HDRTEST drivers/gpu/drm/xe/regs/xe_lrc_layout.h
  HDRTEST drivers/gpu/drm/xe/regs/xe_mchbar_regs.h
  HDRTEST drivers/gpu/drm/xe/regs/xe_engine_regs.h
  HDRTEST drivers/gpu/drm/xe/tests/xe_test.h
  HDRTEST drivers/gpu/drm/xe/tests/xe_kunit_helpers.h
  HDRTEST drivers/gpu/drm/xe/tests/xe_pci_test.h
  HDRTEST drivers/gpu/drm/xe/tests/xe_migrate_test.h
  HDRTEST drivers/gpu/drm/xe/tests/xe_dma_buf_test.h
  HDRTEST drivers/gpu/drm/xe/tests/xe_mocs_test.h
  HDRTEST drivers/gpu/drm/xe/tests/xe_bo_test.h
  HDRTEST drivers/gpu/drm/xe/xe_assert.h
  HDRTEST drivers/gpu/drm/xe/xe_bb.h
  HDRTEST drivers/gpu/drm/xe/xe_bb_types.h
  HDRTEST drivers/gpu/drm/xe/xe_bo.h
  HDRTEST drivers/gpu/drm/xe/xe_bo_doc.h
  HDRTEST drivers/gpu/drm/xe/xe_bo_evict.h
  HDRTEST drivers/gpu/drm/xe/xe_bo_types.h
  HDRTEST drivers/gpu/drm/xe/xe_debugfs.h
  HDRTEST drivers/gpu/drm/xe/xe_devcoredump.h
  HDRTEST drivers/gpu/drm/xe/xe_devcoredump_types.h
  HDRTEST drivers/gpu/drm/xe/xe_device.h
  HDRTEST drivers/gpu/drm/xe/xe_device_sysfs.h
  HDRTEST drivers/gpu/drm/xe/xe_device_types.h
  HDRTEST drivers/gpu/drm/xe/xe_dma_buf.h
  HDRTEST drivers/gpu/drm/xe/xe_drm_client.h
  HDRTEST drivers/gpu/drm/xe/xe_drv.h
  HDRTEST drivers/gpu/drm/xe/xe_exec.h
  HDRTEST drivers/gpu/drm/xe/xe_exec_queue.h
  HDRTEST drivers/gpu/drm/xe/xe_exec_queue_types.h
  HDRTEST drivers/gpu/drm/xe/xe_execlist.h
  HDRTEST drivers/gpu/drm/xe/xe_execlist_types.h
  HDRTEST drivers/gpu/drm/xe/xe_force_wake.h
  HDRTEST drivers/gpu/drm/xe/xe_force_wake_types.h
  HDRTEST drivers/gpu/drm/xe/xe_ggtt.h
  HDRTEST drivers/gpu/drm/xe/xe_ggtt_types.h
  HDRTEST drivers/gpu/drm/xe/xe_gpu_scheduler.h
  HDRTEST drivers/gpu/drm/xe/xe_gpu_scheduler_types.h
  HDRTEST drivers/gpu/drm/xe/xe_gsc.h
  HDRTEST drivers/gpu/drm/xe/xe_gsc_proxy.h
  HDRTEST drivers/gpu/drm/xe/xe_gsc_submit.h
  HDRTEST drivers/gpu/drm/xe/xe_gsc_types.h
  HDRTEST drivers/gpu/drm/xe/xe_gt.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_ccs_mode.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_clock.h
  LD [M]  drivers/gpu/drm/xe/tests/xe_test.o
  HDRTEST drivers/gpu/drm/xe/xe_gt_debugfs.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_freq.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_idle.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_idle_types.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_mcr.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_pagefault.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_printk.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_sriov_printk.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_sysfs.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_sysfs_types.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_throttle_sysfs.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_tlb_invalidation_types.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_topology.h
  HDRTEST drivers/gpu/drm/xe/xe_gt_types.h
  HDRTEST drivers/gpu/drm/xe/xe_guc.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_ads.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_ads_types.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_ct.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_ct_types.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_db_mgr.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_debugfs.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_exec_queue_types.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_fwif.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_hwconfig.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_hxg_helpers.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_log.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_log_types.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_pc.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_pc_types.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_relay.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_relay_types.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_submit.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_submit_types.h
  HDRTEST drivers/gpu/drm/xe/xe_guc_types.h
  HDRTEST drivers/gpu/drm/xe/xe_heci_gsc.h
  HDRTEST drivers/gpu/drm/xe/xe_huc.h
  HDRTEST drivers/gpu/drm/xe/xe_huc_debugfs.h
  HDRTEST drivers/gpu/drm/xe/xe_huc_types.h
  HDRTEST drivers/gpu/drm/xe/xe_hw_engine.h
  HDRTEST drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.h
  HDRTEST drivers/gpu/drm/xe/xe_hw_engine_types.h
  HDRTEST drivers/gpu/drm/xe/xe_hw_fence.h
  HDRTEST drivers/gpu/drm/xe/xe_hw_fence_types.h
  HDRTEST drivers/gpu/drm/xe/xe_hwmon.h
  HDRTEST drivers/gpu/drm/xe/xe_irq.h
  HDRTEST drivers/gpu/drm/xe/xe_lmtt.h
  HDRTEST drivers/gpu/drm/xe/xe_lmtt_types.h
  HDRTEST drivers/gpu/drm/xe/xe_lrc.h
  HDRTEST drivers/gpu/drm/xe/xe_lrc_types.h
  HDRTEST drivers/gpu/drm/xe/xe_macros.h
  HDRTEST drivers/gpu/drm/xe/xe_map.h
  HDRTEST drivers/gpu/drm/xe/xe_memirq.h
  HDRTEST drivers/gpu/drm/xe/xe_memirq_types.h
  HDRTEST drivers/gpu/drm/xe/xe_migrate.h
  HDRTEST drivers/gpu/drm/xe/xe_migrate_doc.h
  HDRTEST drivers/gpu/drm/xe/xe_mmio.h
  HDRTEST drivers/gpu/drm/xe/xe_mocs.h
  HDRTEST drivers/gpu/drm/xe/xe_module.h
  HDRTEST drivers/gpu/drm/xe/xe_pat.h
  HDRTEST drivers/gpu/drm/xe/xe_pci.h
  HDRTEST drivers/gpu/drm/xe/xe_pci_types.h
  HDRTEST drivers/gpu/drm/xe/xe_pcode.h
  HDRTEST drivers/gpu/drm/xe/xe_pcode_api.h
  HDRTEST drivers/gpu/drm/xe/xe_platform_types.h
  HDRTEST drivers/gpu/drm/xe/xe_pm.h
  HDRTEST drivers/gpu/drm/xe/xe_preempt_fence.h
  HDRTEST drivers/gpu/drm/xe/xe_preempt_fence_types.h
  HDRTEST drivers/gpu/drm/xe/xe_pt.h
  HDRTEST drivers/gpu/drm/xe/xe_pt_exec_queue.h
  HDRTEST drivers/gpu/drm/xe/xe_pt_types.h
  HDRTEST drivers/gpu/drm/xe/xe_pt_walk.h
  HDRTEST drivers/gpu/drm/xe/xe_query.h
  HDRTEST drivers/gpu/drm/xe/xe_range_fence.h
  HDRTEST drivers/gpu/drm/xe/xe_reg_sr.h
  HDRTEST drivers/gpu/drm/xe/xe_reg_sr_types.h
  HDRTEST drivers/gpu/drm/xe/xe_reg_whitelist.h
  HDRTEST drivers/gpu/drm/xe/xe_res_cursor.h
  HDRTEST drivers/gpu/drm/xe/xe_ring_ops.h
  HDRTEST drivers/gpu/drm/xe/xe_ring_ops_types.h
  HDRTEST drivers/gpu/drm/xe/xe_rtp.h
  HDRTEST drivers/gpu/drm/xe/xe_rtp_types.h
  HDRTEST drivers/gpu/drm/xe/xe_sa.h
  HDRTEST drivers/gpu/drm/xe/xe_sa_types.h
  HDRTEST drivers/gpu/drm/xe/xe_sched_job.h
  HDRTEST drivers/gpu/drm/xe/xe_sched_job_types.h
  HDRTEST drivers/gpu/drm/xe/xe_sriov.h
  HDRTEST drivers/gpu/drm/xe/xe_sriov_printk.h
  HDRTEST drivers/gpu/drm/xe/xe_sriov_types.h
  HDRTEST drivers/gpu/drm/xe/xe_step.h
  HDRTEST drivers/gpu/drm/xe/xe_step_types.h
  HDRTEST drivers/gpu/drm/xe/xe_sync.h
  HDRTEST drivers/gpu/drm/xe/xe_sync_types.h
  HDRTEST drivers/gpu/drm/xe/xe_tile.h
  HDRTEST drivers/gpu/drm/xe/xe_tile_sysfs.h
  HDRTEST drivers/gpu/drm/xe/xe_tile_sysfs_types.h
  HDRTEST drivers/gpu/drm/xe/xe_trace.h
  HDRTEST drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h
  HDRTEST drivers/gpu/drm/xe/xe_ttm_sys_mgr.h
  HDRTEST drivers/gpu/drm/xe/xe_ttm_vram_mgr.h
  HDRTEST drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
  HDRTEST drivers/gpu/drm/xe/xe_tuning.h
  HDRTEST drivers/gpu/drm/xe/xe_uc.h
  HDRTEST drivers/gpu/drm/xe/xe_uc_debugfs.h
  HDRTEST drivers/gpu/drm/xe/xe_uc_fw.h
  HDRTEST drivers/gpu/drm/xe/xe_uc_fw_abi.h
  HDRTEST drivers/gpu/drm/xe/xe_uc_fw_types.h
  HDRTEST drivers/gpu/drm/xe/xe_uc_types.h
  HDRTEST drivers/gpu/drm/xe/xe_vm.h
  HDRTEST drivers/gpu/drm/xe/xe_vm_doc.h
  HDRTEST drivers/gpu/drm/xe/xe_vm_types.h
  HDRTEST drivers/gpu/drm/xe/xe_vram_freq.h
  HDRTEST drivers/gpu/drm/xe/xe_wa.h
  HDRTEST drivers/gpu/drm/xe/xe_wait_user_fence.h
  HDRTEST drivers/gpu/drm/xe/xe_wopcm.h
  HDRTEST drivers/gpu/drm/xe/xe_wopcm_types.h
  CC [M]  drivers/gpu/drm/xe/xe_gsc.o
  CC [M]  drivers/gpu/drm/xe/xe_guc.o
  CC [M]  drivers/gpu/drm/xe/xe_migrate.o
  CC [M]  drivers/gpu/drm/xe/xe_ring_ops.o
  LD [M]  drivers/gpu/drm/xe/xe.o
  MODPOST drivers/gpu/drm/xe/Module.symvers
  CC [M]  drivers/gpu/drm/xe/xe.mod.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_bo_test.mod.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_dma_buf_test.mod.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_migrate_test.mod.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_mocs_test.mod.o
  CC [M]  drivers/gpu/drm/xe/tests/xe_test.mod.o
  LD [M]  drivers/gpu/drm/xe/tests/xe_test.ko
  LD [M]  drivers/gpu/drm/xe/tests/xe_migrate_test.ko
  LD [M]  drivers/gpu/drm/xe/tests/xe_dma_buf_test.ko
  LD [M]  drivers/gpu/drm/xe/tests/xe_bo_test.ko
  LD [M]  drivers/gpu/drm/xe/xe.ko
  LD [M]  drivers/gpu/drm/xe/tests/xe_mocs_test.ko
make[1]: Leaving directory '/workspace/kernel/build64-default'
run-parts: executing /workspace/ci/hooks/20-kernel-doc
+ SRC_DIR=/workspace/kernel
+ cd /workspace/kernel
+ find drivers/gpu/drm/xe/ -name '*.[ch]' -not -path 'drivers/gpu/drm/xe/display/*'
+ xargs ./scripts/kernel-doc -Werror -none include/uapi/drm/xe_drm.h
drivers/gpu/drm/xe/xe_gsc_submit.c:51: warning: expecting prototype for xe_gsc_get_host_session_id(). Prototype was for xe_gsc_create_host_session_id() instead
1 warnings as Errors
run-parts: /workspace/ci/hooks/20-kernel-doc exited with return code 123



^ permalink raw reply	[flat|nested] 76+ messages in thread

* ✓ CI.checksparse: success for Refactor VM bind code (rev5)
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (34 preceding siblings ...)
  2024-03-08  5:55 ` ✗ CI.Hooks: failure " Patchwork
@ 2024-03-08  5:56 ` Patchwork
  2024-03-08  6:26 ` ✗ CI.BAT: failure " Patchwork
  36 siblings, 0 replies; 76+ messages in thread
From: Patchwork @ 2024-03-08  5:56 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe

== Series Details ==

Series: Refactor VM bind code (rev5)
URL   : https://patchwork.freedesktop.org/series/125608/
State : success

== Summary ==

+ trap cleanup EXIT
+ KERNEL=/kernel
+ MT=/root/linux/maintainer-tools
+ git clone https://gitlab.freedesktop.org/drm/maintainer-tools /root/linux/maintainer-tools
Cloning into '/root/linux/maintainer-tools'...
warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
+ make -C /root/linux/maintainer-tools
make: Entering directory '/root/linux/maintainer-tools'
cc -O2 -g -Wextra -o remap-log remap-log.c
make: Leaving directory '/root/linux/maintainer-tools'
+ cd /kernel
+ git config --global --add safe.directory /kernel
+ /root/linux/maintainer-tools/dim sparse --fast ee6e5c86f4d587b4ce1093eceae7d50e3f3a7c6b
Sparse version: 0.6.1 (Ubuntu: 0.6.1-2build1)
Fast mode used, each commit won't be checked separately.
Okay!

+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel



^ permalink raw reply	[flat|nested] 76+ messages in thread

* ✗ CI.BAT: failure for Refactor VM bind code (rev5)
  2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
                   ` (35 preceding siblings ...)
  2024-03-08  5:56 ` ✓ CI.checksparse: success " Patchwork
@ 2024-03-08  6:26 ` Patchwork
  36 siblings, 0 replies; 76+ messages in thread
From: Patchwork @ 2024-03-08  6:26 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe

[-- Attachment #1: Type: text/plain, Size: 3283 bytes --]

== Series Details ==

Series: Refactor VM bind code (rev5)
URL   : https://patchwork.freedesktop.org/series/125608/
State : failure

== Summary ==

CI Bug Log - changes from xe-919-ee6e5c86f4d587b4ce1093eceae7d50e3f3a7c6b_BAT -> xe-pw-125608v5_BAT
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with xe-pw-125608v5_BAT absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in xe-pw-125608v5_BAT, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Participating hosts (4 -> 4)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in xe-pw-125608v5_BAT:

### IGT changes ###

#### Possible regressions ####

  * igt@xe_exec_threads@threads-mixed-shared-vm-userptr-invalidate-race:
    - bat-atsm-2:         [PASS][1] -> [INCOMPLETE][2]
   [1]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-919-ee6e5c86f4d587b4ce1093eceae7d50e3f3a7c6b/bat-atsm-2/igt@xe_exec_threads@threads-mixed-shared-vm-userptr-invalidate-race.html
   [2]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-125608v5/bat-atsm-2/igt@xe_exec_threads@threads-mixed-shared-vm-userptr-invalidate-race.html
    - bat-dg2-oem2:       [PASS][3] -> [ABORT][4]
   [3]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-919-ee6e5c86f4d587b4ce1093eceae7d50e3f3a7c6b/bat-dg2-oem2/igt@xe_exec_threads@threads-mixed-shared-vm-userptr-invalidate-race.html
   [4]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-125608v5/bat-dg2-oem2/igt@xe_exec_threads@threads-mixed-shared-vm-userptr-invalidate-race.html

  
#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * {igt@xe_exec_queue_property@invalid-property}:
    - bat-dg2-oem2:       [PASS][5] -> [FAIL][6]
   [5]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-919-ee6e5c86f4d587b4ce1093eceae7d50e3f3a7c6b/bat-dg2-oem2/igt@xe_exec_queue_property@invalid-property.html
   [6]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-125608v5/bat-dg2-oem2/igt@xe_exec_queue_property@invalid-property.html
    - bat-atsm-2:         [PASS][7] -> [FAIL][8]
   [7]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-919-ee6e5c86f4d587b4ce1093eceae7d50e3f3a7c6b/bat-atsm-2/igt@xe_exec_queue_property@invalid-property.html
   [8]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-125608v5/bat-atsm-2/igt@xe_exec_queue_property@invalid-property.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).



Build changes
-------------

  * Linux: xe-919-ee6e5c86f4d587b4ce1093eceae7d50e3f3a7c6b -> xe-pw-125608v5

  IGT_7749: 2fd91b8c3cf9aa2b0bb78537a6b5e2bc3de50e0e @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  xe-919-ee6e5c86f4d587b4ce1093eceae7d50e3f3a7c6b: ee6e5c86f4d587b4ce1093eceae7d50e3f3a7c6b
  xe-pw-125608v5: 125608v5

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-125608v5/index.html

[-- Attachment #2: Type: text/html, Size: 3933 bytes --]

^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL
  2024-03-08  5:07 ` [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL Matthew Brost
@ 2024-03-10 17:44   ` Zeng, Oak
  2024-03-11 19:48     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-10 17:44 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew



> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL
> 
> Lock all gpuva ops

Can we have a better wording? Better to say locking all Bos used in gpuva ops? 

Or maybe lock ops by locking and validating all Bos used in ops.

 and validate all BOs in a single step durin the VM
> bind IOCTL. This help with the transition to making all gpuva ops in a
> VM bind IOCTL a single atomic job.

Can you also explain, why you want bind to be a atomic job? 

My guess is, bind ioctl can end up with a series of operations, if some (not all) of those operations fail in the middle, it is hard to revert the successful operations before failure. 
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm.c | 142 ++++++++++++++++++++++++++-----------
>  1 file changed, 101 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 643b3701a738..3b5dc6de07f7 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -413,19 +413,23 @@ int __xe_vm_userptr_needs_repin(struct xe_vm *vm)
> 
>  #define XE_VM_REBIND_RETRY_TIMEOUT_MS 1000
> 
> -static void xe_vm_kill(struct xe_vm *vm)
> +static void xe_vm_kill(struct xe_vm *vm, bool unlocked)
>  {
>  	struct xe_exec_queue *q;
> 
>  	lockdep_assert_held(&vm->lock);
> 
> -	xe_vm_lock(vm, false);
> +	if (unlocked)
> +		xe_vm_lock(vm, false);
> +

Can you explain why we need xe_vm_lock in the first place here? 

My understanding is, xe_vm_lock protect gpu page table update. Below kill function eventually calls into guc_exec_queue_kill where I don't see any page table operation there. So I doubt whether we need the lock in the first place.

>  	vm->flags |= XE_VM_FLAG_BANNED;
>  	trace_xe_vm_kill(vm);
> 
>  	list_for_each_entry(q, &vm->preempt.exec_queues, compute.link)
>  		q->ops->kill(q);
> -	xe_vm_unlock(vm);
> +
> +	if (unlocked)
> +		xe_vm_unlock(vm);
> 
>  	/* TODO: Inform user the VM is banned */
>  }
> @@ -621,7 +625,7 @@ static void preempt_rebind_work_func(struct work_struct
> *w)
> 
>  	if (err) {
>  		drm_warn(&vm->xe->drm, "VM worker error: %d\n", err);
> -		xe_vm_kill(vm);
> +		xe_vm_kill(vm, true);
>  	}
>  	up_write(&vm->lock);
> 
> @@ -1831,17 +1835,9 @@ static int xe_vm_bind(struct xe_vm *vm, struct xe_vma
> *vma, struct xe_exec_queue
>  		      u32 num_syncs, bool immediate, bool first_op,
>  		      bool last_op)
>  {
> -	int err;
> -
>  	xe_vm_assert_held(vm);
>  	xe_bo_assert_held(bo);
> 
> -	if (bo && immediate) {
> -		err = xe_bo_validate(bo, vm, true);
> -		if (err)
> -			return err;
> -	}
> -
>  	return __xe_vm_bind(vm, vma, q, syncs, num_syncs, immediate, first_op,
>  			    last_op);
>  }
> @@ -2488,17 +2484,12 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm,
> struct xe_exec_queue *q,
>  	return 0;
>  }
> 
> -static int op_execute(struct drm_exec *exec, struct xe_vm *vm,
> -		      struct xe_vma *vma, struct xe_vma_op *op)
> +static int op_execute(struct xe_vm *vm, struct xe_vma *vma,
> +		      struct xe_vma_op *op)
>  {
>  	int err;
> 
>  	lockdep_assert_held_write(&vm->lock);
> -
> -	err = xe_vm_prepare_vma(exec, vma, 1);
> -	if (err)
> -		return err;
> -
>  	xe_vm_assert_held(vm);
>  	xe_bo_assert_held(xe_vma_bo(vma));
> 
> @@ -2579,19 +2570,10 @@ static int op_execute(struct drm_exec *exec, struct
> xe_vm *vm,
>  static int __xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
>  			       struct xe_vma_op *op)
>  {
> -	struct drm_exec exec;
>  	int err;
> 
>  retry_userptr:
> -	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
> -	drm_exec_until_all_locked(&exec) {
> -		err = op_execute(&exec, vm, vma, op);
> -		drm_exec_retry_on_contention(&exec);
> -		if (err)
> -			break;
> -	}
> -	drm_exec_fini(&exec);
> -
> +	err = op_execute(vm, vma, op);
>  	if (err == -EAGAIN) {
>  		lockdep_assert_held_write(&vm->lock);
> 
> @@ -2756,29 +2738,107 @@ static void vm_bind_ioctl_ops_unwind(struct xe_vm
> *vm,
>  	}
>  }
> 
> +static int vma_lock(struct drm_exec *exec, struct xe_vma *vma, bool validate)
> +{
> +	struct xe_bo *bo = xe_vma_bo(vma);
> +	int err = 0;
> +
> +	if (bo) {
> +		if (!bo->vm)
> +			err = drm_exec_prepare_obj(exec, &bo->ttm.base, 1);
> +		if (!err && validate)
> +			err = xe_bo_validate(bo, xe_vma_vm(vma), true);
> +	}
> +
> +	return err;
> +}
> +
> +static int op_lock(struct drm_exec *exec, struct xe_vm *vm,
> +		   struct xe_vma_op *op)
> +{
> +	int err = 0;
> +
> +	switch (op->base.op) {
> +	case DRM_GPUVA_OP_MAP:
> +		err = vma_lock(exec, op->map.vma, !xe_vm_in_fault_mode(vm));
> +		break;
> +	case DRM_GPUVA_OP_REMAP:
> +		err = vma_lock(exec, gpuva_to_vma(op->base.remap.unmap->va),
> +			       false);
> +		if (!err && op->remap.prev)
> +			err = vma_lock(exec, op->remap.prev, true);
> +		if (!err && op->remap.next)
> +			err = vma_lock(exec, op->remap.next, true);
> +		break;
> +	case DRM_GPUVA_OP_UNMAP:
> +		err = vma_lock(exec, gpuva_to_vma(op->base.unmap.va), false);
> +		break;
> +	case DRM_GPUVA_OP_PREFETCH:
> +		err = vma_lock(exec, gpuva_to_vma(op->base.prefetch.va), true);
> +		break;
> +	default:
> +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> +	}
> +
> +	return err;
> +}
> +
> +static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
> +				  struct xe_vm *vm,
> +				  struct list_head *ops_list)
> +{
> +	struct xe_vma_op *op;
> +	int err;
> +
> +	err = drm_exec_prepare_obj(exec, xe_vm_obj(vm), 1);
> +	if (err)
> +		return err;
> +
> +	list_for_each_entry(op, ops_list, link) {
> +		err = op_lock(exec, vm, op);
> +		if (err)
> +			return err;
> +	}
> +
> +	return 0;
> +}
> +
>  static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
>  				     struct list_head *ops_list)
>  {
> +	struct drm_exec exec;
>  	struct xe_vma_op *op, *next;
>  	int err;
> 
>  	lockdep_assert_held_write(&vm->lock);
> 
> -	list_for_each_entry_safe(op, next, ops_list, link) {
> -		err = xe_vma_op_execute(vm, op);
> -		if (err) {
> -			drm_warn(&vm->xe->drm, "VM op(%d) failed with %d",
> -				 op->base.op, err);
> -			/*
> -			 * FIXME: Killing VM rather than proper error handling
> -			 */
> -			xe_vm_kill(vm);
> -			return -ENOSPC;
> +	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT |
> +		      DRM_EXEC_IGNORE_DUPLICATES, 0);
> +	drm_exec_until_all_locked(&exec) {
> +		err = vm_bind_ioctl_ops_lock(&exec, vm, ops_list);
> +		drm_exec_retry_on_contention(&exec);
> +		if (err)
> +			goto unlock;
> +

Do you need below ops inside the drm_exec_until_all_locked loop? After you locked all objects, you can close the drm_exec_until_all_locked loop, then perform below out of drm_exec_until_all_locked loop. 

Oak 

> +		list_for_each_entry_safe(op, next, ops_list, link) {
> +			err = xe_vma_op_execute(vm, op);
> +			if (err) {
> +				drm_warn(&vm->xe->drm, "VM op(%d) failed
> with %d",
> +					 op->base.op, err);
> +				/*
> +				 * FIXME: Killing VM rather than proper error
> handling
> +				 */
> +				xe_vm_kill(vm, false);
> +				err = -ENOSPC;
> +				goto unlock;
> +			}
> +			xe_vma_op_cleanup(vm, op);
>  		}
> -		xe_vma_op_cleanup(vm, op);
>  	}
> 
> -	return 0;
> +unlock:
> +	drm_exec_fini(&exec);
> +	return err;
>  }
> 
>  #define SUPPORTED_FLAGS	(DRM_XE_VM_BIND_FLAG_NULL | \
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL
  2024-03-10 17:44   ` Zeng, Oak
@ 2024-03-11 19:48     ` Matthew Brost
  2024-03-11 22:02       ` Zeng, Oak
  0 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-11 19:48 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Sun, Mar 10, 2024 at 11:44:00AM -0600, Zeng, Oak wrote:
> 
> 
> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL
> > 
> > Lock all gpuva ops
> 
> Can we have a better wording? Better to say locking all Bos used in gpuva ops? 
> 
> Or maybe lock ops by locking and validating all Bos used in ops.
> 
>  and validate all BOs in a single step durin the VM


Lock all BOs used in gpuva ops and validate all BOs in a single step
during the VM bind IOCTL?

> > bind IOCTL. This help with the transition to making all gpuva ops in a
> > VM bind IOCTL a single atomic job.
> 
> Can you also explain, why you want bind to be a atomic job? 
> 
> My guess is, bind ioctl can end up with a series of operations, if some (not all) of those operations fail in the middle, it is hard to revert the successful operations before failure. 

Yes, exactly. It is ensure if we fail at some point in the bind IOCTL
(e.g. memory allocation failure) we can unwind to the initial state.
Also another benefit is we get 1 fence per IOCTL which is installed
dma-resv slots and returned to the user via out-syncs. Lastly, it
logically makes sense that 1 IOCTL translates to 1 job.

The cover letter at some point explained this. I add something in the
next rev.

> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_vm.c | 142 ++++++++++++++++++++++++++-----------
> >  1 file changed, 101 insertions(+), 41 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index 643b3701a738..3b5dc6de07f7 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -413,19 +413,23 @@ int __xe_vm_userptr_needs_repin(struct xe_vm *vm)
> > 
> >  #define XE_VM_REBIND_RETRY_TIMEOUT_MS 1000
> > 
> > -static void xe_vm_kill(struct xe_vm *vm)
> > +static void xe_vm_kill(struct xe_vm *vm, bool unlocked)
> >  {
> >  	struct xe_exec_queue *q;
> > 
> >  	lockdep_assert_held(&vm->lock);
> > 
> > -	xe_vm_lock(vm, false);
> > +	if (unlocked)
> > +		xe_vm_lock(vm, false);
> > +
> 
> Can you explain why we need xe_vm_lock in the first place here? 
> 
> My understanding is, xe_vm_lock protect gpu page table update. Below kill function eventually calls into guc_exec_queue_kill where I don't see any page table operation there. So I doubt whether we need the lock in the first place.
> 

I think it it protect vm->preempt.exec_queues list but that could
probably be reworked. For this series I'd rather leave the locking as is
and then in follow up rework the locking a bit and fully document it.

> >  	vm->flags |= XE_VM_FLAG_BANNED;
> >  	trace_xe_vm_kill(vm);
> > 
> >  	list_for_each_entry(q, &vm->preempt.exec_queues, compute.link)
> >  		q->ops->kill(q);
> > -	xe_vm_unlock(vm);
> > +
> > +	if (unlocked)
> > +		xe_vm_unlock(vm);
> > 
> >  	/* TODO: Inform user the VM is banned */
> >  }
> > @@ -621,7 +625,7 @@ static void preempt_rebind_work_func(struct work_struct
> > *w)
> > 
> >  	if (err) {
> >  		drm_warn(&vm->xe->drm, "VM worker error: %d\n", err);
> > -		xe_vm_kill(vm);
> > +		xe_vm_kill(vm, true);
> >  	}
> >  	up_write(&vm->lock);
> > 
> > @@ -1831,17 +1835,9 @@ static int xe_vm_bind(struct xe_vm *vm, struct xe_vma
> > *vma, struct xe_exec_queue
> >  		      u32 num_syncs, bool immediate, bool first_op,
> >  		      bool last_op)
> >  {
> > -	int err;
> > -
> >  	xe_vm_assert_held(vm);
> >  	xe_bo_assert_held(bo);
> > 
> > -	if (bo && immediate) {
> > -		err = xe_bo_validate(bo, vm, true);
> > -		if (err)
> > -			return err;
> > -	}
> > -
> >  	return __xe_vm_bind(vm, vma, q, syncs, num_syncs, immediate, first_op,
> >  			    last_op);
> >  }
> > @@ -2488,17 +2484,12 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm,
> > struct xe_exec_queue *q,
> >  	return 0;
> >  }
> > 
> > -static int op_execute(struct drm_exec *exec, struct xe_vm *vm,
> > -		      struct xe_vma *vma, struct xe_vma_op *op)
> > +static int op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > +		      struct xe_vma_op *op)
> >  {
> >  	int err;
> > 
> >  	lockdep_assert_held_write(&vm->lock);
> > -
> > -	err = xe_vm_prepare_vma(exec, vma, 1);
> > -	if (err)
> > -		return err;
> > -
> >  	xe_vm_assert_held(vm);
> >  	xe_bo_assert_held(xe_vma_bo(vma));
> > 
> > @@ -2579,19 +2570,10 @@ static int op_execute(struct drm_exec *exec, struct
> > xe_vm *vm,
> >  static int __xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
> >  			       struct xe_vma_op *op)
> >  {
> > -	struct drm_exec exec;
> >  	int err;
> > 
> >  retry_userptr:
> > -	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
> > -	drm_exec_until_all_locked(&exec) {
> > -		err = op_execute(&exec, vm, vma, op);
> > -		drm_exec_retry_on_contention(&exec);
> > -		if (err)
> > -			break;
> > -	}
> > -	drm_exec_fini(&exec);
> > -
> > +	err = op_execute(vm, vma, op);
> >  	if (err == -EAGAIN) {
> >  		lockdep_assert_held_write(&vm->lock);
> > 
> > @@ -2756,29 +2738,107 @@ static void vm_bind_ioctl_ops_unwind(struct xe_vm
> > *vm,
> >  	}
> >  }
> > 
> > +static int vma_lock(struct drm_exec *exec, struct xe_vma *vma, bool validate)
> > +{
> > +	struct xe_bo *bo = xe_vma_bo(vma);
> > +	int err = 0;
> > +
> > +	if (bo) {
> > +		if (!bo->vm)
> > +			err = drm_exec_prepare_obj(exec, &bo->ttm.base, 1);
> > +		if (!err && validate)
> > +			err = xe_bo_validate(bo, xe_vma_vm(vma), true);
> > +	}
> > +
> > +	return err;
> > +}
> > +
> > +static int op_lock(struct drm_exec *exec, struct xe_vm *vm,
> > +		   struct xe_vma_op *op)
> > +{
> > +	int err = 0;
> > +
> > +	switch (op->base.op) {
> > +	case DRM_GPUVA_OP_MAP:
> > +		err = vma_lock(exec, op->map.vma, !xe_vm_in_fault_mode(vm));
> > +		break;
> > +	case DRM_GPUVA_OP_REMAP:
> > +		err = vma_lock(exec, gpuva_to_vma(op->base.remap.unmap->va),
> > +			       false);
> > +		if (!err && op->remap.prev)
> > +			err = vma_lock(exec, op->remap.prev, true);
> > +		if (!err && op->remap.next)
> > +			err = vma_lock(exec, op->remap.next, true);
> > +		break;
> > +	case DRM_GPUVA_OP_UNMAP:
> > +		err = vma_lock(exec, gpuva_to_vma(op->base.unmap.va), false);
> > +		break;
> > +	case DRM_GPUVA_OP_PREFETCH:
> > +		err = vma_lock(exec, gpuva_to_vma(op->base.prefetch.va), true);
> > +		break;
> > +	default:
> > +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > +	}
> > +
> > +	return err;
> > +}
> > +
> > +static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
> > +				  struct xe_vm *vm,
> > +				  struct list_head *ops_list)
> > +{
> > +	struct xe_vma_op *op;
> > +	int err;
> > +
> > +	err = drm_exec_prepare_obj(exec, xe_vm_obj(vm), 1);
> > +	if (err)
> > +		return err;
> > +
> > +	list_for_each_entry(op, ops_list, link) {
> > +		err = op_lock(exec, vm, op);
> > +		if (err)
> > +			return err;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
> >  				     struct list_head *ops_list)
> >  {
> > +	struct drm_exec exec;
> >  	struct xe_vma_op *op, *next;
> >  	int err;
> > 
> >  	lockdep_assert_held_write(&vm->lock);
> > 
> > -	list_for_each_entry_safe(op, next, ops_list, link) {
> > -		err = xe_vma_op_execute(vm, op);
> > -		if (err) {
> > -			drm_warn(&vm->xe->drm, "VM op(%d) failed with %d",
> > -				 op->base.op, err);
> > -			/*
> > -			 * FIXME: Killing VM rather than proper error handling
> > -			 */
> > -			xe_vm_kill(vm);
> > -			return -ENOSPC;
> > +	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT |
> > +		      DRM_EXEC_IGNORE_DUPLICATES, 0);
> > +	drm_exec_until_all_locked(&exec) {
> > +		err = vm_bind_ioctl_ops_lock(&exec, vm, ops_list);
> > +		drm_exec_retry_on_contention(&exec);
> > +		if (err)
> > +			goto unlock;
> > +
> 
> Do you need below ops inside the drm_exec_until_all_locked loop? After you locked all objects, you can close the drm_exec_until_all_locked loop, then perform below out of drm_exec_until_all_locked loop. 
> 

Yes, xe_vma_op_execute can GPU allocate memory. GPU memory allocations
can trigger evictions which try to grab more locks. Once the
drm_exec_until_all_locked loop is broken we are not allowed try grab
more locks. Also eventually on memory allocations I think we will pass
in drm_exec state so the looking can hook into that.

Matt

> Oak 
> 
> > +		list_for_each_entry_safe(op, next, ops_list, link) {
> > +			err = xe_vma_op_execute(vm, op);
> > +			if (err) {
> > +				drm_warn(&vm->xe->drm, "VM op(%d) failed
> > with %d",
> > +					 op->base.op, err);
> > +				/*
> > +				 * FIXME: Killing VM rather than proper error
> > handling
> > +				 */
> > +				xe_vm_kill(vm, false);
> > +				err = -ENOSPC;
> > +				goto unlock;
> > +			}
> > +			xe_vma_op_cleanup(vm, op);
> >  		}
> > -		xe_vma_op_cleanup(vm, op);
> >  	}
> > 
> > -	return 0;
> > +unlock:
> > +	drm_exec_fini(&exec);
> > +	return err;
> >  }
> > 
> >  #define SUPPORTED_FLAGS	(DRM_XE_VM_BIND_FLAG_NULL | \
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL
  2024-03-11 19:48     ` Matthew Brost
@ 2024-03-11 22:02       ` Zeng, Oak
  2024-03-12  1:29         ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-11 22:02 UTC (permalink / raw)
  To: Brost, Matthew; +Cc: intel-xe



> -----Original Message-----
> From: Brost, Matthew <matthew.brost@intel.com>
> Sent: Monday, March 11, 2024 3:49 PM
> To: Zeng, Oak <oak.zeng@intel.com>
> Cc: intel-xe@lists.freedesktop.org
> Subject: Re: [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL
> 
> On Sun, Mar 10, 2024 at 11:44:00AM -0600, Zeng, Oak wrote:
> >
> >
> > > -----Original Message-----
> > > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of
> Matthew
> > > Brost
> > > Sent: Friday, March 8, 2024 12:08 AM
> > > To: intel-xe@lists.freedesktop.org
> > > Cc: Brost, Matthew <matthew.brost@intel.com>
> > > Subject: [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL
> > >
> > > Lock all gpuva ops
> >
> > Can we have a better wording? Better to say locking all Bos used in gpuva ops?
> >
> > Or maybe lock ops by locking and validating all Bos used in ops.
> >
> >  and validate all BOs in a single step durin the VM
> 
> 
> Lock all BOs used in gpuva ops and validate all BOs in a single step
> during the VM bind IOCTL?

Yes, that looks better.

> 
> > > bind IOCTL. This help with the transition to making all gpuva ops in a
> > > VM bind IOCTL a single atomic job.
> >
> > Can you also explain, why you want bind to be a atomic job?
> >
> > My guess is, bind ioctl can end up with a series of operations, if some (not all) of
> those operations fail in the middle, it is hard to revert the successful operations
> before failure.
> 
> Yes, exactly. It is ensure if we fail at some point in the bind IOCTL
> (e.g. memory allocation failure) we can unwind to the initial state.
> Also another benefit is we get 1 fence per IOCTL which is installed
> dma-resv slots and returned to the user via out-syncs. Lastly, it
> logically makes sense that 1 IOCTL translates to 1 job.
> 
> The cover letter at some point explained this. I add something in the
> next rev.
> 
> > >
> > > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > > ---
> > >  drivers/gpu/drm/xe/xe_vm.c | 142 ++++++++++++++++++++++++++---------
> --
> > >  1 file changed, 101 insertions(+), 41 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > > index 643b3701a738..3b5dc6de07f7 100644
> > > --- a/drivers/gpu/drm/xe/xe_vm.c
> > > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > > @@ -413,19 +413,23 @@ int __xe_vm_userptr_needs_repin(struct xe_vm
> *vm)
> > >
> > >  #define XE_VM_REBIND_RETRY_TIMEOUT_MS 1000
> > >
> > > -static void xe_vm_kill(struct xe_vm *vm)
> > > +static void xe_vm_kill(struct xe_vm *vm, bool unlocked)
> > >  {
> > >  	struct xe_exec_queue *q;
> > >
> > >  	lockdep_assert_held(&vm->lock);
> > >
> > > -	xe_vm_lock(vm, false);
> > > +	if (unlocked)
> > > +		xe_vm_lock(vm, false);
> > > +
> >
> > Can you explain why we need xe_vm_lock in the first place here?
> >
> > My understanding is, xe_vm_lock protect gpu page table update. Below kill
> function eventually calls into guc_exec_queue_kill where I don't see any page
> table operation there. So I doubt whether we need the lock in the first place.
> >
> 
> I think it it protect vm->preempt.exec_queues list but that could
> probably be reworked. For this series I'd rather leave the locking as is
> and then in follow up rework the locking a bit and fully document it.

Isn't that vm->pre-empt.exec_queues is protected by vm::lock (the rw) semaphore? Xe_vm_lock here is vm's dma resv.

I agree we can rework those locks later.


> 
> > >  	vm->flags |= XE_VM_FLAG_BANNED;
> > >  	trace_xe_vm_kill(vm);
> > >
> > >  	list_for_each_entry(q, &vm->preempt.exec_queues, compute.link)
> > >  		q->ops->kill(q);
> > > -	xe_vm_unlock(vm);
> > > +
> > > +	if (unlocked)
> > > +		xe_vm_unlock(vm);
> > >
> > >  	/* TODO: Inform user the VM is banned */
> > >  }
> > > @@ -621,7 +625,7 @@ static void preempt_rebind_work_func(struct
> work_struct
> > > *w)
> > >
> > >  	if (err) {
> > >  		drm_warn(&vm->xe->drm, "VM worker error: %d\n", err);
> > > -		xe_vm_kill(vm);
> > > +		xe_vm_kill(vm, true);
> > >  	}
> > >  	up_write(&vm->lock);
> > >
> > > @@ -1831,17 +1835,9 @@ static int xe_vm_bind(struct xe_vm *vm, struct
> xe_vma
> > > *vma, struct xe_exec_queue
> > >  		      u32 num_syncs, bool immediate, bool first_op,
> > >  		      bool last_op)
> > >  {
> > > -	int err;
> > > -
> > >  	xe_vm_assert_held(vm);
> > >  	xe_bo_assert_held(bo);
> > >
> > > -	if (bo && immediate) {
> > > -		err = xe_bo_validate(bo, vm, true);
> > > -		if (err)
> > > -			return err;
> > > -	}
> > > -
> > >  	return __xe_vm_bind(vm, vma, q, syncs, num_syncs, immediate,
> first_op,
> > >  			    last_op);
> > >  }
> > > @@ -2488,17 +2484,12 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> *vm,
> > > struct xe_exec_queue *q,
> > >  	return 0;
> > >  }
> > >
> > > -static int op_execute(struct drm_exec *exec, struct xe_vm *vm,
> > > -		      struct xe_vma *vma, struct xe_vma_op *op)
> > > +static int op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > > +		      struct xe_vma_op *op)
> > >  {
> > >  	int err;
> > >
> > >  	lockdep_assert_held_write(&vm->lock);
> > > -
> > > -	err = xe_vm_prepare_vma(exec, vma, 1);
> > > -	if (err)
> > > -		return err;
> > > -
> > >  	xe_vm_assert_held(vm);
> > >  	xe_bo_assert_held(xe_vma_bo(vma));
> > >
> > > @@ -2579,19 +2570,10 @@ static int op_execute(struct drm_exec *exec,
> struct
> > > xe_vm *vm,
> > >  static int __xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > >  			       struct xe_vma_op *op)
> > >  {
> > > -	struct drm_exec exec;
> > >  	int err;
> > >
> > >  retry_userptr:
> > > -	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
> > > -	drm_exec_until_all_locked(&exec) {
> > > -		err = op_execute(&exec, vm, vma, op);
> > > -		drm_exec_retry_on_contention(&exec);
> > > -		if (err)
> > > -			break;
> > > -	}
> > > -	drm_exec_fini(&exec);
> > > -
> > > +	err = op_execute(vm, vma, op);
> > >  	if (err == -EAGAIN) {
> > >  		lockdep_assert_held_write(&vm->lock);
> > >
> > > @@ -2756,29 +2738,107 @@ static void vm_bind_ioctl_ops_unwind(struct
> xe_vm
> > > *vm,
> > >  	}
> > >  }
> > >
> > > +static int vma_lock(struct drm_exec *exec, struct xe_vma *vma, bool
> validate)
> > > +{
> > > +	struct xe_bo *bo = xe_vma_bo(vma);
> > > +	int err = 0;
> > > +
> > > +	if (bo) {
> > > +		if (!bo->vm)
> > > +			err = drm_exec_prepare_obj(exec, &bo->ttm.base, 1);
> > > +		if (!err && validate)
> > > +			err = xe_bo_validate(bo, xe_vma_vm(vma), true);
> > > +	}
> > > +
> > > +	return err;
> > > +}
> > > +
> > > +static int op_lock(struct drm_exec *exec, struct xe_vm *vm,
> > > +		   struct xe_vma_op *op)
> > > +{
> > > +	int err = 0;
> > > +
> > > +	switch (op->base.op) {
> > > +	case DRM_GPUVA_OP_MAP:
> > > +		err = vma_lock(exec, op-
> >map.vma, !xe_vm_in_fault_mode(vm));
> > > +		break;
> > > +	case DRM_GPUVA_OP_REMAP:
> > > +		err = vma_lock(exec, gpuva_to_vma(op->base.remap.unmap-
> >va),
> > > +			       false);
> > > +		if (!err && op->remap.prev)
> > > +			err = vma_lock(exec, op->remap.prev, true);
> > > +		if (!err && op->remap.next)
> > > +			err = vma_lock(exec, op->remap.next, true);
> > > +		break;
> > > +	case DRM_GPUVA_OP_UNMAP:
> > > +		err = vma_lock(exec, gpuva_to_vma(op->base.unmap.va), false);
> > > +		break;
> > > +	case DRM_GPUVA_OP_PREFETCH:
> > > +		err = vma_lock(exec, gpuva_to_vma(op->base.prefetch.va),
> true);
> > > +		break;
> > > +	default:
> > > +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > > +	}
> > > +
> > > +	return err;
> > > +}
> > > +
> > > +static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
> > > +				  struct xe_vm *vm,
> > > +				  struct list_head *ops_list)
> > > +{
> > > +	struct xe_vma_op *op;
> > > +	int err;
> > > +
> > > +	err = drm_exec_prepare_obj(exec, xe_vm_obj(vm), 1);
> > > +	if (err)
> > > +		return err;
> > > +
> > > +	list_for_each_entry(op, ops_list, link) {
> > > +		err = op_lock(exec, vm, op);
> > > +		if (err)
> > > +			return err;
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >  static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
> > >  				     struct list_head *ops_list)
> > >  {
> > > +	struct drm_exec exec;
> > >  	struct xe_vma_op *op, *next;
> > >  	int err;
> > >
> > >  	lockdep_assert_held_write(&vm->lock);
> > >
> > > -	list_for_each_entry_safe(op, next, ops_list, link) {
> > > -		err = xe_vma_op_execute(vm, op);
> > > -		if (err) {
> > > -			drm_warn(&vm->xe->drm, "VM op(%d) failed with %d",
> > > -				 op->base.op, err);
> > > -			/*
> > > -			 * FIXME: Killing VM rather than proper error handling
> > > -			 */
> > > -			xe_vm_kill(vm);
> > > -			return -ENOSPC;
> > > +	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT |
> > > +		      DRM_EXEC_IGNORE_DUPLICATES, 0);
> > > +	drm_exec_until_all_locked(&exec) {
> > > +		err = vm_bind_ioctl_ops_lock(&exec, vm, ops_list);
> > > +		drm_exec_retry_on_contention(&exec);
> > > +		if (err)
> > > +			goto unlock;
> > > +
> >
> > Do you need below ops inside the drm_exec_until_all_locked loop? After you
> locked all objects, you can close the drm_exec_until_all_locked loop, then
> perform below out of drm_exec_until_all_locked loop.
> >
> 
> Yes, xe_vma_op_execute can GPU allocate memory. GPU memory allocations
> can trigger evictions which try to grab more locks. Once the
> drm_exec_until_all_locked loop is broken we are not allowed try grab
> more locks.

I see. So you need xe_vma_op_execute in the drm_exec_until_all_locked loop to grab more locks.


 Also eventually on memory allocations I think we will pass
> in drm_exec state so the looking can hook into that.

Then I guess you need a exec parameter in xe_vma_op_execute, so eventually you can grab more locks in memory allocation?

Oak

> 
> Matt
> 
> > Oak
> >
> > > +		list_for_each_entry_safe(op, next, ops_list, link) {
> > > +			err = xe_vma_op_execute(vm, op);
> > > +			if (err) {
> > > +				drm_warn(&vm->xe->drm, "VM op(%d) failed
> > > with %d",
> > > +					 op->base.op, err);
> > > +				/*
> > > +				 * FIXME: Killing VM rather than proper error
> > > handling
> > > +				 */
> > > +				xe_vm_kill(vm, false);
> > > +				err = -ENOSPC;
> > > +				goto unlock;
> > > +			}
> > > +			xe_vma_op_cleanup(vm, op);
> > >  		}
> > > -		xe_vma_op_cleanup(vm, op);
> > >  	}
> > >
> > > -	return 0;
> > > +unlock:
> > > +	drm_exec_fini(&exec);
> > > +	return err;
> > >  }
> > >
> > >  #define SUPPORTED_FLAGS	(DRM_XE_VM_BIND_FLAG_NULL | \
> > > --
> > > 2.34.1
> >

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL
  2024-03-11 22:02       ` Zeng, Oak
@ 2024-03-12  1:29         ` Matthew Brost
  0 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-12  1:29 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Mon, Mar 11, 2024 at 04:02:28PM -0600, Zeng, Oak wrote:
> 
> 
> > -----Original Message-----
> > From: Brost, Matthew <matthew.brost@intel.com>
> > Sent: Monday, March 11, 2024 3:49 PM
> > To: Zeng, Oak <oak.zeng@intel.com>
> > Cc: intel-xe@lists.freedesktop.org
> > Subject: Re: [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL
> > 
> > On Sun, Mar 10, 2024 at 11:44:00AM -0600, Zeng, Oak wrote:
> > >
> > >
> > > > -----Original Message-----
> > > > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of
> > Matthew
> > > > Brost
> > > > Sent: Friday, March 8, 2024 12:08 AM
> > > > To: intel-xe@lists.freedesktop.org
> > > > Cc: Brost, Matthew <matthew.brost@intel.com>
> > > > Subject: [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL
> > > >
> > > > Lock all gpuva ops
> > >
> > > Can we have a better wording? Better to say locking all Bos used in gpuva ops?
> > >
> > > Or maybe lock ops by locking and validating all Bos used in ops.
> > >
> > >  and validate all BOs in a single step durin the VM
> > 
> > 
> > Lock all BOs used in gpuva ops and validate all BOs in a single step
> > during the VM bind IOCTL?
> 
> Yes, that looks better.
> 
> > 
> > > > bind IOCTL. This help with the transition to making all gpuva ops in a
> > > > VM bind IOCTL a single atomic job.
> > >
> > > Can you also explain, why you want bind to be a atomic job?
> > >
> > > My guess is, bind ioctl can end up with a series of operations, if some (not all) of
> > those operations fail in the middle, it is hard to revert the successful operations
> > before failure.
> > 
> > Yes, exactly. It is ensure if we fail at some point in the bind IOCTL
> > (e.g. memory allocation failure) we can unwind to the initial state.
> > Also another benefit is we get 1 fence per IOCTL which is installed
> > dma-resv slots and returned to the user via out-syncs. Lastly, it
> > logically makes sense that 1 IOCTL translates to 1 job.
> > 
> > The cover letter at some point explained this. I add something in the
> > next rev.
> > 
> > > >
> > > > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/xe/xe_vm.c | 142 ++++++++++++++++++++++++++---------
> > --
> > > >  1 file changed, 101 insertions(+), 41 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > > > index 643b3701a738..3b5dc6de07f7 100644
> > > > --- a/drivers/gpu/drm/xe/xe_vm.c
> > > > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > > > @@ -413,19 +413,23 @@ int __xe_vm_userptr_needs_repin(struct xe_vm
> > *vm)
> > > >
> > > >  #define XE_VM_REBIND_RETRY_TIMEOUT_MS 1000
> > > >
> > > > -static void xe_vm_kill(struct xe_vm *vm)
> > > > +static void xe_vm_kill(struct xe_vm *vm, bool unlocked)
> > > >  {
> > > >  	struct xe_exec_queue *q;
> > > >
> > > >  	lockdep_assert_held(&vm->lock);
> > > >
> > > > -	xe_vm_lock(vm, false);
> > > > +	if (unlocked)
> > > > +		xe_vm_lock(vm, false);
> > > > +
> > >
> > > Can you explain why we need xe_vm_lock in the first place here?
> > >
> > > My understanding is, xe_vm_lock protect gpu page table update. Below kill
> > function eventually calls into guc_exec_queue_kill where I don't see any page
> > table operation there. So I doubt whether we need the lock in the first place.
> > >
> > 
> > I think it it protect vm->preempt.exec_queues list but that could
> > probably be reworked. For this series I'd rather leave the locking as is
> > and then in follow up rework the locking a bit and fully document it.
> 
> Isn't that vm->pre-empt.exec_queues is protected by vm::lock (the rw) semaphore? Xe_vm_lock here is vm's dma resv.
> 

It isn't really all that clear but since this is in the existing code
let's just leave it until we rework / document the locking.

I'll likely add a new patch in next rev at the end of the series which
works on the locking a bit...

> I agree we can rework those locks later.
> 
> 
> > 
> > > >  	vm->flags |= XE_VM_FLAG_BANNED;
> > > >  	trace_xe_vm_kill(vm);
> > > >
> > > >  	list_for_each_entry(q, &vm->preempt.exec_queues, compute.link)
> > > >  		q->ops->kill(q);
> > > > -	xe_vm_unlock(vm);
> > > > +
> > > > +	if (unlocked)
> > > > +		xe_vm_unlock(vm);
> > > >
> > > >  	/* TODO: Inform user the VM is banned */
> > > >  }
> > > > @@ -621,7 +625,7 @@ static void preempt_rebind_work_func(struct
> > work_struct
> > > > *w)
> > > >
> > > >  	if (err) {
> > > >  		drm_warn(&vm->xe->drm, "VM worker error: %d\n", err);
> > > > -		xe_vm_kill(vm);
> > > > +		xe_vm_kill(vm, true);
> > > >  	}
> > > >  	up_write(&vm->lock);
> > > >
> > > > @@ -1831,17 +1835,9 @@ static int xe_vm_bind(struct xe_vm *vm, struct
> > xe_vma
> > > > *vma, struct xe_exec_queue
> > > >  		      u32 num_syncs, bool immediate, bool first_op,
> > > >  		      bool last_op)
> > > >  {
> > > > -	int err;
> > > > -
> > > >  	xe_vm_assert_held(vm);
> > > >  	xe_bo_assert_held(bo);
> > > >
> > > > -	if (bo && immediate) {
> > > > -		err = xe_bo_validate(bo, vm, true);
> > > > -		if (err)
> > > > -			return err;
> > > > -	}
> > > > -
> > > >  	return __xe_vm_bind(vm, vma, q, syncs, num_syncs, immediate,
> > first_op,
> > > >  			    last_op);
> > > >  }
> > > > @@ -2488,17 +2484,12 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> > *vm,
> > > > struct xe_exec_queue *q,
> > > >  	return 0;
> > > >  }
> > > >
> > > > -static int op_execute(struct drm_exec *exec, struct xe_vm *vm,
> > > > -		      struct xe_vma *vma, struct xe_vma_op *op)
> > > > +static int op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > > > +		      struct xe_vma_op *op)
> > > >  {
> > > >  	int err;
> > > >
> > > >  	lockdep_assert_held_write(&vm->lock);
> > > > -
> > > > -	err = xe_vm_prepare_vma(exec, vma, 1);
> > > > -	if (err)
> > > > -		return err;
> > > > -
> > > >  	xe_vm_assert_held(vm);
> > > >  	xe_bo_assert_held(xe_vma_bo(vma));
> > > >
> > > > @@ -2579,19 +2570,10 @@ static int op_execute(struct drm_exec *exec,
> > struct
> > > > xe_vm *vm,
> > > >  static int __xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > > >  			       struct xe_vma_op *op)
> > > >  {
> > > > -	struct drm_exec exec;
> > > >  	int err;
> > > >
> > > >  retry_userptr:
> > > > -	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
> > > > -	drm_exec_until_all_locked(&exec) {
> > > > -		err = op_execute(&exec, vm, vma, op);
> > > > -		drm_exec_retry_on_contention(&exec);
> > > > -		if (err)
> > > > -			break;
> > > > -	}
> > > > -	drm_exec_fini(&exec);
> > > > -
> > > > +	err = op_execute(vm, vma, op);
> > > >  	if (err == -EAGAIN) {
> > > >  		lockdep_assert_held_write(&vm->lock);
> > > >
> > > > @@ -2756,29 +2738,107 @@ static void vm_bind_ioctl_ops_unwind(struct
> > xe_vm
> > > > *vm,
> > > >  	}
> > > >  }
> > > >
> > > > +static int vma_lock(struct drm_exec *exec, struct xe_vma *vma, bool
> > validate)
> > > > +{
> > > > +	struct xe_bo *bo = xe_vma_bo(vma);
> > > > +	int err = 0;
> > > > +
> > > > +	if (bo) {
> > > > +		if (!bo->vm)
> > > > +			err = drm_exec_prepare_obj(exec, &bo->ttm.base, 1);
> > > > +		if (!err && validate)
> > > > +			err = xe_bo_validate(bo, xe_vma_vm(vma), true);
> > > > +	}
> > > > +
> > > > +	return err;
> > > > +}
> > > > +
> > > > +static int op_lock(struct drm_exec *exec, struct xe_vm *vm,
> > > > +		   struct xe_vma_op *op)
> > > > +{
> > > > +	int err = 0;
> > > > +
> > > > +	switch (op->base.op) {
> > > > +	case DRM_GPUVA_OP_MAP:
> > > > +		err = vma_lock(exec, op-
> > >map.vma, !xe_vm_in_fault_mode(vm));
> > > > +		break;
> > > > +	case DRM_GPUVA_OP_REMAP:
> > > > +		err = vma_lock(exec, gpuva_to_vma(op->base.remap.unmap-
> > >va),
> > > > +			       false);
> > > > +		if (!err && op->remap.prev)
> > > > +			err = vma_lock(exec, op->remap.prev, true);
> > > > +		if (!err && op->remap.next)
> > > > +			err = vma_lock(exec, op->remap.next, true);
> > > > +		break;
> > > > +	case DRM_GPUVA_OP_UNMAP:
> > > > +		err = vma_lock(exec, gpuva_to_vma(op->base.unmap.va), false);
> > > > +		break;
> > > > +	case DRM_GPUVA_OP_PREFETCH:
> > > > +		err = vma_lock(exec, gpuva_to_vma(op->base.prefetch.va),
> > true);
> > > > +		break;
> > > > +	default:
> > > > +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > > > +	}
> > > > +
> > > > +	return err;
> > > > +}
> > > > +
> > > > +static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
> > > > +				  struct xe_vm *vm,
> > > > +				  struct list_head *ops_list)
> > > > +{
> > > > +	struct xe_vma_op *op;
> > > > +	int err;
> > > > +
> > > > +	err = drm_exec_prepare_obj(exec, xe_vm_obj(vm), 1);
> > > > +	if (err)
> > > > +		return err;
> > > > +
> > > > +	list_for_each_entry(op, ops_list, link) {
> > > > +		err = op_lock(exec, vm, op);
> > > > +		if (err)
> > > > +			return err;
> > > > +	}
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > >  static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
> > > >  				     struct list_head *ops_list)
> > > >  {
> > > > +	struct drm_exec exec;
> > > >  	struct xe_vma_op *op, *next;
> > > >  	int err;
> > > >
> > > >  	lockdep_assert_held_write(&vm->lock);
> > > >
> > > > -	list_for_each_entry_safe(op, next, ops_list, link) {
> > > > -		err = xe_vma_op_execute(vm, op);
> > > > -		if (err) {
> > > > -			drm_warn(&vm->xe->drm, "VM op(%d) failed with %d",
> > > > -				 op->base.op, err);
> > > > -			/*
> > > > -			 * FIXME: Killing VM rather than proper error handling
> > > > -			 */
> > > > -			xe_vm_kill(vm);
> > > > -			return -ENOSPC;
> > > > +	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT |
> > > > +		      DRM_EXEC_IGNORE_DUPLICATES, 0);
> > > > +	drm_exec_until_all_locked(&exec) {
> > > > +		err = vm_bind_ioctl_ops_lock(&exec, vm, ops_list);
> > > > +		drm_exec_retry_on_contention(&exec);
> > > > +		if (err)
> > > > +			goto unlock;
> > > > +
> > >
> > > Do you need below ops inside the drm_exec_until_all_locked loop? After you
> > locked all objects, you can close the drm_exec_until_all_locked loop, then
> > perform below out of drm_exec_until_all_locked loop.
> > >
> > 
> > Yes, xe_vma_op_execute can GPU allocate memory. GPU memory allocations
> > can trigger evictions which try to grab more locks. Once the
> > drm_exec_until_all_locked loop is broken we are not allowed try grab
> > more locks.
> 
> I see. So you need xe_vma_op_execute in the drm_exec_until_all_locked loop to grab more locks.
> 

Yes.

> 
>  Also eventually on memory allocations I think we will pass
> > in drm_exec state so the looking can hook into that.
> 
> Then I guess you need a exec parameter in xe_vma_op_execute, so eventually you can grab more locks in memory allocation?
> 

This gets reworkeed later in the series where xe_vma_ops is passed
around everywhere (VM, migrate, and PT layers) and we should probably
includd the drm_exec as a member of xe_vma_ops.

Matt

> Oak
> 
> > 
> > Matt
> > 
> > > Oak
> > >
> > > > +		list_for_each_entry_safe(op, next, ops_list, link) {
> > > > +			err = xe_vma_op_execute(vm, op);
> > > > +			if (err) {
> > > > +				drm_warn(&vm->xe->drm, "VM op(%d) failed
> > > > with %d",
> > > > +					 op->base.op, err);
> > > > +				/*
> > > > +				 * FIXME: Killing VM rather than proper error
> > > > handling
> > > > +				 */
> > > > +				xe_vm_kill(vm, false);
> > > > +				err = -ENOSPC;
> > > > +				goto unlock;
> > > > +			}
> > > > +			xe_vma_op_cleanup(vm, op);
> > > >  		}
> > > > -		xe_vma_op_cleanup(vm, op);
> > > >  	}
> > > >
> > > > -	return 0;
> > > > +unlock:
> > > > +	drm_exec_fini(&exec);
> > > > +	return err;
> > > >  }
> > > >
> > > >  #define SUPPORTED_FLAGS	(DRM_XE_VM_BIND_FLAG_NULL | \
> > > > --
> > > > 2.34.1
> > >

^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 02/30] drm/xe: Add ops_execute function which returns a fence
  2024-03-08  5:07 ` [PATCH v4 02/30] drm/xe: Add ops_execute function which returns a fence Matthew Brost
@ 2024-03-22 16:11   ` Zeng, Oak
  2024-03-22 17:31     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-22 16:11 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew



> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 02/30] drm/xe: Add ops_execute function which returns a
> fence
> 
> Add ops_execute function which returns a fence. This will be helpful to
> initiate all binds (VM bind IOCTL, rebinds in exec IOCTL, rebinds in
> preempt rebind worker, and rebinds in pagefaults) via a gpuva ops list.
> Returning a fence is needed in various paths.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm.c | 211 +++++++++++++++++++------------------
>  1 file changed, 111 insertions(+), 100 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 3b5dc6de07f7..fb73afcab3b7 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -1789,16 +1789,17 @@ find_ufence_get(struct xe_sync_entry *syncs, u32
> num_syncs)
>  	return NULL;
>  }
> 
> -static int __xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma,
> -			struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> -			u32 num_syncs, bool immediate, bool first_op,
> -			bool last_op)
> +static struct dma_fence *
> +xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue *q,
> +	   struct xe_bo *bo, struct xe_sync_entry *syncs, u32 num_syncs,
> +	   bool immediate, bool first_op, bool last_op)
>  {
>  	struct dma_fence *fence;
>  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> q);
>  	struct xe_user_fence *ufence;
> 
>  	xe_vm_assert_held(vm);
> +	xe_bo_assert_held(bo);
> 
>  	ufence = find_ufence_get(syncs, num_syncs);
>  	if (vma->ufence && ufence)
> @@ -1810,7 +1811,7 @@ static int __xe_vm_bind(struct xe_vm *vm, struct
> xe_vma *vma,
>  		fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, first_op,
>  				       last_op);
>  		if (IS_ERR(fence))
> -			return PTR_ERR(fence);
> +			return fence;
>  	} else {
>  		int i;
> 
> @@ -1825,26 +1826,14 @@ static int __xe_vm_bind(struct xe_vm *vm, struct
> xe_vma *vma,
> 
>  	if (last_op)
>  		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> -	dma_fence_put(fence);
> -
> -	return 0;
> -}
> -
> -static int xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct
> xe_exec_queue *q,
> -		      struct xe_bo *bo, struct xe_sync_entry *syncs,
> -		      u32 num_syncs, bool immediate, bool first_op,
> -		      bool last_op)
> -{
> -	xe_vm_assert_held(vm);
> -	xe_bo_assert_held(bo);
> 
> -	return __xe_vm_bind(vm, vma, q, syncs, num_syncs, immediate,
> first_op,
> -			    last_op);
> +	return fence;
>  }
> 
> -static int xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
> -			struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> -			u32 num_syncs, bool first_op, bool last_op)
> +static struct dma_fence *
> +xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
> +	     struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> +	     u32 num_syncs, bool first_op, bool last_op)
>  {
>  	struct dma_fence *fence;
>  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> q);
> @@ -1854,14 +1843,13 @@ static int xe_vm_unbind(struct xe_vm *vm, struct
> xe_vma *vma,
> 
>  	fence = xe_vm_unbind_vma(vma, q, syncs, num_syncs, first_op,
> last_op);
>  	if (IS_ERR(fence))
> -		return PTR_ERR(fence);
> +		return fence;
> 
>  	xe_vma_destroy(vma, fence);
>  	if (last_op)
>  		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> -	dma_fence_put(fence);
> 
> -	return 0;
> +	return fence;
>  }
> 
>  #define ALL_DRM_XE_VM_CREATE_FLAGS
> (DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE | \
> @@ -2004,10 +1992,11 @@ static const u32 region_to_mem_type[] = {
>  	XE_PL_VRAM1,
>  };
> 
> -static int xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
> -			  struct xe_exec_queue *q, u32 region,
> -			  struct xe_sync_entry *syncs, u32 num_syncs,
> -			  bool first_op, bool last_op)
> +static struct dma_fence *
> +xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
> +	       struct xe_exec_queue *q, u32 region,
> +	       struct xe_sync_entry *syncs, u32 num_syncs,
> +	       bool first_op, bool last_op)
>  {
>  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> q);
>  	int err;
> @@ -2017,27 +2006,24 @@ static int xe_vm_prefetch(struct xe_vm *vm, struct
> xe_vma *vma,
>  	if (!xe_vma_has_no_bo(vma)) {
>  		err = xe_bo_migrate(xe_vma_bo(vma),
> region_to_mem_type[region]);
>  		if (err)
> -			return err;
> +			return ERR_PTR(err);
>  	}
> 
>  	if (vma->tile_mask != (vma->tile_present & ~vma->usm.tile_invalidated))
> {
>  		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs,
> num_syncs,
>  				  true, first_op, last_op);
>  	} else {
> +		struct dma_fence *fence =
> +			xe_exec_queue_last_fence_get(wait_exec_queue, vm);
>  		int i;
> 
>  		/* Nothing to do, signal fences now */
>  		if (last_op) {
> -			for (i = 0; i < num_syncs; i++) {
> -				struct dma_fence *fence =
> -
> 	xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> -
> +			for (i = 0; i < num_syncs; i++)
>  				xe_sync_entry_signal(&syncs[i], NULL, fence);
> -				dma_fence_put(fence);
> -			}
>  		}
> 
> -		return 0;
> +		return fence;
>  	}
>  }
> 
> @@ -2484,10 +2470,10 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> *vm, struct xe_exec_queue *q,
>  	return 0;
>  }
> 
> -static int op_execute(struct xe_vm *vm, struct xe_vma *vma,
> -		      struct xe_vma_op *op)
> +static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma *vma,
> +				    struct xe_vma_op *op)
>  {
> -	int err;
> +	struct dma_fence *fence = NULL;
> 
>  	lockdep_assert_held_write(&vm->lock);
>  	xe_vm_assert_held(vm);
> @@ -2495,11 +2481,11 @@ static int op_execute(struct xe_vm *vm, struct
> xe_vma *vma,
> 
>  	switch (op->base.op) {
>  	case DRM_GPUVA_OP_MAP:
> -		err = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
> -				 op->syncs, op->num_syncs,
> -				 !xe_vm_in_fault_mode(vm),
> -				 op->flags & XE_VMA_OP_FIRST,
> -				 op->flags & XE_VMA_OP_LAST);
> +		fence = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
> +				   op->syncs, op->num_syncs,
> +				   !xe_vm_in_fault_mode(vm),
> +				   op->flags & XE_VMA_OP_FIRST,
> +				   op->flags & XE_VMA_OP_LAST);
>  		break;
>  	case DRM_GPUVA_OP_REMAP:
>  	{
> @@ -2509,37 +2495,39 @@ static int op_execute(struct xe_vm *vm, struct
> xe_vma *vma,
>  		if (!op->remap.unmap_done) {
>  			if (prev || next)
>  				vma->gpuva.flags |= XE_VMA_FIRST_REBIND;
> -			err = xe_vm_unbind(vm, vma, op->q, op->syncs,
> -					   op->num_syncs,
> -					   op->flags & XE_VMA_OP_FIRST,
> -					   op->flags & XE_VMA_OP_LAST &&
> -					   !prev && !next);
> -			if (err)
> +			fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
> +					     op->num_syncs,
> +					     op->flags & XE_VMA_OP_FIRST,
> +					     op->flags & XE_VMA_OP_LAST &&
> +					     !prev && !next);
> +			if (IS_ERR(fence))
>  				break;
>  			op->remap.unmap_done = true;
>  		}
> 
>  		if (prev) {
>  			op->remap.prev->gpuva.flags |= XE_VMA_LAST_REBIND;
> -			err = xe_vm_bind(vm, op->remap.prev, op->q,
> -					 xe_vma_bo(op->remap.prev), op->syncs,
> -					 op->num_syncs, true, false,
> -					 op->flags & XE_VMA_OP_LAST
> && !next);
> +			dma_fence_put(fence);


So you drop the previous fence. I assume in later operation, we will need to wait dma-fence for the previous operation to complete. Is it safe to only wait for the last fence? Shouldn't we wait all the fences, such as chain the fences in some way?

> +			fence = xe_vm_bind(vm, op->remap.prev, op->q,
> +					   xe_vma_bo(op->remap.prev), op-
> >syncs,
> +					   op->num_syncs, true, false,
> +					   op->flags & XE_VMA_OP_LAST
> && !next);
>  			op->remap.prev->gpuva.flags &=
> ~XE_VMA_LAST_REBIND;
> -			if (err)
> +			if (IS_ERR(fence))
>  				break;
>  			op->remap.prev = NULL;
>  		}
> 
>  		if (next) {
>  			op->remap.next->gpuva.flags |= XE_VMA_LAST_REBIND;
> -			err = xe_vm_bind(vm, op->remap.next, op->q,
> -					 xe_vma_bo(op->remap.next),
> -					 op->syncs, op->num_syncs,
> -					 true, false,
> -					 op->flags & XE_VMA_OP_LAST);
> +			dma_fence_put(fence);


Same comment as above
> +			fence = xe_vm_bind(vm, op->remap.next, op->q,
> +					   xe_vma_bo(op->remap.next),
> +					   op->syncs, op->num_syncs,
> +					   true, false,
> +					   op->flags & XE_VMA_OP_LAST);
>  			op->remap.next->gpuva.flags &=
> ~XE_VMA_LAST_REBIND;
> -			if (err)
> +			if (IS_ERR(fence))
>  				break;
>  			op->remap.next = NULL;
>  		}
> @@ -2547,34 +2535,36 @@ static int op_execute(struct xe_vm *vm, struct
> xe_vma *vma,
>  		break;
>  	}
>  	case DRM_GPUVA_OP_UNMAP:
> -		err = xe_vm_unbind(vm, vma, op->q, op->syncs,
> -				   op->num_syncs, op->flags &
> XE_VMA_OP_FIRST,
> -				   op->flags & XE_VMA_OP_LAST);
> +		fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
> +				     op->num_syncs, op->flags &
> XE_VMA_OP_FIRST,
> +				     op->flags & XE_VMA_OP_LAST);
>  		break;
>  	case DRM_GPUVA_OP_PREFETCH:
> -		err = xe_vm_prefetch(vm, vma, op->q, op->prefetch.region,
> -				     op->syncs, op->num_syncs,
> -				     op->flags & XE_VMA_OP_FIRST,
> -				     op->flags & XE_VMA_OP_LAST);
> +		fence = xe_vm_prefetch(vm, vma, op->q, op->prefetch.region,
> +				       op->syncs, op->num_syncs,
> +				       op->flags & XE_VMA_OP_FIRST,
> +				       op->flags & XE_VMA_OP_LAST);
>  		break;
>  	default:
>  		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
>  	}
> 
> -	if (err)
> +	if (IS_ERR(fence))
>  		trace_xe_vma_fail(vma);
> 
> -	return err;
> +	return fence;
>  }
> 
> -static int __xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
> -			       struct xe_vma_op *op)
> +static struct dma_fence *
> +__xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
> +		    struct xe_vma_op *op)
>  {
> +	struct dma_fence *fence;
>  	int err;
> 
>  retry_userptr:
> -	err = op_execute(vm, vma, op);
> -	if (err == -EAGAIN) {
> +	fence = op_execute(vm, vma, op);
> +	if (IS_ERR(fence) && PTR_ERR(fence) == -EAGAIN) {
>  		lockdep_assert_held_write(&vm->lock);
> 
>  		if (op->base.op == DRM_GPUVA_OP_REMAP) {
> @@ -2591,22 +2581,24 @@ static int __xe_vma_op_execute(struct xe_vm *vm,
> struct xe_vma *vma,
>  			if (!err)
>  				goto retry_userptr;
> 
> +			fence = ERR_PTR(err);
>  			trace_xe_vma_fail(vma);
>  		}
>  	}
> 
> -	return err;
> +	return fence;
>  }
> 
> -static int xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
> +static struct dma_fence *
> +xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
>  {
> -	int ret = 0;
> +	struct dma_fence *fence = ERR_PTR(-ENOMEM);
> 
>  	lockdep_assert_held_write(&vm->lock);
> 
>  	switch (op->base.op) {
>  	case DRM_GPUVA_OP_MAP:
> -		ret = __xe_vma_op_execute(vm, op->map.vma, op);
> +		fence = __xe_vma_op_execute(vm, op->map.vma, op);
>  		break;
>  	case DRM_GPUVA_OP_REMAP:
>  	{
> @@ -2619,23 +2611,23 @@ static int xe_vma_op_execute(struct xe_vm *vm,
> struct xe_vma_op *op)
>  		else
>  			vma = op->remap.next;
> 
> -		ret = __xe_vma_op_execute(vm, vma, op);
> +		fence = __xe_vma_op_execute(vm, vma, op);
>  		break;
>  	}
>  	case DRM_GPUVA_OP_UNMAP:
> -		ret = __xe_vma_op_execute(vm, gpuva_to_vma(op-
> >base.unmap.va),
> -					  op);
> +		fence = __xe_vma_op_execute(vm, gpuva_to_vma(op-
> >base.unmap.va),
> +					    op);
>  		break;
>  	case DRM_GPUVA_OP_PREFETCH:
> -		ret = __xe_vma_op_execute(vm,
> -					  gpuva_to_vma(op->base.prefetch.va),
> -					  op);
> +		fence = __xe_vma_op_execute(vm,
> +					    gpuva_to_vma(op->base.prefetch.va),
> +					    op);
>  		break;
>  	default:
>  		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
>  	}
> 
> -	return ret;
> +	return fence;
>  }
> 
>  static void xe_vma_op_cleanup(struct xe_vm *vm, struct xe_vma_op *op)
> @@ -2803,11 +2795,35 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec
> *exec,
>  	return 0;
>  }
> 
> +static struct dma_fence *ops_execute(struct xe_vm *vm,
> +				     struct list_head *ops_list,
> +				     bool cleanup)
> +{
> +	struct xe_vma_op *op, *next;
> +	struct dma_fence *fence = NULL;
> +
> +	list_for_each_entry_safe(op, next, ops_list, link) {
> +		if (!IS_ERR(fence)) {
> +			dma_fence_put(fence);
> +			fence = xe_vma_op_execute(vm, op);

So you only return the fence of the last operation. In the later on codes, do you use fence to wait for *all* operations to finish?

> +		}
> +		if (IS_ERR(fence)) {
> +			drm_warn(&vm->xe->drm, "VM op(%d) failed with %ld",
> +				 op->base.op, PTR_ERR(fence));
> +			fence = ERR_PTR(-ENOSPC);

So even if there is error, you don't break the loop. Is it to perform the cleanup below?

Once error happen for one operation, you seem to print the same error message for all the rest operations....because fence = xe_vma_op_execute(vm, op) is not called anymore after the first error


Oak

> +		}
> +		if (cleanup)
> +			xe_vma_op_cleanup(vm, op);
> +	}
> +
> +	return fence;
> +}
> +
>  static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
>  				     struct list_head *ops_list)
>  {
>  	struct drm_exec exec;
> -	struct xe_vma_op *op, *next;
> +	struct dma_fence *fence;
>  	int err;
> 
>  	lockdep_assert_held_write(&vm->lock);
> @@ -2820,19 +2836,14 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm
> *vm,
>  		if (err)
>  			goto unlock;
> 
> -		list_for_each_entry_safe(op, next, ops_list, link) {
> -			err = xe_vma_op_execute(vm, op);
> -			if (err) {
> -				drm_warn(&vm->xe->drm, "VM op(%d) failed
> with %d",
> -					 op->base.op, err);
> -				/*
> -				 * FIXME: Killing VM rather than proper error
> handling
> -				 */
> -				xe_vm_kill(vm, false);
> -				err = -ENOSPC;
> -				goto unlock;
> -			}
> -			xe_vma_op_cleanup(vm, op);
> +		fence = ops_execute(vm, ops_list, true);
> +		if (IS_ERR(fence)) {
> +			err = PTR_ERR(fence);
> +			/* FIXME: Killing VM rather than proper error handling */
> +			xe_vm_kill(vm, false);
> +			goto unlock;
> +		} else {
> +			dma_fence_put(fence);
>  		}
>  	}
> 
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 03/30] drm/xe: Move migrate to prefetch to op_lock function
  2024-03-08  5:07 ` [PATCH v4 03/30] drm/xe: Move migrate to prefetch to op_lock function Matthew Brost
@ 2024-03-22 17:06   ` Zeng, Oak
  2024-03-22 17:36     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-22 17:06 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew



> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 03/30] drm/xe: Move migrate to prefetch to op_lock function
> 
> Migrates need to be done under drm exec to make lockdep happy,


Can you explain more here? By under drm exec, do you mean drm_exec_until_all_locked? I do see xe_vm_prefetch/xe_bo_migrate is called inside drm_exec_until_all_locked, in patch 1 of this series, in function vm_bind_ioctl_ops_execute

 move
> the migrate done for prefetches under the op_lock function.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm.c | 28 +++++++++++++---------------
>  1 file changed, 13 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index fb73afcab3b7..70a5ba621e4e 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -1994,20 +1994,10 @@ static const u32 region_to_mem_type[] = {
> 
>  static struct dma_fence *
>  xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
> -	       struct xe_exec_queue *q, u32 region,
> -	       struct xe_sync_entry *syncs, u32 num_syncs,
> -	       bool first_op, bool last_op)
> +	       struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> +	       u32 num_syncs, bool first_op, bool last_op)
>  {
>  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> q);
> -	int err;
> -
> -	xe_assert(vm->xe, region <= ARRAY_SIZE(region_to_mem_type));
> -
> -	if (!xe_vma_has_no_bo(vma)) {
> -		err = xe_bo_migrate(xe_vma_bo(vma),
> region_to_mem_type[region]);
> -		if (err)
> -			return ERR_PTR(err);
> -	}
> 
>  	if (vma->tile_mask != (vma->tile_present & ~vma->usm.tile_invalidated))
> {
>  		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs,
> num_syncs,
> @@ -2540,8 +2530,7 @@ static struct dma_fence *op_execute(struct xe_vm
> *vm, struct xe_vma *vma,
>  				     op->flags & XE_VMA_OP_LAST);
>  		break;
>  	case DRM_GPUVA_OP_PREFETCH:
> -		fence = xe_vm_prefetch(vm, vma, op->q, op->prefetch.region,
> -				       op->syncs, op->num_syncs,
> +		fence = xe_vm_prefetch(vm, vma, op->q, op->syncs, op-
> >num_syncs,
>  				       op->flags & XE_VMA_OP_FIRST,
>  				       op->flags & XE_VMA_OP_LAST);
>  		break;
> @@ -2766,8 +2755,17 @@ static int op_lock(struct drm_exec *exec, struct xe_vm
> *vm,
>  		err = vma_lock(exec, gpuva_to_vma(op->base.unmap.va), false);
>  		break;
>  	case DRM_GPUVA_OP_PREFETCH:
> -		err = vma_lock(exec, gpuva_to_vma(op->base.prefetch.va),
> true);
> +	{
> +		struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va);
> +		u32 region = op->prefetch.region;
> +
> +		xe_assert(vm->xe, region <=
> ARRAY_SIZE(region_to_mem_type));
> +
> +		err = vma_lock(exec, vma, false);
> +		if (!err && !xe_vma_has_no_bo(vma))
> +			err = xe_bo_migrate(xe_vma_bo(vma), region);
>  		break;
> +	}

Understand you have a reason to do this. It does introduce confusion: the function is called op_lock and now you have a migration operation inside.


Oak


>  	default:
>  		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
>  	}
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 04/30] drm/xe: Add struct xe_vma_ops abstraction
  2024-03-08  5:07 ` [PATCH v4 04/30] drm/xe: Add struct xe_vma_ops abstraction Matthew Brost
@ 2024-03-22 17:13   ` Zeng, Oak
  0 siblings, 0 replies; 76+ messages in thread
From: Zeng, Oak @ 2024-03-22 17:13 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew

This patch lgtm. Reviewed-by: Oak Zeng <oak.zeng@intel.com>

> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 04/30] drm/xe: Add struct xe_vma_ops abstraction
> 
> Having a structure which encapsulates a list of VMA operations will help
> enable 1 job for the entire list.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm.c       | 37 ++++++++++++++++++--------------
>  drivers/gpu/drm/xe/xe_vm_types.h |  7 ++++++
>  2 files changed, 28 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 70a5ba621e4e..e342af6b51b1 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -2305,7 +2305,7 @@ static int xe_vma_op_commit(struct xe_vm *vm, struct
> xe_vma_op *op)
>  static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
>  				   struct drm_gpuva_ops *ops,
>  				   struct xe_sync_entry *syncs, u32 num_syncs,
> -				   struct list_head *ops_list, bool last)
> +				   struct xe_vma_ops *vops, bool last)
>  {
>  	struct xe_device *xe = vm->xe;
>  	struct xe_vma_op *last_op = NULL;
> @@ -2317,11 +2317,11 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> *vm, struct xe_exec_queue *q,
>  	drm_gpuva_for_each_op(__op, ops) {
>  		struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
>  		struct xe_vma *vma;
> -		bool first = list_empty(ops_list);
> +		bool first = list_empty(&vops->list);
>  		unsigned int flags = 0;
> 
>  		INIT_LIST_HEAD(&op->link);
> -		list_add_tail(&op->link, ops_list);
> +		list_add_tail(&op->link, &vops->list);
> 
>  		if (first) {
>  			op->flags |= XE_VMA_OP_FIRST;
> @@ -2445,7 +2445,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm,
> struct xe_exec_queue *q,
>  	}
> 
>  	/* FIXME: Unhandled corner case */
> -	XE_WARN_ON(!last_op && last && !list_empty(ops_list));
> +	XE_WARN_ON(!last_op && last && !list_empty(&vops->list));
> 
>  	if (!last_op)
>  		return 0;
> @@ -2775,7 +2775,7 @@ static int op_lock(struct drm_exec *exec, struct xe_vm
> *vm,
> 
>  static int vm_bind_ioctl_ops_lock(struct drm_exec *exec,
>  				  struct xe_vm *vm,
> -				  struct list_head *ops_list)
> +				  struct xe_vma_ops *vops)
>  {
>  	struct xe_vma_op *op;
>  	int err;
> @@ -2784,7 +2784,7 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec
> *exec,
>  	if (err)
>  		return err;
> 
> -	list_for_each_entry(op, ops_list, link) {
> +	list_for_each_entry(op, &vops->list, link) {
>  		err = op_lock(exec, vm, op);
>  		if (err)
>  			return err;
> @@ -2794,13 +2794,13 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec
> *exec,
>  }
> 
>  static struct dma_fence *ops_execute(struct xe_vm *vm,
> -				     struct list_head *ops_list,
> +				     struct xe_vma_ops *vops,
>  				     bool cleanup)
>  {
>  	struct xe_vma_op *op, *next;
>  	struct dma_fence *fence = NULL;
> 
> -	list_for_each_entry_safe(op, next, ops_list, link) {
> +	list_for_each_entry_safe(op, next, &vops->list, link) {
>  		if (!IS_ERR(fence)) {
>  			dma_fence_put(fence);
>  			fence = xe_vma_op_execute(vm, op);
> @@ -2818,7 +2818,7 @@ static struct dma_fence *ops_execute(struct xe_vm
> *vm,
>  }
> 
>  static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
> -				     struct list_head *ops_list)
> +				     struct xe_vma_ops *vops)
>  {
>  	struct drm_exec exec;
>  	struct dma_fence *fence;
> @@ -2829,12 +2829,12 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm
> *vm,
>  	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT |
>  		      DRM_EXEC_IGNORE_DUPLICATES, 0);
>  	drm_exec_until_all_locked(&exec) {
> -		err = vm_bind_ioctl_ops_lock(&exec, vm, ops_list);
> +		err = vm_bind_ioctl_ops_lock(&exec, vm, vops);
>  		drm_exec_retry_on_contention(&exec);
>  		if (err)
>  			goto unlock;
> 
> -		fence = ops_execute(vm, ops_list, true);
> +		fence = ops_execute(vm, vops, true);
>  		if (IS_ERR(fence)) {
>  			err = PTR_ERR(fence);
>  			/* FIXME: Killing VM rather than proper error handling */
> @@ -2992,6 +2992,11 @@ static int vm_bind_ioctl_signal_fences(struct xe_vm
> *vm,
>  	return err;
>  }
> 
> +static void xe_vma_ops_init(struct xe_vma_ops *vops)
> +{
> +	INIT_LIST_HEAD(&vops->list);
> +}
> +
>  int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
>  {
>  	struct xe_device *xe = to_xe_device(dev);
> @@ -3005,7 +3010,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void
> *data, struct drm_file *file)
>  	u32 num_syncs, num_ufence = 0;
>  	struct xe_sync_entry *syncs = NULL;
>  	struct drm_xe_vm_bind_op *bind_ops;
> -	LIST_HEAD(ops_list);
> +	struct xe_vma_ops vops;
>  	int err;
>  	int i;
> 
> @@ -3156,6 +3161,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void
> *data, struct drm_file *file)
>  		goto free_syncs;
>  	}
> 
> +	xe_vma_ops_init(&vops);
>  	for (i = 0; i < args->num_binds; ++i) {
>  		u64 range = bind_ops[i].range;
>  		u64 addr = bind_ops[i].addr;
> @@ -3175,14 +3181,13 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void
> *data, struct drm_file *file)
>  		}
> 
>  		err = vm_bind_ioctl_ops_parse(vm, q, ops[i], syncs, num_syncs,
> -					      &ops_list,
> -					      i == args->num_binds - 1);
> +					      &vops, i == args->num_binds - 1);
>  		if (err)
>  			goto unwind_ops;
>  	}
> 
>  	/* Nothing to do */
> -	if (list_empty(&ops_list)) {
> +	if (list_empty(&vops.list)) {
>  		err = -ENODATA;
>  		goto unwind_ops;
>  	}
> @@ -3191,7 +3196,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void
> *data, struct drm_file *file)
>  	if (q)
>  		xe_exec_queue_get(q);
> 
> -	err = vm_bind_ioctl_ops_execute(vm, &ops_list);
> +	err = vm_bind_ioctl_ops_execute(vm, &vops);
> 
>  	up_write(&vm->lock);
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> b/drivers/gpu/drm/xe/xe_vm_types.h
> index 79b5cab57711..cc3dce893f1e 100644
> --- a/drivers/gpu/drm/xe/xe_vm_types.h
> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> @@ -355,4 +355,11 @@ struct xe_vma_op {
>  		struct xe_vma_op_prefetch prefetch;
>  	};
>  };
> +
> +/** struct xe_vma_ops - VMA operations */
> +struct xe_vma_ops {
> +	/** @list: list of VMA operations */
> +	struct list_head list;
> +};
> +
>  #endif
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 02/30] drm/xe: Add ops_execute function which returns a fence
  2024-03-22 16:11   ` Zeng, Oak
@ 2024-03-22 17:31     ` Matthew Brost
  2024-03-22 19:39       ` Zeng, Oak
  0 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-22 17:31 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Fri, Mar 22, 2024 at 10:11:41AM -0600, Zeng, Oak wrote:
> 
> 
> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 02/30] drm/xe: Add ops_execute function which returns a
> > fence
> > 
> > Add ops_execute function which returns a fence. This will be helpful to
> > initiate all binds (VM bind IOCTL, rebinds in exec IOCTL, rebinds in
> > preempt rebind worker, and rebinds in pagefaults) via a gpuva ops list.
> > Returning a fence is needed in various paths.
> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_vm.c | 211 +++++++++++++++++++------------------
> >  1 file changed, 111 insertions(+), 100 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index 3b5dc6de07f7..fb73afcab3b7 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -1789,16 +1789,17 @@ find_ufence_get(struct xe_sync_entry *syncs, u32
> > num_syncs)
> >  	return NULL;
> >  }
> > 
> > -static int __xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma,
> > -			struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> > -			u32 num_syncs, bool immediate, bool first_op,
> > -			bool last_op)
> > +static struct dma_fence *
> > +xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue *q,
> > +	   struct xe_bo *bo, struct xe_sync_entry *syncs, u32 num_syncs,
> > +	   bool immediate, bool first_op, bool last_op)
> >  {
> >  	struct dma_fence *fence;
> >  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > q);
> >  	struct xe_user_fence *ufence;
> > 
> >  	xe_vm_assert_held(vm);
> > +	xe_bo_assert_held(bo);
> > 
> >  	ufence = find_ufence_get(syncs, num_syncs);
> >  	if (vma->ufence && ufence)
> > @@ -1810,7 +1811,7 @@ static int __xe_vm_bind(struct xe_vm *vm, struct
> > xe_vma *vma,
> >  		fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, first_op,
> >  				       last_op);
> >  		if (IS_ERR(fence))
> > -			return PTR_ERR(fence);
> > +			return fence;
> >  	} else {
> >  		int i;
> > 
> > @@ -1825,26 +1826,14 @@ static int __xe_vm_bind(struct xe_vm *vm, struct
> > xe_vma *vma,
> > 
> >  	if (last_op)
> >  		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> > -	dma_fence_put(fence);
> > -
> > -	return 0;
> > -}
> > -
> > -static int xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct
> > xe_exec_queue *q,
> > -		      struct xe_bo *bo, struct xe_sync_entry *syncs,
> > -		      u32 num_syncs, bool immediate, bool first_op,
> > -		      bool last_op)
> > -{
> > -	xe_vm_assert_held(vm);
> > -	xe_bo_assert_held(bo);
> > 
> > -	return __xe_vm_bind(vm, vma, q, syncs, num_syncs, immediate,
> > first_op,
> > -			    last_op);
> > +	return fence;
> >  }
> > 
> > -static int xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
> > -			struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> > -			u32 num_syncs, bool first_op, bool last_op)
> > +static struct dma_fence *
> > +xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
> > +	     struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> > +	     u32 num_syncs, bool first_op, bool last_op)
> >  {
> >  	struct dma_fence *fence;
> >  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > q);
> > @@ -1854,14 +1843,13 @@ static int xe_vm_unbind(struct xe_vm *vm, struct
> > xe_vma *vma,
> > 
> >  	fence = xe_vm_unbind_vma(vma, q, syncs, num_syncs, first_op,
> > last_op);
> >  	if (IS_ERR(fence))
> > -		return PTR_ERR(fence);
> > +		return fence;
> > 
> >  	xe_vma_destroy(vma, fence);
> >  	if (last_op)
> >  		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> > -	dma_fence_put(fence);
> > 
> > -	return 0;
> > +	return fence;
> >  }
> > 
> >  #define ALL_DRM_XE_VM_CREATE_FLAGS
> > (DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE | \
> > @@ -2004,10 +1992,11 @@ static const u32 region_to_mem_type[] = {
> >  	XE_PL_VRAM1,
> >  };
> > 
> > -static int xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
> > -			  struct xe_exec_queue *q, u32 region,
> > -			  struct xe_sync_entry *syncs, u32 num_syncs,
> > -			  bool first_op, bool last_op)
> > +static struct dma_fence *
> > +xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
> > +	       struct xe_exec_queue *q, u32 region,
> > +	       struct xe_sync_entry *syncs, u32 num_syncs,
> > +	       bool first_op, bool last_op)
> >  {
> >  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > q);
> >  	int err;
> > @@ -2017,27 +2006,24 @@ static int xe_vm_prefetch(struct xe_vm *vm, struct
> > xe_vma *vma,
> >  	if (!xe_vma_has_no_bo(vma)) {
> >  		err = xe_bo_migrate(xe_vma_bo(vma),
> > region_to_mem_type[region]);
> >  		if (err)
> > -			return err;
> > +			return ERR_PTR(err);
> >  	}
> > 
> >  	if (vma->tile_mask != (vma->tile_present & ~vma->usm.tile_invalidated))
> > {
> >  		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs,
> > num_syncs,
> >  				  true, first_op, last_op);
> >  	} else {
> > +		struct dma_fence *fence =
> > +			xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> >  		int i;
> > 
> >  		/* Nothing to do, signal fences now */
> >  		if (last_op) {
> > -			for (i = 0; i < num_syncs; i++) {
> > -				struct dma_fence *fence =
> > -
> > 	xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> > -
> > +			for (i = 0; i < num_syncs; i++)
> >  				xe_sync_entry_signal(&syncs[i], NULL, fence);
> > -				dma_fence_put(fence);
> > -			}
> >  		}
> > 
> > -		return 0;
> > +		return fence;
> >  	}
> >  }
> > 
> > @@ -2484,10 +2470,10 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> > *vm, struct xe_exec_queue *q,
> >  	return 0;
> >  }
> > 
> > -static int op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > -		      struct xe_vma_op *op)
> > +static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > +				    struct xe_vma_op *op)
> >  {
> > -	int err;
> > +	struct dma_fence *fence = NULL;
> > 
> >  	lockdep_assert_held_write(&vm->lock);
> >  	xe_vm_assert_held(vm);
> > @@ -2495,11 +2481,11 @@ static int op_execute(struct xe_vm *vm, struct
> > xe_vma *vma,
> > 
> >  	switch (op->base.op) {
> >  	case DRM_GPUVA_OP_MAP:
> > -		err = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
> > -				 op->syncs, op->num_syncs,
> > -				 !xe_vm_in_fault_mode(vm),
> > -				 op->flags & XE_VMA_OP_FIRST,
> > -				 op->flags & XE_VMA_OP_LAST);
> > +		fence = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
> > +				   op->syncs, op->num_syncs,
> > +				   !xe_vm_in_fault_mode(vm),
> > +				   op->flags & XE_VMA_OP_FIRST,
> > +				   op->flags & XE_VMA_OP_LAST);
> >  		break;
> >  	case DRM_GPUVA_OP_REMAP:
> >  	{
> > @@ -2509,37 +2495,39 @@ static int op_execute(struct xe_vm *vm, struct
> > xe_vma *vma,
> >  		if (!op->remap.unmap_done) {
> >  			if (prev || next)
> >  				vma->gpuva.flags |= XE_VMA_FIRST_REBIND;
> > -			err = xe_vm_unbind(vm, vma, op->q, op->syncs,
> > -					   op->num_syncs,
> > -					   op->flags & XE_VMA_OP_FIRST,
> > -					   op->flags & XE_VMA_OP_LAST &&
> > -					   !prev && !next);
> > -			if (err)
> > +			fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
> > +					     op->num_syncs,
> > +					     op->flags & XE_VMA_OP_FIRST,
> > +					     op->flags & XE_VMA_OP_LAST &&
> > +					     !prev && !next);
> > +			if (IS_ERR(fence))
> >  				break;
> >  			op->remap.unmap_done = true;
> >  		}
> > 
> >  		if (prev) {
> >  			op->remap.prev->gpuva.flags |= XE_VMA_LAST_REBIND;
> > -			err = xe_vm_bind(vm, op->remap.prev, op->q,
> > -					 xe_vma_bo(op->remap.prev), op->syncs,
> > -					 op->num_syncs, true, false,
> > -					 op->flags & XE_VMA_OP_LAST
> > && !next);
> > +			dma_fence_put(fence);
> 
> 
> So you drop the previous fence. I assume in later operation, we will need to wait dma-fence for the previous operation to complete. Is it safe to only wait for the last fence? Shouldn't we wait all the fences, such as chain the fences in some way?
> 

All fences on single xe_exec_queue are should ordered (e.g if the last
completes all fences prior are also complete).

Techincally this is broken on tip and at this point in the series too as
we mix job fences and tlb invalidation fences on single xe_exec_queue.
This series gets around to fix this once we convert an IOCTL into single
bind job. So this patch while not perfect is regressing anything working
toward 100% correctness.

> > +			fence = xe_vm_bind(vm, op->remap.prev, op->q,
> > +					   xe_vma_bo(op->remap.prev), op-
> > >syncs,
> > +					   op->num_syncs, true, false,
> > +					   op->flags & XE_VMA_OP_LAST
> > && !next);
> >  			op->remap.prev->gpuva.flags &=
> > ~XE_VMA_LAST_REBIND;
> > -			if (err)
> > +			if (IS_ERR(fence))
> >  				break;
> >  			op->remap.prev = NULL;
> >  		}
> > 
> >  		if (next) {
> >  			op->remap.next->gpuva.flags |= XE_VMA_LAST_REBIND;
> > -			err = xe_vm_bind(vm, op->remap.next, op->q,
> > -					 xe_vma_bo(op->remap.next),
> > -					 op->syncs, op->num_syncs,
> > -					 true, false,
> > -					 op->flags & XE_VMA_OP_LAST);
> > +			dma_fence_put(fence);
> 
> 
> Same comment as above

Same answer.

> > +			fence = xe_vm_bind(vm, op->remap.next, op->q,
> > +					   xe_vma_bo(op->remap.next),
> > +					   op->syncs, op->num_syncs,
> > +					   true, false,
> > +					   op->flags & XE_VMA_OP_LAST);
> >  			op->remap.next->gpuva.flags &=
> > ~XE_VMA_LAST_REBIND;
> > -			if (err)
> > +			if (IS_ERR(fence))
> >  				break;
> >  			op->remap.next = NULL;
> >  		}
> > @@ -2547,34 +2535,36 @@ static int op_execute(struct xe_vm *vm, struct
> > xe_vma *vma,
> >  		break;
> >  	}
> >  	case DRM_GPUVA_OP_UNMAP:
> > -		err = xe_vm_unbind(vm, vma, op->q, op->syncs,
> > -				   op->num_syncs, op->flags &
> > XE_VMA_OP_FIRST,
> > -				   op->flags & XE_VMA_OP_LAST);
> > +		fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
> > +				     op->num_syncs, op->flags &
> > XE_VMA_OP_FIRST,
> > +				     op->flags & XE_VMA_OP_LAST);
> >  		break;
> >  	case DRM_GPUVA_OP_PREFETCH:
> > -		err = xe_vm_prefetch(vm, vma, op->q, op->prefetch.region,
> > -				     op->syncs, op->num_syncs,
> > -				     op->flags & XE_VMA_OP_FIRST,
> > -				     op->flags & XE_VMA_OP_LAST);
> > +		fence = xe_vm_prefetch(vm, vma, op->q, op->prefetch.region,
> > +				       op->syncs, op->num_syncs,
> > +				       op->flags & XE_VMA_OP_FIRST,
> > +				       op->flags & XE_VMA_OP_LAST);
> >  		break;
> >  	default:
> >  		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> >  	}
> > 
> > -	if (err)
> > +	if (IS_ERR(fence))
> >  		trace_xe_vma_fail(vma);
> > 
> > -	return err;
> > +	return fence;
> >  }
> > 
> > -static int __xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > -			       struct xe_vma_op *op)
> > +static struct dma_fence *
> > +__xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > +		    struct xe_vma_op *op)
> >  {
> > +	struct dma_fence *fence;
> >  	int err;
> > 
> >  retry_userptr:
> > -	err = op_execute(vm, vma, op);
> > -	if (err == -EAGAIN) {
> > +	fence = op_execute(vm, vma, op);
> > +	if (IS_ERR(fence) && PTR_ERR(fence) == -EAGAIN) {
> >  		lockdep_assert_held_write(&vm->lock);
> > 
> >  		if (op->base.op == DRM_GPUVA_OP_REMAP) {
> > @@ -2591,22 +2581,24 @@ static int __xe_vma_op_execute(struct xe_vm *vm,
> > struct xe_vma *vma,
> >  			if (!err)
> >  				goto retry_userptr;
> > 
> > +			fence = ERR_PTR(err);
> >  			trace_xe_vma_fail(vma);
> >  		}
> >  	}
> > 
> > -	return err;
> > +	return fence;
> >  }
> > 
> > -static int xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
> > +static struct dma_fence *
> > +xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
> >  {
> > -	int ret = 0;
> > +	struct dma_fence *fence = ERR_PTR(-ENOMEM);
> > 
> >  	lockdep_assert_held_write(&vm->lock);
> > 
> >  	switch (op->base.op) {
> >  	case DRM_GPUVA_OP_MAP:
> > -		ret = __xe_vma_op_execute(vm, op->map.vma, op);
> > +		fence = __xe_vma_op_execute(vm, op->map.vma, op);
> >  		break;
> >  	case DRM_GPUVA_OP_REMAP:
> >  	{
> > @@ -2619,23 +2611,23 @@ static int xe_vma_op_execute(struct xe_vm *vm,
> > struct xe_vma_op *op)
> >  		else
> >  			vma = op->remap.next;
> > 
> > -		ret = __xe_vma_op_execute(vm, vma, op);
> > +		fence = __xe_vma_op_execute(vm, vma, op);
> >  		break;
> >  	}
> >  	case DRM_GPUVA_OP_UNMAP:
> > -		ret = __xe_vma_op_execute(vm, gpuva_to_vma(op-
> > >base.unmap.va),
> > -					  op);
> > +		fence = __xe_vma_op_execute(vm, gpuva_to_vma(op-
> > >base.unmap.va),
> > +					    op);
> >  		break;
> >  	case DRM_GPUVA_OP_PREFETCH:
> > -		ret = __xe_vma_op_execute(vm,
> > -					  gpuva_to_vma(op->base.prefetch.va),
> > -					  op);
> > +		fence = __xe_vma_op_execute(vm,
> > +					    gpuva_to_vma(op->base.prefetch.va),
> > +					    op);
> >  		break;
> >  	default:
> >  		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> >  	}
> > 
> > -	return ret;
> > +	return fence;
> >  }
> > 
> >  static void xe_vma_op_cleanup(struct xe_vm *vm, struct xe_vma_op *op)
> > @@ -2803,11 +2795,35 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec
> > *exec,
> >  	return 0;
> >  }
> > 
> > +static struct dma_fence *ops_execute(struct xe_vm *vm,
> > +				     struct list_head *ops_list,
> > +				     bool cleanup)
> > +{
> > +	struct xe_vma_op *op, *next;
> > +	struct dma_fence *fence = NULL;
> > +
> > +	list_for_each_entry_safe(op, next, ops_list, link) {
> > +		if (!IS_ERR(fence)) {
> > +			dma_fence_put(fence);
> > +			fence = xe_vma_op_execute(vm, op);
> 
> So you only return the fence of the last operation. In the later on codes, do you use fence to wait for *all* operations to finish?
>

Same answer as above, all fences on exec_queue should be ordered.
 
> > +		}
> > +		if (IS_ERR(fence)) {
> > +			drm_warn(&vm->xe->drm, "VM op(%d) failed with %ld",
> > +				 op->base.op, PTR_ERR(fence));
> > +			fence = ERR_PTR(-ENOSPC);
> 
> So even if there is error, you don't break the loop. Is it to perform the cleanup below?
> 
> Once error happen for one operation, you seem to print the same error message for all the rest operations....because fence = xe_vma_op_execute(vm, op) is not called anymore after the first error
>

Yes.

Matt

> 
> Oak
> 
> > +		}
> > +		if (cleanup)
> > +			xe_vma_op_cleanup(vm, op);
> > +	}
> > +
> > +	return fence;
> > +}
> > +
> >  static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
> >  				     struct list_head *ops_list)
> >  {
> >  	struct drm_exec exec;
> > -	struct xe_vma_op *op, *next;
> > +	struct dma_fence *fence;
> >  	int err;
> > 
> >  	lockdep_assert_held_write(&vm->lock);
> > @@ -2820,19 +2836,14 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm
> > *vm,
> >  		if (err)
> >  			goto unlock;
> > 
> > -		list_for_each_entry_safe(op, next, ops_list, link) {
> > -			err = xe_vma_op_execute(vm, op);
> > -			if (err) {
> > -				drm_warn(&vm->xe->drm, "VM op(%d) failed
> > with %d",
> > -					 op->base.op, err);
> > -				/*
> > -				 * FIXME: Killing VM rather than proper error
> > handling
> > -				 */
> > -				xe_vm_kill(vm, false);
> > -				err = -ENOSPC;
> > -				goto unlock;
> > -			}
> > -			xe_vma_op_cleanup(vm, op);
> > +		fence = ops_execute(vm, ops_list, true);
> > +		if (IS_ERR(fence)) {
> > +			err = PTR_ERR(fence);
> > +			/* FIXME: Killing VM rather than proper error handling */
> > +			xe_vm_kill(vm, false);
> > +			goto unlock;
> > +		} else {
> > +			dma_fence_put(fence);
> >  		}
> >  	}
> > 
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 03/30] drm/xe: Move migrate to prefetch to op_lock function
  2024-03-22 17:06   ` Zeng, Oak
@ 2024-03-22 17:36     ` Matthew Brost
  2024-03-22 19:45       ` Zeng, Oak
  0 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-22 17:36 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Fri, Mar 22, 2024 at 11:06:28AM -0600, Zeng, Oak wrote:
> 
> 
> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 03/30] drm/xe: Move migrate to prefetch to op_lock function
> > 
> > Migrates need to be done under drm exec to make lockdep happy,
> 
> 
> Can you explain more here? By under drm exec, do you mean drm_exec_until_all_locked? I do see xe_vm_prefetch/xe_bo_migrate is called inside drm_exec_until_all_locked, in patch 1 of this series, in function vm_bind_ioctl_ops_execute
> 

This is a stale comment, will fix. Something like:

All non-binding operations in VM bind IOCTL should be in the lock and
prepare step rather than the execution step. Move prefetch to conform to
this pattern.

>  move
> > the migrate done for prefetches under the op_lock function.
> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_vm.c | 28 +++++++++++++---------------
> >  1 file changed, 13 insertions(+), 15 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index fb73afcab3b7..70a5ba621e4e 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -1994,20 +1994,10 @@ static const u32 region_to_mem_type[] = {
> > 
> >  static struct dma_fence *
> >  xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
> > -	       struct xe_exec_queue *q, u32 region,
> > -	       struct xe_sync_entry *syncs, u32 num_syncs,
> > -	       bool first_op, bool last_op)
> > +	       struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> > +	       u32 num_syncs, bool first_op, bool last_op)
> >  {
> >  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > q);
> > -	int err;
> > -
> > -	xe_assert(vm->xe, region <= ARRAY_SIZE(region_to_mem_type));
> > -
> > -	if (!xe_vma_has_no_bo(vma)) {
> > -		err = xe_bo_migrate(xe_vma_bo(vma),
> > region_to_mem_type[region]);
> > -		if (err)
> > -			return ERR_PTR(err);
> > -	}
> > 
> >  	if (vma->tile_mask != (vma->tile_present & ~vma->usm.tile_invalidated))
> > {
> >  		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs,
> > num_syncs,
> > @@ -2540,8 +2530,7 @@ static struct dma_fence *op_execute(struct xe_vm
> > *vm, struct xe_vma *vma,
> >  				     op->flags & XE_VMA_OP_LAST);
> >  		break;
> >  	case DRM_GPUVA_OP_PREFETCH:
> > -		fence = xe_vm_prefetch(vm, vma, op->q, op->prefetch.region,
> > -				       op->syncs, op->num_syncs,
> > +		fence = xe_vm_prefetch(vm, vma, op->q, op->syncs, op-
> > >num_syncs,
> >  				       op->flags & XE_VMA_OP_FIRST,
> >  				       op->flags & XE_VMA_OP_LAST);
> >  		break;
> > @@ -2766,8 +2755,17 @@ static int op_lock(struct drm_exec *exec, struct xe_vm
> > *vm,
> >  		err = vma_lock(exec, gpuva_to_vma(op->base.unmap.va), false);
> >  		break;
> >  	case DRM_GPUVA_OP_PREFETCH:
> > -		err = vma_lock(exec, gpuva_to_vma(op->base.prefetch.va),
> > true);
> > +	{
> > +		struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va);
> > +		u32 region = op->prefetch.region;
> > +
> > +		xe_assert(vm->xe, region <=
> > ARRAY_SIZE(region_to_mem_type));
> > +
> > +		err = vma_lock(exec, vma, false);
> > +		if (!err && !xe_vma_has_no_bo(vma))
> > +			err = xe_bo_migrate(xe_vma_bo(vma), region);
> >  		break;
> > +	}
> 
> Understand you have a reason to do this. It does introduce confusion: the function is called op_lock and now you have a migration operation inside.
> 

Yes, how about? s/op_lock/op_lock_and_prepare/

Likewise: s/vma_lock/vma_lock/vma_lock_and_validate/

Matt

> 
> Oak
> 
> 
> >  	default:
> >  		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> >  	}
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 02/30] drm/xe: Add ops_execute function which returns a fence
  2024-03-22 17:31     ` Matthew Brost
@ 2024-03-22 19:39       ` Zeng, Oak
  0 siblings, 0 replies; 76+ messages in thread
From: Zeng, Oak @ 2024-03-22 19:39 UTC (permalink / raw)
  To: Brost, Matthew; +Cc: intel-xe



> -----Original Message-----
> From: Brost, Matthew <matthew.brost@intel.com>
> Sent: Friday, March 22, 2024 1:31 PM
> To: Zeng, Oak <oak.zeng@intel.com>
> Cc: intel-xe@lists.freedesktop.org
> Subject: Re: [PATCH v4 02/30] drm/xe: Add ops_execute function which returns a
> fence
> 
> On Fri, Mar 22, 2024 at 10:11:41AM -0600, Zeng, Oak wrote:
> >
> >
> > > -----Original Message-----
> > > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of
> Matthew
> > > Brost
> > > Sent: Friday, March 8, 2024 12:08 AM
> > > To: intel-xe@lists.freedesktop.org
> > > Cc: Brost, Matthew <matthew.brost@intel.com>
> > > Subject: [PATCH v4 02/30] drm/xe: Add ops_execute function which returns a
> > > fence
> > >
> > > Add ops_execute function which returns a fence. This will be helpful to
> > > initiate all binds (VM bind IOCTL, rebinds in exec IOCTL, rebinds in
> > > preempt rebind worker, and rebinds in pagefaults) via a gpuva ops list.
> > > Returning a fence is needed in various paths.
> > >
> > > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > > ---
> > >  drivers/gpu/drm/xe/xe_vm.c | 211 +++++++++++++++++++------------------
> > >  1 file changed, 111 insertions(+), 100 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > > index 3b5dc6de07f7..fb73afcab3b7 100644
> > > --- a/drivers/gpu/drm/xe/xe_vm.c
> > > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > > @@ -1789,16 +1789,17 @@ find_ufence_get(struct xe_sync_entry *syncs,
> u32
> > > num_syncs)
> > >  	return NULL;
> > >  }
> > >
> > > -static int __xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma,
> > > -			struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> > > -			u32 num_syncs, bool immediate, bool first_op,
> > > -			bool last_op)
> > > +static struct dma_fence *
> > > +xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct
> xe_exec_queue *q,
> > > +	   struct xe_bo *bo, struct xe_sync_entry *syncs, u32 num_syncs,
> > > +	   bool immediate, bool first_op, bool last_op)
> > >  {
> > >  	struct dma_fence *fence;
> > >  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > > q);
> > >  	struct xe_user_fence *ufence;
> > >
> > >  	xe_vm_assert_held(vm);
> > > +	xe_bo_assert_held(bo);
> > >
> > >  	ufence = find_ufence_get(syncs, num_syncs);
> > >  	if (vma->ufence && ufence)
> > > @@ -1810,7 +1811,7 @@ static int __xe_vm_bind(struct xe_vm *vm, struct
> > > xe_vma *vma,
> > >  		fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, first_op,
> > >  				       last_op);
> > >  		if (IS_ERR(fence))
> > > -			return PTR_ERR(fence);
> > > +			return fence;
> > >  	} else {
> > >  		int i;
> > >
> > > @@ -1825,26 +1826,14 @@ static int __xe_vm_bind(struct xe_vm *vm, struct
> > > xe_vma *vma,
> > >
> > >  	if (last_op)
> > >  		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> > > -	dma_fence_put(fence);
> > > -
> > > -	return 0;
> > > -}
> > > -
> > > -static int xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct
> > > xe_exec_queue *q,
> > > -		      struct xe_bo *bo, struct xe_sync_entry *syncs,
> > > -		      u32 num_syncs, bool immediate, bool first_op,
> > > -		      bool last_op)
> > > -{
> > > -	xe_vm_assert_held(vm);
> > > -	xe_bo_assert_held(bo);
> > >
> > > -	return __xe_vm_bind(vm, vma, q, syncs, num_syncs, immediate,
> > > first_op,
> > > -			    last_op);
> > > +	return fence;
> > >  }
> > >
> > > -static int xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
> > > -			struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> > > -			u32 num_syncs, bool first_op, bool last_op)
> > > +static struct dma_fence *
> > > +xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
> > > +	     struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> > > +	     u32 num_syncs, bool first_op, bool last_op)
> > >  {
> > >  	struct dma_fence *fence;
> > >  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > > q);
> > > @@ -1854,14 +1843,13 @@ static int xe_vm_unbind(struct xe_vm *vm, struct
> > > xe_vma *vma,
> > >
> > >  	fence = xe_vm_unbind_vma(vma, q, syncs, num_syncs, first_op,
> > > last_op);
> > >  	if (IS_ERR(fence))
> > > -		return PTR_ERR(fence);
> > > +		return fence;
> > >
> > >  	xe_vma_destroy(vma, fence);
> > >  	if (last_op)
> > >  		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> > > -	dma_fence_put(fence);
> > >
> > > -	return 0;
> > > +	return fence;
> > >  }
> > >
> > >  #define ALL_DRM_XE_VM_CREATE_FLAGS
> > > (DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE | \
> > > @@ -2004,10 +1992,11 @@ static const u32 region_to_mem_type[] = {
> > >  	XE_PL_VRAM1,
> > >  };
> > >
> > > -static int xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
> > > -			  struct xe_exec_queue *q, u32 region,
> > > -			  struct xe_sync_entry *syncs, u32 num_syncs,
> > > -			  bool first_op, bool last_op)
> > > +static struct dma_fence *
> > > +xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
> > > +	       struct xe_exec_queue *q, u32 region,
> > > +	       struct xe_sync_entry *syncs, u32 num_syncs,
> > > +	       bool first_op, bool last_op)
> > >  {
> > >  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > > q);
> > >  	int err;
> > > @@ -2017,27 +2006,24 @@ static int xe_vm_prefetch(struct xe_vm *vm,
> struct
> > > xe_vma *vma,
> > >  	if (!xe_vma_has_no_bo(vma)) {
> > >  		err = xe_bo_migrate(xe_vma_bo(vma),
> > > region_to_mem_type[region]);
> > >  		if (err)
> > > -			return err;
> > > +			return ERR_PTR(err);
> > >  	}
> > >
> > >  	if (vma->tile_mask != (vma->tile_present & ~vma->usm.tile_invalidated))
> > > {
> > >  		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs,
> > > num_syncs,
> > >  				  true, first_op, last_op);
> > >  	} else {
> > > +		struct dma_fence *fence =
> > > +			xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> > >  		int i;
> > >
> > >  		/* Nothing to do, signal fences now */
> > >  		if (last_op) {
> > > -			for (i = 0; i < num_syncs; i++) {
> > > -				struct dma_fence *fence =
> > > -
> > > 	xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> > > -
> > > +			for (i = 0; i < num_syncs; i++)
> > >  				xe_sync_entry_signal(&syncs[i], NULL, fence);
> > > -				dma_fence_put(fence);
> > > -			}
> > >  		}
> > >
> > > -		return 0;
> > > +		return fence;
> > >  	}
> > >  }
> > >
> > > @@ -2484,10 +2470,10 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> > > *vm, struct xe_exec_queue *q,
> > >  	return 0;
> > >  }
> > >
> > > -static int op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > > -		      struct xe_vma_op *op)
> > > +static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma
> *vma,
> > > +				    struct xe_vma_op *op)
> > >  {
> > > -	int err;
> > > +	struct dma_fence *fence = NULL;
> > >
> > >  	lockdep_assert_held_write(&vm->lock);
> > >  	xe_vm_assert_held(vm);
> > > @@ -2495,11 +2481,11 @@ static int op_execute(struct xe_vm *vm, struct
> > > xe_vma *vma,
> > >
> > >  	switch (op->base.op) {
> > >  	case DRM_GPUVA_OP_MAP:
> > > -		err = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
> > > -				 op->syncs, op->num_syncs,
> > > -				 !xe_vm_in_fault_mode(vm),
> > > -				 op->flags & XE_VMA_OP_FIRST,
> > > -				 op->flags & XE_VMA_OP_LAST);
> > > +		fence = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
> > > +				   op->syncs, op->num_syncs,
> > > +				   !xe_vm_in_fault_mode(vm),
> > > +				   op->flags & XE_VMA_OP_FIRST,
> > > +				   op->flags & XE_VMA_OP_LAST);
> > >  		break;
> > >  	case DRM_GPUVA_OP_REMAP:
> > >  	{
> > > @@ -2509,37 +2495,39 @@ static int op_execute(struct xe_vm *vm, struct
> > > xe_vma *vma,
> > >  		if (!op->remap.unmap_done) {
> > >  			if (prev || next)
> > >  				vma->gpuva.flags |= XE_VMA_FIRST_REBIND;
> > > -			err = xe_vm_unbind(vm, vma, op->q, op->syncs,
> > > -					   op->num_syncs,
> > > -					   op->flags & XE_VMA_OP_FIRST,
> > > -					   op->flags & XE_VMA_OP_LAST &&
> > > -					   !prev && !next);
> > > -			if (err)
> > > +			fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
> > > +					     op->num_syncs,
> > > +					     op->flags & XE_VMA_OP_FIRST,
> > > +					     op->flags & XE_VMA_OP_LAST &&
> > > +					     !prev && !next);
> > > +			if (IS_ERR(fence))
> > >  				break;
> > >  			op->remap.unmap_done = true;
> > >  		}
> > >
> > >  		if (prev) {
> > >  			op->remap.prev->gpuva.flags |= XE_VMA_LAST_REBIND;
> > > -			err = xe_vm_bind(vm, op->remap.prev, op->q,
> > > -					 xe_vma_bo(op->remap.prev), op->syncs,
> > > -					 op->num_syncs, true, false,
> > > -					 op->flags & XE_VMA_OP_LAST
> > > && !next);
> > > +			dma_fence_put(fence);
> >
> >
> > So you drop the previous fence. I assume in later operation, we will need to
> wait dma-fence for the previous operation to complete. Is it safe to only wait for
> the last fence? Shouldn't we wait all the fences, such as chain the fences in some
> way?
> >
> 
> All fences on single xe_exec_queue are should ordered (e.g if the last
> completes all fences prior are also complete).

Ok, if all fences are ordered, this code make sense to me.

> 
> Techincally this is broken on tip and at this point in the series too as
> we mix job fences and tlb invalidation fences on single xe_exec_queue.
> This series gets around to fix this once we convert an IOCTL into single
> bind job. So this patch while not perfect is regressing anything working
> toward 100% correctness.
> 
> > > +			fence = xe_vm_bind(vm, op->remap.prev, op->q,
> > > +					   xe_vma_bo(op->remap.prev), op-
> > > >syncs,
> > > +					   op->num_syncs, true, false,
> > > +					   op->flags & XE_VMA_OP_LAST
> > > && !next);
> > >  			op->remap.prev->gpuva.flags &=
> > > ~XE_VMA_LAST_REBIND;
> > > -			if (err)
> > > +			if (IS_ERR(fence))
> > >  				break;
> > >  			op->remap.prev = NULL;
> > >  		}
> > >
> > >  		if (next) {
> > >  			op->remap.next->gpuva.flags |= XE_VMA_LAST_REBIND;
> > > -			err = xe_vm_bind(vm, op->remap.next, op->q,
> > > -					 xe_vma_bo(op->remap.next),
> > > -					 op->syncs, op->num_syncs,
> > > -					 true, false,
> > > -					 op->flags & XE_VMA_OP_LAST);
> > > +			dma_fence_put(fence);
> >
> >
> > Same comment as above
> 
> Same answer.
> 
> > > +			fence = xe_vm_bind(vm, op->remap.next, op->q,
> > > +					   xe_vma_bo(op->remap.next),
> > > +					   op->syncs, op->num_syncs,
> > > +					   true, false,
> > > +					   op->flags & XE_VMA_OP_LAST);
> > >  			op->remap.next->gpuva.flags &=
> > > ~XE_VMA_LAST_REBIND;
> > > -			if (err)
> > > +			if (IS_ERR(fence))
> > >  				break;
> > >  			op->remap.next = NULL;
> > >  		}
> > > @@ -2547,34 +2535,36 @@ static int op_execute(struct xe_vm *vm, struct
> > > xe_vma *vma,
> > >  		break;
> > >  	}
> > >  	case DRM_GPUVA_OP_UNMAP:
> > > -		err = xe_vm_unbind(vm, vma, op->q, op->syncs,
> > > -				   op->num_syncs, op->flags &
> > > XE_VMA_OP_FIRST,
> > > -				   op->flags & XE_VMA_OP_LAST);
> > > +		fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
> > > +				     op->num_syncs, op->flags &
> > > XE_VMA_OP_FIRST,
> > > +				     op->flags & XE_VMA_OP_LAST);
> > >  		break;
> > >  	case DRM_GPUVA_OP_PREFETCH:
> > > -		err = xe_vm_prefetch(vm, vma, op->q, op->prefetch.region,
> > > -				     op->syncs, op->num_syncs,
> > > -				     op->flags & XE_VMA_OP_FIRST,
> > > -				     op->flags & XE_VMA_OP_LAST);
> > > +		fence = xe_vm_prefetch(vm, vma, op->q, op->prefetch.region,
> > > +				       op->syncs, op->num_syncs,
> > > +				       op->flags & XE_VMA_OP_FIRST,
> > > +				       op->flags & XE_VMA_OP_LAST);
> > >  		break;
> > >  	default:
> > >  		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > >  	}
> > >
> > > -	if (err)
> > > +	if (IS_ERR(fence))
> > >  		trace_xe_vma_fail(vma);
> > >
> > > -	return err;
> > > +	return fence;
> > >  }
> > >
> > > -static int __xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > > -			       struct xe_vma_op *op)
> > > +static struct dma_fence *
> > > +__xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > > +		    struct xe_vma_op *op)
> > >  {
> > > +	struct dma_fence *fence;
> > >  	int err;
> > >
> > >  retry_userptr:
> > > -	err = op_execute(vm, vma, op);
> > > -	if (err == -EAGAIN) {
> > > +	fence = op_execute(vm, vma, op);
> > > +	if (IS_ERR(fence) && PTR_ERR(fence) == -EAGAIN) {
> > >  		lockdep_assert_held_write(&vm->lock);
> > >
> > >  		if (op->base.op == DRM_GPUVA_OP_REMAP) {
> > > @@ -2591,22 +2581,24 @@ static int __xe_vma_op_execute(struct xe_vm
> *vm,
> > > struct xe_vma *vma,
> > >  			if (!err)
> > >  				goto retry_userptr;
> > >
> > > +			fence = ERR_PTR(err);
> > >  			trace_xe_vma_fail(vma);
> > >  		}
> > >  	}
> > >
> > > -	return err;
> > > +	return fence;
> > >  }
> > >
> > > -static int xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
> > > +static struct dma_fence *
> > > +xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
> > >  {
> > > -	int ret = 0;
> > > +	struct dma_fence *fence = ERR_PTR(-ENOMEM);
> > >
> > >  	lockdep_assert_held_write(&vm->lock);
> > >
> > >  	switch (op->base.op) {
> > >  	case DRM_GPUVA_OP_MAP:
> > > -		ret = __xe_vma_op_execute(vm, op->map.vma, op);
> > > +		fence = __xe_vma_op_execute(vm, op->map.vma, op);
> > >  		break;
> > >  	case DRM_GPUVA_OP_REMAP:
> > >  	{
> > > @@ -2619,23 +2611,23 @@ static int xe_vma_op_execute(struct xe_vm *vm,
> > > struct xe_vma_op *op)
> > >  		else
> > >  			vma = op->remap.next;
> > >
> > > -		ret = __xe_vma_op_execute(vm, vma, op);
> > > +		fence = __xe_vma_op_execute(vm, vma, op);
> > >  		break;
> > >  	}
> > >  	case DRM_GPUVA_OP_UNMAP:
> > > -		ret = __xe_vma_op_execute(vm, gpuva_to_vma(op-
> > > >base.unmap.va),
> > > -					  op);
> > > +		fence = __xe_vma_op_execute(vm, gpuva_to_vma(op-
> > > >base.unmap.va),
> > > +					    op);
> > >  		break;
> > >  	case DRM_GPUVA_OP_PREFETCH:
> > > -		ret = __xe_vma_op_execute(vm,
> > > -					  gpuva_to_vma(op->base.prefetch.va),
> > > -					  op);
> > > +		fence = __xe_vma_op_execute(vm,
> > > +					    gpuva_to_vma(op->base.prefetch.va),
> > > +					    op);
> > >  		break;
> > >  	default:
> > >  		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > >  	}
> > >
> > > -	return ret;
> > > +	return fence;
> > >  }
> > >
> > >  static void xe_vma_op_cleanup(struct xe_vm *vm, struct xe_vma_op *op)
> > > @@ -2803,11 +2795,35 @@ static int vm_bind_ioctl_ops_lock(struct
> drm_exec
> > > *exec,
> > >  	return 0;
> > >  }
> > >
> > > +static struct dma_fence *ops_execute(struct xe_vm *vm,
> > > +				     struct list_head *ops_list,
> > > +				     bool cleanup)
> > > +{
> > > +	struct xe_vma_op *op, *next;
> > > +	struct dma_fence *fence = NULL;
> > > +
> > > +	list_for_each_entry_safe(op, next, ops_list, link) {
> > > +		if (!IS_ERR(fence)) {
> > > +			dma_fence_put(fence);
> > > +			fence = xe_vma_op_execute(vm, op);
> >
> > So you only return the fence of the last operation. In the later on codes, do you
> use fence to wait for *all* operations to finish?
> >
> 
> Same answer as above, all fences on exec_queue should be ordered.
> 
> > > +		}
> > > +		if (IS_ERR(fence)) {
> > > +			drm_warn(&vm->xe->drm, "VM op(%d) failed with %ld",
> > > +				 op->base.op, PTR_ERR(fence));
> > > +			fence = ERR_PTR(-ENOSPC);
> >
> > So even if there is error, you don't break the loop. Is it to perform the cleanup
> below?
> >
> > Once error happen for one operation, you seem to print the same error
> message for all the rest operations....because fence = xe_vma_op_execute(vm,
> op) is not called anymore after the first error
> >
> 
> Yes.

Is this problematic though? Lets say you have 2 ops in the list and op_execute failed with op1. You will print as below:

VM op1 failed with xxx
VM op1 failed with xxx


Oak

> 
> Matt
> 
> >
> > Oak
> >
> > > +		}
> > > +		if (cleanup)
> > > +			xe_vma_op_cleanup(vm, op);
> > > +	}
> > > +
> > > +	return fence;
> > > +}
> > > +
> > >  static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
> > >  				     struct list_head *ops_list)
> > >  {
> > >  	struct drm_exec exec;
> > > -	struct xe_vma_op *op, *next;
> > > +	struct dma_fence *fence;
> > >  	int err;
> > >
> > >  	lockdep_assert_held_write(&vm->lock);
> > > @@ -2820,19 +2836,14 @@ static int vm_bind_ioctl_ops_execute(struct
> xe_vm
> > > *vm,
> > >  		if (err)
> > >  			goto unlock;
> > >
> > > -		list_for_each_entry_safe(op, next, ops_list, link) {
> > > -			err = xe_vma_op_execute(vm, op);
> > > -			if (err) {
> > > -				drm_warn(&vm->xe->drm, "VM op(%d) failed
> > > with %d",
> > > -					 op->base.op, err);
> > > -				/*
> > > -				 * FIXME: Killing VM rather than proper error
> > > handling
> > > -				 */
> > > -				xe_vm_kill(vm, false);
> > > -				err = -ENOSPC;
> > > -				goto unlock;
> > > -			}
> > > -			xe_vma_op_cleanup(vm, op);
> > > +		fence = ops_execute(vm, ops_list, true);
> > > +		if (IS_ERR(fence)) {
> > > +			err = PTR_ERR(fence);
> > > +			/* FIXME: Killing VM rather than proper error handling */
> > > +			xe_vm_kill(vm, false);
> > > +			goto unlock;
> > > +		} else {
> > > +			dma_fence_put(fence);
> > >  		}
> > >  	}
> > >
> > > --
> > > 2.34.1
> >

^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 03/30] drm/xe: Move migrate to prefetch to op_lock function
  2024-03-22 17:36     ` Matthew Brost
@ 2024-03-22 19:45       ` Zeng, Oak
  0 siblings, 0 replies; 76+ messages in thread
From: Zeng, Oak @ 2024-03-22 19:45 UTC (permalink / raw)
  To: Brost, Matthew; +Cc: intel-xe



> -----Original Message-----
> From: Brost, Matthew <matthew.brost@intel.com>
> Sent: Friday, March 22, 2024 1:36 PM
> To: Zeng, Oak <oak.zeng@intel.com>
> Cc: intel-xe@lists.freedesktop.org
> Subject: Re: [PATCH v4 03/30] drm/xe: Move migrate to prefetch to op_lock
> function
> 
> On Fri, Mar 22, 2024 at 11:06:28AM -0600, Zeng, Oak wrote:
> >
> >
> > > -----Original Message-----
> > > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of
> Matthew
> > > Brost
> > > Sent: Friday, March 8, 2024 12:08 AM
> > > To: intel-xe@lists.freedesktop.org
> > > Cc: Brost, Matthew <matthew.brost@intel.com>
> > > Subject: [PATCH v4 03/30] drm/xe: Move migrate to prefetch to op_lock
> function
> > >
> > > Migrates need to be done under drm exec to make lockdep happy,
> >
> >
> > Can you explain more here? By under drm exec, do you mean
> drm_exec_until_all_locked? I do see xe_vm_prefetch/xe_bo_migrate is called
> inside drm_exec_until_all_locked, in patch 1 of this series, in function
> vm_bind_ioctl_ops_execute
> >
> 
> This is a stale comment, will fix. Something like:
> 
> All non-binding operations in VM bind IOCTL should be in the lock and
> prepare step rather than the execution step. Move prefetch to conform to
> this pattern.


Have you ever think removing the prefetch API from vm_bind?

One idea is move prefetch to the memory attributes (aka madvise) API we are building for system allocator. From the semantics of prefetch, it is more reasonable to make it part of madvise, vs vm_bind. What do you think?

> 
> >  move
> > > the migrate done for prefetches under the op_lock function.
> > >
> > > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > > ---
> > >  drivers/gpu/drm/xe/xe_vm.c | 28 +++++++++++++---------------
> > >  1 file changed, 13 insertions(+), 15 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > > index fb73afcab3b7..70a5ba621e4e 100644
> > > --- a/drivers/gpu/drm/xe/xe_vm.c
> > > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > > @@ -1994,20 +1994,10 @@ static const u32 region_to_mem_type[] = {
> > >
> > >  static struct dma_fence *
> > >  xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
> > > -	       struct xe_exec_queue *q, u32 region,
> > > -	       struct xe_sync_entry *syncs, u32 num_syncs,
> > > -	       bool first_op, bool last_op)
> > > +	       struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> > > +	       u32 num_syncs, bool first_op, bool last_op)
> > >  {
> > >  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > > q);
> > > -	int err;
> > > -
> > > -	xe_assert(vm->xe, region <= ARRAY_SIZE(region_to_mem_type));
> > > -
> > > -	if (!xe_vma_has_no_bo(vma)) {
> > > -		err = xe_bo_migrate(xe_vma_bo(vma),
> > > region_to_mem_type[region]);
> > > -		if (err)
> > > -			return ERR_PTR(err);
> > > -	}
> > >
> > >  	if (vma->tile_mask != (vma->tile_present & ~vma->usm.tile_invalidated))
> > > {
> > >  		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs,
> > > num_syncs,
> > > @@ -2540,8 +2530,7 @@ static struct dma_fence *op_execute(struct xe_vm
> > > *vm, struct xe_vma *vma,
> > >  				     op->flags & XE_VMA_OP_LAST);
> > >  		break;
> > >  	case DRM_GPUVA_OP_PREFETCH:
> > > -		fence = xe_vm_prefetch(vm, vma, op->q, op->prefetch.region,
> > > -				       op->syncs, op->num_syncs,
> > > +		fence = xe_vm_prefetch(vm, vma, op->q, op->syncs, op-
> > > >num_syncs,
> > >  				       op->flags & XE_VMA_OP_FIRST,
> > >  				       op->flags & XE_VMA_OP_LAST);
> > >  		break;
> > > @@ -2766,8 +2755,17 @@ static int op_lock(struct drm_exec *exec, struct
> xe_vm
> > > *vm,
> > >  		err = vma_lock(exec, gpuva_to_vma(op->base.unmap.va), false);
> > >  		break;
> > >  	case DRM_GPUVA_OP_PREFETCH:
> > > -		err = vma_lock(exec, gpuva_to_vma(op->base.prefetch.va),
> > > true);
> > > +	{
> > > +		struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va);
> > > +		u32 region = op->prefetch.region;
> > > +
> > > +		xe_assert(vm->xe, region <=
> > > ARRAY_SIZE(region_to_mem_type));
> > > +
> > > +		err = vma_lock(exec, vma, false);
> > > +		if (!err && !xe_vma_has_no_bo(vma))
> > > +			err = xe_bo_migrate(xe_vma_bo(vma), region);
> > >  		break;
> > > +	}
> >
> > Understand you have a reason to do this. It does introduce confusion: the
> function is called op_lock and now you have a migration operation inside.
> >
> 
> Yes, how about? s/op_lock/op_lock_and_prepare/
> 
> Likewise: s/vma_lock/vma_lock/vma_lock_and_validate/

Yes, that looks better.

Oak
> 
> Matt
> 
> >
> > Oak
> >
> >
> > >  	default:
> > >  		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > >  	}
> > > --
> > > 2.34.1
> >

^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 05/30] drm/xe: Update xe_vm_rebind to use dummy VMA operations
  2024-03-08  5:07 ` [PATCH v4 05/30] drm/xe: Update xe_vm_rebind to use dummy VMA operations Matthew Brost
@ 2024-03-22 21:23   ` Zeng, Oak
  2024-03-22 22:51     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-22 21:23 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew



> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 05/30] drm/xe: Update xe_vm_rebind to use dummy VMA
> operations
> 
> All bind interfaces are transitioning to use VMA ops, update
> xe_vm_rebind to use VMA ops.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm.c       |  47 +++++---
>  drivers/gpu/drm/xe/xe_vm_types.h | 189 ++++++++++++++++---------------
>  2 files changed, 132 insertions(+), 104 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index e342af6b51b1..0bb807c05d7b 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -755,10 +755,22 @@ int xe_vm_userptr_check_repin(struct xe_vm *vm)
>  		list_empty_careful(&vm->userptr.invalidated)) ? 0 : -EAGAIN;
>  }
> 
> -static struct dma_fence *
> -xe_vm_bind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
> -	       struct xe_sync_entry *syncs, u32 num_syncs,
> -	       bool first_op, bool last_op);
> +static void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma
> *vma)
> +{
> +	vm->dummy_ops.op.base.op = DRM_GPUVA_OP_MAP;
> +	vm->dummy_ops.op.base.map.va.addr = vma->gpuva.va.addr;
> +	vm->dummy_ops.op.base.map.va.range = vma->gpuva.va.range;
> +	vm->dummy_ops.op.base.map.gem.obj = vma->gpuva.gem.obj;
> +	vm->dummy_ops.op.base.map.gem.offset = vma->gpuva.gem.offset;
> +	vm->dummy_ops.op.map.vma = vma;
> +	vm->dummy_ops.op.map.immediate = true;
> +	vm->dummy_ops.op.map.dumpable = vma->gpuva.flags &
> XE_VMA_DUMPABLE;
> +	vm->dummy_ops.op.map.is_null = xe_vma_is_null(vma);
> +}
> +
> +static struct dma_fence *ops_execute(struct xe_vm *vm,
> +				     struct xe_vma_ops *vops,
> +				     bool cleanup);
> 
>  struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
>  {
> @@ -780,7 +792,9 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm,
> bool rebind_worker)
>  			trace_xe_vma_rebind_worker(vma);
>  		else
>  			trace_xe_vma_rebind_exec(vma);
> -		fence = xe_vm_bind_vma(vma, NULL, NULL, 0, false, false);
> +
> +		xe_vm_populate_dummy_rebind(vm, vma);
> +		fence = ops_execute(vm, &vm->dummy_ops.vops, false);
>  		if (IS_ERR(fence))
>  			return fence;
>  	}
> @@ -1289,6 +1303,11 @@ static void xe_vm_free_scratch(struct xe_vm *vm)
>  	}
>  }
> 
> +static void xe_vma_ops_init(struct xe_vma_ops *vops)
> +{
> +	INIT_LIST_HEAD(&vops->list);
> +}

this already showed up on patch 4... you just add it in patch5, then moved it to another location on patch 5...

can this be better organized?


> +
>  struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
>  {
>  	struct drm_gem_object *vm_resv_obj;
> @@ -1310,6 +1329,10 @@ struct xe_vm *xe_vm_create(struct xe_device *xe,
> u32 flags)
>  	init_rwsem(&vm->lock);
>  	mutex_init(&vm->snap_mutex);
> 
> +	xe_vma_ops_init(&vm->dummy_ops.vops);
> +	INIT_LIST_HEAD(&vm->dummy_ops.op.link);
> +	list_add(&vm->dummy_ops.op.link, &vm->dummy_ops.vops.list);
> +
>  	INIT_LIST_HEAD(&vm->rebind_list);
> 
>  	INIT_LIST_HEAD(&vm->userptr.repin_list);
> @@ -2140,6 +2163,7 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct
> xe_bo *bo,
>  		struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
> 
>  		if (__op->op == DRM_GPUVA_OP_MAP) {
> +			op->map.immediate = !xe_vm_in_fault_mode(vm);
>  			op->map.is_null = flags &
> DRM_XE_VM_BIND_FLAG_NULL;
>  			op->map.dumpable = flags &
> DRM_XE_VM_BIND_FLAG_DUMPABLE;
>  			op->map.pat_index = pat_index;
> @@ -2465,7 +2489,7 @@ static struct dma_fence *op_execute(struct xe_vm
> *vm, struct xe_vma *vma,
>  {
>  	struct dma_fence *fence = NULL;
> 
> -	lockdep_assert_held_write(&vm->lock);
> +	lockdep_assert_held(&vm->lock);
>  	xe_vm_assert_held(vm);
>  	xe_bo_assert_held(xe_vma_bo(vma));
> 
> @@ -2473,7 +2497,7 @@ static struct dma_fence *op_execute(struct xe_vm
> *vm, struct xe_vma *vma,
>  	case DRM_GPUVA_OP_MAP:
>  		fence = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
>  				   op->syncs, op->num_syncs,
> -				   !xe_vm_in_fault_mode(vm),
> +				   op->map.immediate,
>  				   op->flags & XE_VMA_OP_FIRST,
>  				   op->flags & XE_VMA_OP_LAST);
>  		break;
> @@ -2554,7 +2578,7 @@ __xe_vma_op_execute(struct xe_vm *vm, struct
> xe_vma *vma,
>  retry_userptr:
>  	fence = op_execute(vm, vma, op);
>  	if (IS_ERR(fence) && PTR_ERR(fence) == -EAGAIN) {
> -		lockdep_assert_held_write(&vm->lock);
> +		lockdep_assert_held(&vm->lock);
> 
>  		if (op->base.op == DRM_GPUVA_OP_REMAP) {
>  			if (!op->remap.unmap_done)
> @@ -2583,7 +2607,7 @@ xe_vma_op_execute(struct xe_vm *vm, struct
> xe_vma_op *op)
>  {
>  	struct dma_fence *fence = ERR_PTR(-ENOMEM);
> 
> -	lockdep_assert_held_write(&vm->lock);
> +	lockdep_assert_held(&vm->lock);
> 
>  	switch (op->base.op) {
>  	case DRM_GPUVA_OP_MAP:
> @@ -2992,11 +3016,6 @@ static int vm_bind_ioctl_signal_fences(struct xe_vm
> *vm,
>  	return err;
>  }
> 
> -static void xe_vma_ops_init(struct xe_vma_ops *vops)
> -{
> -	INIT_LIST_HEAD(&vops->list);
> -}
> -
>  int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
>  {
>  	struct xe_device *xe = to_xe_device(dev);
> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> b/drivers/gpu/drm/xe/xe_vm_types.h
> index cc3dce893f1e..7ef9e632154a 100644
> --- a/drivers/gpu/drm/xe/xe_vm_types.h
> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> @@ -18,6 +18,7 @@
>  #include "xe_range_fence.h"
> 
>  struct xe_bo;
> +struct xe_device;
>  struct xe_sync_entry;
>  struct xe_user_fence;
>  struct xe_vm;
> @@ -124,7 +125,96 @@ struct xe_userptr_vma {
>  	struct xe_userptr userptr;
>  };
> 
> -struct xe_device;
> +/** struct xe_vma_op_map - VMA map operation */
> +struct xe_vma_op_map {
> +	/** @vma: VMA to map */
> +	struct xe_vma *vma;
> +	/** @immediate: Immediate bind */
> +	bool immediate;
> +	/** @is_null: is NULL binding */
> +	bool is_null;
> +	/** @dumpable: whether BO is dumped on GPU hang */
> +	bool dumpable;
> +	/** @pat_index: The pat index to use for this operation. */
> +	u16 pat_index;
> +};
> +
> +/** struct xe_vma_op_remap - VMA remap operation */
> +struct xe_vma_op_remap {
> +	/** @prev: VMA preceding part of a split mapping */
> +	struct xe_vma *prev;
> +	/** @next: VMA subsequent part of a split mapping */
> +	struct xe_vma *next;
> +	/** @start: start of the VMA unmap */
> +	u64 start;
> +	/** @range: range of the VMA unmap */
> +	u64 range;
> +	/** @skip_prev: skip prev rebind */
> +	bool skip_prev;
> +	/** @skip_next: skip next rebind */
> +	bool skip_next;
> +	/** @unmap_done: unmap operation in done */
> +	bool unmap_done;
> +};
> +
> +/** struct xe_vma_op_prefetch - VMA prefetch operation */
> +struct xe_vma_op_prefetch {
> +	/** @region: memory region to prefetch to */
> +	u32 region;
> +};
> +
> +/** enum xe_vma_op_flags - flags for VMA operation */
> +enum xe_vma_op_flags {
> +	/** @XE_VMA_OP_FIRST: first VMA operation for a set of syncs */
> +	XE_VMA_OP_FIRST			= BIT(0),
> +	/** @XE_VMA_OP_LAST: last VMA operation for a set of syncs */
> +	XE_VMA_OP_LAST			= BIT(1),
> +	/** @XE_VMA_OP_COMMITTED: VMA operation committed */
> +	XE_VMA_OP_COMMITTED		= BIT(2),
> +	/** @XE_VMA_OP_PREV_COMMITTED: Previous VMA operation
> committed */
> +	XE_VMA_OP_PREV_COMMITTED	= BIT(3),
> +	/** @XE_VMA_OP_NEXT_COMMITTED: Next VMA operation committed
> */
> +	XE_VMA_OP_NEXT_COMMITTED	= BIT(4),
> +};
> +
> +/** struct xe_vma_op - VMA operation */
> +struct xe_vma_op {
> +	/** @base: GPUVA base operation */
> +	struct drm_gpuva_op base;
> +	/**
> +	 * @ops: GPUVA ops, when set call drm_gpuva_ops_free after this
> +	 * operations is processed
> +	 */
> +	struct drm_gpuva_ops *ops;
> +	/** @q: exec queue for this operation */
> +	struct xe_exec_queue *q;
> +	/**
> +	 * @syncs: syncs for this operation, only used on first and last
> +	 * operation
> +	 */
> +	struct xe_sync_entry *syncs;
> +	/** @num_syncs: number of syncs */
> +	u32 num_syncs;
> +	/** @link: async operation link */
> +	struct list_head link;
> +	/** @flags: operation flags */
> +	enum xe_vma_op_flags flags;
> +
> +	union {
> +		/** @map: VMA map operation specific data */
> +		struct xe_vma_op_map map;
> +		/** @remap: VMA remap operation specific data */
> +		struct xe_vma_op_remap remap;
> +		/** @prefetch: VMA prefetch operation specific data */
> +		struct xe_vma_op_prefetch prefetch;
> +	};
> +};
> +
> +/** struct xe_vma_ops - VMA operations */
> +struct xe_vma_ops {
> +	/** @list: list of VMA operations */
> +	struct list_head list;
> +};

this already showed up on patch 4... you just add it in patch5, then moved it to another location on patch 5...

> 
>  struct xe_vm {
>  	/** @gpuvm: base GPUVM used to track VMAs */
> @@ -267,99 +357,18 @@ struct xe_vm {
>  		bool capture_once;
>  	} error_capture;
> 
> +	/** @dummy_ops: dummy VMA ops to issue rebinds */
> +	struct {
> +		/** @dummy_ops.ops: dummy VMA ops */
> +		struct xe_vma_ops vops;
> +		/** @dummy_ops.op: dummy VMA op */
> +		struct xe_vma_op op;
> +	} dummy_ops;

If only from this patch, it seems you don't have to introduce this dummy_ops member to xe_vm. For example, it can be a local variable in xe_vm_rebind function. But I will keep looking. Maybe you made it this way for future patches.


> +
>  	/** @batch_invalidate_tlb: Always invalidate TLB before batch start */
>  	bool batch_invalidate_tlb;
>  	/** @xef: XE file handle for tracking this VM's drm client */
>  	struct xe_file *xef;
>  };
> 
> -/** struct xe_vma_op_map - VMA map operation */
> -struct xe_vma_op_map {
> -	/** @vma: VMA to map */
> -	struct xe_vma *vma;
> -	/** @is_null: is NULL binding */
> -	bool is_null;
> -	/** @dumpable: whether BO is dumped on GPU hang */
> -	bool dumpable;
> -	/** @pat_index: The pat index to use for this operation. */
> -	u16 pat_index;
> -};
> -
> -/** struct xe_vma_op_remap - VMA remap operation */
> -struct xe_vma_op_remap {
> -	/** @prev: VMA preceding part of a split mapping */
> -	struct xe_vma *prev;
> -	/** @next: VMA subsequent part of a split mapping */
> -	struct xe_vma *next;
> -	/** @start: start of the VMA unmap */
> -	u64 start;
> -	/** @range: range of the VMA unmap */
> -	u64 range;
> -	/** @skip_prev: skip prev rebind */
> -	bool skip_prev;
> -	/** @skip_next: skip next rebind */
> -	bool skip_next;
> -	/** @unmap_done: unmap operation in done */
> -	bool unmap_done;
> -};
> -
> -/** struct xe_vma_op_prefetch - VMA prefetch operation */
> -struct xe_vma_op_prefetch {
> -	/** @region: memory region to prefetch to */
> -	u32 region;
> -};
> -
> -/** enum xe_vma_op_flags - flags for VMA operation */
> -enum xe_vma_op_flags {
> -	/** @XE_VMA_OP_FIRST: first VMA operation for a set of syncs */
> -	XE_VMA_OP_FIRST			= BIT(0),
> -	/** @XE_VMA_OP_LAST: last VMA operation for a set of syncs */
> -	XE_VMA_OP_LAST			= BIT(1),
> -	/** @XE_VMA_OP_COMMITTED: VMA operation committed */
> -	XE_VMA_OP_COMMITTED		= BIT(2),
> -	/** @XE_VMA_OP_PREV_COMMITTED: Previous VMA operation
> committed */
> -	XE_VMA_OP_PREV_COMMITTED	= BIT(3),
> -	/** @XE_VMA_OP_NEXT_COMMITTED: Next VMA operation committed
> */
> -	XE_VMA_OP_NEXT_COMMITTED	= BIT(4),
> -};
> -
> -/** struct xe_vma_op - VMA operation */
> -struct xe_vma_op {
> -	/** @base: GPUVA base operation */
> -	struct drm_gpuva_op base;
> -	/**
> -	 * @ops: GPUVA ops, when set call drm_gpuva_ops_free after this
> -	 * operations is processed
> -	 */
> -	struct drm_gpuva_ops *ops;
> -	/** @q: exec queue for this operation */
> -	struct xe_exec_queue *q;
> -	/**
> -	 * @syncs: syncs for this operation, only used on first and last
> -	 * operation
> -	 */
> -	struct xe_sync_entry *syncs;
> -	/** @num_syncs: number of syncs */
> -	u32 num_syncs;
> -	/** @link: async operation link */
> -	struct list_head link;
> -	/** @flags: operation flags */
> -	enum xe_vma_op_flags flags;
> -
> -	union {
> -		/** @map: VMA map operation specific data */
> -		struct xe_vma_op_map map;
> -		/** @remap: VMA remap operation specific data */
> -		struct xe_vma_op_remap remap;
> -		/** @prefetch: VMA prefetch operation specific data */
> -		struct xe_vma_op_prefetch prefetch;
> -	};
> -};
> -
> -/** struct xe_vma_ops - VMA operations */
> -struct xe_vma_ops {
> -	/** @list: list of VMA operations */
> -	struct list_head list;
> -};

It seems you moved a block of codes to another location. It caused more work for code review. Better to avoid this if we can.

Oak

> -
>  #endif
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 05/30] drm/xe: Update xe_vm_rebind to use dummy VMA operations
  2024-03-22 21:23   ` Zeng, Oak
@ 2024-03-22 22:51     ` Matthew Brost
  0 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-22 22:51 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Fri, Mar 22, 2024 at 03:23:08PM -0600, Zeng, Oak wrote:
> 
> 
> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 05/30] drm/xe: Update xe_vm_rebind to use dummy VMA
> > operations
> > 
> > All bind interfaces are transitioning to use VMA ops, update
> > xe_vm_rebind to use VMA ops.
> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_vm.c       |  47 +++++---
> >  drivers/gpu/drm/xe/xe_vm_types.h | 189 ++++++++++++++++---------------
> >  2 files changed, 132 insertions(+), 104 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index e342af6b51b1..0bb807c05d7b 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -755,10 +755,22 @@ int xe_vm_userptr_check_repin(struct xe_vm *vm)
> >  		list_empty_careful(&vm->userptr.invalidated)) ? 0 : -EAGAIN;
> >  }
> > 
> > -static struct dma_fence *
> > -xe_vm_bind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
> > -	       struct xe_sync_entry *syncs, u32 num_syncs,
> > -	       bool first_op, bool last_op);
> > +static void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma
> > *vma)
> > +{
> > +	vm->dummy_ops.op.base.op = DRM_GPUVA_OP_MAP;
> > +	vm->dummy_ops.op.base.map.va.addr = vma->gpuva.va.addr;
> > +	vm->dummy_ops.op.base.map.va.range = vma->gpuva.va.range;
> > +	vm->dummy_ops.op.base.map.gem.obj = vma->gpuva.gem.obj;
> > +	vm->dummy_ops.op.base.map.gem.offset = vma->gpuva.gem.offset;
> > +	vm->dummy_ops.op.map.vma = vma;
> > +	vm->dummy_ops.op.map.immediate = true;
> > +	vm->dummy_ops.op.map.dumpable = vma->gpuva.flags &
> > XE_VMA_DUMPABLE;
> > +	vm->dummy_ops.op.map.is_null = xe_vma_is_null(vma);
> > +}
> > +
> > +static struct dma_fence *ops_execute(struct xe_vm *vm,
> > +				     struct xe_vma_ops *vops,
> > +				     bool cleanup);
> > 
> >  struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
> >  {
> > @@ -780,7 +792,9 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm,
> > bool rebind_worker)
> >  			trace_xe_vma_rebind_worker(vma);
> >  		else
> >  			trace_xe_vma_rebind_exec(vma);
> > -		fence = xe_vm_bind_vma(vma, NULL, NULL, 0, false, false);
> > +
> > +		xe_vm_populate_dummy_rebind(vm, vma);
> > +		fence = ops_execute(vm, &vm->dummy_ops.vops, false);
> >  		if (IS_ERR(fence))
> >  			return fence;
> >  	}
> > @@ -1289,6 +1303,11 @@ static void xe_vm_free_scratch(struct xe_vm *vm)
> >  	}
> >  }
> > 
> > +static void xe_vma_ops_init(struct xe_vma_ops *vops)
> > +{
> > +	INIT_LIST_HEAD(&vops->list);
> > +}
> 
> this already showed up on patch 4... you just add it in patch5, then moved it to another location on patch 5...
> 
> can this be better organized?
> 

Yes.

> 
> > +
> >  struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
> >  {
> >  	struct drm_gem_object *vm_resv_obj;
> > @@ -1310,6 +1329,10 @@ struct xe_vm *xe_vm_create(struct xe_device *xe,
> > u32 flags)
> >  	init_rwsem(&vm->lock);
> >  	mutex_init(&vm->snap_mutex);
> > 
> > +	xe_vma_ops_init(&vm->dummy_ops.vops);
> > +	INIT_LIST_HEAD(&vm->dummy_ops.op.link);
> > +	list_add(&vm->dummy_ops.op.link, &vm->dummy_ops.vops.list);
> > +
> >  	INIT_LIST_HEAD(&vm->rebind_list);
> > 
> >  	INIT_LIST_HEAD(&vm->userptr.repin_list);
> > @@ -2140,6 +2163,7 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct
> > xe_bo *bo,
> >  		struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
> > 
> >  		if (__op->op == DRM_GPUVA_OP_MAP) {
> > +			op->map.immediate = !xe_vm_in_fault_mode(vm);
> >  			op->map.is_null = flags &
> > DRM_XE_VM_BIND_FLAG_NULL;
> >  			op->map.dumpable = flags &
> > DRM_XE_VM_BIND_FLAG_DUMPABLE;
> >  			op->map.pat_index = pat_index;
> > @@ -2465,7 +2489,7 @@ static struct dma_fence *op_execute(struct xe_vm
> > *vm, struct xe_vma *vma,
> >  {
> >  	struct dma_fence *fence = NULL;
> > 
> > -	lockdep_assert_held_write(&vm->lock);
> > +	lockdep_assert_held(&vm->lock);
> >  	xe_vm_assert_held(vm);
> >  	xe_bo_assert_held(xe_vma_bo(vma));
> > 
> > @@ -2473,7 +2497,7 @@ static struct dma_fence *op_execute(struct xe_vm
> > *vm, struct xe_vma *vma,
> >  	case DRM_GPUVA_OP_MAP:
> >  		fence = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
> >  				   op->syncs, op->num_syncs,
> > -				   !xe_vm_in_fault_mode(vm),
> > +				   op->map.immediate,
> >  				   op->flags & XE_VMA_OP_FIRST,
> >  				   op->flags & XE_VMA_OP_LAST);
> >  		break;
> > @@ -2554,7 +2578,7 @@ __xe_vma_op_execute(struct xe_vm *vm, struct
> > xe_vma *vma,
> >  retry_userptr:
> >  	fence = op_execute(vm, vma, op);
> >  	if (IS_ERR(fence) && PTR_ERR(fence) == -EAGAIN) {
> > -		lockdep_assert_held_write(&vm->lock);
> > +		lockdep_assert_held(&vm->lock);
> > 
> >  		if (op->base.op == DRM_GPUVA_OP_REMAP) {
> >  			if (!op->remap.unmap_done)
> > @@ -2583,7 +2607,7 @@ xe_vma_op_execute(struct xe_vm *vm, struct
> > xe_vma_op *op)
> >  {
> >  	struct dma_fence *fence = ERR_PTR(-ENOMEM);
> > 
> > -	lockdep_assert_held_write(&vm->lock);
> > +	lockdep_assert_held(&vm->lock);
> > 
> >  	switch (op->base.op) {
> >  	case DRM_GPUVA_OP_MAP:
> > @@ -2992,11 +3016,6 @@ static int vm_bind_ioctl_signal_fences(struct xe_vm
> > *vm,
> >  	return err;
> >  }
> > 
> > -static void xe_vma_ops_init(struct xe_vma_ops *vops)
> > -{
> > -	INIT_LIST_HEAD(&vops->list);
> > -}
> > -
> >  int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
> >  {
> >  	struct xe_device *xe = to_xe_device(dev);
> > diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> > b/drivers/gpu/drm/xe/xe_vm_types.h
> > index cc3dce893f1e..7ef9e632154a 100644
> > --- a/drivers/gpu/drm/xe/xe_vm_types.h
> > +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> > @@ -18,6 +18,7 @@
> >  #include "xe_range_fence.h"
> > 
> >  struct xe_bo;
> > +struct xe_device;
> >  struct xe_sync_entry;
> >  struct xe_user_fence;
> >  struct xe_vm;
> > @@ -124,7 +125,96 @@ struct xe_userptr_vma {
> >  	struct xe_userptr userptr;
> >  };
> > 
> > -struct xe_device;
> > +/** struct xe_vma_op_map - VMA map operation */
> > +struct xe_vma_op_map {
> > +	/** @vma: VMA to map */
> > +	struct xe_vma *vma;
> > +	/** @immediate: Immediate bind */
> > +	bool immediate;
> > +	/** @is_null: is NULL binding */
> > +	bool is_null;
> > +	/** @dumpable: whether BO is dumped on GPU hang */
> > +	bool dumpable;
> > +	/** @pat_index: The pat index to use for this operation. */
> > +	u16 pat_index;
> > +};
> > +
> > +/** struct xe_vma_op_remap - VMA remap operation */
> > +struct xe_vma_op_remap {
> > +	/** @prev: VMA preceding part of a split mapping */
> > +	struct xe_vma *prev;
> > +	/** @next: VMA subsequent part of a split mapping */
> > +	struct xe_vma *next;
> > +	/** @start: start of the VMA unmap */
> > +	u64 start;
> > +	/** @range: range of the VMA unmap */
> > +	u64 range;
> > +	/** @skip_prev: skip prev rebind */
> > +	bool skip_prev;
> > +	/** @skip_next: skip next rebind */
> > +	bool skip_next;
> > +	/** @unmap_done: unmap operation in done */
> > +	bool unmap_done;
> > +};
> > +
> > +/** struct xe_vma_op_prefetch - VMA prefetch operation */
> > +struct xe_vma_op_prefetch {
> > +	/** @region: memory region to prefetch to */
> > +	u32 region;
> > +};
> > +
> > +/** enum xe_vma_op_flags - flags for VMA operation */
> > +enum xe_vma_op_flags {
> > +	/** @XE_VMA_OP_FIRST: first VMA operation for a set of syncs */
> > +	XE_VMA_OP_FIRST			= BIT(0),
> > +	/** @XE_VMA_OP_LAST: last VMA operation for a set of syncs */
> > +	XE_VMA_OP_LAST			= BIT(1),
> > +	/** @XE_VMA_OP_COMMITTED: VMA operation committed */
> > +	XE_VMA_OP_COMMITTED		= BIT(2),
> > +	/** @XE_VMA_OP_PREV_COMMITTED: Previous VMA operation
> > committed */
> > +	XE_VMA_OP_PREV_COMMITTED	= BIT(3),
> > +	/** @XE_VMA_OP_NEXT_COMMITTED: Next VMA operation committed
> > */
> > +	XE_VMA_OP_NEXT_COMMITTED	= BIT(4),
> > +};
> > +
> > +/** struct xe_vma_op - VMA operation */
> > +struct xe_vma_op {
> > +	/** @base: GPUVA base operation */
> > +	struct drm_gpuva_op base;
> > +	/**
> > +	 * @ops: GPUVA ops, when set call drm_gpuva_ops_free after this
> > +	 * operations is processed
> > +	 */
> > +	struct drm_gpuva_ops *ops;
> > +	/** @q: exec queue for this operation */
> > +	struct xe_exec_queue *q;
> > +	/**
> > +	 * @syncs: syncs for this operation, only used on first and last
> > +	 * operation
> > +	 */
> > +	struct xe_sync_entry *syncs;
> > +	/** @num_syncs: number of syncs */
> > +	u32 num_syncs;
> > +	/** @link: async operation link */
> > +	struct list_head link;
> > +	/** @flags: operation flags */
> > +	enum xe_vma_op_flags flags;
> > +
> > +	union {
> > +		/** @map: VMA map operation specific data */
> > +		struct xe_vma_op_map map;
> > +		/** @remap: VMA remap operation specific data */
> > +		struct xe_vma_op_remap remap;
> > +		/** @prefetch: VMA prefetch operation specific data */
> > +		struct xe_vma_op_prefetch prefetch;
> > +	};
> > +};
> > +
> > +/** struct xe_vma_ops - VMA operations */
> > +struct xe_vma_ops {
> > +	/** @list: list of VMA operations */
> > +	struct list_head list;
> > +};
> 
> this already showed up on patch 4... you just add it in patch5, then moved it to another location on patch 5...
> 

Yes.

> > 
> >  struct xe_vm {
> >  	/** @gpuvm: base GPUVM used to track VMAs */
> > @@ -267,99 +357,18 @@ struct xe_vm {
> >  		bool capture_once;
> >  	} error_capture;
> > 
> > +	/** @dummy_ops: dummy VMA ops to issue rebinds */
> > +	struct {
> > +		/** @dummy_ops.ops: dummy VMA ops */
> > +		struct xe_vma_ops vops;
> > +		/** @dummy_ops.op: dummy VMA op */
> > +		struct xe_vma_op op;
> > +	} dummy_ops;
> 
> If only from this patch, it seems you don't have to introduce this dummy_ops member to xe_vm. For example, it can be a local variable in xe_vm_rebind function. But I will keep looking. Maybe you made it this way for future patches.
> 
>

I'm going to rewrite or already have rewritten this to use local
xe_vm_ops member and execute all rebinds an atomic unit.

You can ignore this patch and also [1] in this rev of the review.

[1] https://patchwork.freedesktop.org/patch/582015/?series=125608&rev=5

> > +
> >  	/** @batch_invalidate_tlb: Always invalidate TLB before batch start */
> >  	bool batch_invalidate_tlb;
> >  	/** @xef: XE file handle for tracking this VM's drm client */
> >  	struct xe_file *xef;
> >  };
> > 
> > -/** struct xe_vma_op_map - VMA map operation */
> > -struct xe_vma_op_map {
> > -	/** @vma: VMA to map */
> > -	struct xe_vma *vma;
> > -	/** @is_null: is NULL binding */
> > -	bool is_null;
> > -	/** @dumpable: whether BO is dumped on GPU hang */
> > -	bool dumpable;
> > -	/** @pat_index: The pat index to use for this operation. */
> > -	u16 pat_index;
> > -};
> > -
> > -/** struct xe_vma_op_remap - VMA remap operation */
> > -struct xe_vma_op_remap {
> > -	/** @prev: VMA preceding part of a split mapping */
> > -	struct xe_vma *prev;
> > -	/** @next: VMA subsequent part of a split mapping */
> > -	struct xe_vma *next;
> > -	/** @start: start of the VMA unmap */
> > -	u64 start;
> > -	/** @range: range of the VMA unmap */
> > -	u64 range;
> > -	/** @skip_prev: skip prev rebind */
> > -	bool skip_prev;
> > -	/** @skip_next: skip next rebind */
> > -	bool skip_next;
> > -	/** @unmap_done: unmap operation in done */
> > -	bool unmap_done;
> > -};
> > -
> > -/** struct xe_vma_op_prefetch - VMA prefetch operation */
> > -struct xe_vma_op_prefetch {
> > -	/** @region: memory region to prefetch to */
> > -	u32 region;
> > -};
> > -
> > -/** enum xe_vma_op_flags - flags for VMA operation */
> > -enum xe_vma_op_flags {
> > -	/** @XE_VMA_OP_FIRST: first VMA operation for a set of syncs */
> > -	XE_VMA_OP_FIRST			= BIT(0),
> > -	/** @XE_VMA_OP_LAST: last VMA operation for a set of syncs */
> > -	XE_VMA_OP_LAST			= BIT(1),
> > -	/** @XE_VMA_OP_COMMITTED: VMA operation committed */
> > -	XE_VMA_OP_COMMITTED		= BIT(2),
> > -	/** @XE_VMA_OP_PREV_COMMITTED: Previous VMA operation
> > committed */
> > -	XE_VMA_OP_PREV_COMMITTED	= BIT(3),
> > -	/** @XE_VMA_OP_NEXT_COMMITTED: Next VMA operation committed
> > */
> > -	XE_VMA_OP_NEXT_COMMITTED	= BIT(4),
> > -};
> > -
> > -/** struct xe_vma_op - VMA operation */
> > -struct xe_vma_op {
> > -	/** @base: GPUVA base operation */
> > -	struct drm_gpuva_op base;
> > -	/**
> > -	 * @ops: GPUVA ops, when set call drm_gpuva_ops_free after this
> > -	 * operations is processed
> > -	 */
> > -	struct drm_gpuva_ops *ops;
> > -	/** @q: exec queue for this operation */
> > -	struct xe_exec_queue *q;
> > -	/**
> > -	 * @syncs: syncs for this operation, only used on first and last
> > -	 * operation
> > -	 */
> > -	struct xe_sync_entry *syncs;
> > -	/** @num_syncs: number of syncs */
> > -	u32 num_syncs;
> > -	/** @link: async operation link */
> > -	struct list_head link;
> > -	/** @flags: operation flags */
> > -	enum xe_vma_op_flags flags;
> > -
> > -	union {
> > -		/** @map: VMA map operation specific data */
> > -		struct xe_vma_op_map map;
> > -		/** @remap: VMA remap operation specific data */
> > -		struct xe_vma_op_remap remap;
> > -		/** @prefetch: VMA prefetch operation specific data */
> > -		struct xe_vma_op_prefetch prefetch;
> > -	};
> > -};
> > -
> > -/** struct xe_vma_ops - VMA operations */
> > -struct xe_vma_ops {
> > -	/** @list: list of VMA operations */
> > -	struct list_head list;
> > -};
> 
> It seems you moved a block of codes to another location. It caused more work for code review. Better to avoid this if we can.
> 

See above, with my refactor dummy binds and this moving this is not
required.

Matt

> Oak
> 
> > -
> >  #endif
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 06/30] drm/xe: Simplify VM bind IOCTL error handling and cleanup
  2024-03-08  5:07 ` [PATCH v4 06/30] drm/xe: Simplify VM bind IOCTL error handling and cleanup Matthew Brost
@ 2024-03-25 16:03   ` Zeng, Oak
  2024-03-26 18:46     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-25 16:03 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew

Hi Matt,

This looks like a nice clean up to me. See one comment inline.

> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 06/30] drm/xe: Simplify VM bind IOCTL error handling and
> cleanup
> 
> Clean up everything in VM bind IOCTL in 1 path for both errors and
> non-errors. Also move VM bind IOCTL cleanup from ops (also used by
> non-IOCTL binds) to the VM bind IOCTL.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm.c       | 60 +++++---------------------------
>  drivers/gpu/drm/xe/xe_vm_types.h |  5 ---
>  2 files changed, 9 insertions(+), 56 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 0bb807c05d7b..dde777c807cf 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -769,8 +769,7 @@ static void xe_vm_populate_dummy_rebind(struct
> xe_vm *vm, struct xe_vma *vma)
>  }
> 
>  static struct dma_fence *ops_execute(struct xe_vm *vm,
> -				     struct xe_vma_ops *vops,
> -				     bool cleanup);
> +				     struct xe_vma_ops *vops);
> 
>  struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
>  {
> @@ -794,7 +793,7 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm,
> bool rebind_worker)
>  			trace_xe_vma_rebind_exec(vma);
> 
>  		xe_vm_populate_dummy_rebind(vm, vma);
> -		fence = ops_execute(vm, &vm->dummy_ops.vops, false);
> +		fence = ops_execute(vm, &vm->dummy_ops.vops);
>  		if (IS_ERR(fence))
>  			return fence;
>  	}
> @@ -2474,7 +2473,6 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm,
> struct xe_exec_queue *q,
>  	if (!last_op)
>  		return 0;
> 
> -	last_op->ops = ops;
>  	if (last) {
>  		last_op->flags |= XE_VMA_OP_LAST;
>  		last_op->num_syncs = num_syncs;
> @@ -2643,25 +2641,6 @@ xe_vma_op_execute(struct xe_vm *vm, struct
> xe_vma_op *op)
>  	return fence;
>  }
> 
> -static void xe_vma_op_cleanup(struct xe_vm *vm, struct xe_vma_op *op)
> -{
> -	bool last = op->flags & XE_VMA_OP_LAST;
> -
> -	if (last) {
> -		while (op->num_syncs--)
> -			xe_sync_entry_cleanup(&op->syncs[op->num_syncs]);
> -		kfree(op->syncs);
> -		if (op->q)
> -			xe_exec_queue_put(op->q);
> -	}
> -	if (!list_empty(&op->link))
> -		list_del(&op->link);
> -	if (op->ops)
> -		drm_gpuva_ops_free(&vm->gpuvm, op->ops);
> -	if (last)
> -		xe_vm_put(vm);
> -}
> -
>  static void xe_vma_op_unwind(struct xe_vm *vm, struct xe_vma_op *op,
>  			     bool post_commit, bool prev_post_commit,
>  			     bool next_post_commit)
> @@ -2738,8 +2717,6 @@ static void vm_bind_ioctl_ops_unwind(struct xe_vm
> *vm,
>  					 op->flags &
> XE_VMA_OP_PREV_COMMITTED,
>  					 op->flags &
> XE_VMA_OP_NEXT_COMMITTED);
>  		}
> -
> -		drm_gpuva_ops_free(&vm->gpuvm, __ops);
>  	}
>  }
> 
> @@ -2818,8 +2795,7 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec
> *exec,
>  }
> 
>  static struct dma_fence *ops_execute(struct xe_vm *vm,
> -				     struct xe_vma_ops *vops,
> -				     bool cleanup)
> +				     struct xe_vma_ops *vops)
>  {
>  	struct xe_vma_op *op, *next;
>  	struct dma_fence *fence = NULL;
> @@ -2834,8 +2810,6 @@ static struct dma_fence *ops_execute(struct xe_vm
> *vm,
>  				 op->base.op, PTR_ERR(fence));
>  			fence = ERR_PTR(-ENOSPC);
>  		}
> -		if (cleanup)
> -			xe_vma_op_cleanup(vm, op);


Now with this cleanup code removed, do you still want to loop all the ops in the list when xe_vma_op_execute failed with error? Should we break and return earlier in this case?

Oak

>  	}
> 
>  	return fence;
> @@ -2858,7 +2832,7 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm
> *vm,
>  		if (err)
>  			goto unlock;
> 
> -		fence = ops_execute(vm, vops, true);
> +		fence = ops_execute(vm, vops);
>  		if (IS_ERR(fence)) {
>  			err = PTR_ERR(fence);
>  			/* FIXME: Killing VM rather than proper error handling */
> @@ -3211,30 +3185,14 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void
> *data, struct drm_file *file)
>  		goto unwind_ops;
>  	}
> 
> -	xe_vm_get(vm);
> -	if (q)
> -		xe_exec_queue_get(q);
> -
>  	err = vm_bind_ioctl_ops_execute(vm, &vops);
> 
> -	up_write(&vm->lock);
> -
> -	if (q)
> -		xe_exec_queue_put(q);
> -	xe_vm_put(vm);
> -
> -	for (i = 0; bos && i < args->num_binds; ++i)
> -		xe_bo_put(bos[i]);
> -
> -	kvfree(bos);
> -	kvfree(ops);
> -	if (args->num_binds > 1)
> -		kvfree(bind_ops);
> -
> -	return err;
> -
>  unwind_ops:
> -	vm_bind_ioctl_ops_unwind(vm, ops, args->num_binds);
> +	if (err && err != -ENODATA)
> +		vm_bind_ioctl_ops_unwind(vm, ops, args->num_binds);
> +	for (i = args->num_binds - 1; i >= 0; --i)
> +		if (ops[i])
> +			drm_gpuva_ops_free(&vm->gpuvm, ops[i]);
>  free_syncs:
>  	if (err == -ENODATA)
>  		err = vm_bind_ioctl_signal_fences(vm, q, syncs, num_syncs);
> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> b/drivers/gpu/drm/xe/xe_vm_types.h
> index 7ef9e632154a..f097fe318a74 100644
> --- a/drivers/gpu/drm/xe/xe_vm_types.h
> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> @@ -181,11 +181,6 @@ enum xe_vma_op_flags {
>  struct xe_vma_op {
>  	/** @base: GPUVA base operation */
>  	struct drm_gpuva_op base;
> -	/**
> -	 * @ops: GPUVA ops, when set call drm_gpuva_ops_free after this
> -	 * operations is processed
> -	 */
> -	struct drm_gpuva_ops *ops;
>  	/** @q: exec queue for this operation */
>  	struct xe_exec_queue *q;
>  	/**
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 08/30] drm/xe: s/xe_tile_migrate_engine/xe_tile_migrate_exec_queue
  2024-03-08  5:07 ` [PATCH v4 08/30] drm/xe: s/xe_tile_migrate_engine/xe_tile_migrate_exec_queue Matthew Brost
@ 2024-03-25 16:05   ` Zeng, Oak
  0 siblings, 0 replies; 76+ messages in thread
From: Zeng, Oak @ 2024-03-25 16:05 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew

This patch lgtm. Reviewed-by: Oak Zeng <oak.zeng@intel.com>

Oak

> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 08/30] drm/xe:
> s/xe_tile_migrate_engine/xe_tile_migrate_exec_queue
> 
> xe_engine is now xe_exec_queue, adjust this function's name to reflect.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_gt_pagefault.c | 2 +-
>  drivers/gpu/drm/xe/xe_migrate.c      | 8 ++++----
>  drivers/gpu/drm/xe/xe_migrate.h      | 3 ++-
>  3 files changed, 7 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c
> b/drivers/gpu/drm/xe/xe_gt_pagefault.c
> index 3c7d6e4e3917..878e234166aa 100644
> --- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
> +++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
> @@ -210,7 +210,7 @@ static int handle_pagefault(struct xe_gt *gt, struct
> pagefault *pf)
>  	trace_xe_vma_pf_bind(vma);
>  	xe_vm_populate_dummy_rebind(vm, vma);
>  	vm->dummy_ops.op.tile_mask = BIT(tile->id);
> -	vm->dummy_ops.op.q = xe_tile_migrate_engine(tile);
> +	vm->dummy_ops.op.q = xe_tile_migrate_exec_queue(tile);
>  	fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
>  	if (IS_ERR(fence)) {
>  		ret = PTR_ERR(fence);
> diff --git a/drivers/gpu/drm/xe/xe_migrate.c
> b/drivers/gpu/drm/xe/xe_migrate.c
> index ee1bb938c493..3fd76f912fda 100644
> --- a/drivers/gpu/drm/xe/xe_migrate.c
> +++ b/drivers/gpu/drm/xe/xe_migrate.c
> @@ -84,15 +84,15 @@ struct xe_migrate {
>  #define MAX_PTE_PER_SDI 0x1FE
> 
>  /**
> - * xe_tile_migrate_engine() - Get this tile's migrate engine.
> + * xe_tile_migrate_exec_queue() - Get this tile's migrate exec queue.
>   * @tile: The tile.
>   *
> - * Returns the default migrate engine of this tile.
> + * Returns the default migrate exec queue of this tile.
>   * TODO: Perhaps this function is slightly misplaced, and even unneeded?
>   *
> - * Return: The default migrate engine
> + * Return: The default migrate exec queue
>   */
> -struct xe_exec_queue *xe_tile_migrate_engine(struct xe_tile *tile)
> +struct xe_exec_queue *xe_tile_migrate_exec_queue(struct xe_tile *tile)
>  {
>  	return tile->migrate->q;
>  }
> diff --git a/drivers/gpu/drm/xe/xe_migrate.h
> b/drivers/gpu/drm/xe/xe_migrate.h
> index 951f19318ea4..9935ce336bae 100644
> --- a/drivers/gpu/drm/xe/xe_migrate.h
> +++ b/drivers/gpu/drm/xe/xe_migrate.h
> @@ -106,5 +106,6 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
> 
>  void xe_migrate_wait(struct xe_migrate *m);
> 
> -struct xe_exec_queue *xe_tile_migrate_engine(struct xe_tile *tile);
> +struct xe_exec_queue *xe_tile_migrate_exec_queue(struct xe_tile *tile);
> +
>  #endif
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 09/30] drm/xe: Add some members to xe_vma_ops
  2024-03-08  5:07 ` [PATCH v4 09/30] drm/xe: Add some members to xe_vma_ops Matthew Brost
@ 2024-03-25 16:10   ` Zeng, Oak
  2024-03-26 18:47     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-25 16:10 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew



> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 09/30] drm/xe: Add some members to xe_vma_ops
> 
> This will help with moving to single jobs for many bind operations.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm.c       | 13 ++++++++++---
>  drivers/gpu/drm/xe/xe_vm_types.h |  8 ++++++++
>  2 files changed, 18 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index a6bae2f5e296..f8b27746e5a7 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -1307,9 +1307,16 @@ static void xe_vm_free_scratch(struct xe_vm *vm)
>  	}
>  }
> 
> -static void xe_vma_ops_init(struct xe_vma_ops *vops)
> +static void xe_vma_ops_init(struct xe_vma_ops *vops, struct xe_vm *vm,
> +			    struct xe_exec_queue *q,
> +			    struct xe_sync_entry *syncs, u32 num_syncs)
>  {
> +	memset(vops, 0, sizeof(*vops));
>  	INIT_LIST_HEAD(&vops->list);
> +	vops->vm = vm;
> +	vops->q = q;
> +	vops->syncs = syncs;
> +	vops->num_syncs = num_syncs;
>  }
> 
>  struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
> @@ -1333,7 +1340,7 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32
> flags)
>  	init_rwsem(&vm->lock);
>  	mutex_init(&vm->snap_mutex);
> 
> -	xe_vma_ops_init(&vm->dummy_ops.vops);
> +	xe_vma_ops_init(&vm->dummy_ops.vops, vm, NULL, NULL, 0);


You mentioned in previous review, that vm->dummy_ops will be dropped... I guess this line will also be dropped.

Otherwise, this patch looks good to me.

Oak

>  	INIT_LIST_HEAD(&vm->dummy_ops.op.link);
>  	list_add(&vm->dummy_ops.op.link, &vm->dummy_ops.vops.list);
> 
> @@ -3176,7 +3183,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void
> *data, struct drm_file *file)
>  		goto free_syncs;
>  	}
> 
> -	xe_vma_ops_init(&vops);
> +	xe_vma_ops_init(&vops, vm, q, syncs, num_syncs);
>  	for (i = 0; i < args->num_binds; ++i) {
>  		u64 range = bind_ops[i].range;
>  		u64 addr = bind_ops[i].addr;
> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> b/drivers/gpu/drm/xe/xe_vm_types.h
> index 0bba5543ac28..f6ea4df64e79 100644
> --- a/drivers/gpu/drm/xe/xe_vm_types.h
> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> @@ -211,6 +211,14 @@ struct xe_vma_op {
>  struct xe_vma_ops {
>  	/** @list: list of VMA operations */
>  	struct list_head list;
> +	/** @vm: VM */
> +	struct xe_vm *vm;
> +	/** @q: exec queue these operations */
> +	struct xe_exec_queue *q;
> +	/** @syncs: syncs these operation */
> +	struct xe_sync_entry *syncs;
> +	/** @num_syncs: number of syncs */
> +	u32 num_syncs;
>  };
> 
>  struct xe_vm {
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 10/30] drm/xe: Add vm_bind_ioctl_ops_install_fences helper
  2024-03-08  5:07 ` [PATCH v4 10/30] drm/xe: Add vm_bind_ioctl_ops_install_fences helper Matthew Brost
@ 2024-03-25 16:51   ` Zeng, Oak
  2024-03-25 19:34     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-25 16:51 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew



> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 10/30] drm/xe: Add vm_bind_ioctl_ops_install_fences helper
> 
> Simplify VM bind code by signaling out-fences / destroying VMAs in a
> single location. Will help with transition single job for many bind ops.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm.c | 55 ++++++++++++++++----------------------
>  1 file changed, 23 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index f8b27746e5a7..8c96c98cba37 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -1658,7 +1658,7 @@ xe_vm_unbind_vma(struct xe_vma *vma, struct
> xe_exec_queue *q,
>  	struct dma_fence *fence = NULL;
>  	struct dma_fence **fences = NULL;
>  	struct dma_fence_array *cf = NULL;
> -	int cur_fence = 0, i;
> +	int cur_fence = 0;
>  	int number_tiles = hweight8(vma->tile_present);
>  	int err;
>  	u8 id;
> @@ -1716,10 +1716,6 @@ xe_vm_unbind_vma(struct xe_vma *vma, struct
> xe_exec_queue *q,
> 
>  	fence = cf ? &cf->base : !fence ?
>  		xe_exec_queue_last_fence_get(wait_exec_queue, vm) : fence;
> -	if (last_op) {
> -		for (i = 0; i < num_syncs; i++)
> -			xe_sync_entry_signal(&syncs[i], NULL, fence);
> -	}
> 
>  	return fence;
> 
> @@ -1743,7 +1739,7 @@ xe_vm_bind_vma(struct xe_vma *vma, struct
> xe_exec_queue *q,
>  	struct dma_fence **fences = NULL;
>  	struct dma_fence_array *cf = NULL;
>  	struct xe_vm *vm = xe_vma_vm(vma);
> -	int cur_fence = 0, i;
> +	int cur_fence = 0;
>  	int number_tiles = hweight8(vma->tile_mask);
>  	int err;
>  	u8 id;
> @@ -1790,12 +1786,6 @@ xe_vm_bind_vma(struct xe_vma *vma, struct
> xe_exec_queue *q,
>  		}
>  	}
> 
> -	if (last_op) {
> -		for (i = 0; i < num_syncs; i++)
> -			xe_sync_entry_signal(&syncs[i], NULL,
> -					     cf ? &cf->base : fence);
> -	}
> -
>  	return cf ? &cf->base : fence;
> 
>  err_fences:
> @@ -1847,15 +1837,8 @@ xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma,
> struct xe_exec_queue *q,
>  		if (IS_ERR(fence))
>  			return fence;
>  	} else {
> -		int i;
> -
>  		xe_assert(vm->xe, xe_vm_in_fault_mode(vm));
> -
>  		fence = xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> -		if (last_op) {
> -			for (i = 0; i < num_syncs; i++)
> -				xe_sync_entry_signal(&syncs[i], NULL, fence);
> -		}
>  	}
> 
>  	if (last_op)
> @@ -1879,7 +1862,6 @@ xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
>  	if (IS_ERR(fence))
>  		return fence;
> 
> -	xe_vma_destroy(vma, fence);
>  	if (last_op)
>  		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> 
> @@ -2037,17 +2019,7 @@ xe_vm_prefetch(struct xe_vm *vm, struct xe_vma
> *vma,
>  		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs,
> num_syncs,
>  				  vma->tile_mask, true, first_op, last_op);
>  	} else {
> -		struct dma_fence *fence =
> -			xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> -		int i;
> -
> -		/* Nothing to do, signal fences now */
> -		if (last_op) {
> -			for (i = 0; i < num_syncs; i++)
> -				xe_sync_entry_signal(&syncs[i], NULL, fence);
> -		}
> -
> -		return fence;
> +		return xe_exec_queue_last_fence_get(wait_exec_queue, vm);
>  	}
>  }
> 
> @@ -2844,6 +2816,25 @@ struct dma_fence *xe_vm_ops_execute(struct xe_vm
> *vm, struct xe_vma_ops *vops)
>  	return fence;
>  }
> 
> +static void vm_bind_ioctl_ops_install_fences(struct xe_vm *vm,
> +					     struct xe_vma_ops *vops,
> +					     struct dma_fence *fence)

Is this a correct function name? from the codes below, you destroyed the temporary vmas during vm_ioctl, then signaled all the sync entries, then you destroyed the fence generated from the last operation.... it is more like a cleanup stage of the vm_bind.... But I don't quite understand the code, see below questions...


> +{
> +	struct xe_vma_op *op;
> +	int i;
> +
> +	list_for_each_entry(op, &vops->list, link) {
> +		if (op->base.op == DRM_GPUVA_OP_UNMAP)
> +			xe_vma_destroy(gpuva_to_vma(op->base.unmap.va),
> fence);
> +		else if (op->base.op == DRM_GPUVA_OP_REMAP)
> +			xe_vma_destroy(gpuva_to_vma(op-
> >base.remap.unmap->va),
> +				       fence);
> +	}
> +	for (i = 0; i < vops->num_syncs; i++)
> +		xe_sync_entry_signal(vops->syncs + i, NULL, fence);

This signals the out-fence of vm_bind ioctl. Isn't this be done *after* fence is signaled (aka means the last vm bind operation is done)?


> +	dma_fence_put(fence);


I know this is also in the original code below... but I also don't understand why we can destroy fence here. As I understand it, this fence is generated during vm_bind operations. This is the last fence. Shouldn't we wait this fence somewhere so we know all the vm bind operations have been complete? I need your help to understand the picture here.

Oak

> +}
> +
>  static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
>  				     struct xe_vma_ops *vops)
>  {
> @@ -2868,7 +2859,7 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm
> *vm,
>  			xe_vm_kill(vm, false);
>  			goto unlock;
>  		} else {
> -			dma_fence_put(fence);
> +			vm_bind_ioctl_ops_install_fences(vm, vops, fence);
>  		}
>  	}
> 
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 11/30] drm/xe: Move setting last fence to vm_bind_ioctl_ops_install_fences
  2024-03-08  5:07 ` [PATCH v4 11/30] drm/xe: Move setting last fence to vm_bind_ioctl_ops_install_fences Matthew Brost
@ 2024-03-25 17:02   ` Zeng, Oak
  2024-03-25 19:35     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-25 17:02 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew



> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 11/30] drm/xe: Move setting last fence to
> vm_bind_ioctl_ops_install_fences
> 
> This moves setting of the last fence to a single location.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm.c | 9 ++-------
>  1 file changed, 2 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 8c96c98cba37..4432531f39fe 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -1841,9 +1841,6 @@ xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma,
> struct xe_exec_queue *q,
>  		fence = xe_exec_queue_last_fence_get(wait_exec_queue, vm);
>  	}
> 
> -	if (last_op)
> -		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> -
>  	return fence;
>  }
> 
> @@ -1853,7 +1850,6 @@ xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
>  	     u32 num_syncs, bool first_op, bool last_op)
>  {
>  	struct dma_fence *fence;
> -	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> q);
> 
>  	xe_vm_assert_held(vm);
>  	xe_bo_assert_held(xe_vma_bo(vma));
> @@ -1862,9 +1858,6 @@ xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
>  	if (IS_ERR(fence))
>  		return fence;
> 
> -	if (last_op)
> -		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> -
>  	return fence;
>  }
> 
> @@ -2820,6 +2813,7 @@ static void vm_bind_ioctl_ops_install_fences(struct
> xe_vm *vm,
>  					     struct xe_vma_ops *vops,
>  					     struct dma_fence *fence)
>  {
> +	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> vops->q);
>  	struct xe_vma_op *op;
>  	int i;
> 
> @@ -2832,6 +2826,7 @@ static void vm_bind_ioctl_ops_install_fences(struct
> xe_vm *vm,
>  	}
>  	for (i = 0; i < vops->num_syncs; i++)
>  		xe_sync_entry_signal(vops->syncs + i, NULL, fence);
> +	xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);


Oh, With this patch, I can understand the dma-fence-put below won't destroy the last fence, because this fence is set to exec queue's last fence.

I also understand now, how the last fence will be used to signal the out-fences of vm_bind ioctl... things make sense to me now...

IMO, maybe you can squash this patch to the last patch, so people don't have the confusion as I had.

Oak
>  	dma_fence_put(fence);
>  }
> 
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 10/30] drm/xe: Add vm_bind_ioctl_ops_install_fences helper
  2024-03-25 16:51   ` Zeng, Oak
@ 2024-03-25 19:34     ` Matthew Brost
  2024-03-25 19:44       ` Zeng, Oak
  0 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-25 19:34 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Mon, Mar 25, 2024 at 10:51:43AM -0600, Zeng, Oak wrote:
> 
> 
> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 10/30] drm/xe: Add vm_bind_ioctl_ops_install_fences helper
> > 
> > Simplify VM bind code by signaling out-fences / destroying VMAs in a
> > single location. Will help with transition single job for many bind ops.
> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_vm.c | 55 ++++++++++++++++----------------------
> >  1 file changed, 23 insertions(+), 32 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index f8b27746e5a7..8c96c98cba37 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -1658,7 +1658,7 @@ xe_vm_unbind_vma(struct xe_vma *vma, struct
> > xe_exec_queue *q,
> >  	struct dma_fence *fence = NULL;
> >  	struct dma_fence **fences = NULL;
> >  	struct dma_fence_array *cf = NULL;
> > -	int cur_fence = 0, i;
> > +	int cur_fence = 0;
> >  	int number_tiles = hweight8(vma->tile_present);
> >  	int err;
> >  	u8 id;
> > @@ -1716,10 +1716,6 @@ xe_vm_unbind_vma(struct xe_vma *vma, struct
> > xe_exec_queue *q,
> > 
> >  	fence = cf ? &cf->base : !fence ?
> >  		xe_exec_queue_last_fence_get(wait_exec_queue, vm) : fence;
> > -	if (last_op) {
> > -		for (i = 0; i < num_syncs; i++)
> > -			xe_sync_entry_signal(&syncs[i], NULL, fence);
> > -	}
> > 
> >  	return fence;
> > 
> > @@ -1743,7 +1739,7 @@ xe_vm_bind_vma(struct xe_vma *vma, struct
> > xe_exec_queue *q,
> >  	struct dma_fence **fences = NULL;
> >  	struct dma_fence_array *cf = NULL;
> >  	struct xe_vm *vm = xe_vma_vm(vma);
> > -	int cur_fence = 0, i;
> > +	int cur_fence = 0;
> >  	int number_tiles = hweight8(vma->tile_mask);
> >  	int err;
> >  	u8 id;
> > @@ -1790,12 +1786,6 @@ xe_vm_bind_vma(struct xe_vma *vma, struct
> > xe_exec_queue *q,
> >  		}
> >  	}
> > 
> > -	if (last_op) {
> > -		for (i = 0; i < num_syncs; i++)
> > -			xe_sync_entry_signal(&syncs[i], NULL,
> > -					     cf ? &cf->base : fence);
> > -	}
> > -
> >  	return cf ? &cf->base : fence;
> > 
> >  err_fences:
> > @@ -1847,15 +1837,8 @@ xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma,
> > struct xe_exec_queue *q,
> >  		if (IS_ERR(fence))
> >  			return fence;
> >  	} else {
> > -		int i;
> > -
> >  		xe_assert(vm->xe, xe_vm_in_fault_mode(vm));
> > -
> >  		fence = xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> > -		if (last_op) {
> > -			for (i = 0; i < num_syncs; i++)
> > -				xe_sync_entry_signal(&syncs[i], NULL, fence);
> > -		}
> >  	}
> > 
> >  	if (last_op)
> > @@ -1879,7 +1862,6 @@ xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
> >  	if (IS_ERR(fence))
> >  		return fence;
> > 
> > -	xe_vma_destroy(vma, fence);
> >  	if (last_op)
> >  		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> > 
> > @@ -2037,17 +2019,7 @@ xe_vm_prefetch(struct xe_vm *vm, struct xe_vma
> > *vma,
> >  		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs,
> > num_syncs,
> >  				  vma->tile_mask, true, first_op, last_op);
> >  	} else {
> > -		struct dma_fence *fence =
> > -			xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> > -		int i;
> > -
> > -		/* Nothing to do, signal fences now */
> > -		if (last_op) {
> > -			for (i = 0; i < num_syncs; i++)
> > -				xe_sync_entry_signal(&syncs[i], NULL, fence);
> > -		}
> > -
> > -		return fence;
> > +		return xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> >  	}
> >  }
> > 
> > @@ -2844,6 +2816,25 @@ struct dma_fence *xe_vm_ops_execute(struct xe_vm
> > *vm, struct xe_vma_ops *vops)
> >  	return fence;
> >  }
> > 
> > +static void vm_bind_ioctl_ops_install_fences(struct xe_vm *vm,
> > +					     struct xe_vma_ops *vops,
> > +					     struct dma_fence *fence)
> 
> Is this a correct function name? from the codes below, you destroyed the temporary vmas during vm_ioctl, then signaled all the sync entries, then you destroyed the fence generated from the last operation.... it is more like a cleanup stage of the vm_bind.... But I don't quite understand the code, see below questions...
> 

Yes, let me rename. How about vm_bind_ioctl_ops_execute_fini?

'destroyed the temporary vmas during vm_ioctl' - This is destroying
unmapped VMAs when the fence signals.

> 
> > +{
> > +	struct xe_vma_op *op;
> > +	int i;
> > +
> > +	list_for_each_entry(op, &vops->list, link) {
> > +		if (op->base.op == DRM_GPUVA_OP_UNMAP)
> > +			xe_vma_destroy(gpuva_to_vma(op->base.unmap.va),
> > fence);
> > +		else if (op->base.op == DRM_GPUVA_OP_REMAP)
> > +			xe_vma_destroy(gpuva_to_vma(op-
> > >base.remap.unmap->va),
> > +				       fence);
> > +	}
> > +	for (i = 0; i < vops->num_syncs; i++)
> > +		xe_sync_entry_signal(vops->syncs + i, NULL, fence);
> 
> This signals the out-fence of vm_bind ioctl. Isn't this be done *after* fence is signaled (aka means the last vm bind operation is done)?
> 
> 

This, xe_sync_entry_signal, is a bad name. It really should be
xe_sync_entry_install_fence or something like that. It is really is
installing the fence in all out-syncs, the fence signals, then the
out-fence signals.

> > +	dma_fence_put(fence);
> 
> 
> I know this is also in the original code below... but I also don't understand why we can destroy fence here. As I understand it, this fence is generated during vm_bind operations. This is the last fence. Shouldn't we wait this fence somewhere so we know all the vm bind operations have been complete? I need your help to understand the picture here.
>

This isn't destroying the fence - it dropping a reference. This is
reference return from xe_vm_ops_execute, we install the fence anywhere
needed (this might take more refs) then drop the ref from
xe_vm_ops_execute.

Matt
 
> Oak
> 
> > +}
> > +
> >  static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
> >  				     struct xe_vma_ops *vops)
> >  {
> > @@ -2868,7 +2859,7 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm
> > *vm,
> >  			xe_vm_kill(vm, false);
> >  			goto unlock;
> >  		} else {
> > -			dma_fence_put(fence);
> > +			vm_bind_ioctl_ops_install_fences(vm, vops, fence);
> >  		}
> >  	}
> > 
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 11/30] drm/xe: Move setting last fence to vm_bind_ioctl_ops_install_fences
  2024-03-25 17:02   ` Zeng, Oak
@ 2024-03-25 19:35     ` Matthew Brost
  0 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-25 19:35 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Mon, Mar 25, 2024 at 11:02:29AM -0600, Zeng, Oak wrote:
> 
> 
> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 11/30] drm/xe: Move setting last fence to
> > vm_bind_ioctl_ops_install_fences
> > 
> > This moves setting of the last fence to a single location.
> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_vm.c | 9 ++-------
> >  1 file changed, 2 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index 8c96c98cba37..4432531f39fe 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -1841,9 +1841,6 @@ xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma,
> > struct xe_exec_queue *q,
> >  		fence = xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> >  	}
> > 
> > -	if (last_op)
> > -		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> > -
> >  	return fence;
> >  }
> > 
> > @@ -1853,7 +1850,6 @@ xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
> >  	     u32 num_syncs, bool first_op, bool last_op)
> >  {
> >  	struct dma_fence *fence;
> > -	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > q);
> > 
> >  	xe_vm_assert_held(vm);
> >  	xe_bo_assert_held(xe_vma_bo(vma));
> > @@ -1862,9 +1858,6 @@ xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
> >  	if (IS_ERR(fence))
> >  		return fence;
> > 
> > -	if (last_op)
> > -		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> > -
> >  	return fence;
> >  }
> > 
> > @@ -2820,6 +2813,7 @@ static void vm_bind_ioctl_ops_install_fences(struct
> > xe_vm *vm,
> >  					     struct xe_vma_ops *vops,
> >  					     struct dma_fence *fence)
> >  {
> > +	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > vops->q);
> >  	struct xe_vma_op *op;
> >  	int i;
> > 
> > @@ -2832,6 +2826,7 @@ static void vm_bind_ioctl_ops_install_fences(struct
> > xe_vm *vm,
> >  	}
> >  	for (i = 0; i < vops->num_syncs; i++)
> >  		xe_sync_entry_signal(vops->syncs + i, NULL, fence);
> > +	xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> 
> 
> Oh, With this patch, I can understand the dma-fence-put below won't destroy the last fence, because this fence is set to exec queue's last fence.
> 

Yes, xe_exec_queue_last_fence_set in this case takes a ref.

> I also understand now, how the last fence will be used to signal the out-fences of vm_bind ioctl... things make sense to me now...
> 
> IMO, maybe you can squash this patch to the last patch, so people don't have the confusion as I had.
>

Will squash.

Matt

> Oak
> >  	dma_fence_put(fence);
> >  }
> > 
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 10/30] drm/xe: Add vm_bind_ioctl_ops_install_fences helper
  2024-03-25 19:34     ` Matthew Brost
@ 2024-03-25 19:44       ` Zeng, Oak
  0 siblings, 0 replies; 76+ messages in thread
From: Zeng, Oak @ 2024-03-25 19:44 UTC (permalink / raw)
  To: Brost, Matthew; +Cc: intel-xe



> -----Original Message-----
> From: Brost, Matthew <matthew.brost@intel.com>
> Sent: Monday, March 25, 2024 3:35 PM
> To: Zeng, Oak <oak.zeng@intel.com>
> Cc: intel-xe@lists.freedesktop.org
> Subject: Re: [PATCH v4 10/30] drm/xe: Add vm_bind_ioctl_ops_install_fences
> helper
> 
> On Mon, Mar 25, 2024 at 10:51:43AM -0600, Zeng, Oak wrote:
> >
> >
> > > -----Original Message-----
> > > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of
> Matthew
> > > Brost
> > > Sent: Friday, March 8, 2024 12:08 AM
> > > To: intel-xe@lists.freedesktop.org
> > > Cc: Brost, Matthew <matthew.brost@intel.com>
> > > Subject: [PATCH v4 10/30] drm/xe: Add vm_bind_ioctl_ops_install_fences
> helper
> > >
> > > Simplify VM bind code by signaling out-fences / destroying VMAs in a
> > > single location. Will help with transition single job for many bind ops.
> > >
> > > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > > ---
> > >  drivers/gpu/drm/xe/xe_vm.c | 55 ++++++++++++++++----------------------
> > >  1 file changed, 23 insertions(+), 32 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > > index f8b27746e5a7..8c96c98cba37 100644
> > > --- a/drivers/gpu/drm/xe/xe_vm.c
> > > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > > @@ -1658,7 +1658,7 @@ xe_vm_unbind_vma(struct xe_vma *vma, struct
> > > xe_exec_queue *q,
> > >  	struct dma_fence *fence = NULL;
> > >  	struct dma_fence **fences = NULL;
> > >  	struct dma_fence_array *cf = NULL;
> > > -	int cur_fence = 0, i;
> > > +	int cur_fence = 0;
> > >  	int number_tiles = hweight8(vma->tile_present);
> > >  	int err;
> > >  	u8 id;
> > > @@ -1716,10 +1716,6 @@ xe_vm_unbind_vma(struct xe_vma *vma, struct
> > > xe_exec_queue *q,
> > >
> > >  	fence = cf ? &cf->base : !fence ?
> > >  		xe_exec_queue_last_fence_get(wait_exec_queue, vm) : fence;
> > > -	if (last_op) {
> > > -		for (i = 0; i < num_syncs; i++)
> > > -			xe_sync_entry_signal(&syncs[i], NULL, fence);
> > > -	}
> > >
> > >  	return fence;
> > >
> > > @@ -1743,7 +1739,7 @@ xe_vm_bind_vma(struct xe_vma *vma, struct
> > > xe_exec_queue *q,
> > >  	struct dma_fence **fences = NULL;
> > >  	struct dma_fence_array *cf = NULL;
> > >  	struct xe_vm *vm = xe_vma_vm(vma);
> > > -	int cur_fence = 0, i;
> > > +	int cur_fence = 0;
> > >  	int number_tiles = hweight8(vma->tile_mask);
> > >  	int err;
> > >  	u8 id;
> > > @@ -1790,12 +1786,6 @@ xe_vm_bind_vma(struct xe_vma *vma, struct
> > > xe_exec_queue *q,
> > >  		}
> > >  	}
> > >
> > > -	if (last_op) {
> > > -		for (i = 0; i < num_syncs; i++)
> > > -			xe_sync_entry_signal(&syncs[i], NULL,
> > > -					     cf ? &cf->base : fence);
> > > -	}
> > > -
> > >  	return cf ? &cf->base : fence;
> > >
> > >  err_fences:
> > > @@ -1847,15 +1837,8 @@ xe_vm_bind(struct xe_vm *vm, struct xe_vma
> *vma,
> > > struct xe_exec_queue *q,
> > >  		if (IS_ERR(fence))
> > >  			return fence;
> > >  	} else {
> > > -		int i;
> > > -
> > >  		xe_assert(vm->xe, xe_vm_in_fault_mode(vm));
> > > -
> > >  		fence = xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> > > -		if (last_op) {
> > > -			for (i = 0; i < num_syncs; i++)
> > > -				xe_sync_entry_signal(&syncs[i], NULL, fence);
> > > -		}
> > >  	}
> > >
> > >  	if (last_op)
> > > @@ -1879,7 +1862,6 @@ xe_vm_unbind(struct xe_vm *vm, struct xe_vma
> *vma,
> > >  	if (IS_ERR(fence))
> > >  		return fence;
> > >
> > > -	xe_vma_destroy(vma, fence);
> > >  	if (last_op)
> > >  		xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> > >
> > > @@ -2037,17 +2019,7 @@ xe_vm_prefetch(struct xe_vm *vm, struct xe_vma
> > > *vma,
> > >  		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs,
> > > num_syncs,
> > >  				  vma->tile_mask, true, first_op, last_op);
> > >  	} else {
> > > -		struct dma_fence *fence =
> > > -			xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> > > -		int i;
> > > -
> > > -		/* Nothing to do, signal fences now */
> > > -		if (last_op) {
> > > -			for (i = 0; i < num_syncs; i++)
> > > -				xe_sync_entry_signal(&syncs[i], NULL, fence);
> > > -		}
> > > -
> > > -		return fence;
> > > +		return xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> > >  	}
> > >  }
> > >
> > > @@ -2844,6 +2816,25 @@ struct dma_fence *xe_vm_ops_execute(struct
> xe_vm
> > > *vm, struct xe_vma_ops *vops)
> > >  	return fence;
> > >  }
> > >
> > > +static void vm_bind_ioctl_ops_install_fences(struct xe_vm *vm,
> > > +					     struct xe_vma_ops *vops,
> > > +					     struct dma_fence *fence)
> >
> > Is this a correct function name? from the codes below, you destroyed the
> temporary vmas during vm_ioctl, then signaled all the sync entries, then you
> destroyed the fence generated from the last operation.... it is more like a cleanup
> stage of the vm_bind.... But I don't quite understand the code, see below
> questions...
> >
> 
> Yes, let me rename. How about vm_bind_ioctl_ops_execute_fini?

Yes that sounds better.

> 
> 'destroyed the temporary vmas during vm_ioctl' - This is destroying
> unmapped VMAs when the fence signals.

I see.
> 
> >
> > > +{
> > > +	struct xe_vma_op *op;
> > > +	int i;
> > > +
> > > +	list_for_each_entry(op, &vops->list, link) {
> > > +		if (op->base.op == DRM_GPUVA_OP_UNMAP)
> > > +			xe_vma_destroy(gpuva_to_vma(op->base.unmap.va),
> > > fence);
> > > +		else if (op->base.op == DRM_GPUVA_OP_REMAP)
> > > +			xe_vma_destroy(gpuva_to_vma(op-
> > > >base.remap.unmap->va),
> > > +				       fence);
> > > +	}
> > > +	for (i = 0; i < vops->num_syncs; i++)
> > > +		xe_sync_entry_signal(vops->syncs + i, NULL, fence);
> >
> > This signals the out-fence of vm_bind ioctl. Isn't this be done *after* fence is
> signaled (aka means the last vm bind operation is done)?
> >
> >
> 
> This, xe_sync_entry_signal, is a bad name. It really should be
> xe_sync_entry_install_fence or something like that. It is really is
> installing the fence in all out-syncs, the fence signals, then the
> out-fence signals.

Ah! That make sense. Now it is more clear to me.

> 
> > > +	dma_fence_put(fence);
> >
> >
> > I know this is also in the original code below... but I also don't understand why
> we can destroy fence here. As I understand it, this fence is generated during
> vm_bind operations. This is the last fence. Shouldn't we wait this fence
> somewhere so we know all the vm bind operations have been complete? I need
> your help to understand the picture here.
> >
> 
> This isn't destroying the fence - it dropping a reference. This is
> reference return from xe_vm_ops_execute, we install the fence anywhere
> needed (this might take more refs) then drop the ref from
> xe_vm_ops_execute.

Ok, that make sense.

Oak

> 
> Matt
> 
> > Oak
> >
> > > +}
> > > +
> > >  static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
> > >  				     struct xe_vma_ops *vops)
> > >  {
> > > @@ -2868,7 +2859,7 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm
> > > *vm,
> > >  			xe_vm_kill(vm, false);
> > >  			goto unlock;
> > >  		} else {
> > > -			dma_fence_put(fence);
> > > +			vm_bind_ioctl_ops_install_fences(vm, vops, fence);
> > >  		}
> > >  	}
> > >
> > > --
> > > 2.34.1
> >

^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 12/30] drm/xe: Move ufence check to op_lock
  2024-03-08  5:07 ` [PATCH v4 12/30] drm/xe: Move ufence check to op_lock Matthew Brost
@ 2024-03-25 20:37   ` Zeng, Oak
  2024-03-26 18:49     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-25 20:37 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew

Patch makes sense to me. See one comment inline

> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 12/30] drm/xe: Move ufence check to op_lock
> 
> Rather than checking for an unsignaled ufence ay unbind time, check for
> this during the op_lock function. This will help with the transition to
> job 1 per VM bind IOCTL.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm.c | 33 +++++++++++++++++++++++----------
>  1 file changed, 23 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 4432531f39fe..5767955529dd 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -1665,16 +1665,6 @@ xe_vm_unbind_vma(struct xe_vma *vma, struct
> xe_exec_queue *q,
> 
>  	trace_xe_vma_unbind(vma);
> 
> -	if (vma->ufence) {
> -		struct xe_user_fence * const f = vma->ufence;
> -
> -		if (!xe_sync_ufence_get_status(f))
> -			return ERR_PTR(-EBUSY);
> -
> -		vma->ufence = NULL;
> -		xe_sync_ufence_put(f);
> -	}
> -
>  	if (number_tiles > 1) {
>  		fences = kmalloc_array(number_tiles, sizeof(*fences),
>  				       GFP_KERNEL);
> @@ -2721,6 +2711,21 @@ static int vma_lock(struct drm_exec *exec, struct
> xe_vma *vma, bool validate)
>  	return err;
>  }
> 
> +static int check_ufence(struct xe_vma *vma)
> +{
> +	if (vma->ufence) {
> +		struct xe_user_fence * const f = vma->ufence;
> +
> +		if (!xe_sync_ufence_get_status(f))
> +			return -EBUSY;
> +
> +		vma->ufence = NULL;
> +		xe_sync_ufence_put(f);
> +	}
> +
> +	return 0;
> +}
> +
>  static int op_lock(struct drm_exec *exec, struct xe_vm *vm,
>  		   struct xe_vma_op *op)
>  {
> @@ -2731,6 +2736,10 @@ static int op_lock(struct drm_exec *exec, struct xe_vm
> *vm,
>  		err = vma_lock(exec, op-
> >map.vma, !xe_vm_in_fault_mode(vm));
>  		break;
>  	case DRM_GPUVA_OP_REMAP:
> +		err = check_ufence(gpuva_to_vma(op->base.remap.unmap-
> >va));

This is another reason we need to rename op_lock...

Oak

> +		if (err)
> +			break;
> +
>  		err = vma_lock(exec, gpuva_to_vma(op->base.remap.unmap-
> >va),
>  			       false);
>  		if (!err && op->remap.prev)
> @@ -2739,6 +2748,10 @@ static int op_lock(struct drm_exec *exec, struct xe_vm
> *vm,
>  			err = vma_lock(exec, op->remap.next, true);
>  		break;
>  	case DRM_GPUVA_OP_UNMAP:
> +		err = check_ufence(gpuva_to_vma(op->base.unmap.va));
> +		if (err)
> +			break;
> +
>  		err = vma_lock(exec, gpuva_to_vma(op->base.unmap.va), false);
>  		break;
>  	case DRM_GPUVA_OP_PREFETCH:
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 13/30] drm/xe: Move ufence add to vm_bind_ioctl_ops_install_fences
  2024-03-08  5:07 ` [PATCH v4 13/30] drm/xe: Move ufence add to vm_bind_ioctl_ops_install_fences Matthew Brost
@ 2024-03-25 20:54   ` Zeng, Oak
  2024-03-26 18:54     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-25 20:54 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew

This patch makes sense to me. See two nit-pick inline

> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 13/30] drm/xe: Move ufence add to
> vm_bind_ioctl_ops_install_fences
> 
> Rather than adding a ufence to a VMA in the bind function, add the
> ufence to all VMAs in the IOCTL that require binds in
> vm_bind_ioctl_ops_install_fences. This will help with the transition to
> job 1 per VM bind IOCTL.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_sync.c | 15 ++++++++++++
>  drivers/gpu/drm/xe/xe_sync.h |  1 +
>  drivers/gpu/drm/xe/xe_vm.c   | 44 ++++++++++++++++++++++++++++++------
>  3 files changed, 53 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_sync.c b/drivers/gpu/drm/xe/xe_sync.c
> index 02c9577fe418..07aa65d9bcab 100644
> --- a/drivers/gpu/drm/xe/xe_sync.c
> +++ b/drivers/gpu/drm/xe/xe_sync.c
> @@ -343,6 +343,21 @@ xe_sync_in_fence_get(struct xe_sync_entry *sync, int
> num_sync,
>  	return ERR_PTR(-ENOMEM);
>  }
> 
> +/**
> + * __xe_sync_ufence_get() - Get user fence from user fence
> + * @ufence: input user fence
> + *
> + * Get a user fence reference from user fence
> + *
> + * Return: xe_user_fence pointer with reference
> + */
> +struct xe_user_fence *__xe_sync_ufence_get(struct xe_user_fence *ufence)
> +{
> +	user_fence_get(ufence);
> +
> +	return ufence;
> +}

I wonder why this is made part of xe_sync. Isn't just a ufence get function? Can we drop _sync_ from the function name?


> +
>  /**
>   * xe_sync_ufence_get() - Get user fence from sync
>   * @sync: input sync
> diff --git a/drivers/gpu/drm/xe/xe_sync.h b/drivers/gpu/drm/xe/xe_sync.h
> index 0fd0d51208e6..26e9ec9de1a8 100644
> --- a/drivers/gpu/drm/xe/xe_sync.h
> +++ b/drivers/gpu/drm/xe/xe_sync.h
> @@ -38,6 +38,7 @@ static inline bool xe_sync_is_ufence(struct xe_sync_entry
> *sync)
>  	return !!sync->ufence;
>  }
> 
> +struct xe_user_fence *__xe_sync_ufence_get(struct xe_user_fence *ufence);
>  struct xe_user_fence *xe_sync_ufence_get(struct xe_sync_entry *sync);
>  void xe_sync_ufence_put(struct xe_user_fence *ufence);
>  int xe_sync_ufence_get_status(struct xe_user_fence *ufence);
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 5767955529dd..5b93c71fc5e9 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -1810,17 +1810,10 @@ xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma,
> struct xe_exec_queue *q,
>  {
>  	struct dma_fence *fence;
>  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> q);
> -	struct xe_user_fence *ufence;
> 
>  	xe_vm_assert_held(vm);
>  	xe_bo_assert_held(bo);
> 
> -	ufence = find_ufence_get(syncs, num_syncs);
> -	if (vma->ufence && ufence)
> -		xe_sync_ufence_put(vma->ufence);
> -
> -	vma->ufence = ufence ?: vma->ufence;
> -
>  	if (immediate) {
>  		fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, tile_mask,
>  				       first_op, last_op);
> @@ -2822,21 +2815,58 @@ struct dma_fence *xe_vm_ops_execute(struct
> xe_vm *vm, struct xe_vma_ops *vops)
>  	return fence;
>  }
> 
> +static void vma_add_ufence(struct xe_vma *vma, struct xe_user_fence
> *ufence)
> +{
> +	if (vma->ufence)
> +		xe_sync_ufence_put(vma->ufence);

Not sure where/when we introduced xe_sync_ufence_put, for me this can be renamed to xe_ufence_put

Oak

> +	vma->ufence = __xe_sync_ufence_get(ufence);
> +}
> +
> +static void op_add_ufence(struct xe_vm *vm, struct xe_vma_op *op,
> +			  struct xe_user_fence *ufence)
> +{
> +	switch (op->base.op) {
> +	case DRM_GPUVA_OP_MAP:
> +		vma_add_ufence(op->map.vma, ufence);
> +		break;
> +	case DRM_GPUVA_OP_REMAP:
> +		if (op->remap.prev)
> +			vma_add_ufence(op->remap.prev, ufence);
> +		if (op->remap.next)
> +			vma_add_ufence(op->remap.next, ufence);
> +		break;
> +	case DRM_GPUVA_OP_UNMAP:
> +		break;
> +	case DRM_GPUVA_OP_PREFETCH:
> +		vma_add_ufence(gpuva_to_vma(op->base.prefetch.va),
> ufence);
> +		break;
> +	default:
> +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> +	}
> +}
> +
>  static void vm_bind_ioctl_ops_install_fences(struct xe_vm *vm,
>  					     struct xe_vma_ops *vops,
>  					     struct dma_fence *fence)
>  {
>  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> vops->q);
> +	struct xe_user_fence *ufence;
>  	struct xe_vma_op *op;
>  	int i;
> 
> +	ufence = find_ufence_get(vops->syncs, vops->num_syncs);
>  	list_for_each_entry(op, &vops->list, link) {
> +		if (ufence)
> +			op_add_ufence(vm, op, ufence);
> +
>  		if (op->base.op == DRM_GPUVA_OP_UNMAP)
>  			xe_vma_destroy(gpuva_to_vma(op->base.unmap.va),
> fence);
>  		else if (op->base.op == DRM_GPUVA_OP_REMAP)
>  			xe_vma_destroy(gpuva_to_vma(op-
> >base.remap.unmap->va),
>  				       fence);
>  	}
> +	if (ufence)
> +		xe_sync_ufence_put(ufence);
>  	for (i = 0; i < vops->num_syncs; i++)
>  		xe_sync_entry_signal(vops->syncs + i, NULL, fence);
>  	xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 14/30] drm/xe: Add xe_gt_tlb_invalidation_range and convert PT layer to use this
  2024-03-08  5:07 ` [PATCH v4 14/30] drm/xe: Add xe_gt_tlb_invalidation_range and convert PT layer to use this Matthew Brost
@ 2024-03-25 21:35   ` Zeng, Oak
  2024-03-26 18:57     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-25 21:35 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew

Hi Matt,

Patch looks good to me. See one question inline

> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 14/30] drm/xe: Add xe_gt_tlb_invalidation_range and
> convert PT layer to use this
> 
> xe_gt_tlb_invalidation_range accepts a start and end address rather than
> a VMA. This will enable multiple VMAs to be invalidated in a single
> invalidation. Update the PT layer to use this new function.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c | 59 +++++++++++++++------
>  drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h |  3 ++
>  drivers/gpu/drm/xe/xe_pt.c                  | 25 ++++++---
>  3 files changed, 65 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
> b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
> index a3c4ffba679d..ac2bf86de39a 100644
> --- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
> +++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
> @@ -264,11 +264,15 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt)
>  }
> 
>  /**
> - * xe_gt_tlb_invalidation_vma - Issue a TLB invalidation on this GT for a VMA
> + * xe_gt_tlb_invalidation_range - Issue a TLB invalidation on this GT for an
> + * address range
> + *
>   * @gt: graphics tile
>   * @fence: invalidation fence which will be signal on TLB invalidation
>   * completion, can be NULL
> - * @vma: VMA to invalidate
> + * @start: start address
> + * @end: end address
> + * @asid: address space id
>   *
>   * Issue a range based TLB invalidation if supported, if not fallback to a full
>   * TLB invalidation. Completion of TLB is asynchronous and caller can either use
> @@ -278,17 +282,15 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt)
>   * Return: Seqno which can be passed to xe_gt_tlb_invalidation_wait on success,
>   * negative error code on error.
>   */
> -int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
> -			       struct xe_gt_tlb_invalidation_fence *fence,
> -			       struct xe_vma *vma)
> +int xe_gt_tlb_invalidation_range(struct xe_gt *gt,
> +				 struct xe_gt_tlb_invalidation_fence *fence,
> +				 u64 start, u64 end, u32 asid)
>  {
>  	struct xe_device *xe = gt_to_xe(gt);
>  #define MAX_TLB_INVALIDATION_LEN	7
>  	u32 action[MAX_TLB_INVALIDATION_LEN];
>  	int len = 0;
> 
> -	xe_gt_assert(gt, vma);
> -
>  	/* Execlists not supported */
>  	if (gt_to_xe(gt)->info.force_execlist) {
>  		if (fence)
> @@ -302,8 +304,8 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
>  	if (!xe->info.has_range_tlb_invalidation) {
>  		action[len++] = MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL);
>  	} else {
> -		u64 start = xe_vma_start(vma);
> -		u64 length = xe_vma_size(vma);
> +		u64 orig_start = start;
> +		u64 length = end - start;
>  		u64 align, end;
> 
>  		if (length < SZ_4K)
> @@ -316,12 +318,12 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
>  		 * address mask covering the required range.
>  		 */
>  		align = roundup_pow_of_two(length);
> -		start = ALIGN_DOWN(xe_vma_start(vma), align);
> -		end = ALIGN(xe_vma_end(vma), align);
> +		start = ALIGN_DOWN(start, align);
> +		end = ALIGN(end, align);
>  		length = align;
>  		while (start + length < end) {
>  			length <<= 1;
> -			start = ALIGN_DOWN(xe_vma_start(vma), length);
> +			start = ALIGN_DOWN(orig_start, length);
>  		}
> 
>  		/*
> @@ -330,16 +332,17 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
>  		 */
>  		if (length >= SZ_2M) {
>  			length = max_t(u64, SZ_16M, length);
> -			start = ALIGN_DOWN(xe_vma_start(vma), length);
> +			start = ALIGN_DOWN(orig_start, length);
>  		}
> 
>  		xe_gt_assert(gt, length >= SZ_4K);
>  		xe_gt_assert(gt, is_power_of_2(length));
> -		xe_gt_assert(gt, !(length & GENMASK(ilog2(SZ_16M) - 1,
> ilog2(SZ_2M) + 1)));
> +		xe_gt_assert(gt, !(length & GENMASK(ilog2(SZ_16M) - 1,
> +						    ilog2(SZ_2M) + 1)));
>  		xe_gt_assert(gt, IS_ALIGNED(start, length));
> 
>  		action[len++] =
> MAKE_INVAL_OP(XE_GUC_TLB_INVAL_PAGE_SELECTIVE);
> -		action[len++] = xe_vma_vm(vma)->usm.asid;
> +		action[len++] = asid;
>  		action[len++] = lower_32_bits(start);
>  		action[len++] = upper_32_bits(start);
>  		action[len++] = ilog2(length) - ilog2(SZ_4K);
> @@ -350,6 +353,32 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
>  	return send_tlb_invalidation(&gt->uc.guc, fence, action, len);
>  }
> 
> +/**
> + * xe_gt_tlb_invalidation_vma - Issue a TLB invalidation on this GT for a VMA
> + * @gt: graphics tile
> + * @fence: invalidation fence which will be signal on TLB invalidation
> + * completion, can be NULL
> + * @vma: VMA to invalidate
> + *
> + * Issue a range based TLB invalidation if supported, if not fallback to a full
> + * TLB invalidation. Completion of TLB is asynchronous and caller can either use
> + * the invalidation fence or seqno + xe_gt_tlb_invalidation_wait to wait for
> + * completion.
> + *
> + * Return: Seqno which can be passed to xe_gt_tlb_invalidation_wait on success,
> + * negative error code on error.
> + */
> +int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
> +			       struct xe_gt_tlb_invalidation_fence *fence,
> +			       struct xe_vma *vma)
> +{
> +	xe_gt_assert(gt, vma);
> +
> +	return xe_gt_tlb_invalidation_range(gt, fence, xe_vma_start(vma),
> +					    xe_vma_end(vma),
> +					    xe_vma_vm(vma)->usm.asid);
> +}
> +
>  /**
>   * xe_gt_tlb_invalidation_wait - Wait for TLB to complete
>   * @gt: graphics tile
> diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
> b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
> index fbb743d80d2c..bf3bebd9f985 100644
> --- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
> +++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
> @@ -20,6 +20,9 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt);
>  int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
>  			       struct xe_gt_tlb_invalidation_fence *fence,
>  			       struct xe_vma *vma);
> +int xe_gt_tlb_invalidation_range(struct xe_gt *gt,
> +				 struct xe_gt_tlb_invalidation_fence *fence,
> +				 u64 start, u64 end, u32 asid);
>  int xe_gt_tlb_invalidation_wait(struct xe_gt *gt, int seqno);
>  int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32
> len);
> 
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> index 7f54bc3e389d..110d6917089b 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -1074,10 +1074,12 @@ static const struct xe_migrate_pt_update_ops
> userptr_bind_ops = {
>  struct invalidation_fence {
>  	struct xe_gt_tlb_invalidation_fence base;
>  	struct xe_gt *gt;
> -	struct xe_vma *vma;
>  	struct dma_fence *fence;
>  	struct dma_fence_cb cb;
>  	struct work_struct work;
> +	u64 start;
> +	u64 end;
> +	u32 asid;


I didn't see start/end/asid is used anywhere else, except in the below fence_init function... do we really need those members?

Oak

>  };
> 
>  static const char *
> @@ -1120,13 +1122,14 @@ static void invalidation_fence_work_func(struct
> work_struct *w)
>  		container_of(w, struct invalidation_fence, work);
> 
>  	trace_xe_gt_tlb_invalidation_fence_work_func(&ifence->base);
> -	xe_gt_tlb_invalidation_vma(ifence->gt, &ifence->base, ifence->vma);
> +	xe_gt_tlb_invalidation_range(ifence->gt, &ifence->base, ifence->start,
> +				     ifence->end, ifence->asid);
>  }
> 
>  static int invalidation_fence_init(struct xe_gt *gt,
>  				   struct invalidation_fence *ifence,
>  				   struct dma_fence *fence,
> -				   struct xe_vma *vma)
> +				   u64 start, u64 end, u32 asid)
>  {
>  	int ret;
> 
> @@ -1144,7 +1147,9 @@ static int invalidation_fence_init(struct xe_gt *gt,
>  	dma_fence_get(&ifence->base.base);	/* Ref for caller */
>  	ifence->fence = fence;
>  	ifence->gt = gt;
> -	ifence->vma = vma;
> +	ifence->start = start;
> +	ifence->end = end;
> +	ifence->asid = asid;
> 
>  	INIT_WORK(&ifence->work, invalidation_fence_work_func);
>  	ret = dma_fence_add_callback(fence, &ifence->cb,
> invalidation_fence_cb);
> @@ -1286,8 +1291,11 @@ __xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma
> *vma, struct xe_exec_queue
> 
>  		/* TLB invalidation must be done before signaling rebind */
>  		if (ifence) {
> -			int err = invalidation_fence_init(tile->primary_gt, ifence,
> fence,
> -							  vma);
> +			int err = invalidation_fence_init(tile->primary_gt,
> +							  ifence, fence,
> +							  xe_vma_start(vma),
> +							  xe_vma_end(vma),
> +							  xe_vma_vm(vma)-
> >usm.asid);
>  			if (err) {
>  				dma_fence_put(fence);
>  				kfree(ifence);
> @@ -1625,7 +1633,10 @@ __xe_pt_unbind_vma(struct xe_tile *tile, struct
> xe_vma *vma, struct xe_exec_queu
>  			dma_fence_wait(fence, false);
> 
>  		/* TLB invalidation must be done before signaling unbind */
> -		err = invalidation_fence_init(tile->primary_gt, ifence, fence,
> vma);
> +		err = invalidation_fence_init(tile->primary_gt, ifence, fence,
> +					      xe_vma_start(vma),
> +					      xe_vma_end(vma),
> +					      xe_vma_vm(vma)->usm.asid);
>  		if (err) {
>  			dma_fence_put(fence);
>  			kfree(ifence);
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 15/30] drm/xe: Add xe_vm_pgtable_update_op to xe_vma_ops
  2024-03-08  5:07 ` [PATCH v4 15/30] drm/xe: Add xe_vm_pgtable_update_op to xe_vma_ops Matthew Brost
@ 2024-03-25 21:58   ` Zeng, Oak
  2024-03-26 19:05     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-25 21:58 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew



> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 15/30] drm/xe: Add xe_vm_pgtable_update_op to
> xe_vma_ops
> 
> Will help with the converstion to 1 job per VM bind IOCTL. Allocation
> only implemented in this patch.


Can you explain why you need to introduce pt_update_op? this patch seems only allocate some slot for pt_update_op but they are not really used for page table update. I will keep looking the rest of this series. 

I also don't get why this helps 1job/bind ioctl.


Oak

> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_pt_types.h | 12 ++++++
>  drivers/gpu/drm/xe/xe_vm.c       | 66 +++++++++++++++++++++++++++++---
>  drivers/gpu/drm/xe/xe_vm_types.h |  8 ++++
>  3 files changed, 81 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_pt_types.h
> b/drivers/gpu/drm/xe/xe_pt_types.h
> index cee70cb0f014..2093150f461e 100644
> --- a/drivers/gpu/drm/xe/xe_pt_types.h
> +++ b/drivers/gpu/drm/xe/xe_pt_types.h
> @@ -74,4 +74,16 @@ struct xe_vm_pgtable_update {
>  	u32 flags;
>  };
> 
> +/** struct xe_vm_pgtable_update_op - Page table update operation */
> +struct xe_vm_pgtable_update_op {
> +	/** @entries: entries to update for this operation */
> +	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
> +	/** @num_entries: number of entries for this update operation */
> +	u32 num_entries;
> +	/** @bind: is a bind */
> +	bool bind;
> +	/** @rebind: is a rebind */
> +	bool rebind;
> +};
> +
>  #endif
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 5b93c71fc5e9..72e9bdab79d5 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -1319,6 +1319,42 @@ static void xe_vma_ops_init(struct xe_vma_ops *vops,
> struct xe_vm *vm,
>  	vops->num_syncs = num_syncs;
>  }
> 
> +static int xe_vma_ops_alloc(struct xe_vma_ops *vops)
> +{
> +	int i;
> +
> +	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) {
> +		if (!vops->pt_update_ops[i].num_ops)
> +			continue;
> +
> +		vops->pt_update_ops[i].ops =
> +			kmalloc_array(vops->pt_update_ops[i].num_ops,
> +				      sizeof(*vops->pt_update_ops[i].ops),
> +				      GFP_KERNEL);
> +		if (!vops->pt_update_ops[i].ops)
> +			return -ENOMEM;
> +	}
> +
> +	return 0;
> +}
> +
> +static void xe_vma_ops_fini(struct xe_vma_ops *vops)
> +{
> +	int i;
> +
> +	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i)
> +		kfree(vops->pt_update_ops[i].ops);
> +}
> +
> +static void xe_vma_ops_incr_pt_update_ops(struct xe_vma_ops *vops, u8
> tile_mask)
> +{
> +	int i;
> +
> +	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i)
> +		if (BIT(i) & tile_mask)
> +			++vops->pt_update_ops[i].num_ops;
> +}
> +
>  struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
>  {
>  	struct drm_gem_object *vm_resv_obj;
> @@ -1343,6 +1379,11 @@ struct xe_vm *xe_vm_create(struct xe_device *xe,
> u32 flags)
>  	xe_vma_ops_init(&vm->dummy_ops.vops, vm, NULL, NULL, 0);
>  	INIT_LIST_HEAD(&vm->dummy_ops.op.link);
>  	list_add(&vm->dummy_ops.op.link, &vm->dummy_ops.vops.list);
> +	for (id = 0; id < XE_MAX_TILES_PER_DEVICE; ++id)
> +		vm->dummy_ops.vops.pt_update_ops[id].num_ops = 1;
> +	err = xe_vma_ops_alloc(&vm->dummy_ops.vops);
> +	if (err)
> +		goto err_free;
> 
>  	INIT_LIST_HEAD(&vm->rebind_list);
> 
> @@ -1468,12 +1509,14 @@ struct xe_vm *xe_vm_create(struct xe_device *xe,
> u32 flags)
>  	return ERR_PTR(err);
> 
>  err_no_resv:
> -	mutex_destroy(&vm->snap_mutex);
> +	if (!(flags & XE_VM_FLAG_MIGRATION))
> +		xe_device_mem_access_put(xe);
>  	for_each_tile(tile, xe, id)
>  		xe_range_fence_tree_fini(&vm->rftree[id]);
> +err_free:
> +	mutex_destroy(&vm->snap_mutex);
> +	xe_vma_ops_fini(&vm->dummy_ops.vops);
>  	kfree(vm);
> -	if (!(flags & XE_VM_FLAG_MIGRATION))
> -		xe_device_mem_access_put(xe);
>  	return ERR_PTR(err);
>  }
> 
> @@ -1611,6 +1654,7 @@ static void vm_destroy_work_func(struct work_struct
> *w)
> 
>  	trace_xe_vm_free(vm);
>  	dma_fence_put(vm->rebind_fence);
> +	xe_vma_ops_fini(&vm->dummy_ops.vops);
>  	kfree(vm);
>  }
> 
> @@ -2284,7 +2328,6 @@ static int xe_vma_op_commit(struct xe_vm *vm, struct
> xe_vma_op *op)
>  	return err;
>  }
> 
> -
>  static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
>  				   struct drm_gpuva_ops *ops,
>  				   struct xe_sync_entry *syncs, u32 num_syncs,
> @@ -2334,6 +2377,9 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm,
> struct xe_exec_queue *q,
>  				return PTR_ERR(vma);
> 
>  			op->map.vma = vma;
> +			if (op->map.immediate || !xe_vm_in_fault_mode(vm))
> +				xe_vma_ops_incr_pt_update_ops(vops,
> +							      op->tile_mask);
>  			break;
>  		}
>  		case DRM_GPUVA_OP_REMAP:
> @@ -2378,6 +2424,8 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm,
> struct xe_exec_queue *q,
>  					vm_dbg(&xe->drm, "REMAP:SKIP_PREV:
> addr=0x%016llx, range=0x%016llx",
>  					       (ULL)op->remap.start,
>  					       (ULL)op->remap.range);
> +				} else {
> +					xe_vma_ops_incr_pt_update_ops(vops,
> op->tile_mask);
>  				}
>  			}
> 
> @@ -2414,13 +2462,16 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> *vm, struct xe_exec_queue *q,
>  					vm_dbg(&xe->drm, "REMAP:SKIP_NEXT:
> addr=0x%016llx, range=0x%016llx",
>  					       (ULL)op->remap.start,
>  					       (ULL)op->remap.range);
> +				} else {
> +					xe_vma_ops_incr_pt_update_ops(vops,
> op->tile_mask);
>  				}
>  			}
> +			xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask);
>  			break;
>  		}
>  		case DRM_GPUVA_OP_UNMAP:
>  		case DRM_GPUVA_OP_PREFETCH:
> -			/* Nothing to do */
> +			xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask);
>  			break;
>  		default:
>  			drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> @@ -3243,11 +3294,16 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void
> *data, struct drm_file *file)
>  		goto unwind_ops;
>  	}
> 
> +	err = xe_vma_ops_alloc(&vops);
> +	if (err)
> +		goto unwind_ops;
> +
>  	err = vm_bind_ioctl_ops_execute(vm, &vops);
> 
>  unwind_ops:
>  	if (err && err != -ENODATA)
>  		vm_bind_ioctl_ops_unwind(vm, ops, args->num_binds);
> +	xe_vma_ops_fini(&vops);
>  	for (i = args->num_binds - 1; i >= 0; --i)
>  		if (ops[i])
>  			drm_gpuva_ops_free(&vm->gpuvm, ops[i]);
> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> b/drivers/gpu/drm/xe/xe_vm_types.h
> index f6ea4df64e79..f5d740dcbba3 100644
> --- a/drivers/gpu/drm/xe/xe_vm_types.h
> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> @@ -22,6 +22,7 @@ struct xe_device;
>  struct xe_sync_entry;
>  struct xe_user_fence;
>  struct xe_vm;
> +struct xe_vm_pgtable_update_op;
> 
>  #define XE_VMA_READ_ONLY	DRM_GPUVA_USERBITS
>  #define XE_VMA_DESTROYED	(DRM_GPUVA_USERBITS << 1)
> @@ -219,6 +220,13 @@ struct xe_vma_ops {
>  	struct xe_sync_entry *syncs;
>  	/** @num_syncs: number of syncs */
>  	u32 num_syncs;
> +	/** @pt_update_ops: page table update operations */
> +	struct {
> +		/** @ops: operations */
> +		struct xe_vm_pgtable_update_op *ops;
> +		/** @num_ops: number of operations */
> +		u32 num_ops;
> +	} pt_update_ops[XE_MAX_TILES_PER_DEVICE];
>  };
> 
>  struct xe_vm {
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 16/30] drm/xe: Use ordered WQ for TLB invalidation fences
  2024-03-08  5:07 ` [PATCH v4 16/30] drm/xe: Use ordered WQ for TLB invalidation fences Matthew Brost
@ 2024-03-25 22:30   ` Zeng, Oak
  2024-03-26 19:10     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-25 22:30 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew



> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 16/30] drm/xe: Use ordered WQ for TLB invalidation fences
> 
> TLB invalidation fences need to be ordered within an exec queue and if
> an unordered WQ is used TLB invalidation fences could be reordered. Use
> an ordered WQ to fix this.


The code change below makes sense to me. But I think we should improve the description. I think we need to explain what need to be in order and why. As I understand it, we need things to be in below order (just an example):
1)Gpu page table update (such as invalidate certain page table)
2)Invalidate tlb entries for above page table entries
3)Notify/call back to user fence to let user know above vm_unbind is complete.

Obviously 1) and 2) can't be re-ordered, because 2) should be triggered by 1). But 2) and 3) can be reordered if we use unordered WQ - why we want to use ordered wq here.

Simply saying TLB invalidation fences need to be ordered is too simple, at least it is hard for me to understand. Better to improve it.

Thanks,
Oak

> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_pt.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> index 110d6917089b..a878e2217c7f 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -1107,7 +1107,7 @@ static void invalidation_fence_cb(struct dma_fence
> *fence,
> 
>  	trace_xe_gt_tlb_invalidation_fence_cb(&ifence->base);
>  	if (!ifence->fence->error) {
> -		queue_work(system_wq, &ifence->work);
> +		queue_work(ifence->gt->ordered_wq, &ifence->work);
>  	} else {
>  		ifence->base.base.error = ifence->fence->error;
>  		dma_fence_signal(&ifence->base.base);
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 17/30] drm/xe: Delete PT update selftest
  2024-03-08  5:07 ` [PATCH v4 17/30] drm/xe: Delete PT update selftest Matthew Brost
@ 2024-03-25 22:31   ` Zeng, Oak
  0 siblings, 0 replies; 76+ messages in thread
From: Zeng, Oak @ 2024-03-25 22:31 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew

Agree. Patch is reviewed-by: Oak Zeng <oak.zeng@intel.com>

> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 17/30] drm/xe: Delete PT update selftest
> 
> IGTs (e.g. xe_vm) can provide the exact same coverage as the PT update
> selftest. The PT update selftest is dependent on internal functions
> which can change thus maintaining this test is costly and provide no
> extra coverage. Delete this test.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/tests/xe_migrate.c | 86 ---------------------------
>  1 file changed, 86 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/tests/xe_migrate.c
> b/drivers/gpu/drm/xe/tests/xe_migrate.c
> index ce531498f57f..de2c1b7ec371 100644
> --- a/drivers/gpu/drm/xe/tests/xe_migrate.c
> +++ b/drivers/gpu/drm/xe/tests/xe_migrate.c
> @@ -62,36 +62,6 @@ static int run_sanity_job(struct xe_migrate *m, struct
> xe_device *xe,
>  	return 0;
>  }
> 
> -static void
> -sanity_populate_cb(struct xe_migrate_pt_update *pt_update,
> -		   struct xe_tile *tile, struct iosys_map *map, void *dst,
> -		   u32 qword_ofs, u32 num_qwords,
> -		   const struct xe_vm_pgtable_update *update)
> -{
> -	struct migrate_test_params *p =
> -
> 	to_migrate_test_params(xe_cur_kunit_priv(XE_TEST_LIVE_MIGRATE));
> -	int i;
> -	u64 *ptr = dst;
> -	u64 value;
> -
> -	for (i = 0; i < num_qwords; i++) {
> -		value = (qword_ofs + i - update->ofs) * 0x1111111111111111ULL;
> -		if (map)
> -			xe_map_wr(tile_to_xe(tile), map, (qword_ofs + i) *
> -				  sizeof(u64), u64, value);
> -		else
> -			ptr[i] = value;
> -	}
> -
> -	kunit_info(xe_cur_kunit(), "Used %s.\n", map ? "CPU" : "GPU");
> -	if (p->force_gpu && map)
> -		KUNIT_FAIL(xe_cur_kunit(), "GPU pagetable update used
> CPU.\n");
> -}
> -
> -static const struct xe_migrate_pt_update_ops sanity_ops = {
> -	.populate = sanity_populate_cb,
> -};
> -
>  #define check(_retval, _expected, str, _test)				\
>  	do { if ((_retval) != (_expected)) {				\
>  			KUNIT_FAIL(_test, "Sanity check failed: " str	\
> @@ -209,57 +179,6 @@ static void test_copy_vram(struct xe_migrate *m, struct
> xe_bo *bo,
>  	test_copy(m, bo, test, region);
>  }
> 
> -static void test_pt_update(struct xe_migrate *m, struct xe_bo *pt,
> -			   struct kunit *test, bool force_gpu)
> -{
> -	struct xe_device *xe = tile_to_xe(m->tile);
> -	struct dma_fence *fence;
> -	u64 retval, expected;
> -	ktime_t then, now;
> -	int i;
> -
> -	struct xe_vm_pgtable_update update = {
> -		.ofs = 1,
> -		.qwords = 0x10,
> -		.pt_bo = pt,
> -	};
> -	struct xe_migrate_pt_update pt_update = {
> -		.ops = &sanity_ops,
> -	};
> -	struct migrate_test_params p = {
> -		.base.id = XE_TEST_LIVE_MIGRATE,
> -		.force_gpu = force_gpu,
> -	};
> -
> -	test->priv = &p;
> -	/* Test xe_migrate_update_pgtables() updates the pagetable as
> expected */
> -	expected = 0xf0f0f0f0f0f0f0f0ULL;
> -	xe_map_memset(xe, &pt->vmap, 0, (u8)expected, pt->size);
> -
> -	then = ktime_get();
> -	fence = xe_migrate_update_pgtables(m, m->q->vm, NULL, m->q,
> &update, 1,
> -					   NULL, 0, &pt_update);
> -	now = ktime_get();
> -	if (sanity_fence_failed(xe, fence, "Migration pagetable update", test))
> -		return;
> -
> -	kunit_info(test, "Updating without syncing took %llu us,\n",
> -		   (unsigned long long)ktime_to_us(ktime_sub(now, then)));
> -
> -	dma_fence_put(fence);
> -	retval = xe_map_rd(xe, &pt->vmap, 0, u64);
> -	check(retval, expected, "PTE[0] must stay untouched", test);
> -
> -	for (i = 0; i < update.qwords; i++) {
> -		retval = xe_map_rd(xe, &pt->vmap, (update.ofs + i) * 8, u64);
> -		check(retval, i * 0x1111111111111111ULL, "PTE update", test);
> -	}
> -
> -	retval = xe_map_rd(xe, &pt->vmap, 8 * (update.ofs + update.qwords),
> -			   u64);
> -	check(retval, expected, "PTE[0x11] must stay untouched", test);
> -}
> -
>  static void xe_migrate_sanity_test(struct xe_migrate *m, struct kunit *test)
>  {
>  	struct xe_tile *tile = m->tile;
> @@ -398,11 +317,6 @@ static void xe_migrate_sanity_test(struct xe_migrate *m,
> struct kunit *test)
>  		test_copy_vram(m, big, test);
>  	}
> 
> -	kunit_info(test, "Testing page table update using CPU if GPU idle.\n");
> -	test_pt_update(m, pt, test, false);
> -	kunit_info(test, "Testing page table update using GPU\n");
> -	test_pt_update(m, pt, test, true);
> -
>  out:
>  	xe_bb_free(bb, NULL);
>  free_tiny:
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 06/30] drm/xe: Simplify VM bind IOCTL error handling and cleanup
  2024-03-25 16:03   ` Zeng, Oak
@ 2024-03-26 18:46     ` Matthew Brost
  0 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-26 18:46 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Mon, Mar 25, 2024 at 10:03:27AM -0600, Zeng, Oak wrote:
> Hi Matt,
> 
> This looks like a nice clean up to me. See one comment inline.
> 
> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 06/30] drm/xe: Simplify VM bind IOCTL error handling and
> > cleanup
> > 
> > Clean up everything in VM bind IOCTL in 1 path for both errors and
> > non-errors. Also move VM bind IOCTL cleanup from ops (also used by
> > non-IOCTL binds) to the VM bind IOCTL.
> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_vm.c       | 60 +++++---------------------------
> >  drivers/gpu/drm/xe/xe_vm_types.h |  5 ---
> >  2 files changed, 9 insertions(+), 56 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index 0bb807c05d7b..dde777c807cf 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -769,8 +769,7 @@ static void xe_vm_populate_dummy_rebind(struct
> > xe_vm *vm, struct xe_vma *vma)
> >  }
> > 
> >  static struct dma_fence *ops_execute(struct xe_vm *vm,
> > -				     struct xe_vma_ops *vops,
> > -				     bool cleanup);
> > +				     struct xe_vma_ops *vops);
> > 
> >  struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
> >  {
> > @@ -794,7 +793,7 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm,
> > bool rebind_worker)
> >  			trace_xe_vma_rebind_exec(vma);
> > 
> >  		xe_vm_populate_dummy_rebind(vm, vma);
> > -		fence = ops_execute(vm, &vm->dummy_ops.vops, false);
> > +		fence = ops_execute(vm, &vm->dummy_ops.vops);
> >  		if (IS_ERR(fence))
> >  			return fence;
> >  	}
> > @@ -2474,7 +2473,6 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm,
> > struct xe_exec_queue *q,
> >  	if (!last_op)
> >  		return 0;
> > 
> > -	last_op->ops = ops;
> >  	if (last) {
> >  		last_op->flags |= XE_VMA_OP_LAST;
> >  		last_op->num_syncs = num_syncs;
> > @@ -2643,25 +2641,6 @@ xe_vma_op_execute(struct xe_vm *vm, struct
> > xe_vma_op *op)
> >  	return fence;
> >  }
> > 
> > -static void xe_vma_op_cleanup(struct xe_vm *vm, struct xe_vma_op *op)
> > -{
> > -	bool last = op->flags & XE_VMA_OP_LAST;
> > -
> > -	if (last) {
> > -		while (op->num_syncs--)
> > -			xe_sync_entry_cleanup(&op->syncs[op->num_syncs]);
> > -		kfree(op->syncs);
> > -		if (op->q)
> > -			xe_exec_queue_put(op->q);
> > -	}
> > -	if (!list_empty(&op->link))
> > -		list_del(&op->link);
> > -	if (op->ops)
> > -		drm_gpuva_ops_free(&vm->gpuvm, op->ops);
> > -	if (last)
> > -		xe_vm_put(vm);
> > -}
> > -
> >  static void xe_vma_op_unwind(struct xe_vm *vm, struct xe_vma_op *op,
> >  			     bool post_commit, bool prev_post_commit,
> >  			     bool next_post_commit)
> > @@ -2738,8 +2717,6 @@ static void vm_bind_ioctl_ops_unwind(struct xe_vm
> > *vm,
> >  					 op->flags &
> > XE_VMA_OP_PREV_COMMITTED,
> >  					 op->flags &
> > XE_VMA_OP_NEXT_COMMITTED);
> >  		}
> > -
> > -		drm_gpuva_ops_free(&vm->gpuvm, __ops);
> >  	}
> >  }
> > 
> > @@ -2818,8 +2795,7 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec
> > *exec,
> >  }
> > 
> >  static struct dma_fence *ops_execute(struct xe_vm *vm,
> > -				     struct xe_vma_ops *vops,
> > -				     bool cleanup)
> > +				     struct xe_vma_ops *vops)
> >  {
> >  	struct xe_vma_op *op, *next;
> >  	struct dma_fence *fence = NULL;
> > @@ -2834,8 +2810,6 @@ static struct dma_fence *ops_execute(struct xe_vm
> > *vm,
> >  				 op->base.op, PTR_ERR(fence));
> >  			fence = ERR_PTR(-ENOSPC);
> >  		}
> > -		if (cleanup)
> > -			xe_vma_op_cleanup(vm, op);
> 
> 
> Now with this cleanup code removed, do you still want to loop all the ops in the list when xe_vma_op_execute failed with error? Should we break and return earlier in this case?
> 

Yes, this loop gets rewritten in patch #18 but for this patch to be
correct, lets break the loop on error.

Matt

> Oak
> 
> >  	}
> > 
> >  	return fence;
> > @@ -2858,7 +2832,7 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm
> > *vm,
> >  		if (err)
> >  			goto unlock;
> > 
> > -		fence = ops_execute(vm, vops, true);
> > +		fence = ops_execute(vm, vops);
> >  		if (IS_ERR(fence)) {
> >  			err = PTR_ERR(fence);
> >  			/* FIXME: Killing VM rather than proper error handling */
> > @@ -3211,30 +3185,14 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void
> > *data, struct drm_file *file)
> >  		goto unwind_ops;
> >  	}
> > 
> > -	xe_vm_get(vm);
> > -	if (q)
> > -		xe_exec_queue_get(q);
> > -
> >  	err = vm_bind_ioctl_ops_execute(vm, &vops);
> > 
> > -	up_write(&vm->lock);
> > -
> > -	if (q)
> > -		xe_exec_queue_put(q);
> > -	xe_vm_put(vm);
> > -
> > -	for (i = 0; bos && i < args->num_binds; ++i)
> > -		xe_bo_put(bos[i]);
> > -
> > -	kvfree(bos);
> > -	kvfree(ops);
> > -	if (args->num_binds > 1)
> > -		kvfree(bind_ops);
> > -
> > -	return err;
> > -
> >  unwind_ops:
> > -	vm_bind_ioctl_ops_unwind(vm, ops, args->num_binds);
> > +	if (err && err != -ENODATA)
> > +		vm_bind_ioctl_ops_unwind(vm, ops, args->num_binds);
> > +	for (i = args->num_binds - 1; i >= 0; --i)
> > +		if (ops[i])
> > +			drm_gpuva_ops_free(&vm->gpuvm, ops[i]);
> >  free_syncs:
> >  	if (err == -ENODATA)
> >  		err = vm_bind_ioctl_signal_fences(vm, q, syncs, num_syncs);
> > diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> > b/drivers/gpu/drm/xe/xe_vm_types.h
> > index 7ef9e632154a..f097fe318a74 100644
> > --- a/drivers/gpu/drm/xe/xe_vm_types.h
> > +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> > @@ -181,11 +181,6 @@ enum xe_vma_op_flags {
> >  struct xe_vma_op {
> >  	/** @base: GPUVA base operation */
> >  	struct drm_gpuva_op base;
> > -	/**
> > -	 * @ops: GPUVA ops, when set call drm_gpuva_ops_free after this
> > -	 * operations is processed
> > -	 */
> > -	struct drm_gpuva_ops *ops;
> >  	/** @q: exec queue for this operation */
> >  	struct xe_exec_queue *q;
> >  	/**
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 09/30] drm/xe: Add some members to xe_vma_ops
  2024-03-25 16:10   ` Zeng, Oak
@ 2024-03-26 18:47     ` Matthew Brost
  0 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-26 18:47 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Mon, Mar 25, 2024 at 10:10:43AM -0600, Zeng, Oak wrote:
> 
> 
> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 09/30] drm/xe: Add some members to xe_vma_ops
> > 
> > This will help with moving to single jobs for many bind operations.
> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_vm.c       | 13 ++++++++++---
> >  drivers/gpu/drm/xe/xe_vm_types.h |  8 ++++++++
> >  2 files changed, 18 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index a6bae2f5e296..f8b27746e5a7 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -1307,9 +1307,16 @@ static void xe_vm_free_scratch(struct xe_vm *vm)
> >  	}
> >  }
> > 
> > -static void xe_vma_ops_init(struct xe_vma_ops *vops)
> > +static void xe_vma_ops_init(struct xe_vma_ops *vops, struct xe_vm *vm,
> > +			    struct xe_exec_queue *q,
> > +			    struct xe_sync_entry *syncs, u32 num_syncs)
> >  {
> > +	memset(vops, 0, sizeof(*vops));
> >  	INIT_LIST_HEAD(&vops->list);
> > +	vops->vm = vm;
> > +	vops->q = q;
> > +	vops->syncs = syncs;
> > +	vops->num_syncs = num_syncs;
> >  }
> > 
> >  struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
> > @@ -1333,7 +1340,7 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32
> > flags)
> >  	init_rwsem(&vm->lock);
> >  	mutex_init(&vm->snap_mutex);
> > 
> > -	xe_vma_ops_init(&vm->dummy_ops.vops);
> > +	xe_vma_ops_init(&vm->dummy_ops.vops, vm, NULL, NULL, 0);
> 
> 
> You mentioned in previous review, that vm->dummy_ops will be dropped... I guess this line will also be dropped.
> 

Yes, will drop the dummy ops.

Matt

> Otherwise, this patch looks good to me.
> 
> Oak
> 
> >  	INIT_LIST_HEAD(&vm->dummy_ops.op.link);
> >  	list_add(&vm->dummy_ops.op.link, &vm->dummy_ops.vops.list);
> > 
> > @@ -3176,7 +3183,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void
> > *data, struct drm_file *file)
> >  		goto free_syncs;
> >  	}
> > 
> > -	xe_vma_ops_init(&vops);
> > +	xe_vma_ops_init(&vops, vm, q, syncs, num_syncs);
> >  	for (i = 0; i < args->num_binds; ++i) {
> >  		u64 range = bind_ops[i].range;
> >  		u64 addr = bind_ops[i].addr;
> > diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> > b/drivers/gpu/drm/xe/xe_vm_types.h
> > index 0bba5543ac28..f6ea4df64e79 100644
> > --- a/drivers/gpu/drm/xe/xe_vm_types.h
> > +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> > @@ -211,6 +211,14 @@ struct xe_vma_op {
> >  struct xe_vma_ops {
> >  	/** @list: list of VMA operations */
> >  	struct list_head list;
> > +	/** @vm: VM */
> > +	struct xe_vm *vm;
> > +	/** @q: exec queue these operations */
> > +	struct xe_exec_queue *q;
> > +	/** @syncs: syncs these operation */
> > +	struct xe_sync_entry *syncs;
> > +	/** @num_syncs: number of syncs */
> > +	u32 num_syncs;
> >  };
> > 
> >  struct xe_vm {
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 12/30] drm/xe: Move ufence check to op_lock
  2024-03-25 20:37   ` Zeng, Oak
@ 2024-03-26 18:49     ` Matthew Brost
  0 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-26 18:49 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Mon, Mar 25, 2024 at 02:37:28PM -0600, Zeng, Oak wrote:
> Patch makes sense to me. See one comment inline
> 
> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 12/30] drm/xe: Move ufence check to op_lock
> > 
> > Rather than checking for an unsignaled ufence ay unbind time, check for
> > this during the op_lock function. This will help with the transition to
> > job 1 per VM bind IOCTL.
> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_vm.c | 33 +++++++++++++++++++++++----------
> >  1 file changed, 23 insertions(+), 10 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index 4432531f39fe..5767955529dd 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -1665,16 +1665,6 @@ xe_vm_unbind_vma(struct xe_vma *vma, struct
> > xe_exec_queue *q,
> > 
> >  	trace_xe_vma_unbind(vma);
> > 
> > -	if (vma->ufence) {
> > -		struct xe_user_fence * const f = vma->ufence;
> > -
> > -		if (!xe_sync_ufence_get_status(f))
> > -			return ERR_PTR(-EBUSY);
> > -
> > -		vma->ufence = NULL;
> > -		xe_sync_ufence_put(f);
> > -	}
> > -
> >  	if (number_tiles > 1) {
> >  		fences = kmalloc_array(number_tiles, sizeof(*fences),
> >  				       GFP_KERNEL);
> > @@ -2721,6 +2711,21 @@ static int vma_lock(struct drm_exec *exec, struct
> > xe_vma *vma, bool validate)
> >  	return err;
> >  }
> > 
> > +static int check_ufence(struct xe_vma *vma)
> > +{
> > +	if (vma->ufence) {
> > +		struct xe_user_fence * const f = vma->ufence;
> > +
> > +		if (!xe_sync_ufence_get_status(f))
> > +			return -EBUSY;
> > +
> > +		vma->ufence = NULL;
> > +		xe_sync_ufence_put(f);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  static int op_lock(struct drm_exec *exec, struct xe_vm *vm,
> >  		   struct xe_vma_op *op)
> >  {
> > @@ -2731,6 +2736,10 @@ static int op_lock(struct drm_exec *exec, struct xe_vm
> > *vm,
> >  		err = vma_lock(exec, op-
> > >map.vma, !xe_vm_in_fault_mode(vm));
> >  		break;
> >  	case DRM_GPUVA_OP_REMAP:
> > +		err = check_ufence(gpuva_to_vma(op->base.remap.unmap-
> > >va));
> 
> This is another reason we need to rename op_lock...
> 

Agree.

Matt

> Oak
> 
> > +		if (err)
> > +			break;
> > +
> >  		err = vma_lock(exec, gpuva_to_vma(op->base.remap.unmap-
> > >va),
> >  			       false);
> >  		if (!err && op->remap.prev)
> > @@ -2739,6 +2748,10 @@ static int op_lock(struct drm_exec *exec, struct xe_vm
> > *vm,
> >  			err = vma_lock(exec, op->remap.next, true);
> >  		break;
> >  	case DRM_GPUVA_OP_UNMAP:
> > +		err = check_ufence(gpuva_to_vma(op->base.unmap.va));
> > +		if (err)
> > +			break;
> > +
> >  		err = vma_lock(exec, gpuva_to_vma(op->base.unmap.va), false);
> >  		break;
> >  	case DRM_GPUVA_OP_PREFETCH:
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/30] drm/xe: Move ufence add to vm_bind_ioctl_ops_install_fences
  2024-03-25 20:54   ` Zeng, Oak
@ 2024-03-26 18:54     ` Matthew Brost
  2024-03-26 20:59       ` Zeng, Oak
  0 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-26 18:54 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Mon, Mar 25, 2024 at 02:54:44PM -0600, Zeng, Oak wrote:
> This patch makes sense to me. See two nit-pick inline
> 
> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 13/30] drm/xe: Move ufence add to
> > vm_bind_ioctl_ops_install_fences
> > 
> > Rather than adding a ufence to a VMA in the bind function, add the
> > ufence to all VMAs in the IOCTL that require binds in
> > vm_bind_ioctl_ops_install_fences. This will help with the transition to
> > job 1 per VM bind IOCTL.
> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_sync.c | 15 ++++++++++++
> >  drivers/gpu/drm/xe/xe_sync.h |  1 +
> >  drivers/gpu/drm/xe/xe_vm.c   | 44 ++++++++++++++++++++++++++++++------
> >  3 files changed, 53 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_sync.c b/drivers/gpu/drm/xe/xe_sync.c
> > index 02c9577fe418..07aa65d9bcab 100644
> > --- a/drivers/gpu/drm/xe/xe_sync.c
> > +++ b/drivers/gpu/drm/xe/xe_sync.c
> > @@ -343,6 +343,21 @@ xe_sync_in_fence_get(struct xe_sync_entry *sync, int
> > num_sync,
> >  	return ERR_PTR(-ENOMEM);
> >  }
> > 
> > +/**
> > + * __xe_sync_ufence_get() - Get user fence from user fence
> > + * @ufence: input user fence
> > + *
> > + * Get a user fence reference from user fence
> > + *
> > + * Return: xe_user_fence pointer with reference
> > + */
> > +struct xe_user_fence *__xe_sync_ufence_get(struct xe_user_fence *ufence)
> > +{
> > +	user_fence_get(ufence);
> > +
> > +	return ufence;
> > +}
> 
> I wonder why this is made part of xe_sync. Isn't just a ufence get function? Can we drop _sync_ from the function name?
> 
> 

Typically exported functions should have a prefix matching the header
file name.

e.g.

xe_sync.h -> all functions should start with xe_sync_*

In this case struct xe_user_fence is private date member to xe_sync.c
(only define in that C file) and just an opaque pointer to the rest of
the driver.

> > +
> >  /**
> >   * xe_sync_ufence_get() - Get user fence from sync
> >   * @sync: input sync
> > diff --git a/drivers/gpu/drm/xe/xe_sync.h b/drivers/gpu/drm/xe/xe_sync.h
> > index 0fd0d51208e6..26e9ec9de1a8 100644
> > --- a/drivers/gpu/drm/xe/xe_sync.h
> > +++ b/drivers/gpu/drm/xe/xe_sync.h
> > @@ -38,6 +38,7 @@ static inline bool xe_sync_is_ufence(struct xe_sync_entry
> > *sync)
> >  	return !!sync->ufence;
> >  }
> > 
> > +struct xe_user_fence *__xe_sync_ufence_get(struct xe_user_fence *ufence);
> >  struct xe_user_fence *xe_sync_ufence_get(struct xe_sync_entry *sync);
> >  void xe_sync_ufence_put(struct xe_user_fence *ufence);
> >  int xe_sync_ufence_get_status(struct xe_user_fence *ufence);
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index 5767955529dd..5b93c71fc5e9 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -1810,17 +1810,10 @@ xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma,
> > struct xe_exec_queue *q,
> >  {
> >  	struct dma_fence *fence;
> >  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > q);
> > -	struct xe_user_fence *ufence;
> > 
> >  	xe_vm_assert_held(vm);
> >  	xe_bo_assert_held(bo);
> > 
> > -	ufence = find_ufence_get(syncs, num_syncs);
> > -	if (vma->ufence && ufence)
> > -		xe_sync_ufence_put(vma->ufence);
> > -
> > -	vma->ufence = ufence ?: vma->ufence;
> > -
> >  	if (immediate) {
> >  		fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, tile_mask,
> >  				       first_op, last_op);
> > @@ -2822,21 +2815,58 @@ struct dma_fence *xe_vm_ops_execute(struct
> > xe_vm *vm, struct xe_vma_ops *vops)
> >  	return fence;
> >  }
> > 
> > +static void vma_add_ufence(struct xe_vma *vma, struct xe_user_fence
> > *ufence)
> > +{
> > +	if (vma->ufence)
> > +		xe_sync_ufence_put(vma->ufence);
> 
> Not sure where/when we introduced xe_sync_ufence_put, for me this can be renamed to xe_ufence_put
> 

See above, I think the naming is correct. All of this is a matter of
opinion, we don't have any offical style guidelines for Xe but we might
want to think about writing some up / fixing Xe to conform while the
driver is still relatively small.

Matt

> Oak
> 
> > +	vma->ufence = __xe_sync_ufence_get(ufence);
> > +}
> > +
> > +static void op_add_ufence(struct xe_vm *vm, struct xe_vma_op *op,
> > +			  struct xe_user_fence *ufence)
> > +{
> > +	switch (op->base.op) {
> > +	case DRM_GPUVA_OP_MAP:
> > +		vma_add_ufence(op->map.vma, ufence);
> > +		break;
> > +	case DRM_GPUVA_OP_REMAP:
> > +		if (op->remap.prev)
> > +			vma_add_ufence(op->remap.prev, ufence);
> > +		if (op->remap.next)
> > +			vma_add_ufence(op->remap.next, ufence);
> > +		break;
> > +	case DRM_GPUVA_OP_UNMAP:
> > +		break;
> > +	case DRM_GPUVA_OP_PREFETCH:
> > +		vma_add_ufence(gpuva_to_vma(op->base.prefetch.va),
> > ufence);
> > +		break;
> > +	default:
> > +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > +	}
> > +}
> > +
> >  static void vm_bind_ioctl_ops_install_fences(struct xe_vm *vm,
> >  					     struct xe_vma_ops *vops,
> >  					     struct dma_fence *fence)
> >  {
> >  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > vops->q);
> > +	struct xe_user_fence *ufence;
> >  	struct xe_vma_op *op;
> >  	int i;
> > 
> > +	ufence = find_ufence_get(vops->syncs, vops->num_syncs);
> >  	list_for_each_entry(op, &vops->list, link) {
> > +		if (ufence)
> > +			op_add_ufence(vm, op, ufence);
> > +
> >  		if (op->base.op == DRM_GPUVA_OP_UNMAP)
> >  			xe_vma_destroy(gpuva_to_vma(op->base.unmap.va),
> > fence);
> >  		else if (op->base.op == DRM_GPUVA_OP_REMAP)
> >  			xe_vma_destroy(gpuva_to_vma(op-
> > >base.remap.unmap->va),
> >  				       fence);
> >  	}
> > +	if (ufence)
> > +		xe_sync_ufence_put(ufence);
> >  	for (i = 0; i < vops->num_syncs; i++)
> >  		xe_sync_entry_signal(vops->syncs + i, NULL, fence);
> >  	xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 14/30] drm/xe: Add xe_gt_tlb_invalidation_range and convert PT layer to use this
  2024-03-25 21:35   ` Zeng, Oak
@ 2024-03-26 18:57     ` Matthew Brost
  0 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-26 18:57 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Mon, Mar 25, 2024 at 03:35:16PM -0600, Zeng, Oak wrote:
> Hi Matt,
> 
> Patch looks good to me. See one question inline
> 
> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 14/30] drm/xe: Add xe_gt_tlb_invalidation_range and
> > convert PT layer to use this
> > 
> > xe_gt_tlb_invalidation_range accepts a start and end address rather than
> > a VMA. This will enable multiple VMAs to be invalidated in a single
> > invalidation. Update the PT layer to use this new function.
> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c | 59 +++++++++++++++------
> >  drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h |  3 ++
> >  drivers/gpu/drm/xe/xe_pt.c                  | 25 ++++++---
> >  3 files changed, 65 insertions(+), 22 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
> > b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
> > index a3c4ffba679d..ac2bf86de39a 100644
> > --- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
> > +++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
> > @@ -264,11 +264,15 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt)
> >  }
> > 
> >  /**
> > - * xe_gt_tlb_invalidation_vma - Issue a TLB invalidation on this GT for a VMA
> > + * xe_gt_tlb_invalidation_range - Issue a TLB invalidation on this GT for an
> > + * address range
> > + *
> >   * @gt: graphics tile
> >   * @fence: invalidation fence which will be signal on TLB invalidation
> >   * completion, can be NULL
> > - * @vma: VMA to invalidate
> > + * @start: start address
> > + * @end: end address
> > + * @asid: address space id
> >   *
> >   * Issue a range based TLB invalidation if supported, if not fallback to a full
> >   * TLB invalidation. Completion of TLB is asynchronous and caller can either use
> > @@ -278,17 +282,15 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt)
> >   * Return: Seqno which can be passed to xe_gt_tlb_invalidation_wait on success,
> >   * negative error code on error.
> >   */
> > -int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
> > -			       struct xe_gt_tlb_invalidation_fence *fence,
> > -			       struct xe_vma *vma)
> > +int xe_gt_tlb_invalidation_range(struct xe_gt *gt,
> > +				 struct xe_gt_tlb_invalidation_fence *fence,
> > +				 u64 start, u64 end, u32 asid)
> >  {
> >  	struct xe_device *xe = gt_to_xe(gt);
> >  #define MAX_TLB_INVALIDATION_LEN	7
> >  	u32 action[MAX_TLB_INVALIDATION_LEN];
> >  	int len = 0;
> > 
> > -	xe_gt_assert(gt, vma);
> > -
> >  	/* Execlists not supported */
> >  	if (gt_to_xe(gt)->info.force_execlist) {
> >  		if (fence)
> > @@ -302,8 +304,8 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
> >  	if (!xe->info.has_range_tlb_invalidation) {
> >  		action[len++] = MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL);
> >  	} else {
> > -		u64 start = xe_vma_start(vma);
> > -		u64 length = xe_vma_size(vma);
> > +		u64 orig_start = start;
> > +		u64 length = end - start;
> >  		u64 align, end;
> > 
> >  		if (length < SZ_4K)
> > @@ -316,12 +318,12 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
> >  		 * address mask covering the required range.
> >  		 */
> >  		align = roundup_pow_of_two(length);
> > -		start = ALIGN_DOWN(xe_vma_start(vma), align);
> > -		end = ALIGN(xe_vma_end(vma), align);
> > +		start = ALIGN_DOWN(start, align);
> > +		end = ALIGN(end, align);
> >  		length = align;
> >  		while (start + length < end) {
> >  			length <<= 1;
> > -			start = ALIGN_DOWN(xe_vma_start(vma), length);
> > +			start = ALIGN_DOWN(orig_start, length);
> >  		}
> > 
> >  		/*
> > @@ -330,16 +332,17 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
> >  		 */
> >  		if (length >= SZ_2M) {
> >  			length = max_t(u64, SZ_16M, length);
> > -			start = ALIGN_DOWN(xe_vma_start(vma), length);
> > +			start = ALIGN_DOWN(orig_start, length);
> >  		}
> > 
> >  		xe_gt_assert(gt, length >= SZ_4K);
> >  		xe_gt_assert(gt, is_power_of_2(length));
> > -		xe_gt_assert(gt, !(length & GENMASK(ilog2(SZ_16M) - 1,
> > ilog2(SZ_2M) + 1)));
> > +		xe_gt_assert(gt, !(length & GENMASK(ilog2(SZ_16M) - 1,
> > +						    ilog2(SZ_2M) + 1)));
> >  		xe_gt_assert(gt, IS_ALIGNED(start, length));
> > 
> >  		action[len++] =
> > MAKE_INVAL_OP(XE_GUC_TLB_INVAL_PAGE_SELECTIVE);
> > -		action[len++] = xe_vma_vm(vma)->usm.asid;
> > +		action[len++] = asid;
> >  		action[len++] = lower_32_bits(start);
> >  		action[len++] = upper_32_bits(start);
> >  		action[len++] = ilog2(length) - ilog2(SZ_4K);
> > @@ -350,6 +353,32 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
> >  	return send_tlb_invalidation(&gt->uc.guc, fence, action, len);
> >  }
> > 
> > +/**
> > + * xe_gt_tlb_invalidation_vma - Issue a TLB invalidation on this GT for a VMA
> > + * @gt: graphics tile
> > + * @fence: invalidation fence which will be signal on TLB invalidation
> > + * completion, can be NULL
> > + * @vma: VMA to invalidate
> > + *
> > + * Issue a range based TLB invalidation if supported, if not fallback to a full
> > + * TLB invalidation. Completion of TLB is asynchronous and caller can either use
> > + * the invalidation fence or seqno + xe_gt_tlb_invalidation_wait to wait for
> > + * completion.
> > + *
> > + * Return: Seqno which can be passed to xe_gt_tlb_invalidation_wait on success,
> > + * negative error code on error.
> > + */
> > +int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
> > +			       struct xe_gt_tlb_invalidation_fence *fence,
> > +			       struct xe_vma *vma)
> > +{
> > +	xe_gt_assert(gt, vma);
> > +
> > +	return xe_gt_tlb_invalidation_range(gt, fence, xe_vma_start(vma),
> > +					    xe_vma_end(vma),
> > +					    xe_vma_vm(vma)->usm.asid);
> > +}
> > +
> >  /**
> >   * xe_gt_tlb_invalidation_wait - Wait for TLB to complete
> >   * @gt: graphics tile
> > diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
> > b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
> > index fbb743d80d2c..bf3bebd9f985 100644
> > --- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
> > +++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
> > @@ -20,6 +20,9 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt);
> >  int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
> >  			       struct xe_gt_tlb_invalidation_fence *fence,
> >  			       struct xe_vma *vma);
> > +int xe_gt_tlb_invalidation_range(struct xe_gt *gt,
> > +				 struct xe_gt_tlb_invalidation_fence *fence,
> > +				 u64 start, u64 end, u32 asid);
> >  int xe_gt_tlb_invalidation_wait(struct xe_gt *gt, int seqno);
> >  int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32
> > len);
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> > index 7f54bc3e389d..110d6917089b 100644
> > --- a/drivers/gpu/drm/xe/xe_pt.c
> > +++ b/drivers/gpu/drm/xe/xe_pt.c
> > @@ -1074,10 +1074,12 @@ static const struct xe_migrate_pt_update_ops
> > userptr_bind_ops = {
> >  struct invalidation_fence {
> >  	struct xe_gt_tlb_invalidation_fence base;
> >  	struct xe_gt *gt;
> > -	struct xe_vma *vma;
> >  	struct dma_fence *fence;
> >  	struct dma_fence_cb cb;
> >  	struct work_struct work;
> > +	u64 start;
> > +	u64 end;
> > +	u32 asid;
> 
> 
> I didn't see start/end/asid is used anywhere else, except in the below fence_init function... do we really need those members?
> 

Yes, see below.

> Oak
> 
> >  };
> > 
> >  static const char *
> > @@ -1120,13 +1122,14 @@ static void invalidation_fence_work_func(struct
> > work_struct *w)
> >  		container_of(w, struct invalidation_fence, work);
> > 
> >  	trace_xe_gt_tlb_invalidation_fence_work_func(&ifence->base);
> > -	xe_gt_tlb_invalidation_vma(ifence->gt, &ifence->base, ifence->vma);
> > +	xe_gt_tlb_invalidation_range(ifence->gt, &ifence->base, ifence->start,
> > +				     ifence->end, ifence->asid);

They are used right here ^^^

Matt

> >  }
> > 
> >  static int invalidation_fence_init(struct xe_gt *gt,
> >  				   struct invalidation_fence *ifence,
> >  				   struct dma_fence *fence,
> > -				   struct xe_vma *vma)
> > +				   u64 start, u64 end, u32 asid)
> >  {
> >  	int ret;
> > 
> > @@ -1144,7 +1147,9 @@ static int invalidation_fence_init(struct xe_gt *gt,
> >  	dma_fence_get(&ifence->base.base);	/* Ref for caller */
> >  	ifence->fence = fence;
> >  	ifence->gt = gt;
> > -	ifence->vma = vma;
> > +	ifence->start = start;
> > +	ifence->end = end;
> > +	ifence->asid = asid;
> > 
> >  	INIT_WORK(&ifence->work, invalidation_fence_work_func);
> >  	ret = dma_fence_add_callback(fence, &ifence->cb,
> > invalidation_fence_cb);
> > @@ -1286,8 +1291,11 @@ __xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma
> > *vma, struct xe_exec_queue
> > 
> >  		/* TLB invalidation must be done before signaling rebind */
> >  		if (ifence) {
> > -			int err = invalidation_fence_init(tile->primary_gt, ifence,
> > fence,
> > -							  vma);
> > +			int err = invalidation_fence_init(tile->primary_gt,
> > +							  ifence, fence,
> > +							  xe_vma_start(vma),
> > +							  xe_vma_end(vma),
> > +							  xe_vma_vm(vma)-
> > >usm.asid);
> >  			if (err) {
> >  				dma_fence_put(fence);
> >  				kfree(ifence);
> > @@ -1625,7 +1633,10 @@ __xe_pt_unbind_vma(struct xe_tile *tile, struct
> > xe_vma *vma, struct xe_exec_queu
> >  			dma_fence_wait(fence, false);
> > 
> >  		/* TLB invalidation must be done before signaling unbind */
> > -		err = invalidation_fence_init(tile->primary_gt, ifence, fence,
> > vma);
> > +		err = invalidation_fence_init(tile->primary_gt, ifence, fence,
> > +					      xe_vma_start(vma),
> > +					      xe_vma_end(vma),
> > +					      xe_vma_vm(vma)->usm.asid);
> >  		if (err) {
> >  			dma_fence_put(fence);
> >  			kfree(ifence);
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 15/30] drm/xe: Add xe_vm_pgtable_update_op to xe_vma_ops
  2024-03-25 21:58   ` Zeng, Oak
@ 2024-03-26 19:05     ` Matthew Brost
  2024-03-27  1:29       ` Zeng, Oak
  0 siblings, 1 reply; 76+ messages in thread
From: Matthew Brost @ 2024-03-26 19:05 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Mon, Mar 25, 2024 at 03:58:10PM -0600, Zeng, Oak wrote:
> 
> 
> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 15/30] drm/xe: Add xe_vm_pgtable_update_op to
> > xe_vma_ops
> > 
> > Will help with the converstion to 1 job per VM bind IOCTL. Allocation
> > only implemented in this patch.
> 
> 
> Can you explain why you need to introduce pt_update_op? this patch seems only allocate some slot for pt_update_op but they are not really used for page table update. I will keep looking the rest of this series. 
> 
> I also don't get why this helps 1job/bind ioctl.
> 

Each VMA operations is converted into 0-3 PT per ops tile. i.e. a MAP VMA
operations with immediate clear generates 0 PT ops, a REMAP VMA with
both prev & next generates 3 PT ops. PT ops work on the internal / GPU
PT state compared to VMA ops which operate on the internal GPUVM state.

The flow roughly is:

generate VMA ops from IOCTL input
convert all VMA ops to PT ops, prep and stage PT ops
run PT ops as an atomic unit (1 job)
commit PT ops
commit VMA ops

If at any point a failure occurs before the commit step the PT ops can
be unwound.

Likewise when a failure occurs the VMA ops are unwound too, this is just
layer above the PT ops.

In the end if an errors at point in the IOCTL the original GPUVM and PT
state is restored. This compared to serial execution on tip where is an
error occurs we just kill the VM.

Does this make sense?

Matt

> 
> Oak
> 
> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_pt_types.h | 12 ++++++
> >  drivers/gpu/drm/xe/xe_vm.c       | 66 +++++++++++++++++++++++++++++---
> >  drivers/gpu/drm/xe/xe_vm_types.h |  8 ++++
> >  3 files changed, 81 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_pt_types.h
> > b/drivers/gpu/drm/xe/xe_pt_types.h
> > index cee70cb0f014..2093150f461e 100644
> > --- a/drivers/gpu/drm/xe/xe_pt_types.h
> > +++ b/drivers/gpu/drm/xe/xe_pt_types.h
> > @@ -74,4 +74,16 @@ struct xe_vm_pgtable_update {
> >  	u32 flags;
> >  };
> > 
> > +/** struct xe_vm_pgtable_update_op - Page table update operation */
> > +struct xe_vm_pgtable_update_op {
> > +	/** @entries: entries to update for this operation */
> > +	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
> > +	/** @num_entries: number of entries for this update operation */
> > +	u32 num_entries;
> > +	/** @bind: is a bind */
> > +	bool bind;
> > +	/** @rebind: is a rebind */
> > +	bool rebind;
> > +};
> > +
> >  #endif
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index 5b93c71fc5e9..72e9bdab79d5 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -1319,6 +1319,42 @@ static void xe_vma_ops_init(struct xe_vma_ops *vops,
> > struct xe_vm *vm,
> >  	vops->num_syncs = num_syncs;
> >  }
> > 
> > +static int xe_vma_ops_alloc(struct xe_vma_ops *vops)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) {
> > +		if (!vops->pt_update_ops[i].num_ops)
> > +			continue;
> > +
> > +		vops->pt_update_ops[i].ops =
> > +			kmalloc_array(vops->pt_update_ops[i].num_ops,
> > +				      sizeof(*vops->pt_update_ops[i].ops),
> > +				      GFP_KERNEL);
> > +		if (!vops->pt_update_ops[i].ops)
> > +			return -ENOMEM;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void xe_vma_ops_fini(struct xe_vma_ops *vops)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i)
> > +		kfree(vops->pt_update_ops[i].ops);
> > +}
> > +
> > +static void xe_vma_ops_incr_pt_update_ops(struct xe_vma_ops *vops, u8
> > tile_mask)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i)
> > +		if (BIT(i) & tile_mask)
> > +			++vops->pt_update_ops[i].num_ops;
> > +}
> > +
> >  struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
> >  {
> >  	struct drm_gem_object *vm_resv_obj;
> > @@ -1343,6 +1379,11 @@ struct xe_vm *xe_vm_create(struct xe_device *xe,
> > u32 flags)
> >  	xe_vma_ops_init(&vm->dummy_ops.vops, vm, NULL, NULL, 0);
> >  	INIT_LIST_HEAD(&vm->dummy_ops.op.link);
> >  	list_add(&vm->dummy_ops.op.link, &vm->dummy_ops.vops.list);
> > +	for (id = 0; id < XE_MAX_TILES_PER_DEVICE; ++id)
> > +		vm->dummy_ops.vops.pt_update_ops[id].num_ops = 1;
> > +	err = xe_vma_ops_alloc(&vm->dummy_ops.vops);
> > +	if (err)
> > +		goto err_free;
> > 
> >  	INIT_LIST_HEAD(&vm->rebind_list);
> > 
> > @@ -1468,12 +1509,14 @@ struct xe_vm *xe_vm_create(struct xe_device *xe,
> > u32 flags)
> >  	return ERR_PTR(err);
> > 
> >  err_no_resv:
> > -	mutex_destroy(&vm->snap_mutex);
> > +	if (!(flags & XE_VM_FLAG_MIGRATION))
> > +		xe_device_mem_access_put(xe);
> >  	for_each_tile(tile, xe, id)
> >  		xe_range_fence_tree_fini(&vm->rftree[id]);
> > +err_free:
> > +	mutex_destroy(&vm->snap_mutex);
> > +	xe_vma_ops_fini(&vm->dummy_ops.vops);
> >  	kfree(vm);
> > -	if (!(flags & XE_VM_FLAG_MIGRATION))
> > -		xe_device_mem_access_put(xe);
> >  	return ERR_PTR(err);
> >  }
> > 
> > @@ -1611,6 +1654,7 @@ static void vm_destroy_work_func(struct work_struct
> > *w)
> > 
> >  	trace_xe_vm_free(vm);
> >  	dma_fence_put(vm->rebind_fence);
> > +	xe_vma_ops_fini(&vm->dummy_ops.vops);
> >  	kfree(vm);
> >  }
> > 
> > @@ -2284,7 +2328,6 @@ static int xe_vma_op_commit(struct xe_vm *vm, struct
> > xe_vma_op *op)
> >  	return err;
> >  }
> > 
> > -
> >  static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
> >  				   struct drm_gpuva_ops *ops,
> >  				   struct xe_sync_entry *syncs, u32 num_syncs,
> > @@ -2334,6 +2377,9 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm,
> > struct xe_exec_queue *q,
> >  				return PTR_ERR(vma);
> > 
> >  			op->map.vma = vma;
> > +			if (op->map.immediate || !xe_vm_in_fault_mode(vm))
> > +				xe_vma_ops_incr_pt_update_ops(vops,
> > +							      op->tile_mask);
> >  			break;
> >  		}
> >  		case DRM_GPUVA_OP_REMAP:
> > @@ -2378,6 +2424,8 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm,
> > struct xe_exec_queue *q,
> >  					vm_dbg(&xe->drm, "REMAP:SKIP_PREV:
> > addr=0x%016llx, range=0x%016llx",
> >  					       (ULL)op->remap.start,
> >  					       (ULL)op->remap.range);
> > +				} else {
> > +					xe_vma_ops_incr_pt_update_ops(vops,
> > op->tile_mask);
> >  				}
> >  			}
> > 
> > @@ -2414,13 +2462,16 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> > *vm, struct xe_exec_queue *q,
> >  					vm_dbg(&xe->drm, "REMAP:SKIP_NEXT:
> > addr=0x%016llx, range=0x%016llx",
> >  					       (ULL)op->remap.start,
> >  					       (ULL)op->remap.range);
> > +				} else {
> > +					xe_vma_ops_incr_pt_update_ops(vops,
> > op->tile_mask);
> >  				}
> >  			}
> > +			xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask);
> >  			break;
> >  		}
> >  		case DRM_GPUVA_OP_UNMAP:
> >  		case DRM_GPUVA_OP_PREFETCH:
> > -			/* Nothing to do */
> > +			xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask);
> >  			break;
> >  		default:
> >  			drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > @@ -3243,11 +3294,16 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void
> > *data, struct drm_file *file)
> >  		goto unwind_ops;
> >  	}
> > 
> > +	err = xe_vma_ops_alloc(&vops);
> > +	if (err)
> > +		goto unwind_ops;
> > +
> >  	err = vm_bind_ioctl_ops_execute(vm, &vops);
> > 
> >  unwind_ops:
> >  	if (err && err != -ENODATA)
> >  		vm_bind_ioctl_ops_unwind(vm, ops, args->num_binds);
> > +	xe_vma_ops_fini(&vops);
> >  	for (i = args->num_binds - 1; i >= 0; --i)
> >  		if (ops[i])
> >  			drm_gpuva_ops_free(&vm->gpuvm, ops[i]);
> > diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> > b/drivers/gpu/drm/xe/xe_vm_types.h
> > index f6ea4df64e79..f5d740dcbba3 100644
> > --- a/drivers/gpu/drm/xe/xe_vm_types.h
> > +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> > @@ -22,6 +22,7 @@ struct xe_device;
> >  struct xe_sync_entry;
> >  struct xe_user_fence;
> >  struct xe_vm;
> > +struct xe_vm_pgtable_update_op;
> > 
> >  #define XE_VMA_READ_ONLY	DRM_GPUVA_USERBITS
> >  #define XE_VMA_DESTROYED	(DRM_GPUVA_USERBITS << 1)
> > @@ -219,6 +220,13 @@ struct xe_vma_ops {
> >  	struct xe_sync_entry *syncs;
> >  	/** @num_syncs: number of syncs */
> >  	u32 num_syncs;
> > +	/** @pt_update_ops: page table update operations */
> > +	struct {
> > +		/** @ops: operations */
> > +		struct xe_vm_pgtable_update_op *ops;
> > +		/** @num_ops: number of operations */
> > +		u32 num_ops;
> > +	} pt_update_ops[XE_MAX_TILES_PER_DEVICE];
> >  };
> > 
> >  struct xe_vm {
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 16/30] drm/xe: Use ordered WQ for TLB invalidation fences
  2024-03-25 22:30   ` Zeng, Oak
@ 2024-03-26 19:10     ` Matthew Brost
  0 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-26 19:10 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Mon, Mar 25, 2024 at 04:30:51PM -0600, Zeng, Oak wrote:
> 
> 
> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 16/30] drm/xe: Use ordered WQ for TLB invalidation fences
> > 
> > TLB invalidation fences need to be ordered within an exec queue and if
> > an unordered WQ is used TLB invalidation fences could be reordered. Use
> > an ordered WQ to fix this.
> 
> 
> The code change below makes sense to me. But I think we should improve the description. I think we need to explain what need to be in order and why. As I understand it, we need things to be in below order (just an example):
> 1)Gpu page table update (such as invalidate certain page table)
> 2)Invalidate tlb entries for above page table entries
> 3)Notify/call back to user fence to let user know above vm_unbind is complete.
> 
> Obviously 1) and 2) can't be re-ordered, because 2) should be triggered by 1). But 2) and 3) can be reordered if we use unordered WQ - why we want to use ordered wq here.
> 
> Simply saying TLB invalidation fences need to be ordered is too simple, at least it is hard for me to understand. Better to improve it.
> 

Let me improve this in the next rev.

Matt

> Thanks,
> Oak
> 
> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_pt.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> > index 110d6917089b..a878e2217c7f 100644
> > --- a/drivers/gpu/drm/xe/xe_pt.c
> > +++ b/drivers/gpu/drm/xe/xe_pt.c
> > @@ -1107,7 +1107,7 @@ static void invalidation_fence_cb(struct dma_fence
> > *fence,
> > 
> >  	trace_xe_gt_tlb_invalidation_fence_cb(&ifence->base);
> >  	if (!ifence->fence->error) {
> > -		queue_work(system_wq, &ifence->work);
> > +		queue_work(ifence->gt->ordered_wq, &ifence->work);
> >  	} else {
> >  		ifence->base.base.error = ifence->fence->error;
> >  		dma_fence_signal(&ifence->base.base);
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 13/30] drm/xe: Move ufence add to vm_bind_ioctl_ops_install_fences
  2024-03-26 18:54     ` Matthew Brost
@ 2024-03-26 20:59       ` Zeng, Oak
  0 siblings, 0 replies; 76+ messages in thread
From: Zeng, Oak @ 2024-03-26 20:59 UTC (permalink / raw)
  To: Brost, Matthew; +Cc: intel-xe



> -----Original Message-----
> From: Brost, Matthew <matthew.brost@intel.com>
> Sent: Tuesday, March 26, 2024 2:54 PM
> To: Zeng, Oak <oak.zeng@intel.com>
> Cc: intel-xe@lists.freedesktop.org
> Subject: Re: [PATCH v4 13/30] drm/xe: Move ufence add to
> vm_bind_ioctl_ops_install_fences
> 
> On Mon, Mar 25, 2024 at 02:54:44PM -0600, Zeng, Oak wrote:
> > This patch makes sense to me. See two nit-pick inline
> >
> > > -----Original Message-----
> > > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of
> Matthew
> > > Brost
> > > Sent: Friday, March 8, 2024 12:08 AM
> > > To: intel-xe@lists.freedesktop.org
> > > Cc: Brost, Matthew <matthew.brost@intel.com>
> > > Subject: [PATCH v4 13/30] drm/xe: Move ufence add to
> > > vm_bind_ioctl_ops_install_fences
> > >
> > > Rather than adding a ufence to a VMA in the bind function, add the
> > > ufence to all VMAs in the IOCTL that require binds in
> > > vm_bind_ioctl_ops_install_fences. This will help with the transition to
> > > job 1 per VM bind IOCTL.
> > >
> > > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > > ---
> > >  drivers/gpu/drm/xe/xe_sync.c | 15 ++++++++++++
> > >  drivers/gpu/drm/xe/xe_sync.h |  1 +
> > >  drivers/gpu/drm/xe/xe_vm.c   | 44 ++++++++++++++++++++++++++++++--
> ----
> > >  3 files changed, 53 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/xe/xe_sync.c b/drivers/gpu/drm/xe/xe_sync.c
> > > index 02c9577fe418..07aa65d9bcab 100644
> > > --- a/drivers/gpu/drm/xe/xe_sync.c
> > > +++ b/drivers/gpu/drm/xe/xe_sync.c
> > > @@ -343,6 +343,21 @@ xe_sync_in_fence_get(struct xe_sync_entry *sync,
> int
> > > num_sync,
> > >  	return ERR_PTR(-ENOMEM);
> > >  }
> > >
> > > +/**
> > > + * __xe_sync_ufence_get() - Get user fence from user fence
> > > + * @ufence: input user fence
> > > + *
> > > + * Get a user fence reference from user fence
> > > + *
> > > + * Return: xe_user_fence pointer with reference
> > > + */
> > > +struct xe_user_fence *__xe_sync_ufence_get(struct xe_user_fence
> *ufence)
> > > +{
> > > +	user_fence_get(ufence);
> > > +
> > > +	return ufence;
> > > +}
> >
> > I wonder why this is made part of xe_sync. Isn't just a ufence get function? Can
> we drop _sync_ from the function name?
> >
> >
> 
> Typically exported functions should have a prefix matching the header
> file name.
> 
> e.g.
> 
> xe_sync.h -> all functions should start with xe_sync_*
> 
> In this case struct xe_user_fence is private date member to xe_sync.c
> (only define in that C file) and just an opaque pointer to the rest of
> the driver.


That makes sense. Thanks for explaining.

Oak

> 
> > > +
> > >  /**
> > >   * xe_sync_ufence_get() - Get user fence from sync
> > >   * @sync: input sync
> > > diff --git a/drivers/gpu/drm/xe/xe_sync.h b/drivers/gpu/drm/xe/xe_sync.h
> > > index 0fd0d51208e6..26e9ec9de1a8 100644
> > > --- a/drivers/gpu/drm/xe/xe_sync.h
> > > +++ b/drivers/gpu/drm/xe/xe_sync.h
> > > @@ -38,6 +38,7 @@ static inline bool xe_sync_is_ufence(struct
> xe_sync_entry
> > > *sync)
> > >  	return !!sync->ufence;
> > >  }
> > >
> > > +struct xe_user_fence *__xe_sync_ufence_get(struct xe_user_fence
> *ufence);
> > >  struct xe_user_fence *xe_sync_ufence_get(struct xe_sync_entry *sync);
> > >  void xe_sync_ufence_put(struct xe_user_fence *ufence);
> > >  int xe_sync_ufence_get_status(struct xe_user_fence *ufence);
> > > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > > index 5767955529dd..5b93c71fc5e9 100644
> > > --- a/drivers/gpu/drm/xe/xe_vm.c
> > > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > > @@ -1810,17 +1810,10 @@ xe_vm_bind(struct xe_vm *vm, struct xe_vma
> *vma,
> > > struct xe_exec_queue *q,
> > >  {
> > >  	struct dma_fence *fence;
> > >  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > > q);
> > > -	struct xe_user_fence *ufence;
> > >
> > >  	xe_vm_assert_held(vm);
> > >  	xe_bo_assert_held(bo);
> > >
> > > -	ufence = find_ufence_get(syncs, num_syncs);
> > > -	if (vma->ufence && ufence)
> > > -		xe_sync_ufence_put(vma->ufence);
> > > -
> > > -	vma->ufence = ufence ?: vma->ufence;
> > > -
> > >  	if (immediate) {
> > >  		fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, tile_mask,
> > >  				       first_op, last_op);
> > > @@ -2822,21 +2815,58 @@ struct dma_fence *xe_vm_ops_execute(struct
> > > xe_vm *vm, struct xe_vma_ops *vops)
> > >  	return fence;
> > >  }
> > >
> > > +static void vma_add_ufence(struct xe_vma *vma, struct xe_user_fence
> > > *ufence)
> > > +{
> > > +	if (vma->ufence)
> > > +		xe_sync_ufence_put(vma->ufence);
> >
> > Not sure where/when we introduced xe_sync_ufence_put, for me this can be
> renamed to xe_ufence_put
> >
> 
> See above, I think the naming is correct. All of this is a matter of
> opinion, we don't have any offical style guidelines for Xe but we might
> want to think about writing some up / fixing Xe to conform while the
> driver is still relatively small.
> 
> Matt
> 
> > Oak
> >
> > > +	vma->ufence = __xe_sync_ufence_get(ufence);
> > > +}
> > > +
> > > +static void op_add_ufence(struct xe_vm *vm, struct xe_vma_op *op,
> > > +			  struct xe_user_fence *ufence)
> > > +{
> > > +	switch (op->base.op) {
> > > +	case DRM_GPUVA_OP_MAP:
> > > +		vma_add_ufence(op->map.vma, ufence);
> > > +		break;
> > > +	case DRM_GPUVA_OP_REMAP:
> > > +		if (op->remap.prev)
> > > +			vma_add_ufence(op->remap.prev, ufence);
> > > +		if (op->remap.next)
> > > +			vma_add_ufence(op->remap.next, ufence);
> > > +		break;
> > > +	case DRM_GPUVA_OP_UNMAP:
> > > +		break;
> > > +	case DRM_GPUVA_OP_PREFETCH:
> > > +		vma_add_ufence(gpuva_to_vma(op->base.prefetch.va),
> > > ufence);
> > > +		break;
> > > +	default:
> > > +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > > +	}
> > > +}
> > > +
> > >  static void vm_bind_ioctl_ops_install_fences(struct xe_vm *vm,
> > >  					     struct xe_vma_ops *vops,
> > >  					     struct dma_fence *fence)
> > >  {
> > >  	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > > vops->q);
> > > +	struct xe_user_fence *ufence;
> > >  	struct xe_vma_op *op;
> > >  	int i;
> > >
> > > +	ufence = find_ufence_get(vops->syncs, vops->num_syncs);
> > >  	list_for_each_entry(op, &vops->list, link) {
> > > +		if (ufence)
> > > +			op_add_ufence(vm, op, ufence);
> > > +
> > >  		if (op->base.op == DRM_GPUVA_OP_UNMAP)
> > >  			xe_vma_destroy(gpuva_to_vma(op->base.unmap.va),
> > > fence);
> > >  		else if (op->base.op == DRM_GPUVA_OP_REMAP)
> > >  			xe_vma_destroy(gpuva_to_vma(op-
> > > >base.remap.unmap->va),
> > >  				       fence);
> > >  	}
> > > +	if (ufence)
> > > +		xe_sync_ufence_put(ufence);
> > >  	for (i = 0; i < vops->num_syncs; i++)
> > >  		xe_sync_entry_signal(vops->syncs + i, NULL, fence);
> > >  	xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence);
> > > --
> > > 2.34.1
> >

^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 15/30] drm/xe: Add xe_vm_pgtable_update_op to xe_vma_ops
  2024-03-26 19:05     ` Matthew Brost
@ 2024-03-27  1:29       ` Zeng, Oak
  0 siblings, 0 replies; 76+ messages in thread
From: Zeng, Oak @ 2024-03-27  1:29 UTC (permalink / raw)
  To: Brost, Matthew; +Cc: intel-xe



> -----Original Message-----
> From: Brost, Matthew <matthew.brost@intel.com>
> Sent: Tuesday, March 26, 2024 3:06 PM
> To: Zeng, Oak <oak.zeng@intel.com>
> Cc: intel-xe@lists.freedesktop.org
> Subject: Re: [PATCH v4 15/30] drm/xe: Add xe_vm_pgtable_update_op to
> xe_vma_ops
> 
> On Mon, Mar 25, 2024 at 03:58:10PM -0600, Zeng, Oak wrote:
> >
> >
> > > -----Original Message-----
> > > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of
> Matthew
> > > Brost
> > > Sent: Friday, March 8, 2024 12:08 AM
> > > To: intel-xe@lists.freedesktop.org
> > > Cc: Brost, Matthew <matthew.brost@intel.com>
> > > Subject: [PATCH v4 15/30] drm/xe: Add xe_vm_pgtable_update_op to
> > > xe_vma_ops
> > >
> > > Will help with the converstion to 1 job per VM bind IOCTL. Allocation
> > > only implemented in this patch.
> >
> >
> > Can you explain why you need to introduce pt_update_op? this patch seems
> only allocate some slot for pt_update_op but they are not really used for page
> table update. I will keep looking the rest of this series.
> >
> > I also don't get why this helps 1job/bind ioctl.
> >
> 
> Each VMA operations is converted into 0-3 PT per ops tile. i.e. a MAP VMA
> operations with immediate clear generates 0 PT ops, a REMAP VMA with
> both prev & next generates 3 PT ops. PT ops work on the internal / GPU
> PT state compared to VMA ops which operate on the internal GPUVM state.
> 
> The flow roughly is:
> 
> generate VMA ops from IOCTL input
> convert all VMA ops to PT ops, prep and stage PT ops
> run PT ops as an atomic unit (1 job)
> commit PT ops
> commit VMA ops
> 
> If at any point a failure occurs before the commit step the PT ops can
> be unwound.
> 
> Likewise when a failure occurs the VMA ops are unwound too, this is just
> layer above the PT ops.
> 
> In the end if an errors at point in the IOCTL the original GPUVM and PT
> state is restored. This compared to serial execution on tip where is an
> error occurs we just kill the VM.
> 
> Does this make sense?

Hi Matt,

Thanks for explain it. Should we also document such implementation details in the xe_vm_doc.h?

Oak

> 
> Matt
> 
> >
> > Oak
> >
> > >
> > > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > > ---
> > >  drivers/gpu/drm/xe/xe_pt_types.h | 12 ++++++
> > >  drivers/gpu/drm/xe/xe_vm.c       | 66 +++++++++++++++++++++++++++++--
> -
> > >  drivers/gpu/drm/xe/xe_vm_types.h |  8 ++++
> > >  3 files changed, 81 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/xe/xe_pt_types.h
> > > b/drivers/gpu/drm/xe/xe_pt_types.h
> > > index cee70cb0f014..2093150f461e 100644
> > > --- a/drivers/gpu/drm/xe/xe_pt_types.h
> > > +++ b/drivers/gpu/drm/xe/xe_pt_types.h
> > > @@ -74,4 +74,16 @@ struct xe_vm_pgtable_update {
> > >  	u32 flags;
> > >  };
> > >
> > > +/** struct xe_vm_pgtable_update_op - Page table update operation */
> > > +struct xe_vm_pgtable_update_op {
> > > +	/** @entries: entries to update for this operation */
> > > +	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
> > > +	/** @num_entries: number of entries for this update operation */
> > > +	u32 num_entries;
> > > +	/** @bind: is a bind */
> > > +	bool bind;
> > > +	/** @rebind: is a rebind */
> > > +	bool rebind;
> > > +};
> > > +
> > >  #endif
> > > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > > index 5b93c71fc5e9..72e9bdab79d5 100644
> > > --- a/drivers/gpu/drm/xe/xe_vm.c
> > > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > > @@ -1319,6 +1319,42 @@ static void xe_vma_ops_init(struct xe_vma_ops
> *vops,
> > > struct xe_vm *vm,
> > >  	vops->num_syncs = num_syncs;
> > >  }
> > >
> > > +static int xe_vma_ops_alloc(struct xe_vma_ops *vops)
> > > +{
> > > +	int i;
> > > +
> > > +	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) {
> > > +		if (!vops->pt_update_ops[i].num_ops)
> > > +			continue;
> > > +
> > > +		vops->pt_update_ops[i].ops =
> > > +			kmalloc_array(vops->pt_update_ops[i].num_ops,
> > > +				      sizeof(*vops->pt_update_ops[i].ops),
> > > +				      GFP_KERNEL);
> > > +		if (!vops->pt_update_ops[i].ops)
> > > +			return -ENOMEM;
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static void xe_vma_ops_fini(struct xe_vma_ops *vops)
> > > +{
> > > +	int i;
> > > +
> > > +	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i)
> > > +		kfree(vops->pt_update_ops[i].ops);
> > > +}
> > > +
> > > +static void xe_vma_ops_incr_pt_update_ops(struct xe_vma_ops *vops, u8
> > > tile_mask)
> > > +{
> > > +	int i;
> > > +
> > > +	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i)
> > > +		if (BIT(i) & tile_mask)
> > > +			++vops->pt_update_ops[i].num_ops;
> > > +}
> > > +
> > >  struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
> > >  {
> > >  	struct drm_gem_object *vm_resv_obj;
> > > @@ -1343,6 +1379,11 @@ struct xe_vm *xe_vm_create(struct xe_device *xe,
> > > u32 flags)
> > >  	xe_vma_ops_init(&vm->dummy_ops.vops, vm, NULL, NULL, 0);
> > >  	INIT_LIST_HEAD(&vm->dummy_ops.op.link);
> > >  	list_add(&vm->dummy_ops.op.link, &vm->dummy_ops.vops.list);
> > > +	for (id = 0; id < XE_MAX_TILES_PER_DEVICE; ++id)
> > > +		vm->dummy_ops.vops.pt_update_ops[id].num_ops = 1;
> > > +	err = xe_vma_ops_alloc(&vm->dummy_ops.vops);
> > > +	if (err)
> > > +		goto err_free;
> > >
> > >  	INIT_LIST_HEAD(&vm->rebind_list);
> > >
> > > @@ -1468,12 +1509,14 @@ struct xe_vm *xe_vm_create(struct xe_device
> *xe,
> > > u32 flags)
> > >  	return ERR_PTR(err);
> > >
> > >  err_no_resv:
> > > -	mutex_destroy(&vm->snap_mutex);
> > > +	if (!(flags & XE_VM_FLAG_MIGRATION))
> > > +		xe_device_mem_access_put(xe);
> > >  	for_each_tile(tile, xe, id)
> > >  		xe_range_fence_tree_fini(&vm->rftree[id]);
> > > +err_free:
> > > +	mutex_destroy(&vm->snap_mutex);
> > > +	xe_vma_ops_fini(&vm->dummy_ops.vops);
> > >  	kfree(vm);
> > > -	if (!(flags & XE_VM_FLAG_MIGRATION))
> > > -		xe_device_mem_access_put(xe);
> > >  	return ERR_PTR(err);
> > >  }
> > >
> > > @@ -1611,6 +1654,7 @@ static void vm_destroy_work_func(struct
> work_struct
> > > *w)
> > >
> > >  	trace_xe_vm_free(vm);
> > >  	dma_fence_put(vm->rebind_fence);
> > > +	xe_vma_ops_fini(&vm->dummy_ops.vops);
> > >  	kfree(vm);
> > >  }
> > >
> > > @@ -2284,7 +2328,6 @@ static int xe_vma_op_commit(struct xe_vm *vm,
> struct
> > > xe_vma_op *op)
> > >  	return err;
> > >  }
> > >
> > > -
> > >  static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct
> xe_exec_queue *q,
> > >  				   struct drm_gpuva_ops *ops,
> > >  				   struct xe_sync_entry *syncs, u32 num_syncs,
> > > @@ -2334,6 +2377,9 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> *vm,
> > > struct xe_exec_queue *q,
> > >  				return PTR_ERR(vma);
> > >
> > >  			op->map.vma = vma;
> > > +			if (op->map.immediate || !xe_vm_in_fault_mode(vm))
> > > +				xe_vma_ops_incr_pt_update_ops(vops,
> > > +							      op->tile_mask);
> > >  			break;
> > >  		}
> > >  		case DRM_GPUVA_OP_REMAP:
> > > @@ -2378,6 +2424,8 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> *vm,
> > > struct xe_exec_queue *q,
> > >  					vm_dbg(&xe->drm, "REMAP:SKIP_PREV:
> > > addr=0x%016llx, range=0x%016llx",
> > >  					       (ULL)op->remap.start,
> > >  					       (ULL)op->remap.range);
> > > +				} else {
> > > +					xe_vma_ops_incr_pt_update_ops(vops,
> > > op->tile_mask);
> > >  				}
> > >  			}
> > >
> > > @@ -2414,13 +2462,16 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> > > *vm, struct xe_exec_queue *q,
> > >  					vm_dbg(&xe->drm, "REMAP:SKIP_NEXT:
> > > addr=0x%016llx, range=0x%016llx",
> > >  					       (ULL)op->remap.start,
> > >  					       (ULL)op->remap.range);
> > > +				} else {
> > > +					xe_vma_ops_incr_pt_update_ops(vops,
> > > op->tile_mask);
> > >  				}
> > >  			}
> > > +			xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask);
> > >  			break;
> > >  		}
> > >  		case DRM_GPUVA_OP_UNMAP:
> > >  		case DRM_GPUVA_OP_PREFETCH:
> > > -			/* Nothing to do */
> > > +			xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask);
> > >  			break;
> > >  		default:
> > >  			drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > > @@ -3243,11 +3294,16 @@ int xe_vm_bind_ioctl(struct drm_device *dev,
> void
> > > *data, struct drm_file *file)
> > >  		goto unwind_ops;
> > >  	}
> > >
> > > +	err = xe_vma_ops_alloc(&vops);
> > > +	if (err)
> > > +		goto unwind_ops;
> > > +
> > >  	err = vm_bind_ioctl_ops_execute(vm, &vops);
> > >
> > >  unwind_ops:
> > >  	if (err && err != -ENODATA)
> > >  		vm_bind_ioctl_ops_unwind(vm, ops, args->num_binds);
> > > +	xe_vma_ops_fini(&vops);
> > >  	for (i = args->num_binds - 1; i >= 0; --i)
> > >  		if (ops[i])
> > >  			drm_gpuva_ops_free(&vm->gpuvm, ops[i]);
> > > diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> > > b/drivers/gpu/drm/xe/xe_vm_types.h
> > > index f6ea4df64e79..f5d740dcbba3 100644
> > > --- a/drivers/gpu/drm/xe/xe_vm_types.h
> > > +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> > > @@ -22,6 +22,7 @@ struct xe_device;
> > >  struct xe_sync_entry;
> > >  struct xe_user_fence;
> > >  struct xe_vm;
> > > +struct xe_vm_pgtable_update_op;
> > >
> > >  #define XE_VMA_READ_ONLY	DRM_GPUVA_USERBITS
> > >  #define XE_VMA_DESTROYED	(DRM_GPUVA_USERBITS << 1)
> > > @@ -219,6 +220,13 @@ struct xe_vma_ops {
> > >  	struct xe_sync_entry *syncs;
> > >  	/** @num_syncs: number of syncs */
> > >  	u32 num_syncs;
> > > +	/** @pt_update_ops: page table update operations */
> > > +	struct {
> > > +		/** @ops: operations */
> > > +		struct xe_vm_pgtable_update_op *ops;
> > > +		/** @num_ops: number of operations */
> > > +		u32 num_ops;
> > > +	} pt_update_ops[XE_MAX_TILES_PER_DEVICE];
> > >  };
> > >
> > >  struct xe_vm {
> > > --
> > > 2.34.1
> >

^ permalink raw reply	[flat|nested] 76+ messages in thread

* RE: [PATCH v4 18/30] drm/xe: Convert multiple bind ops into single job
  2024-03-08  5:07 ` [PATCH v4 18/30] drm/xe: Convert multiple bind ops into single job Matthew Brost
@ 2024-03-27  2:40   ` Zeng, Oak
  2024-03-27 19:26     ` Matthew Brost
  0 siblings, 1 reply; 76+ messages in thread
From: Zeng, Oak @ 2024-03-27  2:40 UTC (permalink / raw)
  To: Brost, Matthew, intel-xe; +Cc: Brost, Matthew

Hi Matt,

This patch is very big to review. I wasn't able to look the whole patch. See some comments inline for now. I need to continue it.

Is it possible to divide into small patches?

> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> Brost
> Sent: Friday, March 8, 2024 12:08 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Brost, Matthew <matthew.brost@intel.com>
> Subject: [PATCH v4 18/30] drm/xe: Convert multiple bind ops into single job
> 
> This aligns with the uAPI of an array of binds or single bind that
> results in multiple GPUVA ops to be considered a single atomic
> operations.
> 
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_bo_types.h     |    2 +
>  drivers/gpu/drm/xe/xe_exec.c         |   25 +-
>  drivers/gpu/drm/xe/xe_gt_pagefault.c |    6 +-
>  drivers/gpu/drm/xe/xe_migrate.c      |  298 ++++----
>  drivers/gpu/drm/xe/xe_migrate.h      |   32 +-
>  drivers/gpu/drm/xe/xe_pt.c           | 1018 ++++++++++++++++----------
>  drivers/gpu/drm/xe/xe_pt.h           |    7 +
>  drivers/gpu/drm/xe/xe_pt_types.h     |   34 +
>  drivers/gpu/drm/xe/xe_vm.c           |  533 ++++----------
>  drivers/gpu/drm/xe/xe_vm.h           |    5 +-
>  drivers/gpu/drm/xe/xe_vm_types.h     |   29 +-
>  11 files changed, 969 insertions(+), 1020 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_bo_types.h
> b/drivers/gpu/drm/xe/xe_bo_types.h
> index 14ef13b7b421..1ff5b5a68adc 100644
> --- a/drivers/gpu/drm/xe/xe_bo_types.h
> +++ b/drivers/gpu/drm/xe/xe_bo_types.h
> @@ -77,6 +77,8 @@ struct xe_bo {
>  	} props;
>  	/** @freed: List node for delayed put. */
>  	struct llist_node freed;
> +	/** @update_index: Update index if PT BO */
> +	int update_index;
>  	/** @created: Whether the bo has passed initial creation */
>  	bool created;
> 
> diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
> index 952496c6260d..4feff67620c4 100644
> --- a/drivers/gpu/drm/xe/xe_exec.c
> +++ b/drivers/gpu/drm/xe/xe_exec.c
> @@ -294,30 +294,9 @@ int xe_exec_ioctl(struct drm_device *dev, void *data,
> struct drm_file *file)
>  		err = PTR_ERR(rebind_fence);
>  		goto err_put_job;
>  	}
> +	dma_fence_put(rebind_fence);
> 
> -	/*
> -	 * We store the rebind_fence in the VM so subsequent execs don't get
> -	 * scheduled before the rebinds of userptrs / evicted BOs is complete.
> -	 */
> -	if (rebind_fence) {
> -		dma_fence_put(vm->rebind_fence);
> -		vm->rebind_fence = rebind_fence;
> -	}
> -	if (vm->rebind_fence) {
> -		if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
> -			     &vm->rebind_fence->flags)) {
> -			dma_fence_put(vm->rebind_fence);
> -			vm->rebind_fence = NULL;
> -		} else {
> -			dma_fence_get(vm->rebind_fence);
> -			err = drm_sched_job_add_dependency(&job->drm,
> -							   vm->rebind_fence);
> -			if (err)
> -				goto err_put_job;
> -		}
> -	}
> -
> -	/* Wait behind munmap style rebinds */
> +	/* Wait for rebinds */
>  	if (!xe_vm_in_lr_mode(vm)) {
>  		err = drm_sched_job_add_resv_dependencies(&job->drm,
>  							  xe_vm_resv(vm),


Can you explain why you can wait for rebind using above codes? I understand here we make all the fences in vm reservation object a dependency of the job. But did we add rebind_fence to vm's reservation object? I can't find such code in this patch


> diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c
> b/drivers/gpu/drm/xe/xe_gt_pagefault.c
> index 878e234166aa..bd8688b2f462 100644
> --- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
> +++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
> @@ -208,9 +208,9 @@ static int handle_pagefault(struct xe_gt *gt, struct
> pagefault *pf)
> 
>  	/* Bind VMA only to the GT that has faulted */
>  	trace_xe_vma_pf_bind(vma);
> -	xe_vm_populate_dummy_rebind(vm, vma);
> -	vm->dummy_ops.op.tile_mask = BIT(tile->id);
> -	vm->dummy_ops.op.q = xe_tile_migrate_exec_queue(tile);
> +	xe_vm_populate_dummy_rebind(vm, vma, BIT(tile->id));
> +	vm->dummy_ops.vops.pt_update_ops[tile->id].q =
> +		xe_tile_migrate_exec_queue(tile);

I guess I will ignore all those dummy_rebind/dummy_ops code for now.


>  	fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
>  	if (IS_ERR(fence)) {
>  		ret = PTR_ERR(fence);
> diff --git a/drivers/gpu/drm/xe/xe_migrate.c
> b/drivers/gpu/drm/xe/xe_migrate.c
> index 3fd76f912fda..cc0499f3702c 100644
> --- a/drivers/gpu/drm/xe/xe_migrate.c
> +++ b/drivers/gpu/drm/xe/xe_migrate.c
> @@ -1106,6 +1106,7 @@ struct dma_fence *xe_migrate_clear(struct xe_migrate
> *m,
>  }
> 
>  static void write_pgtable(struct xe_tile *tile, struct xe_bb *bb, u64 ppgtt_ofs,
> +			  const struct xe_vm_pgtable_update_op *pt_op,
>  			  const struct xe_vm_pgtable_update *update,
>  			  struct xe_migrate_pt_update *pt_update)
>  {
> @@ -1140,8 +1141,12 @@ static void write_pgtable(struct xe_tile *tile, struct
> xe_bb *bb, u64 ppgtt_ofs,
>  		bb->cs[bb->len++] = MI_STORE_DATA_IMM |
> MI_SDI_NUM_QW(chunk);
>  		bb->cs[bb->len++] = lower_32_bits(addr);
>  		bb->cs[bb->len++] = upper_32_bits(addr);
> -		ops->populate(pt_update, tile, NULL, bb->cs + bb->len, ofs,
> chunk,
> -			      update);
> +		if (pt_op->bind)
> +			ops->populate(pt_update, tile, NULL, bb->cs + bb->len,
> +				      ofs, chunk, update);
> +		else
> +			ops->clear(pt_update, tile, NULL, bb->cs + bb->len,
> +				   ofs, chunk, update);
> 
>  		bb->len += chunk * 2;
>  		ofs += chunk;
> @@ -1166,114 +1171,58 @@ struct migrate_test_params {
> 
>  static struct dma_fence *
>  xe_migrate_update_pgtables_cpu(struct xe_migrate *m,
> -			       struct xe_vm *vm, struct xe_bo *bo,
> -			       const struct  xe_vm_pgtable_update *updates,
> -			       u32 num_updates, bool wait_vm,
>  			       struct xe_migrate_pt_update *pt_update)
>  {
>  	XE_TEST_DECLARE(struct migrate_test_params *test =
>  			to_migrate_test_params
>  			(xe_cur_kunit_priv(XE_TEST_LIVE_MIGRATE));)
>  	const struct xe_migrate_pt_update_ops *ops = pt_update->ops;
> -	struct dma_fence *fence;
> +	struct xe_vm *vm = pt_update->vops->vm;
> +	struct xe_vm_pgtable_update_ops *pt_update_ops =
> +		&pt_update->vops->pt_update_ops[pt_update->tile_id];
>  	int err;
> -	u32 i;
> +	u32 j, i;
> 
>  	if (XE_TEST_ONLY(test && test->force_gpu))
>  		return ERR_PTR(-ETIME);
> 
> -	if (bo && !dma_resv_test_signaled(bo->ttm.base.resv,
> -					  DMA_RESV_USAGE_KERNEL))
> -		return ERR_PTR(-ETIME);
> -
> -	if (wait_vm && !dma_resv_test_signaled(xe_vm_resv(vm),
> -					       DMA_RESV_USAGE_BOOKKEEP))
> -		return ERR_PTR(-ETIME);
> -
>  	if (ops->pre_commit) {
>  		pt_update->job = NULL;
>  		err = ops->pre_commit(pt_update);
>  		if (err)
>  			return ERR_PTR(err);
>  	}
> -	for (i = 0; i < num_updates; i++) {
> -		const struct xe_vm_pgtable_update *update = &updates[i];
> -
> -		ops->populate(pt_update, m->tile, &update->pt_bo->vmap,
> NULL,
> -			      update->ofs, update->qwords, update);
> -	}
> -
> -	if (vm) {
> -		trace_xe_vm_cpu_bind(vm);
> -		xe_device_wmb(vm->xe);
> -	}
> -
> -	fence = dma_fence_get_stub();
> -
> -	return fence;
> -}
> -
> -static bool no_in_syncs(struct xe_vm *vm, struct xe_exec_queue *q,
> -			struct xe_sync_entry *syncs, u32 num_syncs)
> -{
> -	struct dma_fence *fence;
> -	int i;
> 
> -	for (i = 0; i < num_syncs; i++) {
> -		fence = syncs[i].fence;
> -
> -		if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
> -				       &fence->flags))
> -			return false;
> -	}
> -	if (q) {
> -		fence = xe_exec_queue_last_fence_get(q, vm);
> -		if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
> -			dma_fence_put(fence);
> -			return false;
> +	for (j = 0; j < pt_update_ops->num_ops; ++j) {
> +		const struct xe_vm_pgtable_update_op *pt_op =
> +			&pt_update_ops->ops[j];
> +
> +		for (i = 0; i < pt_op->num_entries; i++) {
> +			const struct xe_vm_pgtable_update *update =
> +				&pt_op->entries[i];
> +
> +			if (pt_op->bind)
> +				ops->populate(pt_update, m->tile,
> +					      &update->pt_bo->vmap, NULL,
> +					      update->ofs, update->qwords,
> +					      update);
> +			else
> +				ops->clear(pt_update, m->tile,
> +					   &update->pt_bo->vmap, NULL,
> +					   update->ofs, update->qwords, update);
>  		}
> -		dma_fence_put(fence);
>  	}
> 
> -	return true;
> +	trace_xe_vm_cpu_bind(vm);
> +	xe_device_wmb(vm->xe);
> +
> +	return dma_fence_get_stub();
>  }
> 
> -/**
> - * xe_migrate_update_pgtables() - Pipelined page-table update
> - * @m: The migrate context.
> - * @vm: The vm we'll be updating.
> - * @bo: The bo whose dma-resv we will await before updating, or NULL if
> userptr.
> - * @q: The exec queue to be used for the update or NULL if the default
> - * migration engine is to be used.
> - * @updates: An array of update descriptors.
> - * @num_updates: Number of descriptors in @updates.
> - * @syncs: Array of xe_sync_entry to await before updating. Note that waits
> - * will block the engine timeline.
> - * @num_syncs: Number of entries in @syncs.
> - * @pt_update: Pointer to a struct xe_migrate_pt_update, which contains
> - * pointers to callback functions and, if subclassed, private arguments to
> - * those.
> - *
> - * Perform a pipelined page-table update. The update descriptors are typically
> - * built under the same lock critical section as a call to this function. If
> - * using the default engine for the updates, they will be performed in the
> - * order they grab the job_mutex. If different engines are used, external
> - * synchronization is needed for overlapping updates to maintain page-table
> - * consistency. Note that the meaing of "overlapping" is that the updates
> - * touch the same page-table, which might be a higher-level page-directory.
> - * If no pipelining is needed, then updates may be performed by the cpu.
> - *
> - * Return: A dma_fence that, when signaled, indicates the update completion.
> - */
> -struct dma_fence *
> -xe_migrate_update_pgtables(struct xe_migrate *m,
> -			   struct xe_vm *vm,
> -			   struct xe_bo *bo,
> -			   struct xe_exec_queue *q,
> -			   const struct xe_vm_pgtable_update *updates,
> -			   u32 num_updates,
> -			   struct xe_sync_entry *syncs, u32 num_syncs,
> -			   struct xe_migrate_pt_update *pt_update)
> +static struct dma_fence *
> +__xe_migrate_update_pgtables(struct xe_migrate *m,
> +			     struct xe_migrate_pt_update *pt_update,
> +			     struct xe_vm_pgtable_update_ops *pt_update_ops)

Maybe rename this function to _gpu?

>  {
>  	const struct xe_migrate_pt_update_ops *ops = pt_update->ops;
>  	struct xe_tile *tile = m->tile;
> @@ -1282,59 +1231,45 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
>  	struct xe_sched_job *job;
>  	struct dma_fence *fence;
>  	struct drm_suballoc *sa_bo = NULL;
> -	struct xe_vma *vma = pt_update->vma;
>  	struct xe_bb *bb;
> -	u32 i, batch_size, ppgtt_ofs, update_idx, page_ofs = 0;
> +	u32 i, j, batch_size = 0, ppgtt_ofs, update_idx, page_ofs = 0;
> +	u32 num_updates = 0, current_update = 0;
>  	u64 addr;
>  	int err = 0;
> -	bool usm = !q && xe->info.has_usm;
> -	bool first_munmap_rebind = vma &&
> -		vma->gpuva.flags & XE_VMA_FIRST_REBIND;
> -	struct xe_exec_queue *q_override = !q ? m->q : q;
> -	u16 pat_index = xe->pat.idx[XE_CACHE_WB];
> +	bool is_migrate = pt_update_ops->q == m->q;
> +	bool usm = is_migrate && xe->info.has_usm;
> 
> -	/* Use the CPU if no in syncs and engine is idle */
> -	if (no_in_syncs(vm, q, syncs, num_syncs) &&
> xe_exec_queue_is_idle(q_override)) {
> -		fence =  xe_migrate_update_pgtables_cpu(m, vm, bo, updates,
> -							num_updates,
> -							first_munmap_rebind,
> -							pt_update);
> -		if (!IS_ERR(fence) || fence == ERR_PTR(-EAGAIN))
> -			return fence;
> +	for (i = 0; i < pt_update_ops->num_ops; ++i) {
> +		struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops-
> >ops[i];
> +		struct xe_vm_pgtable_update *updates = pt_op->entries;
> +
> +		num_updates += pt_op->num_entries;
> +		for (j = 0; j < pt_op->num_entries; ++j) {
> +			u32 num_cmds = DIV_ROUND_UP(updates[j].qwords,
> 0x1ff);
> +
> +			/* align noop + MI_STORE_DATA_IMM cmd prefix */
> +			batch_size += 4 * num_cmds + updates[j].qwords * 2;
> +		}
>  	}
> 
>  	/* fixed + PTE entries */
>  	if (IS_DGFX(xe))
> -		batch_size = 2;
> +		batch_size += 2;
>  	else
> -		batch_size = 6 + num_updates * 2;
> +		batch_size += 6 + num_updates * 2;
> 
> -	for (i = 0; i < num_updates; i++) {
> -		u32 num_cmds = DIV_ROUND_UP(updates[i].qwords,
> MAX_PTE_PER_SDI);
> -
> -		/* align noop + MI_STORE_DATA_IMM cmd prefix */
> -		batch_size += 4 * num_cmds + updates[i].qwords * 2;
> -	}
> -
> -	/*
> -	 * XXX: Create temp bo to copy from, if batch_size becomes too big?
> -	 *
> -	 * Worst case: Sum(2 * (each lower level page size) + (top level page size))
> -	 * Should be reasonably bound..
> -	 */
> -	xe_tile_assert(tile, batch_size < SZ_128K);
> -
> -	bb = xe_bb_new(gt, batch_size, !q && xe->info.has_usm);
> +	bb = xe_bb_new(gt, batch_size, usm);
>  	if (IS_ERR(bb))
>  		return ERR_CAST(bb);
> 
>  	/* For sysmem PTE's, need to map them in our hole.. */
>  	if (!IS_DGFX(xe)) {
>  		ppgtt_ofs = NUM_KERNEL_PDE - 1;
> -		if (q) {
> -			xe_tile_assert(tile, num_updates <=
> NUM_VMUSA_WRITES_PER_UNIT);
> +		if (!is_migrate) {
> +			u32 num_units = DIV_ROUND_UP(num_updates,
> +
> NUM_VMUSA_WRITES_PER_UNIT);
> 
> -			sa_bo = drm_suballoc_new(&m->vm_update_sa, 1,
> +			sa_bo = drm_suballoc_new(&m->vm_update_sa,
> num_units,
>  						 GFP_KERNEL, true, 0);
>  			if (IS_ERR(sa_bo)) {
>  				err = PTR_ERR(sa_bo);
> @@ -1354,14 +1289,26 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
>  		bb->cs[bb->len++] = ppgtt_ofs * XE_PAGE_SIZE + page_ofs;
>  		bb->cs[bb->len++] = 0; /* upper_32_bits */
> 
> -		for (i = 0; i < num_updates; i++) {
> -			struct xe_bo *pt_bo = updates[i].pt_bo;
> +		for (i = 0; i < pt_update_ops->num_ops; ++i) {
> +			struct xe_vm_pgtable_update_op *pt_op =
> +				&pt_update_ops->ops[i];
> +			struct xe_vm_pgtable_update *updates = pt_op-
> >entries;
> 
> -			xe_tile_assert(tile, pt_bo->size == SZ_4K);
> +			for (j = 0; j < pt_op->num_entries; ++j, ++current_update)
> {
> +				struct xe_vm *vm = pt_update->vops->vm;
> +				struct xe_bo *pt_bo = updates[j].pt_bo;
> 
> -			addr = vm->pt_ops->pte_encode_bo(pt_bo, 0,
> pat_index, 0);
> -			bb->cs[bb->len++] = lower_32_bits(addr);
> -			bb->cs[bb->len++] = upper_32_bits(addr);
> +				xe_tile_assert(tile, pt_bo->size == SZ_4K);
> +
> +				/* Map a PT at most once */
> +				if (pt_bo->update_index < 0)
> +					pt_bo->update_index = current_update;
> +
> +				addr = vm->pt_ops->pte_encode_bo(pt_bo, 0,
> +								 XE_CACHE_WB,
> 0);
> +				bb->cs[bb->len++] = lower_32_bits(addr);
> +				bb->cs[bb->len++] = upper_32_bits(addr);
> +			}
>  		}
> 
>  		bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
> @@ -1369,22 +1316,39 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
> 
>  		addr = xe_migrate_vm_addr(ppgtt_ofs, 0) +
>  			(page_ofs / sizeof(u64)) * XE_PAGE_SIZE;
> -		for (i = 0; i < num_updates; i++)
> -			write_pgtable(tile, bb, addr + i * XE_PAGE_SIZE,
> -				      &updates[i], pt_update);
> +		for (i = 0; i < pt_update_ops->num_ops; ++i) {
> +			struct xe_vm_pgtable_update_op *pt_op =
> +				&pt_update_ops->ops[i];
> +			struct xe_vm_pgtable_update *updates = pt_op-
> >entries;
> +
> +			for (j = 0; j < pt_op->num_entries; ++j) {
> +				struct xe_bo *pt_bo = updates[j].pt_bo;
> +
> +				write_pgtable(tile, bb, addr +
> +					      pt_bo->update_index *
> XE_PAGE_SIZE,
> +					      pt_op, &updates[j], pt_update);
> +			}
> +		}
>  	} else {
>  		/* phys pages, no preamble required */
>  		bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
>  		update_idx = bb->len;
> 
> -		for (i = 0; i < num_updates; i++)
> -			write_pgtable(tile, bb, 0, &updates[i], pt_update);
> +		for (i = 0; i < pt_update_ops->num_ops; ++i) {
> +			struct xe_vm_pgtable_update_op *pt_op =
> +				&pt_update_ops->ops[i];
> +			struct xe_vm_pgtable_update *updates = pt_op-
> >entries;
> +
> +			for (j = 0; j < pt_op->num_entries; ++j)
> +				write_pgtable(tile, bb, 0, pt_op, &updates[j],
> +					      pt_update);
> +		}
>  	}
> 
> -	if (!q)
> +	if (is_migrate)
>  		mutex_lock(&m->job_mutex);
> 
> -	job = xe_bb_create_migration_job(q ?: m->q, bb,
> +	job = xe_bb_create_migration_job(pt_update_ops->q, bb,
>  					 xe_migrate_batch_base(m, usm),
>  					 update_idx);
>  	if (IS_ERR(job)) {
> @@ -1392,32 +1356,6 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
>  		goto err_bb;
>  	}
> 
> -	/* Wait on BO move */
> -	if (bo) {
> -		err = job_add_deps(job, bo->ttm.base.resv,
> -				   DMA_RESV_USAGE_KERNEL);
> -		if (err)
> -			goto err_job;
> -	}
> -
> -	/*
> -	 * Munmap style VM unbind, need to wait for all jobs to be complete /
> -	 * trigger preempts before moving forward
> -	 */
> -	if (first_munmap_rebind) {
> -		err = job_add_deps(job, xe_vm_resv(vm),
> -				   DMA_RESV_USAGE_BOOKKEEP);
> -		if (err)
> -			goto err_job;
> -	}
> -
> -	err = xe_sched_job_last_fence_add_dep(job, vm);
> -	for (i = 0; !err && i < num_syncs; i++)
> -		err = xe_sync_entry_add_deps(&syncs[i], job);
> -
> -	if (err)
> -		goto err_job;
> -
>  	if (ops->pre_commit) {
>  		pt_update->job = job;
>  		err = ops->pre_commit(pt_update);
> @@ -1428,7 +1366,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
>  	fence = dma_fence_get(&job->drm.s_fence->finished);
>  	xe_sched_job_push(job);
> 
> -	if (!q)
> +	if (is_migrate)
>  		mutex_unlock(&m->job_mutex);
> 
>  	xe_bb_free(bb, fence);
> @@ -1439,7 +1377,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
>  err_job:
>  	xe_sched_job_put(job);
>  err_bb:
> -	if (!q)
> +	if (is_migrate)
>  		mutex_unlock(&m->job_mutex);
>  	xe_bb_free(bb, NULL);
>  err:
> @@ -1447,6 +1385,38 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
>  	return ERR_PTR(err);
>  }
> 
> +/**
> + * xe_migrate_update_pgtables() - Pipelined page-table update
> + * @m: The migrate context.
> + * @pt_update: PT update arguments
> + *
> + * Perform a pipelined page-table update. The update descriptors are typically
> + * built under the same lock critical section as a call to this function. If
> + * using the default engine for the updates, they will be performed in the
> + * order they grab the job_mutex. If different engines are used, external
> + * synchronization is needed for overlapping updates to maintain page-table
> + * consistency. Note that the meaing of "overlapping" is that the updates
> + * touch the same page-table, which might be a higher-level page-directory.
> + * If no pipelining is needed, then updates may be performed by the cpu.
> + *
> + * Return: A dma_fence that, when signaled, indicates the update completion.
> + */
> +struct dma_fence *
> +xe_migrate_update_pgtables(struct xe_migrate *m,
> +			   struct xe_migrate_pt_update *pt_update)
> +
> +{
> +	struct xe_vm_pgtable_update_ops *pt_update_ops =
> +		&pt_update->vops->pt_update_ops[pt_update->tile_id];
> +	struct dma_fence *fence;
> +
> +	fence =  xe_migrate_update_pgtables_cpu(m, pt_update);

So now by default you use cpu to update page table first. Only if there is error you fall back to gpu page table update. Should we also consider performance here? For example, consider page table is usually in vram, isn't cpu writing to page table is usually slower than gpu writing?

> +	if (!IS_ERR(fence))
> +		return fence;
> +
> +	return __xe_migrate_update_pgtables(m, pt_update, pt_update_ops);
> +}
> +
>  /**
>   * xe_migrate_wait() - Complete all operations using the xe_migrate context
>   * @m: Migrate context to wait for.
> diff --git a/drivers/gpu/drm/xe/xe_migrate.h
> b/drivers/gpu/drm/xe/xe_migrate.h
> index 9935ce336bae..bd8eba1d3552 100644
> --- a/drivers/gpu/drm/xe/xe_migrate.h
> +++ b/drivers/gpu/drm/xe/xe_migrate.h
> @@ -47,6 +47,24 @@ struct xe_migrate_pt_update_ops {
>  			 struct xe_tile *tile, struct iosys_map *map,
>  			 void *pos, u32 ofs, u32 num_qwords,
>  			 const struct xe_vm_pgtable_update *update);
> +	/**
> +	 * @clear: Clear a command buffer or page-table with ptes.
> +	 * @pt_update: Embeddable callback argument.
> +	 * @tile: The tile for the current operation.
> +	 * @map: struct iosys_map into the memory to be populated.
> +	 * @pos: If @map is NULL, map into the memory to be populated.
> +	 * @ofs: qword offset into @map, unused if @map is NULL.
> +	 * @num_qwords: Number of qwords to write.
> +	 * @update: Information about the PTEs to be inserted.
> +	 *
> +	 * This interface is intended to be used as a callback into the
> +	 * page-table system to populate command buffers or shared
> +	 * page-tables with PTEs.
> +	 */
> +	void (*clear)(struct xe_migrate_pt_update *pt_update,
> +		      struct xe_tile *tile, struct iosys_map *map,
> +		      void *pos, u32 ofs, u32 num_qwords,
> +		      const struct xe_vm_pgtable_update *update);
> 
>  	/**
>  	 * @pre_commit: Callback to be called just before arming the
> @@ -67,14 +85,10 @@ struct xe_migrate_pt_update_ops {
>  struct xe_migrate_pt_update {
>  	/** @ops: Pointer to the struct xe_migrate_pt_update_ops callbacks */
>  	const struct xe_migrate_pt_update_ops *ops;
> -	/** @vma: The vma we're updating the pagetable for. */
> -	struct xe_vma *vma;
> +	/** @vops: VMA operations */
> +	struct xe_vma_ops *vops;
>  	/** @job: The job if a GPU page-table update. NULL otherwise */
>  	struct xe_sched_job *job;
> -	/** @start: Start of update for the range fence */
> -	u64 start;
> -	/** @last: Last of update for the range fence */
> -	u64 last;
>  	/** @tile_id: Tile ID of the update */
>  	u8 tile_id;
>  };
> @@ -96,12 +110,6 @@ struct xe_vm *xe_migrate_get_vm(struct xe_migrate
> *m);
> 
>  struct dma_fence *
>  xe_migrate_update_pgtables(struct xe_migrate *m,
> -			   struct xe_vm *vm,
> -			   struct xe_bo *bo,
> -			   struct xe_exec_queue *q,
> -			   const struct xe_vm_pgtable_update *updates,
> -			   u32 num_updates,
> -			   struct xe_sync_entry *syncs, u32 num_syncs,
>  			   struct xe_migrate_pt_update *pt_update);
> 
>  void xe_migrate_wait(struct xe_migrate *m);
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> index a878e2217c7f..5a8523d0a049 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -8,12 +8,14 @@
>  #include "xe_bo.h"
>  #include "xe_device.h"
>  #include "xe_drm_client.h"
> +#include "xe_exec_queue.h"
>  #include "xe_gt.h"
>  #include "xe_gt_tlb_invalidation.h"
>  #include "xe_migrate.h"
>  #include "xe_pt_types.h"
>  #include "xe_pt_walk.h"
>  #include "xe_res_cursor.h"
> +#include "xe_sync.h"
>  #include "xe_trace.h"
>  #include "xe_ttm_stolen_mgr.h"
>  #include "xe_vm.h"
> @@ -324,6 +326,7 @@ xe_pt_new_shared(struct xe_walk_update *wupd, struct
> xe_pt *parent,
>  	entry->pt = parent;
>  	entry->flags = 0;
>  	entry->qwords = 0;
> +	entry->pt_bo->update_index = -1;
> 
>  	if (alloc_entries) {
>  		entry->pt_entries = kmalloc_array(XE_PDES,
> @@ -831,9 +834,7 @@ static void xe_pt_commit_locks_assert(struct xe_vma
> *vma)
> 
>  	lockdep_assert_held(&vm->lock);
> 
> -	if (xe_vma_is_userptr(vma))
> -		lockdep_assert_held_read(&vm->userptr.notifier_lock);
> -	else if (!xe_vma_is_null(vma))
> +	if (!xe_vma_is_userptr(vma) && !xe_vma_is_null(vma))
>  		dma_resv_assert_held(xe_vma_bo(vma)->ttm.base.resv);
> 
>  	xe_vm_assert_held(vm);
> @@ -855,10 +856,8 @@ static void xe_pt_commit_bind(struct xe_vma *vma,
>  		if (!rebind)
>  			pt->num_live += entries[i].qwords;
> 
> -		if (!pt->level) {
> -			kfree(entries[i].pt_entries);
> +		if (!pt->level)
>  			continue;
> -		}
> 
>  		pt_dir = as_xe_pt_dir(pt);
>  		for (j = 0; j < entries[i].qwords; j++) {
> @@ -871,10 +870,18 @@ static void xe_pt_commit_bind(struct xe_vma *vma,
> 
>  			pt_dir->children[j_] = &newpte->base;
>  		}
> -		kfree(entries[i].pt_entries);
>  	}
>  }
> 
> +static void xe_pt_free_bind(struct xe_vm_pgtable_update *entries,
> +			    u32 num_entries)
> +{
> +	u32 i;
> +
> +	for (i = 0; i < num_entries; i++)
> +		kfree(entries[i].pt_entries);
> +}
> +
>  static int
>  xe_pt_prepare_bind(struct xe_tile *tile, struct xe_vma *vma,
>  		   struct xe_vm_pgtable_update *entries, u32 *num_entries)
> @@ -893,12 +900,13 @@ xe_pt_prepare_bind(struct xe_tile *tile, struct xe_vma
> *vma,
> 
>  static void xe_vm_dbg_print_entries(struct xe_device *xe,
>  				    const struct xe_vm_pgtable_update *entries,
> -				    unsigned int num_entries)
> +				    unsigned int num_entries, bool bind)
>  #if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_VM))
>  {
>  	unsigned int i;
> 
> -	vm_dbg(&xe->drm, "%u entries to update\n", num_entries);
> +	vm_dbg(&xe->drm, "%s: %u entries to update\n", bind ? "bind" :
> "unbind",
> +	       num_entries);
>  	for (i = 0; i < num_entries; i++) {
>  		const struct xe_vm_pgtable_update *entry = &entries[i];
>  		struct xe_pt *xe_pt = entry->pt;
> @@ -919,66 +927,122 @@ static void xe_vm_dbg_print_entries(struct xe_device
> *xe,
>  {}
>  #endif
> 
> -#ifdef CONFIG_DRM_XE_USERPTR_INVAL_INJECT
> +static int job_add_deps(struct xe_sched_job *job, struct dma_resv *resv,
> +			enum dma_resv_usage usage)
> +{
> +	return drm_sched_job_add_resv_dependencies(&job->drm, resv,
> usage);
> +}
> 
> -static int xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma)
> +static bool no_in_syncs(struct xe_sync_entry *syncs, u32 num_syncs)
>  {
> -	u32 divisor = uvma->userptr.divisor ? uvma->userptr.divisor : 2;
> -	static u32 count;
> +	int i;
> 
> -	if (count++ % divisor == divisor - 1) {
> -		struct xe_vm *vm = xe_vma_vm(&uvma->vma);
> +	for (i = 0; i < num_syncs; i++) {
> +		struct dma_fence *fence = syncs[i].fence;
> 
> -		uvma->userptr.divisor = divisor << 1;
> -		spin_lock(&vm->userptr.invalidated_lock);
> -		list_move_tail(&uvma->userptr.invalidate_link,
> -			       &vm->userptr.invalidated);
> -		spin_unlock(&vm->userptr.invalidated_lock);
> -		return true;
> +		if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
> +				       &fence->flags))
> +			return false;
>  	}
> 
> -	return false;
> +	return true;
>  }
> 
> -#else
> -
> -static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma)
> +static int vma_add_deps(struct xe_vma *vma, struct xe_sched_job *job)


From the implementation, it seems this is adding vma as a job's dependency...but the function name says add dependency to vma...

>  {
> -	return false;
> +	struct xe_bo *bo = xe_vma_bo(vma);
> +
> +	xe_bo_assert_held(bo);
> +
> +	if (bo && !bo->vm) {
> +		if (!job) {
> +			if (!dma_resv_test_signaled(bo->ttm.base.resv,
> +						    DMA_RESV_USAGE_KERNEL))
> +				return -ETIME;
> +		} else {
> +			return job_add_deps(job, bo->ttm.base.resv,
> +					    DMA_RESV_USAGE_KERNEL);
> +		}
> +	}
> +
> +	return 0;
>  }
> 
> -#endif
> +static int op_add_deps(struct xe_vm *vm, struct xe_vma_op *op,
> +		       struct xe_sched_job *job)
> +{
> +	int err = 0;
> 
> -/**
> - * struct xe_pt_migrate_pt_update - Callback argument for pre-commit callbacks
> - * @base: Base we derive from.
> - * @bind: Whether this is a bind or an unbind operation. A bind operation
> - *        makes the pre-commit callback error with -EAGAIN if it detects a
> - *        pending invalidation.
> - * @locked: Whether the pre-commit callback locked the userptr notifier lock
> - *          and it needs unlocking.
> - */
> -struct xe_pt_migrate_pt_update {
> -	struct xe_migrate_pt_update base;
> -	bool bind;
> -	bool locked;
> -};
> +	switch (op->base.op) {
> +	case DRM_GPUVA_OP_MAP:
> +		if (!op->map.immediate && xe_vm_in_fault_mode(vm))
> +			break;
> +
> +		err = vma_add_deps(op->map.vma, job);
> +		break;
> +	case DRM_GPUVA_OP_REMAP:
> +		if (op->remap.prev)
> +			err = vma_add_deps(op->remap.prev, job);
> +		if (!err && op->remap.next)
> +			err = vma_add_deps(op->remap.next, job);
> +		break;
> +	case DRM_GPUVA_OP_UNMAP:
> +		break;
> +	case DRM_GPUVA_OP_PREFETCH:
> +		err = vma_add_deps(gpuva_to_vma(op->base.prefetch.va), job);
> +		break;
> +	default:
> +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> +	}
> +
> +	return err;
> +}
> 
> -/*
> - * This function adds the needed dependencies to a page-table update job
> - * to make sure racing jobs for separate bind engines don't race writing
> - * to the same page-table range, wreaking havoc. Initially use a single
> - * fence for the entire VM. An optimization would use smaller granularity.
> - */
>  static int xe_pt_vm_dependencies(struct xe_sched_job *job,
> -				 struct xe_range_fence_tree *rftree,
> -				 u64 start, u64 last)
> +				 struct xe_vm *vm,
> +				 struct xe_vma_ops *vops,
> +				 struct xe_vm_pgtable_update_ops
> *pt_update_ops,
> +				 struct xe_range_fence_tree *rftree)
>  {
>  	struct xe_range_fence *rtfence;
>  	struct dma_fence *fence;
> -	int err;
> +	struct xe_vma_op *op;
> +	int err = 0, i;
> +
> +	xe_vm_assert_held(vm);
> +
> +	if (!job && !no_in_syncs(vops->syncs, vops->num_syncs))
> +		return -ETIME;
> +
> +	if (!job && !xe_exec_queue_is_idle(pt_update_ops->q))
> +		return -ETIME;
> 
> -	rtfence = xe_range_fence_tree_first(rftree, start, last);
> +	if (pt_update_ops->wait_vm_bookkeep) {
> +		if (!job) {
> +			if (!dma_resv_test_signaled(xe_vm_resv(vm),
> +
> DMA_RESV_USAGE_BOOKKEEP))
> +				return -ETIME;
> +		} else {
> +			err = job_add_deps(job, xe_vm_resv(vm),
> +					   DMA_RESV_USAGE_BOOKKEEP);
> +			if (err)
> +				return err;
> +		}
> +	} else if (pt_update_ops->wait_vm_kernel) {
> +		if (!job) {
> +			if (!dma_resv_test_signaled(xe_vm_resv(vm),
> +						    DMA_RESV_USAGE_KERNEL))
> +				return -ETIME;
> +		} else {
> +			err = job_add_deps(job, xe_vm_resv(vm),
> +					   DMA_RESV_USAGE_KERNEL);
> +			if (err)
> +				return err;
> +		}
> +	}
> +
> +	rtfence = xe_range_fence_tree_first(rftree, pt_update_ops->start,
> +					    pt_update_ops->last);
>  	while (rtfence) {
>  		fence = rtfence->fence;
> 
> @@ -996,80 +1060,136 @@ static int xe_pt_vm_dependencies(struct
> xe_sched_job *job,
>  				return err;
>  		}
> 
> -		rtfence = xe_range_fence_tree_next(rtfence, start, last);
> +		rtfence = xe_range_fence_tree_next(rtfence,
> +						   pt_update_ops->start,
> +						   pt_update_ops->last);
>  	}
> 
> -	return 0;
> +	list_for_each_entry(op, &vops->list, link) {
> +		err = op_add_deps(vm, op, job);
> +		if (err)
> +			return err;
> +	}
> +
> +	for (i = 0; job && !err && i < vops->num_syncs; i++)
> +		err = xe_sync_entry_add_deps(&vops->syncs[i], job);
> +
> +	return err;
>  }
> 
>  static int xe_pt_pre_commit(struct xe_migrate_pt_update *pt_update)
>  {
> -	struct xe_range_fence_tree *rftree =
> -		&xe_vma_vm(pt_update->vma)->rftree[pt_update->tile_id];
> +	struct xe_vma_ops *vops = pt_update->vops;
> +	struct xe_vm *vm = vops->vm;
> +	struct xe_range_fence_tree *rftree = &vm->rftree[pt_update->tile_id];
> +	struct xe_vm_pgtable_update_ops *pt_update_ops =
> +		&vops->pt_update_ops[pt_update->tile_id];
> +
> +	return xe_pt_vm_dependencies(pt_update->job, vm, pt_update->vops,
> +				     pt_update_ops, rftree);
> +}
> +
> +#ifdef CONFIG_DRM_XE_USERPTR_INVAL_INJECT
> +
> +static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma)
> +{
> +	u32 divisor = uvma->userptr.divisor ? uvma->userptr.divisor : 2;
> +	static u32 count;
> +
> +	if (count++ % divisor == divisor - 1) {
> +		uvma->userptr.divisor = divisor << 1;
> +		return true;
> +	}
> 
> -	return xe_pt_vm_dependencies(pt_update->job, rftree,
> -				     pt_update->start, pt_update->last);
> +	return false;
>  }
> 
> -static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> +#else
> +
> +static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma)
>  {
> -	struct xe_pt_migrate_pt_update *userptr_update =
> -		container_of(pt_update, typeof(*userptr_update), base);
> -	struct xe_userptr_vma *uvma = to_userptr_vma(pt_update->vma);
> -	unsigned long notifier_seq = uvma->userptr.notifier_seq;
> -	struct xe_vm *vm = xe_vma_vm(&uvma->vma);
> -	int err = xe_pt_vm_dependencies(pt_update->job,
> -					&vm->rftree[pt_update->tile_id],
> -					pt_update->start,
> -					pt_update->last);
> +	return false;
> +}
> 
> -	if (err)
> -		return err;
> +#endif
> 
> -	userptr_update->locked = false;
> +static void vma_check_userptr(struct xe_vm *vm, struct xe_vma *vma)
> +{
> +	struct xe_userptr_vma *uvma = to_userptr_vma(vma);
> +	unsigned long notifier_seq = uvma->userptr.notifier_seq;
> 
> -	/*
> -	 * Wait until nobody is running the invalidation notifier, and
> -	 * since we're exiting the loop holding the notifier lock,
> -	 * nobody can proceed invalidating either.
> -	 *
> -	 * Note that we don't update the vma->userptr.notifier_seq since
> -	 * we don't update the userptr pages.
> -	 */
> -	do {
> -		down_read(&vm->userptr.notifier_lock);
> -		if (!mmu_interval_read_retry(&uvma->userptr.notifier,
> -					     notifier_seq))
> -			break;
> +	lockdep_assert_held_read(&vm->userptr.notifier_lock);
> 
> -		up_read(&vm->userptr.notifier_lock);
> +	if (uvma->userptr.initial_bind || xe_vm_in_fault_mode(vm))
> +		return;
> 
> -		if (userptr_update->bind)
> -			return -EAGAIN;
> +	if (!mmu_interval_read_retry(&uvma->userptr.notifier,
> +				     notifier_seq) &&
> +	    !xe_pt_userptr_inject_eagain(uvma))
> +		return;

After this, we need to retry the get_user_pages_fast thing but I don't see how this is achieved...

Oak

> 
> -		notifier_seq = mmu_interval_read_begin(&uvma-
> >userptr.notifier);
> -	} while (true);
> +	spin_lock(&vm->userptr.invalidated_lock);
> +	list_move_tail(&uvma->userptr.invalidate_link,
> +		       &vm->userptr.invalidated);
> +	spin_unlock(&vm->userptr.invalidated_lock);
> 
> -	/* Inject errors to test_whether they are handled correctly */
> -	if (userptr_update->bind && xe_pt_userptr_inject_eagain(uvma)) {
> -		up_read(&vm->userptr.notifier_lock);
> -		return -EAGAIN;
> +	if (xe_vm_in_preempt_fence_mode(vm)) {
> +		struct dma_resv_iter cursor;
> +		struct dma_fence *fence;
> +
> +		dma_resv_iter_begin(&cursor, xe_vm_resv(vm),
> +				    DMA_RESV_USAGE_BOOKKEEP);
> +		dma_resv_for_each_fence_unlocked(&cursor, fence)
> +			dma_fence_enable_sw_signaling(fence);
> +		dma_resv_iter_end(&cursor);
>  	}
> +}
> 
> -	userptr_update->locked = true;
> +static void op_check_userptr(struct xe_vm *vm, struct xe_vma_op *op)
> +{
> +	lockdep_assert_held_read(&vm->userptr.notifier_lock);
> 
> -	return 0;
> +	switch (op->base.op) {
> +	case DRM_GPUVA_OP_MAP:
> +		if (!op->map.immediate && xe_vm_in_fault_mode(vm))
> +			break;
> +
> +		vma_check_userptr(vm, op->map.vma);
> +		break;
> +	case DRM_GPUVA_OP_REMAP:
> +		if (op->remap.prev)
> +			vma_check_userptr(vm, op->remap.prev);
> +		if (op->remap.next)
> +			vma_check_userptr(vm, op->remap.next);
> +		break;
> +	case DRM_GPUVA_OP_UNMAP:
> +		break;
> +	case DRM_GPUVA_OP_PREFETCH:
> +		vma_check_userptr(vm, gpuva_to_vma(op->base.prefetch.va));
> +		break;
> +	default:
> +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> +	}
>  }
> 
> -static const struct xe_migrate_pt_update_ops bind_ops = {
> -	.populate = xe_vm_populate_pgtable,
> -	.pre_commit = xe_pt_pre_commit,
> -};
> +static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> +{
> +	struct xe_vm *vm = pt_update->vops->vm;
> +	struct xe_vma_ops *vops = pt_update->vops;
> +	struct xe_vma_op *op;
> +	int err;
> 
> -static const struct xe_migrate_pt_update_ops userptr_bind_ops = {
> -	.populate = xe_vm_populate_pgtable,
> -	.pre_commit = xe_pt_userptr_pre_commit,
> -};
> +	err = xe_pt_pre_commit(pt_update);
> +	if (err)
> +		return err;
> +
> +	down_read(&vm->userptr.notifier_lock);
> +
> +	list_for_each_entry(op, &vops->list, link)
> +		op_check_userptr(vm, op);
> +
> +	return 0;
> +}
> 
>  struct invalidation_fence {
>  	struct xe_gt_tlb_invalidation_fence base;
> @@ -1166,181 +1286,6 @@ static int invalidation_fence_init(struct xe_gt *gt,
>  	return ret && ret != -ENOENT ? ret : 0;
>  }
> 
> -static void xe_pt_calc_rfence_interval(struct xe_vma *vma,
> -				       struct xe_pt_migrate_pt_update *update,
> -				       struct xe_vm_pgtable_update *entries,
> -				       u32 num_entries)
> -{
> -	int i, level = 0;
> -
> -	for (i = 0; i < num_entries; i++) {
> -		const struct xe_vm_pgtable_update *entry = &entries[i];
> -
> -		if (entry->pt->level > level)
> -			level = entry->pt->level;
> -	}
> -
> -	/* Greedy (non-optimal) calculation but simple */
> -	update->base.start = ALIGN_DOWN(xe_vma_start(vma),
> -					0x1ull << xe_pt_shift(level));
> -	update->base.last = ALIGN(xe_vma_end(vma),
> -				  0x1ull << xe_pt_shift(level)) - 1;
> -}
> -
> -/**
> - * __xe_pt_bind_vma() - Build and connect a page-table tree for the vma
> - * address range.
> - * @tile: The tile to bind for.
> - * @vma: The vma to bind.
> - * @q: The exec_queue with which to do pipelined page-table updates.
> - * @syncs: Entries to sync on before binding the built tree to the live vm tree.
> - * @num_syncs: Number of @sync entries.
> - * @rebind: Whether we're rebinding this vma to the same address range
> without
> - * an unbind in-between.
> - *
> - * This function builds a page-table tree (see xe_pt_stage_bind() for more
> - * information on page-table building), and the xe_vm_pgtable_update entries
> - * abstracting the operations needed to attach it to the main vm tree. It
> - * then takes the relevant locks and updates the metadata side of the main
> - * vm tree and submits the operations for pipelined attachment of the
> - * gpu page-table to the vm main tree, (which can be done either by the
> - * cpu and the GPU).
> - *
> - * Return: A valid dma-fence representing the pipelined attachment operation
> - * on success, an error pointer on error.
> - */
> -struct dma_fence *
> -__xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct
> xe_exec_queue *q,
> -		 struct xe_sync_entry *syncs, u32 num_syncs,
> -		 bool rebind)
> -{
> -	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
> -	struct xe_pt_migrate_pt_update bind_pt_update = {
> -		.base = {
> -			.ops = xe_vma_is_userptr(vma) ? &userptr_bind_ops :
> &bind_ops,
> -			.vma = vma,
> -			.tile_id = tile->id,
> -		},
> -		.bind = true,
> -	};
> -	struct xe_vm *vm = xe_vma_vm(vma);
> -	u32 num_entries;
> -	struct dma_fence *fence;
> -	struct invalidation_fence *ifence = NULL;
> -	struct xe_range_fence *rfence;
> -	int err;
> -
> -	bind_pt_update.locked = false;
> -	xe_bo_assert_held(xe_vma_bo(vma));
> -	xe_vm_assert_held(vm);
> -
> -	vm_dbg(&xe_vma_vm(vma)->xe->drm,
> -	       "Preparing bind, with range [%llx...%llx) engine %p.\n",
> -	       xe_vma_start(vma), xe_vma_end(vma), q);
> -
> -	err = xe_pt_prepare_bind(tile, vma, entries, &num_entries);
> -	if (err)
> -		goto err;
> -	xe_tile_assert(tile, num_entries <= ARRAY_SIZE(entries));
> -
> -	xe_vm_dbg_print_entries(tile_to_xe(tile), entries, num_entries);
> -	xe_pt_calc_rfence_interval(vma, &bind_pt_update, entries,
> -				   num_entries);
> -
> -	/*
> -	 * If rebind, we have to invalidate TLB on !LR vms to invalidate
> -	 * cached PTEs point to freed memory. on LR vms this is done
> -	 * automatically when the context is re-enabled by the rebind worker,
> -	 * or in fault mode it was invalidated on PTE zapping.
> -	 *
> -	 * If !rebind, and scratch enabled VMs, there is a chance the scratch
> -	 * PTE is already cached in the TLB so it needs to be invalidated.
> -	 * on !LR VMs this is done in the ring ops preceding a batch, but on
> -	 * non-faulting LR, in particular on user-space batch buffer chaining,
> -	 * it needs to be done here.
> -	 */
> -	if ((rebind && !xe_vm_in_lr_mode(vm) && !vm->batch_invalidate_tlb)
> ||
> -	    (!rebind && xe_vm_has_scratch(vm) &&
> xe_vm_in_preempt_fence_mode(vm))) {
> -		ifence = kzalloc(sizeof(*ifence), GFP_KERNEL);
> -		if (!ifence)
> -			return ERR_PTR(-ENOMEM);
> -	}
> -
> -	rfence = kzalloc(sizeof(*rfence), GFP_KERNEL);
> -	if (!rfence) {
> -		kfree(ifence);
> -		return ERR_PTR(-ENOMEM);
> -	}
> -
> -	fence = xe_migrate_update_pgtables(tile->migrate,
> -					   vm, xe_vma_bo(vma), q,
> -					   entries, num_entries,
> -					   syncs, num_syncs,
> -					   &bind_pt_update.base);
> -	if (!IS_ERR(fence)) {
> -		bool last_munmap_rebind = vma->gpuva.flags &
> XE_VMA_LAST_REBIND;
> -		LLIST_HEAD(deferred);
> -		int err;
> -
> -		err = xe_range_fence_insert(&vm->rftree[tile->id], rfence,
> -					    &xe_range_fence_kfree_ops,
> -					    bind_pt_update.base.start,
> -					    bind_pt_update.base.last, fence);
> -		if (err)
> -			dma_fence_wait(fence, false);
> -
> -		/* TLB invalidation must be done before signaling rebind */
> -		if (ifence) {
> -			int err = invalidation_fence_init(tile->primary_gt,
> -							  ifence, fence,
> -							  xe_vma_start(vma),
> -							  xe_vma_end(vma),
> -							  xe_vma_vm(vma)-
> >usm.asid);
> -			if (err) {
> -				dma_fence_put(fence);
> -				kfree(ifence);
> -				return ERR_PTR(err);
> -			}
> -			fence = &ifence->base.base;
> -		}
> -
> -		/* add shared fence now for pagetable delayed destroy */
> -		dma_resv_add_fence(xe_vm_resv(vm), fence, !rebind &&
> -				   last_munmap_rebind ?
> -				   DMA_RESV_USAGE_KERNEL :
> -				   DMA_RESV_USAGE_BOOKKEEP);
> -
> -		if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm)
> -			dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv,
> fence,
> -					   DMA_RESV_USAGE_BOOKKEEP);
> -		xe_pt_commit_bind(vma, entries, num_entries, rebind,
> -				  bind_pt_update.locked ? &deferred : NULL);
> -
> -		/* This vma is live (again?) now */
> -		vma->tile_present |= BIT(tile->id);
> -
> -		if (bind_pt_update.locked) {
> -			to_userptr_vma(vma)->userptr.initial_bind = true;
> -			up_read(&vm->userptr.notifier_lock);
> -			xe_bo_put_commit(&deferred);
> -		}
> -		if (!rebind && last_munmap_rebind &&
> -		    xe_vm_in_preempt_fence_mode(vm))
> -			xe_vm_queue_rebind_worker(vm);
> -	} else {
> -		kfree(rfence);
> -		kfree(ifence);
> -		if (bind_pt_update.locked)
> -			up_read(&vm->userptr.notifier_lock);
> -		xe_pt_abort_bind(vma, entries, num_entries);
> -	}
> -
> -	return fence;
> -
> -err:
> -	return ERR_PTR(err);
> -}
> -
>  struct xe_pt_stage_unbind_walk {
>  	/** @base: The pagewalk base-class. */
>  	struct xe_pt_walk base;
> @@ -1491,8 +1436,8 @@ xe_migrate_clear_pgtable_callback(struct
> xe_migrate_pt_update *pt_update,
>  				  void *ptr, u32 qword_ofs, u32 num_qwords,
>  				  const struct xe_vm_pgtable_update *update)
>  {
> -	struct xe_vma *vma = pt_update->vma;
> -	u64 empty = __xe_pt_empty_pte(tile, xe_vma_vm(vma), update->pt-
> >level);
> +	struct xe_vm *vm = pt_update->vops->vm;
> +	u64 empty = __xe_pt_empty_pte(tile, vm, update->pt->level);
>  	int i;
> 
>  	if (map && map->is_iomem)
> @@ -1536,144 +1481,443 @@ xe_pt_commit_unbind(struct xe_vma *vma,
>  	}
>  }
> 
> -static const struct xe_migrate_pt_update_ops unbind_ops = {
> -	.populate = xe_migrate_clear_pgtable_callback,
> +static void
> +xe_pt_update_ops_rfence_interval(struct xe_vm_pgtable_update_ops
> *pt_update_ops,
> +				 struct xe_vma *vma)
> +{
> +	u32 current_op = pt_update_ops->current_op;
> +	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops-
> >ops[current_op];
> +	int i, level = 0;
> +	u64 start, last;
> +
> +	for (i = 0; i < pt_op->num_entries; i++) {
> +		const struct xe_vm_pgtable_update *entry = &pt_op->entries[i];
> +
> +		if (entry->pt->level > level)
> +			level = entry->pt->level;
> +	}
> +
> +	/* Greedy (non-optimal) calculation but simple */
> +	start = ALIGN_DOWN(xe_vma_start(vma), 0x1ull << xe_pt_shift(level));
> +	last = ALIGN(xe_vma_end(vma), 0x1ull << xe_pt_shift(level)) - 1;
> +
> +	if (start < pt_update_ops->start)
> +		pt_update_ops->start = start;
> +	if (last > pt_update_ops->last)
> +		pt_update_ops->last = last;
> +}
> +
> +static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile,
> +			   struct xe_vm_pgtable_update_ops *pt_update_ops,
> +			   struct xe_vma *vma)
> +{
> +	u32 current_op = pt_update_ops->current_op;
> +	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops-
> >ops[current_op];
> +	struct llist_head *deferred = &pt_update_ops->deferred;
> +	int err;
> +
> +	xe_bo_assert_held(xe_vma_bo(vma));
> +
> +	vm_dbg(&xe_vma_vm(vma)->xe->drm,
> +	       "Preparing bind, with range [%llx...%llx)\n",
> +	       xe_vma_start(vma), xe_vma_end(vma) - 1);
> +
> +	pt_op->bind = true;
> +	pt_op->rebind = BIT(tile->id) & vma->tile_present;
> +
> +	err = xe_pt_prepare_bind(tile, vma, pt_op->entries,
> +				 &pt_op->num_entries);
> +	if (!err) {
> +		xe_tile_assert(tile, pt_op->num_entries <=
> +			       ARRAY_SIZE(pt_op->entries));
> +		xe_vm_dbg_print_entries(tile_to_xe(tile), pt_op->entries,
> +					pt_op->num_entries, true);
> +
> +		xe_pt_update_ops_rfence_interval(pt_update_ops, vma);
> +		++pt_update_ops->current_op;
> +		pt_update_ops->needs_userptr_lock |=
> xe_vma_is_userptr(vma);
> +
> +		/*
> +		 * If rebind, we have to invalidate TLB on !LR vms to invalidate
> +		 * cached PTEs point to freed memory. on LR vms this is done
> +		 * automatically when the context is re-enabled by the rebind
> +		 * worker, or in fault mode it was invalidated on PTE zapping.
> +		 *
> +		 * If !rebind, and scratch enabled VMs, there is a chance the
> +		 * scratch PTE is already cached in the TLB so it needs to be
> +		 * invalidated. on !LR VMs this is done in the ring ops
> +		 * preceding a batch, but on non-faulting LR, in particular on
> +		 * user-space batch buffer chaining, it needs to be done here.
> +		 */
> +		pt_update_ops->needs_invalidation |=
> +			(pt_op->rebind && xe_vm_in_lr_mode(vm) &&
> +			!vm->batch_invalidate_tlb) ||
> +			(!pt_op->rebind && vm->scratch_pt[tile->id] &&
> +			 xe_vm_in_preempt_fence_mode(vm));
> +
> +		/* FIXME: Don't commit right away */
> +		xe_pt_commit_bind(vma, pt_op->entries, pt_op->num_entries,
> +				  pt_op->rebind, deferred);
> +	}
> +
> +	return err;
> +}
> +
> +static int unbind_op_prepare(struct xe_tile *tile,
> +			     struct xe_vm_pgtable_update_ops *pt_update_ops,
> +			     struct xe_vma *vma)
> +{
> +	u32 current_op = pt_update_ops->current_op;
> +	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops-
> >ops[current_op];
> +	struct llist_head *deferred = &pt_update_ops->deferred;
> +
> +	xe_bo_assert_held(xe_vma_bo(vma));
> +
> +	vm_dbg(&xe_vma_vm(vma)->xe->drm,
> +	       "Preparing unbind, with range [%llx...%llx)\n",
> +	       xe_vma_start(vma), xe_vma_end(vma) - 1);
> +
> +	pt_op->bind = false;
> +	pt_op->rebind = false;
> +
> +	pt_op->num_entries = xe_pt_stage_unbind(tile, vma, pt_op->entries);
> +
> +	xe_vm_dbg_print_entries(tile_to_xe(tile), pt_op->entries,
> +				pt_op->num_entries, false);
> +	xe_pt_update_ops_rfence_interval(pt_update_ops, vma);
> +	++pt_update_ops->current_op;
> +	pt_update_ops->needs_userptr_lock |= xe_vma_is_userptr(vma);
> +	pt_update_ops->needs_invalidation = true;
> +
> +	/* FIXME: Don't commit right away */
> +	xe_pt_commit_unbind(vma, pt_op->entries, pt_op->num_entries,
> +			    deferred);
> +
> +	return 0;
> +}
> +
> +static int op_prepare(struct xe_vm *vm,
> +		      struct xe_tile *tile,
> +		      struct xe_vm_pgtable_update_ops *pt_update_ops,
> +		      struct xe_vma_op *op)
> +{
> +	int err = 0;
> +
> +	xe_vm_assert_held(vm);
> +
> +	switch (op->base.op) {
> +	case DRM_GPUVA_OP_MAP:
> +		if (!op->map.immediate && xe_vm_in_fault_mode(vm))
> +			break;
> +
> +		err = bind_op_prepare(vm, tile, pt_update_ops, op->map.vma);
> +		pt_update_ops->wait_vm_kernel = true;
> +		break;
> +	case DRM_GPUVA_OP_REMAP:
> +		err = unbind_op_prepare(tile, pt_update_ops,
> +					gpuva_to_vma(op->base.remap.unmap-
> >va));
> +
> +		if (!err && op->remap.prev) {
> +			err = bind_op_prepare(vm, tile, pt_update_ops,
> +					      op->remap.prev);
> +			pt_update_ops->wait_vm_bookkeep = true;
> +		}
> +		if (!err && op->remap.next) {
> +			err = bind_op_prepare(vm, tile, pt_update_ops,
> +					      op->remap.next);
> +			pt_update_ops->wait_vm_bookkeep = true;
> +		}
> +		break;
> +	case DRM_GPUVA_OP_UNMAP:
> +		err = unbind_op_prepare(tile, pt_update_ops,
> +					gpuva_to_vma(op->base.unmap.va));
> +		break;
> +	case DRM_GPUVA_OP_PREFETCH:
> +		err = bind_op_prepare(vm, tile, pt_update_ops,
> +				      gpuva_to_vma(op->base.prefetch.va));
> +		pt_update_ops->wait_vm_kernel = true;
> +		break;
> +	default:
> +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> +	}
> +
> +	return err;
> +}
> +
> +static void
> +xe_pt_update_ops_init(struct xe_vm_pgtable_update_ops *pt_update_ops)
> +{
> +	init_llist_head(&pt_update_ops->deferred);
> +	pt_update_ops->start = ~0x0ull;
> +	pt_update_ops->last = 0x0ull;
> +}
> +
> +/**
> + * xe_pt_update_ops_prepare() - Prepare PT update operations
> + * @tile: Tile of PT update operations
> + * @vops: VMA operationa
> + *
> + * Prepare PT update operations which includes updating internal PT state,
> + * allocate memory for page tables, populate page table being pruned in, and
> + * create PT update operations for leaf insertion / removal.
> + *
> + * Return: 0 on success, negative error code on error.
> + */
> +int xe_pt_update_ops_prepare(struct xe_tile *tile, struct xe_vma_ops *vops)
> +{
> +	struct xe_vm_pgtable_update_ops *pt_update_ops =
> +		&vops->pt_update_ops[tile->id];
> +	struct xe_vma_op *op;
> +	int err;
> +
> +	lockdep_assert_held(&vops->vm->lock);
> +	xe_vm_assert_held(vops->vm);
> +
> +	xe_pt_update_ops_init(pt_update_ops);
> +
> +	list_for_each_entry(op, &vops->list, link) {
> +		err = op_prepare(vops->vm, tile, pt_update_ops, op);
> +
> +		if (err)
> +			return err;
> +	}
> +
> +	xe_tile_assert(tile, pt_update_ops->current_op ==
> +		       pt_update_ops->num_ops);
> +
> +	return 0;
> +}
> +
> +static void bind_op_commit(struct xe_vm *vm, struct xe_tile *tile,
> +			   struct xe_vm_pgtable_update_ops *pt_update_ops,
> +			   struct xe_vma *vma, struct dma_fence *fence)
> +{
> +	if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm)
> +		dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence,
> +				   pt_update_ops->wait_vm_bookkeep ?
> +				   DMA_RESV_USAGE_KERNEL :
> +				   DMA_RESV_USAGE_BOOKKEEP);
> +	vma->tile_present |= BIT(tile->id);
> +	if (xe_vma_is_userptr(vma)) {
> +		lockdep_assert_held_read(&vm->userptr.notifier_lock);
> +		to_userptr_vma(vma)->userptr.initial_bind = true;
> +	}
> +
> +	/*
> +	 * Kick rebind worker if this bind triggers preempt fences and not in
> +	 * the rebind worker
> +	 */
> +	if (pt_update_ops->wait_vm_bookkeep &&
> +	    xe_vm_in_preempt_fence_mode(vm) &&
> +	    !current->mm)
> +		xe_vm_queue_rebind_worker(vm);
> +}
> +
> +static void unbind_op_commit(struct xe_vm *vm, struct xe_tile *tile,
> +			     struct xe_vm_pgtable_update_ops *pt_update_ops,
> +			     struct xe_vma *vma, struct dma_fence *fence)
> +{
> +	if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm)
> +		dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence,
> +				   pt_update_ops->wait_vm_bookkeep ?
> +				   DMA_RESV_USAGE_KERNEL :
> +				   DMA_RESV_USAGE_BOOKKEEP);
> +	vma->tile_present &= ~BIT(tile->id);
> +	if (!vma->tile_present) {
> +		list_del_init(&vma->combined_links.rebind);
> +		if (xe_vma_is_userptr(vma)) {
> +			lockdep_assert_held_read(&vm->userptr.notifier_lock);
> +
> +			spin_lock(&vm->userptr.invalidated_lock);
> +			list_del_init(&to_userptr_vma(vma)-
> >userptr.invalidate_link);
> +			spin_unlock(&vm->userptr.invalidated_lock);
> +		}
> +	}
> +}
> +
> +static void op_commit(struct xe_vm *vm,
> +		      struct xe_tile *tile,
> +		      struct xe_vm_pgtable_update_ops *pt_update_ops,
> +		      struct xe_vma_op *op, struct dma_fence *fence)
> +{
> +	xe_vm_assert_held(vm);
> +
> +	switch (op->base.op) {
> +	case DRM_GPUVA_OP_MAP:
> +		if (!op->map.immediate && xe_vm_in_fault_mode(vm))
> +			break;
> +
> +		bind_op_commit(vm, tile, pt_update_ops, op->map.vma, fence);
> +		break;
> +	case DRM_GPUVA_OP_REMAP:
> +		unbind_op_commit(vm, tile, pt_update_ops,
> +				 gpuva_to_vma(op->base.remap.unmap->va),
> fence);
> +
> +		if (op->remap.prev)
> +			bind_op_commit(vm, tile, pt_update_ops, op-
> >remap.prev,
> +				       fence);
> +		if (op->remap.next)
> +			bind_op_commit(vm, tile, pt_update_ops, op-
> >remap.next,
> +				       fence);
> +		break;
> +	case DRM_GPUVA_OP_UNMAP:
> +		unbind_op_commit(vm, tile, pt_update_ops,
> +				 gpuva_to_vma(op->base.unmap.va), fence);
> +		break;
> +	case DRM_GPUVA_OP_PREFETCH:
> +		bind_op_commit(vm, tile, pt_update_ops,
> +			       gpuva_to_vma(op->base.prefetch.va), fence);
> +		break;
> +	default:
> +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> +	}
> +}
> +
> +static const struct xe_migrate_pt_update_ops migrate_ops = {
> +	.populate = xe_vm_populate_pgtable,
> +	.clear = xe_migrate_clear_pgtable_callback,
>  	.pre_commit = xe_pt_pre_commit,
>  };
> 
> -static const struct xe_migrate_pt_update_ops userptr_unbind_ops = {
> -	.populate = xe_migrate_clear_pgtable_callback,
> +static const struct xe_migrate_pt_update_ops userptr_migrate_ops = {
> +	.populate = xe_vm_populate_pgtable,
> +	.clear = xe_migrate_clear_pgtable_callback,
>  	.pre_commit = xe_pt_userptr_pre_commit,
>  };
> 
>  /**
> - * __xe_pt_unbind_vma() - Disconnect and free a page-table tree for the vma
> - * address range.
> - * @tile: The tile to unbind for.
> - * @vma: The vma to unbind.
> - * @q: The exec_queue with which to do pipelined page-table updates.
> - * @syncs: Entries to sync on before disconnecting the tree to be destroyed.
> - * @num_syncs: Number of @sync entries.
> + * xe_pt_update_ops_run() - Run PT update operations
> + * @tile: Tile of PT update operations
> + * @vops: VMA operationa
>   *
> - * This function builds a the xe_vm_pgtable_update entries abstracting the
> - * operations needed to detach the page-table tree to be destroyed from the
> - * man vm tree.
> - * It then takes the relevant locks and submits the operations for
> - * pipelined detachment of the gpu page-table from  the vm main tree,
> - * (which can be done either by the cpu and the GPU), Finally it frees the
> - * detached page-table tree.
> + * Run PT update operations which includes committing internal PT state
> changes,
> + * creating job for PT update operations for leaf insertion / removal, and
> + * installing job fence in various places.
>   *
> - * Return: A valid dma-fence representing the pipelined detachment operation
> - * on success, an error pointer on error.
> + * Return: fence on success, negative ERR_PTR on error.
>   */
>  struct dma_fence *
> -__xe_pt_unbind_vma(struct xe_tile *tile, struct xe_vma *vma, struct
> xe_exec_queue *q,
> -		   struct xe_sync_entry *syncs, u32 num_syncs)
> +xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
>  {
> -	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
> -	struct xe_pt_migrate_pt_update unbind_pt_update = {
> -		.base = {
> -			.ops = xe_vma_is_userptr(vma) ? &userptr_unbind_ops :
> -			&unbind_ops,
> -			.vma = vma,
> -			.tile_id = tile->id,
> -		},
> -	};
> -	struct xe_vm *vm = xe_vma_vm(vma);
> -	u32 num_entries;
> -	struct dma_fence *fence = NULL;
> -	struct invalidation_fence *ifence;
> +	struct xe_vm *vm = vops->vm;
> +	struct xe_vm_pgtable_update_ops *pt_update_ops =
> +		&vops->pt_update_ops[tile->id];
> +	struct dma_fence *fence;
> +	struct invalidation_fence *ifence = NULL;
>  	struct xe_range_fence *rfence;
> +	struct xe_vma_op *op;
> +	int err = 0;
> +	struct xe_migrate_pt_update update = {
> +		.ops = pt_update_ops->needs_userptr_lock ?
> +			&userptr_migrate_ops :
> +			&migrate_ops,
> +		.vops = vops,
> +		.tile_id = tile->id
> +	};
> 
> -	LLIST_HEAD(deferred);
> -
> -	xe_bo_assert_held(xe_vma_bo(vma));
> +	lockdep_assert_held(&vm->lock);
>  	xe_vm_assert_held(vm);
> 
> -	vm_dbg(&xe_vma_vm(vma)->xe->drm,
> -	       "Preparing unbind, with range [%llx...%llx) engine %p.\n",
> -	       xe_vma_start(vma), xe_vma_end(vma), q);
> -
> -	num_entries = xe_pt_stage_unbind(tile, vma, entries);
> -	xe_tile_assert(tile, num_entries <= ARRAY_SIZE(entries));
> -
> -	xe_vm_dbg_print_entries(tile_to_xe(tile), entries, num_entries);
> -	xe_pt_calc_rfence_interval(vma, &unbind_pt_update, entries,
> -				   num_entries);
> -
> -	ifence = kzalloc(sizeof(*ifence), GFP_KERNEL);
> -	if (!ifence)
> -		return ERR_PTR(-ENOMEM);
> +	if (pt_update_ops->needs_invalidation) {
> +		ifence = kzalloc(sizeof(*ifence), GFP_KERNEL);
> +		if (!ifence)
> +			return ERR_PTR(-ENOMEM);
> +	}
> 
>  	rfence = kzalloc(sizeof(*rfence), GFP_KERNEL);
>  	if (!rfence) {
> -		kfree(ifence);
> -		return ERR_PTR(-ENOMEM);
> +		err = -ENOMEM;
> +		goto free_ifence;
>  	}
> 
> -	/*
> -	 * Even if we were already evicted and unbind to destroy, we need to
> -	 * clear again here. The eviction may have updated pagetables at a
> -	 * lower level, because it needs to be more conservative.
> -	 */
> -	fence = xe_migrate_update_pgtables(tile->migrate,
> -					   vm, NULL, q ? q :
> -					   vm->q[tile->id],
> -					   entries, num_entries,
> -					   syncs, num_syncs,
> -					   &unbind_pt_update.base);
> -	if (!IS_ERR(fence)) {
> -		int err;
> -
> -		err = xe_range_fence_insert(&vm->rftree[tile->id], rfence,
> -					    &xe_range_fence_kfree_ops,
> -					    unbind_pt_update.base.start,
> -					    unbind_pt_update.base.last, fence);
> -		if (err)
> -			dma_fence_wait(fence, false);
> +	fence = xe_migrate_update_pgtables(tile->migrate, &update);
> +	if (IS_ERR(fence)) {
> +		err = PTR_ERR(fence);
> +		goto free_rfence;
> +	}
> +
> +	err = xe_range_fence_insert(&vm->rftree[tile->id], rfence,
> +				    &xe_range_fence_kfree_ops,
> +				    pt_update_ops->start,
> +				    pt_update_ops->last, fence);
> +	if (err)
> +		dma_fence_wait(fence, false);
> 
> -		/* TLB invalidation must be done before signaling unbind */
> +	/* tlb invalidation must be done before signaling rebind */
> +	if (ifence) {
>  		err = invalidation_fence_init(tile->primary_gt, ifence, fence,
> -					      xe_vma_start(vma),
> -					      xe_vma_end(vma),
> -					      xe_vma_vm(vma)->usm.asid);
> -		if (err) {
> -			dma_fence_put(fence);
> -			kfree(ifence);
> -			return ERR_PTR(err);
> -		}
> +					      pt_update_ops->start,
> +					      pt_update_ops->last,
> +					      vm->usm.asid);
> +		if (err)
> +			goto put_fence;
>  		fence = &ifence->base.base;
> +	}
> 
> -		/* add shared fence now for pagetable delayed destroy */
> -		dma_resv_add_fence(xe_vm_resv(vm), fence,
> -				   DMA_RESV_USAGE_BOOKKEEP);
> +	dma_resv_add_fence(xe_vm_resv(vm), fence,
> +			   pt_update_ops->wait_vm_bookkeep ?
> +			   DMA_RESV_USAGE_KERNEL :
> +			   DMA_RESV_USAGE_BOOKKEEP);
> 
> -		/* This fence will be installed by caller when doing eviction */
> -		if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm)
> -			dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv,
> fence,
> -					   DMA_RESV_USAGE_BOOKKEEP);
> -		xe_pt_commit_unbind(vma, entries, num_entries,
> -				    unbind_pt_update.locked ? &deferred : NULL);
> -		vma->tile_present &= ~BIT(tile->id);
> -	} else {
> -		kfree(rfence);
> -		kfree(ifence);
> -	}
> +	list_for_each_entry(op, &vops->list, link)
> +		op_commit(vops->vm, tile, pt_update_ops, op, fence);
> 
> -	if (!vma->tile_present)
> -		list_del_init(&vma->combined_links.rebind);
> +	if (pt_update_ops->needs_userptr_lock)
> +		up_read(&vm->userptr.notifier_lock);
> 
> -	if (unbind_pt_update.locked) {
> -		xe_tile_assert(tile, xe_vma_is_userptr(vma));
> +	return fence;
> 
> -		if (!vma->tile_present) {
> -			spin_lock(&vm->userptr.invalidated_lock);
> -			list_del_init(&to_userptr_vma(vma)-
> >userptr.invalidate_link);
> -			spin_unlock(&vm->userptr.invalidated_lock);
> -		}
> +put_fence:
> +	if (pt_update_ops->needs_userptr_lock)
>  		up_read(&vm->userptr.notifier_lock);
> -		xe_bo_put_commit(&deferred);
> +	dma_fence_put(fence);
> +free_rfence:
> +	kfree(rfence);
> +free_ifence:
> +	kfree(ifence);
> +
> +	return ERR_PTR(err);
> +}
> +
> +/**
> + * xe_pt_update_ops_fini() - Finish PT update operations
> + * @tile: Tile of PT update operations
> + * @vops: VMA operations
> + *
> + * Finish PT update operations by committing to destroy page table memory
> + */
> +void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops)
> +{
> +	struct xe_vm_pgtable_update_ops *pt_update_ops =
> +		&vops->pt_update_ops[tile->id];
> +	int i;
> +
> +	lockdep_assert_held(&vops->vm->lock);
> +	xe_vm_assert_held(vops->vm);
> +
> +	/* FIXME: Not 100% correct */
> +	for (i = 0; i < pt_update_ops->num_ops; ++i) {
> +		struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops-
> >ops[i];
> +
> +		if (pt_op->bind)
> +			xe_pt_free_bind(pt_op->entries, pt_op->num_entries);
>  	}
> +	xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred);
> +}
> 
> -	return fence;
> +/**
> + * xe_pt_update_ops_abort() - Abort PT update operations
> + * @tile: Tile of PT update operations
> + * @vops: VMA operationa
> + *
> + *  Abort PT update operations by unwinding internal PT state
> + */
> +void xe_pt_update_ops_abort(struct xe_tile *tile, struct xe_vma_ops *vops)
> +{
> +	lockdep_assert_held(&vops->vm->lock);
> +	xe_vm_assert_held(vops->vm);
> +
> +	/* FIXME: Just kill VM for now + cleanup PTs */
> +	xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred);
> +	xe_vm_kill(vops->vm, false);
>  }
> diff --git a/drivers/gpu/drm/xe/xe_pt.h b/drivers/gpu/drm/xe/xe_pt.h
> index 71a4fbfcff43..cbf8170d89cc 100644
> --- a/drivers/gpu/drm/xe/xe_pt.h
> +++ b/drivers/gpu/drm/xe/xe_pt.h
> @@ -17,6 +17,7 @@ struct xe_sync_entry;
>  struct xe_tile;
>  struct xe_vm;
>  struct xe_vma;
> +struct xe_vma_ops;
> 
>  /* Largest huge pte is currently 1GiB. May become device dependent. */
>  #define MAX_HUGEPTE_LEVEL 2
> @@ -34,6 +35,12 @@ void xe_pt_populate_empty(struct xe_tile *tile, struct
> xe_vm *vm,
> 
>  void xe_pt_destroy(struct xe_pt *pt, u32 flags, struct llist_head *deferred);
> 
> +int xe_pt_update_ops_prepare(struct xe_tile *tile, struct xe_vma_ops *vops);
> +struct dma_fence *xe_pt_update_ops_run(struct xe_tile *tile,
> +				       struct xe_vma_ops *vops);
> +void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops);
> +void xe_pt_update_ops_abort(struct xe_tile *tile, struct xe_vma_ops *vops);
> +
>  struct dma_fence *
>  __xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct
> xe_exec_queue *q,
>  		 struct xe_sync_entry *syncs, u32 num_syncs,
> diff --git a/drivers/gpu/drm/xe/xe_pt_types.h
> b/drivers/gpu/drm/xe/xe_pt_types.h
> index 2093150f461e..16252f1be055 100644
> --- a/drivers/gpu/drm/xe/xe_pt_types.h
> +++ b/drivers/gpu/drm/xe/xe_pt_types.h
> @@ -86,4 +86,38 @@ struct xe_vm_pgtable_update_op {
>  	bool rebind;
>  };
> 
> +/** struct xe_vm_pgtable_update_ops: page table update operations */
> +struct xe_vm_pgtable_update_ops {
> +	/** @ops: operations */
> +	struct xe_vm_pgtable_update_op *ops;
> +	/** @deferred: deferred list to destroy PT entries */
> +	struct llist_head deferred;
> +	/** @q: exec queue for PT operations */
> +	struct xe_exec_queue *q;
> +	/** @start: start address of ops */
> +	u64 start;
> +	/** @last: last address of ops */
> +	u64 last;
> +	/** @num_ops: number of operations */
> +	u32 num_ops;
> +	/** @current_op: current operations */
> +	u32 current_op;
> +	/** @needs_userptr_lock: Needs userptr lock */
> +	bool needs_userptr_lock;
> +	/** @needs_invalidation: Needs invalidation */
> +	bool needs_invalidation;
> +	/**
> +	 * @wait_vm_bookkeep: PT operations need to wait until VM is idle
> +	 * (bookkeep dma-resv slots are idle) and stage all future VM activity
> +	 * behind these operations (install PT operations into VM kernel
> +	 * dma-resv slot).
> +	 */
> +	bool wait_vm_bookkeep;
> +	/**
> +	 * @wait_vm_kernel: PT operations need to wait until VM kernel dma-
> resv
> +	 * slots are idle.
> +	 */
> +	bool wait_vm_kernel;
> +};
> +
>  #endif
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 72e9bdab79d5..47658465b735 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -413,7 +413,7 @@ int __xe_vm_userptr_needs_repin(struct xe_vm *vm)
> 
>  #define XE_VM_REBIND_RETRY_TIMEOUT_MS 1000
> 
> -static void xe_vm_kill(struct xe_vm *vm, bool unlocked)
> +void xe_vm_kill(struct xe_vm *vm, bool unlocked)
>  {
>  	struct xe_exec_queue *q;
> 
> @@ -577,13 +577,9 @@ static void preempt_rebind_work_func(struct
> work_struct *w)
>  		err = PTR_ERR(rebind_fence);
>  		goto out_unlock;
>  	}
> +	dma_fence_put(rebind_fence);
> 
> -	if (rebind_fence) {
> -		dma_fence_wait(rebind_fence, false);
> -		dma_fence_put(rebind_fence);
> -	}
> -
> -	/* Wait on munmap style VM unbinds */
> +	/* Wait on rebinds */
>  	wait = dma_resv_wait_timeout(xe_vm_resv(vm),
>  				     DMA_RESV_USAGE_KERNEL,
>  				     false, MAX_SCHEDULE_TIMEOUT);
> @@ -759,11 +755,35 @@ int xe_vm_userptr_check_repin(struct xe_vm *vm)
>   * xe_vm_populate_dummy_rebind() - Populate dummy rebind VMA ops
>   * @vm: The VM.
>   * @vma: VMA to populate dummy VMA ops
> + * @tile_mask: tile mask for VMA ops
>   *
>   * Populate dummy VMA ops which can be used to issue a rebind for the VMA
>   */
> -void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma)
> +void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma,
> +				 u8 tile_mask)
>  {
> +	int i;
> +
> +	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) {
> +		if (BIT(i) & tile_mask) {
> +			struct xe_vm_pgtable_update_op *pt_op =
> +				vm->dummy_ops.vops.pt_update_ops[i].ops;
> +
> +			memset(&vm->dummy_ops.vops.pt_update_ops[i], 0,
> +			       sizeof(vm->dummy_ops.vops.pt_update_ops[i]));
> +			vm->dummy_ops.vops.pt_update_ops[i].ops = pt_op;
> +			vm->dummy_ops.vops.pt_update_ops[i].num_ops = 1;
> +
> +			/*
> +			 * Wait for VM to be idle / schedule execs + resume
> +			 * behind rebinds
> +			 */
> +			vm-
> >dummy_ops.vops.pt_update_ops[i].wait_vm_bookkeep =
> +				true;
> +		} else {
> +			vm->dummy_ops.vops.pt_update_ops[i].num_ops = 0;
> +		}
> +	}
>  	vm->dummy_ops.op.base.op = DRM_GPUVA_OP_MAP;
>  	vm->dummy_ops.op.base.map.va.addr = vma->gpuva.va.addr;
>  	vm->dummy_ops.op.base.map.va.range = vma->gpuva.va.range;
> @@ -797,7 +817,7 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm,
> bool rebind_worker)
>  		else
>  			trace_xe_vma_rebind_exec(vma);
> 
> -		xe_vm_populate_dummy_rebind(vm, vma);
> +		xe_vm_populate_dummy_rebind(vm, vma, vma->tile_present);
>  		fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
>  		if (IS_ERR(fence))
>  			return fence;
> @@ -1653,7 +1673,6 @@ static void vm_destroy_work_func(struct work_struct
> *w)
>  		XE_WARN_ON(vm->pt_root[id]);
> 
>  	trace_xe_vm_free(vm);
> -	dma_fence_put(vm->rebind_fence);
>  	xe_vma_ops_fini(&vm->dummy_ops.vops);
>  	kfree(vm);
>  }
> @@ -1691,147 +1710,6 @@ to_wait_exec_queue(struct xe_vm *vm, struct
> xe_exec_queue *q)
>  	return q ? q : vm->q[0];
>  }
> 
> -static struct dma_fence *
> -xe_vm_unbind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
> -		 struct xe_sync_entry *syncs, u32 num_syncs,
> -		 bool first_op, bool last_op)
> -{
> -	struct xe_vm *vm = xe_vma_vm(vma);
> -	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> q);
> -	struct xe_tile *tile;
> -	struct dma_fence *fence = NULL;
> -	struct dma_fence **fences = NULL;
> -	struct dma_fence_array *cf = NULL;
> -	int cur_fence = 0;
> -	int number_tiles = hweight8(vma->tile_present);
> -	int err;
> -	u8 id;
> -
> -	trace_xe_vma_unbind(vma);
> -
> -	if (number_tiles > 1) {
> -		fences = kmalloc_array(number_tiles, sizeof(*fences),
> -				       GFP_KERNEL);
> -		if (!fences)
> -			return ERR_PTR(-ENOMEM);
> -	}
> -
> -	for_each_tile(tile, vm->xe, id) {
> -		if (!(vma->tile_present & BIT(id)))
> -			goto next;
> -
> -		fence = __xe_pt_unbind_vma(tile, vma, q ? q : vm->q[id],
> -					   first_op ? syncs : NULL,
> -					   first_op ? num_syncs : 0);
> -		if (IS_ERR(fence)) {
> -			err = PTR_ERR(fence);
> -			goto err_fences;
> -		}
> -
> -		if (fences)
> -			fences[cur_fence++] = fence;
> -
> -next:
> -		if (q && vm->pt_root[id] && !list_empty(&q->multi_gt_list))
> -			q = list_next_entry(q, multi_gt_list);
> -	}
> -
> -	if (fences) {
> -		cf = dma_fence_array_create(number_tiles, fences,
> -					    vm->composite_fence_ctx,
> -					    vm->composite_fence_seqno++,
> -					    false);
> -		if (!cf) {
> -			--vm->composite_fence_seqno;
> -			err = -ENOMEM;
> -			goto err_fences;
> -		}
> -	}
> -
> -	fence = cf ? &cf->base : !fence ?
> -		xe_exec_queue_last_fence_get(wait_exec_queue, vm) : fence;
> -
> -	return fence;
> -
> -err_fences:
> -	if (fences) {
> -		while (cur_fence)
> -			dma_fence_put(fences[--cur_fence]);
> -		kfree(fences);
> -	}
> -
> -	return ERR_PTR(err);
> -}
> -
> -static struct dma_fence *
> -xe_vm_bind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
> -	       struct xe_sync_entry *syncs, u32 num_syncs,
> -	       u8 tile_mask, bool first_op, bool last_op)
> -{
> -	struct xe_tile *tile;
> -	struct dma_fence *fence;
> -	struct dma_fence **fences = NULL;
> -	struct dma_fence_array *cf = NULL;
> -	struct xe_vm *vm = xe_vma_vm(vma);
> -	int cur_fence = 0;
> -	int number_tiles = hweight8(vma->tile_mask);
> -	int err;
> -	u8 id;
> -
> -	trace_xe_vma_bind(vma);
> -
> -	if (number_tiles > 1) {
> -		fences = kmalloc_array(number_tiles, sizeof(*fences),
> -				       GFP_KERNEL);
> -		if (!fences)
> -			return ERR_PTR(-ENOMEM);
> -	}
> -
> -	for_each_tile(tile, vm->xe, id) {
> -		if (!(tile_mask & BIT(id)))
> -			goto next;
> -
> -		fence = __xe_pt_bind_vma(tile, vma, q ? q : vm->q[id],
> -					 first_op ? syncs : NULL,
> -					 first_op ? num_syncs : 0,
> -					 vma->tile_present & BIT(id));
> -		if (IS_ERR(fence)) {
> -			err = PTR_ERR(fence);
> -			goto err_fences;
> -		}
> -
> -		if (fences)
> -			fences[cur_fence++] = fence;
> -
> -next:
> -		if (q && vm->pt_root[id] && !list_empty(&q->multi_gt_list))
> -			q = list_next_entry(q, multi_gt_list);
> -	}
> -
> -	if (fences) {
> -		cf = dma_fence_array_create(number_tiles, fences,
> -					    vm->composite_fence_ctx,
> -					    vm->composite_fence_seqno++,
> -					    false);
> -		if (!cf) {
> -			--vm->composite_fence_seqno;
> -			err = -ENOMEM;
> -			goto err_fences;
> -		}
> -	}
> -
> -	return cf ? &cf->base : fence;
> -
> -err_fences:
> -	if (fences) {
> -		while (cur_fence)
> -			dma_fence_put(fences[--cur_fence]);
> -		kfree(fences);
> -	}
> -
> -	return ERR_PTR(err);
> -}
> -
>  static struct xe_user_fence *
>  find_ufence_get(struct xe_sync_entry *syncs, u32 num_syncs)
>  {
> @@ -1847,47 +1725,6 @@ find_ufence_get(struct xe_sync_entry *syncs, u32
> num_syncs)
>  	return NULL;
>  }
> 
> -static struct dma_fence *
> -xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue *q,
> -	   struct xe_bo *bo, struct xe_sync_entry *syncs, u32 num_syncs,
> -	   u8 tile_mask, bool immediate, bool first_op, bool last_op)
> -{
> -	struct dma_fence *fence;
> -	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> q);
> -
> -	xe_vm_assert_held(vm);
> -	xe_bo_assert_held(bo);
> -
> -	if (immediate) {
> -		fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, tile_mask,
> -				       first_op, last_op);
> -		if (IS_ERR(fence))
> -			return fence;
> -	} else {
> -		xe_assert(vm->xe, xe_vm_in_fault_mode(vm));
> -		fence = xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> -	}
> -
> -	return fence;
> -}
> -
> -static struct dma_fence *
> -xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
> -	     struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> -	     u32 num_syncs, bool first_op, bool last_op)
> -{
> -	struct dma_fence *fence;
> -
> -	xe_vm_assert_held(vm);
> -	xe_bo_assert_held(xe_vma_bo(vma));
> -
> -	fence = xe_vm_unbind_vma(vma, q, syncs, num_syncs, first_op,
> last_op);
> -	if (IS_ERR(fence))
> -		return fence;
> -
> -	return fence;
> -}
> -
>  #define ALL_DRM_XE_VM_CREATE_FLAGS
> (DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE | \
>  				    DRM_XE_VM_CREATE_FLAG_LR_MODE | \
>  				    DRM_XE_VM_CREATE_FLAG_FAULT_MODE)
> @@ -2028,21 +1865,6 @@ static const u32 region_to_mem_type[] = {
>  	XE_PL_VRAM1,
>  };
> 
> -static struct dma_fence *
> -xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
> -	       struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> -	       u32 num_syncs, bool first_op, bool last_op)
> -{
> -	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> q);
> -
> -	if (vma->tile_mask != (vma->tile_present & ~vma->usm.tile_invalidated))
> {
> -		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs,
> num_syncs,
> -				  vma->tile_mask, true, first_op, last_op);
> -	} else {
> -		return xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> -	}
> -}
> -
>  static void prep_vma_destroy(struct xe_vm *vm, struct xe_vma *vma,
>  			     bool post_commit)
>  {
> @@ -2334,7 +2156,6 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm,
> struct xe_exec_queue *q,
>  				   struct xe_vma_ops *vops, bool last)
>  {
>  	struct xe_device *xe = vm->xe;
> -	struct xe_vma_op *last_op = NULL;
>  	struct drm_gpuva_op *__op;
>  	struct xe_tile *tile;
>  	u8 id, tile_mask = 0;
> @@ -2348,19 +2169,10 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> *vm, struct xe_exec_queue *q,
>  	drm_gpuva_for_each_op(__op, ops) {
>  		struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
>  		struct xe_vma *vma;
> -		bool first = list_empty(&vops->list);
>  		unsigned int flags = 0;
> 
>  		INIT_LIST_HEAD(&op->link);
>  		list_add_tail(&op->link, &vops->list);
> -
> -		if (first) {
> -			op->flags |= XE_VMA_OP_FIRST;
> -			op->num_syncs = num_syncs;
> -			op->syncs = syncs;
> -		}
> -
> -		op->q = q;
>  		op->tile_mask = tile_mask;
> 
>  		switch (op->base.op) {
> @@ -2471,196 +2283,21 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> *vm, struct xe_exec_queue *q,
>  		}
>  		case DRM_GPUVA_OP_UNMAP:
>  		case DRM_GPUVA_OP_PREFETCH:
> +			/* FIXME: Need to skip some prefetch ops */
>  			xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask);
>  			break;
>  		default:
>  			drm_warn(&vm->xe->drm, "NOT POSSIBLE");
>  		}
> 
> -		last_op = op;
> -
>  		err = xe_vma_op_commit(vm, op);
>  		if (err)
>  			return err;
>  	}
> 
> -	/* FIXME: Unhandled corner case */
> -	XE_WARN_ON(!last_op && last && !list_empty(&vops->list));
> -
> -	if (!last_op)
> -		return 0;
> -
> -	if (last) {
> -		last_op->flags |= XE_VMA_OP_LAST;
> -		last_op->num_syncs = num_syncs;
> -		last_op->syncs = syncs;
> -	}
> -
>  	return 0;
>  }
> 
> -static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma *vma,
> -				    struct xe_vma_op *op)
> -{
> -	struct dma_fence *fence = NULL;
> -
> -	lockdep_assert_held(&vm->lock);
> -	xe_vm_assert_held(vm);
> -	xe_bo_assert_held(xe_vma_bo(vma));
> -
> -	switch (op->base.op) {
> -	case DRM_GPUVA_OP_MAP:
> -		/* FIXME: Override vma->tile_mask for page faults */
> -		fence = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
> -				   op->syncs, op->num_syncs,
> -				   op->map.immediate,
> -				   op->tile_mask,
> -				   op->flags & XE_VMA_OP_FIRST,
> -				   op->flags & XE_VMA_OP_LAST);
> -		break;
> -	case DRM_GPUVA_OP_REMAP:
> -	{
> -		bool prev = !!op->remap.prev;
> -		bool next = !!op->remap.next;
> -
> -		if (!op->remap.unmap_done) {
> -			if (prev || next)
> -				vma->gpuva.flags |= XE_VMA_FIRST_REBIND;
> -			fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
> -					     op->num_syncs,
> -					     op->flags & XE_VMA_OP_FIRST,
> -					     op->flags & XE_VMA_OP_LAST &&
> -					     !prev && !next);
> -			if (IS_ERR(fence))
> -				break;
> -			op->remap.unmap_done = true;
> -		}
> -
> -		if (prev) {
> -			op->remap.prev->gpuva.flags |= XE_VMA_LAST_REBIND;
> -			dma_fence_put(fence);
> -			fence = xe_vm_bind(vm, op->remap.prev, op->q,
> -					   xe_vma_bo(op->remap.prev), op-
> >syncs,
> -					   op->num_syncs, op->remap.prev-
> >tile_mask,
> -					   true, false,
> -					   op->flags & XE_VMA_OP_LAST
> && !next);
> -			op->remap.prev->gpuva.flags &=
> ~XE_VMA_LAST_REBIND;
> -			if (IS_ERR(fence))
> -				break;
> -			op->remap.prev = NULL;
> -		}
> -
> -		if (next) {
> -			op->remap.next->gpuva.flags |= XE_VMA_LAST_REBIND;
> -			dma_fence_put(fence);
> -			fence = xe_vm_bind(vm, op->remap.next, op->q,
> -					   xe_vma_bo(op->remap.next),
> -					   op->syncs, op->num_syncs,
> -					   op->remap.next->tile_mask, true, false,
> -					   op->flags & XE_VMA_OP_LAST);
> -			op->remap.next->gpuva.flags &=
> ~XE_VMA_LAST_REBIND;
> -			if (IS_ERR(fence))
> -				break;
> -			op->remap.next = NULL;
> -		}
> -
> -		break;
> -	}
> -	case DRM_GPUVA_OP_UNMAP:
> -		fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
> -				     op->num_syncs, op->flags &
> XE_VMA_OP_FIRST,
> -				     op->flags & XE_VMA_OP_LAST);
> -		break;
> -	case DRM_GPUVA_OP_PREFETCH:
> -		fence = xe_vm_prefetch(vm, vma, op->q, op->syncs, op-
> >num_syncs,
> -				       op->flags & XE_VMA_OP_FIRST,
> -				       op->flags & XE_VMA_OP_LAST);
> -		break;
> -	default:
> -		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> -	}
> -
> -	if (IS_ERR(fence))
> -		trace_xe_vma_fail(vma);
> -
> -	return fence;
> -}
> -
> -static struct dma_fence *
> -__xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
> -		    struct xe_vma_op *op)
> -{
> -	struct dma_fence *fence;
> -	int err;
> -
> -retry_userptr:
> -	fence = op_execute(vm, vma, op);
> -	if (IS_ERR(fence) && PTR_ERR(fence) == -EAGAIN) {
> -		lockdep_assert_held(&vm->lock);
> -
> -		if (op->base.op == DRM_GPUVA_OP_REMAP) {
> -			if (!op->remap.unmap_done)
> -				vma = gpuva_to_vma(op->base.remap.unmap-
> >va);
> -			else if (op->remap.prev)
> -				vma = op->remap.prev;
> -			else
> -				vma = op->remap.next;
> -		}
> -
> -		if (xe_vma_is_userptr(vma)) {
> -			err = xe_vma_userptr_pin_pages(to_userptr_vma(vma));
> -			if (!err)
> -				goto retry_userptr;
> -
> -			fence = ERR_PTR(err);
> -			trace_xe_vma_fail(vma);
> -		}
> -	}
> -
> -	return fence;
> -}
> -
> -static struct dma_fence *
> -xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
> -{
> -	struct dma_fence *fence = ERR_PTR(-ENOMEM);
> -
> -	lockdep_assert_held(&vm->lock);
> -
> -	switch (op->base.op) {
> -	case DRM_GPUVA_OP_MAP:
> -		fence = __xe_vma_op_execute(vm, op->map.vma, op);
> -		break;
> -	case DRM_GPUVA_OP_REMAP:
> -	{
> -		struct xe_vma *vma;
> -
> -		if (!op->remap.unmap_done)
> -			vma = gpuva_to_vma(op->base.remap.unmap->va);
> -		else if (op->remap.prev)
> -			vma = op->remap.prev;
> -		else
> -			vma = op->remap.next;
> -
> -		fence = __xe_vma_op_execute(vm, vma, op);
> -		break;
> -	}
> -	case DRM_GPUVA_OP_UNMAP:
> -		fence = __xe_vma_op_execute(vm, gpuva_to_vma(op-
> >base.unmap.va),
> -					    op);
> -		break;
> -	case DRM_GPUVA_OP_PREFETCH:
> -		fence = __xe_vma_op_execute(vm,
> -					    gpuva_to_vma(op->base.prefetch.va),
> -					    op);
> -		break;
> -	default:
> -		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> -	}
> -
> -	return fence;
> -}
> -
>  static void xe_vma_op_unwind(struct xe_vm *vm, struct xe_vma_op *op,
>  			     bool post_commit, bool prev_post_commit,
>  			     bool next_post_commit)
> @@ -2837,6 +2474,32 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec
> *exec,
>  	return 0;
>  }
> 
> +static int vm_ops_setup_tile_args(struct xe_vm *vm, struct xe_vma_ops *vops)
> +{
> +	struct xe_exec_queue *q = vops->q;
> +	struct xe_tile *tile;
> +	int number_tiles = 0;
> +	u8 id;
> +
> +	for_each_tile(tile, vm->xe, id) {
> +		if (vops->pt_update_ops[id].num_ops)
> +			++number_tiles;
> +
> +		if (vops->pt_update_ops[id].q)
> +			continue;
> +
> +		if (q) {
> +			vops->pt_update_ops[id].q = q;
> +			if (vm->pt_root[id] && !list_empty(&q->multi_gt_list))
> +				q = list_next_entry(q, multi_gt_list);
> +		} else {
> +			vops->pt_update_ops[id].q = vm->q[id];
> +		}
> +	}
> +
> +	return number_tiles;
> +}
> +
>  /**
>   * xe_vm_ops_execute() - Execute VMA ops
>   * @vm: The VM.
> @@ -2848,21 +2511,81 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec
> *exec,
>   */
>  struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops
> *vops)
>  {
> -	struct xe_vma_op *op, *next;
> +	struct xe_tile *tile;
>  	struct dma_fence *fence = NULL;
> +	struct dma_fence **fences = NULL;
> +	struct dma_fence_array *cf = NULL;
> +	int number_tiles = 0, current_fence = 0, err;
> +	u8 id;
> +
> +	number_tiles = vm_ops_setup_tile_args(vm, vops);
> +	if (number_tiles == 0)
> +		return ERR_PTR(-ENODATA);
> +
> +	if (number_tiles > 1) {
> +		fences = kmalloc_array(number_tiles, sizeof(*fences),
> +				       GFP_KERNEL);
> +		if (!fences)
> +			return ERR_PTR(-ENOMEM);
> +	}
> +
> +	for_each_tile(tile, vm->xe, id) {
> +		if (!vops->pt_update_ops[id].num_ops)
> +			continue;
> 
> -	list_for_each_entry_safe(op, next, &vops->list, link) {
> -		if (!IS_ERR(fence)) {
> -			dma_fence_put(fence);
> -			fence = xe_vma_op_execute(vm, op);
> +		err = xe_pt_update_ops_prepare(tile, vops);
> +		if (err) {
> +			fence = ERR_PTR(err);
> +			goto err_out;
>  		}
> -		if (IS_ERR(fence)) {
> -			drm_warn(&vm->xe->drm, "VM op(%d) failed with %ld",
> -				 op->base.op, PTR_ERR(fence));
> -			fence = ERR_PTR(-ENOSPC);
> +	}
> +
> +	for_each_tile(tile, vm->xe, id) {
> +		if (!vops->pt_update_ops[id].num_ops)
> +			continue;
> +
> +		fence = xe_pt_update_ops_run(tile, vops);
> +		if (IS_ERR(fence))
> +			goto err_out;
> +
> +		if (fences)
> +			fences[current_fence++] = fence;
> +	}
> +
> +	if (fences) {
> +		cf = dma_fence_array_create(number_tiles, fences,
> +					    vm->composite_fence_ctx,
> +					    vm->composite_fence_seqno++,
> +					    false);
> +		if (!cf) {
> +			--vm->composite_fence_seqno;
> +			fence = ERR_PTR(-ENOMEM);
> +			goto err_out;
>  		}
> +		fence = &cf->base;
> +	}
> +
> +	for_each_tile(tile, vm->xe, id) {
> +		if (!vops->pt_update_ops[id].num_ops)
> +			continue;
> +
> +		xe_pt_update_ops_fini(tile, vops);
>  	}
> 
> +	return fence;
> +
> +err_out:
> +	for_each_tile(tile, vm->xe, id) {
> +		if (!vops->pt_update_ops[id].num_ops)
> +			continue;
> +
> +		xe_pt_update_ops_abort(tile, vops);
> +	}
> +	while (current_fence)
> +		dma_fence_put(fences[--current_fence]);
> +	kfree(fences);
> +	kfree(cf);
> +
>  	return fence;
>  }
> 
> @@ -2944,12 +2667,10 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm
> *vm,
>  		fence = xe_vm_ops_execute(vm, vops);
>  		if (IS_ERR(fence)) {
>  			err = PTR_ERR(fence);
> -			/* FIXME: Killing VM rather than proper error handling */
> -			xe_vm_kill(vm, false);
>  			goto unlock;
> -		} else {
> -			vm_bind_ioctl_ops_install_fences(vm, vops, fence);
>  		}
> +
> +		vm_bind_ioctl_ops_install_fences(vm, vops, fence);
>  	}
> 
>  unlock:
> diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
> index b40160b1be01..8201ecb8f05a 100644
> --- a/drivers/gpu/drm/xe/xe_vm.h
> +++ b/drivers/gpu/drm/xe/xe_vm.h
> @@ -262,9 +262,12 @@ static inline struct dma_resv *xe_vm_resv(struct xe_vm
> *vm)
>   */
>  #define xe_vm_assert_held(vm) dma_resv_assert_held(xe_vm_resv(vm))
> 
> -void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma);
> +void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma,
> +				 u8 tile_mask);
>  struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops
> *vops);
> 
> +void xe_vm_kill(struct xe_vm *vm, bool unlocked);
> +
>  #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_VM)
>  #define vm_dbg drm_dbg
>  #else
> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> b/drivers/gpu/drm/xe/xe_vm_types.h
> index f5d740dcbba3..83cb13275904 100644
> --- a/drivers/gpu/drm/xe/xe_vm_types.h
> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> @@ -166,29 +166,18 @@ struct xe_vma_op_prefetch {
> 
>  /** enum xe_vma_op_flags - flags for VMA operation */
>  enum xe_vma_op_flags {
> -	/** @XE_VMA_OP_FIRST: first VMA operation for a set of syncs */
> -	XE_VMA_OP_FIRST			= BIT(0),
> -	/** @XE_VMA_OP_LAST: last VMA operation for a set of syncs */
> -	XE_VMA_OP_LAST			= BIT(1),
>  	/** @XE_VMA_OP_COMMITTED: VMA operation committed */
> -	XE_VMA_OP_COMMITTED		= BIT(2),
> +	XE_VMA_OP_COMMITTED		= BIT(0),
>  	/** @XE_VMA_OP_PREV_COMMITTED: Previous VMA operation
> committed */
> -	XE_VMA_OP_PREV_COMMITTED	= BIT(3),
> +	XE_VMA_OP_PREV_COMMITTED	= BIT(1),
>  	/** @XE_VMA_OP_NEXT_COMMITTED: Next VMA operation committed
> */
> -	XE_VMA_OP_NEXT_COMMITTED	= BIT(4),
> +	XE_VMA_OP_NEXT_COMMITTED	= BIT(2),
>  };
> 
>  /** struct xe_vma_op - VMA operation */
>  struct xe_vma_op {
>  	/** @base: GPUVA base operation */
>  	struct drm_gpuva_op base;
> -	/** @q: exec queue for this operation */
> -	struct xe_exec_queue *q;
> -	/**
> -	 * @syncs: syncs for this operation, only used on first and last
> -	 * operation
> -	 */
> -	struct xe_sync_entry *syncs;
>  	/** @num_syncs: number of syncs */
>  	u32 num_syncs;
>  	/** @link: async operation link */
> @@ -214,19 +203,14 @@ struct xe_vma_ops {
>  	struct list_head list;
>  	/** @vm: VM */
>  	struct xe_vm *vm;
> -	/** @q: exec queue these operations */
> +	/** @q: exec queue for VMA operations */
>  	struct xe_exec_queue *q;
>  	/** @syncs: syncs these operation */
>  	struct xe_sync_entry *syncs;
>  	/** @num_syncs: number of syncs */
>  	u32 num_syncs;
>  	/** @pt_update_ops: page table update operations */
> -	struct {
> -		/** @ops: operations */
> -		struct xe_vm_pgtable_update_op *ops;
> -		/** @num_ops: number of operations */
> -		u32 num_ops;
> -	} pt_update_ops[XE_MAX_TILES_PER_DEVICE];
> +	struct xe_vm_pgtable_update_ops
> pt_update_ops[XE_MAX_TILES_PER_DEVICE];
>  };
> 
>  struct xe_vm {
> @@ -283,9 +267,6 @@ struct xe_vm {
>  	 */
>  	struct list_head rebind_list;
> 
> -	/** @rebind_fence: rebind fence from execbuf */
> -	struct dma_fence *rebind_fence;
> -
>  	/**
>  	 * @destroy_work: worker to destroy VM, needed as a dma_fence
> signaling
>  	 * from an irq context can be last put and the destroy needs to be able
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 18/30] drm/xe: Convert multiple bind ops into single job
  2024-03-27  2:40   ` Zeng, Oak
@ 2024-03-27 19:26     ` Matthew Brost
  0 siblings, 0 replies; 76+ messages in thread
From: Matthew Brost @ 2024-03-27 19:26 UTC (permalink / raw)
  To: Zeng, Oak; +Cc: intel-xe

On Tue, Mar 26, 2024 at 08:40:05PM -0600, Zeng, Oak wrote:
> Hi Matt,
> 
> This patch is very big to review. I wasn't able to look the whole patch. See some comments inline for now. I need to continue it.
> 
> Is it possible to divide into small patches?
> 

Thanks for the review, yes this is a big patch and unfortunately this
one probably can't be split up much more without breaking the driver.

This is why we likely merge the patches prior to this one first, then
work through this patch and the next few in a single series.

Most likely we will another reviewer on this due its large size.

> > -----Original Message-----
> > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Matthew
> > Brost
> > Sent: Friday, March 8, 2024 12:08 AM
> > To: intel-xe@lists.freedesktop.org
> > Cc: Brost, Matthew <matthew.brost@intel.com>
> > Subject: [PATCH v4 18/30] drm/xe: Convert multiple bind ops into single job
> > 
> > This aligns with the uAPI of an array of binds or single bind that
> > results in multiple GPUVA ops to be considered a single atomic
> > operations.
> > 
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_bo_types.h     |    2 +
> >  drivers/gpu/drm/xe/xe_exec.c         |   25 +-
> >  drivers/gpu/drm/xe/xe_gt_pagefault.c |    6 +-
> >  drivers/gpu/drm/xe/xe_migrate.c      |  298 ++++----
> >  drivers/gpu/drm/xe/xe_migrate.h      |   32 +-
> >  drivers/gpu/drm/xe/xe_pt.c           | 1018 ++++++++++++++++----------
> >  drivers/gpu/drm/xe/xe_pt.h           |    7 +
> >  drivers/gpu/drm/xe/xe_pt_types.h     |   34 +
> >  drivers/gpu/drm/xe/xe_vm.c           |  533 ++++----------
> >  drivers/gpu/drm/xe/xe_vm.h           |    5 +-
> >  drivers/gpu/drm/xe/xe_vm_types.h     |   29 +-
> >  11 files changed, 969 insertions(+), 1020 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_bo_types.h
> > b/drivers/gpu/drm/xe/xe_bo_types.h
> > index 14ef13b7b421..1ff5b5a68adc 100644
> > --- a/drivers/gpu/drm/xe/xe_bo_types.h
> > +++ b/drivers/gpu/drm/xe/xe_bo_types.h
> > @@ -77,6 +77,8 @@ struct xe_bo {
> >  	} props;
> >  	/** @freed: List node for delayed put. */
> >  	struct llist_node freed;
> > +	/** @update_index: Update index if PT BO */
> > +	int update_index;
> >  	/** @created: Whether the bo has passed initial creation */
> >  	bool created;
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
> > index 952496c6260d..4feff67620c4 100644
> > --- a/drivers/gpu/drm/xe/xe_exec.c
> > +++ b/drivers/gpu/drm/xe/xe_exec.c
> > @@ -294,30 +294,9 @@ int xe_exec_ioctl(struct drm_device *dev, void *data,
> > struct drm_file *file)
> >  		err = PTR_ERR(rebind_fence);
> >  		goto err_put_job;
> >  	}
> > +	dma_fence_put(rebind_fence);
> > 
> > -	/*
> > -	 * We store the rebind_fence in the VM so subsequent execs don't get
> > -	 * scheduled before the rebinds of userptrs / evicted BOs is complete.
> > -	 */
> > -	if (rebind_fence) {
> > -		dma_fence_put(vm->rebind_fence);
> > -		vm->rebind_fence = rebind_fence;
> > -	}
> > -	if (vm->rebind_fence) {
> > -		if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
> > -			     &vm->rebind_fence->flags)) {
> > -			dma_fence_put(vm->rebind_fence);
> > -			vm->rebind_fence = NULL;
> > -		} else {
> > -			dma_fence_get(vm->rebind_fence);
> > -			err = drm_sched_job_add_dependency(&job->drm,
> > -							   vm->rebind_fence);
> > -			if (err)
> > -				goto err_put_job;
> > -		}
> > -	}
> > -
> > -	/* Wait behind munmap style rebinds */
> > +	/* Wait for rebinds */
> >  	if (!xe_vm_in_lr_mode(vm)) {
> >  		err = drm_sched_job_add_resv_dependencies(&job->drm,
> >  							  xe_vm_resv(vm),
> 
> 
> Can you explain why you can wait for rebind using above codes? I understand here we make all the fences in vm reservation object a dependency of the job. But did we add rebind_fence to vm's reservation object? I can't find such code in this patch
> 

Rebinds set wait_vm_bookkeep == true in xe_vma_ops, which schedules
rebinds behind the VM's bookkeep slot and inserts the rebind in the
kernel slot. With rebinds being the kernel slot, no need to wait on the
rebind_fence as all execs already wait on the kernel slots. Thomas has
a series [1] in inflight to make this too which will get merged before the
next rev.

[1] https://patchwork.freedesktop.org/series/131421/

> 
> > diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c
> > b/drivers/gpu/drm/xe/xe_gt_pagefault.c
> > index 878e234166aa..bd8688b2f462 100644
> > --- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
> > +++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
> > @@ -208,9 +208,9 @@ static int handle_pagefault(struct xe_gt *gt, struct
> > pagefault *pf)
> > 
> >  	/* Bind VMA only to the GT that has faulted */
> >  	trace_xe_vma_pf_bind(vma);
> > -	xe_vm_populate_dummy_rebind(vm, vma);
> > -	vm->dummy_ops.op.tile_mask = BIT(tile->id);
> > -	vm->dummy_ops.op.q = xe_tile_migrate_exec_queue(tile);
> > +	xe_vm_populate_dummy_rebind(vm, vma, BIT(tile->id));
> > +	vm->dummy_ops.vops.pt_update_ops[tile->id].q =
> > +		xe_tile_migrate_exec_queue(tile);
> 
> I guess I will ignore all those dummy_rebind/dummy_ops code for now.
> 

Yep.

> 
> >  	fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
> >  	if (IS_ERR(fence)) {
> >  		ret = PTR_ERR(fence);
> > diff --git a/drivers/gpu/drm/xe/xe_migrate.c
> > b/drivers/gpu/drm/xe/xe_migrate.c
> > index 3fd76f912fda..cc0499f3702c 100644
> > --- a/drivers/gpu/drm/xe/xe_migrate.c
> > +++ b/drivers/gpu/drm/xe/xe_migrate.c
> > @@ -1106,6 +1106,7 @@ struct dma_fence *xe_migrate_clear(struct xe_migrate
> > *m,
> >  }
> > 
> >  static void write_pgtable(struct xe_tile *tile, struct xe_bb *bb, u64 ppgtt_ofs,
> > +			  const struct xe_vm_pgtable_update_op *pt_op,
> >  			  const struct xe_vm_pgtable_update *update,
> >  			  struct xe_migrate_pt_update *pt_update)
> >  {
> > @@ -1140,8 +1141,12 @@ static void write_pgtable(struct xe_tile *tile, struct
> > xe_bb *bb, u64 ppgtt_ofs,
> >  		bb->cs[bb->len++] = MI_STORE_DATA_IMM |
> > MI_SDI_NUM_QW(chunk);
> >  		bb->cs[bb->len++] = lower_32_bits(addr);
> >  		bb->cs[bb->len++] = upper_32_bits(addr);
> > -		ops->populate(pt_update, tile, NULL, bb->cs + bb->len, ofs,
> > chunk,
> > -			      update);
> > +		if (pt_op->bind)
> > +			ops->populate(pt_update, tile, NULL, bb->cs + bb->len,
> > +				      ofs, chunk, update);
> > +		else
> > +			ops->clear(pt_update, tile, NULL, bb->cs + bb->len,
> > +				   ofs, chunk, update);
> > 
> >  		bb->len += chunk * 2;
> >  		ofs += chunk;
> > @@ -1166,114 +1171,58 @@ struct migrate_test_params {
> > 
> >  static struct dma_fence *
> >  xe_migrate_update_pgtables_cpu(struct xe_migrate *m,
> > -			       struct xe_vm *vm, struct xe_bo *bo,
> > -			       const struct  xe_vm_pgtable_update *updates,
> > -			       u32 num_updates, bool wait_vm,
> >  			       struct xe_migrate_pt_update *pt_update)
> >  {
> >  	XE_TEST_DECLARE(struct migrate_test_params *test =
> >  			to_migrate_test_params
> >  			(xe_cur_kunit_priv(XE_TEST_LIVE_MIGRATE));)
> >  	const struct xe_migrate_pt_update_ops *ops = pt_update->ops;
> > -	struct dma_fence *fence;
> > +	struct xe_vm *vm = pt_update->vops->vm;
> > +	struct xe_vm_pgtable_update_ops *pt_update_ops =
> > +		&pt_update->vops->pt_update_ops[pt_update->tile_id];
> >  	int err;
> > -	u32 i;
> > +	u32 j, i;
> > 
> >  	if (XE_TEST_ONLY(test && test->force_gpu))
> >  		return ERR_PTR(-ETIME);
> > 
> > -	if (bo && !dma_resv_test_signaled(bo->ttm.base.resv,
> > -					  DMA_RESV_USAGE_KERNEL))
> > -		return ERR_PTR(-ETIME);
> > -
> > -	if (wait_vm && !dma_resv_test_signaled(xe_vm_resv(vm),
> > -					       DMA_RESV_USAGE_BOOKKEEP))
> > -		return ERR_PTR(-ETIME);
> > -
> >  	if (ops->pre_commit) {
> >  		pt_update->job = NULL;
> >  		err = ops->pre_commit(pt_update);
> >  		if (err)
> >  			return ERR_PTR(err);
> >  	}
> > -	for (i = 0; i < num_updates; i++) {
> > -		const struct xe_vm_pgtable_update *update = &updates[i];
> > -
> > -		ops->populate(pt_update, m->tile, &update->pt_bo->vmap,
> > NULL,
> > -			      update->ofs, update->qwords, update);
> > -	}
> > -
> > -	if (vm) {
> > -		trace_xe_vm_cpu_bind(vm);
> > -		xe_device_wmb(vm->xe);
> > -	}
> > -
> > -	fence = dma_fence_get_stub();
> > -
> > -	return fence;
> > -}
> > -
> > -static bool no_in_syncs(struct xe_vm *vm, struct xe_exec_queue *q,
> > -			struct xe_sync_entry *syncs, u32 num_syncs)
> > -{
> > -	struct dma_fence *fence;
> > -	int i;
> > 
> > -	for (i = 0; i < num_syncs; i++) {
> > -		fence = syncs[i].fence;
> > -
> > -		if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
> > -				       &fence->flags))
> > -			return false;
> > -	}
> > -	if (q) {
> > -		fence = xe_exec_queue_last_fence_get(q, vm);
> > -		if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
> > -			dma_fence_put(fence);
> > -			return false;
> > +	for (j = 0; j < pt_update_ops->num_ops; ++j) {
> > +		const struct xe_vm_pgtable_update_op *pt_op =
> > +			&pt_update_ops->ops[j];
> > +
> > +		for (i = 0; i < pt_op->num_entries; i++) {
> > +			const struct xe_vm_pgtable_update *update =
> > +				&pt_op->entries[i];
> > +
> > +			if (pt_op->bind)
> > +				ops->populate(pt_update, m->tile,
> > +					      &update->pt_bo->vmap, NULL,
> > +					      update->ofs, update->qwords,
> > +					      update);
> > +			else
> > +				ops->clear(pt_update, m->tile,
> > +					   &update->pt_bo->vmap, NULL,
> > +					   update->ofs, update->qwords, update);
> >  		}
> > -		dma_fence_put(fence);
> >  	}
> > 
> > -	return true;
> > +	trace_xe_vm_cpu_bind(vm);
> > +	xe_device_wmb(vm->xe);
> > +
> > +	return dma_fence_get_stub();
> >  }
> > 
> > -/**
> > - * xe_migrate_update_pgtables() - Pipelined page-table update
> > - * @m: The migrate context.
> > - * @vm: The vm we'll be updating.
> > - * @bo: The bo whose dma-resv we will await before updating, or NULL if
> > userptr.
> > - * @q: The exec queue to be used for the update or NULL if the default
> > - * migration engine is to be used.
> > - * @updates: An array of update descriptors.
> > - * @num_updates: Number of descriptors in @updates.
> > - * @syncs: Array of xe_sync_entry to await before updating. Note that waits
> > - * will block the engine timeline.
> > - * @num_syncs: Number of entries in @syncs.
> > - * @pt_update: Pointer to a struct xe_migrate_pt_update, which contains
> > - * pointers to callback functions and, if subclassed, private arguments to
> > - * those.
> > - *
> > - * Perform a pipelined page-table update. The update descriptors are typically
> > - * built under the same lock critical section as a call to this function. If
> > - * using the default engine for the updates, they will be performed in the
> > - * order they grab the job_mutex. If different engines are used, external
> > - * synchronization is needed for overlapping updates to maintain page-table
> > - * consistency. Note that the meaing of "overlapping" is that the updates
> > - * touch the same page-table, which might be a higher-level page-directory.
> > - * If no pipelining is needed, then updates may be performed by the cpu.
> > - *
> > - * Return: A dma_fence that, when signaled, indicates the update completion.
> > - */
> > -struct dma_fence *
> > -xe_migrate_update_pgtables(struct xe_migrate *m,
> > -			   struct xe_vm *vm,
> > -			   struct xe_bo *bo,
> > -			   struct xe_exec_queue *q,
> > -			   const struct xe_vm_pgtable_update *updates,
> > -			   u32 num_updates,
> > -			   struct xe_sync_entry *syncs, u32 num_syncs,
> > -			   struct xe_migrate_pt_update *pt_update)
> > +static struct dma_fence *
> > +__xe_migrate_update_pgtables(struct xe_migrate *m,
> > +			     struct xe_migrate_pt_update *pt_update,
> > +			     struct xe_vm_pgtable_update_ops *pt_update_ops)
> 
> Maybe rename this function to _gpu?
> 

I'd rather avoid name class within this patch. If we want to rename an
existing function I'd do it in own patch as prep or as a follow up.

> >  {
> >  	const struct xe_migrate_pt_update_ops *ops = pt_update->ops;
> >  	struct xe_tile *tile = m->tile;
> > @@ -1282,59 +1231,45 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
> >  	struct xe_sched_job *job;
> >  	struct dma_fence *fence;
> >  	struct drm_suballoc *sa_bo = NULL;
> > -	struct xe_vma *vma = pt_update->vma;
> >  	struct xe_bb *bb;
> > -	u32 i, batch_size, ppgtt_ofs, update_idx, page_ofs = 0;
> > +	u32 i, j, batch_size = 0, ppgtt_ofs, update_idx, page_ofs = 0;
> > +	u32 num_updates = 0, current_update = 0;
> >  	u64 addr;
> >  	int err = 0;
> > -	bool usm = !q && xe->info.has_usm;
> > -	bool first_munmap_rebind = vma &&
> > -		vma->gpuva.flags & XE_VMA_FIRST_REBIND;
> > -	struct xe_exec_queue *q_override = !q ? m->q : q;
> > -	u16 pat_index = xe->pat.idx[XE_CACHE_WB];
> > +	bool is_migrate = pt_update_ops->q == m->q;
> > +	bool usm = is_migrate && xe->info.has_usm;
> > 
> > -	/* Use the CPU if no in syncs and engine is idle */
> > -	if (no_in_syncs(vm, q, syncs, num_syncs) &&
> > xe_exec_queue_is_idle(q_override)) {
> > -		fence =  xe_migrate_update_pgtables_cpu(m, vm, bo, updates,
> > -							num_updates,
> > -							first_munmap_rebind,
> > -							pt_update);
> > -		if (!IS_ERR(fence) || fence == ERR_PTR(-EAGAIN))
> > -			return fence;
> > +	for (i = 0; i < pt_update_ops->num_ops; ++i) {
> > +		struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops-
> > >ops[i];
> > +		struct xe_vm_pgtable_update *updates = pt_op->entries;
> > +
> > +		num_updates += pt_op->num_entries;
> > +		for (j = 0; j < pt_op->num_entries; ++j) {
> > +			u32 num_cmds = DIV_ROUND_UP(updates[j].qwords,
> > 0x1ff);
> > +
> > +			/* align noop + MI_STORE_DATA_IMM cmd prefix */
> > +			batch_size += 4 * num_cmds + updates[j].qwords * 2;
> > +		}
> >  	}
> > 
> >  	/* fixed + PTE entries */
> >  	if (IS_DGFX(xe))
> > -		batch_size = 2;
> > +		batch_size += 2;
> >  	else
> > -		batch_size = 6 + num_updates * 2;
> > +		batch_size += 6 + num_updates * 2;
> > 
> > -	for (i = 0; i < num_updates; i++) {
> > -		u32 num_cmds = DIV_ROUND_UP(updates[i].qwords,
> > MAX_PTE_PER_SDI);
> > -
> > -		/* align noop + MI_STORE_DATA_IMM cmd prefix */
> > -		batch_size += 4 * num_cmds + updates[i].qwords * 2;
> > -	}
> > -
> > -	/*
> > -	 * XXX: Create temp bo to copy from, if batch_size becomes too big?
> > -	 *
> > -	 * Worst case: Sum(2 * (each lower level page size) + (top level page size))
> > -	 * Should be reasonably bound..
> > -	 */
> > -	xe_tile_assert(tile, batch_size < SZ_128K);
> > -
> > -	bb = xe_bb_new(gt, batch_size, !q && xe->info.has_usm);
> > +	bb = xe_bb_new(gt, batch_size, usm);
> >  	if (IS_ERR(bb))
> >  		return ERR_CAST(bb);
> > 
> >  	/* For sysmem PTE's, need to map them in our hole.. */
> >  	if (!IS_DGFX(xe)) {
> >  		ppgtt_ofs = NUM_KERNEL_PDE - 1;
> > -		if (q) {
> > -			xe_tile_assert(tile, num_updates <=
> > NUM_VMUSA_WRITES_PER_UNIT);
> > +		if (!is_migrate) {
> > +			u32 num_units = DIV_ROUND_UP(num_updates,
> > +
> > NUM_VMUSA_WRITES_PER_UNIT);
> > 
> > -			sa_bo = drm_suballoc_new(&m->vm_update_sa, 1,
> > +			sa_bo = drm_suballoc_new(&m->vm_update_sa,
> > num_units,
> >  						 GFP_KERNEL, true, 0);
> >  			if (IS_ERR(sa_bo)) {
> >  				err = PTR_ERR(sa_bo);
> > @@ -1354,14 +1289,26 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
> >  		bb->cs[bb->len++] = ppgtt_ofs * XE_PAGE_SIZE + page_ofs;
> >  		bb->cs[bb->len++] = 0; /* upper_32_bits */
> > 
> > -		for (i = 0; i < num_updates; i++) {
> > -			struct xe_bo *pt_bo = updates[i].pt_bo;
> > +		for (i = 0; i < pt_update_ops->num_ops; ++i) {
> > +			struct xe_vm_pgtable_update_op *pt_op =
> > +				&pt_update_ops->ops[i];
> > +			struct xe_vm_pgtable_update *updates = pt_op-
> > >entries;
> > 
> > -			xe_tile_assert(tile, pt_bo->size == SZ_4K);
> > +			for (j = 0; j < pt_op->num_entries; ++j, ++current_update)
> > {
> > +				struct xe_vm *vm = pt_update->vops->vm;
> > +				struct xe_bo *pt_bo = updates[j].pt_bo;
> > 
> > -			addr = vm->pt_ops->pte_encode_bo(pt_bo, 0,
> > pat_index, 0);
> > -			bb->cs[bb->len++] = lower_32_bits(addr);
> > -			bb->cs[bb->len++] = upper_32_bits(addr);
> > +				xe_tile_assert(tile, pt_bo->size == SZ_4K);
> > +
> > +				/* Map a PT at most once */
> > +				if (pt_bo->update_index < 0)
> > +					pt_bo->update_index = current_update;
> > +
> > +				addr = vm->pt_ops->pte_encode_bo(pt_bo, 0,
> > +								 XE_CACHE_WB,
> > 0);
> > +				bb->cs[bb->len++] = lower_32_bits(addr);
> > +				bb->cs[bb->len++] = upper_32_bits(addr);
> > +			}
> >  		}
> > 
> >  		bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
> > @@ -1369,22 +1316,39 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
> > 
> >  		addr = xe_migrate_vm_addr(ppgtt_ofs, 0) +
> >  			(page_ofs / sizeof(u64)) * XE_PAGE_SIZE;
> > -		for (i = 0; i < num_updates; i++)
> > -			write_pgtable(tile, bb, addr + i * XE_PAGE_SIZE,
> > -				      &updates[i], pt_update);
> > +		for (i = 0; i < pt_update_ops->num_ops; ++i) {
> > +			struct xe_vm_pgtable_update_op *pt_op =
> > +				&pt_update_ops->ops[i];
> > +			struct xe_vm_pgtable_update *updates = pt_op-
> > >entries;
> > +
> > +			for (j = 0; j < pt_op->num_entries; ++j) {
> > +				struct xe_bo *pt_bo = updates[j].pt_bo;
> > +
> > +				write_pgtable(tile, bb, addr +
> > +					      pt_bo->update_index *
> > XE_PAGE_SIZE,
> > +					      pt_op, &updates[j], pt_update);
> > +			}
> > +		}
> >  	} else {
> >  		/* phys pages, no preamble required */
> >  		bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
> >  		update_idx = bb->len;
> > 
> > -		for (i = 0; i < num_updates; i++)
> > -			write_pgtable(tile, bb, 0, &updates[i], pt_update);
> > +		for (i = 0; i < pt_update_ops->num_ops; ++i) {
> > +			struct xe_vm_pgtable_update_op *pt_op =
> > +				&pt_update_ops->ops[i];
> > +			struct xe_vm_pgtable_update *updates = pt_op-
> > >entries;
> > +
> > +			for (j = 0; j < pt_op->num_entries; ++j)
> > +				write_pgtable(tile, bb, 0, pt_op, &updates[j],
> > +					      pt_update);
> > +		}
> >  	}
> > 
> > -	if (!q)
> > +	if (is_migrate)
> >  		mutex_lock(&m->job_mutex);
> > 
> > -	job = xe_bb_create_migration_job(q ?: m->q, bb,
> > +	job = xe_bb_create_migration_job(pt_update_ops->q, bb,
> >  					 xe_migrate_batch_base(m, usm),
> >  					 update_idx);
> >  	if (IS_ERR(job)) {
> > @@ -1392,32 +1356,6 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
> >  		goto err_bb;
> >  	}
> > 
> > -	/* Wait on BO move */
> > -	if (bo) {
> > -		err = job_add_deps(job, bo->ttm.base.resv,
> > -				   DMA_RESV_USAGE_KERNEL);
> > -		if (err)
> > -			goto err_job;
> > -	}
> > -
> > -	/*
> > -	 * Munmap style VM unbind, need to wait for all jobs to be complete /
> > -	 * trigger preempts before moving forward
> > -	 */
> > -	if (first_munmap_rebind) {
> > -		err = job_add_deps(job, xe_vm_resv(vm),
> > -				   DMA_RESV_USAGE_BOOKKEEP);
> > -		if (err)
> > -			goto err_job;
> > -	}
> > -
> > -	err = xe_sched_job_last_fence_add_dep(job, vm);
> > -	for (i = 0; !err && i < num_syncs; i++)
> > -		err = xe_sync_entry_add_deps(&syncs[i], job);
> > -
> > -	if (err)
> > -		goto err_job;
> > -
> >  	if (ops->pre_commit) {
> >  		pt_update->job = job;
> >  		err = ops->pre_commit(pt_update);
> > @@ -1428,7 +1366,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
> >  	fence = dma_fence_get(&job->drm.s_fence->finished);
> >  	xe_sched_job_push(job);
> > 
> > -	if (!q)
> > +	if (is_migrate)
> >  		mutex_unlock(&m->job_mutex);
> > 
> >  	xe_bb_free(bb, fence);
> > @@ -1439,7 +1377,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
> >  err_job:
> >  	xe_sched_job_put(job);
> >  err_bb:
> > -	if (!q)
> > +	if (is_migrate)
> >  		mutex_unlock(&m->job_mutex);
> >  	xe_bb_free(bb, NULL);
> >  err:
> > @@ -1447,6 +1385,38 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
> >  	return ERR_PTR(err);
> >  }
> > 
> > +/**
> > + * xe_migrate_update_pgtables() - Pipelined page-table update
> > + * @m: The migrate context.
> > + * @pt_update: PT update arguments
> > + *
> > + * Perform a pipelined page-table update. The update descriptors are typically
> > + * built under the same lock critical section as a call to this function. If
> > + * using the default engine for the updates, they will be performed in the
> > + * order they grab the job_mutex. If different engines are used, external
> > + * synchronization is needed for overlapping updates to maintain page-table
> > + * consistency. Note that the meaing of "overlapping" is that the updates
> > + * touch the same page-table, which might be a higher-level page-directory.
> > + * If no pipelining is needed, then updates may be performed by the cpu.
> > + *
> > + * Return: A dma_fence that, when signaled, indicates the update completion.
> > + */
> > +struct dma_fence *
> > +xe_migrate_update_pgtables(struct xe_migrate *m,
> > +			   struct xe_migrate_pt_update *pt_update)
> > +
> > +{
> > +	struct xe_vm_pgtable_update_ops *pt_update_ops =
> > +		&pt_update->vops->pt_update_ops[pt_update->tile_id];
> > +	struct dma_fence *fence;
> > +
> > +	fence =  xe_migrate_update_pgtables_cpu(m, pt_update);
> 
> So now by default you use cpu to update page table first. Only if there is error you fall back to gpu page table update. Should we also consider performance here? For example, consider page table is usually in vram, isn't cpu writing to page table is usually slower than gpu writing?
> 

This is existing behavior that is refactored.

The behavior is:

- If no dependencies for the bind execute immediately with the CPU doing a bind
- If no dependencies, schedule a job which will execute once dependencies are resolved to complete the bind via GPU

Later in series [2] this is reworked so the job uses the CPU to complete
the bind with a new backend [3]. Yes, the idea is that using the CPU
will always be faster.

[2] https://patchwork.freedesktop.org/patch/582003/?series=125608&rev=5
[3] https://patchwork.freedesktop.org/patch/582027/?series=125608&rev=5

> > +	if (!IS_ERR(fence))
> > +		return fence;
> > +
> > +	return __xe_migrate_update_pgtables(m, pt_update, pt_update_ops);
> > +}
> > +
> >  /**
> >   * xe_migrate_wait() - Complete all operations using the xe_migrate context
> >   * @m: Migrate context to wait for.
> > diff --git a/drivers/gpu/drm/xe/xe_migrate.h
> > b/drivers/gpu/drm/xe/xe_migrate.h
> > index 9935ce336bae..bd8eba1d3552 100644
> > --- a/drivers/gpu/drm/xe/xe_migrate.h
> > +++ b/drivers/gpu/drm/xe/xe_migrate.h
> > @@ -47,6 +47,24 @@ struct xe_migrate_pt_update_ops {
> >  			 struct xe_tile *tile, struct iosys_map *map,
> >  			 void *pos, u32 ofs, u32 num_qwords,
> >  			 const struct xe_vm_pgtable_update *update);
> > +	/**
> > +	 * @clear: Clear a command buffer or page-table with ptes.
> > +	 * @pt_update: Embeddable callback argument.
> > +	 * @tile: The tile for the current operation.
> > +	 * @map: struct iosys_map into the memory to be populated.
> > +	 * @pos: If @map is NULL, map into the memory to be populated.
> > +	 * @ofs: qword offset into @map, unused if @map is NULL.
> > +	 * @num_qwords: Number of qwords to write.
> > +	 * @update: Information about the PTEs to be inserted.
> > +	 *
> > +	 * This interface is intended to be used as a callback into the
> > +	 * page-table system to populate command buffers or shared
> > +	 * page-tables with PTEs.
> > +	 */
> > +	void (*clear)(struct xe_migrate_pt_update *pt_update,
> > +		      struct xe_tile *tile, struct iosys_map *map,
> > +		      void *pos, u32 ofs, u32 num_qwords,
> > +		      const struct xe_vm_pgtable_update *update);
> > 
> >  	/**
> >  	 * @pre_commit: Callback to be called just before arming the
> > @@ -67,14 +85,10 @@ struct xe_migrate_pt_update_ops {
> >  struct xe_migrate_pt_update {
> >  	/** @ops: Pointer to the struct xe_migrate_pt_update_ops callbacks */
> >  	const struct xe_migrate_pt_update_ops *ops;
> > -	/** @vma: The vma we're updating the pagetable for. */
> > -	struct xe_vma *vma;
> > +	/** @vops: VMA operations */
> > +	struct xe_vma_ops *vops;
> >  	/** @job: The job if a GPU page-table update. NULL otherwise */
> >  	struct xe_sched_job *job;
> > -	/** @start: Start of update for the range fence */
> > -	u64 start;
> > -	/** @last: Last of update for the range fence */
> > -	u64 last;
> >  	/** @tile_id: Tile ID of the update */
> >  	u8 tile_id;
> >  };
> > @@ -96,12 +110,6 @@ struct xe_vm *xe_migrate_get_vm(struct xe_migrate
> > *m);
> > 
> >  struct dma_fence *
> >  xe_migrate_update_pgtables(struct xe_migrate *m,
> > -			   struct xe_vm *vm,
> > -			   struct xe_bo *bo,
> > -			   struct xe_exec_queue *q,
> > -			   const struct xe_vm_pgtable_update *updates,
> > -			   u32 num_updates,
> > -			   struct xe_sync_entry *syncs, u32 num_syncs,
> >  			   struct xe_migrate_pt_update *pt_update);
> > 
> >  void xe_migrate_wait(struct xe_migrate *m);
> > diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> > index a878e2217c7f..5a8523d0a049 100644
> > --- a/drivers/gpu/drm/xe/xe_pt.c
> > +++ b/drivers/gpu/drm/xe/xe_pt.c
> > @@ -8,12 +8,14 @@
> >  #include "xe_bo.h"
> >  #include "xe_device.h"
> >  #include "xe_drm_client.h"
> > +#include "xe_exec_queue.h"
> >  #include "xe_gt.h"
> >  #include "xe_gt_tlb_invalidation.h"
> >  #include "xe_migrate.h"
> >  #include "xe_pt_types.h"
> >  #include "xe_pt_walk.h"
> >  #include "xe_res_cursor.h"
> > +#include "xe_sync.h"
> >  #include "xe_trace.h"
> >  #include "xe_ttm_stolen_mgr.h"
> >  #include "xe_vm.h"
> > @@ -324,6 +326,7 @@ xe_pt_new_shared(struct xe_walk_update *wupd, struct
> > xe_pt *parent,
> >  	entry->pt = parent;
> >  	entry->flags = 0;
> >  	entry->qwords = 0;
> > +	entry->pt_bo->update_index = -1;
> > 
> >  	if (alloc_entries) {
> >  		entry->pt_entries = kmalloc_array(XE_PDES,
> > @@ -831,9 +834,7 @@ static void xe_pt_commit_locks_assert(struct xe_vma
> > *vma)
> > 
> >  	lockdep_assert_held(&vm->lock);
> > 
> > -	if (xe_vma_is_userptr(vma))
> > -		lockdep_assert_held_read(&vm->userptr.notifier_lock);
> > -	else if (!xe_vma_is_null(vma))
> > +	if (!xe_vma_is_userptr(vma) && !xe_vma_is_null(vma))
> >  		dma_resv_assert_held(xe_vma_bo(vma)->ttm.base.resv);
> > 
> >  	xe_vm_assert_held(vm);
> > @@ -855,10 +856,8 @@ static void xe_pt_commit_bind(struct xe_vma *vma,
> >  		if (!rebind)
> >  			pt->num_live += entries[i].qwords;
> > 
> > -		if (!pt->level) {
> > -			kfree(entries[i].pt_entries);
> > +		if (!pt->level)
> >  			continue;
> > -		}
> > 
> >  		pt_dir = as_xe_pt_dir(pt);
> >  		for (j = 0; j < entries[i].qwords; j++) {
> > @@ -871,10 +870,18 @@ static void xe_pt_commit_bind(struct xe_vma *vma,
> > 
> >  			pt_dir->children[j_] = &newpte->base;
> >  		}
> > -		kfree(entries[i].pt_entries);
> >  	}
> >  }
> > 
> > +static void xe_pt_free_bind(struct xe_vm_pgtable_update *entries,
> > +			    u32 num_entries)
> > +{
> > +	u32 i;
> > +
> > +	for (i = 0; i < num_entries; i++)
> > +		kfree(entries[i].pt_entries);
> > +}
> > +
> >  static int
> >  xe_pt_prepare_bind(struct xe_tile *tile, struct xe_vma *vma,
> >  		   struct xe_vm_pgtable_update *entries, u32 *num_entries)
> > @@ -893,12 +900,13 @@ xe_pt_prepare_bind(struct xe_tile *tile, struct xe_vma
> > *vma,
> > 
> >  static void xe_vm_dbg_print_entries(struct xe_device *xe,
> >  				    const struct xe_vm_pgtable_update *entries,
> > -				    unsigned int num_entries)
> > +				    unsigned int num_entries, bool bind)
> >  #if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_VM))
> >  {
> >  	unsigned int i;
> > 
> > -	vm_dbg(&xe->drm, "%u entries to update\n", num_entries);
> > +	vm_dbg(&xe->drm, "%s: %u entries to update\n", bind ? "bind" :
> > "unbind",
> > +	       num_entries);
> >  	for (i = 0; i < num_entries; i++) {
> >  		const struct xe_vm_pgtable_update *entry = &entries[i];
> >  		struct xe_pt *xe_pt = entry->pt;
> > @@ -919,66 +927,122 @@ static void xe_vm_dbg_print_entries(struct xe_device
> > *xe,
> >  {}
> >  #endif
> > 
> > -#ifdef CONFIG_DRM_XE_USERPTR_INVAL_INJECT
> > +static int job_add_deps(struct xe_sched_job *job, struct dma_resv *resv,
> > +			enum dma_resv_usage usage)
> > +{
> > +	return drm_sched_job_add_resv_dependencies(&job->drm, resv,
> > usage);
> > +}
> > 
> > -static int xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma)
> > +static bool no_in_syncs(struct xe_sync_entry *syncs, u32 num_syncs)
> >  {
> > -	u32 divisor = uvma->userptr.divisor ? uvma->userptr.divisor : 2;
> > -	static u32 count;
> > +	int i;
> > 
> > -	if (count++ % divisor == divisor - 1) {
> > -		struct xe_vm *vm = xe_vma_vm(&uvma->vma);
> > +	for (i = 0; i < num_syncs; i++) {
> > +		struct dma_fence *fence = syncs[i].fence;
> > 
> > -		uvma->userptr.divisor = divisor << 1;
> > -		spin_lock(&vm->userptr.invalidated_lock);
> > -		list_move_tail(&uvma->userptr.invalidate_link,
> > -			       &vm->userptr.invalidated);
> > -		spin_unlock(&vm->userptr.invalidated_lock);
> > -		return true;
> > +		if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
> > +				       &fence->flags))
> > +			return false;
> >  	}
> > 
> > -	return false;
> > +	return true;
> >  }
> > 
> > -#else
> > -
> > -static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma)
> > +static int vma_add_deps(struct xe_vma *vma, struct xe_sched_job *job)
> 
> 
> From the implementation, it seems this is adding vma as a job's dependency...but the function name says add dependency to vma...

vma_add_deps_to_job?

add_vma_deps_to_job?

> 
> >  {
> > -	return false;
> > +	struct xe_bo *bo = xe_vma_bo(vma);
> > +
> > +	xe_bo_assert_held(bo);
> > +
> > +	if (bo && !bo->vm) {
> > +		if (!job) {
> > +			if (!dma_resv_test_signaled(bo->ttm.base.resv,
> > +						    DMA_RESV_USAGE_KERNEL))
> > +				return -ETIME;
> > +		} else {
> > +			return job_add_deps(job, bo->ttm.base.resv,
> > +					    DMA_RESV_USAGE_KERNEL);
> > +		}
> > +	}
> > +
> > +	return 0;
> >  }
> > 
> > -#endif
> > +static int op_add_deps(struct xe_vm *vm, struct xe_vma_op *op,
> > +		       struct xe_sched_job *job)
> > +{
> > +	int err = 0;
> > 
> > -/**
> > - * struct xe_pt_migrate_pt_update - Callback argument for pre-commit callbacks
> > - * @base: Base we derive from.
> > - * @bind: Whether this is a bind or an unbind operation. A bind operation
> > - *        makes the pre-commit callback error with -EAGAIN if it detects a
> > - *        pending invalidation.
> > - * @locked: Whether the pre-commit callback locked the userptr notifier lock
> > - *          and it needs unlocking.
> > - */
> > -struct xe_pt_migrate_pt_update {
> > -	struct xe_migrate_pt_update base;
> > -	bool bind;
> > -	bool locked;
> > -};
> > +	switch (op->base.op) {
> > +	case DRM_GPUVA_OP_MAP:
> > +		if (!op->map.immediate && xe_vm_in_fault_mode(vm))
> > +			break;
> > +
> > +		err = vma_add_deps(op->map.vma, job);
> > +		break;
> > +	case DRM_GPUVA_OP_REMAP:
> > +		if (op->remap.prev)
> > +			err = vma_add_deps(op->remap.prev, job);
> > +		if (!err && op->remap.next)
> > +			err = vma_add_deps(op->remap.next, job);
> > +		break;
> > +	case DRM_GPUVA_OP_UNMAP:
> > +		break;
> > +	case DRM_GPUVA_OP_PREFETCH:
> > +		err = vma_add_deps(gpuva_to_vma(op->base.prefetch.va), job);
> > +		break;
> > +	default:
> > +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > +	}
> > +
> > +	return err;
> > +}
> > 
> > -/*
> > - * This function adds the needed dependencies to a page-table update job
> > - * to make sure racing jobs for separate bind engines don't race writing
> > - * to the same page-table range, wreaking havoc. Initially use a single
> > - * fence for the entire VM. An optimization would use smaller granularity.
> > - */
> >  static int xe_pt_vm_dependencies(struct xe_sched_job *job,
> > -				 struct xe_range_fence_tree *rftree,
> > -				 u64 start, u64 last)
> > +				 struct xe_vm *vm,
> > +				 struct xe_vma_ops *vops,
> > +				 struct xe_vm_pgtable_update_ops
> > *pt_update_ops,
> > +				 struct xe_range_fence_tree *rftree)
> >  {
> >  	struct xe_range_fence *rtfence;
> >  	struct dma_fence *fence;
> > -	int err;
> > +	struct xe_vma_op *op;
> > +	int err = 0, i;
> > +
> > +	xe_vm_assert_held(vm);
> > +
> > +	if (!job && !no_in_syncs(vops->syncs, vops->num_syncs))
> > +		return -ETIME;
> > +
> > +	if (!job && !xe_exec_queue_is_idle(pt_update_ops->q))
> > +		return -ETIME;
> > 
> > -	rtfence = xe_range_fence_tree_first(rftree, start, last);
> > +	if (pt_update_ops->wait_vm_bookkeep) {
> > +		if (!job) {
> > +			if (!dma_resv_test_signaled(xe_vm_resv(vm),
> > +
> > DMA_RESV_USAGE_BOOKKEEP))
> > +				return -ETIME;
> > +		} else {
> > +			err = job_add_deps(job, xe_vm_resv(vm),
> > +					   DMA_RESV_USAGE_BOOKKEEP);
> > +			if (err)
> > +				return err;
> > +		}
> > +	} else if (pt_update_ops->wait_vm_kernel) {
> > +		if (!job) {
> > +			if (!dma_resv_test_signaled(xe_vm_resv(vm),
> > +						    DMA_RESV_USAGE_KERNEL))
> > +				return -ETIME;
> > +		} else {
> > +			err = job_add_deps(job, xe_vm_resv(vm),
> > +					   DMA_RESV_USAGE_KERNEL);
> > +			if (err)
> > +				return err;
> > +		}
> > +	}
> > +
> > +	rtfence = xe_range_fence_tree_first(rftree, pt_update_ops->start,
> > +					    pt_update_ops->last);
> >  	while (rtfence) {
> >  		fence = rtfence->fence;
> > 
> > @@ -996,80 +1060,136 @@ static int xe_pt_vm_dependencies(struct
> > xe_sched_job *job,
> >  				return err;
> >  		}
> > 
> > -		rtfence = xe_range_fence_tree_next(rtfence, start, last);
> > +		rtfence = xe_range_fence_tree_next(rtfence,
> > +						   pt_update_ops->start,
> > +						   pt_update_ops->last);
> >  	}
> > 
> > -	return 0;
> > +	list_for_each_entry(op, &vops->list, link) {
> > +		err = op_add_deps(vm, op, job);
> > +		if (err)
> > +			return err;
> > +	}
> > +
> > +	for (i = 0; job && !err && i < vops->num_syncs; i++)
> > +		err = xe_sync_entry_add_deps(&vops->syncs[i], job);
> > +
> > +	return err;
> >  }
> > 
> >  static int xe_pt_pre_commit(struct xe_migrate_pt_update *pt_update)
> >  {
> > -	struct xe_range_fence_tree *rftree =
> > -		&xe_vma_vm(pt_update->vma)->rftree[pt_update->tile_id];
> > +	struct xe_vma_ops *vops = pt_update->vops;
> > +	struct xe_vm *vm = vops->vm;
> > +	struct xe_range_fence_tree *rftree = &vm->rftree[pt_update->tile_id];
> > +	struct xe_vm_pgtable_update_ops *pt_update_ops =
> > +		&vops->pt_update_ops[pt_update->tile_id];
> > +
> > +	return xe_pt_vm_dependencies(pt_update->job, vm, pt_update->vops,
> > +				     pt_update_ops, rftree);
> > +}
> > +
> > +#ifdef CONFIG_DRM_XE_USERPTR_INVAL_INJECT
> > +
> > +static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma)
> > +{
> > +	u32 divisor = uvma->userptr.divisor ? uvma->userptr.divisor : 2;
> > +	static u32 count;
> > +
> > +	if (count++ % divisor == divisor - 1) {
> > +		uvma->userptr.divisor = divisor << 1;
> > +		return true;
> > +	}
> > 
> > -	return xe_pt_vm_dependencies(pt_update->job, rftree,
> > -				     pt_update->start, pt_update->last);
> > +	return false;
> >  }
> > 
> > -static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> > +#else
> > +
> > +static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma)
> >  {
> > -	struct xe_pt_migrate_pt_update *userptr_update =
> > -		container_of(pt_update, typeof(*userptr_update), base);
> > -	struct xe_userptr_vma *uvma = to_userptr_vma(pt_update->vma);
> > -	unsigned long notifier_seq = uvma->userptr.notifier_seq;
> > -	struct xe_vm *vm = xe_vma_vm(&uvma->vma);
> > -	int err = xe_pt_vm_dependencies(pt_update->job,
> > -					&vm->rftree[pt_update->tile_id],
> > -					pt_update->start,
> > -					pt_update->last);
> > +	return false;
> > +}
> > 
> > -	if (err)
> > -		return err;
> > +#endif
> > 
> > -	userptr_update->locked = false;
> > +static void vma_check_userptr(struct xe_vm *vm, struct xe_vma *vma)
> > +{
> > +	struct xe_userptr_vma *uvma = to_userptr_vma(vma);
> > +	unsigned long notifier_seq = uvma->userptr.notifier_seq;
> > 
> > -	/*
> > -	 * Wait until nobody is running the invalidation notifier, and
> > -	 * since we're exiting the loop holding the notifier lock,
> > -	 * nobody can proceed invalidating either.
> > -	 *
> > -	 * Note that we don't update the vma->userptr.notifier_seq since
> > -	 * we don't update the userptr pages.
> > -	 */
> > -	do {
> > -		down_read(&vm->userptr.notifier_lock);
> > -		if (!mmu_interval_read_retry(&uvma->userptr.notifier,
> > -					     notifier_seq))
> > -			break;
> > +	lockdep_assert_held_read(&vm->userptr.notifier_lock);
> > 
> > -		up_read(&vm->userptr.notifier_lock);
> > +	if (uvma->userptr.initial_bind || xe_vm_in_fault_mode(vm))
> > +		return;
> > 
> > -		if (userptr_update->bind)
> > -			return -EAGAIN;
> > +	if (!mmu_interval_read_retry(&uvma->userptr.notifier,
> > +				     notifier_seq) &&
> > +	    !xe_pt_userptr_inject_eagain(uvma))
> > +		return;
> 
> After this, we need to retry the get_user_pages_fast thing but I don't see how this is achieved...
> 

This is broken for faulting mode...

For dma-fence mode, adding to userptr.invalidated is enough. Next exec
picks this up, pins userptr pages, and issues a rebind. See
xe_vm_userptr_pin, xe_vm_rebind.

For preempt fence mode, triggering the DMA_RESV_USAGE_BOOKKEEP fences
interrupts execution, queue rebind worker, and uses a same list / flow
as execs to resume exection. I am missing a
dma_resv_wait(DMA_RESV_USAGE_BOOKKEEP) here though as we need to wait
for execution to interrupted before moving on. Will include in next rev.

For faulting mode, we should cancel the bind by converting cpu bind /
job bind to clear the PTEs entries. This will ensure a stale userptr is
not visable to the GPU and next access will trigger a fault kicking off
a pin and rebind. Again will fix in next rev.

Matt

> Oak
> 
> > 
> > -		notifier_seq = mmu_interval_read_begin(&uvma-
> > >userptr.notifier);
> > -	} while (true);
> > +	spin_lock(&vm->userptr.invalidated_lock);
> > +	list_move_tail(&uvma->userptr.invalidate_link,
> > +		       &vm->userptr.invalidated);
> > +	spin_unlock(&vm->userptr.invalidated_lock);
> > 
> > -	/* Inject errors to test_whether they are handled correctly */
> > -	if (userptr_update->bind && xe_pt_userptr_inject_eagain(uvma)) {
> > -		up_read(&vm->userptr.notifier_lock);
> > -		return -EAGAIN;
> > +	if (xe_vm_in_preempt_fence_mode(vm)) {
> > +		struct dma_resv_iter cursor;
> > +		struct dma_fence *fence;
> > +
> > +		dma_resv_iter_begin(&cursor, xe_vm_resv(vm),
> > +				    DMA_RESV_USAGE_BOOKKEEP);
> > +		dma_resv_for_each_fence_unlocked(&cursor, fence)
> > +			dma_fence_enable_sw_signaling(fence);
> > +		dma_resv_iter_end(&cursor);
> >  	}
> > +}
> > 
> > -	userptr_update->locked = true;
> > +static void op_check_userptr(struct xe_vm *vm, struct xe_vma_op *op)
> > +{
> > +	lockdep_assert_held_read(&vm->userptr.notifier_lock);
> > 
> > -	return 0;
> > +	switch (op->base.op) {
> > +	case DRM_GPUVA_OP_MAP:
> > +		if (!op->map.immediate && xe_vm_in_fault_mode(vm))
> > +			break;
> > +
> > +		vma_check_userptr(vm, op->map.vma);
> > +		break;
> > +	case DRM_GPUVA_OP_REMAP:
> > +		if (op->remap.prev)
> > +			vma_check_userptr(vm, op->remap.prev);
> > +		if (op->remap.next)
> > +			vma_check_userptr(vm, op->remap.next);
> > +		break;
> > +	case DRM_GPUVA_OP_UNMAP:
> > +		break;
> > +	case DRM_GPUVA_OP_PREFETCH:
> > +		vma_check_userptr(vm, gpuva_to_vma(op->base.prefetch.va));
> > +		break;
> > +	default:
> > +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > +	}
> >  }
> > 
> > -static const struct xe_migrate_pt_update_ops bind_ops = {
> > -	.populate = xe_vm_populate_pgtable,
> > -	.pre_commit = xe_pt_pre_commit,
> > -};
> > +static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> > +{
> > +	struct xe_vm *vm = pt_update->vops->vm;
> > +	struct xe_vma_ops *vops = pt_update->vops;
> > +	struct xe_vma_op *op;
> > +	int err;
> > 
> > -static const struct xe_migrate_pt_update_ops userptr_bind_ops = {
> > -	.populate = xe_vm_populate_pgtable,
> > -	.pre_commit = xe_pt_userptr_pre_commit,
> > -};
> > +	err = xe_pt_pre_commit(pt_update);
> > +	if (err)
> > +		return err;
> > +
> > +	down_read(&vm->userptr.notifier_lock);
> > +
> > +	list_for_each_entry(op, &vops->list, link)
> > +		op_check_userptr(vm, op);
> > +
> > +	return 0;
> > +}
> > 
> >  struct invalidation_fence {
> >  	struct xe_gt_tlb_invalidation_fence base;
> > @@ -1166,181 +1286,6 @@ static int invalidation_fence_init(struct xe_gt *gt,
> >  	return ret && ret != -ENOENT ? ret : 0;
> >  }
> > 
> > -static void xe_pt_calc_rfence_interval(struct xe_vma *vma,
> > -				       struct xe_pt_migrate_pt_update *update,
> > -				       struct xe_vm_pgtable_update *entries,
> > -				       u32 num_entries)
> > -{
> > -	int i, level = 0;
> > -
> > -	for (i = 0; i < num_entries; i++) {
> > -		const struct xe_vm_pgtable_update *entry = &entries[i];
> > -
> > -		if (entry->pt->level > level)
> > -			level = entry->pt->level;
> > -	}
> > -
> > -	/* Greedy (non-optimal) calculation but simple */
> > -	update->base.start = ALIGN_DOWN(xe_vma_start(vma),
> > -					0x1ull << xe_pt_shift(level));
> > -	update->base.last = ALIGN(xe_vma_end(vma),
> > -				  0x1ull << xe_pt_shift(level)) - 1;
> > -}
> > -
> > -/**
> > - * __xe_pt_bind_vma() - Build and connect a page-table tree for the vma
> > - * address range.
> > - * @tile: The tile to bind for.
> > - * @vma: The vma to bind.
> > - * @q: The exec_queue with which to do pipelined page-table updates.
> > - * @syncs: Entries to sync on before binding the built tree to the live vm tree.
> > - * @num_syncs: Number of @sync entries.
> > - * @rebind: Whether we're rebinding this vma to the same address range
> > without
> > - * an unbind in-between.
> > - *
> > - * This function builds a page-table tree (see xe_pt_stage_bind() for more
> > - * information on page-table building), and the xe_vm_pgtable_update entries
> > - * abstracting the operations needed to attach it to the main vm tree. It
> > - * then takes the relevant locks and updates the metadata side of the main
> > - * vm tree and submits the operations for pipelined attachment of the
> > - * gpu page-table to the vm main tree, (which can be done either by the
> > - * cpu and the GPU).
> > - *
> > - * Return: A valid dma-fence representing the pipelined attachment operation
> > - * on success, an error pointer on error.
> > - */
> > -struct dma_fence *
> > -__xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct
> > xe_exec_queue *q,
> > -		 struct xe_sync_entry *syncs, u32 num_syncs,
> > -		 bool rebind)
> > -{
> > -	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
> > -	struct xe_pt_migrate_pt_update bind_pt_update = {
> > -		.base = {
> > -			.ops = xe_vma_is_userptr(vma) ? &userptr_bind_ops :
> > &bind_ops,
> > -			.vma = vma,
> > -			.tile_id = tile->id,
> > -		},
> > -		.bind = true,
> > -	};
> > -	struct xe_vm *vm = xe_vma_vm(vma);
> > -	u32 num_entries;
> > -	struct dma_fence *fence;
> > -	struct invalidation_fence *ifence = NULL;
> > -	struct xe_range_fence *rfence;
> > -	int err;
> > -
> > -	bind_pt_update.locked = false;
> > -	xe_bo_assert_held(xe_vma_bo(vma));
> > -	xe_vm_assert_held(vm);
> > -
> > -	vm_dbg(&xe_vma_vm(vma)->xe->drm,
> > -	       "Preparing bind, with range [%llx...%llx) engine %p.\n",
> > -	       xe_vma_start(vma), xe_vma_end(vma), q);
> > -
> > -	err = xe_pt_prepare_bind(tile, vma, entries, &num_entries);
> > -	if (err)
> > -		goto err;
> > -	xe_tile_assert(tile, num_entries <= ARRAY_SIZE(entries));
> > -
> > -	xe_vm_dbg_print_entries(tile_to_xe(tile), entries, num_entries);
> > -	xe_pt_calc_rfence_interval(vma, &bind_pt_update, entries,
> > -				   num_entries);
> > -
> > -	/*
> > -	 * If rebind, we have to invalidate TLB on !LR vms to invalidate
> > -	 * cached PTEs point to freed memory. on LR vms this is done
> > -	 * automatically when the context is re-enabled by the rebind worker,
> > -	 * or in fault mode it was invalidated on PTE zapping.
> > -	 *
> > -	 * If !rebind, and scratch enabled VMs, there is a chance the scratch
> > -	 * PTE is already cached in the TLB so it needs to be invalidated.
> > -	 * on !LR VMs this is done in the ring ops preceding a batch, but on
> > -	 * non-faulting LR, in particular on user-space batch buffer chaining,
> > -	 * it needs to be done here.
> > -	 */
> > -	if ((rebind && !xe_vm_in_lr_mode(vm) && !vm->batch_invalidate_tlb)
> > ||
> > -	    (!rebind && xe_vm_has_scratch(vm) &&
> > xe_vm_in_preempt_fence_mode(vm))) {
> > -		ifence = kzalloc(sizeof(*ifence), GFP_KERNEL);
> > -		if (!ifence)
> > -			return ERR_PTR(-ENOMEM);
> > -	}
> > -
> > -	rfence = kzalloc(sizeof(*rfence), GFP_KERNEL);
> > -	if (!rfence) {
> > -		kfree(ifence);
> > -		return ERR_PTR(-ENOMEM);
> > -	}
> > -
> > -	fence = xe_migrate_update_pgtables(tile->migrate,
> > -					   vm, xe_vma_bo(vma), q,
> > -					   entries, num_entries,
> > -					   syncs, num_syncs,
> > -					   &bind_pt_update.base);
> > -	if (!IS_ERR(fence)) {
> > -		bool last_munmap_rebind = vma->gpuva.flags &
> > XE_VMA_LAST_REBIND;
> > -		LLIST_HEAD(deferred);
> > -		int err;
> > -
> > -		err = xe_range_fence_insert(&vm->rftree[tile->id], rfence,
> > -					    &xe_range_fence_kfree_ops,
> > -					    bind_pt_update.base.start,
> > -					    bind_pt_update.base.last, fence);
> > -		if (err)
> > -			dma_fence_wait(fence, false);
> > -
> > -		/* TLB invalidation must be done before signaling rebind */
> > -		if (ifence) {
> > -			int err = invalidation_fence_init(tile->primary_gt,
> > -							  ifence, fence,
> > -							  xe_vma_start(vma),
> > -							  xe_vma_end(vma),
> > -							  xe_vma_vm(vma)-
> > >usm.asid);
> > -			if (err) {
> > -				dma_fence_put(fence);
> > -				kfree(ifence);
> > -				return ERR_PTR(err);
> > -			}
> > -			fence = &ifence->base.base;
> > -		}
> > -
> > -		/* add shared fence now for pagetable delayed destroy */
> > -		dma_resv_add_fence(xe_vm_resv(vm), fence, !rebind &&
> > -				   last_munmap_rebind ?
> > -				   DMA_RESV_USAGE_KERNEL :
> > -				   DMA_RESV_USAGE_BOOKKEEP);
> > -
> > -		if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm)
> > -			dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv,
> > fence,
> > -					   DMA_RESV_USAGE_BOOKKEEP);
> > -		xe_pt_commit_bind(vma, entries, num_entries, rebind,
> > -				  bind_pt_update.locked ? &deferred : NULL);
> > -
> > -		/* This vma is live (again?) now */
> > -		vma->tile_present |= BIT(tile->id);
> > -
> > -		if (bind_pt_update.locked) {
> > -			to_userptr_vma(vma)->userptr.initial_bind = true;
> > -			up_read(&vm->userptr.notifier_lock);
> > -			xe_bo_put_commit(&deferred);
> > -		}
> > -		if (!rebind && last_munmap_rebind &&
> > -		    xe_vm_in_preempt_fence_mode(vm))
> > -			xe_vm_queue_rebind_worker(vm);
> > -	} else {
> > -		kfree(rfence);
> > -		kfree(ifence);
> > -		if (bind_pt_update.locked)
> > -			up_read(&vm->userptr.notifier_lock);
> > -		xe_pt_abort_bind(vma, entries, num_entries);
> > -	}
> > -
> > -	return fence;
> > -
> > -err:
> > -	return ERR_PTR(err);
> > -}
> > -
> >  struct xe_pt_stage_unbind_walk {
> >  	/** @base: The pagewalk base-class. */
> >  	struct xe_pt_walk base;
> > @@ -1491,8 +1436,8 @@ xe_migrate_clear_pgtable_callback(struct
> > xe_migrate_pt_update *pt_update,
> >  				  void *ptr, u32 qword_ofs, u32 num_qwords,
> >  				  const struct xe_vm_pgtable_update *update)
> >  {
> > -	struct xe_vma *vma = pt_update->vma;
> > -	u64 empty = __xe_pt_empty_pte(tile, xe_vma_vm(vma), update->pt-
> > >level);
> > +	struct xe_vm *vm = pt_update->vops->vm;
> > +	u64 empty = __xe_pt_empty_pte(tile, vm, update->pt->level);
> >  	int i;
> > 
> >  	if (map && map->is_iomem)
> > @@ -1536,144 +1481,443 @@ xe_pt_commit_unbind(struct xe_vma *vma,
> >  	}
> >  }
> > 
> > -static const struct xe_migrate_pt_update_ops unbind_ops = {
> > -	.populate = xe_migrate_clear_pgtable_callback,
> > +static void
> > +xe_pt_update_ops_rfence_interval(struct xe_vm_pgtable_update_ops
> > *pt_update_ops,
> > +				 struct xe_vma *vma)
> > +{
> > +	u32 current_op = pt_update_ops->current_op;
> > +	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops-
> > >ops[current_op];
> > +	int i, level = 0;
> > +	u64 start, last;
> > +
> > +	for (i = 0; i < pt_op->num_entries; i++) {
> > +		const struct xe_vm_pgtable_update *entry = &pt_op->entries[i];
> > +
> > +		if (entry->pt->level > level)
> > +			level = entry->pt->level;
> > +	}
> > +
> > +	/* Greedy (non-optimal) calculation but simple */
> > +	start = ALIGN_DOWN(xe_vma_start(vma), 0x1ull << xe_pt_shift(level));
> > +	last = ALIGN(xe_vma_end(vma), 0x1ull << xe_pt_shift(level)) - 1;
> > +
> > +	if (start < pt_update_ops->start)
> > +		pt_update_ops->start = start;
> > +	if (last > pt_update_ops->last)
> > +		pt_update_ops->last = last;
> > +}
> > +
> > +static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile,
> > +			   struct xe_vm_pgtable_update_ops *pt_update_ops,
> > +			   struct xe_vma *vma)
> > +{
> > +	u32 current_op = pt_update_ops->current_op;
> > +	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops-
> > >ops[current_op];
> > +	struct llist_head *deferred = &pt_update_ops->deferred;
> > +	int err;
> > +
> > +	xe_bo_assert_held(xe_vma_bo(vma));
> > +
> > +	vm_dbg(&xe_vma_vm(vma)->xe->drm,
> > +	       "Preparing bind, with range [%llx...%llx)\n",
> > +	       xe_vma_start(vma), xe_vma_end(vma) - 1);
> > +
> > +	pt_op->bind = true;
> > +	pt_op->rebind = BIT(tile->id) & vma->tile_present;
> > +
> > +	err = xe_pt_prepare_bind(tile, vma, pt_op->entries,
> > +				 &pt_op->num_entries);
> > +	if (!err) {
> > +		xe_tile_assert(tile, pt_op->num_entries <=
> > +			       ARRAY_SIZE(pt_op->entries));
> > +		xe_vm_dbg_print_entries(tile_to_xe(tile), pt_op->entries,
> > +					pt_op->num_entries, true);
> > +
> > +		xe_pt_update_ops_rfence_interval(pt_update_ops, vma);
> > +		++pt_update_ops->current_op;
> > +		pt_update_ops->needs_userptr_lock |=
> > xe_vma_is_userptr(vma);
> > +
> > +		/*
> > +		 * If rebind, we have to invalidate TLB on !LR vms to invalidate
> > +		 * cached PTEs point to freed memory. on LR vms this is done
> > +		 * automatically when the context is re-enabled by the rebind
> > +		 * worker, or in fault mode it was invalidated on PTE zapping.
> > +		 *
> > +		 * If !rebind, and scratch enabled VMs, there is a chance the
> > +		 * scratch PTE is already cached in the TLB so it needs to be
> > +		 * invalidated. on !LR VMs this is done in the ring ops
> > +		 * preceding a batch, but on non-faulting LR, in particular on
> > +		 * user-space batch buffer chaining, it needs to be done here.
> > +		 */
> > +		pt_update_ops->needs_invalidation |=
> > +			(pt_op->rebind && xe_vm_in_lr_mode(vm) &&
> > +			!vm->batch_invalidate_tlb) ||
> > +			(!pt_op->rebind && vm->scratch_pt[tile->id] &&
> > +			 xe_vm_in_preempt_fence_mode(vm));
> > +
> > +		/* FIXME: Don't commit right away */
> > +		xe_pt_commit_bind(vma, pt_op->entries, pt_op->num_entries,
> > +				  pt_op->rebind, deferred);
> > +	}
> > +
> > +	return err;
> > +}
> > +
> > +static int unbind_op_prepare(struct xe_tile *tile,
> > +			     struct xe_vm_pgtable_update_ops *pt_update_ops,
> > +			     struct xe_vma *vma)
> > +{
> > +	u32 current_op = pt_update_ops->current_op;
> > +	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops-
> > >ops[current_op];
> > +	struct llist_head *deferred = &pt_update_ops->deferred;
> > +
> > +	xe_bo_assert_held(xe_vma_bo(vma));
> > +
> > +	vm_dbg(&xe_vma_vm(vma)->xe->drm,
> > +	       "Preparing unbind, with range [%llx...%llx)\n",
> > +	       xe_vma_start(vma), xe_vma_end(vma) - 1);
> > +
> > +	pt_op->bind = false;
> > +	pt_op->rebind = false;
> > +
> > +	pt_op->num_entries = xe_pt_stage_unbind(tile, vma, pt_op->entries);
> > +
> > +	xe_vm_dbg_print_entries(tile_to_xe(tile), pt_op->entries,
> > +				pt_op->num_entries, false);
> > +	xe_pt_update_ops_rfence_interval(pt_update_ops, vma);
> > +	++pt_update_ops->current_op;
> > +	pt_update_ops->needs_userptr_lock |= xe_vma_is_userptr(vma);
> > +	pt_update_ops->needs_invalidation = true;
> > +
> > +	/* FIXME: Don't commit right away */
> > +	xe_pt_commit_unbind(vma, pt_op->entries, pt_op->num_entries,
> > +			    deferred);
> > +
> > +	return 0;
> > +}
> > +
> > +static int op_prepare(struct xe_vm *vm,
> > +		      struct xe_tile *tile,
> > +		      struct xe_vm_pgtable_update_ops *pt_update_ops,
> > +		      struct xe_vma_op *op)
> > +{
> > +	int err = 0;
> > +
> > +	xe_vm_assert_held(vm);
> > +
> > +	switch (op->base.op) {
> > +	case DRM_GPUVA_OP_MAP:
> > +		if (!op->map.immediate && xe_vm_in_fault_mode(vm))
> > +			break;
> > +
> > +		err = bind_op_prepare(vm, tile, pt_update_ops, op->map.vma);
> > +		pt_update_ops->wait_vm_kernel = true;
> > +		break;
> > +	case DRM_GPUVA_OP_REMAP:
> > +		err = unbind_op_prepare(tile, pt_update_ops,
> > +					gpuva_to_vma(op->base.remap.unmap-
> > >va));
> > +
> > +		if (!err && op->remap.prev) {
> > +			err = bind_op_prepare(vm, tile, pt_update_ops,
> > +					      op->remap.prev);
> > +			pt_update_ops->wait_vm_bookkeep = true;
> > +		}
> > +		if (!err && op->remap.next) {
> > +			err = bind_op_prepare(vm, tile, pt_update_ops,
> > +					      op->remap.next);
> > +			pt_update_ops->wait_vm_bookkeep = true;
> > +		}
> > +		break;
> > +	case DRM_GPUVA_OP_UNMAP:
> > +		err = unbind_op_prepare(tile, pt_update_ops,
> > +					gpuva_to_vma(op->base.unmap.va));
> > +		break;
> > +	case DRM_GPUVA_OP_PREFETCH:
> > +		err = bind_op_prepare(vm, tile, pt_update_ops,
> > +				      gpuva_to_vma(op->base.prefetch.va));
> > +		pt_update_ops->wait_vm_kernel = true;
> > +		break;
> > +	default:
> > +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > +	}
> > +
> > +	return err;
> > +}
> > +
> > +static void
> > +xe_pt_update_ops_init(struct xe_vm_pgtable_update_ops *pt_update_ops)
> > +{
> > +	init_llist_head(&pt_update_ops->deferred);
> > +	pt_update_ops->start = ~0x0ull;
> > +	pt_update_ops->last = 0x0ull;
> > +}
> > +
> > +/**
> > + * xe_pt_update_ops_prepare() - Prepare PT update operations
> > + * @tile: Tile of PT update operations
> > + * @vops: VMA operationa
> > + *
> > + * Prepare PT update operations which includes updating internal PT state,
> > + * allocate memory for page tables, populate page table being pruned in, and
> > + * create PT update operations for leaf insertion / removal.
> > + *
> > + * Return: 0 on success, negative error code on error.
> > + */
> > +int xe_pt_update_ops_prepare(struct xe_tile *tile, struct xe_vma_ops *vops)
> > +{
> > +	struct xe_vm_pgtable_update_ops *pt_update_ops =
> > +		&vops->pt_update_ops[tile->id];
> > +	struct xe_vma_op *op;
> > +	int err;
> > +
> > +	lockdep_assert_held(&vops->vm->lock);
> > +	xe_vm_assert_held(vops->vm);
> > +
> > +	xe_pt_update_ops_init(pt_update_ops);
> > +
> > +	list_for_each_entry(op, &vops->list, link) {
> > +		err = op_prepare(vops->vm, tile, pt_update_ops, op);
> > +
> > +		if (err)
> > +			return err;
> > +	}
> > +
> > +	xe_tile_assert(tile, pt_update_ops->current_op ==
> > +		       pt_update_ops->num_ops);
> > +
> > +	return 0;
> > +}
> > +
> > +static void bind_op_commit(struct xe_vm *vm, struct xe_tile *tile,
> > +			   struct xe_vm_pgtable_update_ops *pt_update_ops,
> > +			   struct xe_vma *vma, struct dma_fence *fence)
> > +{
> > +	if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm)
> > +		dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence,
> > +				   pt_update_ops->wait_vm_bookkeep ?
> > +				   DMA_RESV_USAGE_KERNEL :
> > +				   DMA_RESV_USAGE_BOOKKEEP);
> > +	vma->tile_present |= BIT(tile->id);
> > +	if (xe_vma_is_userptr(vma)) {
> > +		lockdep_assert_held_read(&vm->userptr.notifier_lock);
> > +		to_userptr_vma(vma)->userptr.initial_bind = true;
> > +	}
> > +
> > +	/*
> > +	 * Kick rebind worker if this bind triggers preempt fences and not in
> > +	 * the rebind worker
> > +	 */
> > +	if (pt_update_ops->wait_vm_bookkeep &&
> > +	    xe_vm_in_preempt_fence_mode(vm) &&
> > +	    !current->mm)
> > +		xe_vm_queue_rebind_worker(vm);
> > +}
> > +
> > +static void unbind_op_commit(struct xe_vm *vm, struct xe_tile *tile,
> > +			     struct xe_vm_pgtable_update_ops *pt_update_ops,
> > +			     struct xe_vma *vma, struct dma_fence *fence)
> > +{
> > +	if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm)
> > +		dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence,
> > +				   pt_update_ops->wait_vm_bookkeep ?
> > +				   DMA_RESV_USAGE_KERNEL :
> > +				   DMA_RESV_USAGE_BOOKKEEP);
> > +	vma->tile_present &= ~BIT(tile->id);
> > +	if (!vma->tile_present) {
> > +		list_del_init(&vma->combined_links.rebind);
> > +		if (xe_vma_is_userptr(vma)) {
> > +			lockdep_assert_held_read(&vm->userptr.notifier_lock);
> > +
> > +			spin_lock(&vm->userptr.invalidated_lock);
> > +			list_del_init(&to_userptr_vma(vma)-
> > >userptr.invalidate_link);
> > +			spin_unlock(&vm->userptr.invalidated_lock);
> > +		}
> > +	}
> > +}
> > +
> > +static void op_commit(struct xe_vm *vm,
> > +		      struct xe_tile *tile,
> > +		      struct xe_vm_pgtable_update_ops *pt_update_ops,
> > +		      struct xe_vma_op *op, struct dma_fence *fence)
> > +{
> > +	xe_vm_assert_held(vm);
> > +
> > +	switch (op->base.op) {
> > +	case DRM_GPUVA_OP_MAP:
> > +		if (!op->map.immediate && xe_vm_in_fault_mode(vm))
> > +			break;
> > +
> > +		bind_op_commit(vm, tile, pt_update_ops, op->map.vma, fence);
> > +		break;
> > +	case DRM_GPUVA_OP_REMAP:
> > +		unbind_op_commit(vm, tile, pt_update_ops,
> > +				 gpuva_to_vma(op->base.remap.unmap->va),
> > fence);
> > +
> > +		if (op->remap.prev)
> > +			bind_op_commit(vm, tile, pt_update_ops, op-
> > >remap.prev,
> > +				       fence);
> > +		if (op->remap.next)
> > +			bind_op_commit(vm, tile, pt_update_ops, op-
> > >remap.next,
> > +				       fence);
> > +		break;
> > +	case DRM_GPUVA_OP_UNMAP:
> > +		unbind_op_commit(vm, tile, pt_update_ops,
> > +				 gpuva_to_vma(op->base.unmap.va), fence);
> > +		break;
> > +	case DRM_GPUVA_OP_PREFETCH:
> > +		bind_op_commit(vm, tile, pt_update_ops,
> > +			       gpuva_to_vma(op->base.prefetch.va), fence);
> > +		break;
> > +	default:
> > +		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > +	}
> > +}
> > +
> > +static const struct xe_migrate_pt_update_ops migrate_ops = {
> > +	.populate = xe_vm_populate_pgtable,
> > +	.clear = xe_migrate_clear_pgtable_callback,
> >  	.pre_commit = xe_pt_pre_commit,
> >  };
> > 
> > -static const struct xe_migrate_pt_update_ops userptr_unbind_ops = {
> > -	.populate = xe_migrate_clear_pgtable_callback,
> > +static const struct xe_migrate_pt_update_ops userptr_migrate_ops = {
> > +	.populate = xe_vm_populate_pgtable,
> > +	.clear = xe_migrate_clear_pgtable_callback,
> >  	.pre_commit = xe_pt_userptr_pre_commit,
> >  };
> > 
> >  /**
> > - * __xe_pt_unbind_vma() - Disconnect and free a page-table tree for the vma
> > - * address range.
> > - * @tile: The tile to unbind for.
> > - * @vma: The vma to unbind.
> > - * @q: The exec_queue with which to do pipelined page-table updates.
> > - * @syncs: Entries to sync on before disconnecting the tree to be destroyed.
> > - * @num_syncs: Number of @sync entries.
> > + * xe_pt_update_ops_run() - Run PT update operations
> > + * @tile: Tile of PT update operations
> > + * @vops: VMA operationa
> >   *
> > - * This function builds a the xe_vm_pgtable_update entries abstracting the
> > - * operations needed to detach the page-table tree to be destroyed from the
> > - * man vm tree.
> > - * It then takes the relevant locks and submits the operations for
> > - * pipelined detachment of the gpu page-table from  the vm main tree,
> > - * (which can be done either by the cpu and the GPU), Finally it frees the
> > - * detached page-table tree.
> > + * Run PT update operations which includes committing internal PT state
> > changes,
> > + * creating job for PT update operations for leaf insertion / removal, and
> > + * installing job fence in various places.
> >   *
> > - * Return: A valid dma-fence representing the pipelined detachment operation
> > - * on success, an error pointer on error.
> > + * Return: fence on success, negative ERR_PTR on error.
> >   */
> >  struct dma_fence *
> > -__xe_pt_unbind_vma(struct xe_tile *tile, struct xe_vma *vma, struct
> > xe_exec_queue *q,
> > -		   struct xe_sync_entry *syncs, u32 num_syncs)
> > +xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> >  {
> > -	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
> > -	struct xe_pt_migrate_pt_update unbind_pt_update = {
> > -		.base = {
> > -			.ops = xe_vma_is_userptr(vma) ? &userptr_unbind_ops :
> > -			&unbind_ops,
> > -			.vma = vma,
> > -			.tile_id = tile->id,
> > -		},
> > -	};
> > -	struct xe_vm *vm = xe_vma_vm(vma);
> > -	u32 num_entries;
> > -	struct dma_fence *fence = NULL;
> > -	struct invalidation_fence *ifence;
> > +	struct xe_vm *vm = vops->vm;
> > +	struct xe_vm_pgtable_update_ops *pt_update_ops =
> > +		&vops->pt_update_ops[tile->id];
> > +	struct dma_fence *fence;
> > +	struct invalidation_fence *ifence = NULL;
> >  	struct xe_range_fence *rfence;
> > +	struct xe_vma_op *op;
> > +	int err = 0;
> > +	struct xe_migrate_pt_update update = {
> > +		.ops = pt_update_ops->needs_userptr_lock ?
> > +			&userptr_migrate_ops :
> > +			&migrate_ops,
> > +		.vops = vops,
> > +		.tile_id = tile->id
> > +	};
> > 
> > -	LLIST_HEAD(deferred);
> > -
> > -	xe_bo_assert_held(xe_vma_bo(vma));
> > +	lockdep_assert_held(&vm->lock);
> >  	xe_vm_assert_held(vm);
> > 
> > -	vm_dbg(&xe_vma_vm(vma)->xe->drm,
> > -	       "Preparing unbind, with range [%llx...%llx) engine %p.\n",
> > -	       xe_vma_start(vma), xe_vma_end(vma), q);
> > -
> > -	num_entries = xe_pt_stage_unbind(tile, vma, entries);
> > -	xe_tile_assert(tile, num_entries <= ARRAY_SIZE(entries));
> > -
> > -	xe_vm_dbg_print_entries(tile_to_xe(tile), entries, num_entries);
> > -	xe_pt_calc_rfence_interval(vma, &unbind_pt_update, entries,
> > -				   num_entries);
> > -
> > -	ifence = kzalloc(sizeof(*ifence), GFP_KERNEL);
> > -	if (!ifence)
> > -		return ERR_PTR(-ENOMEM);
> > +	if (pt_update_ops->needs_invalidation) {
> > +		ifence = kzalloc(sizeof(*ifence), GFP_KERNEL);
> > +		if (!ifence)
> > +			return ERR_PTR(-ENOMEM);
> > +	}
> > 
> >  	rfence = kzalloc(sizeof(*rfence), GFP_KERNEL);
> >  	if (!rfence) {
> > -		kfree(ifence);
> > -		return ERR_PTR(-ENOMEM);
> > +		err = -ENOMEM;
> > +		goto free_ifence;
> >  	}
> > 
> > -	/*
> > -	 * Even if we were already evicted and unbind to destroy, we need to
> > -	 * clear again here. The eviction may have updated pagetables at a
> > -	 * lower level, because it needs to be more conservative.
> > -	 */
> > -	fence = xe_migrate_update_pgtables(tile->migrate,
> > -					   vm, NULL, q ? q :
> > -					   vm->q[tile->id],
> > -					   entries, num_entries,
> > -					   syncs, num_syncs,
> > -					   &unbind_pt_update.base);
> > -	if (!IS_ERR(fence)) {
> > -		int err;
> > -
> > -		err = xe_range_fence_insert(&vm->rftree[tile->id], rfence,
> > -					    &xe_range_fence_kfree_ops,
> > -					    unbind_pt_update.base.start,
> > -					    unbind_pt_update.base.last, fence);
> > -		if (err)
> > -			dma_fence_wait(fence, false);
> > +	fence = xe_migrate_update_pgtables(tile->migrate, &update);
> > +	if (IS_ERR(fence)) {
> > +		err = PTR_ERR(fence);
> > +		goto free_rfence;
> > +	}
> > +
> > +	err = xe_range_fence_insert(&vm->rftree[tile->id], rfence,
> > +				    &xe_range_fence_kfree_ops,
> > +				    pt_update_ops->start,
> > +				    pt_update_ops->last, fence);
> > +	if (err)
> > +		dma_fence_wait(fence, false);
> > 
> > -		/* TLB invalidation must be done before signaling unbind */
> > +	/* tlb invalidation must be done before signaling rebind */
> > +	if (ifence) {
> >  		err = invalidation_fence_init(tile->primary_gt, ifence, fence,
> > -					      xe_vma_start(vma),
> > -					      xe_vma_end(vma),
> > -					      xe_vma_vm(vma)->usm.asid);
> > -		if (err) {
> > -			dma_fence_put(fence);
> > -			kfree(ifence);
> > -			return ERR_PTR(err);
> > -		}
> > +					      pt_update_ops->start,
> > +					      pt_update_ops->last,
> > +					      vm->usm.asid);
> > +		if (err)
> > +			goto put_fence;
> >  		fence = &ifence->base.base;
> > +	}
> > 
> > -		/* add shared fence now for pagetable delayed destroy */
> > -		dma_resv_add_fence(xe_vm_resv(vm), fence,
> > -				   DMA_RESV_USAGE_BOOKKEEP);
> > +	dma_resv_add_fence(xe_vm_resv(vm), fence,
> > +			   pt_update_ops->wait_vm_bookkeep ?
> > +			   DMA_RESV_USAGE_KERNEL :
> > +			   DMA_RESV_USAGE_BOOKKEEP);
> > 
> > -		/* This fence will be installed by caller when doing eviction */
> > -		if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm)
> > -			dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv,
> > fence,
> > -					   DMA_RESV_USAGE_BOOKKEEP);
> > -		xe_pt_commit_unbind(vma, entries, num_entries,
> > -				    unbind_pt_update.locked ? &deferred : NULL);
> > -		vma->tile_present &= ~BIT(tile->id);
> > -	} else {
> > -		kfree(rfence);
> > -		kfree(ifence);
> > -	}
> > +	list_for_each_entry(op, &vops->list, link)
> > +		op_commit(vops->vm, tile, pt_update_ops, op, fence);
> > 
> > -	if (!vma->tile_present)
> > -		list_del_init(&vma->combined_links.rebind);
> > +	if (pt_update_ops->needs_userptr_lock)
> > +		up_read(&vm->userptr.notifier_lock);
> > 
> > -	if (unbind_pt_update.locked) {
> > -		xe_tile_assert(tile, xe_vma_is_userptr(vma));
> > +	return fence;
> > 
> > -		if (!vma->tile_present) {
> > -			spin_lock(&vm->userptr.invalidated_lock);
> > -			list_del_init(&to_userptr_vma(vma)-
> > >userptr.invalidate_link);
> > -			spin_unlock(&vm->userptr.invalidated_lock);
> > -		}
> > +put_fence:
> > +	if (pt_update_ops->needs_userptr_lock)
> >  		up_read(&vm->userptr.notifier_lock);
> > -		xe_bo_put_commit(&deferred);
> > +	dma_fence_put(fence);
> > +free_rfence:
> > +	kfree(rfence);
> > +free_ifence:
> > +	kfree(ifence);
> > +
> > +	return ERR_PTR(err);
> > +}
> > +
> > +/**
> > + * xe_pt_update_ops_fini() - Finish PT update operations
> > + * @tile: Tile of PT update operations
> > + * @vops: VMA operations
> > + *
> > + * Finish PT update operations by committing to destroy page table memory
> > + */
> > +void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops)
> > +{
> > +	struct xe_vm_pgtable_update_ops *pt_update_ops =
> > +		&vops->pt_update_ops[tile->id];
> > +	int i;
> > +
> > +	lockdep_assert_held(&vops->vm->lock);
> > +	xe_vm_assert_held(vops->vm);
> > +
> > +	/* FIXME: Not 100% correct */
> > +	for (i = 0; i < pt_update_ops->num_ops; ++i) {
> > +		struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops-
> > >ops[i];
> > +
> > +		if (pt_op->bind)
> > +			xe_pt_free_bind(pt_op->entries, pt_op->num_entries);
> >  	}
> > +	xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred);
> > +}
> > 
> > -	return fence;
> > +/**
> > + * xe_pt_update_ops_abort() - Abort PT update operations
> > + * @tile: Tile of PT update operations
> > + * @vops: VMA operationa
> > + *
> > + *  Abort PT update operations by unwinding internal PT state
> > + */
> > +void xe_pt_update_ops_abort(struct xe_tile *tile, struct xe_vma_ops *vops)
> > +{
> > +	lockdep_assert_held(&vops->vm->lock);
> > +	xe_vm_assert_held(vops->vm);
> > +
> > +	/* FIXME: Just kill VM for now + cleanup PTs */
> > +	xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred);
> > +	xe_vm_kill(vops->vm, false);
> >  }
> > diff --git a/drivers/gpu/drm/xe/xe_pt.h b/drivers/gpu/drm/xe/xe_pt.h
> > index 71a4fbfcff43..cbf8170d89cc 100644
> > --- a/drivers/gpu/drm/xe/xe_pt.h
> > +++ b/drivers/gpu/drm/xe/xe_pt.h
> > @@ -17,6 +17,7 @@ struct xe_sync_entry;
> >  struct xe_tile;
> >  struct xe_vm;
> >  struct xe_vma;
> > +struct xe_vma_ops;
> > 
> >  /* Largest huge pte is currently 1GiB. May become device dependent. */
> >  #define MAX_HUGEPTE_LEVEL 2
> > @@ -34,6 +35,12 @@ void xe_pt_populate_empty(struct xe_tile *tile, struct
> > xe_vm *vm,
> > 
> >  void xe_pt_destroy(struct xe_pt *pt, u32 flags, struct llist_head *deferred);
> > 
> > +int xe_pt_update_ops_prepare(struct xe_tile *tile, struct xe_vma_ops *vops);
> > +struct dma_fence *xe_pt_update_ops_run(struct xe_tile *tile,
> > +				       struct xe_vma_ops *vops);
> > +void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops);
> > +void xe_pt_update_ops_abort(struct xe_tile *tile, struct xe_vma_ops *vops);
> > +
> >  struct dma_fence *
> >  __xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct
> > xe_exec_queue *q,
> >  		 struct xe_sync_entry *syncs, u32 num_syncs,
> > diff --git a/drivers/gpu/drm/xe/xe_pt_types.h
> > b/drivers/gpu/drm/xe/xe_pt_types.h
> > index 2093150f461e..16252f1be055 100644
> > --- a/drivers/gpu/drm/xe/xe_pt_types.h
> > +++ b/drivers/gpu/drm/xe/xe_pt_types.h
> > @@ -86,4 +86,38 @@ struct xe_vm_pgtable_update_op {
> >  	bool rebind;
> >  };
> > 
> > +/** struct xe_vm_pgtable_update_ops: page table update operations */
> > +struct xe_vm_pgtable_update_ops {
> > +	/** @ops: operations */
> > +	struct xe_vm_pgtable_update_op *ops;
> > +	/** @deferred: deferred list to destroy PT entries */
> > +	struct llist_head deferred;
> > +	/** @q: exec queue for PT operations */
> > +	struct xe_exec_queue *q;
> > +	/** @start: start address of ops */
> > +	u64 start;
> > +	/** @last: last address of ops */
> > +	u64 last;
> > +	/** @num_ops: number of operations */
> > +	u32 num_ops;
> > +	/** @current_op: current operations */
> > +	u32 current_op;
> > +	/** @needs_userptr_lock: Needs userptr lock */
> > +	bool needs_userptr_lock;
> > +	/** @needs_invalidation: Needs invalidation */
> > +	bool needs_invalidation;
> > +	/**
> > +	 * @wait_vm_bookkeep: PT operations need to wait until VM is idle
> > +	 * (bookkeep dma-resv slots are idle) and stage all future VM activity
> > +	 * behind these operations (install PT operations into VM kernel
> > +	 * dma-resv slot).
> > +	 */
> > +	bool wait_vm_bookkeep;
> > +	/**
> > +	 * @wait_vm_kernel: PT operations need to wait until VM kernel dma-
> > resv
> > +	 * slots are idle.
> > +	 */
> > +	bool wait_vm_kernel;
> > +};
> > +
> >  #endif
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index 72e9bdab79d5..47658465b735 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -413,7 +413,7 @@ int __xe_vm_userptr_needs_repin(struct xe_vm *vm)
> > 
> >  #define XE_VM_REBIND_RETRY_TIMEOUT_MS 1000
> > 
> > -static void xe_vm_kill(struct xe_vm *vm, bool unlocked)
> > +void xe_vm_kill(struct xe_vm *vm, bool unlocked)
> >  {
> >  	struct xe_exec_queue *q;
> > 
> > @@ -577,13 +577,9 @@ static void preempt_rebind_work_func(struct
> > work_struct *w)
> >  		err = PTR_ERR(rebind_fence);
> >  		goto out_unlock;
> >  	}
> > +	dma_fence_put(rebind_fence);
> > 
> > -	if (rebind_fence) {
> > -		dma_fence_wait(rebind_fence, false);
> > -		dma_fence_put(rebind_fence);
> > -	}
> > -
> > -	/* Wait on munmap style VM unbinds */
> > +	/* Wait on rebinds */
> >  	wait = dma_resv_wait_timeout(xe_vm_resv(vm),
> >  				     DMA_RESV_USAGE_KERNEL,
> >  				     false, MAX_SCHEDULE_TIMEOUT);
> > @@ -759,11 +755,35 @@ int xe_vm_userptr_check_repin(struct xe_vm *vm)
> >   * xe_vm_populate_dummy_rebind() - Populate dummy rebind VMA ops
> >   * @vm: The VM.
> >   * @vma: VMA to populate dummy VMA ops
> > + * @tile_mask: tile mask for VMA ops
> >   *
> >   * Populate dummy VMA ops which can be used to issue a rebind for the VMA
> >   */
> > -void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma)
> > +void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma,
> > +				 u8 tile_mask)
> >  {
> > +	int i;
> > +
> > +	for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) {
> > +		if (BIT(i) & tile_mask) {
> > +			struct xe_vm_pgtable_update_op *pt_op =
> > +				vm->dummy_ops.vops.pt_update_ops[i].ops;
> > +
> > +			memset(&vm->dummy_ops.vops.pt_update_ops[i], 0,
> > +			       sizeof(vm->dummy_ops.vops.pt_update_ops[i]));
> > +			vm->dummy_ops.vops.pt_update_ops[i].ops = pt_op;
> > +			vm->dummy_ops.vops.pt_update_ops[i].num_ops = 1;
> > +
> > +			/*
> > +			 * Wait for VM to be idle / schedule execs + resume
> > +			 * behind rebinds
> > +			 */
> > +			vm-
> > >dummy_ops.vops.pt_update_ops[i].wait_vm_bookkeep =
> > +				true;
> > +		} else {
> > +			vm->dummy_ops.vops.pt_update_ops[i].num_ops = 0;
> > +		}
> > +	}
> >  	vm->dummy_ops.op.base.op = DRM_GPUVA_OP_MAP;
> >  	vm->dummy_ops.op.base.map.va.addr = vma->gpuva.va.addr;
> >  	vm->dummy_ops.op.base.map.va.range = vma->gpuva.va.range;
> > @@ -797,7 +817,7 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm,
> > bool rebind_worker)
> >  		else
> >  			trace_xe_vma_rebind_exec(vma);
> > 
> > -		xe_vm_populate_dummy_rebind(vm, vma);
> > +		xe_vm_populate_dummy_rebind(vm, vma, vma->tile_present);
> >  		fence = xe_vm_ops_execute(vm, &vm->dummy_ops.vops);
> >  		if (IS_ERR(fence))
> >  			return fence;
> > @@ -1653,7 +1673,6 @@ static void vm_destroy_work_func(struct work_struct
> > *w)
> >  		XE_WARN_ON(vm->pt_root[id]);
> > 
> >  	trace_xe_vm_free(vm);
> > -	dma_fence_put(vm->rebind_fence);
> >  	xe_vma_ops_fini(&vm->dummy_ops.vops);
> >  	kfree(vm);
> >  }
> > @@ -1691,147 +1710,6 @@ to_wait_exec_queue(struct xe_vm *vm, struct
> > xe_exec_queue *q)
> >  	return q ? q : vm->q[0];
> >  }
> > 
> > -static struct dma_fence *
> > -xe_vm_unbind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
> > -		 struct xe_sync_entry *syncs, u32 num_syncs,
> > -		 bool first_op, bool last_op)
> > -{
> > -	struct xe_vm *vm = xe_vma_vm(vma);
> > -	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > q);
> > -	struct xe_tile *tile;
> > -	struct dma_fence *fence = NULL;
> > -	struct dma_fence **fences = NULL;
> > -	struct dma_fence_array *cf = NULL;
> > -	int cur_fence = 0;
> > -	int number_tiles = hweight8(vma->tile_present);
> > -	int err;
> > -	u8 id;
> > -
> > -	trace_xe_vma_unbind(vma);
> > -
> > -	if (number_tiles > 1) {
> > -		fences = kmalloc_array(number_tiles, sizeof(*fences),
> > -				       GFP_KERNEL);
> > -		if (!fences)
> > -			return ERR_PTR(-ENOMEM);
> > -	}
> > -
> > -	for_each_tile(tile, vm->xe, id) {
> > -		if (!(vma->tile_present & BIT(id)))
> > -			goto next;
> > -
> > -		fence = __xe_pt_unbind_vma(tile, vma, q ? q : vm->q[id],
> > -					   first_op ? syncs : NULL,
> > -					   first_op ? num_syncs : 0);
> > -		if (IS_ERR(fence)) {
> > -			err = PTR_ERR(fence);
> > -			goto err_fences;
> > -		}
> > -
> > -		if (fences)
> > -			fences[cur_fence++] = fence;
> > -
> > -next:
> > -		if (q && vm->pt_root[id] && !list_empty(&q->multi_gt_list))
> > -			q = list_next_entry(q, multi_gt_list);
> > -	}
> > -
> > -	if (fences) {
> > -		cf = dma_fence_array_create(number_tiles, fences,
> > -					    vm->composite_fence_ctx,
> > -					    vm->composite_fence_seqno++,
> > -					    false);
> > -		if (!cf) {
> > -			--vm->composite_fence_seqno;
> > -			err = -ENOMEM;
> > -			goto err_fences;
> > -		}
> > -	}
> > -
> > -	fence = cf ? &cf->base : !fence ?
> > -		xe_exec_queue_last_fence_get(wait_exec_queue, vm) : fence;
> > -
> > -	return fence;
> > -
> > -err_fences:
> > -	if (fences) {
> > -		while (cur_fence)
> > -			dma_fence_put(fences[--cur_fence]);
> > -		kfree(fences);
> > -	}
> > -
> > -	return ERR_PTR(err);
> > -}
> > -
> > -static struct dma_fence *
> > -xe_vm_bind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
> > -	       struct xe_sync_entry *syncs, u32 num_syncs,
> > -	       u8 tile_mask, bool first_op, bool last_op)
> > -{
> > -	struct xe_tile *tile;
> > -	struct dma_fence *fence;
> > -	struct dma_fence **fences = NULL;
> > -	struct dma_fence_array *cf = NULL;
> > -	struct xe_vm *vm = xe_vma_vm(vma);
> > -	int cur_fence = 0;
> > -	int number_tiles = hweight8(vma->tile_mask);
> > -	int err;
> > -	u8 id;
> > -
> > -	trace_xe_vma_bind(vma);
> > -
> > -	if (number_tiles > 1) {
> > -		fences = kmalloc_array(number_tiles, sizeof(*fences),
> > -				       GFP_KERNEL);
> > -		if (!fences)
> > -			return ERR_PTR(-ENOMEM);
> > -	}
> > -
> > -	for_each_tile(tile, vm->xe, id) {
> > -		if (!(tile_mask & BIT(id)))
> > -			goto next;
> > -
> > -		fence = __xe_pt_bind_vma(tile, vma, q ? q : vm->q[id],
> > -					 first_op ? syncs : NULL,
> > -					 first_op ? num_syncs : 0,
> > -					 vma->tile_present & BIT(id));
> > -		if (IS_ERR(fence)) {
> > -			err = PTR_ERR(fence);
> > -			goto err_fences;
> > -		}
> > -
> > -		if (fences)
> > -			fences[cur_fence++] = fence;
> > -
> > -next:
> > -		if (q && vm->pt_root[id] && !list_empty(&q->multi_gt_list))
> > -			q = list_next_entry(q, multi_gt_list);
> > -	}
> > -
> > -	if (fences) {
> > -		cf = dma_fence_array_create(number_tiles, fences,
> > -					    vm->composite_fence_ctx,
> > -					    vm->composite_fence_seqno++,
> > -					    false);
> > -		if (!cf) {
> > -			--vm->composite_fence_seqno;
> > -			err = -ENOMEM;
> > -			goto err_fences;
> > -		}
> > -	}
> > -
> > -	return cf ? &cf->base : fence;
> > -
> > -err_fences:
> > -	if (fences) {
> > -		while (cur_fence)
> > -			dma_fence_put(fences[--cur_fence]);
> > -		kfree(fences);
> > -	}
> > -
> > -	return ERR_PTR(err);
> > -}
> > -
> >  static struct xe_user_fence *
> >  find_ufence_get(struct xe_sync_entry *syncs, u32 num_syncs)
> >  {
> > @@ -1847,47 +1725,6 @@ find_ufence_get(struct xe_sync_entry *syncs, u32
> > num_syncs)
> >  	return NULL;
> >  }
> > 
> > -static struct dma_fence *
> > -xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue *q,
> > -	   struct xe_bo *bo, struct xe_sync_entry *syncs, u32 num_syncs,
> > -	   u8 tile_mask, bool immediate, bool first_op, bool last_op)
> > -{
> > -	struct dma_fence *fence;
> > -	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > q);
> > -
> > -	xe_vm_assert_held(vm);
> > -	xe_bo_assert_held(bo);
> > -
> > -	if (immediate) {
> > -		fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, tile_mask,
> > -				       first_op, last_op);
> > -		if (IS_ERR(fence))
> > -			return fence;
> > -	} else {
> > -		xe_assert(vm->xe, xe_vm_in_fault_mode(vm));
> > -		fence = xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> > -	}
> > -
> > -	return fence;
> > -}
> > -
> > -static struct dma_fence *
> > -xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
> > -	     struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> > -	     u32 num_syncs, bool first_op, bool last_op)
> > -{
> > -	struct dma_fence *fence;
> > -
> > -	xe_vm_assert_held(vm);
> > -	xe_bo_assert_held(xe_vma_bo(vma));
> > -
> > -	fence = xe_vm_unbind_vma(vma, q, syncs, num_syncs, first_op,
> > last_op);
> > -	if (IS_ERR(fence))
> > -		return fence;
> > -
> > -	return fence;
> > -}
> > -
> >  #define ALL_DRM_XE_VM_CREATE_FLAGS
> > (DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE | \
> >  				    DRM_XE_VM_CREATE_FLAG_LR_MODE | \
> >  				    DRM_XE_VM_CREATE_FLAG_FAULT_MODE)
> > @@ -2028,21 +1865,6 @@ static const u32 region_to_mem_type[] = {
> >  	XE_PL_VRAM1,
> >  };
> > 
> > -static struct dma_fence *
> > -xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
> > -	       struct xe_exec_queue *q, struct xe_sync_entry *syncs,
> > -	       u32 num_syncs, bool first_op, bool last_op)
> > -{
> > -	struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm,
> > q);
> > -
> > -	if (vma->tile_mask != (vma->tile_present & ~vma->usm.tile_invalidated))
> > {
> > -		return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs,
> > num_syncs,
> > -				  vma->tile_mask, true, first_op, last_op);
> > -	} else {
> > -		return xe_exec_queue_last_fence_get(wait_exec_queue, vm);
> > -	}
> > -}
> > -
> >  static void prep_vma_destroy(struct xe_vm *vm, struct xe_vma *vma,
> >  			     bool post_commit)
> >  {
> > @@ -2334,7 +2156,6 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm,
> > struct xe_exec_queue *q,
> >  				   struct xe_vma_ops *vops, bool last)
> >  {
> >  	struct xe_device *xe = vm->xe;
> > -	struct xe_vma_op *last_op = NULL;
> >  	struct drm_gpuva_op *__op;
> >  	struct xe_tile *tile;
> >  	u8 id, tile_mask = 0;
> > @@ -2348,19 +2169,10 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> > *vm, struct xe_exec_queue *q,
> >  	drm_gpuva_for_each_op(__op, ops) {
> >  		struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
> >  		struct xe_vma *vma;
> > -		bool first = list_empty(&vops->list);
> >  		unsigned int flags = 0;
> > 
> >  		INIT_LIST_HEAD(&op->link);
> >  		list_add_tail(&op->link, &vops->list);
> > -
> > -		if (first) {
> > -			op->flags |= XE_VMA_OP_FIRST;
> > -			op->num_syncs = num_syncs;
> > -			op->syncs = syncs;
> > -		}
> > -
> > -		op->q = q;
> >  		op->tile_mask = tile_mask;
> > 
> >  		switch (op->base.op) {
> > @@ -2471,196 +2283,21 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm
> > *vm, struct xe_exec_queue *q,
> >  		}
> >  		case DRM_GPUVA_OP_UNMAP:
> >  		case DRM_GPUVA_OP_PREFETCH:
> > +			/* FIXME: Need to skip some prefetch ops */
> >  			xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask);
> >  			break;
> >  		default:
> >  			drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> >  		}
> > 
> > -		last_op = op;
> > -
> >  		err = xe_vma_op_commit(vm, op);
> >  		if (err)
> >  			return err;
> >  	}
> > 
> > -	/* FIXME: Unhandled corner case */
> > -	XE_WARN_ON(!last_op && last && !list_empty(&vops->list));
> > -
> > -	if (!last_op)
> > -		return 0;
> > -
> > -	if (last) {
> > -		last_op->flags |= XE_VMA_OP_LAST;
> > -		last_op->num_syncs = num_syncs;
> > -		last_op->syncs = syncs;
> > -	}
> > -
> >  	return 0;
> >  }
> > 
> > -static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > -				    struct xe_vma_op *op)
> > -{
> > -	struct dma_fence *fence = NULL;
> > -
> > -	lockdep_assert_held(&vm->lock);
> > -	xe_vm_assert_held(vm);
> > -	xe_bo_assert_held(xe_vma_bo(vma));
> > -
> > -	switch (op->base.op) {
> > -	case DRM_GPUVA_OP_MAP:
> > -		/* FIXME: Override vma->tile_mask for page faults */
> > -		fence = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
> > -				   op->syncs, op->num_syncs,
> > -				   op->map.immediate,
> > -				   op->tile_mask,
> > -				   op->flags & XE_VMA_OP_FIRST,
> > -				   op->flags & XE_VMA_OP_LAST);
> > -		break;
> > -	case DRM_GPUVA_OP_REMAP:
> > -	{
> > -		bool prev = !!op->remap.prev;
> > -		bool next = !!op->remap.next;
> > -
> > -		if (!op->remap.unmap_done) {
> > -			if (prev || next)
> > -				vma->gpuva.flags |= XE_VMA_FIRST_REBIND;
> > -			fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
> > -					     op->num_syncs,
> > -					     op->flags & XE_VMA_OP_FIRST,
> > -					     op->flags & XE_VMA_OP_LAST &&
> > -					     !prev && !next);
> > -			if (IS_ERR(fence))
> > -				break;
> > -			op->remap.unmap_done = true;
> > -		}
> > -
> > -		if (prev) {
> > -			op->remap.prev->gpuva.flags |= XE_VMA_LAST_REBIND;
> > -			dma_fence_put(fence);
> > -			fence = xe_vm_bind(vm, op->remap.prev, op->q,
> > -					   xe_vma_bo(op->remap.prev), op-
> > >syncs,
> > -					   op->num_syncs, op->remap.prev-
> > >tile_mask,
> > -					   true, false,
> > -					   op->flags & XE_VMA_OP_LAST
> > && !next);
> > -			op->remap.prev->gpuva.flags &=
> > ~XE_VMA_LAST_REBIND;
> > -			if (IS_ERR(fence))
> > -				break;
> > -			op->remap.prev = NULL;
> > -		}
> > -
> > -		if (next) {
> > -			op->remap.next->gpuva.flags |= XE_VMA_LAST_REBIND;
> > -			dma_fence_put(fence);
> > -			fence = xe_vm_bind(vm, op->remap.next, op->q,
> > -					   xe_vma_bo(op->remap.next),
> > -					   op->syncs, op->num_syncs,
> > -					   op->remap.next->tile_mask, true, false,
> > -					   op->flags & XE_VMA_OP_LAST);
> > -			op->remap.next->gpuva.flags &=
> > ~XE_VMA_LAST_REBIND;
> > -			if (IS_ERR(fence))
> > -				break;
> > -			op->remap.next = NULL;
> > -		}
> > -
> > -		break;
> > -	}
> > -	case DRM_GPUVA_OP_UNMAP:
> > -		fence = xe_vm_unbind(vm, vma, op->q, op->syncs,
> > -				     op->num_syncs, op->flags &
> > XE_VMA_OP_FIRST,
> > -				     op->flags & XE_VMA_OP_LAST);
> > -		break;
> > -	case DRM_GPUVA_OP_PREFETCH:
> > -		fence = xe_vm_prefetch(vm, vma, op->q, op->syncs, op-
> > >num_syncs,
> > -				       op->flags & XE_VMA_OP_FIRST,
> > -				       op->flags & XE_VMA_OP_LAST);
> > -		break;
> > -	default:
> > -		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > -	}
> > -
> > -	if (IS_ERR(fence))
> > -		trace_xe_vma_fail(vma);
> > -
> > -	return fence;
> > -}
> > -
> > -static struct dma_fence *
> > -__xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma,
> > -		    struct xe_vma_op *op)
> > -{
> > -	struct dma_fence *fence;
> > -	int err;
> > -
> > -retry_userptr:
> > -	fence = op_execute(vm, vma, op);
> > -	if (IS_ERR(fence) && PTR_ERR(fence) == -EAGAIN) {
> > -		lockdep_assert_held(&vm->lock);
> > -
> > -		if (op->base.op == DRM_GPUVA_OP_REMAP) {
> > -			if (!op->remap.unmap_done)
> > -				vma = gpuva_to_vma(op->base.remap.unmap-
> > >va);
> > -			else if (op->remap.prev)
> > -				vma = op->remap.prev;
> > -			else
> > -				vma = op->remap.next;
> > -		}
> > -
> > -		if (xe_vma_is_userptr(vma)) {
> > -			err = xe_vma_userptr_pin_pages(to_userptr_vma(vma));
> > -			if (!err)
> > -				goto retry_userptr;
> > -
> > -			fence = ERR_PTR(err);
> > -			trace_xe_vma_fail(vma);
> > -		}
> > -	}
> > -
> > -	return fence;
> > -}
> > -
> > -static struct dma_fence *
> > -xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
> > -{
> > -	struct dma_fence *fence = ERR_PTR(-ENOMEM);
> > -
> > -	lockdep_assert_held(&vm->lock);
> > -
> > -	switch (op->base.op) {
> > -	case DRM_GPUVA_OP_MAP:
> > -		fence = __xe_vma_op_execute(vm, op->map.vma, op);
> > -		break;
> > -	case DRM_GPUVA_OP_REMAP:
> > -	{
> > -		struct xe_vma *vma;
> > -
> > -		if (!op->remap.unmap_done)
> > -			vma = gpuva_to_vma(op->base.remap.unmap->va);
> > -		else if (op->remap.prev)
> > -			vma = op->remap.prev;
> > -		else
> > -			vma = op->remap.next;
> > -
> > -		fence = __xe_vma_op_execute(vm, vma, op);
> > -		break;
> > -	}
> > -	case DRM_GPUVA_OP_UNMAP:
> > -		fence = __xe_vma_op_execute(vm, gpuva_to_vma(op-
> > >base.unmap.va),
> > -					    op);
> > -		break;
> > -	case DRM_GPUVA_OP_PREFETCH:
> > -		fence = __xe_vma_op_execute(vm,
> > -					    gpuva_to_vma(op->base.prefetch.va),
> > -					    op);
> > -		break;
> > -	default:
> > -		drm_warn(&vm->xe->drm, "NOT POSSIBLE");
> > -	}
> > -
> > -	return fence;
> > -}
> > -
> >  static void xe_vma_op_unwind(struct xe_vm *vm, struct xe_vma_op *op,
> >  			     bool post_commit, bool prev_post_commit,
> >  			     bool next_post_commit)
> > @@ -2837,6 +2474,32 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec
> > *exec,
> >  	return 0;
> >  }
> > 
> > +static int vm_ops_setup_tile_args(struct xe_vm *vm, struct xe_vma_ops *vops)
> > +{
> > +	struct xe_exec_queue *q = vops->q;
> > +	struct xe_tile *tile;
> > +	int number_tiles = 0;
> > +	u8 id;
> > +
> > +	for_each_tile(tile, vm->xe, id) {
> > +		if (vops->pt_update_ops[id].num_ops)
> > +			++number_tiles;
> > +
> > +		if (vops->pt_update_ops[id].q)
> > +			continue;
> > +
> > +		if (q) {
> > +			vops->pt_update_ops[id].q = q;
> > +			if (vm->pt_root[id] && !list_empty(&q->multi_gt_list))
> > +				q = list_next_entry(q, multi_gt_list);
> > +		} else {
> > +			vops->pt_update_ops[id].q = vm->q[id];
> > +		}
> > +	}
> > +
> > +	return number_tiles;
> > +}
> > +
> >  /**
> >   * xe_vm_ops_execute() - Execute VMA ops
> >   * @vm: The VM.
> > @@ -2848,21 +2511,81 @@ static int vm_bind_ioctl_ops_lock(struct drm_exec
> > *exec,
> >   */
> >  struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops
> > *vops)
> >  {
> > -	struct xe_vma_op *op, *next;
> > +	struct xe_tile *tile;
> >  	struct dma_fence *fence = NULL;
> > +	struct dma_fence **fences = NULL;
> > +	struct dma_fence_array *cf = NULL;
> > +	int number_tiles = 0, current_fence = 0, err;
> > +	u8 id;
> > +
> > +	number_tiles = vm_ops_setup_tile_args(vm, vops);
> > +	if (number_tiles == 0)
> > +		return ERR_PTR(-ENODATA);
> > +
> > +	if (number_tiles > 1) {
> > +		fences = kmalloc_array(number_tiles, sizeof(*fences),
> > +				       GFP_KERNEL);
> > +		if (!fences)
> > +			return ERR_PTR(-ENOMEM);
> > +	}
> > +
> > +	for_each_tile(tile, vm->xe, id) {
> > +		if (!vops->pt_update_ops[id].num_ops)
> > +			continue;
> > 
> > -	list_for_each_entry_safe(op, next, &vops->list, link) {
> > -		if (!IS_ERR(fence)) {
> > -			dma_fence_put(fence);
> > -			fence = xe_vma_op_execute(vm, op);
> > +		err = xe_pt_update_ops_prepare(tile, vops);
> > +		if (err) {
> > +			fence = ERR_PTR(err);
> > +			goto err_out;
> >  		}
> > -		if (IS_ERR(fence)) {
> > -			drm_warn(&vm->xe->drm, "VM op(%d) failed with %ld",
> > -				 op->base.op, PTR_ERR(fence));
> > -			fence = ERR_PTR(-ENOSPC);
> > +	}
> > +
> > +	for_each_tile(tile, vm->xe, id) {
> > +		if (!vops->pt_update_ops[id].num_ops)
> > +			continue;
> > +
> > +		fence = xe_pt_update_ops_run(tile, vops);
> > +		if (IS_ERR(fence))
> > +			goto err_out;
> > +
> > +		if (fences)
> > +			fences[current_fence++] = fence;
> > +	}
> > +
> > +	if (fences) {
> > +		cf = dma_fence_array_create(number_tiles, fences,
> > +					    vm->composite_fence_ctx,
> > +					    vm->composite_fence_seqno++,
> > +					    false);
> > +		if (!cf) {
> > +			--vm->composite_fence_seqno;
> > +			fence = ERR_PTR(-ENOMEM);
> > +			goto err_out;
> >  		}
> > +		fence = &cf->base;
> > +	}
> > +
> > +	for_each_tile(tile, vm->xe, id) {
> > +		if (!vops->pt_update_ops[id].num_ops)
> > +			continue;
> > +
> > +		xe_pt_update_ops_fini(tile, vops);
> >  	}
> > 
> > +	return fence;
> > +
> > +err_out:
> > +	for_each_tile(tile, vm->xe, id) {
> > +		if (!vops->pt_update_ops[id].num_ops)
> > +			continue;
> > +
> > +		xe_pt_update_ops_abort(tile, vops);
> > +	}
> > +	while (current_fence)
> > +		dma_fence_put(fences[--current_fence]);
> > +	kfree(fences);
> > +	kfree(cf);
> > +
> >  	return fence;
> >  }
> > 
> > @@ -2944,12 +2667,10 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm
> > *vm,
> >  		fence = xe_vm_ops_execute(vm, vops);
> >  		if (IS_ERR(fence)) {
> >  			err = PTR_ERR(fence);
> > -			/* FIXME: Killing VM rather than proper error handling */
> > -			xe_vm_kill(vm, false);
> >  			goto unlock;
> > -		} else {
> > -			vm_bind_ioctl_ops_install_fences(vm, vops, fence);
> >  		}
> > +
> > +		vm_bind_ioctl_ops_install_fences(vm, vops, fence);
> >  	}
> > 
> >  unlock:
> > diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
> > index b40160b1be01..8201ecb8f05a 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.h
> > +++ b/drivers/gpu/drm/xe/xe_vm.h
> > @@ -262,9 +262,12 @@ static inline struct dma_resv *xe_vm_resv(struct xe_vm
> > *vm)
> >   */
> >  #define xe_vm_assert_held(vm) dma_resv_assert_held(xe_vm_resv(vm))
> > 
> > -void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma);
> > +void xe_vm_populate_dummy_rebind(struct xe_vm *vm, struct xe_vma *vma,
> > +				 u8 tile_mask);
> >  struct dma_fence *xe_vm_ops_execute(struct xe_vm *vm, struct xe_vma_ops
> > *vops);
> > 
> > +void xe_vm_kill(struct xe_vm *vm, bool unlocked);
> > +
> >  #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_VM)
> >  #define vm_dbg drm_dbg
> >  #else
> > diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> > b/drivers/gpu/drm/xe/xe_vm_types.h
> > index f5d740dcbba3..83cb13275904 100644
> > --- a/drivers/gpu/drm/xe/xe_vm_types.h
> > +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> > @@ -166,29 +166,18 @@ struct xe_vma_op_prefetch {
> > 
> >  /** enum xe_vma_op_flags - flags for VMA operation */
> >  enum xe_vma_op_flags {
> > -	/** @XE_VMA_OP_FIRST: first VMA operation for a set of syncs */
> > -	XE_VMA_OP_FIRST			= BIT(0),
> > -	/** @XE_VMA_OP_LAST: last VMA operation for a set of syncs */
> > -	XE_VMA_OP_LAST			= BIT(1),
> >  	/** @XE_VMA_OP_COMMITTED: VMA operation committed */
> > -	XE_VMA_OP_COMMITTED		= BIT(2),
> > +	XE_VMA_OP_COMMITTED		= BIT(0),
> >  	/** @XE_VMA_OP_PREV_COMMITTED: Previous VMA operation
> > committed */
> > -	XE_VMA_OP_PREV_COMMITTED	= BIT(3),
> > +	XE_VMA_OP_PREV_COMMITTED	= BIT(1),
> >  	/** @XE_VMA_OP_NEXT_COMMITTED: Next VMA operation committed
> > */
> > -	XE_VMA_OP_NEXT_COMMITTED	= BIT(4),
> > +	XE_VMA_OP_NEXT_COMMITTED	= BIT(2),
> >  };
> > 
> >  /** struct xe_vma_op - VMA operation */
> >  struct xe_vma_op {
> >  	/** @base: GPUVA base operation */
> >  	struct drm_gpuva_op base;
> > -	/** @q: exec queue for this operation */
> > -	struct xe_exec_queue *q;
> > -	/**
> > -	 * @syncs: syncs for this operation, only used on first and last
> > -	 * operation
> > -	 */
> > -	struct xe_sync_entry *syncs;
> >  	/** @num_syncs: number of syncs */
> >  	u32 num_syncs;
> >  	/** @link: async operation link */
> > @@ -214,19 +203,14 @@ struct xe_vma_ops {
> >  	struct list_head list;
> >  	/** @vm: VM */
> >  	struct xe_vm *vm;
> > -	/** @q: exec queue these operations */
> > +	/** @q: exec queue for VMA operations */
> >  	struct xe_exec_queue *q;
> >  	/** @syncs: syncs these operation */
> >  	struct xe_sync_entry *syncs;
> >  	/** @num_syncs: number of syncs */
> >  	u32 num_syncs;
> >  	/** @pt_update_ops: page table update operations */
> > -	struct {
> > -		/** @ops: operations */
> > -		struct xe_vm_pgtable_update_op *ops;
> > -		/** @num_ops: number of operations */
> > -		u32 num_ops;
> > -	} pt_update_ops[XE_MAX_TILES_PER_DEVICE];
> > +	struct xe_vm_pgtable_update_ops
> > pt_update_ops[XE_MAX_TILES_PER_DEVICE];
> >  };
> > 
> >  struct xe_vm {
> > @@ -283,9 +267,6 @@ struct xe_vm {
> >  	 */
> >  	struct list_head rebind_list;
> > 
> > -	/** @rebind_fence: rebind fence from execbuf */
> > -	struct dma_fence *rebind_fence;
> > -
> >  	/**
> >  	 * @destroy_work: worker to destroy VM, needed as a dma_fence
> > signaling
> >  	 * from an irq context can be last put and the destroy needs to be able
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

end of thread, other threads:[~2024-03-27 19:28 UTC | newest]

Thread overview: 76+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-08  5:07 [PATCH v4 00/30] Refactor VM bind code Matthew Brost
2024-03-08  5:07 ` [PATCH v4 01/30] drm/xe: Lock all gpuva ops during VM bind IOCTL Matthew Brost
2024-03-10 17:44   ` Zeng, Oak
2024-03-11 19:48     ` Matthew Brost
2024-03-11 22:02       ` Zeng, Oak
2024-03-12  1:29         ` Matthew Brost
2024-03-08  5:07 ` [PATCH v4 02/30] drm/xe: Add ops_execute function which returns a fence Matthew Brost
2024-03-22 16:11   ` Zeng, Oak
2024-03-22 17:31     ` Matthew Brost
2024-03-22 19:39       ` Zeng, Oak
2024-03-08  5:07 ` [PATCH v4 03/30] drm/xe: Move migrate to prefetch to op_lock function Matthew Brost
2024-03-22 17:06   ` Zeng, Oak
2024-03-22 17:36     ` Matthew Brost
2024-03-22 19:45       ` Zeng, Oak
2024-03-08  5:07 ` [PATCH v4 04/30] drm/xe: Add struct xe_vma_ops abstraction Matthew Brost
2024-03-22 17:13   ` Zeng, Oak
2024-03-08  5:07 ` [PATCH v4 05/30] drm/xe: Update xe_vm_rebind to use dummy VMA operations Matthew Brost
2024-03-22 21:23   ` Zeng, Oak
2024-03-22 22:51     ` Matthew Brost
2024-03-08  5:07 ` [PATCH v4 06/30] drm/xe: Simplify VM bind IOCTL error handling and cleanup Matthew Brost
2024-03-25 16:03   ` Zeng, Oak
2024-03-26 18:46     ` Matthew Brost
2024-03-08  5:07 ` [PATCH v4 07/30] drm/xe: Update pagefaults to use dummy VMA operations Matthew Brost
2024-03-08  5:07 ` [PATCH v4 08/30] drm/xe: s/xe_tile_migrate_engine/xe_tile_migrate_exec_queue Matthew Brost
2024-03-25 16:05   ` Zeng, Oak
2024-03-08  5:07 ` [PATCH v4 09/30] drm/xe: Add some members to xe_vma_ops Matthew Brost
2024-03-25 16:10   ` Zeng, Oak
2024-03-26 18:47     ` Matthew Brost
2024-03-08  5:07 ` [PATCH v4 10/30] drm/xe: Add vm_bind_ioctl_ops_install_fences helper Matthew Brost
2024-03-25 16:51   ` Zeng, Oak
2024-03-25 19:34     ` Matthew Brost
2024-03-25 19:44       ` Zeng, Oak
2024-03-08  5:07 ` [PATCH v4 11/30] drm/xe: Move setting last fence to vm_bind_ioctl_ops_install_fences Matthew Brost
2024-03-25 17:02   ` Zeng, Oak
2024-03-25 19:35     ` Matthew Brost
2024-03-08  5:07 ` [PATCH v4 12/30] drm/xe: Move ufence check to op_lock Matthew Brost
2024-03-25 20:37   ` Zeng, Oak
2024-03-26 18:49     ` Matthew Brost
2024-03-08  5:07 ` [PATCH v4 13/30] drm/xe: Move ufence add to vm_bind_ioctl_ops_install_fences Matthew Brost
2024-03-25 20:54   ` Zeng, Oak
2024-03-26 18:54     ` Matthew Brost
2024-03-26 20:59       ` Zeng, Oak
2024-03-08  5:07 ` [PATCH v4 14/30] drm/xe: Add xe_gt_tlb_invalidation_range and convert PT layer to use this Matthew Brost
2024-03-25 21:35   ` Zeng, Oak
2024-03-26 18:57     ` Matthew Brost
2024-03-08  5:07 ` [PATCH v4 15/30] drm/xe: Add xe_vm_pgtable_update_op to xe_vma_ops Matthew Brost
2024-03-25 21:58   ` Zeng, Oak
2024-03-26 19:05     ` Matthew Brost
2024-03-27  1:29       ` Zeng, Oak
2024-03-08  5:07 ` [PATCH v4 16/30] drm/xe: Use ordered WQ for TLB invalidation fences Matthew Brost
2024-03-25 22:30   ` Zeng, Oak
2024-03-26 19:10     ` Matthew Brost
2024-03-08  5:07 ` [PATCH v4 17/30] drm/xe: Delete PT update selftest Matthew Brost
2024-03-25 22:31   ` Zeng, Oak
2024-03-08  5:07 ` [PATCH v4 18/30] drm/xe: Convert multiple bind ops into single job Matthew Brost
2024-03-27  2:40   ` Zeng, Oak
2024-03-27 19:26     ` Matthew Brost
2024-03-08  5:07 ` [PATCH v4 19/30] drm/xe: Remove old functions defs in xe_pt.h Matthew Brost
2024-03-08  5:07 ` [PATCH v4 20/30] drm/xe: Update PT layer with better error handling Matthew Brost
2024-03-08  5:07 ` [PATCH v4 21/30] drm/xe: Update xe_vm_rebind to return int Matthew Brost
2024-03-08  5:07 ` [PATCH v4 22/30] drm/xe: Move vma rebinding to the drm_exec locking loop Matthew Brost
2024-03-08  5:07 ` [PATCH v4 23/30] drm/xe: Update VM trace events Matthew Brost
2024-03-08  5:08 ` [PATCH v4 24/30] drm/xe: Update clear / populate arguments Matthew Brost
2024-03-08  5:08 ` [PATCH v4 25/30] drm/xe: Add __xe_migrate_update_pgtables_cpu helper Matthew Brost
2024-03-08  5:08 ` [PATCH v4 26/30] drm/xe: CPU binds for jobs Matthew Brost
2024-03-08  5:08 ` [PATCH v4 27/30] drm/xe: Don't use migrate exec queue for page fault binds Matthew Brost
2024-03-08  5:08 ` [PATCH v4 28/30] drm/xe: Add VM bind IOCTL error injection Matthew Brost
2024-03-08  5:08 ` [PATCH v4 29/30] drm/xe/guc: Assert time'd out jobs are not from a VM exec queue Matthew Brost
2024-03-08  5:08 ` [PATCH v4 30/30] drm/xe: Add PT exec queues Matthew Brost
2024-03-08  5:42 ` ✓ CI.Patch_applied: success for Refactor VM bind code (rev5) Patchwork
2024-03-08  5:43 ` ✗ CI.checkpatch: warning " Patchwork
2024-03-08  5:44 ` ✓ CI.KUnit: success " Patchwork
2024-03-08  5:55 ` ✓ CI.Build: " Patchwork
2024-03-08  5:55 ` ✗ CI.Hooks: failure " Patchwork
2024-03-08  5:56 ` ✓ CI.checksparse: success " Patchwork
2024-03-08  6:26 ` ✗ CI.BAT: failure " Patchwork

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.