VirtualBox

Changeset 85291 in vbox for trunk


Ignore:
Timestamp:
Jul 13, 2020 7:37:06 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
139268
Message:

Networking/DevVirtioNet_1_0.cpp: Made some performance tweaks and minor cleanup

Location:
trunk/src/VBox/Devices
Files:
3 edited

Legend:

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

    r85109 r85291  
    14981498        if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
    14991499        {
    1500             LogFunc(("Waken due to %s\n", rc == VERR_TIMEOUT ? "timeout" : "getting interrupted"));
     1500            LogFunc(("Woken due to %s\n", rc == VERR_TIMEOUT ? "timeout" : "getting interrupted"));
    15011501            continue;
    15021502        }
     
    17521752            paVirtSegsToGuest[cSegs].pvSeg = ((uint8_t *)pvBuf) + uOffset;
    17531753            cbBufRemaining -= cbLimited;
    1754             uOffset        += cbLimited;
     1754            uOffset += cbLimited;
    17551755            cVirtqBufs++;
    17561756            cSegs++;
     
    19231923
    19241924        PVIRTIONETVIRTQ pRxVirtq = &pThis->aVirtqs[RXQIDX(uVirtqPair)];
    1925         if (RT_SUCCESS(!virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pRxVirtq)))
     1925        if (RT_SUCCESS(virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pRxVirtq)))
    19261926        {
    1927             /* Drop packets if VM is not running or cable is disconnected. */
    1928             if (!virtioNetIsOperational(pThis, pDevIns) || !IS_LINK_UP(pThis))
    1929                 return VINF_SUCCESS;
    1930 
    19311927            STAM_PROFILE_START(&pThis->StatReceive, a);
    19321928            virtioNetR3SetReadLed(pThisCC, true);
  • trunk/src/VBox/Devices/VirtIO/VirtioCore.cpp

    r85132 r85291  
    324324    return virtioCoreVirtqAvailBufCount_inline(pDevIns, pVirtio, pVirtq);
    325325}
    326 
    327 /** @} */
    328 
    329 void virtioCoreGCPhysChainInit(PVIRTIOSGBUF pGcSgBuf, PVIRTIOSGSEG paSegs, size_t cSegs)
    330 {
    331     AssertPtr(pGcSgBuf);
    332     Assert(   (cSegs > 0 && VALID_PTR(paSegs)) || (!cSegs && !paSegs));
    333     Assert(cSegs < (~(unsigned)0 >> 1));
    334 
    335     pGcSgBuf->paSegs = paSegs;
    336     pGcSgBuf->cSegs  = (unsigned)cSegs;
    337     pGcSgBuf->idxSeg = 0;
    338     if (cSegs && paSegs)
    339     {
    340         pGcSgBuf->GCPhysCur = paSegs[0].GCPhys;
    341         pGcSgBuf->cbSegLeft = paSegs[0].cbSeg;
    342     }
    343     else
    344     {
    345         pGcSgBuf->GCPhysCur = 0;
    346         pGcSgBuf->cbSegLeft = 0;
    347     }
    348 }
    349 
    350 static RTGCPHYS virtioCoreGCPhysChainGet(PVIRTIOSGBUF pGcSgBuf, size_t *pcbData)
    351 {
    352     size_t cbData;
    353     RTGCPHYS pGcBuf;
    354 
    355     /* Check that the S/G buffer has memory left. */
    356     if (RT_LIKELY(pGcSgBuf->idxSeg < pGcSgBuf->cSegs && pGcSgBuf->cbSegLeft))
    357     { /* likely */ }
    358     else
    359     {
    360         *pcbData = 0;
    361         return 0;
    362     }
    363 
    364     AssertMsg(    pGcSgBuf->cbSegLeft <= 128 * _1M
    365               && (RTGCPHYS)pGcSgBuf->GCPhysCur >= (RTGCPHYS)pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys
    366               && (RTGCPHYS)pGcSgBuf->GCPhysCur + pGcSgBuf->cbSegLeft <=
    367                    (RTGCPHYS)pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys + pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg,
    368                  ("pGcSgBuf->idxSeg=%d pGcSgBuf->cSegs=%d pGcSgBuf->GCPhysCur=%p pGcSgBuf->cbSegLeft=%zd "
    369                   "pGcSgBuf->paSegs[%d].GCPhys=%p pGcSgBuf->paSegs[%d].cbSeg=%zd\n",
    370                   pGcSgBuf->idxSeg, pGcSgBuf->cSegs, pGcSgBuf->GCPhysCur, pGcSgBuf->cbSegLeft,
    371                   pGcSgBuf->idxSeg, pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys, pGcSgBuf->idxSeg,
    372                   pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg));
    373 
    374     cbData = RT_MIN(*pcbData, pGcSgBuf->cbSegLeft);
    375     pGcBuf = pGcSgBuf->GCPhysCur;
    376     pGcSgBuf->cbSegLeft -= cbData;
    377     if (!pGcSgBuf->cbSegLeft)
    378     {
    379         pGcSgBuf->idxSeg++;
    380 
    381         if (pGcSgBuf->idxSeg < pGcSgBuf->cSegs)
    382         {
    383             pGcSgBuf->GCPhysCur = pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys;
    384             pGcSgBuf->cbSegLeft = pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg;
    385         }
    386         *pcbData = cbData;
    387     }
    388     else
    389         pGcSgBuf->GCPhysCur = pGcSgBuf->GCPhysCur + cbData;
    390 
    391     return pGcBuf;
    392 }
    393 
    394 void virtioCoreGCPhysChainReset(PVIRTIOSGBUF pGcSgBuf)
    395 {
    396     AssertPtrReturnVoid(pGcSgBuf);
    397 
    398     pGcSgBuf->idxSeg = 0;
    399     if (pGcSgBuf->cSegs)
    400     {
    401         pGcSgBuf->GCPhysCur = pGcSgBuf->paSegs[0].GCPhys;
    402         pGcSgBuf->cbSegLeft = pGcSgBuf->paSegs[0].cbSeg;
    403     }
    404     else
    405     {
    406         pGcSgBuf->GCPhysCur = 0;
    407         pGcSgBuf->cbSegLeft = 0;
    408     }
    409 }
    410 
    411 RTGCPHYS virtioCoreGCPhysChainAdvance(PVIRTIOSGBUF pGcSgBuf, size_t cbAdvance)
    412 {
    413     AssertReturn(pGcSgBuf, 0);
    414 
    415     size_t cbLeft = cbAdvance;
    416     while (cbLeft)
    417     {
    418         size_t cbThisAdvance = cbLeft;
    419         virtioCoreGCPhysChainGet(pGcSgBuf, &cbThisAdvance);
    420         if (!cbThisAdvance)
    421             break;
    422 
    423         cbLeft -= cbThisAdvance;
    424     }
    425     return cbAdvance - cbLeft;
    426 }
    427 
    428 RTGCPHYS virtioCoreGCPhysChainGetNextSeg(PVIRTIOSGBUF pGcSgBuf, size_t *pcbSeg)
    429 {
    430     AssertReturn(pGcSgBuf, 0);
    431     AssertPtrReturn(pcbSeg, 0);
    432 
    433     if (!*pcbSeg)
    434         *pcbSeg = pGcSgBuf->cbSegLeft;
    435 
    436     return virtioCoreGCPhysChainGet(pGcSgBuf, pcbSeg);
    437 }
    438 
    439 size_t virtioCoreGCPhysChainCalcBufSize(PVIRTIOSGBUF pGcSgBuf)
    440 {
    441     size_t   cb = 0;
    442     unsigned i  = pGcSgBuf->cSegs;
    443      while (i-- > 0)
    444          cb += pGcSgBuf->paSegs[i].cbSeg;
    445      return cb;
    446  }
    447326
    448327#ifdef IN_RING3
     
    763642
    764643/** API Function: See header file */
     644uint32_t virtioCoreR3VirtqBufRetain(PVIRTQBUF pVirtqBuf)
     645{
     646    AssertReturn(pVirtqBuf, UINT32_MAX);
     647    AssertReturn(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC, UINT32_MAX);
     648    uint32_t cRefs = ASMAtomicIncU32(&pVirtqBuf->cRefs);
     649    Assert(cRefs > 1);
     650    Assert(cRefs < 16);
     651    return cRefs;
     652}
     653
     654
     655/** API Function: See header file */
     656uint32_t virtioCoreR3VirtqBufRelease(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf)
     657{
     658    if (!pVirtqBuf)
     659        return 0;
     660    AssertReturn(pVirtqBuf, 0);
     661    AssertReturn(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC, 0);
     662    uint32_t cRefs = ASMAtomicDecU32(&pVirtqBuf->cRefs);
     663    Assert(cRefs < 16);
     664    if (cRefs == 0)
     665    {
     666        pVirtqBuf->u32Magic = ~VIRTQBUF_MAGIC;
     667        RTMemFree(pVirtqBuf);
     668        STAM_REL_COUNTER_INC(&pVirtio->StatDescChainsFreed);
     669    }
     670    return cRefs;
     671}
     672
     673/** API Function: See header file */
     674void virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio)
     675{
     676    virtioKick(pVirtio->pDevInsR3, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig);
     677}
     678
     679/** API Function: See header file */
     680void virtioCoreVirtqEnableNotify(PVIRTIOCORE pVirtio, uint16_t uVirtq, bool fEnable)
     681{
     682
     683    Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues));
     684    PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq];
     685
     686    if (pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
     687    {
     688        uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, pVirtq);
     689
     690        if (fEnable)
     691            fFlags &= ~ VIRTQ_USED_F_NO_NOTIFY;
     692        else
     693            fFlags |= VIRTQ_USED_F_NO_NOTIFY;
     694
     695        virtioWriteUsedRingFlags(pVirtio->pDevInsR3, pVirtio, pVirtq, fFlags);
     696    }
     697}
     698
     699/** API function: See Header file  */
     700void virtioCoreResetAll(PVIRTIOCORE pVirtio)
     701{
     702    LogFunc(("\n"));
     703    pVirtio->fDeviceStatus |= VIRTIO_STATUS_DEVICE_NEEDS_RESET;
     704    if (pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
     705    {
     706        pVirtio->fGenUpdatePending = true;
     707        virtioKick(pVirtio->pDevInsR3, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig);
     708    }
     709}
     710
     711/** API function: See Header file  */
     712int virtioCoreR3VirtqAvailBufPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq,
     713                         PPVIRTQBUF ppVirtqBuf)
     714{
     715    return virtioCoreR3VirtqAvailBufGet(pDevIns, pVirtio, uVirtq, ppVirtqBuf, false);
     716}
     717
     718/** API function: See Header file  */
     719int virtioCoreR3VirtqAvailBufNext(PVIRTIOCORE pVirtio, uint16_t uVirtq)
     720{
     721    Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues));
     722
     723    PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq];
     724
     725    AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtq->uEnable,
     726                    ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
     727
     728    if (IS_VIRTQ_EMPTY(pVirtio->pDevInsR3, pVirtio, pVirtq))
     729        return VERR_NOT_AVAILABLE;
     730
     731    Log6Func(("%s avail shadow idx: %u\n", pVirtq->szName, pVirtq->uAvailIdxShadow));
     732    pVirtq->uAvailIdxShadow++;
     733
     734    return VINF_SUCCESS;
     735}
     736
     737
     738/** API Function: See header file */
    765739int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq,
    766740                             uint16_t uHeadIdx, PPVIRTQBUF ppVirtqBuf)
     
    771745    AssertMsgReturn(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues),
    772746                        ("uVirtq out of range"), VERR_INVALID_PARAMETER);
     747
    773748    PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq];
    774 
    775     if (!IS_DRIVER_OK(pVirtio) || !pVirtq->uEnable)
    776     {
    777         LogRelFunc(("Driver not ready or queue not enabled\n"));
    778         return 0;
    779     }
    780749
    781750    AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtq->uEnable,
     
    784753    uint16_t uDescIdx = uHeadIdx;
    785754
    786     Log6Func(("%s DESC CHAIN: (head) desc_idx=%u\n", pVirtq->szName, uHeadIdx));
     755    Log6Func(("%s DESC CHAIN: (head) desc_idx=%u\n", pVirtio->aVirtqueues[uVirtq].szName, uHeadIdx));
    787756
    788757    /*
     
    794763    pVirtqBuf->cRefs     = 1;
    795764    pVirtqBuf->uHeadIdx  = uHeadIdx;
    796     pVirtqBuf->uVirtq = uVirtq;
     765    pVirtqBuf->uVirtq    = uVirtq;
    797766    *ppVirtqBuf = pVirtqBuf;
    798767
     
    802771    VIRTQ_DESC_T desc;
    803772
    804     uint32_t cbIn = 0;
    805     uint32_t cbOut = 0;
    806     uint32_t cSegsIn = 0;
     773    uint32_t cbIn     = 0;
     774    uint32_t cbOut    = 0;
     775    uint32_t cSegsIn  = 0;
    807776    uint32_t cSegsOut = 0;
     777
    808778    PVIRTIOSGSEG paSegsIn  = pVirtqBuf->aSegsIn;
    809779    PVIRTIOSGSEG paSegsOut = pVirtqBuf->aSegsOut;
     
    847817            cbOut += desc.cb;
    848818            pSeg = &paSegsOut[cSegsOut++];
     819#ifdef DEEP_DEBUG
    849820            if (LogIs11Enabled())
    850821            {
     
    852823                Log(("\n"));
    853824            }
     825#endif
    854826        }
    855827
     
    886858}
    887859
    888 /** API Function: See header file */
    889 uint32_t virtioCoreR3VirtqBufRetain(PVIRTQBUF pVirtqBuf)
    890 {
    891     AssertReturn(pVirtqBuf, UINT32_MAX);
    892     AssertReturn(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC, UINT32_MAX);
    893     uint32_t cRefs = ASMAtomicIncU32(&pVirtqBuf->cRefs);
    894     Assert(cRefs > 1);
    895     Assert(cRefs < 16);
    896     return cRefs;
    897 }
    898 
    899 
    900 /** API Function: See header file */
    901 uint32_t virtioCoreR3VirtqBufRelease(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf)
    902 {
    903     if (!pVirtqBuf)
    904         return 0;
    905     AssertReturn(pVirtqBuf, 0);
    906     AssertReturn(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC, 0);
    907     uint32_t cRefs = ASMAtomicDecU32(&pVirtqBuf->cRefs);
    908     Assert(cRefs < 16);
    909     if (cRefs == 0)
    910     {
    911         pVirtqBuf->u32Magic = ~VIRTQBUF_MAGIC;
    912         RTMemFree(pVirtqBuf);
    913         STAM_REL_COUNTER_INC(&pVirtio->StatDescChainsFreed);
    914     }
    915     return cRefs;
    916 }
    917 
    918 /** API Function: See header file */
    919 void virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio)
    920 {
    921     virtioKick(pVirtio->pDevInsR3, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig);
    922 }
    923 
    924 /** API Function: See header file */
    925 void virtioCoreVirtqEnableNotify(PVIRTIOCORE pVirtio, uint16_t uVirtq, bool fEnable)
    926 {
    927 
    928     Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues));
    929     PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq];
    930 
    931     if (pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
    932     {
    933         uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, pVirtq);
    934 
    935         if (fEnable)
    936             fFlags &= ~ VIRTQ_USED_F_NO_NOTIFY;
    937         else
    938             fFlags |= VIRTQ_USED_F_NO_NOTIFY;
    939 
    940         virtioWriteUsedRingFlags(pVirtio->pDevInsR3, pVirtio, pVirtq, fFlags);
    941     }
    942 }
    943 
    944 /** API function: See Header file  */
    945 void virtioCoreResetAll(PVIRTIOCORE pVirtio)
    946 {
    947     LogFunc(("\n"));
    948     pVirtio->fDeviceStatus |= VIRTIO_STATUS_DEVICE_NEEDS_RESET;
    949     if (pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
    950     {
    951         pVirtio->fGenUpdatePending = true;
    952         virtioKick(pVirtio->pDevInsR3, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig);
    953     }
    954 }
    955 
    956 /** API function: See Header file  */
    957 int virtioCoreR3VirtqAvailBufPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq,
    958                          PPVIRTQBUF ppVirtqBuf)
    959 {
    960     return virtioCoreR3VirtqAvailBufGet(pDevIns, pVirtio, uVirtq, ppVirtqBuf, false);
    961 }
    962 
    963 /** API function: See Header file  */
    964 int virtioCoreR3VirtqAvailBufNext(PVIRTIOCORE pVirtio, uint16_t uVirtq)
    965 {
    966     Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues));
    967     PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq];
    968 
    969     AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtq->uEnable,
    970                     ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
    971 
    972     if (IS_VIRTQ_EMPTY(pVirtio->pDevInsR3, pVirtio, pVirtq))
    973         return VERR_NOT_AVAILABLE;
    974 
    975     Log6Func(("%s avail shadow idx: %u\n", pVirtq->szName, pVirtq->uAvailIdxShadow));
    976     pVirtq->uAvailIdxShadow++;
    977 
    978     return VINF_SUCCESS;
    979 }
    980 
    981860/** API function: See Header file  */
    982861int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq,
     
    1027906        cbRemain = cbTotal = RTSgBufCalcTotalLength(pSgVirtReturn);
    1028907        AssertMsgReturn(cbTarget >= cbRemain, ("No space to write data to phys memory"), VERR_BUFFER_OVERFLOW);
    1029         virtioCoreGCPhysChainReset(pSgPhysReturn); /* Reset ptr because req data may have already been written */
     908        virtioCoreGCPhysChainReset(pSgPhysReturn);
    1030909        while (cbRemain)
    1031910        {
     
    1064943}
    1065944
    1066 /** API function: See Header file  */
    1067 void virtioCoreR3VirqBufFill(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb)
    1068 {
    1069     uint8_t *pb = (uint8_t *)pv;
    1070     size_t cbLim = RT_MIN(pVirtqBuf->cbPhysReturn, cb);
    1071     while (cbLim)
    1072     {
    1073         size_t cbSeg = cbLim;
    1074         RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysReturn, &cbSeg);
    1075         PDMDevHlpPCIPhysWrite(pVirtio->pDevInsR3, GCPhys, pb, cbSeg);
    1076         pb += cbSeg;
    1077         cbLim -= cbSeg;
    1078         pVirtqBuf->cbPhysSend -= cbSeg;
    1079     }
    1080     LogFunc(("Added %d/%d bytes to %s buffer, head idx: %u (%d bytes remain)\n",
    1081              cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtq),
    1082              pVirtqBuf->uHeadIdx, pVirtqBuf->cbPhysReturn));
    1083 }
    1084 
    1085 
    1086 /** API function: See Header file  */
    1087 void virtioCoreR3VirtqBufDrain(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb)
    1088 {
    1089     uint8_t *pb = (uint8_t *)pv;
    1090     size_t cbLim = RT_MIN(pVirtqBuf->cbPhysSend, cb);
    1091     while (cbLim)
    1092     {
    1093         size_t cbSeg = cbLim;
    1094         RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysSend, &cbSeg);
    1095         PDMDevHlpPCIPhysRead(pVirtio->pDevInsR3, GCPhys, pb, cbSeg);
    1096         pb += cbSeg;
    1097         cbLim -= cbSeg;
    1098         pVirtqBuf->cbPhysSend -= cbSeg;
    1099     }
    1100     LogFunc(("Drained %d/%d bytes from %s buffer, head idx: %u (%d bytes left)\n",
    1101              cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtq),
    1102              pVirtqBuf->uHeadIdx, pVirtqBuf->cbPhysSend));
    1103 }
    1104945
    1105946#endif /* IN_RING3 */
     
    12551096    pVirtq->uAvailIdxShadow  = 0;
    12561097    pVirtq->uUsedIdxShadow   = 0;
    1257     pVirtq->uEnable     = false;
    1258     pVirtq->uSize       = VIRTQ_MAX_ENTRIES;
    1259     pVirtq->uNotifyOffset  = uVirtq;
    1260     pVirtq->uMsix = uVirtq + 2;
    1261     pVirtq->fUsedRingEvent = false;
     1098    pVirtq->uEnable          = false;
     1099    pVirtq->uSize            = VIRTQ_MAX_ENTRIES;
     1100    pVirtq->uNotifyOffset    = uVirtq;
     1101    pVirtq->uMsix            = uVirtq + 2;
     1102    pVirtq->fUsedRingEvent   = false;
    12621103
    12631104    if (!pVirtio->fMsiSupport) /* VirtIO 1.0, 4.1.4.3 and 4.1.5.1.2 */
     
    15271368    AssertReturn(cb == 1 || cb == 2 || cb == 4, VERR_INVALID_PARAMETER);
    15281369    Assert(pVirtio == (PVIRTIOCORE)pvUser); RT_NOREF(pvUser);
    1529 
    15301370
    15311371    uint32_t uOffset;
     
    18491689            break;
    18501690        case kvirtIoVmStateChangedResume:
    1851             virtioCoreNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, 0 /* uVirtq */);
     1691            for (int uVirtq = 0; uVirtq < VIRTQ_MAX_COUNT; uVirtq++)
     1692            {
     1693                if (pVirtio->aVirtqueues[uVirtq].uEnable)
     1694                    virtioCoreNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, uVirtq);
     1695            }
    18521696            break;
    18531697        default:
     
    18741718}
    18751719
    1876 /**
    1877  * Setup PCI device controller and Virtio state
    1878  *
    1879  * This should be called from PDMDEVREGR3::pfnConstruct.
    1880  *
    1881  * @param   pDevIns                 The device instance.
    1882  * @param   pVirtio                 Pointer to the shared virtio state.  This
    1883  *                                  must be the first member in the shared
    1884  *                                  device instance data!
    1885  * @param   pVirtioCC               Pointer to the ring-3 virtio state.  This
    1886  *                                  must be the first member in the ring-3
    1887  *                                  device instance data!
    1888  * @param   pPciParams              Values to populate industry standard PCI Configuration Space data structure
    1889  * @param   pcszInstance            Device instance name (format-specifier)
    1890  * @param   fDevSpecificFeatures    VirtIO device-specific features offered by
    1891  *                                  client
    1892  * @param   cbDevSpecificCfg        Size of virtio_pci_device_cap device-specific struct
    1893  * @param   pvDevSpecificCfg        Address of client's dev-specific
    1894  *                                  configuration struct.
    1895  */
     1720/** API Function: See header file */
    18961721int virtioCoreR3Init(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, PVIRTIOPCIPARAMS pPciParams,
    18971722                     const char *pcszInstance, uint64_t fDevSpecificFeatures, void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg)
  • trunk/src/VBox/Devices/VirtIO/VirtioCore.h

    r85194 r85291  
    402402
    403403/**
     404 * Setup PCI device controller and Virtio state
     405 *
     406 * This should be called from PDMDEVREGR3::pfnConstruct.
     407 *
     408 * @param   pDevIns                 The device instance.
     409 * @param   pVirtio                 Pointer to the shared virtio state.  This
     410 *                                  must be the first member in the shared
     411 *                                  device instance data!
     412 * @param   pVirtioCC               Pointer to the ring-3 virtio state.  This
     413 *                                  must be the first member in the ring-3
     414 *                                  device instance data!
     415 * @param   pPciParams              Values to populate industry standard PCI Configuration Space data structure
     416 * @param   pcszInstance            Device instance name (format-specifier)
     417 * @param   fDevSpecificFeatures    VirtIO device-specific features offered by
     418 *                                  client
     419 * @param   cbDevSpecificCfg        Size of virtio_pci_device_cap device-specific struct
     420 * @param   pvDevSpecificCfg        Address of client's dev-specific
     421 *                                  configuration struct.
     422 */
     423int virtioCoreR3Init(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC,
     424                          PVIRTIOPCIPARAMS pPciParams, const char *pcszInstance,
     425                          uint64_t fDevSpecificFeatures, void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg);
     426
     427/**
    404428 * Initiate orderly reset procedure. This is an exposed API for clients that might need it.
    405429 * Invoked by client to reset the device and driver (see VirtIO 1.0 section 2.1.1/2.1.2)
     
    621645int virtioCoreR3VirtqAvailBufNext(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr);
    622646
     647
     648DECLINLINE(void) virtioCoreGCPhysChainInit(PVIRTIOSGBUF pGcSgBuf, PVIRTIOSGSEG paSegs, size_t cSegs)
     649{
     650    AssertPtr(pGcSgBuf);
     651    Assert((cSegs > 0 && VALID_PTR(paSegs)) || (!cSegs && !paSegs));
     652    Assert(cSegs < (~(unsigned)0 >> 1));
     653
     654    pGcSgBuf->paSegs = paSegs;
     655    pGcSgBuf->cSegs  = (unsigned)cSegs;
     656    pGcSgBuf->idxSeg = 0;
     657    if (cSegs && paSegs)
     658    {
     659        pGcSgBuf->GCPhysCur = paSegs[0].GCPhys;
     660        pGcSgBuf->cbSegLeft = paSegs[0].cbSeg;
     661    }
     662    else
     663    {
     664        pGcSgBuf->GCPhysCur = 0;
     665        pGcSgBuf->cbSegLeft = 0;
     666    }
     667}
     668
     669DECLINLINE(RTGCPHYS) virtioCoreGCPhysChainGet(PVIRTIOSGBUF pGcSgBuf, size_t *pcbData)
     670{
     671    size_t cbData;
     672    RTGCPHYS pGcBuf;
     673
     674    /* Check that the S/G buffer has memory left. */
     675    if (RT_LIKELY(pGcSgBuf->idxSeg < pGcSgBuf->cSegs && pGcSgBuf->cbSegLeft))
     676    { /* likely */ }
     677    else
     678    {
     679        *pcbData = 0;
     680        return 0;
     681    }
     682
     683    AssertMsg(    pGcSgBuf->cbSegLeft <= 128 * _1M
     684              && (RTGCPHYS)pGcSgBuf->GCPhysCur >= (RTGCPHYS)pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys
     685              && (RTGCPHYS)pGcSgBuf->GCPhysCur + pGcSgBuf->cbSegLeft <=
     686                   (RTGCPHYS)pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys + pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg,
     687                 ("pGcSgBuf->idxSeg=%d pGcSgBuf->cSegs=%d pGcSgBuf->GCPhysCur=%p pGcSgBuf->cbSegLeft=%zd "
     688                  "pGcSgBuf->paSegs[%d].GCPhys=%p pGcSgBuf->paSegs[%d].cbSeg=%zd\n",
     689                  pGcSgBuf->idxSeg, pGcSgBuf->cSegs, pGcSgBuf->GCPhysCur, pGcSgBuf->cbSegLeft,
     690                  pGcSgBuf->idxSeg, pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys, pGcSgBuf->idxSeg,
     691                  pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg));
     692
     693    cbData = RT_MIN(*pcbData, pGcSgBuf->cbSegLeft);
     694    pGcBuf = pGcSgBuf->GCPhysCur;
     695    pGcSgBuf->cbSegLeft -= cbData;
     696    if (!pGcSgBuf->cbSegLeft)
     697    {
     698        pGcSgBuf->idxSeg++;
     699
     700        if (pGcSgBuf->idxSeg < pGcSgBuf->cSegs)
     701        {
     702            pGcSgBuf->GCPhysCur = pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys;
     703            pGcSgBuf->cbSegLeft = pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg;
     704        }
     705        *pcbData = cbData;
     706    }
     707    else
     708        pGcSgBuf->GCPhysCur = pGcSgBuf->GCPhysCur + cbData;
     709
     710    return pGcBuf;
     711}
     712
     713DECLINLINE(void) virtioCoreGCPhysChainReset(PVIRTIOSGBUF pGcSgBuf)
     714{
     715    AssertPtrReturnVoid(pGcSgBuf);
     716
     717    pGcSgBuf->idxSeg = 0;
     718    if (pGcSgBuf->cSegs)
     719    {
     720        pGcSgBuf->GCPhysCur = pGcSgBuf->paSegs[0].GCPhys;
     721        pGcSgBuf->cbSegLeft = pGcSgBuf->paSegs[0].cbSeg;
     722    }
     723    else
     724    {
     725        pGcSgBuf->GCPhysCur = 0;
     726        pGcSgBuf->cbSegLeft = 0;
     727    }
     728}
     729
     730DECLINLINE(RTGCPHYS) virtioCoreGCPhysChainAdvance(PVIRTIOSGBUF pGcSgBuf, size_t cbAdvance)
     731{
     732    AssertReturn(pGcSgBuf, 0);
     733
     734    size_t cbLeft = cbAdvance;
     735    while (cbLeft)
     736    {
     737        size_t cbThisAdvance = cbLeft;
     738        virtioCoreGCPhysChainGet(pGcSgBuf, &cbThisAdvance);
     739        if (!cbThisAdvance)
     740            break;
     741
     742        cbLeft -= cbThisAdvance;
     743    }
     744    return cbAdvance - cbLeft;
     745}
     746
     747DECLINLINE(RTGCPHYS) virtioCoreGCPhysChainGetNextSeg(PVIRTIOSGBUF pGcSgBuf, size_t *pcbSeg)
     748{
     749    AssertReturn(pGcSgBuf, 0);
     750    AssertPtrReturn(pcbSeg, 0);
     751
     752    if (!*pcbSeg)
     753        *pcbSeg = pGcSgBuf->cbSegLeft;
     754
     755    return virtioCoreGCPhysChainGet(pGcSgBuf, pcbSeg);
     756}
     757
     758DECLINLINE(size_t) virtioCoreGCPhysChainCalcBufSize(PVIRTIOSGBUF pGcSgBuf)
     759{
     760    size_t   cb = 0;
     761    unsigned i  = pGcSgBuf->cSegs;
     762     while (i-- > 0)
     763         cb += pGcSgBuf->paSegs[i].cbSeg;
     764     return cb;
     765 }
     766
     767#define VIRTQNAME(a_pVirtio, a_uVirtq) ((a_pVirtio)->aVirtqueues[(a_uVirtq)].szName)
     768
    623769/**
    624770 * Add some bytes to a virtq (s/g) buffer, converting them from virtual memory to GCPhys
     
    632778 * @param   cb          number of bytes to add to the s/g buffer.
    633779 */
    634 void virtioCoreR3VirqBufFill(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb);
     780DECLINLINE(void) virtioCoreR3VirqBufFill(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb)
     781{
     782    uint8_t *pb = (uint8_t *)pv;
     783    size_t cbLim = RT_MIN(pVirtqBuf->cbPhysReturn, cb);
     784    while (cbLim)
     785    {
     786        size_t cbSeg = cbLim;
     787        RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysReturn, &cbSeg);
     788        PDMDevHlpPCIPhysWrite(pVirtio->pDevInsR3, GCPhys, pb, cbSeg);
     789        pb += cbSeg;
     790        cbLim -= cbSeg;
     791        pVirtqBuf->cbPhysSend -= cbSeg;
     792    }
     793    LogFunc(("Added %d/%d bytes to %s buffer, head idx: %u (%d bytes remain)\n",
     794             cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtq),
     795             pVirtqBuf->uHeadIdx, pVirtqBuf->cbPhysReturn));
     796}
    635797
    636798/**
     
    645807 * @param   cb          number of bytes to Drain from buffer
    646808 */
    647 void virtioCoreR3VirtqBufDrain(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb);
     809DECLINLINE(void) virtioCoreR3VirtqBufDrain(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb)
     810{
     811    uint8_t *pb = (uint8_t *)pv;
     812    size_t cbLim = RT_MIN(pVirtqBuf->cbPhysSend, cb);
     813    while (cbLim)
     814    {
     815        size_t cbSeg = cbLim;
     816        RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysSend, &cbSeg);
     817        PDMDevHlpPCIPhysRead(pVirtio->pDevInsR3, GCPhys, pb, cbSeg);
     818        pb += cbSeg;
     819        cbLim -= cbSeg;
     820        pVirtqBuf->cbPhysSend -= cbSeg;
     821    }
     822    LogFunc(("Drained %d/%d bytes from %s buffer, head idx: %u (%d bytes left)\n",
     823             cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtq),
     824             pVirtqBuf->uHeadIdx, pVirtqBuf->cbPhysSend));
     825}
     826
     827#undef VIRTQNAME
    648828
    649829/**
     
    8201000void     virtioCoreR3VmStateChanged(PVIRTIOCORE pVirtio, VIRTIOVMSTATECHANGED enmState);
    8211001void     virtioCoreR3Term(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC);
    822 int      virtioCoreR3Init(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, PVIRTIOPCIPARAMS pPciParams,
    823                           const char *pcszInstance, uint64_t fDevSpecificFeatures, void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg);
    8241002int      virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio);
    8251003const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState);
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