Skip to content

Commit df7ea89

Browse files
author
Iouri Tarassov
committed
drivers: hv: dxgkrnl: Fix synchronization locks
Signed-off-by: Iouri Tarassov <[email protected]>
1 parent 8ca52f5 commit df7ea89

File tree

7 files changed

+101
-50
lines changed

7 files changed

+101
-50
lines changed

drivers/hv/dxgkrnl/dxgadapter.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ void dxgadapter_release(struct kref *refcount)
136136
struct dxgadapter *adapter;
137137

138138
adapter = container_of(refcount, struct dxgadapter, adapter_kref);
139-
DXG_TRACE("%p", adapter);
139+
DXG_TRACE("Destroying adapter: %px", adapter);
140140
kfree(adapter);
141141
}
142142

@@ -270,6 +270,8 @@ struct dxgdevice *dxgdevice_create(struct dxgadapter *adapter,
270270
if (ret < 0) {
271271
kref_put(&device->device_kref, dxgdevice_release);
272272
device = NULL;
273+
} else {
274+
DXG_TRACE("dxgdevice created: %px", device);
273275
}
274276
}
275277
return device;
@@ -413,11 +415,8 @@ void dxgdevice_destroy(struct dxgdevice *device)
413415

414416
cleanup:
415417

416-
if (device->adapter) {
418+
if (device->adapter)
417419
dxgprocess_adapter_remove_device(device);
418-
kref_put(&device->adapter->adapter_kref, dxgadapter_release);
419-
device->adapter = NULL;
420-
}
421420

422421
up_write(&device->device_lock);
423422

@@ -721,6 +720,8 @@ void dxgdevice_release(struct kref *refcount)
721720
struct dxgdevice *device;
722721

723722
device = container_of(refcount, struct dxgdevice, device_kref);
723+
DXG_TRACE("Destroying device: %px", device);
724+
kref_put(&device->adapter->adapter_kref, dxgadapter_release);
724725
kfree(device);
725726
}
726727

@@ -999,6 +1000,9 @@ void dxgpagingqueue_destroy(struct dxgpagingqueue *pqueue)
9991000
kfree(pqueue);
10001001
}
10011002

