Skip to content

Commit 601638b

Browse files
author
Iouri Tarassov
committed
drivers: hv: dxgkrnl: Implement operations with GPU sync objects
GPU synchronization objects are used to synchornize GPU command execution between different execution contexts. A wait for a sync object could be submitted to a GPU context (thread) or could be done on CPU. The wait is satisfied when the sync object is signaled. The signal operation could be submitted to a GPU context (thread) or could be signaled by a CPU thread. Implement the following ioctls: LX_DXCREATESYNCHRONIZATIONOBJECT, LX_DXSIGNALSYNCHRONIZATIONOBJECT, LX_DXWAITFORSYNCHRONIZATIONOBJECT, LX_DXDESTROYSYNCHRONIZATIONOBJECT, LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMCPU, LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMGPU, LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMGPU2, LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMCPU, LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMGPU. Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
1 parent 909d70f commit 601638b

4 files changed

Lines changed: 1541 additions & 12 deletions

File tree

drivers/hv/dxgkrnl/dxgadapter.c

Lines changed: 273 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,55 @@ void dxgadapter_remove_process(struct dxgprocess_adapter *process_info)
167167
process_info->adapter_process_list_entry.prev = NULL;
168168
}
169169

170+
void dxgadapter_remove_shared_resource(struct dxgadapter *adapter,
171+
struct dxgsharedresource *object)
172+
{
173+
down_write(&adapter->shared_resource_list_lock);
174+
if (object->shared_resource_list_entry.next) {
175+
list_del(&object->shared_resource_list_entry);
176+
object->shared_resource_list_entry.next = NULL;
177+
}
178+
up_write(&adapter->shared_resource_list_lock);
179+
}
180+
181+
void dxgadapter_add_shared_syncobj(struct dxgadapter *adapter,
182+
struct dxgsharedsyncobject *object)
183+
{
184+
down_write(&adapter->shared_resource_list_lock);
185+
list_add_tail(&object->adapter_shared_syncobj_list_entry,
186+
&adapter->adapter_shared_syncobj_list_head);
187+
up_write(&adapter->shared_resource_list_lock);
188+
}
189+
190+
void dxgadapter_remove_shared_syncobj(struct dxgadapter *adapter,
191+
struct dxgsharedsyncobject *object)
192+
{
193+
down_write(&adapter->shared_resource_list_lock);
194+
if (object->adapter_shared_syncobj_list_entry.next) {
195+
list_del(&object->adapter_shared_syncobj_list_entry);
196+
object->adapter_shared_syncobj_list_entry.next = NULL;
197+
}
198+
up_write(&adapter->shared_resource_list_lock);
199+
}
200+
201+
void dxgadapter_add_syncobj(struct dxgadapter *adapter,
202+
struct dxgsyncobject *object)
203+
{
204+
down_write(&adapter->shared_resource_list_lock);
205+
list_add_tail(&object->syncobj_list_entry, &adapter->syncobj_list_head);
206+
up_write(&adapter->shared_resource_list_lock);
207+
}
208+
209+
void dxgadapter_remove_syncobj(struct dxgsyncobject *object)
210+
{
211+
down_write(&object->adapter->shared_resource_list_lock);
212+
if (object->syncobj_list_entry.next) {
213+
list_del(&object->syncobj_list_entry);
214+
object->syncobj_list_entry.next = NULL;
215+
}
216+
up_write(&object->adapter->shared_resource_list_lock);
217+
}
218+
170219
int dxgadapter_acquire_lock_exclusive(struct dxgadapter *adapter)
171220
{
172221
down_write(&adapter->core_lock);
@@ -679,6 +728,30 @@ void dxgdevice_release(struct kref *refcount)
679728
vfree(device);
680729
}
681730

731+
void dxgdevice_add_syncobj(struct dxgdevice *device,
732+
struct dxgsyncobject *syncobj)
733+
{
734+
dxgdevice_acquire_alloc_list_lock(device);
735+
list_add_tail(&syncobj->syncobj_list_entry, &device->syncobj_list_head);
736+
kref_get(&syncobj->syncobj_kref);
737+
dxgdevice_release_alloc_list_lock(device);
738+
}
739+
740+
void dxgdevice_remove_syncobj(struct dxgsyncobject *entry)
741+
{
742+
struct dxgdevice *device = entry->device;
743+
744+
dxgdevice_acquire_alloc_list_lock(device);
745+
if (entry->syncobj_list_entry.next) {
746+
list_del(&entry->syncobj_list_entry);
747+
entry->syncobj_list_entry.next = NULL;
748+
kref_put(&entry->syncobj_kref, dxgsyncobject_release);
749+
}
750+
dxgdevice_release_alloc_list_lock(device);
751+
kref_put(&device->device_kref, dxgdevice_release);
752+
entry->device = NULL;
753+
}
754+
682755
struct dxgcontext *dxgcontext_create(struct dxgdevice *device)
683756
{
684757
struct dxgcontext *context = vzalloc(sizeof(struct dxgcontext));
@@ -934,28 +1007,221 @@ void dxgprocess_adapter_remove_device(struct dxgdevice *device)
9341007
mutex_unlock(&device->adapter_info->device_list_mutex);
9351008
}
9361009

