svn commit: r302932 - head/usr.sbin/bhyve

Alexander Motin mav at FreeBSD.org
Sat Jul 16 09:08:34 UTC 2016


Author: mav
Date: Sat Jul 16 09:08:33 2016
New Revision: 302932
URL: https://svnweb.freebsd.org/changeset/base/302932

Log:
  Increase I82545_MAX_TXSEGS from 20 to 64 and add checks for it.
  
  There seems no hard limit on number of segments per packet in the chip,
  and 20 appeared insufficient.  Hope 64 will be enough, but if not -- add
  check to report that and drop the packet instead of corrupting stack.

Modified:
  head/usr.sbin/bhyve/Makefile
  head/usr.sbin/bhyve/pci_e82545.c

Modified: head/usr.sbin/bhyve/Makefile
==============================================================================
--- head/usr.sbin/bhyve/Makefile	Sat Jul 16 08:17:14 2016	(r302931)
+++ head/usr.sbin/bhyve/Makefile	Sat Jul 16 09:08:33 2016	(r302932)
@@ -29,6 +29,7 @@ SRCS=	\
 	mptbl.c			\
 	pci_ahci.c		\
 	pci_e82545.c		\
+	pci_e82580.c		\
 	pci_emul.c		\
 	pci_fbuf.c		\
 	pci_hostbridge.c	\

Modified: head/usr.sbin/bhyve/pci_e82545.c
==============================================================================
--- head/usr.sbin/bhyve/pci_e82545.c	Sat Jul 16 08:17:14 2016	(r302931)
+++ head/usr.sbin/bhyve/pci_e82545.c	Sat Jul 16 09:08:33 2016	(r302932)
@@ -109,12 +109,8 @@ __FBSDID("$FreeBSD$");
 
 #define E1000_ICR_SRPD		0x00010000
 
-/*
- * XXX does this actually have a limit on the 82545 ?
- * There is a limit on the max number of bytes, but perhaps not
- * on descriptors ??
- */
-#define I82545_MAX_TXSEGS	20
+/* This is an arbitrary number.  There is no hard limit on the chip. */
+#define I82545_MAX_TXSEGS	64
 
 /* Legacy receive descriptor */
 struct e1000_rx_desc {
@@ -1050,15 +1046,18 @@ e82545_transmit_backend(struct e82545_so
 }
 
 static void
-e82545_transmit_done(struct e82545_softc *sc, union e1000_tx_udesc **txwb,
-    int nwb)
+e82545_transmit_done(struct e82545_softc *sc, uint16_t head, uint16_t tail,
+    uint16_t dsize, int *tdwb)
 {
-	int i;
+	union e1000_tx_udesc *dsc;
 
-	/* Write-back tx descriptor status */
-	for (i = 0; i < nwb; i++)
-		txwb[i]->td.upper.data |= E1000_TXD_STAT_DD;
-	/* XXX wmb() */
+	for ( ; head != tail; head = (head + 1) % dsize) {
+		dsc = &sc->esc_txdesc[head];
+		if (dsc->td.lower.data & E1000_TXD_CMD_RS) {
+			dsc->td.upper.data |= E1000_TXD_STAT_DD;
+			*tdwb = 1;
+		}
+	}
 }
 
 static int
@@ -1068,22 +1067,21 @@ e82545_transmit(struct e82545_softc *sc,
 	uint8_t *hdr, *hdrp;
 	struct iovec iovb[I82545_MAX_TXSEGS + 2];
 	struct iovec tiov[I82545_MAX_TXSEGS + 2];
-	union e1000_tx_udesc *txwb[I82545_MAX_TXSEGS];
 	struct e1000_context_desc *cd;
 	struct ck_info ckinfo[2];
 	struct iovec *iov;
 	union  e1000_tx_udesc *dsc;
-	int desc, dtype, len, ntype, nwb, iovcnt, tlen, hdrlen, vlen, tcp, tso;
+	int desc, dtype, len, ntype, iovcnt, tlen, hdrlen, vlen, tcp, tso;
 	int mss, paylen, seg, tiovcnt, left, now, nleft, nnow, pv, pvoff;
 	uint32_t tcpsum, tcpseq;
-	uint16_t ipcs, tcpcs, ipid;
+	uint16_t ipcs, tcpcs, ipid, ohead;
 
 	ckinfo[0].ck_valid = ckinfo[1].ck_valid = 0;
 	iovcnt = 0;
 	tlen = 0;
-	nwb = 0;
 	ntype = 0;
 	tso = 0;
+	ohead = head;
 
 	/* iovb[0/1] may be used for writable copy of headers. */
 	iov = &iovb[2];
@@ -1104,11 +1102,8 @@ e82545_transmit(struct e82545_softc *sc,
 				    head, dsc->td.buffer_addr,
 				    dsc->td.upper.data, dsc->td.lower.data);
 				/* Save context and return */
-				/* XXX ignore DD processing here */
 				sc->esc_txctx = dsc->cd;
-				*rhead = (head + 1) % dsize;
-				return (1);
-				break;
+				goto done;
 			case E1000_TXD_TYP_L:
 				DPRINTF("tx legacy desc idx %d: %08x%08x\r\n",
 				    head, dsc->td.upper.data, dsc->td.lower.data);
@@ -1142,16 +1137,14 @@ e82545_transmit(struct e82545_softc *sc,
 			    (dsc->td.lower.data & E1000_TXD_CMD_IFCS) == 0)
 				len -= 2;
 			tlen += len;
-			iov[iovcnt].iov_base = paddr_guest2host(sc->esc_ctx,
-			    dsc->td.buffer_addr, len);
-			iov[iovcnt].iov_len = len;
+			if (iovcnt < I82545_MAX_TXSEGS) {
+				iov[iovcnt].iov_base = paddr_guest2host(
+				    sc->esc_ctx, dsc->td.buffer_addr, len);
+				iov[iovcnt].iov_len = len;
+			}
 			iovcnt++;
 		}
 
-		/* Record the descriptor addres if write-back requested */
-		if (dsc->td.lower.data & E1000_TXD_CMD_RS)
-			txwb[nwb++] = dsc;
-
 		/*
 		 * Pull out info that is valid in the final descriptor
 		 * and exit descriptor loop.
@@ -1197,6 +1190,12 @@ e82545_transmit(struct e82545_softc *sc,
 		}
 	}
 
+	if (iovcnt > I82545_MAX_TXSEGS) {
+		WPRINTF("tx too many descriptors (%d > %d) -- dropped\r\n",
+		    iovcnt, I82545_MAX_TXSEGS);
+		goto done;
+	}
+
 	hdrlen = vlen = 0;
 	/* Estimate writable space for VLAN header insertion. */
 	if ((sc->esc_CTRL & E1000_CTRL_VME) &&
@@ -1356,12 +1355,10 @@ e82545_transmit(struct e82545_softc *sc,
 	}
 
 done:
-	/* Record if tx descs were written back */
-	e82545_transmit_done(sc, txwb, nwb);
-	if (nwb)
-		*tdwb = 1;
+	head = (head + 1) % dsize;
+	e82545_transmit_done(sc, ohead, head, dsize, tdwb);
 
-	*rhead = (head + 1) % dsize;
+	*rhead = head;
 	return (desc + 1);
 }
 


More information about the svn-src-all mailing list