1003+
/*
1004+
* Process_adapter_mutex is held.
1005+
*/
10021006
struct dxgprocess_adapter *dxgprocess_adapter_create(struct dxgprocess *process,
10031007
struct dxgadapter *adapter)
10041008
{
@@ -1108,7 +1112,7 @@ int dxgprocess_adapter_add_device(struct dxgprocess *process,
11081112

11091113
void dxgprocess_adapter_remove_device(struct dxgdevice *device)
11101114
{
1111-
DXG_TRACE("Removing device: %p", device);
1115+
DXG_TRACE("Removing device: %px", device);
11121116
mutex_lock(&device->adapter_info->device_list_mutex);
11131117
if (device->device_list_entry.next) {
11141118
list_del(&device->device_list_entry);
@@ -1147,8 +1151,7 @@ void dxgsharedsyncobj_release(struct kref *refcount)
11471151
if (syncobj->adapter) {
11481152
dxgadapter_remove_shared_syncobj(syncobj->adapter,
11491153
syncobj);
1150-
kref_put(&syncobj->adapter->adapter_kref,
1151-
dxgadapter_release);
1154+
kref_put(&syncobj->adapter->adapter_kref, dxgadapter_release);
11521155
}
11531156
kfree(syncobj);
11541157
}

drivers/hv/dxgkrnl/dxgkrnl.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,10 @@ struct dxgprocess {
404404
/* Handle of the corresponding objec on the host */
405405
struct d3dkmthandle host_handle;
406406

407-
/* List of opened adapters (dxgprocess_adapter) */
407+
/*
408+
* List of opened adapters (dxgprocess_adapter).
409+
* Protected by process_adapter_mutex.
410+
*/
408411
struct list_head process_adapter_list_head;
409412
};
410413

@@ -451,6 +454,8 @@ enum dxgadapter_state {
451454
struct dxgadapter {
452455
struct rw_semaphore core_lock;
453456
struct kref adapter_kref;
457+
/* Protects creation and destruction of dxgdevice objects */
458+
struct mutex device_creation_lock;
454459
/* Entry in the list of adapters in dxgglobal */
455460
struct list_head adapter_list_entry;
456461
/* The list of dxgprocess_adapter entries */
@@ -997,6 +1002,7 @@ void dxgk_validate_ioctls(void);
9971002

9981003
#define DXG_TRACE(fmt, ...) do { \
9991004
trace_printk(dev_fmt(fmt) "\n", ##__VA_ARGS__); \
1005+
dev_dbg(DXGDEV, "%s: " fmt, __func__, ##__VA_ARGS__); \
10001006
} while (0)
10011007

10021008
#define DXG_ERR(fmt, ...) do { \

drivers/hv/dxgkrnl/dxgmodule.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ int dxgglobal_create_adapter(struct pci_dev *dev, guid_t *guid,
272272
adapter->host_vgpu_luid = host_vgpu_luid;
273273
kref_init(&adapter->adapter_kref);
274274
init_rwsem(&adapter->core_lock);
275+
mutex_init(&adapter->device_creation_lock);
275276

276277
INIT_LIST_HEAD(&adapter->adapter_process_list_head);
277278
INIT_LIST_HEAD(&adapter->shared_resource_list_head);
@@ -961,4 +962,4 @@ module_exit(dxg_drv_exit);
961962

962963
MODULE_LICENSE("GPL");
963964
MODULE_DESCRIPTION("Microsoft Dxgkrnl virtual compute device Driver");
964-
MODULE_VERSION("2.0.0");
965+
MODULE_VERSION("2.0.1");

drivers/hv/dxgkrnl/dxgprocess.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -214,14 +214,15 @@ int dxgprocess_close_adapter(struct dxgprocess *process,
214214
hmgrtable_unlock(&process->local_handle_table, DXGLOCK_EXCL);
215215

216216
if (adapter) {
217+
mutex_lock(&adapter->device_creation_lock);
218+
dxgglobal_acquire_process_adapter_lock();
217219
adapter_info = dxgprocess_get_adapter_info(process, adapter);
218-
if (adapter_info) {
219-
dxgglobal_acquire_process_adapter_lock();
220+
if (adapter_info)
220221
dxgprocess_adapter_release(adapter_info);
221-
dxgglobal_release_process_adapter_lock();
222-
} else {
222+
else
223223
ret = -EINVAL;
224-
}
224+
dxgglobal_release_process_adapter_lock();
225+
mutex_unlock(&adapter->device_creation_lock);
225226
} else {
226227
DXG_ERR("Adapter not found %x", handle.v);
227228
ret = -EINVAL;

drivers/hv/dxgkrnl/dxgvmbus.c

Lines changed: 59 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,8 +1573,27 @@ process_allocation_handles(struct dxgprocess *process,
15731573
struct dxgresource *resource)
15741574
{
15751575
int ret = 0;
1576-
int i;
1576+
int i = 0;
1577+
int k;
1578+
struct dxgkvmb_command_allocinfo_return *host_alloc;
15771579

1580+
/*
1581+
* Assign handle to the internal objects, so VM bus messages will be
1582+
* sent to the host to free them during object destruction.
1583+
*/
1584+
if (args->flags.create_resource)
1585+
resource->handle = res->resource;
1586+
for (i = 0; i < args->alloc_count; i++) {
1587+
host_alloc = &res->allocation_info[i];
1588+
dxgalloc[i]->alloc_handle = host_alloc->allocation;
1589+
}
1590+
1591+
/*
1592+
* Assign handle to the handle table.
1593+
* In case of a failure all handles should be freed.
1594+
* When the function returns, the objects could be destroyed by
1595+
* handle immediately.
1596+
*/
15781597
hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL);
15791598
if (args->flags.create_resource) {
15801599
ret = hmgrtable_assign_handle(&process->handle_table, resource,
@@ -1583,14 +1602,12 @@ process_allocation_handles(struct dxgprocess *process,
15831602
if (ret < 0) {
15841603
DXG_ERR("failed to assign resource handle %x",
15851604
res->resource.v);
1605+
goto cleanup;
15861606
} else {
1587-
resource->handle = res->resource;
15881607
resource->handle_valid = 1;
15891608
}
15901609
}
15911610
for (i = 0; i < args->alloc_count; i++) {
1592-
struct dxgkvmb_command_allocinfo_return *host_alloc;
1593-
15941611
host_alloc = &res->allocation_info[i];
15951612
ret = hmgrtable_assign_handle(&process->handle_table,
15961613
dxgalloc[i],
@@ -1602,9 +1619,26 @@ process_allocation_handles(struct dxgprocess *process,
16021619
args->alloc_count, i);
16031620
break;
16041621
}
1605-
dxgalloc[i]->alloc_handle = host_alloc->allocation;
16061622
dxgalloc[i]->handle_valid = 1;
16071623
}
1624+
if (ret < 0) {
1625+
if (args->flags.create_resource) {
1626+
hmgrtable_free_handle(&process->handle_table,
1627+
HMGRENTRY_TYPE_DXGRESOURCE,
1628+
res->resource);
1629+
resource->handle_valid = 0;
1630+
}
1631+
for (k = 0; k < i; k++) {
1632+
host_alloc = &res->allocation_info[i];
1633+
hmgrtable_free_handle(&process->handle_table,
1634+
HMGRENTRY_TYPE_DXGALLOCATION,
1635+
host_alloc->allocation);
1636+
dxgalloc[i]->handle_valid = 0;
1637+
}
1638+
}
1639+
1640+
cleanup:
1641+
16081642
hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
16091643

16101644
if (ret)
@@ -1705,18 +1739,17 @@ create_local_allocations(struct dxgprocess *process,
17051739
}
17061740
}
17071741

1708-
ret = process_allocation_handles(process, device, args, result,
1709-
dxgalloc, resource);
1710-
if (ret < 0)
1711-
goto cleanup;
1712-
17131742
ret = copy_to_user(&input_args->global_share, &args->global_share,
17141743
sizeof(struct d3dkmthandle));
17151744
if (ret) {
17161745
DXG_ERR("failed to copy global share");
17171746
ret = -EFAULT;
1747+
goto cleanup;
17181748
}
17191749

1750+
ret = process_allocation_handles(process, device, args, result,
1751+
dxgalloc, resource);
1752+
17201753
cleanup:
17211754

17221755
if (ret < 0) {
@@ -3576,22 +3609,6 @@ int dxgvmb_send_create_hwqueue(struct dxgprocess *process,
35763609
goto cleanup;
35773610
}
35783611

3579-
ret = hmgrtable_assign_handle_safe(&process->handle_table, hwqueue,
3580-
HMGRENTRY_TYPE_DXGHWQUEUE,
3581-
command->hwqueue);
3582-
if (ret < 0)
3583-
goto cleanup;
3584-
3585-
ret = hmgrtable_assign_handle_safe(&process->handle_table,
3586-
NULL,
3587-
HMGRENTRY_TYPE_MONITOREDFENCE,
3588-
command->hwqueue_progress_fence);
3589-
if (ret < 0)
3590-
goto cleanup;
3591-
3592-
hwqueue->handle = command->hwqueue;
3593-
hwqueue->progress_fence_sync_object = command->hwqueue_progress_fence;
3594-
35953612
hwqueue->progress_fence_mapped_address =
35963613
dxg_map_iospace((u64)command->hwqueue_progress_fence_cpuva,
35973614
PAGE_SIZE, PROT_READ | PROT_WRITE, true);
@@ -3641,6 +3658,22 @@ int dxgvmb_send_create_hwqueue(struct dxgprocess *process,
36413658
}
36423659
}
36433660

3661+
ret = hmgrtable_assign_handle_safe(&process->handle_table,
3662+
NULL,
3663+
HMGRENTRY_TYPE_MONITOREDFENCE,
3664+
command->hwqueue_progress_fence);
3665+
if (ret < 0)
3666+
goto cleanup;
3667+
3668+
hwqueue->progress_fence_sync_object = command->hwqueue_progress_fence;
3669+
hwqueue->handle = command->hwqueue;
3670+
3671+
ret = hmgrtable_assign_handle_safe(&process->handle_table, hwqueue,
3672+
HMGRENTRY_TYPE_DXGHWQUEUE,
3673+
command->hwqueue);
3674+
if (ret < 0)
3675+
hwqueue->handle.v = 0;
3676+
36443677
cleanup:
36453678
if (ret < 0) {
36463679
DXG_ERR("failed %x", ret);

drivers/hv/dxgkrnl/ioctl.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,7 @@ dxgkio_create_device(struct dxgprocess *process, void *__user inargs)
636636
struct dxgdevice *device = NULL;
637637
struct d3dkmthandle host_device_handle = {};
638638
bool adapter_locked = false;
639+
bool device_creation_locked = false;
639640

640641
ret = copy_from_user(&args, inargs, sizeof(args));
641642
if (ret) {
@@ -651,6 +652,9 @@ dxgkio_create_device(struct dxgprocess *process, void *__user inargs)
651652
goto cleanup;
652653
}
653654

655+
mutex_lock(&adapter->device_creation_lock);
656+
device_creation_locked = true;
657+
654658
device = dxgdevice_create(adapter, process);
655659
if (device == NULL) {
656660
ret = -ENOMEM;
@@ -699,6 +703,9 @@ dxgkio_create_device(struct dxgprocess *process, void *__user inargs)
699703
if (adapter_locked)
700704
dxgadapter_release_lock_shared(adapter);
701705

706+
if (device_creation_locked)
707+
mutex_unlock(&adapter->device_creation_lock);
708+
702709
if (adapter)
703710
kref_put(&adapter->adapter_kref, dxgadapter_release);
704711

@@ -803,22 +810,21 @@ dxgkio_create_context_virtual(struct dxgprocess *process, void *__user inargs)
803810
host_context_handle = dxgvmb_send_create_context(adapter,
804811
process, &args);
805812
if (host_context_handle.v) {
806-
hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL);
807-
ret = hmgrtable_assign_handle(&process->handle_table, context,
808-
HMGRENTRY_TYPE_DXGCONTEXT,
809-
host_context_handle);
810-
if (ret >= 0)
811-
context->handle = host_context_handle;
812-
hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
813-
if (ret < 0)
814-
goto cleanup;
815813
ret = copy_to_user(&((struct d3dkmt_createcontextvirtual *)
816814
inargs)->context, &host_context_handle,
817815
sizeof(struct d3dkmthandle));
818816
if (ret) {
819817
DXG_ERR("failed to copy context handle");
820818
ret = -EFAULT;
819+
goto cleanup;
821820
}
821+
hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL);
822+
ret = hmgrtable_assign_handle(&process->handle_table, context,
823+
HMGRENTRY_TYPE_DXGCONTEXT,
824+
host_context_handle);
825+
if (ret >= 0)
826+
context->handle = host_context_handle;
827+
hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
822828
} else {
823829
DXG_ERR("invalid host handle");
824830
ret = -EINVAL;

drivers/hv/dxgkrnl/misc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ extern const struct d3dkmthandle zerohandle;
3838
* core_lock (dxgadapter lock)
3939
* device_lock (dxgdevice lock)
4040
* process_adapter_mutex
41+
* device_creation_lock in dxgadapter
4142
* adapter_list_lock
4243
* device_mutex (dxgglobal mutex)
4344
*/

0 commit comments

Comments
 (0)