Skip to content

Commit 518f7d2

Browse files
author
Iouri Tarassov
committed
drivers: hv: dxgkrnl: Implement sharing resources and sync objects
Implement IOCTLs for sharing dxgresource and dxgsyncobject objects between processes in the virtual machine. Resources and sync objects are shared using FD (file descriptor) 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 object in WDDM API calls, the object needs to be opened using its FD handle. An object could be opened by the following ioctls: LX_DXOPENRESOURCEFROMNTHANDLE, LX_DXOPENSYNCOBJECTFROMNTHANDLE2. LX_DXQUERYRESOURCEINFOFROMNTHANDLE 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 LX_DXOPENRESOURCEFROMNTHANDLE. Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
1 parent 2717c5f commit 518f7d2

2 files changed

Lines changed: 1123 additions & 3 deletions

File tree

drivers/hv/dxgkrnl/dxgvmbus.c

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,142 @@ int dxgvmb_send_destroy_process(struct d3dkmthandle process)
710710
return ret;
711711
}
712712

713+
int dxgvmb_send_open_sync_object_nt(struct dxgprocess *process,
714+
struct dxgvmbuschannel *channel,
715+
struct d3dkmt_opensyncobjectfromnthandle2
716+
*args,
717+
struct dxgsyncobject *syncobj)
718+
{
719+
struct dxgkvmb_command_opensyncobject *command;
720+
struct dxgkvmb_command_opensyncobject_return result = { };
721+
int ret;
722+
struct dxgvmbusmsg msg;
723+
724+
ret = init_message(&msg, NULL, process, sizeof(*command));
725+
if (ret)
726+
return ret;
727+
command = (void *)msg.msg;
728+
729+
command_vm_to_host_init2(&command->hdr, DXGK_VMBCOMMAND_OPENSYNCOBJECT,
730+
process->host_handle);
731+
command->device = args->device;
732+
command->global_sync_object = syncobj->shared_owner->host_shared_handle;
733+
command->flags = args->flags;
734+
if (syncobj->monitored_fence)
735+
command->engine_affinity =
736+
args->monitored_fence.engine_affinity;
737+
738+
ret = dxgglobal_acquire_channel_lock();
739+
if (ret < 0)
740+
goto cleanup;
741+
742+
ret = dxgvmb_send_sync_msg(channel, msg.hdr, msg.size,
743+
&result, sizeof(result));
744+
745+
dxgglobal_release_channel_lock();
746+
747+
if (ret < 0)
748+
goto cleanup;
749+
750+
ret = ntstatus2int(result.status);
751+
if (ret < 0)
752+
goto cleanup;
753+
754+
args->sync_object = result.sync_object;
755+
if (syncobj->monitored_fence) {
756+
void *va = dxg_map_iospace(result.guest_cpu_physical_address,
757+
PAGE_SIZE, PROT_READ | PROT_WRITE,
758+
true);
759+
if (va == NULL) {
760+
ret = -ENOMEM;
761+
goto cleanup;
762+
}
763+
args->monitored_fence.fence_value_cpu_va = va;
764+
args->monitored_fence.fence_value_gpu_va =
765+
result.gpu_virtual_address;
766+
syncobj->mapped_address = va;
767+
}
768+
769+
cleanup:
770+
free_message(&msg, process);
771+
if (ret)
772+
dev_dbg(dxgglobaldev, "err: %s %d", __func__, ret);
773+
return ret;
774+
}
775+
776+
int dxgvmb_send_create_nt_shared_object(struct dxgprocess *process,
777+
struct d3dkmthandle object,
778+
struct d3dkmthandle *shared_handle)
779+
{
780+
struct dxgkvmb_command_createntsharedobject *command;
781+
int ret;
782+
struct dxgvmbusmsg msg;
783+
784+
ret = init_message(&msg, NULL, process, sizeof(*command));
785+
if (ret)
786+
return ret;
787+
command = (void *)msg.msg;
788+
789+
command_vm_to_host_init2(&command->hdr,
790+
DXGK_VMBCOMMAND_CREATENTSHAREDOBJECT,
791+
process->host_handle);
792+
command->object = object;
793+
794+
ret = dxgglobal_acquire_channel_lock();
795+
if (ret < 0)
796+
goto cleanup;
797+
798+
ret = dxgvmb_send_sync_msg(dxgglobal_get_dxgvmbuschannel(),
799+
msg.hdr, msg.size, shared_handle,
800+
sizeof(*shared_handle));
801+
802+
dxgglobal_release_channel_lock();
803+
804+
if (ret < 0)
805+
goto cleanup;
806+
if (shared_handle->v == 0) {
807+
pr_err("failed to create NT shared object");
808+
ret = -ENOTRECOVERABLE;
809+
}
810+
811+
cleanup:
812+
free_message(&msg, process);
813+
if (ret)
814+
dev_dbg(dxgglobaldev, "err: %s %d", __func__, ret);
815+
return ret;
816+
}
817+
818+
int dxgvmb_send_destroy_nt_shared_object(struct d3dkmthandle shared_handle)
819+
{
820+
struct dxgkvmb_command_destroyntsharedobject *command;
821+
int ret;
822+
struct dxgvmbusmsg msg;
823+
824+
ret = init_message(&msg, NULL, NULL, sizeof(*command));
825+
if (ret)
826+
return ret;
827+
command = (void *)msg.msg;
828+
829+
command_vm_to_host_init1(&command->hdr,
830+
DXGK_VMBCOMMAND_DESTROYNTSHAREDOBJECT);
831+
command->shared_handle = shared_handle;
832+
833+
ret = dxgglobal_acquire_channel_lock();
834+
if (ret < 0)
835+
goto cleanup;
836+
837+
ret = dxgvmb_send_sync_msg_ntstatus(dxgglobal_get_dxgvmbuschannel(),
838+
msg.hdr, msg.size);
839+
840+
dxgglobal_release_channel_lock();
841+
842+
cleanup:
843+
free_message(&msg, NULL);
844+
if (ret)
845+
dev_dbg(dxgglobaldev, "err: %s %d", __func__, ret);
846+
return ret;
847+
}
848+
713849
int dxgvmb_send_destroy_sync_object(struct dxgprocess *process,
714850
struct d3dkmthandle sync_object)
715851
{
@@ -1515,6 +1651,60 @@ int dxgvmb_send_destroy_allocation(struct dxgprocess *process,
15151651
return ret;
15161652
}
15171653

1654+
int dxgvmb_send_open_resource(struct dxgprocess *process,
1655+
struct dxgadapter *adapter,
1656+
struct d3dkmthandle device,
1657+
struct d3dkmthandle global_share,
1658+
u32 allocation_count,
1659+
u32 total_priv_drv_data_size,
1660+
struct d3dkmthandle *resource_handle,
1661+
struct d3dkmthandle *alloc_handles)
1662+
{
1663+
struct dxgkvmb_command_openresource *command;
1664+
struct dxgkvmb_command_openresource_return *result;
1665+
struct d3dkmthandle *handles;
1666+
int ret;
1667+
int i;
1668+
u32 result_size = allocation_count * sizeof(struct d3dkmthandle) +
1669+
sizeof(*result);
1670+
struct dxgvmbusmsgres msg = {.hdr = NULL};
1671+
1672+
ret = init_message_res(&msg, adapter, process, sizeof(*command),
1673+
result_size);
1674+
if (ret)
1675+
goto cleanup;
1676+
command = msg.msg;
1677+
result = msg.res;
1678+
1679+
command_vgpu_to_host_init2(&command->hdr, DXGK_VMBCOMMAND_OPENRESOURCE,
1680+
process->host_handle);
1681+
command->device = device;
1682+
command->nt_security_sharing = 1;
1683+
command->global_share = global_share;
1684+
command->allocation_count = allocation_count;
1685+
command->total_priv_drv_data_size = total_priv_drv_data_size;
1686+
1687+
ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
1688+
result, msg.res_size);
1689+
if (ret < 0)
1690+
goto cleanup;
1691+
1692+
ret = ntstatus2int(result->status);
1693+
if (ret < 0)
1694+
goto cleanup;
1695+
1696+
*resource_handle = result->resource;
1697+
handles = (struct d3dkmthandle *) &result[1];
1698+
for (i = 0; i < allocation_count; i++)
1699+
alloc_handles[i] = handles[i];
1700+
1701+
cleanup:
1702+
free_message((struct dxgvmbusmsg *)&msg, process);
1703+
if (ret)
1704+
dev_dbg(dxgglobaldev, "err: %s %d", __func__, ret);
1705+
return ret;
1706+
}
1707+
15181708
int dxgvmb_send_get_stdalloc_data(struct dxgdevice *device,
15191709
enum d3dkmdt_standardallocationtype alloctype,
15201710
struct d3dkmdt_gdisurfacedata *alloc_data,

0 commit comments

Comments
 (0)