1 /* 2 * Virtio Shared dma-buf 3 * 4 * Copyright Red Hat, Inc. 2023 5 * 6 * Authors: 7 * Albert Esteve <aesteve@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 15 #include "hw/virtio/virtio-dmabuf.h" 16 17 18 static GMutex lock; 19 static GHashTable *resource_uuids; 20 21 /* 22 * uuid_equal_func: wrapper for UUID is_equal function to 23 * satisfy g_hash_table_new expected parameters signatures. 24 */ 25 static int uuid_equal_func(const void *lhv, const void *rhv) 26 { 27 return qemu_uuid_is_equal(lhv, rhv); 28 } 29 30 static bool virtio_add_resource(QemuUUID *uuid, VirtioSharedObject *value) 31 { 32 bool result = true; 33 34 g_mutex_lock(&lock); 35 if (resource_uuids == NULL) { 36 resource_uuids = g_hash_table_new_full(qemu_uuid_hash, 37 uuid_equal_func, 38 NULL, 39 g_free); 40 } 41 if (g_hash_table_lookup(resource_uuids, uuid) == NULL) { 42 g_hash_table_insert(resource_uuids, uuid, value); 43 } else { 44 result = false; 45 } 46 g_mutex_unlock(&lock); 47 48 return result; 49 } 50 51 bool virtio_add_dmabuf(QemuUUID *uuid, int udmabuf_fd) 52 { 53 bool result; 54 VirtioSharedObject *vso; 55 if (udmabuf_fd < 0) { 56 return false; 57 } 58 vso = g_new(VirtioSharedObject, 1); 59 vso->type = TYPE_DMABUF; 60 vso->value = GINT_TO_POINTER(udmabuf_fd); 61 result = virtio_add_resource(uuid, vso); 62 if (!result) { 63 g_free(vso); 64 } 65 66 return result; 67 } 68 69 bool virtio_add_vhost_device(QemuUUID *uuid, struct vhost_dev *dev) 70 { 71 bool result; 72 VirtioSharedObject *vso; 73 if (dev == NULL) { 74 return false; 75 } 76 vso = g_new(VirtioSharedObject, 1); 77 vso->type = TYPE_VHOST_DEV; 78 vso->value = dev; 79 result = virtio_add_resource(uuid, vso); 80 if (!result) { 81 g_free(vso); 82 } 83 84 return result; 85 } 86 87 bool virtio_remove_resource(const QemuUUID *uuid) 88 { 89 bool result; 90 g_mutex_lock(&lock); 91 result = g_hash_table_remove(resource_uuids, uuid); 92 g_mutex_unlock(&lock); 93 94 return result; 95 } 96 97 static VirtioSharedObject *get_shared_object(const QemuUUID *uuid) 98 { 99 gpointer lookup_res = NULL; 100 101 g_mutex_lock(&lock); 102 if (resource_uuids != NULL) { 103 lookup_res = g_hash_table_lookup(resource_uuids, uuid); 104 } 105 g_mutex_unlock(&lock); 106 107 return (VirtioSharedObject *) lookup_res; 108 } 109 110 int virtio_lookup_dmabuf(const QemuUUID *uuid) 111 { 112 VirtioSharedObject *vso = get_shared_object(uuid); 113 if (vso == NULL) { 114 return -1; 115 } 116 assert(vso->type == TYPE_DMABUF); 117 return GPOINTER_TO_INT(vso->value); 118 } 119 120 struct vhost_dev *virtio_lookup_vhost_device(const QemuUUID *uuid) 121 { 122 VirtioSharedObject *vso = get_shared_object(uuid); 123 if (vso == NULL) { 124 return NULL; 125 } 126 assert(vso->type == TYPE_VHOST_DEV); 127 return (struct vhost_dev *) vso->value; 128 } 129 130 SharedObjectType virtio_object_type(const QemuUUID *uuid) 131 { 132 VirtioSharedObject *vso = get_shared_object(uuid); 133 if (vso == NULL) { 134 return TYPE_INVALID; 135 } 136 return vso->type; 137 } 138 139 void virtio_free_resources(void) 140 { 141 g_mutex_lock(&lock); 142 g_hash_table_destroy(resource_uuids); 143 /* Reference count shall be 0 after the implicit unref on destroy */ 144 resource_uuids = NULL; 145 g_mutex_unlock(&lock); 146 } 147