Skip to content

Commit 61fda28

Browse files
Iouri Tarassovchessturo
authored andcommitted
drivers: hv: dxgkrnl: Sharing of dxgresource objects
Implement creation of shared resources and ioctls for sharing dxgresource objects between processes in the virtual machine. A dxgresource object is a collection of dxgallocation objects. The driver API allows addition/removal of allocations to a resource, but has limitations on addition/removal of allocations to a shared resource. When a resource is "sealed", addition/removal of allocations is not allowed. Resources are shared using file descriptor (FD) handles. The name "NT handle" is used to be compatible with Windows implementation. An FD handle is created by the LX_DXSHAREOBJECTS ioctl. The given FD handle could be sent to another process using any Linux API. To use a shared resource object in other ioctls the object needs to be opened using its FD handle. An resource object is opened by the LX_DXOPENRESOURCEFROMNTHANDLE ioctl. This ioctl returns a d3dkmthandle value, which can be used to reference the resource object. The LX_DXQUERYRESOURCEINFOFROMNTHANDLE ioctl is used to query private driver data of a shared resource object. This private data needs to be used to actually open the object using the LX_DXOPENRESOURCEFROMNTHANDLE ioctl. Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com> [kms: forward port to 6.6 from 6.1. No code changes made.] Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
1 parent ff83a21 commit 61fda28

7 files changed

Lines changed: 1200 additions & 4 deletions

File tree

drivers/hv/dxgkrnl/dxgadapter.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,17 @@ void dxgadapter_remove_process(struct dxgprocess_adapter *process_info)
160160
list_del(&process_info->adapter_process_list_entry);
161161
}
162162

163+
void dxgadapter_remove_shared_resource(struct dxgadapter *adapter,
164+
struct dxgsharedresource *object)
165+
{
166+
down_write(&adapter->shared_resource_list_lock);
167+
if (object->shared_resource_list_entry.next) {
168+
list_del(&object->shared_resource_list_entry);
169+
object->shared_resource_list_entry.next = NULL;
170+
}
171+
up_write(&adapter->shared_resource_list_lock);
172+
}
173+
163174
void dxgadapter_add_syncobj(struct dxgadapter *adapter,
164175
struct dxgsyncobject *object)
165176
{
@@ -489,6 +500,69 @@ void dxgdevice_remove_resource(struct dxgdevice *device,
489500
}
490501
}
491502

503+
struct dxgsharedresource *dxgsharedresource_create(struct dxgadapter *adapter)
504+
{
505+
struct dxgsharedresource *resource;
506+
507+
resource = kzalloc(sizeof(*resource), GFP_KERNEL);
508+
if (resource) {
509+
INIT_LIST_HEAD(&resource->resource_list_head);
510+
kref_init(&resource->sresource_kref);
511+
mutex_init(&resource->fd_mutex);
512+
resource->adapter = adapter;
513+
}
514+
return resource;
515+
}
516+
517+
void dxgsharedresource_destroy(struct kref *refcount)
518+
{
519+
struct dxgsharedresource *resource;
520+
521+
resource = container_of(refcount, struct dxgsharedresource,
522+
sresource_kref);
523+
if (resource->runtime_private_data)
524+
vfree(resource->runtime_private_data);
525+
if (resource->resource_private_data)
526+
vfree(resource->resource_private_data);
527+
if (resource->alloc_private_data_sizes)
528+
vfree(resource->alloc_private_data_sizes);
529+
if (resource->alloc_private_data)
530+
vfree(resource->alloc_private_data);
531+
kfree(resource);
532+
}
533+
534+
void dxgsharedresource_add_resource(struct dxgsharedresource *shared_resource,
535+
struct dxgresource *resource)
536+
{
537+
down_write(&shared_resource->adapter->shared_resource_list_lock);
538+
DXG_TRACE("Adding resource: %p %p", shared_resource, resource);
539+
list_add_tail(&resource->shared_resource_list_entry,
540+
&shared_resource->resource_list_head);
541+
kref_get(&shared_resource->sresource_kref);
542+
kref_get(&resource->resource_kref);
543+
resource->shared_owner = shared_resource;
544+
up_write(&shared_resource->adapter->shared_resource_list_lock);
545+
}
546+
547+
void dxgsharedresource_remove_resource(struct dxgsharedresource
548+
*shared_resource,
549+
struct dxgresource *resource)
550+
{
551+
struct dxgadapter *adapter = shared_resource->adapter;
552+
553+
down_write(&adapter->shared_resource_list_lock);
554+
DXG_TRACE("Removing resource: %p %p", shared_resource, resource);
555+
if (resource->shared_resource_list_entry.next) {
556+
list_del(&resource->shared_resource_list_entry);
557+
resource->shared_resource_list_entry.next = NULL;
558+
kref_put(&shared_resource->sresource_kref,
559+
dxgsharedresource_destroy);
560+
resource->shared_owner = NULL;
561+
kref_put(&resource->resource_kref, dxgresource_release);
562+
}
563+
up_write(&adapter->shared_resource_list_lock);
564+
}
565+
492566
struct dxgresource *dxgresource_create(struct dxgdevice *device)
493567
{
494568
struct dxgresource *resource;
@@ -532,6 +606,7 @@ void dxgresource_destroy(struct dxgresource *resource)
532606
struct d3dkmt_destroyallocation2 args = { };
533607
int destroyed = test_and_set_bit(0, &resource->flags);
534608
struct dxgdevice *device = resource->device;
609+
struct dxgsharedresource *shared_resource;
535610

536611
if (!destroyed) {
537612
dxgresource_free_handle(resource);
@@ -547,6 +622,12 @@ void dxgresource_destroy(struct dxgresource *resource)
547622
dxgallocation_destroy(alloc);
548623
}
549624
dxgdevice_remove_resource(device, resource);
625+
shared_resource = resource->shared_owner;
626+
if (shared_resource) {
627+
dxgsharedresource_remove_resource(shared_resource,
628+
resource);
629+
resource->shared_owner = NULL;
630+
}
550631
}
551632
kref_put(&resource->resource_kref, dxgresource_release);
552633
}