937-
void dxghwqueue_destroy(struct dxgprocess *process, struct dxghwqueue *hwqueue)
1010+
struct dxgsharedsyncobject *dxgsharedsyncobj_create(struct dxgadapter *adapter,
1011+
struct dxgsyncobject *so)
9381012
{
939-
/* Placeholder */
1013+
struct dxgsharedsyncobject *syncobj;
1014+
1015+
syncobj = vzalloc(sizeof(*syncobj));
1016+
if (syncobj) {
1017+
kref_init(&syncobj->ssyncobj_kref);
1018+
INIT_LIST_HEAD(&syncobj->shared_syncobj_list_head);
1019+
syncobj->adapter = adapter;
1020+
syncobj->type = so->type;
1021+
syncobj->monitored_fence = so->monitored_fence;
1022+
dxgadapter_add_shared_syncobj(adapter, syncobj);
1023+
kref_get(&adapter->adapter_kref);
1024+
init_rwsem(&syncobj->syncobj_list_lock);
1025+
mutex_init(&syncobj->fd_mutex);
1026+
}
1027+
return syncobj;
9401028
}
9411029

942-
void dxgpagingqueue_destroy(struct dxgpagingqueue *pqueue)
1030+
void dxgsharedsyncobj_release(struct kref *refcount)
9431031
{
944-
/* Placeholder */
1032+
struct dxgsharedsyncobject *syncobj;
1033+
1034+
syncobj = container_of(refcount, struct dxgsharedsyncobject,
1035+
ssyncobj_kref);
1036+
dev_dbg(dxgglobaldev, "Destroying shared sync object %p", syncobj);
1037+
if (syncobj->adapter) {
1038+
dxgadapter_remove_shared_syncobj(syncobj->adapter,
1039+
syncobj);
1040+
kref_put(&syncobj->adapter->adapter_kref,
1041+
dxgadapter_release);
1042+
}
1043+
vfree(syncobj);
9451044
}
9461045

947-
void dxgpagingqueue_stop(struct dxgpagingqueue *pqueue)
1046+
void dxgsharedsyncobj_add_syncobj(struct dxgsharedsyncobject *shared,
1047+
struct dxgsyncobject *syncobj)
9481048
{
949-
/* Placeholder */
1049+
dev_dbg(dxgglobaldev, "%s 0x%p 0x%p", __func__, shared, syncobj);
1050+
kref_get(&shared->ssyncobj_kref);
1051+
down_write(&shared->syncobj_list_lock);
1052+
list_add(&syncobj->shared_syncobj_list_entry,
1053+
&shared->shared_syncobj_list_head);
1054+
syncobj->shared_owner = shared;
1055+
up_write(&shared->syncobj_list_lock);
1056+
}
1057+
1058+
void dxgsharedsyncobj_remove_syncobj(struct dxgsharedsyncobject *shared,
1059+
struct dxgsyncobject *syncobj)
1060+
{
1061+
dev_dbg(dxgglobaldev, "%s 0x%p", __func__, shared);
1062+
down_write(&shared->syncobj_list_lock);
1063+
list_del(&syncobj->shared_syncobj_list_entry);
1064+
up_write(&shared->syncobj_list_lock);
1065+
}
1066+
1067+
struct dxgsyncobject *dxgsyncobject_create(struct dxgprocess *process,
1068+
struct dxgdevice *device,
1069+
struct dxgadapter *adapter,
1070+
enum
1071+
d3dddi_synchronizationobject_type
1072+
type,
1073+
struct
1074+
d3dddi_synchronizationobject_flags
1075+
flags)
1076+
{
1077+
struct dxgsyncobject *syncobj;
1078+
1079+
syncobj = vzalloc(sizeof(*syncobj));
1080+
if (syncobj == NULL)
1081+
goto cleanup;
1082+
syncobj->type = type;
1083+
syncobj->process = process;
1084+
switch (type) {
1085+
case _D3DDDI_MONITORED_FENCE:
1086+
case _D3DDDI_PERIODIC_MONITORED_FENCE:
1087+
syncobj->monitored_fence = 1;
1088+
break;
1089+
case _D3DDDI_CPU_NOTIFICATION:
1090+
syncobj->cpu_event = 1;
1091+
syncobj->host_event = vzalloc(sizeof(struct dxghostevent));
1092+
if (syncobj->host_event == NULL)
1093+
goto cleanup;
1094+
break;
1095+
default:
1096+
break;
1097+
}
1098+
if (flags.shared) {
1099+
syncobj->shared = 1;
1100+
if (!flags.nt_security_sharing) {
1101+
dev_err(dxgglobaldev,
1102+
"%s: nt_security_sharing must be set",
1103+
__func__);
1104+
goto cleanup;
1105+
}
1106+
}
1107+
1108+
kref_init(&syncobj->syncobj_kref);
1109+
1110+
if (syncobj->monitored_fence) {
1111+
syncobj->device = device;
1112+
syncobj->device_handle = device->handle;
1113+
kref_get(&device->device_kref);
1114+
dxgdevice_add_syncobj(device, syncobj);
1115+
} else {
1116+
dxgadapter_add_syncobj(adapter, syncobj);
1117+
}
1118+
syncobj->adapter = adapter;
1119+
kref_get(&adapter->adapter_kref);
1120+
1121+
dev_dbg(dxgglobaldev, "%s 0x%p\n", __func__, syncobj);
1122+
return syncobj;
1123+
cleanup:
1124+
if (syncobj->host_event)
1125+
vfree(syncobj->host_event);
1126+
if (syncobj)
1127+
vfree(syncobj);
1128+
return NULL;
9501129
}
9511130

