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 = false; 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 result = g_hash_table_insert(resource_uuids, uuid, value); 43 } 44 g_mutex_unlock(&lock); 45 46 return result; 47 } 48 49 bool virtio_add_dmabuf(QemuUUID *uuid, int udmabuf_fd) 50 { 51 bool result; 52 VirtioSharedObject *vso; 53 if (udmabuf_fd < 0) { 54 return false; 55 } 56 vso = g_new(VirtioSharedObject, 1); 57 vso->type = TYPE_DMABUF; 58 vso->value = GINT_TO_POINTER(udmabuf_fd); 59 result = virtio_add_resource(uuid, vso); 60 61 return result; 62 } 63 64 bool virtio_add_vhost_device(QemuUUID *uuid, struct vhost_dev *dev) 65 { 66 bool result; 67 VirtioSharedObject *vso; 68 if (dev == NULL) { 69 return false; 70 } 71 vso = g_new(VirtioSharedObject, 1); 72 vso->type = TYPE_VHOST_DEV; 73 vso->value = dev; 74 result = virtio_add_resource(uuid, vso); 75 76 return result; 77 } 78 79 bool virtio_remove_resource(const QemuUUID *uuid) 80 { 81 bool result; 82 g_mutex_lock(&lock); 83 result = g_hash_table_remove(resource_uuids, uuid); 84 g_mutex_unlock(&lock); 85 86 return result; 87 } 88 89 static VirtioSharedObject *get_shared_object(const QemuUUID *uuid) 90 { 91 gpointer lookup_res = NULL; 92 93 g_mutex_lock(&lock); 94 if (resource_uuids != NULL) { 95 lookup_res = g_hash_table_lookup(resource_uuids, uuid); 96 } 97 g_mutex_unlock(&lock); 98 99 return (VirtioSharedObject *) lookup_res; 100 } 101 102 int virtio_lookup_dmabuf(const QemuUUID *uuid) 103 { 104 VirtioSharedObject *vso = get_shared_object(uuid); 105 if (vso == NULL) { 106 return -1; 107 } 108 assert(vso->type == TYPE_DMABUF); 109 return GPOINTER_TO_INT(vso->value); 110 } 111 112 struct vhost_dev *virtio_lookup_vhost_device(const QemuUUID *uuid) 113 { 114 VirtioSharedObject *vso = get_shared_object(uuid); 115 if (vso == NULL) { 116 return NULL; 117 } 118 assert(vso->type == TYPE_VHOST_DEV); 119 return (struct vhost_dev *) vso->value; 120 } 121 122 SharedObjectType virtio_object_type(const QemuUUID *uuid) 123 { 124 VirtioSharedObject *vso = get_shared_object(uuid); 125 if (vso == NULL) { 126 return TYPE_INVALID; 127 } 128 return vso->type; 129 } 130 131 void virtio_free_resources(void) 132 { 133 g_mutex_lock(&lock); 134 g_hash_table_destroy(resource_uuids); 135 /* Reference count shall be 0 after the implicit unref on destroy */ 136 resource_uuids = NULL; 137 g_mutex_unlock(&lock); 138 } 139