Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 19 Apr 2013 11:46:03 -0400
From:      Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
To:        freebsd-virtualization@freebsd.org
Subject:   direct descriptor support for virtio block device
Message-ID:  <4FC78CC2-AAF3-4802-ACFC-3F3281DC45DE@pluribusnetworks.com>

next in thread | raw e-mail | index | archive | help

--Apple-Mail=_31F1079F-E4E1-4782-8EAA-8441AC83B269
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=us-ascii


The current virtio block device advertises support for the indirect =
descriptors feature yet is unable to cope if the guest elects not to use =
them.  Attached is a patch for direct descriptors along with an =
implementation of device reset.

Tycho


--Apple-Mail=_31F1079F-E4E1-4782-8EAA-8441AC83B269
Content-Disposition: attachment;
	filename=vtblk-diff.txt
Content-Type: text/plain;
	name="vtblk-diff.txt"
Content-Transfer-Encoding: 7bit

diff -r 7ec7f1183c3c usr.sbin/bhyve/pci_virtio_block.c
--- a/usr.sbin/bhyve/pci_virtio_block.c	Thu Apr 18 07:43:45 2013 -0400
+++ b/usr.sbin/bhyve/pci_virtio_block.c	Fri Apr 19 11:08:32 2013 -0400
@@ -187,6 +187,13 @@
 {
 	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 @@
 	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 @@
 
 	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);
+	indirect = ((vd->vd_flags & VRING_DESC_F_INDIRECT) != 0);
 
-	nsegs = vd->vd_len / sizeof(struct virtio_desc);
-	assert(nsegs >= 3);
-	assert(nsegs < VTBLK_MAXSEGS + 2);
-
-	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,21 @@
 	/*
 	 * 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;
+	for (i = 1, iolen = 0; i <= VTBLK_MAXSEGS + 1; i++) {
+		if (indirect) {
+			vd = &vid[i];
+		} else {
+			vd = &hq->hq_dtable[vd->vd_next];
+		}
 
-		assert(vid[i].vd_flags & VRING_DESC_F_NEXT);
-		assert((vid[i].vd_flags & VRING_DESC_F_INDIRECT) == 0);
+		if ((vd->vd_flags & VRING_DESC_F_NEXT) == 0)
+			break;
+
+		iov[i - 1].iov_base = paddr_guest2host(vtblk_ctx(sc),
+						       vd->vd_addr,
+						       vd->vd_len);
+		iov[i - 1].iov_len = vd->vd_len;
+		iolen += vd->vd_len;
 
 		/*
 		 * - write op implies read-only descriptor,
@@ -268,58 +272,35 @@
 		 * 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);
 	}
 
 	/* 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 - 1, offset));
 
 	if (writeop){
-		err = pwritev(sc->vbsc_fd, iov, nsegs - 2, offset);
+		err = pwritev(sc->vbsc_fd, iov, i - 1, offset);
 	} else {
-		err = preadv(sc->vbsc_fd, iov, nsegs - 2, offset);
+		err = preadv(sc->vbsc_fd, iov, i - 1, 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 +313,21 @@
 			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

--Apple-Mail=_31F1079F-E4E1-4782-8EAA-8441AC83B269--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4FC78CC2-AAF3-4802-ACFC-3F3281DC45DE>