Skip to content

Commit 97febe8

Browse files
author
Iouri Tarassov
committed
drivers: hv: dxgkrnl: Implement sharing resources and sync objects
Resources and sync objects could be shared using 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. The handle could be opened only by dxgkrnl ioctls: LX_DXOPENRESOURCEFROMNTHANDLE, LX_DXOPENSYNCOBJECTFROMNTHANDLE2. LX_DXQUERYRESOURCEINFOFROMNTHANDLE is used to query private driver data of a shared resource object. Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
1 parent 601638b commit 97febe8

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
@@ -686,6 +686,142 @@ int dxgvmb_send_destroy_process(struct d3dkmthandle process)
686686
return ret;
687687
}
688688

689+
int dxgvmb_send_open_sync_object_nt(struct dxgprocess *process,
690+
struct dxgvmbuschannel *channel,
691+
struct d3dkmt_opensyncobjectfromnthandle2
692+
*args,
693+
struct dxgsyncobject *syncobj)
694+
{
695+
struct dxgkvmb_command_opensyncobject *command;
696+
struct dxgkvmb_command_opensyncobject_return result = { };
697+
int ret;
698+
struct dxgvmbusmsg msg;
699+
700+
ret = init_message(&msg, NULL, process, sizeof(*command));
701+
if (ret)
702+
return ret;
703+
command = (void *)msg.msg;
704+
705+
command_vm_to_host_init2(&command->hdr, DXGK_VMBCOMMAND_OPENSYNCOBJECT,
706+
process->host_handle);
707+
command->device = args->device;
708+
command->global_sync_object = syncobj->shared_owner->host_shared_handle;
709+
command->flags = args->flags;
710+
if (syncobj->monitored_fence)
711+
command->engine_affinity =
712+
args->monitored_fence.engine_affinity;
713+
714+
ret = dxgglobal_acquire_channel_lock();
715+
if (ret < 0)
716+
goto cleanup;
717+
718+
ret = dxgvmb_send_sync_msg(channel, msg.hdr, msg.size,
719+
&result, sizeof(result));
720+
721+
dxgglobal_release_channel_lock();
722+
723+
if (ret < 0)
724+
goto cleanup;
725+
726+
ret = ntstatus2int(result.status);
727+
if (ret < 0)
728+
goto cleanup;
729+
730+
args->sync_object = result.sync_object;
731+
if (syncobj->monitored_fence) {
732+
void *va = dxg_map_iospace(result.guest_cpu_physical_address,
733+
PAGE_SIZE, PROT_READ | PROT_WRITE,
734+
true);
735+
if (va == NULL) {
736+
ret = -ENOMEM;
737+
goto cleanup;
738+
}
739+
args->monitored_fence.fence_value_cpu_va = va;
740+
args->monitored_fence.fence_value_gpu_va =
741+
result.gpu_virtual_address;
742+
syncobj->mapped_address = va;
743+
}
744+
745+
cleanup:
746+
free_message(&msg, process);
747+
if (ret)
748+
dev_dbg(dxgglobaldev, "err: %s %d", __func__, ret);
749+
return ret;
750+
}
751+
752+
int dxgvmb_send_create_nt_shared_object(struct dxgprocess *process,
753+
struct d3dkmthandle object,
754+
struct d3dkmthandle *shared_handle)
755+
{
756+
struct dxgkvmb_command_createntsharedobject *command;
757+
int ret;
758+
struct dxgvmbusmsg msg;
759+
760+
ret = init_message(&msg, NULL, process, sizeof(*command));
761+
if (ret)
762+
return ret;
763+
command = (void *)msg.msg;
764+
765+
command_vm_to_host_init2(&command->hdr,
766+
DXGK_VMBCOMMAND_CREATENTSHAREDOBJECT,
767+
process->host_handle);
768+
command->object = object;
769+
770+
ret = dxgglobal_acquire_channel_lock();
771+
if (ret < 0)
772+
goto cleanup;
773+
774+
ret = dxgvmb_send_sync_msg(dxgglobal_get_dxgvmbuschannel(),
775+
msg.hdr, msg.size, shared_handle,
776+
sizeof(*shared_handle));
777+
778+
dxgglobal_release_channel_lock();
779+
780+
if (ret < 0)
781+
goto cleanup;
782+
if (shared_handle->v == 0) {
783+
pr_err("failed to create NT shared object");
784+
ret = -ENOTRECOVERABLE;
785+
}
786+
787+
cleanup:
788+
free_message(&msg, process);
789+
if (ret)
790+
dev_dbg(dxgglobaldev, "err: %s %d", __func__, ret);
791+
return ret;
792+
}
793+
794+
int dxgvmb_send_destroy_nt_shared_object(struct d3dkmthandle shared_handle)
795+
{
796+
struct dxgkvmb_command_destroyntsharedobject *command;
797+
int ret;
798+
struct dxgvmbusmsg msg;
799+
800+
ret = init_message(&msg, NULL, NULL, sizeof(*command));
801+
if (ret)
802+
return ret;
803+
command = (void *)msg.msg;
804+
805+
command_vm_to_host_init1(&command->hdr,
806+
DXGK_VMBCOMMAND_DESTROYNTSHAREDOBJECT);
807+
command->shared_handle = shared_handle;
808+
809+
ret = dxgglobal_acquire_channel_lock();
810+
if (ret < 0)
811+
goto cleanup;
812+
813+
ret = dxgvmb_send_sync_msg_ntstatus(dxgglobal_get_dxgvmbuschannel(),
814+
msg.hdr, msg.size);
815+
816+
dxgglobal_release_channel_lock();
817+
818+
cleanup:
819+
free_message(&msg, NULL);
820+
if (ret)
821+
dev_dbg(dxgglobaldev, "err: %s %d", __func__, ret);
822+
return ret;
823+
}
824+
689825
int dxgvmb_send_destroy_sync_object(struct dxgprocess *process,
690826
struct d3dkmthandle sync_object)
691827
{
@@ -1491,6 +1627,60 @@ int dxgvmb_send_destroy_allocation(struct dxgprocess *process,
14911627
return ret;
14921628
}
14931629

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

0 commit comments

Comments
 (0)