Skip to content

Commit 5aa0ab0

Browse files
mbrost05gregkh
authored andcommitted
drm/xe: Don't allow evicting of BOs in same VM in array of VM binds
[ Upstream commit 7ac74613e5f2ef3450f44fd2127198662c2563a9 ] 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: [email protected] Reported-by: Paulo Zanoni <[email protected]> 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 <[email protected]> Tested-by: Paulo Zanoni <[email protected]> Reviewed-by: Thomas Hellström <[email protected]> Link: https://lore.kernel.org/r/[email protected] (cherry picked from commit 8b9ba8d6d95fe75fed6b0480bb03da4b321bea08) Signed-off-by: Lucas De Marchi <[email protected]> [ removed exec parameter from xe_bo_validate() calls ] Signed-off-by: Sasha Levin <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 21723da commit 5aa0ab0

2 files changed

Lines changed: 25 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
@@ -2894,7 +2894,7 @@ static void vm_bind_ioctl_ops_unwind(struct xe_vm *vm,
28942894
}
28952895

28962896
static int vma_lock_and_validate(struct drm_exec *exec, struct xe_vma *vma,
2897-
bool validate)
2897+
bool res_evict, bool validate)
28982898
{
28992899
struct xe_bo *bo = xe_vma_bo(vma);
29002900
struct xe_vm *vm = xe_vma_vm(vma);
@@ -2905,7 +2905,8 @@ static int vma_lock_and_validate(struct drm_exec *exec, struct xe_vma *vma,
29052905
err = drm_exec_lock_obj(exec, &bo->ttm.base);
29062906
if (!err && validate)
29072907
err = xe_bo_validate(bo, vm,
2908-
!xe_vm_in_preempt_fence_mode(vm));
2908+
!xe_vm_in_preempt_fence_mode(vm) &&
2909+
res_evict);
29092910
}
29102911

29112912
return err;
@@ -2978,14 +2979,23 @@ static int prefetch_ranges(struct xe_vm *vm, struct xe_vma_op *op)
29782979
}
29792980

29802981
static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm,
2981-
struct xe_vma_op *op)
2982+
struct xe_vma_ops *vops, struct xe_vma_op *op)
29822983
{
29832984
int err = 0;
2985+
bool res_evict;
2986+
2987+
/*
2988+
* We only allow evicting a BO within the VM if it is not part of an
2989+
* array of binds, as an array of binds can evict another BO within the
2990+
* bind.
2991+
*/
2992+
res_evict = !(vops->flags & XE_VMA_OPS_ARRAY_OF_BINDS);
29842993

29852994
switch (op->base.op) {
29862995
case DRM_GPUVA_OP_MAP:
29872996
if (!op->map.invalidate_on_bind)
29882997
err = vma_lock_and_validate(exec, op->map.vma,
2998+
res_evict,
29892999
!xe_vm_in_fault_mode(vm) ||
29903000
op->map.immediate);
29913001
break;
@@ -2996,11 +3006,13 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm,
29963006

29973007
err = vma_lock_and_validate(exec,
29983008
gpuva_to_vma(op->base.remap.unmap->va),
2999-
false);
3009+
res_evict, false);
30003010
if (!err && op->remap.prev)
3001-
err = vma_lock_and_validate(exec, op->remap.prev, true);
3011+
err = vma_lock_and_validate(exec, op->remap.prev,
3012+
res_evict, true);
30023013
if (!err && op->remap.next)
3003-
err = vma_lock_and_validate(exec, op->remap.next, true);
3014+
err = vma_lock_and_validate(exec, op->remap.next,
3015+
res_evict, true);
30043016
break;
30053017
case DRM_GPUVA_OP_UNMAP:
30063018
err = check_ufence(gpuva_to_vma(op->base.unmap.va));
@@ -3009,7 +3021,7 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm,
30093021

30103022
err = vma_lock_and_validate(exec,
30113023
gpuva_to_vma(op->base.unmap.va),
3012-
false);
3024+
res_evict, false);
30133025
break;
30143026
case DRM_GPUVA_OP_PREFETCH:
30153027
{
@@ -3025,7 +3037,7 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm,
30253037

30263038
err = vma_lock_and_validate(exec,
30273039
gpuva_to_vma(op->base.prefetch.va),
3028-
false);
3040+
res_evict, false);
30293041
if (!err && !xe_vma_has_no_bo(vma))
30303042
err = xe_bo_migrate(xe_vma_bo(vma),
30313043
region_to_mem_type[region]);
@@ -3069,7 +3081,7 @@ static int vm_bind_ioctl_ops_lock_and_prep(struct drm_exec *exec,
30693081
return err;
30703082

30713083
list_for_each_entry(op, &vops->list, link) {
3072-
err = op_lock_and_prep(exec, vm, op);
3084+
err = op_lock_and_prep(exec, vm, vops, op);
30733085
if (err)
30743086
return err;
30753087
}
@@ -3698,6 +3710,8 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
36983710
}
36993711

37003712
xe_vma_ops_init(&vops, vm, q, syncs, num_syncs);
3713+
if (args->num_binds > 1)
3714+
vops.flags |= XE_VMA_OPS_ARRAY_OF_BINDS;
37013715
for (i = 0; i < args->num_binds; ++i) {
37023716
u64 range = bind_ops[i].range;
37033717
u64 addr = bind_ops[i].addr;

drivers/gpu/drm/xe/xe_vm_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,8 @@ struct xe_vma_ops {
467467
struct xe_vm_pgtable_update_ops pt_update_ops[XE_MAX_TILES_PER_DEVICE];
468468
/** @flag: signify the properties within xe_vma_ops*/
469469
#define XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH BIT(0)
470+
#define XE_VMA_OPS_FLAG_MADVISE BIT(1)
471+
#define XE_VMA_OPS_ARRAY_OF_BINDS BIT(2)
470472
u32 flags;
471473
#ifdef TEST_VM_OPS_ERROR
472474
/** @inject_error: inject error to test error handling */

0 commit comments

Comments
 (0)