Skip to content

Commit 6f4b7ae

Browse files
matt-auldThomas Hellström
authored andcommitted
drm/xe/uapi: disallow bind queue sharing
Currently this is very broken if someone attempts to create a bind queue and share it across multiple VMs. For example currently we assume it is safe to acquire the user VM lock to protect some of the bind queue state, but if allow sharing the bind queue with multiple VMs then this quickly breaks down. To fix this reject using a bind queue with any VM that is not the same VM that was originally passed when creating the bind queue. This a uAPI change, however this was more of an oversight on kernel side that we didn't reject this, and expectation is that userspace shouldn't be using bind queues in this way, so in theory this change should go unnoticed. Based on a patch from Matt Brost. v2 (Matt B): - Hold the vm lock over queue create, to ensure it can't be closed as we attach the user_vm to the queue. - Make sure we actually check for NULL user_vm in destruction path. v3: - Fix error path handling. Fixes: dd08ebf ("drm/xe: Introduce a new DRM driver for Intel GPUs") Reported-by: Thomas Hellström <thomas.hellstrom@linux.intel.com> Signed-off-by: Matthew Auld <matthew.auld@intel.com> Cc: José Roberto de Souza <jose.souza@intel.com> Cc: Matthew Brost <matthew.brost@intel.com> Cc: Michal Mrozek <michal.mrozek@intel.com> Cc: Carl Zhang <carl.zhang@intel.com> Cc: <stable@vger.kernel.org> # v6.8+ Acked-by: José Roberto de Souza <jose.souza@intel.com> Reviewed-by: Matthew Brost <matthew.brost@intel.com> Reviewed-by: Arvind Yadav <arvind.yadav@intel.com> Acked-by: Michal Mrozek <michal.mrozek@intel.com> Link: https://patch.msgid.link/20260120110609.77958-3-matthew.auld@intel.com (cherry picked from commit 9dd08fd) Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
1 parent b886aa6 commit 6f4b7ae

5 files changed

Lines changed: 45 additions & 3 deletions

File tree

drivers/gpu/drm/xe/xe_exec_queue.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ struct xe_exec_queue *xe_exec_queue_create_class(struct xe_device *xe, struct xe
328328
* @xe: Xe device.
329329
* @tile: tile which bind exec queue belongs to.
330330
* @flags: exec queue creation flags
331+
* @user_vm: The user VM which this exec queue belongs to
331332
* @extensions: exec queue creation extensions
332333
*
333334
* Normalize bind exec queue creation. Bind exec queue is tied to migration VM
@@ -341,6 +342,7 @@ struct xe_exec_queue *xe_exec_queue_create_class(struct xe_device *xe, struct xe
341342
*/
342343
struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
343344
struct xe_tile *tile,
345+
struct xe_vm *user_vm,
344346
u32 flags, u64 extensions)
345347
{
346348
struct xe_gt *gt = tile->primary_gt;
@@ -377,6 +379,9 @@ struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
377379
xe_exec_queue_put(q);
378380
return ERR_PTR(err);
379381
}
382+
383+
if (user_vm)
384+
q->user_vm = xe_vm_get(user_vm);
380385
}
381386

382387
return q;
@@ -407,6 +412,11 @@ void xe_exec_queue_destroy(struct kref *ref)
407412
xe_exec_queue_put(eq);
408413
}
409414

415+
if (q->user_vm) {
416+
xe_vm_put(q->user_vm);
417+
q->user_vm = NULL;
418+
}
419+
410420
q->ops->destroy(q);
411421
}
412422

@@ -742,16 +752,34 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
742752
XE_IOCTL_DBG(xe, eci[0].engine_instance != 0))
743753
return -EINVAL;
744754

755+
vm = xe_vm_lookup(xef, args->vm_id);
756+
if (XE_IOCTL_DBG(xe, !vm))
757+
return -ENOENT;
758+
759+
err = down_read_interruptible(&vm->lock);
760+
if (err) {
761+
xe_vm_put(vm);
762+
return err;
763+
}
764+
765+
if (XE_IOCTL_DBG(xe, xe_vm_is_closed_or_banned(vm))) {
766+
up_read(&vm->lock);
767+
xe_vm_put(vm);
768+
return -ENOENT;
769+
}
770+
745771
for_each_tile(tile, xe, id) {
746772
struct xe_exec_queue *new;
747773

748774
flags |= EXEC_QUEUE_FLAG_VM;
749775
if (id)
750776
flags |= EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD;
751777

752-
new = xe_exec_queue_create_bind(xe, tile, flags,
778+
new = xe_exec_queue_create_bind(xe, tile, vm, flags,
753779
args->extensions);
754780
if (IS_ERR(new)) {
781+
up_read(&vm->lock);
782+
xe_vm_put(vm);
755783
err = PTR_ERR(new);
756784
if (q)
757785
goto put_exec_queue;
@@ -763,6 +791,8 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
763791
list_add_tail(&new->multi_gt_list,
764792
&q->multi_gt_link);
765793
}
794+
up_read(&vm->lock);
795+
xe_vm_put(vm);
766796
} else {
767797
logical_mask = calc_validate_logical_mask(xe, eci,
768798
args->width,

drivers/gpu/drm/xe/xe_exec_queue.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct xe_exec_queue *xe_exec_queue_create_class(struct xe_device *xe, struct xe
2828
u32 flags, u64 extensions);
2929
struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
3030
struct xe_tile *tile,
31+
struct xe_vm *user_vm,
3132
u32 flags, u64 extensions);
3233

3334
void xe_exec_queue_fini(struct xe_exec_queue *q);

drivers/gpu/drm/xe/xe_exec_queue_types.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ struct xe_exec_queue {
5454
struct kref refcount;
5555
/** @vm: VM (address space) for this exec queue */
5656
struct xe_vm *vm;
57+
/**
58+
* @user_vm: User VM (address space) for this exec queue (bind queues
59+
* only)
60+
*/
61+
struct xe_vm *user_vm;
62+
5763
/** @class: class of this exec queue */
5864
enum xe_engine_class class;
5965
/**

drivers/gpu/drm/xe/xe_sriov_vf_ccs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ int xe_sriov_vf_ccs_init(struct xe_device *xe)
346346
flags = EXEC_QUEUE_FLAG_KERNEL |
347347
EXEC_QUEUE_FLAG_PERMANENT |
348348
EXEC_QUEUE_FLAG_MIGRATE;
349-
q = xe_exec_queue_create_bind(xe, tile, flags, 0);
349+
q = xe_exec_queue_create_bind(xe, tile, NULL, flags, 0);
350350
if (IS_ERR(q)) {
351351
err = PTR_ERR(q);
352352
goto err_ret;

drivers/gpu/drm/xe/xe_vm.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1617,7 +1617,7 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef)
16171617
if (!vm->pt_root[id])
16181618
continue;
16191619

1620-
q = xe_exec_queue_create_bind(xe, tile, create_flags, 0);
1620+
q = xe_exec_queue_create_bind(xe, tile, vm, create_flags, 0);
16211621
if (IS_ERR(q)) {
16221622
err = PTR_ERR(q);
16231623
goto err_close;
@@ -3578,6 +3578,11 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
35783578
}
35793579
}
35803580

3581+
if (XE_IOCTL_DBG(xe, q && vm != q->user_vm)) {
3582+
err = -EINVAL;
3583+
goto put_exec_queue;
3584+
}
3585+
35813586
/* Ensure all UNMAPs visible */
35823587
xe_svm_flush(vm);
35833588

0 commit comments

Comments
 (0)