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