xref: /qemu/hw/vfio-user/proxy.c (revision 438d863f1f40fbc2b57bf94cc6c998a6445c0932)
1 /*
2  * vfio protocol over a UNIX socket.
3  *
4  * Copyright © 2018, 2021 Oracle and/or its affiliates.
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include "qemu/osdep.h"
10 #include <sys/ioctl.h>
11 
12 #include "hw/vfio/vfio-device.h"
13 #include "hw/vfio-user/proxy.h"
14 #include "qapi/error.h"
15 #include "qemu/error-report.h"
16 #include "qemu/lockable.h"
17 #include "system/iothread.h"
18 
19 static IOThread *vfio_user_iothread;
20 
21 static void vfio_user_shutdown(VFIOUserProxy *proxy);
22 
23 
24 /*
25  * Functions called by main, CPU, or iothread threads
26  */
27 
28 static void vfio_user_shutdown(VFIOUserProxy *proxy)
29 {
30     qio_channel_shutdown(proxy->ioc, QIO_CHANNEL_SHUTDOWN_READ, NULL);
31     qio_channel_set_aio_fd_handler(proxy->ioc, proxy->ctx, NULL,
32                                    proxy->ctx, NULL, NULL);
33 }
34 
35 /*
36  * Functions only called by iothread
37  */
38 
39 static void vfio_user_cb(void *opaque)
40 {
41     VFIOUserProxy *proxy = opaque;
42 
43     QEMU_LOCK_GUARD(&proxy->lock);
44 
45     proxy->state = VFIO_PROXY_CLOSED;
46     qemu_cond_signal(&proxy->close_cv);
47 }
48 
49 
50 /*
51  * Functions called by main or CPU threads
52  */
53 
54 static QLIST_HEAD(, VFIOUserProxy) vfio_user_sockets =
55     QLIST_HEAD_INITIALIZER(vfio_user_sockets);
56 
57 VFIOUserProxy *vfio_user_connect_dev(SocketAddress *addr, Error **errp)
58 {
59     VFIOUserProxy *proxy;
60     QIOChannelSocket *sioc;
61     QIOChannel *ioc;
62     char *sockname;
63 
64     if (addr->type != SOCKET_ADDRESS_TYPE_UNIX) {
65         error_setg(errp, "vfio_user_connect - bad address family");
66         return NULL;
67     }
68     sockname = addr->u.q_unix.path;
69 
70     sioc = qio_channel_socket_new();
71     ioc = QIO_CHANNEL(sioc);
72     if (qio_channel_socket_connect_sync(sioc, addr, errp)) {
73         object_unref(OBJECT(ioc));
74         return NULL;
75     }
76     qio_channel_set_blocking(ioc, false, NULL);
77 
78     proxy = g_malloc0(sizeof(VFIOUserProxy));
79     proxy->sockname = g_strdup_printf("unix:%s", sockname);
80     proxy->ioc = ioc;
81     proxy->flags = VFIO_PROXY_CLIENT;
82     proxy->state = VFIO_PROXY_CONNECTED;
83 
84     qemu_mutex_init(&proxy->lock);
85     qemu_cond_init(&proxy->close_cv);
86 
87     if (vfio_user_iothread == NULL) {
88         vfio_user_iothread = iothread_create("VFIO user", errp);
89     }
90 
91     proxy->ctx = iothread_get_aio_context(vfio_user_iothread);
92 
93     QTAILQ_INIT(&proxy->outgoing);
94     QTAILQ_INIT(&proxy->incoming);
95     QTAILQ_INIT(&proxy->free);
96     QTAILQ_INIT(&proxy->pending);
97     QLIST_INSERT_HEAD(&vfio_user_sockets, proxy, next);
98 
99     return proxy;
100 }
101 
102 void vfio_user_disconnect(VFIOUserProxy *proxy)
103 {
104     VFIOUserMsg *r1, *r2;
105 
106     qemu_mutex_lock(&proxy->lock);
107 
108     /* our side is quitting */
109     if (proxy->state == VFIO_PROXY_CONNECTED) {
110         vfio_user_shutdown(proxy);
111         if (!QTAILQ_EMPTY(&proxy->pending)) {
112             error_printf("vfio_user_disconnect: outstanding requests\n");
113         }
114     }
115     object_unref(OBJECT(proxy->ioc));
116     proxy->ioc = NULL;
117 
118     proxy->state = VFIO_PROXY_CLOSING;
119     QTAILQ_FOREACH_SAFE(r1, &proxy->outgoing, next, r2) {
120         qemu_cond_destroy(&r1->cv);
121         QTAILQ_REMOVE(&proxy->outgoing, r1, next);
122         g_free(r1);
123     }
124     QTAILQ_FOREACH_SAFE(r1, &proxy->incoming, next, r2) {
125         qemu_cond_destroy(&r1->cv);
126         QTAILQ_REMOVE(&proxy->incoming, r1, next);
127         g_free(r1);
128     }
129     QTAILQ_FOREACH_SAFE(r1, &proxy->pending, next, r2) {
130         qemu_cond_destroy(&r1->cv);
131         QTAILQ_REMOVE(&proxy->pending, r1, next);
132         g_free(r1);
133     }
134     QTAILQ_FOREACH_SAFE(r1, &proxy->free, next, r2) {
135         qemu_cond_destroy(&r1->cv);
136         QTAILQ_REMOVE(&proxy->free, r1, next);
137         g_free(r1);
138     }
139 
140     /*
141      * Make sure the iothread isn't blocking anywhere
142      * with a ref to this proxy by waiting for a BH
143      * handler to run after the proxy fd handlers were
144      * deleted above.
145      */
146     aio_bh_schedule_oneshot(proxy->ctx, vfio_user_cb, proxy);
147     qemu_cond_wait(&proxy->close_cv, &proxy->lock);
148 
149     /* we now hold the only ref to proxy */
150     qemu_mutex_unlock(&proxy->lock);
151     qemu_cond_destroy(&proxy->close_cv);
152     qemu_mutex_destroy(&proxy->lock);
153 
154     QLIST_REMOVE(proxy, next);
155     if (QLIST_EMPTY(&vfio_user_sockets)) {
156         iothread_destroy(vfio_user_iothread);
157         vfio_user_iothread = NULL;
158     }
159 
160     g_free(proxy->sockname);
161     g_free(proxy);
162 }
163