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