Skip to content

Commit 2717c5f

Browse files
author
Iouri Tarassov
committed
drivers: hv: dxgkrnl: Implement operations with GPU sync objects
Implement ioctls for using GPU synchronization objects: LX_DXCREATESYNCHRONIZATIONOBJECT, LX_DXSIGNALSYNCHRONIZATIONOBJECT, LX_DXWAITFORSYNCHRONIZATIONOBJECT, LX_DXDESTROYSYNCHRONIZATIONOBJECT, LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMCPU, LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMGPU, LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMGPU2, LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMCPU, LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMGPU. 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. The driver creates the corresponsing tracking structures and sends VM bus messages to the host to do the corresponding operation. When a caller needs to wait for a sync object on CPU, an event structure is added to the global list (dxgglobal->host_event_list_head). Each list entry has an ID and a pointer to the event to signal. When the sync object is signaled on the host, the host sends a message to the guest with the event ID to signal. dxgglobal_signal_host_event() processes this message and signals the corresponding CPU event. Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
1 parent db6038b commit 2717c5f

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);
@@ -680,6 +729,30 @@ void dxgdevice_release(struct kref *refcount)
680729
vfree(device);
681730
}
682731

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

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

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

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

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

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

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)