xref: /qemu/hw/display/virtio-dmabuf.c (revision 8b7b9c5c)
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