Skip to content

Commit 7ac7461

Browse files
mbrost05Lucas De Marchi
authored andcommitted
drm/xe: Don't allow evicting of BOs in same VM in array of VM binds
An array of VM binds can potentially evict other buffer objects (BOs) within the same VM under certain conditions, which may lead to NULL pointer dereferences later in the bind pipeline. To prevent this, clear the allow_res_evict flag in the xe_bo_validate call. v2: - Invert polarity of no_res_evict (Thomas) - Add comment in code explaining issue (Thomas) Cc: stable@vger.kernel.org Reported-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/6268 Fixes: 774b5fa ("drm/xe: Avoid evicting object of the same vm in none fault mode") Fixes: 77f2ef3 ("drm/xe: Lock all gpuva ops during VM bind IOCTL") Fixes: dd08ebf ("drm/xe: Introduce a new DRM driver for Intel GPUs") Signed-off-by: Matthew Brost <matthew.brost@intel.com> Tested-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com> Link: https://lore.kernel.org/r/20251009110618.3481870-1-matthew.brost@intel.com (cherry picked from commit 8b9ba8d) Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
1 parent e5ae8d1 commit 7ac7461

2 files changed

Lines changed: 24 additions & 9 deletions

File tree

drivers/gpu/drm/xe/xe_vm.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2832,7 +2832,7 @@ static void vm_bind_ioctl_ops_unwind(struct xe_vm *vm,
28322832
}
28332833

28342834
static int vma_lock_and_validate(struct drm_exec *exec, struct xe_vma *vma,
2835-
bool validate)
2835+
bool res_evict, bool validate)
28362836
{
28372837
struct xe_bo *bo = xe_vma_bo(vma);
28382838
struct xe_vm *vm = xe_vma_vm(vma);
@@ -2843,7 +2843,8 @@ static int vma_lock_and_validate(struct drm_exec *exec, struct xe_vma *vma,
28432843
err = drm_exec_lock_obj(exec, &bo->ttm.base);
28442844
if (!err && validate)
28452845
err = xe_bo_validate(bo, vm,
2846-
!xe_vm_in_preempt_fence_mode(vm), exec);
2846+
!xe_vm_in_preempt_fence_mode(vm) &&
2847+
res_evict, exec);
28472848
}
28482849

28492850
return err;
@@ -2913,14 +2914,23 @@ static int prefetch_ranges(struct xe_vm *vm, struct xe_vma_op *op)
29132914
}
29142915

29152916
static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm,
2916-
struct xe_vma_op *op)
2917+
struct xe_vma_ops *vops, struct xe_vma_op *op)
29172918
{
29182919
int err = 0;
2920+
bool res_evict;
2921+
2922+
/*
2923+
* We only allow evicting a BO within the VM if it is not part of an
2924+
* array of binds, as an array of binds can evict another BO within the
2925+
* bind.
2926+
*/
2927+
res_evict = !(vops->flags & XE_VMA_OPS_ARRAY_OF_BINDS);
29192928

29202929
switch (op->base.op) {
29212930
case DRM_GPUVA_OP_MAP:
29222931
if (!op->map.invalidate_on_bind)
29232932
err = vma_lock_and_validate(exec, op->map.vma,
2933+
res_evict,
29242934
!xe_vm_in_fault_mode(vm) ||
29252935
op->map.immediate);
29262936
break;
@@ -2931,11 +2941,13 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm,
29312941

29322942
err = vma_lock_and_validate(exec,
29332943
gpuva_to_vma(op->base.remap.unmap->va),
2934-
false);
2944+
res_evict, false);
29352945
if (!err && op->remap.prev)
2936-
err = vma_lock_and_validate(exec, op->remap.prev, true);
2946+
err = vma_lock_and_validate(exec, op->remap.prev,
2947+
res_evict, true);
29372948
if (!err && op->remap.next)
2938-
err = vma_lock_and_validate(exec, op->remap.next, true);
2949+
err = vma_lock_and_validate(exec, op->remap.next,
2950+
res_evict, true);
29392951
break;
29402952
case DRM_GPUVA_OP_UNMAP:
29412953
err = check_ufence(gpuva_to_vma(op->base.unmap.va));
@@ -2944,7 +2956,7 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm,
29442956

29452957
err = vma_lock_and_validate(exec,
29462958
gpuva_to_vma(op->base.unmap.va),
2947-
false);
2959+
res_evict, false);
29482960
break;
29492961
case DRM_GPUVA_OP_PREFETCH:
29502962
{
@@ -2959,7 +2971,7 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm,
29592971

29602972
err = vma_lock_and_validate(exec,
29612973
gpuva_to_vma(op->base.prefetch.va),
2962-
false);
2974+
res_evict, false);
29632975
if (!err && !xe_vma_has_no_bo(vma))
29642976
err = xe_bo_migrate(xe_vma_bo(vma),
29652977
region_to_mem_type[region],
@@ -3005,7 +3017,7 @@ static int vm_bind_ioctl_ops_lock_and_prep(struct drm_exec *exec,
30053017
return err;
30063018

30073019
list_for_each_entry(op, &vops->list, link) {
3008-
err = op_lock_and_prep(exec, vm, op);
3020+
err = op_lock_and_prep(exec, vm, vops, op);
30093021
if (err)
30103022
return err;
30113023
}
@@ -3638,6 +3650,8 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
36383650
}
36393651

36403652
xe_vma_ops_init(&vops, vm, q, syncs, num_syncs);
3653+
if (args->num_binds > 1)
3654+
vops.flags |= XE_VMA_OPS_ARRAY_OF_BINDS;
36413655
for (i = 0; i < args->num_binds; ++i) {
36423656
u64 range = bind_ops[i].range;
36433657
u64 addr = bind_ops[i].addr;

drivers/gpu/drm/xe/xe_vm_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ struct xe_vma_ops {
476476
/** @flag: signify the properties within xe_vma_ops*/
477477
#define XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH BIT(0)
478478
#define XE_VMA_OPS_FLAG_MADVISE BIT(1)
479+
#define XE_VMA_OPS_ARRAY_OF_BINDS BIT(2)
479480
u32 flags;
480481
#ifdef TEST_VM_OPS_ERROR
481482
/** @inject_error: inject error to test error handling */

0 commit comments

Comments
 (0)