From owner-svn-src-all@FreeBSD.ORG Fri Mar 27 08:53:00 2015 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 15E89F17; Fri, 27 Mar 2015 08:53:00 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id F3C1CC30; Fri, 27 Mar 2015 08:52:59 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t2R8qxqD025751; Fri, 27 Mar 2015 08:52:59 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t2R8qw68025740; Fri, 27 Mar 2015 08:52:58 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201503270852.t2R8qw68025740@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Fri, 27 Mar 2015 08:52:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r280743 - stable/10/usr.sbin/bhyve X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 27 Mar 2015 08:53:00 -0000 Author: mav Date: Fri Mar 27 08:52:57 2015 New Revision: 280743 URL: https://svnweb.freebsd.org/changeset/base/280743 Log: MFC r280026, r280041: Modify virtqueue helpers added in r253440 to allow queuing. Original virtqueue design allows queued and out-of-order processing, but helpers added in r253440 suppose only direct blocking in-order one. It could be fine for network, etc., but it is a huge limitation for storage devices. Modified: stable/10/usr.sbin/bhyve/pci_virtio_block.c stable/10/usr.sbin/bhyve/pci_virtio_net.c stable/10/usr.sbin/bhyve/pci_virtio_rnd.c stable/10/usr.sbin/bhyve/virtio.c stable/10/usr.sbin/bhyve/virtio.h Directory Properties: stable/10/ (props changed) Modified: stable/10/usr.sbin/bhyve/pci_virtio_block.c ============================================================================== --- stable/10/usr.sbin/bhyve/pci_virtio_block.c Fri Mar 27 08:51:20 2015 (r280742) +++ stable/10/usr.sbin/bhyve/pci_virtio_block.c Fri Mar 27 08:52:57 2015 (r280743) @@ -170,9 +170,9 @@ pci_vtblk_proc(struct pci_vtblk_softc *s int writeop, type; off_t offset; struct iovec iov[VTBLK_MAXSEGS + 2]; - uint16_t flags[VTBLK_MAXSEGS + 2]; + uint16_t idx, flags[VTBLK_MAXSEGS + 2]; - n = vq_getchain(vq, iov, VTBLK_MAXSEGS + 2, flags); + n = vq_getchain(vq, &idx, iov, VTBLK_MAXSEGS + 2, flags); /* * The first descriptor will be the read-only fixed header, @@ -258,7 +258,7 @@ pci_vtblk_proc(struct pci_vtblk_softc *s * Return the descriptor back to the host. * We wrote 1 byte (our status) to host. */ - vq_relchain(vq, 1); + vq_relchain(vq, idx, 1); } static void @@ -266,7 +266,6 @@ pci_vtblk_notify(void *vsc, struct vqueu { struct pci_vtblk_softc *sc = vsc; - vq_startchains(vq); while (vq_has_descs(vq)) pci_vtblk_proc(sc, vq); vq_endchains(vq, 1); /* Generate interrupt if appropriate. */ Modified: stable/10/usr.sbin/bhyve/pci_virtio_net.c ============================================================================== --- stable/10/usr.sbin/bhyve/pci_virtio_net.c Fri Mar 27 08:51:20 2015 (r280742) +++ stable/10/usr.sbin/bhyve/pci_virtio_net.c Fri Mar 27 08:52:57 2015 (r280743) @@ -288,6 +288,7 @@ pci_vtnet_tap_rx(struct pci_vtnet_softc struct vqueue_info *vq; void *vrx; int len, n; + uint16_t idx; /* * Should never be called without a valid tap fd @@ -310,7 +311,6 @@ pci_vtnet_tap_rx(struct pci_vtnet_softc * Check for available rx buffers */ vq = &sc->vsc_queues[VTNET_RXQ]; - vq_startchains(vq); if (!vq_has_descs(vq)) { /* * Drop the packet and try later. Interrupt on @@ -325,7 +325,7 @@ pci_vtnet_tap_rx(struct pci_vtnet_softc /* * Get descriptor chain. */ - n = vq_getchain(vq, iov, VTNET_MAXSEGS, NULL); + n = vq_getchain(vq, &idx, iov, VTNET_MAXSEGS, NULL); assert(n >= 1 && n <= VTNET_MAXSEGS); /* @@ -342,6 +342,7 @@ pci_vtnet_tap_rx(struct pci_vtnet_softc * No more packets, but still some avail ring * entries. Interrupt if needed/appropriate. */ + vq_retchain(vq); vq_endchains(vq, 0); return; } @@ -362,7 +363,7 @@ pci_vtnet_tap_rx(struct pci_vtnet_softc /* * Release this chain and handle more chains. */ - vq_relchain(vq, len + sc->rx_vhdrlen); + vq_relchain(vq, idx, len + sc->rx_vhdrlen); } while (vq_has_descs(vq)); /* Interrupt if needed, including for NOTIFY_ON_EMPTY. */ @@ -401,13 +402,14 @@ pci_vtnet_proctx(struct pci_vtnet_softc struct iovec iov[VTNET_MAXSEGS + 1]; int i, n; int plen, tlen; + uint16_t idx; /* * Obtain chain of descriptors. The first one is * really the header descriptor, so we need to sum * up two lengths: packet length and transfer length. */ - n = vq_getchain(vq, iov, VTNET_MAXSEGS, NULL); + n = vq_getchain(vq, &idx, iov, VTNET_MAXSEGS, NULL); assert(n >= 1 && n <= VTNET_MAXSEGS); plen = 0; tlen = iov[0].iov_len; @@ -420,7 +422,7 @@ pci_vtnet_proctx(struct pci_vtnet_softc pci_vtnet_tap_tx(sc, &iov[1], n - 1, plen); /* chain is processed, release it and set tlen */ - vq_relchain(vq, tlen); + vq_relchain(vq, idx, tlen); } static void @@ -479,7 +481,6 @@ pci_vtnet_tx_thread(void *param) sc->tx_in_progress = 1; pthread_mutex_unlock(&sc->tx_mtx); - vq_startchains(vq); do { /* * Run through entries, placing them into Modified: stable/10/usr.sbin/bhyve/pci_virtio_rnd.c ============================================================================== --- stable/10/usr.sbin/bhyve/pci_virtio_rnd.c Fri Mar 27 08:51:20 2015 (r280742) +++ stable/10/usr.sbin/bhyve/pci_virtio_rnd.c Fri Mar 27 08:52:57 2015 (r280743) @@ -103,18 +103,17 @@ pci_vtrnd_notify(void *vsc, struct vqueu struct iovec iov; struct pci_vtrnd_softc *sc; int len; + uint16_t idx; sc = vsc; - vq_startchains(vq); - if (sc->vrsc_fd < 0) { vq_endchains(vq, 0); return; } while (vq_has_descs(vq)) { - vq_getchain(vq, &iov, 1, NULL); + vq_getchain(vq, &idx, &iov, 1, NULL); len = read(sc->vrsc_fd, iov.iov_base, iov.iov_len); @@ -126,7 +125,7 @@ pci_vtrnd_notify(void *vsc, struct vqueu /* * Release this chain and handle more */ - vq_relchain(vq, len); + vq_relchain(vq, idx, len); } vq_endchains(vq, 1); /* Generate interrupt if appropriate. */ } Modified: stable/10/usr.sbin/bhyve/virtio.c ============================================================================== --- stable/10/usr.sbin/bhyve/virtio.c Fri Mar 27 08:51:20 2015 (r280742) +++ stable/10/usr.sbin/bhyve/virtio.c Fri Mar 27 08:52:57 2015 (r280743) @@ -97,6 +97,7 @@ vi_reset_dev(struct virtio_softc *vs) for (vq = vs->vs_queues, i = 0; i < nvq; vq++, i++) { vq->vq_flags = 0; vq->vq_last_avail = 0; + vq->vq_save_used = 0; vq->vq_pfn = 0; vq->vq_msix_idx = VIRTIO_MSI_NO_VECTOR; } @@ -188,6 +189,7 @@ vi_vq_init(struct virtio_softc *vs, uint /* Mark queue as allocated, and start at 0 when we use it. */ vq->vq_flags = VQ_ALLOC; vq->vq_last_avail = 0; + vq->vq_save_used = 0; } /* @@ -247,12 +249,12 @@ _vq_record(int i, volatile struct virtio * that vq_has_descs() does one). */ int -vq_getchain(struct vqueue_info *vq, +vq_getchain(struct vqueue_info *vq, uint16_t *pidx, struct iovec *iov, int n_iov, uint16_t *flags) { int i; u_int ndesc, n_indir; - u_int idx, head, next; + u_int idx, next; volatile struct virtio_desc *vdir, *vindir, *vp; struct vmctx *ctx; struct virtio_softc *vs; @@ -295,8 +297,8 @@ vq_getchain(struct vqueue_info *vq, * index, but we just abort if the count gets excessive. */ ctx = vs->vs_pi->pi_vmctx; - head = vq->vq_avail->va_ring[idx & (vq->vq_qsize - 1)]; - next = head; + *pidx = next = vq->vq_avail->va_ring[idx & (vq->vq_qsize - 1)]; + vq->vq_last_avail++; for (i = 0; i < VQ_MAX_DESCRIPTORS; next = vdir->vd_next) { if (next >= vq->vq_qsize) { fprintf(stderr, @@ -370,16 +372,29 @@ loopy: } /* - * Return the currently-first request chain to the guest, setting - * its I/O length to the provided value. + * Return the currently-first request chain back to the available queue. * * (This chain is the one you handled when you called vq_getchain() * and used its positive return value.) */ void -vq_relchain(struct vqueue_info *vq, uint32_t iolen) +vq_retchain(struct vqueue_info *vq) { - uint16_t head, uidx, mask; + + vq->vq_last_avail--; +} + +/* + * Return specified request chain to the guest, setting its I/O length + * to the provided value. + * + * (This chain is the one you handled when you called vq_getchain() + * and used its positive return value.) + */ +void +vq_relchain(struct vqueue_info *vq, uint16_t idx, uint32_t iolen) +{ + uint16_t uidx, mask; volatile struct vring_used *vuh; volatile struct virtio_used *vue; @@ -395,11 +410,10 @@ vq_relchain(struct vqueue_info *vq, uint */ mask = vq->vq_qsize - 1; vuh = vq->vq_used; - head = vq->vq_avail->va_ring[vq->vq_last_avail++ & mask]; uidx = vuh->vu_idx; vue = &vuh->vu_ring[uidx++ & mask]; - vue->vu_idx = head; /* ie, vue->id = head */ + vue->vu_idx = idx; vue->vu_tlen = iolen; vuh->vu_idx = uidx; } @@ -436,8 +450,8 @@ vq_endchains(struct vqueue_info *vq, int * entire avail was processed, we need to interrupt always. */ vs = vq->vq_vs; - new_idx = vq->vq_used->vu_idx; old_idx = vq->vq_save_used; + vq->vq_save_used = new_idx = vq->vq_used->vu_idx; if (used_all_avail && (vs->vs_negotiated_caps & VIRTIO_F_NOTIFY_ON_EMPTY)) intr = 1; Modified: stable/10/usr.sbin/bhyve/virtio.h ============================================================================== --- stable/10/usr.sbin/bhyve/virtio.h Fri Mar 27 08:51:20 2015 (r280742) +++ stable/10/usr.sbin/bhyve/virtio.h Fri Mar 27 08:52:57 2015 (r280743) @@ -425,20 +425,6 @@ vq_has_descs(struct vqueue_info *vq) } /* - * Called by virtio driver as it starts processing chains. Each - * completed chain (obtained from vq_getchain()) is released by - * calling vq_relchain(), then when all are done, vq_endchains() - * can tell if / how-many chains were processed and know whether - * and how to generate an interrupt. - */ -static inline void -vq_startchains(struct vqueue_info *vq) -{ - - vq->vq_save_used = vq->vq_used->vu_idx; -} - -/* * Deliver an interrupt to guest on the given virtual queue * (if possible, or a generic MSI interrupt if not using MSI-X). */ @@ -465,9 +451,10 @@ int vi_intr_init(struct virtio_softc *vs void vi_reset_dev(struct virtio_softc *); void vi_set_io_bar(struct virtio_softc *, int); -int vq_getchain(struct vqueue_info *vq, +int vq_getchain(struct vqueue_info *vq, uint16_t *pidx, struct iovec *iov, int n_iov, uint16_t *flags); -void vq_relchain(struct vqueue_info *vq, uint32_t iolen); +void vq_retchain(struct vqueue_info *vq); +void vq_relchain(struct vqueue_info *vq, uint16_t idx, uint32_t iolen); void vq_endchains(struct vqueue_info *vq, int used_all_avail); uint64_t vi_pci_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,