Date: Sat, 16 Jul 2016 09:08:33 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r302932 - head/usr.sbin/bhyve Message-ID: <201607160908.u6G98XP9092656@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201607160908.u6G98XP9092656>