From owner-svn-src-head@FreeBSD.ORG Tue Apr 23 16:40:40 2013 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id D5BFD6B1; Tue, 23 Apr 2013 16:40:40 +0000 (UTC) (envelope-from neel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id B6B171FF8; Tue, 23 Apr 2013 16:40:40 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r3NGeePO001678; Tue, 23 Apr 2013 16:40:40 GMT (envelope-from neel@svn.freebsd.org) Received: (from neel@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r3NGeejp001677; Tue, 23 Apr 2013 16:40:40 GMT (envelope-from neel@svn.freebsd.org) Message-Id: <201304231640.r3NGeejp001677@svn.freebsd.org> From: Neel Natu Date: Tue, 23 Apr 2013 16:40:40 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r249813 - head/usr.sbin/bhyve X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Apr 2013 16:40:40 -0000 Author: neel Date: Tue Apr 23 16:40:39 2013 New Revision: 249813 URL: http://svnweb.freebsd.org/changeset/base/249813 Log: Teach the virtio block device to deal with direct as well as indirect descriptors. Prior to this change the device would only work with guests that chose to use indirect descriptors. Modify the device reset callback to actually reset the device state. Submitted by: Tycho Nightingale (tycho.nightingale@pluribusnetworks.com) Modified: head/usr.sbin/bhyve/pci_virtio_block.c Modified: head/usr.sbin/bhyve/pci_virtio_block.c ============================================================================== --- head/usr.sbin/bhyve/pci_virtio_block.c Tue Apr 23 16:33:25 2013 (r249812) +++ head/usr.sbin/bhyve/pci_virtio_block.c Tue Apr 23 16:40:39 2013 (r249813) @@ -187,6 +187,13 @@ pci_vtblk_update_status(struct pci_vtblk { if (value == 0) { DPRINTF(("vtblk: device reset requested !\n")); + sc->vbsc_isr = 0; + sc->msix_table_idx_req = VIRTIO_MSI_NO_VECTOR; + sc->msix_table_idx_cfg = VIRTIO_MSI_NO_VECTOR; + sc->vbsc_features = 0; + sc->vbsc_pfn = 0; + sc->vbsc_lastq = 0; + memset(&sc->vbsc_q, 0, sizeof(struct vring_hqueue)); } sc->vbsc_status = value; @@ -203,9 +210,8 @@ pci_vtblk_proc(struct pci_vtblk_softc *s int i; int err; int iolen; - int nsegs; int uidx, aidx, didx; - int writeop, type; + int indirect, writeop, type; off_t offset; uidx = *hq->hq_used_idx; @@ -215,30 +221,21 @@ pci_vtblk_proc(struct pci_vtblk_softc *s vd = &hq->hq_dtable[didx]; - /* - * Verify that the descriptor is indirect, and obtain - * the pointer to the indirect descriptor. - * There has to be space for at least 3 descriptors - * in the indirect descriptor array: the block header, - * 1 or more data descriptors, and a status byte. - */ - assert(vd->vd_flags & VRING_DESC_F_INDIRECT); - - nsegs = vd->vd_len / sizeof(struct virtio_desc); - assert(nsegs >= 3); - assert(nsegs < VTBLK_MAXSEGS + 2); + indirect = ((vd->vd_flags & VRING_DESC_F_INDIRECT) != 0); - vid = paddr_guest2host(vtblk_ctx(sc), vd->vd_addr, vd->vd_len); - assert((vid->vd_flags & VRING_DESC_F_INDIRECT) == 0); + if (indirect) { + vid = paddr_guest2host(vtblk_ctx(sc), vd->vd_addr, vd->vd_len); + vd = &vid[0]; + } /* * The first descriptor will be the read-only fixed header */ - vbh = paddr_guest2host(vtblk_ctx(sc), vid[0].vd_addr, + vbh = paddr_guest2host(vtblk_ctx(sc), vd->vd_addr, sizeof(struct virtio_blk_hdr)); - assert(vid[0].vd_len == sizeof(struct virtio_blk_hdr)); - assert(vid[0].vd_flags & VRING_DESC_F_NEXT); - assert((vid[0].vd_flags & VRING_DESC_F_WRITE) == 0); + assert(vd->vd_len == sizeof(struct virtio_blk_hdr)); + assert(vd->vd_flags & VRING_DESC_F_NEXT); + assert((vd->vd_flags & VRING_DESC_F_WRITE) == 0); /* * XXX @@ -253,14 +250,18 @@ pci_vtblk_proc(struct pci_vtblk_softc *s /* * Build up the iovec based on the guest's data descriptors */ - for (i = 1, iolen = 0; i < nsegs - 1; i++) { - iov[i-1].iov_base = paddr_guest2host(vtblk_ctx(sc), - vid[i].vd_addr, vid[i].vd_len); - iov[i-1].iov_len = vid[i].vd_len; - iolen += vid[i].vd_len; + i = iolen = 0; + while (1) { + if (indirect) + vd = &vid[i + 1]; /* skip first indirect desc */ + else + vd = &hq->hq_dtable[vd->vd_next]; + + if ((vd->vd_flags & VRING_DESC_F_NEXT) == 0) + break; - assert(vid[i].vd_flags & VRING_DESC_F_NEXT); - assert((vid[i].vd_flags & VRING_DESC_F_INDIRECT) == 0); + if (i == VTBLK_MAXSEGS) + break; /* * - write op implies read-only descriptor, @@ -268,58 +269,41 @@ pci_vtblk_proc(struct pci_vtblk_softc *s * therefore test the inverse of the descriptor bit * to the op. */ - assert(((vid[i].vd_flags & VRING_DESC_F_WRITE) == 0) == + assert(((vd->vd_flags & VRING_DESC_F_WRITE) == 0) == writeop); + + iov[i].iov_base = paddr_guest2host(vtblk_ctx(sc), + vd->vd_addr, + vd->vd_len); + iov[i].iov_len = vd->vd_len; + iolen += vd->vd_len; + i++; } /* Lastly, get the address of the status byte */ - status = paddr_guest2host(vtblk_ctx(sc), vid[nsegs - 1].vd_addr, 1); - assert(vid[nsegs - 1].vd_len == 1); - assert((vid[nsegs - 1].vd_flags & VRING_DESC_F_NEXT) == 0); - assert(vid[nsegs - 1].vd_flags & VRING_DESC_F_WRITE); + status = paddr_guest2host(vtblk_ctx(sc), vd->vd_addr, 1); + assert(vd->vd_len == 1); + assert((vd->vd_flags & VRING_DESC_F_NEXT) == 0); + assert(vd->vd_flags & VRING_DESC_F_WRITE); DPRINTF(("virtio-block: %s op, %d bytes, %d segs, offset %ld\n\r", - writeop ? "write" : "read", iolen, nsegs - 2, offset)); + writeop ? "write" : "read", iolen, i, offset)); - if (writeop){ - err = pwritev(sc->vbsc_fd, iov, nsegs - 2, offset); - } else { - err = preadv(sc->vbsc_fd, iov, nsegs - 2, offset); - } + if (writeop) + err = pwritev(sc->vbsc_fd, iov, i, offset); + else + err = preadv(sc->vbsc_fd, iov, i, offset); *status = err < 0 ? VTBLK_S_IOERR : VTBLK_S_OK; /* - * Return the single indirect descriptor back to the host + * Return the single descriptor back to the host */ vu = &hq->hq_used_ring[uidx % hq->hq_size]; vu->vu_idx = didx; vu->vu_tlen = 1; hq->hq_cur_aidx++; *hq->hq_used_idx += 1; -} - -static void -pci_vtblk_qnotify(struct pci_vtblk_softc *sc) -{ - struct vring_hqueue *hq = &sc->vbsc_q; - int i; - int ndescs; - - /* - * Calculate number of ring entries to process - */ - ndescs = hq_num_avail(hq); - - if (ndescs == 0) - return; - - /* - * Run through all the entries, placing them into iovecs and - * sending when an end-of-packet is found - */ - for (i = 0; i < ndescs; i++) - pci_vtblk_proc(sc, hq); /* * Generate an interrupt if able @@ -332,7 +316,21 @@ pci_vtblk_qnotify(struct pci_vtblk_softc pci_generate_msi(sc->vbsc_pi, 0); } } - +} + +static void +pci_vtblk_qnotify(struct pci_vtblk_softc *sc) +{ + struct vring_hqueue *hq = &sc->vbsc_q; + int ndescs; + + while ((ndescs = hq_num_avail(hq)) != 0) { + /* + * Run through all the entries, placing them into iovecs and + * sending when an end-of-packet is found + */ + pci_vtblk_proc(sc, hq); + } } static void