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