9521131
void dxgsyncobject_destroy(struct dxgprocess *process,
9531132
struct dxgsyncobject *syncobj)
9541133
{
955-
/* Placeholder */
1134+
int destroyed;
1135+
struct dxghosteventcpu *host_event;
1136+
1137+
dev_dbg(dxgglobaldev, "%s 0x%p", __func__, syncobj);
1138+
1139+
dxgsyncobject_stop(syncobj);
1140+
1141+
destroyed = test_and_set_bit(0, &syncobj->flags);
1142+
if (!destroyed) {
1143+
dev_dbg(dxgglobaldev, "Deleting handle: %x", syncobj->handle.v);
1144+
hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL);
1145+
if (syncobj->handle.v) {
1146+
hmgrtable_free_handle(&process->handle_table,
1147+
HMGRENTRY_TYPE_DXGSYNCOBJECT,
1148+
syncobj->handle);
1149+
syncobj->handle.v = 0;
1150+
kref_put(&syncobj->syncobj_kref, dxgsyncobject_release);
1151+
}
1152+
hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
1153+
1154+
if (syncobj->cpu_event) {
1155+
host_event = syncobj->host_event;
1156+
if (host_event->cpu_event) {
1157+
eventfd_ctx_put(host_event->cpu_event);
1158+
if (host_event->hdr.event_id)
1159+
dxgglobal_remove_host_event(
1160+
&host_event->hdr);
1161+
host_event->cpu_event = NULL;
1162+
}
1163+
}
1164+
if (syncobj->monitored_fence)
1165+
dxgdevice_remove_syncobj(syncobj);
1166+
else
1167+
dxgadapter_remove_syncobj(syncobj);
1168+
if (syncobj->adapter) {
1169+
kref_put(&syncobj->adapter->adapter_kref,
1170+
dxgadapter_release);
1171+
syncobj->adapter = NULL;
1172+
}
1173+
}
1174+
kref_put(&syncobj->syncobj_kref, dxgsyncobject_release);
9561175
}
9571176

9581177
void dxgsyncobject_stop(struct dxgsyncobject *syncobj)
1178+
{
1179+
int stopped = test_and_set_bit(1, &syncobj->flags);
1180+
1181+
if (!stopped) {
1182+
dev_dbg(dxgglobaldev, "stopping");
1183+
if (syncobj->monitored_fence) {
1184+
if (syncobj->mapped_address) {
1185+
int ret =
1186+
dxg_unmap_iospace(syncobj->mapped_address,
1187+
PAGE_SIZE);
1188+
1189+
(void)ret;
1190+
dev_dbg(dxgglobaldev, "fence is unmapped %d %p\n",
1191+
ret, syncobj->mapped_address);
1192+
syncobj->mapped_address = NULL;
1193+
}
1194+
}
1195+
}
1196+
}
1197+
1198+
void dxgsyncobject_release(struct kref *refcount)
1199+
{
1200+
struct dxgsyncobject *syncobj;
1201+
1202+
syncobj = container_of(refcount, struct dxgsyncobject, syncobj_kref);
1203+
if (syncobj->shared_owner) {
1204+
dxgsharedsyncobj_remove_syncobj(syncobj->shared_owner,
1205+
syncobj);
1206+
kref_put(&syncobj->shared_owner->ssyncobj_kref,
1207+
dxgsharedsyncobj_release);
1208+
}
1209+
if (syncobj->host_event)
1210+
vfree(syncobj->host_event);
1211+
vfree(syncobj);
1212+
}
1213+
1214+
void dxghwqueue_destroy(struct dxgprocess *process, struct dxghwqueue *hwqueue)
1215+
{
1216+
/* Placeholder */
1217+
}
1218+
1219+
void dxgpagingqueue_destroy(struct dxgpagingqueue *pqueue)
1220+
{
1221+
/* Placeholder */
1222+
}
1223+
1224+
void dxgpagingqueue_stop(struct dxgpagingqueue *pqueue)
9591225
{
9601226
/* Placeholder */
9611227
}

drivers/hv/dxgkrnl/dxgkrnl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ struct dxgpagingqueue {
9999
* a message from host.
100100
*/
101101
enum dxghosteventtype {
102-
dxghostevent_cpu_event,
103-
dxghostevent_dma_fence
102+
dxghostevent_cpu_event = 1,
103+
dxghostevent_dma_fence = 2
104104
};
105105

106106
struct dxghostevent {

0 commit comments

Comments
 (0)