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