drivers/hv/dxgkrnl/dxgkrnl.h

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct dxgdevice;
3838
struct dxgcontext;
3939
struct dxgallocation;
4040
struct dxgresource;
41+
struct dxgsharedresource;
4142
struct dxgsyncobject;
4243

4344
/*
@@ -372,6 +373,8 @@ struct dxgadapter {
372373
struct list_head adapter_list_entry;
373374
/* The list of dxgprocess_adapter entries */
374375
struct list_head adapter_process_list_head;
376+
/* List of all dxgsharedresource objects */
377+
struct list_head shared_resource_list_head;
375378
/* List of all non-device dxgsyncobject objects */
376379
struct list_head syncobj_list_head;
377380
/* This lock protects shared resource and syncobject lists */
@@ -405,6 +408,8 @@ void dxgadapter_remove_syncobj(struct dxgsyncobject *so);
405408
void dxgadapter_add_process(struct dxgadapter *adapter,
406409
struct dxgprocess_adapter *process_info);
407410
void dxgadapter_remove_process(struct dxgprocess_adapter *process_info);
411+
void dxgadapter_remove_shared_resource(struct dxgadapter *adapter,
412+
struct dxgsharedresource *object);
408413

409414
/*
410415
* The object represent the device object.
@@ -484,6 +489,64 @@ void dxgcontext_destroy_safe(struct dxgprocess *pr, struct dxgcontext *ctx);
484489
void dxgcontext_release(struct kref *refcount);
485490
bool dxgcontext_is_active(struct dxgcontext *ctx);
486491

492+
/*
493+
* A shared resource object is created to track the list of dxgresource objects,
494+
* which are opened for the same underlying shared resource.
495+
* Objects are shared by using a file descriptor handle.
496+
* FD is created by calling dxgk_share_objects and providing shandle to
497+
* dxgsharedresource. The FD points to a dxgresource object, which is created
498+
* by calling dxgk_open_resource_nt. dxgresource object is referenced by the
499+
* FD.
500+
*
501+
* The object is referenced by every dxgresource in its list.
502+
*
503+
*/
504+
struct dxgsharedresource {
505+
/* Every dxgresource object in the resource list takes a reference */
506+
struct kref sresource_kref;
507+
struct dxgadapter *adapter;
508+
/* List of dxgresource objects, opened for the shared resource. */
509+
/* Protected by dxgadapter::shared_resource_list_lock */
510+
struct list_head resource_list_head;
511+
/* Entry in the list of dxgsharedresource in dxgadapter */
512+
/* Protected by dxgadapter::shared_resource_list_lock */
513+
struct list_head shared_resource_list_entry;
514+
struct mutex fd_mutex;
515+
/* Referenced by file descriptors */
516+
int host_shared_handle_nt_reference;
517+
/* Corresponding global handle in the host */
518+
struct d3dkmthandle host_shared_handle;
519+
/*
520+
* When the sync object is shared by NT handle, this is the
521+
* corresponding handle in the host
522+
*/
523+
struct d3dkmthandle host_shared_handle_nt;
524+
/* Values below are computed when the resource is sealed */
525+
u32 runtime_private_data_size;
526+
u32 alloc_private_data_size;
527+
u32 resource_private_data_size;
528+
u32 allocation_count;
529+
union {
530+
struct {
531+
/* Cannot add new allocations */
532+
u32 sealed:1;
533+
u32 reserved:31;
534+
};
535+
long flags;
536+
};
537+
u32 *alloc_private_data_sizes;
538+
u8 *alloc_private_data;
539+
u8 *runtime_private_data;
540+
u8 *resource_private_data;
541+
};
542+
543+
struct dxgsharedresource *dxgsharedresource_create(struct dxgadapter *adapter);
544+
void dxgsharedresource_destroy(struct kref *refcount);
545+
void dxgsharedresource_add_resource(struct dxgsharedresource *sres,
546+
struct dxgresource *res);
547+
void dxgsharedresource_remove_resource(struct dxgsharedresource *sres,
548+
struct dxgresource *res);
549+
487550
struct dxgresource {
488551
struct kref resource_kref;
489552
enum dxgobjectstate object_state;
@@ -504,6 +567,8 @@ struct dxgresource {
504567
};
505568
long flags;
506569
};
570+
/* Owner of the shared resource */
571+
struct dxgsharedresource *shared_owner;
507572
};
508573

