VirtualBox

Changeset 71456 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Mar 22, 2018 2:08:12 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
121425
Message:

Dev/E1000: (bugref:7346) Phar Lap ETS support: fetch RX descriptors when advancing RDH to allow using an entire ring (RDH==RDT).

File:
1 edited

Legend:

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

    r71190 r71456  
    17831783
    17841784
    1785 #if defined(E1K_WITH_RXD_CACHE) && defined(IN_RING3) /* currently only used in ring-3 due to stack space requirements of the caller */
     1785#ifdef E1K_WITH_RXD_CACHE
     1786/**
     1787 * Return the number of RX descriptor that belong to the hardware.
     1788 *
     1789 * @returns the number of available descriptors in RX ring.
     1790 * @param   pThis       The device state structure.
     1791 * @thread  ???
     1792 */
     1793DECLINLINE(uint32_t) e1kGetRxLen(PE1KSTATE pThis)
     1794{
     1795    /**
     1796     *  Make sure RDT won't change during computation. EMT may modify RDT at
     1797     *  any moment.
     1798     */
     1799    uint32_t rdt = RDT;
     1800    return (RDH > rdt ? RDLEN/sizeof(E1KRXDESC) : 0) + rdt - RDH;
     1801}
     1802
     1803DECLINLINE(unsigned) e1kRxDInCache(PE1KSTATE pThis)
     1804{
     1805    return pThis->nRxDFetched > pThis->iRxDCurrent ?
     1806        pThis->nRxDFetched - pThis->iRxDCurrent : 0;
     1807}
     1808
     1809DECLINLINE(unsigned) e1kRxDIsCacheEmpty(PE1KSTATE pThis)
     1810{
     1811    return pThis->iRxDCurrent >= pThis->nRxDFetched;
     1812}
     1813
     1814/**
     1815 * Load receive descriptors from guest memory. The caller needs to be in Rx
     1816 * critical section.
     1817 *
     1818 * We need two physical reads in case the tail wrapped around the end of RX
     1819 * descriptor ring.
     1820 *
     1821 * @returns the actual number of descriptors fetched.
     1822 * @param   pThis       The device state structure.
     1823 * @param   pDesc       Pointer to descriptor union.
     1824 * @param   addr        Physical address in guest context.
     1825 * @thread  EMT, RX
     1826 */
     1827DECLINLINE(unsigned) e1kRxDPrefetch(PE1KSTATE pThis)
     1828{
     1829    /* We've already loaded pThis->nRxDFetched descriptors past RDH. */
     1830    unsigned nDescsAvailable    = e1kGetRxLen(pThis) - e1kRxDInCache(pThis);
     1831    unsigned nDescsToFetch      = RT_MIN(nDescsAvailable, E1K_RXD_CACHE_SIZE - pThis->nRxDFetched);
     1832    unsigned nDescsTotal        = RDLEN / sizeof(E1KRXDESC);
     1833    Assert(nDescsTotal != 0);
     1834    if (nDescsTotal == 0)
     1835        return 0;
     1836    unsigned nFirstNotLoaded    = (RDH + e1kRxDInCache(pThis)) % nDescsTotal;
     1837    unsigned nDescsInSingleRead = RT_MIN(nDescsToFetch, nDescsTotal - nFirstNotLoaded);
     1838    E1kLog3(("%s e1kRxDPrefetch: nDescsAvailable=%u nDescsToFetch=%u "
     1839             "nDescsTotal=%u nFirstNotLoaded=0x%x nDescsInSingleRead=%u\n",
     1840             pThis->szPrf, nDescsAvailable, nDescsToFetch, nDescsTotal,
     1841             nFirstNotLoaded, nDescsInSingleRead));
     1842    if (nDescsToFetch == 0)
     1843        return 0;
     1844    E1KRXDESC* pFirstEmptyDesc = &pThis->aRxDescriptors[pThis->nRxDFetched];
     1845    PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
     1846                      ((uint64_t)RDBAH << 32) + RDBAL + nFirstNotLoaded * sizeof(E1KRXDESC),
     1847                      pFirstEmptyDesc, nDescsInSingleRead * sizeof(E1KRXDESC));
     1848    // uint64_t addrBase = ((uint64_t)RDBAH << 32) + RDBAL;
     1849    // unsigned i, j;
     1850    // for (i = pThis->nRxDFetched; i < pThis->nRxDFetched + nDescsInSingleRead; ++i)
     1851    // {
     1852    //     pThis->aRxDescAddr[i] = addrBase + (nFirstNotLoaded + i - pThis->nRxDFetched) * sizeof(E1KRXDESC);
     1853    //     E1kLog3(("%s aRxDescAddr[%d] = %p\n", pThis->szPrf, i, pThis->aRxDescAddr[i]));
     1854    // }
     1855    E1kLog3(("%s Fetched %u RX descriptors at %08x%08x(0x%x), RDLEN=%08x, RDH=%08x, RDT=%08x\n",
     1856             pThis->szPrf, nDescsInSingleRead,
     1857             RDBAH, RDBAL + RDH * sizeof(E1KRXDESC),
     1858             nFirstNotLoaded, RDLEN, RDH, RDT));
     1859    if (nDescsToFetch > nDescsInSingleRead)
     1860    {
     1861        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
     1862                          ((uint64_t)RDBAH << 32) + RDBAL,
     1863                          pFirstEmptyDesc + nDescsInSingleRead,
     1864                          (nDescsToFetch - nDescsInSingleRead) * sizeof(E1KRXDESC));
     1865        // Assert(i == pThis->nRxDFetched  + nDescsInSingleRead);
     1866        // for (j = 0; i < pThis->nRxDFetched + nDescsToFetch; ++i, ++j)
     1867        // {
     1868        //     pThis->aRxDescAddr[i] = addrBase + j * sizeof(E1KRXDESC);
     1869        //     E1kLog3(("%s aRxDescAddr[%d] = %p\n", pThis->szPrf, i, pThis->aRxDescAddr[i]));
     1870        // }
     1871        E1kLog3(("%s Fetched %u RX descriptors at %08x%08x\n",
     1872                 pThis->szPrf, nDescsToFetch - nDescsInSingleRead,
     1873                 RDBAH, RDBAL));
     1874    }
     1875    pThis->nRxDFetched += nDescsToFetch;
     1876    return nDescsToFetch;
     1877}
     1878
     1879# ifdef IN_RING3 /* currently only used in ring-3 due to stack space requirements of the caller */
    17861880/**
    17871881 * Dump receive descriptor to debug log.
     
    18131907             E1K_SPEC_PRI(pDesc->status.u16Special)));
    18141908}
    1815 #endif /* E1K_WITH_RXD_CACHE && IN_RING3 */
     1909# endif /* IN_RING3 */
     1910#endif /* E1K_WITH_RXD_CACHE */
    18161911
    18171912/**
     
    20052100    if (++RDH * sizeof(E1KRXDESC) >= RDLEN)
    20062101        RDH = 0;
     2102#ifdef E1K_WITH_RXD_CACHE
     2103    /*
     2104     * We need to fetch descriptors now as the guest may advance RDT all the way
     2105     * to RDH as soon as we generate RXDMT0 interrupt. This is mostly to provide
     2106     * compatibility with Phar Lap ETS, see @bugref(7346). Note that we do not
     2107     * check if the receiver is enabled. It must be, otherwise we won't get here
     2108     * in the first place.
     2109     *
     2110     * Note that we should have moved both RDH and iRxDCurrent by now.
     2111     */
     2112    if (e1kRxDIsCacheEmpty(pThis))
     2113    {
     2114        /* Cache is empty, reset it and check if we can fetch more. */
     2115        pThis->iRxDCurrent = pThis->nRxDFetched = 0;
     2116        E1kLog3(("%s e1kAdvanceRDH: Rx cache is empty, RDH=%x RDT=%x "
     2117                 "iRxDCurrent=%x nRxDFetched=%x\n",
     2118                 pThis->szPrf, RDH, RDT, pThis->iRxDCurrent, pThis->nRxDFetched));
     2119        e1kRxDPrefetch(pThis);
     2120    }
     2121#endif /* E1K_WITH_RXD_CACHE */
    20072122    /*
    20082123     * Compute current receive queue length and fire RXDMT0 interrupt
     
    20342149#ifdef E1K_WITH_RXD_CACHE
    20352150
    2036 /**
    2037  * Return the number of RX descriptor that belong to the hardware.
    2038  *
    2039  * @returns the number of available descriptors in RX ring.
    2040  * @param   pThis       The device state structure.
    2041  * @thread  ???
    2042  */
    2043 DECLINLINE(uint32_t) e1kGetRxLen(PE1KSTATE pThis)
    2044 {
    2045     /**
    2046      *  Make sure RDT won't change during computation. EMT may modify RDT at
    2047      *  any moment.
    2048      */
    2049     uint32_t rdt = RDT;
    2050     return (RDH > rdt ? RDLEN/sizeof(E1KRXDESC) : 0) + rdt - RDH;
    2051 }
    2052 
    2053 DECLINLINE(unsigned) e1kRxDInCache(PE1KSTATE pThis)
    2054 {
    2055     return pThis->nRxDFetched > pThis->iRxDCurrent ?
    2056         pThis->nRxDFetched - pThis->iRxDCurrent : 0;
    2057 }
    2058 
    2059 DECLINLINE(unsigned) e1kRxDIsCacheEmpty(PE1KSTATE pThis)
    2060 {
    2061     return pThis->iRxDCurrent >= pThis->nRxDFetched;
    2062 }
    2063 
    2064 /**
    2065  * Load receive descriptors from guest memory. The caller needs to be in Rx
    2066  * critical section.
    2067  *
    2068  * We need two physical reads in case the tail wrapped around the end of RX
    2069  * descriptor ring.
    2070  *
    2071  * @returns the actual number of descriptors fetched.
    2072  * @param   pThis       The device state structure.
    2073  * @param   pDesc       Pointer to descriptor union.
    2074  * @param   addr        Physical address in guest context.
    2075  * @thread  EMT, RX
    2076  */
    2077 DECLINLINE(unsigned) e1kRxDPrefetch(PE1KSTATE pThis)
    2078 {
    2079     /* We've already loaded pThis->nRxDFetched descriptors past RDH. */
    2080     unsigned nDescsAvailable    = e1kGetRxLen(pThis) - e1kRxDInCache(pThis);
    2081     unsigned nDescsToFetch      = RT_MIN(nDescsAvailable, E1K_RXD_CACHE_SIZE - pThis->nRxDFetched);
    2082     unsigned nDescsTotal        = RDLEN / sizeof(E1KRXDESC);
    2083     Assert(nDescsTotal != 0);
    2084     if (nDescsTotal == 0)
    2085         return 0;
    2086     unsigned nFirstNotLoaded    = (RDH + e1kRxDInCache(pThis)) % nDescsTotal;
    2087     unsigned nDescsInSingleRead = RT_MIN(nDescsToFetch, nDescsTotal - nFirstNotLoaded);
    2088     E1kLog3(("%s e1kRxDPrefetch: nDescsAvailable=%u nDescsToFetch=%u "
    2089              "nDescsTotal=%u nFirstNotLoaded=0x%x nDescsInSingleRead=%u\n",
    2090              pThis->szPrf, nDescsAvailable, nDescsToFetch, nDescsTotal,
    2091              nFirstNotLoaded, nDescsInSingleRead));
    2092     if (nDescsToFetch == 0)
    2093         return 0;
    2094     E1KRXDESC* pFirstEmptyDesc = &pThis->aRxDescriptors[pThis->nRxDFetched];
    2095     PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
    2096                       ((uint64_t)RDBAH << 32) + RDBAL + nFirstNotLoaded * sizeof(E1KRXDESC),
    2097                       pFirstEmptyDesc, nDescsInSingleRead * sizeof(E1KRXDESC));
    2098     // uint64_t addrBase = ((uint64_t)RDBAH << 32) + RDBAL;
    2099     // unsigned i, j;
    2100     // for (i = pThis->nRxDFetched; i < pThis->nRxDFetched + nDescsInSingleRead; ++i)
    2101     // {
    2102     //     pThis->aRxDescAddr[i] = addrBase + (nFirstNotLoaded + i - pThis->nRxDFetched) * sizeof(E1KRXDESC);
    2103     //     E1kLog3(("%s aRxDescAddr[%d] = %p\n", pThis->szPrf, i, pThis->aRxDescAddr[i]));
    2104     // }
    2105     E1kLog3(("%s Fetched %u RX descriptors at %08x%08x(0x%x), RDLEN=%08x, RDH=%08x, RDT=%08x\n",
    2106              pThis->szPrf, nDescsInSingleRead,
    2107              RDBAH, RDBAL + RDH * sizeof(E1KRXDESC),
    2108              nFirstNotLoaded, RDLEN, RDH, RDT));
    2109     if (nDescsToFetch > nDescsInSingleRead)
    2110     {
    2111         PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
    2112                           ((uint64_t)RDBAH << 32) + RDBAL,
    2113                           pFirstEmptyDesc + nDescsInSingleRead,
    2114                           (nDescsToFetch - nDescsInSingleRead) * sizeof(E1KRXDESC));
    2115         // Assert(i == pThis->nRxDFetched  + nDescsInSingleRead);
    2116         // for (j = 0; i < pThis->nRxDFetched + nDescsToFetch; ++i, ++j)
    2117         // {
    2118         //     pThis->aRxDescAddr[i] = addrBase + j * sizeof(E1KRXDESC);
    2119         //     E1kLog3(("%s aRxDescAddr[%d] = %p\n", pThis->szPrf, i, pThis->aRxDescAddr[i]));
    2120         // }
    2121         E1kLog3(("%s Fetched %u RX descriptors at %08x%08x\n",
    2122                  pThis->szPrf, nDescsToFetch - nDescsInSingleRead,
    2123                  RDBAH, RDBAL));
    2124     }
    2125     pThis->nRxDFetched += nDescsToFetch;
    2126     return nDescsToFetch;
    2127 }
    2128 
    21292151# ifdef IN_RING3 /* currently only used in ring-3 due to stack space requirements of the caller */
    21302152
     
    21752197                          e1kDescAddr(RDBAH, RDBAL, RDH),
    21762198                          pDesc, sizeof(E1KRXDESC));
     2199    /*
     2200     * We need to print the descriptor before advancing RDH as it may fetch new
     2201     * descriptors into the cache.
     2202     */
     2203    e1kPrintRDesc(pThis, pDesc);
    21772204    e1kAdvanceRDH(pThis);
    2178     e1kPrintRDesc(pThis, pDesc);
    21792205}
    21802206
     
    21972223}
    21982224
    2199 # endif
     2225# endif /* IN_RING3 */
    22002226
    22012227#else /* !E1K_WITH_RXD_CACHE */
     
    31843210    {
    31853211        E1kLog(("%s e1kRegWriteRDT\n",  pThis->szPrf));
     3212#ifndef E1K_WITH_RXD_CACHE
    31863213        /*
    31873214         * Some drivers advance RDT too far, so that it equals RDH. This
     
    31983225                value = RDH - 1;
    31993226        }
     3227#endif /* !E1K_WITH_RXD_CACHE */
    32003228        rc = e1kRegWriteDefault(pThis, offset, index, value);
    32013229#ifdef E1K_WITH_RXD_CACHE
Note: See TracChangeset for help on using the changeset viewer.

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