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 */
uuid_equal_func(const void * lhv,const void * rhv)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
virtio_add_resource(QemuUUID * uuid,VirtioSharedObject * value)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
virtio_add_dmabuf(QemuUUID * uuid,int udmabuf_fd)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
virtio_add_vhost_device(QemuUUID * uuid,struct vhost_dev * dev)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
virtio_remove_resource(const QemuUUID * uuid)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
get_shared_object(const QemuUUID * uuid)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
virtio_lookup_dmabuf(const QemuUUID * uuid)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
virtio_lookup_vhost_device(const QemuUUID * uuid)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
virtio_object_type(const QemuUUID * uuid)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
virtio_free_resources(void)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