VirtualBox

Changeset 19113 in vbox for trunk/src/VBox/Devices/Network


Ignore:
Timestamp:
Apr 22, 2009 3:04:04 PM (16 years ago)
Author:
vboxsync
Message:

PCNet: handle rare cases were the register content changed when we left the critical section during RX

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/DevPCNet.cpp

    r19112 r19113  
    18251825 * Write data into guest receive buffers.
    18261826 */
    1827 static void pcnetReceiveNoSync(PCNetState *pThis, const uint8_t *buf, size_t size)
     1827static void pcnetReceiveNoSync(PCNetState *pThis, const uint8_t *buf, size_t cbToRecv)
    18281828{
    18291829    PPDMDEVINS pDevIns = PCNETSTATE_2_DEVINS(pThis);
    18301830    int is_padr = 0, is_bcast = 0, is_ladr = 0;
    18311831    unsigned iRxDesc;
    1832     int pkt_size;
    1833 
    1834     if (RT_UNLIKELY(CSR_DRX(pThis) || CSR_STOP(pThis) || CSR_SPND(pThis) || !size))
     1832    int cbPacket;
     1833
     1834    if (RT_UNLIKELY(CSR_DRX(pThis) || CSR_STOP(pThis) || CSR_SPND(pThis) || !cbToRecv))
    18351835        return;
    18361836
     
    18411841        return;
    18421842
    1843     Log(("#%d pcnetReceiveNoSync: size=%d\n", PCNET_INST_NR, size));
     1843    Log(("#%d pcnetReceiveNoSync: size=%d\n", PCNET_INST_NR, cbToRecv));
    18441844
    18451845    /*
     
    18471847     */
    18481848    if (   CSR_PROM(pThis)
    1849         || (is_padr  = padr_match(pThis, buf, size))
    1850         || (is_bcast = padr_bcast(pThis, buf, size))
    1851         || (is_ladr  = ladr_match(pThis, buf, size)))
     1849        || (is_padr  = padr_match(pThis, buf, cbToRecv))
     1850        || (is_bcast = padr_bcast(pThis, buf, cbToRecv))
     1851        || (is_ladr  = ladr_match(pThis, buf, cbToRecv)))
    18521852    {
    18531853        if (HOST_IS_OWNER(CSR_CRST(pThis)))
     
    18781878            RTGCPHYS32 crda = CSR_CRDA(pThis);
    18791879            RTGCPHYS32 next_crda;
    1880             RMD      rmd, next_rmd;
    1881 
    1882             memcpy(src, buf, size);
     1880            RMD        rmd, next_rmd;
     1881
     1882            memcpy(src, buf, cbToRecv);
    18831883            if (!CSR_ASTRP_RCV(pThis))
    18841884            {
     
    18861886                uint8_t *p = src;
    18871887
    1888                 while (size < 60)
    1889                     src[size++] = 0;
    1890                 while (p != &src[size])
     1888                while (cbToRecv < 60)
     1889                    src[cbToRecv++] = 0;
     1890                while (p != &src[cbToRecv])
    18911891                    CRC(fcs, *p++);
    1892                 ((uint32_t *)&src[size])[0] = htonl(fcs);
     1892                ((uint32_t *)&src[cbToRecv])[0] = htonl(fcs);
    18931893                /* FCS at end of packet */
    18941894            }
    1895             size += 4;
    1896             pkt_size = (int)size;                           Assert((size_t)pkt_size == size);
     1895            cbToRecv += 4;
     1896            cbPacket = (int)cbToRecv;                           Assert((size_t)cbPacket == cbToRecv);
    18971897
    18981898#ifdef PCNET_DEBUG_MATCH
     
    19041904                rmd.rmd1.stp = 1;
    19051905
    1906             size_t count = RT_MIN(4096 - (size_t)rmd.rmd1.bcnt, size);
     1906            size_t cbBuf = RT_MIN(4096 - (size_t)rmd.rmd1.bcnt, cbToRecv);
    19071907            RTGCPHYS32 rbadr = PHYSADDR(pThis, rmd.rmd0.rbadr);
     1908
     1909            /* save the old value to check if it was changed as long as we didn't
     1910             * hold the critical section */
     1911            iRxDesc = CSR_RCVRC(pThis);
    19081912
    19091913            /* We have to leave the critical section here or we risk deadlocking
     
    19171921             */
    19181922            PDMCritSectLeave(&pThis->CritSect);
    1919             PDMDevHlpPhysWrite(pDevIns, rbadr, src, count);
     1923            PDMDevHlpPhysWrite(pDevIns, rbadr, src, cbBuf);
    19201924            int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
    19211925            AssertReleaseRC(rc);
    19221926
    1923             src  += count;
    1924             size -= count;
    1925 
    1926             /* adapt the current RX descriptor counter */
    1927             iRxDesc = CSR_RCVRC(pThis);
    1928             if (iRxDesc-- < 2)
    1929                 iRxDesc = CSR_RCVRL(pThis);
    1930             CSR_RCVRC(pThis) = iRxDesc;
    1931 
    1932             while (size > 0)
     1927            /* RX disabled in the meantime? If so, abort RX. */
     1928            if (RT_UNLIKELY(CSR_DRX(pThis) || CSR_STOP(pThis) || CSR_SPND(pThis)))
     1929                return;
     1930
     1931            /* Was the register modified in the meantime? If so, don't touch the
     1932             * register but still update the RX descriptor. */
     1933            if (RT_LIKELY(iRxDesc == CSR_RCVRC(pThis)))
     1934            {
     1935                if (iRxDesc-- < 2)
     1936                    iRxDesc = CSR_RCVRL(pThis);
     1937                CSR_RCVRC(pThis) = iRxDesc;
     1938            }
     1939            else
     1940                iRxDesc = CSR_RCVRC(pThis);
     1941
     1942            src      += cbBuf;
     1943            cbToRecv -= cbBuf;
     1944
     1945            while (cbToRecv > 0)
    19331946            {
    19341947                /* Read the entire next descriptor as we're likely to need it. */
     
    19481961                rmd  = next_rmd;
    19491962
    1950                 count = RT_MIN(4096 - (size_t)rmd.rmd1.bcnt, size);
     1963                cbBuf = RT_MIN(4096 - (size_t)rmd.rmd1.bcnt, cbToRecv);
    19511964                RTGCPHYS32 rbadr = PHYSADDR(pThis, rmd.rmd0.rbadr);
    19521965
     
    19551968                 * handler associated with it. See above for additional comments. */
    19561969                PDMCritSectLeave(&pThis->CritSect);
    1957                 PDMDevHlpPhysWrite(pDevIns, rbadr, src, count);
    1958                 int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
     1970                PDMDevHlpPhysWrite(pDevIns, rbadr, src, cbBuf);
     1971                rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
    19591972                AssertReleaseRC(rc);
    19601973
    1961                 src  += count;
    1962                 size -= count;
    1963 
    1964                 /* adapt the current RX descriptor counter */
    1965                 iRxDesc = CSR_RCVRC(pThis);
    1966                 if (iRxDesc-- < 1)
    1967                     iRxDesc = CSR_RCVRL(pThis);
    1968                 CSR_RCVRC(pThis) = iRxDesc;
     1974                /* RX disabled in the meantime? If so, abort RX. */
     1975                if (RT_UNLIKELY(CSR_DRX(pThis) || CSR_STOP(pThis) || CSR_SPND(pThis)))
     1976                    return;
     1977
     1978                /* Was the register modified in the meantime? If so, don't touch the
     1979                 * register but still update the RX descriptor. */
     1980                if (RT_LIKELY(iRxDesc == CSR_RCVRC(pThis)))
     1981                {
     1982                    if (iRxDesc-- < 2)
     1983                        iRxDesc = CSR_RCVRL(pThis);
     1984                    CSR_RCVRC(pThis) = iRxDesc;
     1985                }
     1986                else
     1987                    iRxDesc = CSR_RCVRC(pThis);
     1988
     1989                src      += cbBuf;
     1990                cbToRecv -= cbBuf;
    19691991            }
    19701992
    1971             if (RT_LIKELY(size == 0))
     1993            if (RT_LIKELY(cbToRecv == 0))
    19721994            {
    19731995                rmd.rmd1.enp  = 1;
     
    19751997                rmd.rmd1.lafm = !CSR_PROM(pThis) && is_ladr;
    19761998                rmd.rmd1.bam  = !CSR_PROM(pThis) && is_bcast;
    1977                 rmd.rmd2.mcnt = pkt_size;
    1978 
    1979                 STAM_REL_COUNTER_ADD(&pThis->StatReceiveBytes, pkt_size);
     1999                rmd.rmd2.mcnt = cbPacket;
     2000
     2001                STAM_REL_COUNTER_ADD(&pThis->StatReceiveBytes, cbPacket);
    19802002            }
    19812003            else
    19822004            {
    1983                 Log(("#%d: Overflow by %ubytes\n", PCNET_INST_NR, size));
     2005                Log(("#%d: Overflow by %ubytes\n", PCNET_INST_NR, cbToRecv));
    19842006                rmd.rmd1.oflo = 1;
    19852007                rmd.rmd1.buff = 1;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette