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