From nobody Tue Feb 10 04:55:20 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1568209773; cv=none; d=zoho.com; s=zohoarc; b=Ab04QbN7UsTThnKkCBApAeLbz0Tm+qGaiQTmnru7vL1U4lPBNVQV+19NDHtyaM4wXJwpMTtUyFPv9N6h2EJTY1D/cZ92Grq2R05Z/OWYGlcG+fMV1xPFzukI+1ubXEvjPHqcSDWUgbW5ncujut8db3u0kJeshbXQbF6zMKT/4J4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1568209773; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=v/IB/AAFW4b1C3sXMpnaQuw3v8WkgayFHJYtK3mGy+I=; b=hvUcmC11ll3f3JhgViopBPy93/botJ/aGz5YM1BStWTI7TZkinfnCmMMCNKrqn8GAGM7hI5RzC749it5jZjF4lXZds983kL3ApmBtgCx4nGdcv7MgAm5OGBLvUPRuRD4yiUFH3YPlMRDLFnYS496EHqZe8okbeyCfEE8Cjg3cjg= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1568209773261468.45747612461366; Wed, 11 Sep 2019 06:49:33 -0700 (PDT) Received: from localhost ([::1]:51277 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i82zx-0006ee-1w for importer@patchew.org; Wed, 11 Sep 2019 09:49:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34917) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i82wP-0003gv-8S for qemu-devel@nongnu.org; Wed, 11 Sep 2019 09:45:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i82wN-0008UL-J3 for qemu-devel@nongnu.org; Wed, 11 Sep 2019 09:45:49 -0400 Received: from s3.sipsolutions.net ([2a01:4f8:191:4433::2]:57028 helo=sipsolutions.net) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i82wN-0008TW-At for qemu-devel@nongnu.org; Wed, 11 Sep 2019 09:45:47 -0400 Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1i82wK-0000VV-Vh; Wed, 11 Sep 2019 15:45:45 +0200 From: Johannes Berg To: qemu-devel@nongnu.org Date: Wed, 11 Sep 2019 15:45:39 +0200 Message-Id: <20190911134539.25650-3-johannes@sipsolutions.net> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190911134539.25650-1-johannes@sipsolutions.net> References: <20190911134539.25650-1-johannes@sipsolutions.net> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a01:4f8:191:4433::2 Subject: [Qemu-devel] [RFC v2 2/2] libvhost-user: implement in-band notifications X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Johannes Berg , "Michael S . Tsirkin" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" From: Johannes Berg Add support for VHOST_USER_PROTOCOL_F_IN_BAND_NOTIFICATIONS, but as it's not desired by default, don't enable it unless the device implementation opts in by returning it from its protocol features callback. Note that I updated vu_set_vring_err_exec(), but didn't add any sending of the VHOST_USER_SLAVE_VRING_ERR message as there's no write to the err_fd today either. Signed-off-by: Johannes Berg --- contrib/libvhost-user/libvhost-user.c | 94 ++++++++++++++++++++++++--- contrib/libvhost-user/libvhost-user.h | 4 ++ 2 files changed, 89 insertions(+), 9 deletions(-) diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/= libvhost-user.c index f1677da21201..6367ddeb17fb 100644 --- a/contrib/libvhost-user/libvhost-user.c +++ b/contrib/libvhost-user/libvhost-user.c @@ -136,6 +136,7 @@ vu_request_to_string(unsigned int req) REQ(VHOST_USER_GET_INFLIGHT_FD), REQ(VHOST_USER_SET_INFLIGHT_FD), REQ(VHOST_USER_GPU_SET_SOCKET), + REQ(VHOST_USER_VRING_KICK), REQ(VHOST_USER_MAX), }; #undef REQ @@ -163,7 +164,10 @@ vu_panic(VuDev *dev, const char *msg, ...) dev->panic(dev, buf); free(buf); =20 - /* FIXME: find a way to call virtio_error? */ + /* + * FIXME: + * find a way to call virtio_error, or perhaps close the connection? + */ } =20 /* Translate guest physical address to our virtual address. */ @@ -920,6 +924,7 @@ static bool vu_check_queue_msg_file(VuDev *dev, VhostUserMsg *vmsg) { int index =3D vmsg->payload.u64 & VHOST_USER_VRING_IDX_MASK; + bool nofd =3D vmsg->payload.u64 & VHOST_USER_VRING_NOFD_MASK; =20 if (index >=3D dev->max_queues) { vmsg_close_fds(vmsg); @@ -927,8 +932,12 @@ vu_check_queue_msg_file(VuDev *dev, VhostUserMsg *vmsg) return false; } =20 - if (vmsg->payload.u64 & VHOST_USER_VRING_NOFD_MASK || - vmsg->fd_num !=3D 1) { + if (nofd) { + vmsg_close_fds(vmsg); + return true; + } + + if (vmsg->fd_num !=3D 1) { vmsg_close_fds(vmsg); vu_panic(dev, "Invalid fds in request: %d", vmsg->request); return false; @@ -1025,6 +1034,7 @@ static bool vu_set_vring_kick_exec(VuDev *dev, VhostUserMsg *vmsg) { int index =3D vmsg->payload.u64 & VHOST_USER_VRING_IDX_MASK; + bool nofd =3D vmsg->payload.u64 & VHOST_USER_VRING_NOFD_MASK; =20 DPRINT("u64: 0x%016"PRIx64"\n", vmsg->payload.u64); =20 @@ -1038,8 +1048,8 @@ vu_set_vring_kick_exec(VuDev *dev, VhostUserMsg *vmsg) dev->vq[index].kick_fd =3D -1; } =20 - dev->vq[index].kick_fd =3D vmsg->fds[0]; - DPRINT("Got kick_fd: %d for vq: %d\n", vmsg->fds[0], index); + dev->vq[index].kick_fd =3D nofd ? -1 : vmsg->fds[0]; + DPRINT("Got kick_fd: %d for vq: %d\n", dev->vq[index].kick_fd, index); =20 dev->vq[index].started =3D true; if (dev->iface->queue_set_started) { @@ -1116,6 +1126,7 @@ static bool vu_set_vring_call_exec(VuDev *dev, VhostUserMsg *vmsg) { int index =3D vmsg->payload.u64 & VHOST_USER_VRING_IDX_MASK; + bool nofd =3D vmsg->payload.u64 & VHOST_USER_VRING_NOFD_MASK; =20 DPRINT("u64: 0x%016"PRIx64"\n", vmsg->payload.u64); =20 @@ -1128,14 +1139,14 @@ vu_set_vring_call_exec(VuDev *dev, VhostUserMsg *vm= sg) dev->vq[index].call_fd =3D -1; } =20 - dev->vq[index].call_fd =3D vmsg->fds[0]; + dev->vq[index].call_fd =3D nofd ? -1 : vmsg->fds[0]; =20 /* in case of I/O hang after reconnecting */ - if (eventfd_write(vmsg->fds[0], 1)) { + if (dev->vq[index].call_fd !=3D -1 && eventfd_write(vmsg->fds[0], 1)) { return -1; } =20 - DPRINT("Got call_fd: %d for vq: %d\n", vmsg->fds[0], index); + DPRINT("Got call_fd: %d for vq: %d\n", dev->vq[index].call_fd, index); =20 return false; } @@ -1144,6 +1155,7 @@ static bool vu_set_vring_err_exec(VuDev *dev, VhostUserMsg *vmsg) { int index =3D vmsg->payload.u64 & VHOST_USER_VRING_IDX_MASK; + bool nofd =3D vmsg->payload.u64 & VHOST_USER_VRING_NOFD_MASK; =20 DPRINT("u64: 0x%016"PRIx64"\n", vmsg->payload.u64); =20 @@ -1156,7 +1168,7 @@ vu_set_vring_err_exec(VuDev *dev, VhostUserMsg *vmsg) dev->vq[index].err_fd =3D -1; } =20 - dev->vq[index].err_fd =3D vmsg->fds[0]; + dev->vq[index].err_fd =3D nofd ? -1 : vmsg->fds[0]; =20 return false; } @@ -1164,6 +1176,14 @@ vu_set_vring_err_exec(VuDev *dev, VhostUserMsg *vmsg) static bool vu_get_protocol_features_exec(VuDev *dev, VhostUserMsg *vmsg) { + /* + * Note that we support, but intentionally do not set, + * VHOST_USER_PROTOCOL_F_IN_BAND_NOTIFICATIONS. This means that + * a device implementation can return it in its callback + * (get_protocol_features) if it wants to use this for + * simulation, but it is otherwise not desirable (if even + * implemented by the master.) + */ uint64_t features =3D 1ULL << VHOST_USER_PROTOCOL_F_MQ | 1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD | 1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ | @@ -1196,6 +1216,25 @@ vu_set_protocol_features_exec(VuDev *dev, VhostUserM= sg *vmsg) =20 dev->protocol_features =3D vmsg->payload.u64; =20 + if (vu_has_protocol_feature(dev, + VHOST_USER_PROTOCOL_F_IN_BAND_NOTIFICATION= S) && + (!vu_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_SLAVE_REQ) || + !vu_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_REPLY_ACK))) { + /* + * The use case for using messages for kick/call is simulation, to= make + * the kick and call synchronous. To actually get that behaviour, = both + * of the other features are required. + * Theoretically, one could use only kick messages, or do them wit= hout + * having F_REPLY_ACK, but too many (possibly pending) messages on= the + * socket will eventually cause the master to hang, to avoid this = in + * scenarios where not desired enforce that the settings are in a = way + * that actually enables the simulation case. + */ + vu_panic(dev, + "F_IN_BAND_NOTIFICATIONS requires F_SLAVE_REQ && F_REPLY_= ACK"); + return false; + } + if (dev->iface->set_protocol_features) { dev->iface->set_protocol_features(dev, features); } @@ -1456,6 +1495,25 @@ vu_set_inflight_fd(VuDev *dev, VhostUserMsg *vmsg) return false; } =20 +static bool +vu_handle_vring_kick(VuDev *dev, VhostUserMsg *vmsg) +{ + unsigned int index =3D vmsg->payload.state.index; + + if (index >=3D dev->max_queues) { + vu_panic(dev, "Invalid queue index: %u", index); + return false; + } + + DPRINT("Got kick message: handler:%p idx:%d\n", + dev->vq[index].handler, index); + if (dev->vq[index].handler) { + dev->vq[index].handler(dev, index); + } + + return false; +} + static bool vu_process_message(VuDev *dev, VhostUserMsg *vmsg) { @@ -1538,6 +1596,8 @@ vu_process_message(VuDev *dev, VhostUserMsg *vmsg) return vu_get_inflight_fd(dev, vmsg); case VHOST_USER_SET_INFLIGHT_FD: return vu_set_inflight_fd(dev, vmsg); + case VHOST_USER_VRING_KICK: + return vu_handle_vring_kick(dev, vmsg); default: vmsg_close_fds(vmsg); vu_panic(dev, "Unhandled request: %d", vmsg->request); @@ -2010,6 +2070,22 @@ vu_queue_notify(VuDev *dev, VuVirtq *vq) return; } =20 + if (vu_has_protocol_feature(dev, + VHOST_USER_PROTOCOL_F_IN_BAND_NOTIFICATION= S) && + vu_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_SLAVE_REQ)) { + VhostUserMsg vmsg =3D { + .request =3D VHOST_USER_SLAVE_VRING_CALL, + .flags =3D VHOST_USER_VERSION, + .size =3D sizeof(vmsg.payload.state), + .payload.state =3D { + .index =3D vq - dev->vq, + }, + }; + + vu_message_write(dev, dev->slave_fd, &vmsg); + return; + } + if (eventfd_write(vq->call_fd, 1) < 0) { vu_panic(dev, "Error writing eventfd: %s", strerror(errno)); } diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/= libvhost-user.h index 46b600799b2e..a22dc4733849 100644 --- a/contrib/libvhost-user/libvhost-user.h +++ b/contrib/libvhost-user/libvhost-user.h @@ -53,6 +53,7 @@ enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD =3D 10, VHOST_USER_PROTOCOL_F_HOST_NOTIFIER =3D 11, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD =3D 12, + VHOST_USER_PROTOCOL_F_IN_BAND_NOTIFICATIONS =3D 13, =20 VHOST_USER_PROTOCOL_F_MAX }; @@ -94,6 +95,7 @@ typedef enum VhostUserRequest { VHOST_USER_GET_INFLIGHT_FD =3D 31, VHOST_USER_SET_INFLIGHT_FD =3D 32, VHOST_USER_GPU_SET_SOCKET =3D 33, + VHOST_USER_VRING_KICK =3D 34, VHOST_USER_MAX } VhostUserRequest; =20 @@ -102,6 +104,8 @@ typedef enum VhostUserSlaveRequest { VHOST_USER_SLAVE_IOTLB_MSG =3D 1, VHOST_USER_SLAVE_CONFIG_CHANGE_MSG =3D 2, VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG =3D 3, + VHOST_USER_SLAVE_VRING_CALL =3D 4, + VHOST_USER_SLAVE_VRING_ERR =3D 5, VHOST_USER_SLAVE_MAX } VhostUserSlaveRequest; =20 --=20 2.20.1