509574
struct dxgresource *dxgresource_create(struct dxgdevice *dev);
@@ -658,6 +723,18 @@ int dxgvmb_send_wait_sync_object_cpu(struct dxgprocess *process,
658723
int dxgvmb_send_query_adapter_info(struct dxgprocess *process,
659724
struct dxgadapter *adapter,
660725
struct d3dkmt_queryadapterinfo *args);
726+
int dxgvmb_send_create_nt_shared_object(struct dxgprocess *process,
727+
struct d3dkmthandle object,
728+
struct d3dkmthandle *shared_handle);
729+
int dxgvmb_send_destroy_nt_shared_object(struct d3dkmthandle shared_handle);
730+
int dxgvmb_send_open_resource(struct dxgprocess *process,
731+
struct dxgadapter *adapter,
732+
struct d3dkmthandle device,
733+
struct d3dkmthandle global_share,
734+
u32 allocation_count,
735+
u32 total_priv_drv_data_size,
736+
struct d3dkmthandle *resource_handle,
737+
struct d3dkmthandle *alloc_handles);
661738
int dxgvmb_send_get_stdalloc_data(struct dxgdevice *device,
662739
enum d3dkmdt_standardallocationtype t,
663740
struct d3dkmdt_gdisurfacedata *data,

drivers/hv/dxgkrnl/dxgmodule.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ int dxgglobal_create_adapter(struct pci_dev *dev, guid_t *guid,
258258
init_rwsem(&adapter->core_lock);
259259

260260
INIT_LIST_HEAD(&adapter->adapter_process_list_head);
261+
INIT_LIST_HEAD(&adapter->shared_resource_list_head);
261262
INIT_LIST_HEAD(&adapter->syncobj_list_head);
262263
init_rwsem(&adapter->shared_resource_list_lock);
263264
adapter->pci_dev = dev;

drivers/hv/dxgkrnl/dxgvmbus.c

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,79 @@ int dxgvmb_send_destroy_process(struct d3dkmthandle process)
712712
return ret;
713713
}
714714

715+
int dxgvmb_send_create_nt_shared_object(struct dxgprocess *process,
716+
struct d3dkmthandle object,
717+
struct d3dkmthandle *shared_handle)
718+
{
719+
struct dxgkvmb_command_createntsharedobject *command;
720+
int ret;
721+
struct dxgvmbusmsg msg;
722+
723+
ret = init_message(&msg, NULL, process, sizeof(*command));
724+
if (ret)
725+
return ret;
726+
command = (void *)msg.msg;
727+
728+
command_vm_to_host_init2(&command->hdr,
729+
DXGK_VMBCOMMAND_CREATENTSHAREDOBJECT,
730+
process->host_handle);
731+
command->object = object;
732+
733+
ret = dxgglobal_acquire_channel_lock();
734+
if (ret < 0)
735+
goto cleanup;
736+
737+
ret = dxgvmb_send_sync_msg(dxgglobal_get_dxgvmbuschannel(),
738+
msg.hdr, msg.size, shared_handle,
739+
sizeof(*shared_handle));
740+
741+
dxgglobal_release_channel_lock();
742+
743+
if (ret < 0)
744+
goto cleanup;
745+
if (shared_handle->v == 0) {
746+
DXG_ERR("failed to create NT shared object");
747+
ret = -ENOTRECOVERABLE;
748+
}
749+
750+
cleanup:
751+
free_message(&msg, process);
752+
if (ret)
753+
DXG_TRACE("err: %d", ret);
754+
return ret;
755+
}
756+
757+
int dxgvmb_send_destroy_nt_shared_object(struct d3dkmthandle shared_handle)
758+
{
759+
struct dxgkvmb_command_destroyntsharedobject *command;
760+
int ret;
761+
struct dxgvmbusmsg msg;
762+
763+
ret = init_message(&msg, NULL, NULL, sizeof(*command));
764+
if (ret)
765+
return ret;
766+
command = (void *)msg.msg;
767+
768+
command_vm_to_host_init1(&command->hdr,
769+
DXGK_VMBCOMMAND_DESTROYNTSHAREDOBJECT);
770+
command->shared_handle = shared_handle;
771+
772+
ret = dxgglobal_acquire_channel_lock();
773+
if (ret < 0)
774+
goto cleanup;
775+
776+
ret = dxgvmb_send_sync_msg_ntstatus(dxgglobal_get_dxgvmbuschannel(),
777+
msg.hdr, msg.size);
778+
779+
dxgglobal_release_channel_lock();
780+
781+
cleanup:
782+
free_message(&msg, NULL);
783+
if (ret)
784+
DXG_TRACE("err: %d", ret);
785+
return ret;
786+
}
787+
715788
int dxgvmb_send_destroy_sync_object(struct dxgprocess *process,
716789
struct d3dkmthandle sync_object)
717790
{
@@ -1552,6 +1625,60 @@ int dxgvmb_send_destroy_allocation(struct dxgprocess *process,
15521625
return ret;
15531626
}
15541627

1628+
int dxgvmb_send_open_resource(struct dxgprocess *process,
1629+
struct dxgadapter *adapter,
1630+
struct d3dkmthandle device,
1631+
struct d3dkmthandle global_share,
1632+
u32 allocation_count,
1633+
u32 total_priv_drv_data_size,
1634+
struct d3dkmthandle *resource_handle,
1635+
struct d3dkmthandle *alloc_handles)
1636+
{
1637+
struct dxgkvmb_command_openresource *command;
1638+
struct dxgkvmb_command_openresource_return *result;
1639+
struct d3dkmthandle *handles;
1640+
int ret;
1641+
int i;
1642+
u32 result_size = allocation_count * sizeof(struct d3dkmthandle) +
1643+
sizeof(*result);
1644+
struct dxgvmbusmsgres msg = {.hdr = NULL};
1645+
1646+
ret = init_message_res(&msg, adapter, process, sizeof(*command),
1647+
result_size);
1648+
if (ret)
1649+
goto cleanup;
1650+
command = msg.msg;
1651+
result = msg.res;
1652+
1653+
command_vgpu_to_host_init2(&command->hdr, DXGK_VMBCOMMAND_OPENRESOURCE,
1654+
process->host_handle);
1655+
command->device = device;
1656+
command->nt_security_sharing = 1;
1657+
command->global_share = global_share;
1658+
command->allocation_count = allocation_count;
1659+
command->total_priv_drv_data_size = total_priv_drv_data_size;
1660+
1661+
ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
1662+
result, msg.res_size);
1663+
if (ret < 0)
1664+
goto cleanup;
1665+
1666+
ret = ntstatus2int(result->status);
1667+
if (ret < 0)
1668+
goto cleanup;
1669+
1670+
*resource_handle = result->resource;
1671+
handles = (struct d3dkmthandle *) &result[1];
1672+
for (i = 0; i < allocation_count; i++)
1673+
alloc_handles[i] = handles[i];
1674+
1675+
cleanup:
1676+
free_message((struct dxgvmbusmsg *)&msg, process);
1677+
if (ret)
1678+
DXG_TRACE("err: %d", ret);
1679+
return ret;
1680+
}
1681+
15551682
int dxgvmb_send_get_stdalloc_data(struct dxgdevice *device,
15561683
enum d3dkmdt_standardallocationtype alloctype,
15571684
struct d3dkmdt_gdisurfacedata *alloc_data,

0 commit comments

Comments
 (0)