VirtualBox

Changeset 83913 in vbox for trunk/src/VBox/Devices/VirtIO


Ignore:
Timestamp:
Apr 22, 2020 4:52:12 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
137452
Message:

Network/DevVirtioNet_1_0.cpp: Various fixes and improvements, most notably: Implemented SSM (save, restore, pause, resume, stop) all tested, implemented STAM similarly to DevVirtioNet.cpp, verified, added support for VIRTIO_F_EVENT_IDX feature, improved internal handling of Rx/Tx queue pair mgt (will facility multiqueue (MQ) feature better), fixed various @todo's added by bird

Location:
trunk/src/VBox/Devices/VirtIO
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r83664 r83913  
    174174DECLINLINE(bool) virtqIsEmpty(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
    175175{
    176     uint16_t uAvailGuest = virtioReadAvailRingIdx(pDevIns, pVirtio, idxQueue);
    177     bool fEmpty = uAvailGuest == pVirtio->virtqState[idxQueue].uAvailIdx;
    178 
    179     Log6Func(("%s: uAvailGuest=%u uAvailIdx=%u. (%s)\n",
    180              VIRTQNAME(pVirtio, idxQueue), uAvailGuest, pVirtio->virtqState[idxQueue].uAvailIdx,
     176    uint16_t uAvailGuestIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, idxQueue);
     177    bool fEmpty = uAvailGuestIdx == pVirtio->virtqState[idxQueue].uAvailIdx;
     178
     179    Log6Func(("%s idx=%u, shadow idx=%u (%s)\n",
     180             VIRTQNAME(pVirtio, idxQueue), uAvailGuestIdx, pVirtio->virtqState[idxQueue].uAvailIdx,
    181181             fEmpty ? "Queue empty" : "Queue has available descriptors"));
    182182    return fEmpty;
     
    266266}
    267267
    268 #if 0 /* unused - *May* be used when VIRTIO_F_EVENT_IDX optional feature is implemented VirtIO 1.0, 2.4.9.2*/
    269268DECLINLINE(void) virtioWriteUsedAvailEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, uint32_t uAvailEventIdx)
    270269{
     
    275274                          &uAvailEventIdx, sizeof(uAvailEventIdx));
    276275}
    277 #endif
    278276
    279277
     
    390388}
    391389
     390size_t virtioCoreSgBufCalcTotalLength(PVIRTIOSGBUF pGcSgBuf)
     391{
     392    size_t   cb = 0;
     393    unsigned i  = pGcSgBuf->cSegs;
     394     while (i-- > 0)
     395         cb += pGcSgBuf->paSegs[i].cbSeg;
     396     return cb;
     397 }
     398
    392399#ifdef LOG_ENABLED
     400
     401void virtioPrintFeatures(VIRTIOCORE *pVirtio)
     402{
     403#ifdef LOG_ENABLED
     404    static struct
     405    {
     406        uint64_t fFeatureBit;
     407        const char *pcszDesc;
     408    } const s_aFeatures[] =
     409    {
     410        { VIRTIO_F_RING_INDIRECT_DESC,      "   RING_INDIRECT_DESC   Driver can use descriptors with VIRTQ_DESC_F_INDIRECT flag set\n" },
     411        { VIRTIO_F_RING_EVENT_IDX,          "   RING_EVENT_IDX       Enables use_event and avail_event fields described in 2.4.7, 2.4.8\n" },
     412        { VIRTIO_F_VERSION_1,               "   VERSION              Used to detect legacy drivers.\n" },
     413    };
     414
     415#define MAXLINE 80
     416    /* Display as a single buf to prevent interceding log messages */
     417    uint16_t cbBuf = RT_ELEMENTS(s_aFeatures) * 132;
     418    char *pszBuf = (char *)RTMemAllocZ(cbBuf);
     419    Assert(pszBuf);
     420    char *cp = pszBuf;
     421    for (unsigned i = 0; i < RT_ELEMENTS(s_aFeatures); ++i)
     422    {
     423        bool isOffered    = pVirtio->uDeviceFeatures  & s_aFeatures[i].fFeatureBit;
     424        bool isNegotiated = pVirtio->uDriverFeatures  & s_aFeatures[i].fFeatureBit;
     425        cp += RTStrPrintf(cp, cbBuf - (cp - pszBuf), "        %s       %s   %s",
     426                          isOffered ? "+" : "-", isNegotiated ? "x" : " ", s_aFeatures[i].pcszDesc);
     427    }
     428    Log3(("VirtIO Features Configuration\n\n"
     429          "    Offered  Accepted  Feature              Description\n"
     430          "    -------  --------  -------              -----------\n"
     431          "%s\n", pszBuf));
     432    RTMemFree(pszBuf);
     433
     434#else  /* !LOG_ENABLED */
     435    RT_NOREF3(pThis, fFeatures, pcszText);
     436#endif /* !LOG_ENABLED */
     437}
     438
    393439
    394440/**
     
    910956    uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, idxQueue, pVirtq->uAvailIdx);
    911957
     958    if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX)
     959        virtioWriteUsedAvailEvent(pDevIns,pVirtio, idxQueue, pVirtq->uAvailIdx + 1);
     960
    912961    if (fRemove)
    913962        pVirtq->uAvailIdx++;
     
    9611010    Assert(pDescChain->cRefs > 0);
    9621011
    963     AssertMsgReturn(IS_DRIVER_OK(pVirtio) /*&& pVirtio->uQueueEnable[idxQueue]*/,
    964                     ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
     1012    AssertMsgReturn(IS_DRIVER_OK(pVirtio), ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
    9651013
    9661014    Log6Func(("Copying client data to %s, desc chain (head desc_idx %d)\n",
     
    9731021    if (pSgVirtReturn)
    9741022    {
     1023        size_t cbTarget = virtioCoreSgBufCalcTotalLength(pSgPhysReturn);
    9751024        cbRemain = cbTotal = RTSgBufCalcTotalLength(pSgVirtReturn);
     1025        AssertMsgReturn(cbTarget >= cbRemain, ("Not space to write data to phys memory"), VERR_BUFFER_OVERFLOW);
    9761026        virtioCoreSgBufReset(pSgPhysReturn); /* Reset ptr because req data may have already been written */
    9771027        while (cbRemain)
    9781028        {
    979             PVIRTIOSGSEG paSeg = &pSgPhysReturn->paSegs[pSgPhysReturn->idxSeg];
    980             /** @todo r=bird: Shouldn't this be: RT_MIN(pSgVirtReturn->cbSegLeft, pSgPhysReturn->cbSegLeft); */
    981             cbCopy = RT_MIN(pSgVirtReturn->cbSegLeft, paSeg->cbSeg - (size_t)(pSgPhysReturn->gcPhysCur - paSeg->gcPhys));
    982             Assert(cbCopy > 0); /** @todo r=bird: There is no check that there is sufficient space in the output
    983                                  * buffer (pSgPhysReturn), so we might loop here forever if the caller is careless,
    984                                  * right?  I'm pretty sure virtioScsiR3SendEvent could do more checks. */
     1029            cbCopy = RT_MIN(pSgVirtReturn->cbSegLeft,  pSgPhysReturn->cbSegLeft);
     1030            Assert(cbCopy > 0);
    9851031            PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)pSgPhysReturn->gcPhysCur, pSgVirtReturn->pvSegCur, cbCopy);
    9861032            RTSgBufAdvance(pSgVirtReturn, cbCopy);
     
    10301076 * @param   pVirtio     Pointer to the shared virtio state.
    10311077 * @param   idxQueue    Queue number
     1078 * @param   fForce      Force guest notification even if VIRTQ_USED_F_NO_NOTIFY is set
    10321079 *
    10331080 * @returns VBox status code.
     
    10351082 * @retval  VERR_INVALID_STATE VirtIO not in ready state
    10361083 */
    1037 int virtioCoreQueueSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
     1084int virtioCoreQueueSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fForce)
    10381085{
    10391086    Assert(idxQueue < RT_ELEMENTS(pVirtio->virtqState));
     
    10471094
    10481095    virtioWriteUsedRingIdx(pDevIns, pVirtio, idxQueue, pVirtq->uUsedIdx);
    1049     virtioNotifyGuestDriver(pDevIns, pVirtio, idxQueue, false);
     1096    virtioNotifyGuestDriver(pDevIns, pVirtio, idxQueue, fForce);
    10501097
    10511098    return VINF_SUCCESS;
     
    11011148        if (pVirtq->fEventThresholdReached)
    11021149        {
     1150#ifdef IN_RING3
     1151        Log6Func(("...kicking guest %s, VIRTIO_F_EVENT_IDX set and threshold (%d) reached\n",
     1152                   VIRTQNAME(pVirtio, idxQueue), (uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxQueue)));
     1153#else
     1154        Log6Func(("... kicking guest %s, VIRTIO_F_EVENT_IDX set and threshold reached\n",
     1155                   VIRTQNAME(pVirtio, idxQueue)));
     1156#endif
    11031157            virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uQueueMsixVector[idxQueue], fForce);
    11041158            pVirtq->fEventThresholdReached = false;
    11051159            return;
    11061160        }
    1107         Log6Func(("...skipping interrupt: VIRTIO_F_EVENT_IDX set but threshold not reached\n"));
     1161#ifdef IN_RING3
     1162        Log6Func(("...skipping interrupt %s, VIRTIO_F_EVENT_IDX set but threshold (%d) not reached (%d)\n",
     1163                   VIRTQNAME(pVirtio, idxQueue),(uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxQueue), pVirtq->uUsedIdx));
     1164#else
     1165        Log6Func(("...skipping interrupt %s, VIRTIO_F_EVENT_IDX set but threshold not reached\n",
     1166                    VIRTQNAME(pVirtio, idxQueue)));
     1167#endif
    11081168    }
    11091169    else
     
    11121172        if (fForce || !(virtioReadUsedRingFlags(pDevIns, pVirtio, idxQueue) & VIRTQ_AVAIL_F_NO_INTERRUPT))
    11131173        {
     1174            if (fForce)
     1175                Log6Func(("... kicking guest, queue %s, because force flag set\n"));
    11141176            virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uQueueMsixVector[idxQueue], fForce);
    11151177            return;
    11161178        }
    1117 /** TEMPORARY DEBUGGING HACK, EVALUATE AND REMOVE */
    1118 virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uQueueMsixVector[idxQueue], fForce);
    1119 
    1120         Log6Func(("...skipping interrupt. Guest flagged VIRTQ_AVAIL_F_NO_INTERRUPT for queue\n"));
     1179        Log6Func(("...skipping interrupt, queue %s, Guest flagged VIRTQ_AVAIL_F_NO_INTERRUPT for queue\n"));
    11211180    }
    11221181}
     
    11341193{
    11351194    if (fForce)
    1136         Log6Func(("reason: resumed after suspend\n"));
     1195        Log6Func(("reason: forced\n"));
    11371196    else
    11381197    if (uCause == VIRTIO_ISR_VIRTQ_INTERRUPT)
     
    11701229{
    11711230    Assert(idxQueue < RT_ELEMENTS(pVirtio->virtqState));
    1172     PVIRTQSTATE pVirtQ = &pVirtio->virtqState[idxQueue];
    1173     pVirtQ->uAvailIdx = 0;
    1174     pVirtQ->uUsedIdx  = 0;
     1231    PVIRTQSTATE pVirtq = &pVirtio->virtqState[idxQueue];
     1232    pVirtq->uAvailIdx = 0;
     1233    pVirtq->uUsedIdx  = 0;
     1234    pVirtq->fEventThresholdReached = false;
    11751235    pVirtio->uQueueEnable[idxQueue] = false;
    11761236    pVirtio->uQueueSize[idxQueue] = VIRTQ_MAX_SIZE;
    11771237    pVirtio->uQueueNotifyOff[idxQueue] = idxQueue;
    11781238    pVirtio->uQueueMsixVector[idxQueue] = idxQueue + 2;
    1179 
    11801239    if (!pVirtio->fMsiSupport) /* VirtIO 1.0, 4.1.4.3 and 4.1.5.1.2 */
    11811240        pVirtio->uQueueMsixVector[idxQueue] = VIRTIO_MSI_NO_VECTOR;
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h

    r83603 r83913  
    269269    uint8_t                     uPrevDeviceStatus;                  /**< (MMIO) Prev Device Status           GUEST */
    270270    uint8_t                     uConfigGeneration;                  /**< (MMIO) Device config sequencer       HOST */
    271 
    272271    VIRTQSTATE                  virtqState[VIRTQ_MAX_CNT];          /**< Local impl-specific queue context         */
    273272
     
    281280    /** @} */
    282281
    283     bool                        fGenUpdatePending;                  /**< If set, update cfg gen after driver reads */
     282    bool                        fGenUpdatePending;                 /**< If set, update cfg gen after driver reads */
    284283    uint8_t                     uPciCfgDataOff;
    285     uint8_t                     uISR;                               /**< Interrupt Status Register.                */
     284    uint8_t                     uISR;                              /**< Interrupt Status Register.                */
    286285    uint8_t                     fMsiSupport;
    287286
     
    419418
    420419int  virtioCoreR3QueuePendingCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue);
    421 int  virtioCoreQueueSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue);
     420int  virtioCoreQueueSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fForce);
    422421bool virtioCoreQueueIsEmpty(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue);
    423422void virtioCoreQueueEnable(PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fEnabled);
     
    425424void virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio);
    426425void virtioCoreResetAll(PVIRTIOCORE pVirtio);
     426void virtioPrintFeatures(VIRTIOCORE *pVirtio);
    427427
    428428/**
     
    474474    return pVirtio->uDriverFeatures;
    475475}
     476
    476477
    477478/**
     
    503504size_t   virtioCoreSgBufCalcTotalLength(PCVIRTIOSGBUF pGcSgBuf);
    504505void     virtioCoreSgBufReset(PVIRTIOSGBUF pGcSgBuf);
     506size_t   virtioCoreSgBufCalcTotalLength(PVIRTIOSGBUF pGcSgBuf);
    505507int      virtioCoreR3SaveExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM);
    506508int      virtioCoreR3LoadExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM);
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