--- /dev/null
+From stable+bounces-294399-greg=kroah.com@vger.kernel.org Sat Aug 1 18:59:22 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Aug 2026 12:59:12 -0400
+Subject: drm/exec: Remove the index parameter from drm_exec_for_each_locked_obj[_reverse]
+To: stable@vger.kernel.org
+Cc: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>, "Christian König" <christian.koenig@amd.com>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260801165915.2408629-1-sashal@kernel.org>
+
+From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+
+[ Upstream commit ce44b78512e9102aea54ff6b6e521d6c8de9f31c ]
+
+Nobody makes any use of it. Possible internal future users can
+instead use the _index variable. External users shouldn't use
+it since the array it's pointing into is internal drm_exec state.
+
+v2:
+- Use a unique id for the loop variable (Christian)
+
+Assisted-by: GitHub Copilot:claude-sonnet-4.6
+Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Link: https://patch.msgid.link/20260520101616.41284-2-thomas.hellstrom@linux.intel.com
+Stable-dep-of: af80e2bfde93 ("drm/xe: Wait on external BO kernel fences in exec IOCTL")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 9 +++------
+ drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c | 3 +--
+ drivers/gpu/drm/drm_exec.c | 6 ++----
+ drivers/gpu/drm/drm_gpuvm.c | 3 +--
+ drivers/gpu/drm/xe/xe_vm.c | 3 +--
+ include/drm/drm_exec.h | 20 ++++++++++++--------
+ 6 files changed, 20 insertions(+), 24 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+@@ -864,7 +864,6 @@ static int amdgpu_cs_parser_bos(struct a
+ struct amdgpu_vm *vm = &fpriv->vm;
+ struct amdgpu_bo_list_entry *e;
+ struct drm_gem_object *obj;
+- unsigned long index;
+ unsigned int i;
+ int r;
+
+@@ -969,7 +968,7 @@ static int amdgpu_cs_parser_bos(struct a
+ goto out_free_user_pages;
+ }
+
+- drm_exec_for_each_locked_object(&p->exec, index, obj) {
++ drm_exec_for_each_locked_object(&p->exec, obj) {
+ r = amdgpu_cs_bo_validate(p, gem_to_amdgpu_bo(obj));
+ if (unlikely(r))
+ goto out_free_user_pages;
+@@ -1196,7 +1195,6 @@ static int amdgpu_cs_sync_rings(struct a
+ struct drm_gpu_scheduler *sched;
+ struct drm_gem_object *obj;
+ struct dma_fence *fence;
+- unsigned long index;
+ unsigned int i;
+ int r;
+
+@@ -1207,7 +1205,7 @@ static int amdgpu_cs_sync_rings(struct a
+ return r;
+ }
+
+- drm_exec_for_each_locked_object(&p->exec, index, obj) {
++ drm_exec_for_each_locked_object(&p->exec, obj) {
+ struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+
+ struct dma_resv *resv = bo->tbo.base.resv;
+@@ -1276,7 +1274,6 @@ static int amdgpu_cs_submit(struct amdgp
+ struct amdgpu_vm *vm = &fpriv->vm;
+ struct amdgpu_bo_list_entry *e;
+ struct drm_gem_object *gobj;
+- unsigned long index;
+ unsigned int i;
+ uint64_t seq;
+ int r;
+@@ -1327,7 +1324,7 @@ static int amdgpu_cs_submit(struct amdgp
+ }
+
+ p->fence = dma_fence_get(&leader->base.s_fence->finished);
+- drm_exec_for_each_locked_object(&p->exec, index, gobj) {
++ drm_exec_for_each_locked_object(&p->exec, gobj) {
+
+ ttm_bo_move_to_lru_tail_unlocked(&gem_to_amdgpu_bo(gobj)->tbo);
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c
+@@ -49,7 +49,6 @@ amdgpu_eviction_fence_replace_fence(stru
+ {
+ struct amdgpu_eviction_fence *old_ef, *new_ef;
+ struct drm_gem_object *obj;
+- unsigned long index;
+ int ret;
+
+ if (evf_mgr->ev_fence &&
+@@ -77,7 +76,7 @@ amdgpu_eviction_fence_replace_fence(stru
+ spin_unlock(&evf_mgr->ev_fence_lock);
+
+ /* Attach the new fence */
+- drm_exec_for_each_locked_object(exec, index, obj) {
++ drm_exec_for_each_locked_object(exec, obj) {
+ struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+
+ if (!bo)
+--- a/drivers/gpu/drm/drm_exec.c
++++ b/drivers/gpu/drm/drm_exec.c
+@@ -24,7 +24,6 @@
+ *
+ * struct drm_gem_object *obj;
+ * struct drm_exec exec;
+- * unsigned long index;
+ * int ret;
+ *
+ * drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT);
+@@ -40,7 +39,7 @@
+ * goto error;
+ * }
+ *
+- * drm_exec_for_each_locked_object(&exec, index, obj) {
++ * drm_exec_for_each_locked_object(&exec, obj) {
+ * dma_resv_add_fence(obj->resv, fence, DMA_RESV_USAGE_READ);
+ * ...
+ * }
+@@ -56,9 +55,8 @@
+ static void drm_exec_unlock_all(struct drm_exec *exec)
+ {
+ struct drm_gem_object *obj;
+- unsigned long index;
+
+- drm_exec_for_each_locked_object_reverse(exec, index, obj) {
++ drm_exec_for_each_locked_object_reverse(exec, obj) {
+ dma_resv_unlock(obj->resv);
+ drm_gem_object_put(obj);
+ }
+--- a/drivers/gpu/drm/drm_gpuvm.c
++++ b/drivers/gpu/drm/drm_gpuvm.c
+@@ -1521,9 +1521,8 @@ drm_gpuvm_resv_add_fence(struct drm_gpuv
+ enum dma_resv_usage extobj_usage)
+ {
+ struct drm_gem_object *obj;
+- unsigned long index;
+
+- drm_exec_for_each_locked_object(exec, index, obj) {
++ drm_exec_for_each_locked_object(exec, obj) {
+ dma_resv_assert_held(obj->resv);
+ dma_resv_add_fence(obj->resv, fence,
+ drm_gpuvm_is_extobj(gpuvm, obj) ?
+--- a/drivers/gpu/drm/xe/xe_vm.c
++++ b/drivers/gpu/drm/xe/xe_vm.c
+@@ -355,7 +355,6 @@ int xe_vm_validate_rebind(struct xe_vm *
+ unsigned int num_fences)
+ {
+ struct drm_gem_object *obj;
+- unsigned long index;
+ int ret;
+
+ do {
+@@ -368,7 +367,7 @@ int xe_vm_validate_rebind(struct xe_vm *
+ return ret;
+ } while (!list_empty(&vm->gpuvm.evict.list));
+
+- drm_exec_for_each_locked_object(exec, index, obj) {
++ drm_exec_for_each_locked_object(exec, obj) {
+ ret = dma_resv_reserve_fences(obj->resv, num_fences);
+ if (ret)
+ return ret;
+--- a/include/drm/drm_exec.h
++++ b/include/drm/drm_exec.h
+@@ -65,31 +65,35 @@ drm_exec_obj(struct drm_exec *exec, unsi
+ return index < exec->num_objects ? exec->objects[index] : NULL;
+ }
+
++/* Helper for drm_exec_for_each_locked_object(). Internal use only. */
++#define __drm_exec_for_each_locked_object(exec, obj, __index) \
++ for (unsigned long __index = 0; ((obj) = drm_exec_obj(exec, __index)); ++__index)
+ /**
+ * drm_exec_for_each_locked_object - iterate over all the locked objects
+ * @exec: drm_exec object
+- * @index: unsigned long index for the iteration
+ * @obj: the current GEM object
+ *
+ * Iterate over all the locked GEM objects inside the drm_exec object.
+ */
+-#define drm_exec_for_each_locked_object(exec, index, obj) \
+- for ((index) = 0; ((obj) = drm_exec_obj(exec, index)); ++(index))
++#define drm_exec_for_each_locked_object(exec, obj) \
++ __drm_exec_for_each_locked_object(exec, obj, __UNIQUE_ID(drm_exec))
+
++/* Helper for drm_exec_for_each_locked_object_reverse(). Internal use only. */
++#define __drm_exec_for_each_locked_object_reverse(exec, obj, __index) \
++ for (unsigned long __index = (exec)->num_objects - 1; \
++ ((obj) = drm_exec_obj(exec, __index)); --__index)
+ /**
+ * drm_exec_for_each_locked_object_reverse - iterate over all the locked
+ * objects in reverse locking order
+ * @exec: drm_exec object
+- * @index: unsigned long index for the iteration
+ * @obj: the current GEM object
+ *
+ * Iterate over all the locked GEM objects inside the drm_exec object in
+- * reverse locking order. Note that @index may go below zero and wrap,
++ * reverse locking order. Note that the internal index may wrap around,
+ * but that will be caught by drm_exec_obj(), returning a NULL object.
+ */
+-#define drm_exec_for_each_locked_object_reverse(exec, index, obj) \
+- for ((index) = (exec)->num_objects - 1; \
+- ((obj) = drm_exec_obj(exec, index)); --(index))
++#define drm_exec_for_each_locked_object_reverse(exec, obj) \
++ __drm_exec_for_each_locked_object_reverse(exec, obj, __UNIQUE_ID(drm_exec))
+
+ /**
+ * drm_exec_until_all_locked - loop until all GEM objects are locked
--- /dev/null
+From stable+bounces-294400-greg=kroah.com@vger.kernel.org Sat Aug 1 18:59:38 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Aug 2026 12:59:13 -0400
+Subject: drm/xe: Wait on external BO kernel fences in exec IOCTL
+To: stable@vger.kernel.org
+Cc: "Matthew Brost" <matthew.brost@intel.com>, "Matthew Auld" <matthew.auld@intel.com>, "Thomas Hellström" <thomas.hellstrom@linux.intel.com>
+Message-ID: <20260801165915.2408629-2-sashal@kernel.org>
+
+From: Matthew Brost <matthew.brost@intel.com>
+
+[ Upstream commit af80e2bfde9312c76b60cf9274248dce0410b30d ]
+
+Before arming a user job, xe_exec_ioctl() only added the VM's
+dma-resv KERNEL slot as a dependency. That slot covers rebinds and
+the kernel operations of the VM's private BOs, but not external BOs
+(bo->vm == NULL), which carry their kernel operations (evictions,
+moves, ...) in their own dma-resv KERNEL slot.
+
+The DMA_RESV_USAGE_KERNEL slot is the cross-driver contract for
+memory management operations that must complete before the BO or its
+backing store may be used: any accessor is required to wait on the
+KERNEL fences before touching the resv. By skipping the external BOs'
+KERNEL slots, the exec path violated that contract and could schedule
+a user job while a kernel operation on an external BO mapped by the VM
+was still in flight, racing against it and potentially reading or
+writing memory that was being moved.
+
+Replace the VM-only dependency with an iteration over every object
+locked by the exec, adding each object's KERNEL slot as a job
+dependency. This covers the VM resv (rebinds and private BOs) as well
+as every external BO, mirroring the drm_gpuvm_resv_add_fence() call
+that later publishes the job fence to the same set of objects.
+Long-running mode continues to skip this, as before.
+
+Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
+Cc: stable@vger.kernel.org
+Assisted-by: GitHub_Copilot:claude-opus-4.8
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Matthew Auld <matthew.auld@intel.com>
+Link: https://patch.msgid.link/20260702215805.4011228-1-matthew.brost@intel.com
+(cherry picked from commit a6b842acf3ddd1efc53a56de9260cfa718fb35e7)
+Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Signed-off-by: Review <review@local>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/xe/xe_exec.c | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+--- a/drivers/gpu/drm/xe/xe_exec.c
++++ b/drivers/gpu/drm/xe/xe_exec.c
+@@ -286,13 +286,23 @@ retry:
+ goto err_exec;
+ }
+
+- /* Wait behind rebinds */
++ /*
++ * Wait behind rebinds and any kernel operations (evictions, defrag
++ * moves, ...) on the VM and all external BOs. The VM's private BOs
++ * carry their kernel ops in the VM dma-resv KERNEL slot, while each
++ * external BO carries them in its own dma-resv KERNEL slot; both are
++ * covered by iterating every object locked by the exec, mirroring the
++ * drm_gpuvm_resv_add_fence() below.
++ */
+ if (!xe_vm_in_lr_mode(vm)) {
+- err = xe_sched_job_add_deps(job,
+- xe_vm_resv(vm),
+- DMA_RESV_USAGE_KERNEL);
+- if (err)
+- goto err_put_job;
++ struct drm_gem_object *obj;
++
++ drm_exec_for_each_locked_object(exec, obj) {
++ err = xe_sched_job_add_deps(job, obj->resv,
++ DMA_RESV_USAGE_KERNEL);
++ if (err)
++ goto err_put_job;
++ }
+ }
+
+ for (i = 0; i < num_syncs && !err; i++)