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