VirtualBox

Changeset 84819 in vbox for trunk


Ignore:
Timestamp:
Jun 12, 2020 8:00:27 PM (5 years ago)
Author:
vboxsync
Message:

Virtio/VirtioCore.cpp, Network/DevVirtioNet_1_0.cpp, Storage/DevVirtioSCSI.cpp: Renamed Virtio_1_0.cpp/h to VirtioCore.cpp/h to be consistent with bird's extraction of the common Virtio code to VIRTIOCORE. Further improved the API function names and comments, and changed key variables to simplify things and more clearly reflect their relationship to VirtIO architecture. For example PVIRTIO_DESC_CHAIN_T pDescChain becomes PVIRTQBUF pVirtqBuf and added comments above the VIRTQBUF typedef to explain what's going on. Moved all the API function descriptions into the header file.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Makefile.kmk

    r84540 r84819  
    481481  VBoxDD_SOURCES        += \
    482482        VirtIO/Virtio.cpp \
    483         VirtIO/Virtio_1_0.cpp \
     483        VirtIO/VirtioCore.cpp \
    484484        Network/DevVirtioNet.cpp
    485485 endif
     
    970970   VBoxDDRC_SOURCES     += \
    971971        VirtIO/Virtio.cpp \
    972         VirtIO/Virtio_1_0.cpp \
     972        VirtIO/VirtioCore.cpp \
    973973        Network/DevVirtioNet.cpp
    974974  endif
     
    11691169  VBoxDDR0_SOURCES      += \
    11701170        VirtIO/Virtio.cpp \
    1171         VirtIO/Virtio_1_0.cpp \
     1171        VirtIO/VirtioCore.cpp \
    11721172        Network/DevVirtioNet.cpp
    11731173 endif
  • trunk/src/VBox/Devices/Network/DevVirtioNet_1_0.cpp

    r84806 r84819  
    5555# include <iprt/uuid.h>
    5656#endif
    57 #include "../VirtIO/Virtio_1_0.h"
     57#include "../VirtIO/VirtioCore.h"
    5858
    5959#include "VBoxDD.h"
     
    6767#define VIRTIONET_PREALLOCATE_RX_SEG_COUNT     32
    6868
    69 #define VIRTQNAME(idxVirtq)       (pThis->aVirtqs[idxVirtq]->szName)
    70 #define CBVIRTQNAME(idxVirtq)     RTStrNLen(VIRTQNAME(idxVirtq), sizeof(VIRTQNAME(idxVirtq)))
     69#define VIRTQNAME(uVirtqNbr)       (pThis->aVirtqs[uVirtqNbr]->szName)
     70#define CBVIRTQNAME(uVirtqNbr)     RTStrNLen(VIRTQNAME(uVirtqNbr), sizeof(VIRTQNAME(uVirtqNbr)))
    7171#define FEATURE_ENABLED(feature)  RT_BOOL(pThis->fNegotiatedFeatures & VIRTIONET_F_##feature)
    7272#define FEATURE_DISABLED(feature) (!FEATURE_ENABLED(feature))
    7373#define FEATURE_OFFERED(feature)  VIRTIONET_HOST_FEATURES_OFFERED & VIRTIONET_F_##feature
    7474
    75 #define IS_VIRTQ_EMPTY(pDevIns, pVirtio, idxVirtq) \
    76             (virtioCoreVirtqAvailCount(pDevIns, pVirtio, idxVirtq) == 0)
     75#define IS_VIRTQ_EMPTY(pDevIns, pVirtio, uVirtqNbr) \
     76            (virtioCoreVirtqAvailCount(pDevIns, pVirtio, uVirtqNbr) == 0)
    7777
    7878#define SET_LINK_UP(pState) \
     
    227227};
    228228#pragma pack()
    229 typedef virtio_net_pkt_hdr VIRTIONET_PKT_HDR_T, *PVIRTIONET_PKT_HDR_T;
    230 AssertCompileSize(VIRTIONET_PKT_HDR_T, 12);
     229typedef virtio_net_pkt_hdr VIRTIONETPKTHDR, *PVIRTIONETPKTHDR;
     230AssertCompileSize(VIRTIONETPKTHDR, 12);
    231231
    232232/* Control virtq: Command entry (VirtIO 1.0, 5.1.6.5) */
     
    615615 * @callback_method_impl{VIRTIOCORER0,pfnVirtqNotified}
    616616 */
    617 static DECLCALLBACK(void) virtioNetVirtqNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)
     617static DECLCALLBACK(void) virtioNetVirtqNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
    618618{
    619619    RT_NOREF(pVirtio);
    620620    PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    621621
    622     PVIRTIONETVIRTQ  pVirtq = &pThis->aVirtqs[idxVirtq];
     622    PVIRTIONETVIRTQ  pVirtq  = &pThis->aVirtqs[uVirtqNbr];
    623623    PVIRTIONETWORKER pWorker = pVirtq->pWorker;
    624624
     
    627627#endif
    628628
    629     if (IS_RX_VIRTQ(idxVirtq))
    630     {
    631         uint16_t cBufsAvailable = virtioCoreVirtqAvailCount(pDevIns, pVirtio, idxVirtq);
     629    if (IS_RX_VIRTQ(uVirtqNbr))
     630    {
     631        uint16_t cBufsAvailable = virtioCoreVirtqAvailCount(pDevIns, pVirtio, uVirtqNbr);
    632632
    633633        if (cBufsAvailable)
     
    641641                    pThis->szInst, pVirtq->szName));
    642642    }
    643     else if (IS_TX_VIRTQ(idxVirtq) || IS_CTRL_VIRTQ(idxVirtq))
     643    else if (IS_TX_VIRTQ(uVirtqNbr) || IS_CTRL_VIRTQ(uVirtqNbr))
    644644    {
    645645        /* Wake queue's worker thread up if sleeping (e.g. a Tx queue, or the control queue */
     
    663663    }
    664664    else
    665         LogRelFunc(("%s unrecognized queue %s (idx=%d) notified\n", pThis->szInst, pVirtq->szName, idxVirtq));
     665        LogRelFunc(("%s unrecognized queue %s (idx=%d) notified\n", pThis->szInst, pVirtq->szName, uVirtqNbr));
    666666}
    667667
     
    769769
    770770#ifdef LOG_ENABLED
    771 void virtioNetDumpGcPhysRxBuf(PPDMDEVINS pDevIns, PVIRTIONET_PKT_HDR_T pRxPktHdr,
     771void virtioNetDumpGcPhysRxBuf(PPDMDEVINS pDevIns, PVIRTIONETPKTHDR pRxPktHdr,
    772772                     uint16_t cDescs, uint8_t *pvBuf, uint16_t cb, RTGCPHYS GCPhysRxBuf, uint8_t cbRxBuf)
    773773{
     
    789789                        pRxPktHdr->uChksumStart, pRxPktHdr->uChksumOffset, pRxPktHdr->uNumBuffers));
    790790
    791         virtioCoreHexDump((uint8_t *)pRxPktHdr, sizeof(VIRTIONET_PKT_HDR_T), 0, "Dump of virtual rPktHdr");
     791        virtioCoreHexDump((uint8_t *)pRxPktHdr, sizeof(VIRTIONETPKTHDR), 0, "Dump of virtual rPktHdr");
    792792    }
    793793    virtioNetR3PacketDump(pThis, (const uint8_t *)pvBuf, cb, "<-- Incoming");
     
    841841        pHlp->pfnPrintf(pHlp, "Virtq information:\n\n");
    842842
    843         for (int idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++)
     843        for (int uVirtqNbr = 0; uVirtqNbr < pThis->cVirtVirtqs; uVirtqNbr++)
    844844        {
    845             PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[idxVirtq];
     845            PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[uVirtqNbr];
    846846
    847847            if (pVirtq->fHasWorker)
     
    873873            }
    874874            pHlp->pfnPrintf(pHlp, "\n");
    875             virtioCoreR3VirtqInfo(pDevIns, pHlp, pszArgs, idxVirtq);
     875            virtioCoreR3VirtqInfo(pDevIns, pHlp, pszArgs, uVirtqNbr);
    876876            pHlp->pfnPrintf(pHlp, "    ---------------------------------------------------------------------\n");
    877877            pHlp->pfnPrintf(pHlp, "\n");
     
    963963
    964964    }
    965     pHlp->pfnPrintf(pHlp, "\n");
    966     virtioCoreR3Info(pDevIns, pHlp, pszArgs);
     965    /** @todo implement this
     966      * pHlp->pfnPrintf(pHlp, "\n");
     967      * virtioCoreR3Info(pDevIns, pHlp, pszArgs);
     968      */
    967969    pHlp->pfnPrintf(pHlp, "\n");
    968970}
     
    11391141    pHlp->pfnSSMGetU16(     pSSM, &pThis->cWorkers);
    11401142
    1141     for (int idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++)
    1142         pHlp->pfnSSMGetBool(pSSM, &pThis->aVirtqs[idxVirtq].fAttachedToVirtioCore);
     1143    for (int uVirtqNbr = 0; uVirtqNbr < pThis->cVirtVirtqs; uVirtqNbr++)
     1144        pHlp->pfnSSMGetBool(pSSM, &pThis->aVirtqs[uVirtqNbr].fAttachedToVirtioCore);
    11431145
    11441146    int rc;
     
    12281230    pHlp->pfnSSMPutU16(     pSSM, pThis->cWorkers);
    12291231
    1230     for (int idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++)
    1231         pHlp->pfnSSMPutBool(pSSM, pThis->aVirtqs[idxVirtq].fAttachedToVirtioCore);
     1232    for (int uVirtqNbr = 0; uVirtqNbr < pThis->cVirtVirtqs; uVirtqNbr++)
     1233        pHlp->pfnSSMPutBool(pSSM, pThis->aVirtqs[uVirtqNbr].fAttachedToVirtioCore);
    12321234
    12331235    /* Save config area */
     
    14891491        rc = VINF_SUCCESS;
    14901492    }
    1491     virtioCoreVirtqNotifyEnable(&pThis->Virtio, pRxVirtq->idx, rc == VERR_INVALID_STATE /* fEnable */);
     1493    virtioCoreVirtqEnableNotify(&pThis->Virtio, pRxVirtq->idx, rc == VERR_INVALID_STATE /* fEnable */);
    14921494    return rc;
    14931495}
     
    14951497static bool virtioNetR3RxBufsAvail(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETVIRTQ *pRxVirtq)
    14961498{
    1497     for (int idxVirtqPair = 0; idxVirtqPair < pThis->cVirtqPairs; idxVirtqPair++)
    1498     {
    1499         PVIRTIONETVIRTQ pThisRxVirtq = &pThis->aVirtqs[RXQIDX(idxVirtqPair)];
     1499    for (int uVirtqNbrPair = 0; uVirtqNbrPair < pThis->cVirtqPairs; uVirtqNbrPair++)
     1500    {
     1501        PVIRTIONETVIRTQ pThisRxVirtq = &pThis->aVirtqs[RXQIDX(uVirtqNbrPair)];
    15001502        if (RT_SUCCESS(virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pThisRxVirtq)))
    15011503        {
     
    15661568 * @param   pCtx                The context descriptor.
    15671569 */
    1568 DECLINLINE(PPDMNETWORKGSO) virtioNetR3SetupGsoCtx(PPDMNETWORKGSO pGso, VIRTIONET_PKT_HDR_T const *pPktHdr)
     1570DECLINLINE(PPDMNETWORKGSO) virtioNetR3SetupGsoCtx(PPDMNETWORKGSO pGso, VIRTIONETPKTHDR const *pPktHdr)
    15691571{
    15701572    pGso->u8Type = PDMNETWORKGSOTYPE_INVALID;
     
    17291731
    17301732static int virtioNetR3CopyRxPktToGuest(PPDMDEVINS pDevIns, PVIRTIONET pThis, const void *pvBuf, size_t cb,
    1731                                        VIRTIONET_PKT_HDR_T *rxPktHdr, uint16_t cSegsAllocated,
     1733                                       VIRTIONETPKTHDR *rxPktHdr, uint16_t cSegsAllocated,
    17321734                                       PRTSGBUF pVirtSegBufToGuest, PRTSGSEG paVirtSegsToGuest,
    17331735                                       PVIRTIONETVIRTQ pRxVirtq)
     
    17391741    for (cDescs = uOffset = 0; uOffset < cb; )
    17401742    {
    1741         PVIRTIO_DESC_CHAIN_T pDescChain = NULL;
    1742 
    1743         int rc = virtioCoreR3VirtqGet(pDevIns, &pThis->Virtio, pRxVirtq->idx, &pDescChain, true);
     1743        PVIRTQBUF pVirtqBuf = NULL;
     1744
     1745        int rc = virtioCoreR3VirtqBufGet(pDevIns, &pThis->Virtio, pRxVirtq->idx, &pVirtqBuf, true);
    17441746        AssertMsgReturn(rc == VINF_SUCCESS || rc == VERR_NOT_AVAILABLE, ("%Rrc\n", rc), rc);
    17451747
    17461748        /** @todo  Find a better way to deal with this */
    1747         AssertMsgReturnStmt(rc == VINF_SUCCESS && pDescChain->cbPhysReturn,
     1749        AssertMsgReturnStmt(rc == VINF_SUCCESS && pVirtqBuf->cbPhysReturn,
    17481750                            ("Not enough Rx buffers in queue to accomodate ethernet packet\n"),
    1749                             virtioCoreR3DescChainRelease(&pThis->Virtio, pDescChain),
     1751                            virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf),
    17501752                            VERR_INTERNAL_ERROR);
    17511753
     
    17541756         * virtio_net_header.num_buffers, to defer updating (in GCPhys). Re-visit if needed */
    17551757
    1756         AssertMsgReturnStmt(pDescChain->pSgPhysReturn->paSegs[0].cbSeg >= sizeof(VIRTIONET_PKT_HDR_T),
     1758        AssertMsgReturnStmt(pVirtqBuf->pSgPhysReturn->paSegs[0].cbSeg >= sizeof(VIRTIONETPKTHDR),
    17571759                            ("Desc chain's first seg has insufficient space for pkt header!\n"),
    1758                             virtioCoreR3DescChainRelease(&pThis->Virtio, pDescChain),
     1760                            virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf),
    17591761                            VERR_INTERNAL_ERROR);
    17601762
    1761         size_t cbDescChainLeft = pDescChain->cbPhysReturn;
    1762         uint8_t  cbHdr = sizeof(VIRTIONET_PKT_HDR_T);
     1763        size_t cbDescChainLeft = pVirtqBuf->cbPhysReturn;
     1764        uint8_t  cbHdr = sizeof(VIRTIONETPKTHDR);
    17631765
    17641766        /* Fill the Guest Rx buffer with data received from the interface */
     
    17761778
    17771779                /* Calculate & cache addr of field to update after final value is known, in GCPhys mem */
    1778                 GCPhysPktHdrNumBuffers = pDescChain->pSgPhysReturn->paSegs[0].GCPhys
    1779                                          + RT_UOFFSETOF(VIRTIONET_PKT_HDR_T, uNumBuffers);
     1780                GCPhysPktHdrNumBuffers = pVirtqBuf->pSgPhysReturn->paSegs[0].GCPhys
     1781                                         + RT_UOFFSETOF(VIRTIONETPKTHDR, uNumBuffers);
    17801782                fAddPktHdr = false;
    17811783                cSegs++;
     
    17871789                paVirtSegsToGuest = (PRTSGSEG)RTMemRealloc(paVirtSegsToGuest, sizeof(RTSGSEG) * cSegsAllocated);
    17881790                if (!paVirtSegsToGuest)
    1789                     virtioCoreR3DescChainRelease(&pThis->Virtio, pDescChain);
     1791                    virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf);
    17901792                AssertReturn(paVirtSegsToGuest, VERR_NO_MEMORY);
    17911793            }
     
    18021804            Log7Func(("Send Rx pkt to guest...\n"));
    18031805            STAM_PROFILE_START(&pThis->StatReceiveStore, a);
    1804             virtioCoreR3VirtqPut(pDevIns, &pThis->Virtio, pRxVirtq->idx,
    1805                                  pVirtSegBufToGuest, pDescChain, true /* fFence */);
     1806            virtioCoreR3VirtqBufPut(pDevIns, &pThis->Virtio, pRxVirtq->idx,
     1807                                 pVirtSegBufToGuest, pVirtqBuf, true /* fFence */);
    18061808            STAM_PROFILE_STOP(&pThis->StatReceiveStore, a);
    18071809
     
    18101812        }
    18111813
    1812         virtioCoreR3DescChainRelease(&pThis->Virtio, pDescChain);
     1814        virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf);
    18131815    }
    18141816
     
    18531855
    18541856    LogFunc(("%s (%RTmac) pGso %s\n", pThis->szInst, pvBuf, pGso ? "present" : "not present"));
    1855     VIRTIONET_PKT_HDR_T rxPktHdr = { 0 };
     1857    VIRTIONETPKTHDR rxPktHdr = { 0 };
    18561858
    18571859    if (pGso)
     
    19611963              selection algorithm feasible or even necessary to prevent starvation? */
    19621964
    1963     for (int idxVirtqPair = 0; idxVirtqPair < pThis->cVirtqPairs; idxVirtqPair++)
    1964     {
    1965 
    1966         PVIRTIONETVIRTQ pRxVirtq = &pThis->aVirtqs[RXQIDX(idxVirtqPair)];
     1965    for (int uVirtqNbrPair = 0; uVirtqNbrPair < pThis->cVirtqPairs; uVirtqNbrPair++)
     1966    {
     1967
     1968        PVIRTIONETVIRTQ pRxVirtq = &pThis->aVirtqs[RXQIDX(uVirtqNbrPair)];
    19671969        if (RT_SUCCESS(!virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pRxVirtq)))
    19681970        {
     
    19982000
    19992001/* Read physical bytes from the out segment(s) of descriptor chain */
    2000 static void virtioNetR3PullChain(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIO_DESC_CHAIN_T pDescChain, void *pv, size_t cb)
     2002static void virtioNetR3PullChain(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTQBUF pVirtqBuf, void *pv, size_t cb)
    20012003{
    20022004    uint8_t *pb = (uint8_t *)pv;
    2003     size_t cbLim = RT_MIN(pDescChain->cbPhysSend, cb);
     2005    size_t cbLim = RT_MIN(pVirtqBuf->cbPhysSend, cb);
    20042006    while (cbLim)
    20052007    {
    20062008        size_t cbSeg = cbLim;
    2007         RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg);
     2009        RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pVirtqBuf->pSgPhysSend, &cbSeg);
    20082010        PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pb, cbSeg);
    20092011        pb += cbSeg;
    20102012        cbLim -= cbSeg;
    2011         pDescChain->cbPhysSend -= cbSeg;
     2013        pVirtqBuf->cbPhysSend -= cbSeg;
    20122014    }
    20132015    LogFunc(("%s Pulled %d/%d bytes from desc chain (%d bytes left)\n",
    2014              pThis->szInst, cb - cbLim, cb, pDescChain->cbPhysSend));
     2016             pThis->szInst, cb - cbLim, cb, pVirtqBuf->cbPhysSend));
    20152017    RT_NOREF(pThis);
    20162018}
    20172019
    20182020static uint8_t virtioNetR3CtrlRx(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC,
    2019                                  PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTIO_DESC_CHAIN_T pDescChain)
     2021                                 PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf)
    20202022{
    20212023
     
    20442046
    20452047    uint8_t fOn, fPromiscChanged = false;
    2046     virtioNetR3PullChain(pDevIns, pThis, pDescChain, &fOn, (size_t)RT_MIN(pDescChain->cbPhysSend, sizeof(fOn)));
     2048    virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &fOn, (size_t)RT_MIN(pVirtqBuf->cbPhysSend, sizeof(fOn)));
    20472049
    20482050    switch(pCtrlPktHdr->uCmd)
     
    20922094
    20932095static uint8_t virtioNetR3CtrlMac(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC,
    2094                                   PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTIO_DESC_CHAIN_T pDescChain)
     2096                                  PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf)
    20952097{
    20962098    LogFunc(("%s Processing CTRL MAC command\n", pThis->szInst));
     
    21042106    AssertMsgReturn((v), ("DESC chain too small to process CTRL_MAC_TABLE_SET cmd\n"), VIRTIONET_ERROR)
    21052107
    2106     AssertMsgReturn(pDescChain->cbPhysSend >= sizeof(*pCtrlPktHdr),
     2108    AssertMsgReturn(pVirtqBuf->cbPhysSend >= sizeof(*pCtrlPktHdr),
    21072109                   ("insufficient descriptor space for ctrl pkt hdr"),
    21082110                   VIRTIONET_ERROR);
    21092111
    2110     size_t cbRemaining = pDescChain->cbPhysSend;
     2112    size_t cbRemaining = pVirtqBuf->cbPhysSend;
    21112113    switch(pCtrlPktHdr->uCmd)
    21122114    {
     
    21152117            /* Set default Rx filter MAC */
    21162118            ASSERT_CTRL_ADDR_SET(cbRemaining >= sizeof(VIRTIONET_CTRL_MAC_TABLE_LEN));
    2117             virtioNetR3PullChain(pDevIns, pThis, pDescChain, &pThis->rxFilterMacDefault, sizeof(VIRTIONET_CTRL_MAC_TABLE_LEN));
     2119            virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &pThis->rxFilterMacDefault, sizeof(VIRTIONET_CTRL_MAC_TABLE_LEN));
    21182120            break;
    21192121        }
     
    21242126            /* Load unicast MAC filter table */
    21252127            ASSERT_CTRL_TABLE_SET(cbRemaining >= sizeof(cMacs));
    2126             virtioNetR3PullChain(pDevIns, pThis, pDescChain, &cMacs, sizeof(cMacs));
     2128            virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &cMacs, sizeof(cMacs));
    21272129            cbRemaining -= sizeof(cMacs);
    21282130            Log7Func(("%s Guest provided %d unicast MAC Table entries\n", pThis->szInst, cMacs));
     
    21312133                uint32_t cbMacs = cMacs * sizeof(RTMAC);
    21322134                ASSERT_CTRL_TABLE_SET(cbRemaining >= cbMacs);
    2133                 virtioNetR3PullChain(pDevIns, pThis, pDescChain, &pThis->aMacUnicastFilter, cbMacs);
     2135                virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &pThis->aMacUnicastFilter, cbMacs);
    21342136                cbRemaining -= cbMacs;
    21352137            }
     
    21382140            /* Load multicast MAC filter table */
    21392141            ASSERT_CTRL_TABLE_SET(cbRemaining >= sizeof(cMacs));
    2140             virtioNetR3PullChain(pDevIns, pThis, pDescChain, &cMacs, sizeof(cMacs));
     2142            virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &cMacs, sizeof(cMacs));
    21412143            cbRemaining -= sizeof(cMacs);
    21422144            Log10Func(("%s Guest provided %d multicast MAC Table entries\n", pThis->szInst, cMacs));
     
    21452147                uint32_t cbMacs = cMacs * sizeof(RTMAC);
    21462148                ASSERT_CTRL_TABLE_SET(cbRemaining >= cbMacs);
    2147                 virtioNetR3PullChain(pDevIns, pThis, pDescChain, &pThis->aMacMulticastFilter, cbMacs);
     2149                virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &pThis->aMacMulticastFilter, cbMacs);
    21482150                cbRemaining -= cbMacs;
    21492151            }
     
    21652167
    21662168static uint8_t virtioNetR3CtrlVlan(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC,
    2167                                    PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTIO_DESC_CHAIN_T pDescChain)
     2169                                   PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf)
    21682170{
    21692171    LogFunc(("%s Processing CTRL VLAN command\n", pThis->szInst));
     
    21722174
    21732175    uint16_t uVlanId;
    2174     size_t cbRemaining = pDescChain->cbPhysSend - sizeof(*pCtrlPktHdr);
     2176    size_t cbRemaining = pVirtqBuf->cbPhysSend - sizeof(*pCtrlPktHdr);
    21752177    AssertMsgReturn(cbRemaining > sizeof(uVlanId),
    21762178        ("DESC chain too small for VIRTIO_NET_CTRL_VLAN cmd processing"), VIRTIONET_ERROR);
    2177     virtioNetR3PullChain(pDevIns, pThis, pDescChain, &uVlanId, sizeof(uVlanId));
     2179    virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &uVlanId, sizeof(uVlanId));
    21782180    AssertMsgReturn(uVlanId > VIRTIONET_MAX_VLAN_ID,
    21792181        ("%s VLAN ID out of range (VLAN ID=%u)\n", pThis->szInst, uVlanId), VIRTIONET_ERROR);
     
    21942196
    21952197static void virtioNetR3Ctrl(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC,
    2196                             PVIRTIO_DESC_CHAIN_T pDescChain)
     2198                            PVIRTQBUF pVirtqBuf)
    21972199{
    21982200    LogFunc(("%s Received CTRL packet from guest\n", pThis->szInst));
    21992201
    2200     if (pDescChain->cbPhysSend < 2)
     2202    if (pVirtqBuf->cbPhysSend < 2)
    22012203    {
    22022204        LogFunc(("%s CTRL packet from guest driver incomplete. Skipping ctrl cmd\n", pThis->szInst));
    22032205        return;
    22042206    }
    2205     else if (pDescChain->cbPhysReturn < sizeof(VIRTIONET_CTRL_HDR_T_ACK))
     2207    else if (pVirtqBuf->cbPhysReturn < sizeof(VIRTIONET_CTRL_HDR_T_ACK))
    22062208    {
    22072209        LogFunc(("%s Guest driver didn't allocate memory to receive ctrl pkt ACK. Skipping ctrl cmd\n", pThis->szInst));
     
    22162218    AssertPtrReturnVoid(pCtrlPktHdr);
    22172219
    2218     AssertMsgReturnVoid(pDescChain->cbPhysSend >= sizeof(VIRTIONET_CTRL_HDR_T),
     2220    AssertMsgReturnVoid(pVirtqBuf->cbPhysSend >= sizeof(VIRTIONET_CTRL_HDR_T),
    22192221                        ("DESC chain too small for CTRL pkt header"));
    22202222
    2221     virtioNetR3PullChain(pDevIns, pThis, pDescChain, pCtrlPktHdr,
    2222                          RT_MIN(pDescChain->cbPhysSend, sizeof(VIRTIONET_CTRL_HDR_T)));
     2223    virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, pCtrlPktHdr,
     2224                         RT_MIN(pVirtqBuf->cbPhysSend, sizeof(VIRTIONET_CTRL_HDR_T)));
    22232225
    22242226    Log7Func(("%s CTRL COMMAND: class=%d command=%d\n", pThis->szInst, pCtrlPktHdr->uClass, pCtrlPktHdr->uCmd));
     
    22282230    {
    22292231        case VIRTIONET_CTRL_RX:
    2230             uAck = virtioNetR3CtrlRx(pDevIns, pThis, pThisCC, pCtrlPktHdr, pDescChain);
     2232            uAck = virtioNetR3CtrlRx(pDevIns, pThis, pThisCC, pCtrlPktHdr, pVirtqBuf);
    22312233            break;
    22322234        case VIRTIONET_CTRL_MAC:
    2233             uAck = virtioNetR3CtrlMac(pDevIns, pThis, pThisCC, pCtrlPktHdr, pDescChain);
     2235            uAck = virtioNetR3CtrlMac(pDevIns, pThis, pThisCC, pCtrlPktHdr, pVirtqBuf);
    22342236            break;
    22352237        case VIRTIONET_CTRL_VLAN:
    2236             uAck = virtioNetR3CtrlVlan(pDevIns, pThis, pThisCC, pCtrlPktHdr, pDescChain);
     2238            uAck = virtioNetR3CtrlVlan(pDevIns, pThis, pThisCC, pCtrlPktHdr, pVirtqBuf);
    22372239            break;
    22382240        case VIRTIONET_CTRL_ANNOUNCE:
     
    22832285    RTSgBufInit(pReturnSegBuf, paReturnSegs, cSegs);
    22842286
    2285     virtioCoreR3VirtqPut(pDevIns, &pThis->Virtio, CTRLQIDX, pReturnSegBuf, pDescChain, true /* fFence */);
     2287    virtioCoreR3VirtqBufPut(pDevIns, &pThis->Virtio, CTRLQIDX, pReturnSegBuf, pVirtqBuf, true /* fFence */);
    22862288    virtioCoreVirtqSync(pDevIns, &pThis->Virtio, CTRLQIDX);
    22872289
     
    22962298}
    22972299
    2298 static int virtioNetR3ReadHeader(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, PVIRTIONET_PKT_HDR_T pPktHdr, size_t cbFrame)
     2300static int virtioNetR3ReadHeader(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, PVIRTIONETPKTHDR pPktHdr, size_t cbFrame)
    22992301{
    23002302    int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pPktHdr, sizeof(*pPktHdr));
     
    23432345
    23442346static int virtioNetR3TransmitFrame(PVIRTIONET pThis, PVIRTIONETCC pThisCC, PPDMSCATTERGATHER pSgBuf,
    2345                                PPDMNETWORKGSO pGso, PVIRTIONET_PKT_HDR_T pPktHdr)
     2347                               PPDMNETWORKGSO pGso, PVIRTIONETPKTHDR pPktHdr)
    23462348{
    23472349    virtioNetR3PacketDump(pThis, (uint8_t *)pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed, "--> Outgoing");
     
    24492451
    24502452    int rc;
    2451     PVIRTIO_DESC_CHAIN_T pDescChain = NULL;
    2452     while ((rc = virtioCoreR3VirtqPeek(pVirtio->pDevInsR3, pVirtio, pTxVirtq->idx, &pDescChain)) == VINF_SUCCESS)
     2453    PVIRTQBUF pVirtqBuf = NULL;
     2454    while ((rc = virtioCoreR3VirtqBufPeek(pVirtio->pDevInsR3, pVirtio, pTxVirtq->idx, &pVirtqBuf)) == VINF_SUCCESS)
    24532455    {
    24542456        Log10Func(("%s fetched descriptor chain from %s\n", pThis->szInst, pTxVirtq->szName));
    24552457
    2456         PVIRTIOSGBUF pSgPhysSend = pDescChain->pSgPhysSend;
     2458        PVIRTIOSGBUF pSgPhysSend = pVirtqBuf->pSgPhysSend;
    24572459        PVIRTIOSGSEG paSegsFromGuest = pSgPhysSend->paSegs;
    24582460        uint32_t cSegsFromGuest = pSgPhysSend->cSegs;
    24592461
    2460         VIRTIONET_PKT_HDR_T PktHdr;
     2462        VIRTIONETPKTHDR PktHdr;
    24612463        size_t uSize = 0;
    24622464
     
    25142516
    25152517                LogFunc((".... Copied %lu bytes to %lu byte guest buffer, residual=%lu\n",
    2516                      cbTotal, pDescChain->cbPhysSend, pDescChain->cbPhysSend - cbTotal));
     2518                     cbTotal, pVirtqBuf->cbPhysSend, pVirtqBuf->cbPhysSend - cbTotal));
    25172519
    25182520                rc = virtioNetR3TransmitFrame(pThis, pThisCC, pSgBufToPdmLeafDevice, pGso, &PktHdr);
     
    25312533                Log4Func(("Failed to allocate S/G buffer: size=%u rc=%Rrc\n", uSize, rc));
    25322534                /* Stop trying to fetch TX descriptors until we get more bandwidth. */
    2533                 virtioCoreR3DescChainRelease(pVirtio, pDescChain);
     2535                virtioCoreR3VirtqBufRelease(pVirtio, pVirtqBuf);
    25342536                break;
    25352537            }
    25362538
    25372539            /* Remove this descriptor chain from the available ring */
    2538             virtioCoreR3VirtqSkip(pVirtio, pTxVirtq->idx);
     2540            virtioCoreR3VirtqBufSkip(pVirtio, pTxVirtq->idx);
    25392541
    25402542            /* No data to return to guest, but call is needed put elem (e.g. desc chain) on used ring */
    2541             virtioCoreR3VirtqPut(pVirtio->pDevInsR3, pVirtio, pTxVirtq->idx, NULL, pDescChain, true /* fFence */);
     2543            virtioCoreR3VirtqBufPut(pVirtio->pDevInsR3, pVirtio, pTxVirtq->idx, NULL, pVirtqBuf, true /* fFence */);
    25422544
    25432545            /* Update used ring idx and notify guest that we've transmitted the data it sent */
     
    25452547        }
    25462548
    2547         virtioCoreR3DescChainRelease(pVirtio, pDescChain);
    2548         pDescChain = NULL;
     2549        virtioCoreR3VirtqBufRelease(pVirtio, pVirtqBuf);
     2550        pVirtqBuf = NULL;
    25492551    }
    25502552    virtioNetR3SetWriteLed(pThisCC, false);
     
    27922794
    27932795    uint16_t idxWorker = CTRLWIDX + 1;
    2794     for (uint16_t idxVirtqPair = 0; idxVirtqPair < pThis->cVirtqPairs; idxVirtqPair++, idxWorker++)
    2795     {
    2796         PVIRTIONETVIRTQ pTxVirtq = &pThis->aVirtqs[TXQIDX(idxVirtqPair)];
    2797         PVIRTIONETVIRTQ pRxVirtq = &pThis->aVirtqs[RXQIDX(idxVirtqPair)];
     2796    for (uint16_t uVirtqNbrPair = 0; uVirtqNbrPair < pThis->cVirtqPairs; uVirtqNbrPair++, idxWorker++)
     2797    {
     2798        PVIRTIONETVIRTQ pTxVirtq = &pThis->aVirtqs[TXQIDX(uVirtqNbrPair)];
     2799        PVIRTIONETVIRTQ pRxVirtq = &pThis->aVirtqs[RXQIDX(uVirtqNbrPair)];
    27982800
    27992801        rc = virtioNetR3CreateOneWorkerThread(pDevIns, pThis, idxWorker, &pThis->aWorkers[idxWorker],
     
    28252827    /** @todo Race w/guest enabling/disabling guest notifications cyclically.
    28262828              See BugRef #8651, Comment #82 */
    2827     virtioCoreVirtqNotifyEnable(&pThis->Virtio, pVirtq->idx, true /* fEnable */);
     2829    virtioCoreVirtqEnableNotify(&pThis->Virtio, pVirtq->idx, true /* fEnable */);
    28282830
    28292831    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
     
    28572859             {
    28582860                 Log10Func(("%s %s worker woken. Fetching desc chain\n", pThis->szInst, pVirtq->szName));
    2859                  PVIRTIO_DESC_CHAIN_T pDescChain = NULL;
    2860                  int rc = virtioCoreR3VirtqGet(pDevIns, &pThis->Virtio, pVirtq->idx, &pDescChain, true);
     2861                 PVIRTQBUF pVirtqBuf = NULL;
     2862                 int rc = virtioCoreR3VirtqBufGet(pDevIns, &pThis->Virtio, pVirtq->idx, &pVirtqBuf, true);
    28612863                 if (rc == VERR_NOT_AVAILABLE)
    28622864                 {
     
    28642866                    continue;
    28652867                 }
    2866                  virtioNetR3Ctrl(pDevIns, pThis, pThisCC, pDescChain);
    2867                  virtioCoreR3DescChainRelease(&pThis->Virtio, pDescChain);
     2868                 virtioNetR3Ctrl(pDevIns, pThis, pThisCC, pVirtqBuf);
     2869                 virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf);
    28682870             }
    28692871             else /* Must be Tx queue */
     
    29112913        pThisCC->fQuiescing = false;
    29122914
    2913         for (unsigned idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++)
     2915        for (unsigned uVirtqNbr = 0; uVirtqNbr < pThis->cVirtVirtqs; uVirtqNbr++)
    29142916        {
    2915             PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[idxVirtq];
    2916             pVirtq->idx = idxVirtq;
     2917            PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[uVirtqNbr];
     2918            pVirtq->idx = uVirtqNbr;
    29172919            (void) virtioCoreR3VirtqAttach(&pThis->Virtio, pVirtq->idx, pVirtq->szName);
    29182920            pVirtq->fAttachedToVirtioCore = true;
    29192921            if (IS_VIRTQ_EMPTY(pThisCC->pDevIns, &pThis->Virtio, pVirtq->idx))
    2920                 virtioCoreVirtqNotifyEnable(&pThis->Virtio, pVirtq->idx, true /* fEnable */);
     2922                virtioCoreVirtqEnableNotify(&pThis->Virtio, pVirtq->idx, true /* fEnable */);
    29212923        }
    29222924    }
     
    29442946        pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, true);
    29452947
    2946         for (uint16_t idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++)
    2947             pThis->aVirtqs[idxVirtq].fAttachedToVirtioCore = false;
     2948        for (uint16_t uVirtqNbr = 0; uVirtqNbr < pThis->cVirtVirtqs; uVirtqNbr++)
     2949            pThis->aVirtqs[uVirtqNbr].fAttachedToVirtioCore = false;
    29482950    }
    29492951}
  • trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp

    r84803 r84819  
    5151# include <iprt/uuid.h>
    5252#endif
    53 #include "../VirtIO/Virtio_1_0.h"
     53#include "../VirtIO/VirtioCore.h"
    5454
    5555#include "VBoxSCSI.h"
     
    112112#define VIRTQ_REQ_BASE                              2           /**< Spec-defined base index of request queues       */
    113113
    114 #define VIRTQNAME(idxVirtq) (pThis->aszVirtqNames[idxVirtq])            /**< Macro to get queue name from its index          */
    115 #define CBVIRTQNAME(idxVirtq) RTStrNLen(VIRTQNAME(idxVirtq), sizeof(VIRTQNAME(idxVirtq)))
    116 
    117 #define IS_REQ_VIRTQ(idxVirtq) (idxVirtq >= VIRTQ_REQ_BASE && idxVirtq < VIRTIOSCSI_VIRTQ_CNT)
     114#define VIRTQNAME(uVirtqNbr) (pThis->aszVirtqNames[uVirtqNbr])            /**< Macro to get queue name from its index          */
     115#define CBVIRTQNAME(uVirtqNbr) RTStrNLen(VIRTQNAME(uVirtqNbr), sizeof(VIRTQNAME(uVirtqNbr)))
     116
     117#define IS_REQ_VIRTQ(uVirtqNbr) (uVirtqNbr >= VIRTQ_REQ_BASE && uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT)
    118118
    119119#define VIRTIO_IS_IN_DIRECTION(pMediaExTxDirEnumValue) \
     
    123123    ((pMediaExTxDirEnumValue) == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE)
    124124
    125 #define IS_VIRTQ_EMPTY(pDevIns, pVirtio, idxVirtq) \
    126             (virtioCoreVirtqAvailCount(pDevIns, pVirtio, idxVirtq) == 0)
     125#define IS_VIRTQ_EMPTY(pDevIns, pVirtio, uVirtqNbr) \
     126            (virtioCoreVirtqAvailCount(pDevIns, pVirtio, uVirtqNbr) == 0)
    127127
    128128
     
    557557    PDMMEDIAEXIOREQ                hIoReq;                      /**< Handle of I/O request                             */
    558558    PVIRTIOSCSITARGET              pTarget;                     /**< Target                                            */
    559     uint16_t                       idxVirtq;                        /**< Index of queue this request arrived on            */
    560     PVIRTIO_DESC_CHAIN_T           pDescChain;                  /**< Prepared desc chain pulled from virtq avail ring  */
     559    uint16_t                       uVirtqNbr;                   /**< Index of queue this request arrived on            */
     560    PVIRTQBUF                      pVirtqBuf;                   /**< Prepared desc chain pulled from virtq avail ring  */
    561561    size_t                         cbDataIn;                    /**< size of dataout buffer                            */
    562562    size_t                         cbDataOut;                   /**< size of dataout buffer                            */
     
    576576 * @todo this causes burn if I prefix with at-sign. This callback is in VIRTIOCORER0 and VIRTIOCORER3
    577577 */
    578 static DECLCALLBACK(void) virtioScsiNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)
     578static DECLCALLBACK(void) virtioScsiNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
    579579{
    580580
     
    582582    PVIRTIOSCSI pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    583583
    584     AssertReturnVoid(idxVirtq < VIRTIOSCSI_VIRTQ_CNT);
    585     PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[idxVirtq];
     584    AssertReturnVoid(uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT);
     585    PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[uVirtqNbr];
    586586
    587587#if defined (IN_RING3) && defined (LOG_ENABLED)
     
    589589#endif
    590590
    591     if (idxVirtq == CONTROLQ_IDX || IS_REQ_VIRTQ(idxVirtq))
    592     {
    593         Log6Func(("%s has available data\n", VIRTQNAME(idxVirtq)));
     591    if (uVirtqNbr == CONTROLQ_IDX || IS_REQ_VIRTQ(uVirtqNbr))
     592    {
     593        Log6Func(("%s has available data\n", VIRTQNAME(uVirtqNbr)));
    594594        /* Wake queue's worker thread up if sleeping */
    595595        if (!ASMAtomicXchgBool(&pWorker->fNotified, true))
     
    597597            if (ASMAtomicReadBool(&pWorker->fSleeping))
    598598            {
    599                 Log6Func(("waking %s worker.\n", VIRTQNAME(idxVirtq)));
     599                Log6Func(("waking %s worker.\n", VIRTQNAME(uVirtqNbr)));
    600600                int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess);
    601601                AssertRC(rc);
     
    603603        }
    604604    }
    605     else if (idxVirtq == EVENTQ_IDX)
    606     {
    607         Log3Func(("Driver queued buffer(s) to %s\n", VIRTQNAME(idxVirtq)));
     605    else if (uVirtqNbr == EVENTQ_IDX)
     606    {
     607        Log3Func(("Driver queued buffer(s) to %s\n", VIRTQNAME(uVirtqNbr)));
    608608//        if (ASMAtomicXchgBool(&pThis->fEventsMissed, false))
    609609//            virtioScsiR3ReportEventsMissed(pDevIns, pThis, 0);
    610610    }
    611611    else
    612         LogFunc(("Unexpected queue idx (ignoring): %d\n", idxVirtq));
     612        LogFunc(("Unexpected queue idx (ignoring): %d\n", uVirtqNbr));
    613613}
    614614
     
    621621    RTStrCopy(pThis->aszVirtqNames[CONTROLQ_IDX], VIRTIO_MAX_VIRTQ_NAME_SIZE, "controlq");
    622622    RTStrCopy(pThis->aszVirtqNames[EVENTQ_IDX],   VIRTIO_MAX_VIRTQ_NAME_SIZE, "eventq");
    623     for (uint16_t idxVirtq = VIRTQ_REQ_BASE; idxVirtq < VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_VIRTQ_CNT; idxVirtq++)
    624         RTStrPrintf(pThis->aszVirtqNames[idxVirtq], VIRTIO_MAX_VIRTQ_NAME_SIZE,
    625                     "requestq<%d>", idxVirtq - VIRTQ_REQ_BASE);
     623    for (uint16_t uVirtqNbr = VIRTQ_REQ_BASE; uVirtqNbr < VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_VIRTQ_CNT; uVirtqNbr++)
     624        RTStrPrintf(pThis->aszVirtqNames[uVirtqNbr], VIRTIO_MAX_VIRTQ_NAME_SIZE,
     625                    "requestq<%d>", uVirtqNbr - VIRTQ_REQ_BASE);
    626626}
    627627
     
    754754    }
    755755
    756     PVIRTIO_DESC_CHAIN_T pDescChain = NULL;
    757     int rc = virtioCoreR3VirtqGet(pDevIns, &pThis->Virtio, EVENTQ_IDX, &pDescChain, true);
     756    PVIRTQBUF pVirtqBuf = NULL;
     757    int rc = virtioCoreR3VirtqBufGet(pDevIns, &pThis->Virtio, EVENTQ_IDX, &pVirtqBuf, true);
    758758    if (rc == VERR_NOT_AVAILABLE)
    759759    {
     
    783783    RTSgBufInit(&ReqSgBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
    784784
    785     rc = virtioCoreR3VirtqPut(pDevIns, &pThis->Virtio, EVENTQ_IDX, &ReqSgBuf, pDescChain, true /*fFence*/);
     785    rc = virtioCoreR3VirtqBufPut(pDevIns, &pThis->Virtio, EVENTQ_IDX, &ReqSgBuf, pVirtqBuf, true /*fFence*/);
    786786    if (rc == VINF_SUCCESS)
    787787        virtioCoreVirtqSync(pDevIns, &pThis->Virtio, EVENTQ_IDX, false);
    788788    else
    789789        LogRel(("Error writing control message to guest\n"));
    790     virtioCoreR3DescChainRelease(&pThis->Virtio, pDescChain);
     790    virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf);
    791791
    792792    return rc;
     
    800800    RTMemFree(pReq->pbSense);
    801801    pReq->pbSense = NULL;
    802     virtioCoreR3DescChainRelease(&pThis->Virtio, pReq->pDescChain);
    803     pReq->pDescChain = NULL;
     802    virtioCoreR3VirtqBufRelease(&pThis->Virtio, pReq->pVirtqBuf);
     803    pReq->pVirtqBuf = NULL;
    804804    pTarget->pDrvMediaEx->pfnIoReqFree(pTarget->pDrvMediaEx, pReq->hIoReq);
    805805}
     
    811811 * @param   pThis       VirtIO SCSI shared instance data.
    812812 * @param   pThisCC     VirtIO SCSI ring-3 instance data.
    813  * @param   idxVirtq        Virtq index
    814  * @param   pDescChain  Pointer to pre-processed descriptor chain pulled from virtq
     813 * @param   uVirtqNbr        Virtq index
     814 * @param   pVirtqBuf  Pointer to pre-processed descriptor chain pulled from virtq
    815815 * @param   pRespHdr    Response header
    816816 * @param   pbSense     Pointer to sense buffer or NULL if none.
     
    819819 * @returns VINF_SUCCESS
    820820 */
    821 static int virtioScsiR3ReqErr(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, uint16_t idxVirtq,
    822                               PVIRTIO_DESC_CHAIN_T pDescChain, REQ_RESP_HDR_T *pRespHdr, uint8_t *pbSense,
     821static int virtioScsiR3ReqErr(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, uint16_t uVirtqNbr,
     822                              PVIRTQBUF pVirtqBuf, REQ_RESP_HDR_T *pRespHdr, uint8_t *pbSense,
    823823                              size_t cbSenseCfg)
    824824{
     
    853853        pRespHdr->uResponse = VIRTIOSCSI_S_RESET;
    854854
    855     virtioCoreR3VirtqPut(pDevIns, &pThis->Virtio, idxVirtq, &ReqSgBuf, pDescChain, true /* fFence */);
    856     virtioCoreVirtqSync(pDevIns, &pThis->Virtio, idxVirtq);
     855    virtioCoreR3VirtqBufPut(pDevIns, &pThis->Virtio, uVirtqNbr, &ReqSgBuf, pVirtqBuf, true /* fFence */);
     856    virtioCoreVirtqSync(pDevIns, &pThis->Virtio, uVirtqNbr);
    857857
    858858    if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThisCC->fQuiescing)
     
    872872 * @param   pThis       VirtIO SCSI shared instance data.
    873873 * @param   pThisCC     VirtIO SCSI ring-3 instance data.
    874  * @param   idxVirtq        Virtq index
    875  * @param   pDescChain  Pointer to pre-processed descriptor chain pulled from virtq
     874 * @param   uVirtqNbr   Virtq index
     875 * @param   pVirtqBuf   Pointer to pre-processed descriptor chain pulled from virtq
    876876 * @param   cbResidual  The number of residual bytes or something like that.
    877877 * @param   bStatus     The SCSI status code.
     
    883883 * @returns VINF_SUCCESS
    884884 */
    885 static int virtioScsiR3ReqErr4(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, uint16_t idxVirtq,
    886                                PVIRTIO_DESC_CHAIN_T pDescChain, size_t cbResidual, uint8_t bStatus, uint8_t bResponse,
     885static int virtioScsiR3ReqErr4(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, uint16_t uVirtqNbr,
     886                               PVIRTQBUF pVirtqBuf, size_t cbResidual, uint8_t bStatus, uint8_t bResponse,
    887887                               uint8_t *pbSense, size_t cbSense, size_t cbSenseCfg)
    888888{
     
    894894    RespHdr.uResponse        = bResponse;
    895895
    896     return virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, &RespHdr, pbSense, cbSenseCfg);
     896    return virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, &RespHdr, pbSense, cbSenseCfg);
    897897}
    898898
     
    993993    {
    994994        LogFunc(("cbDataIn = %u, cbDataOut = %u (cbIn = %u, cbOut = %u)\n",
    995                   pReq->cbDataIn, pReq->cbDataOut, pReq->pDescChain->cbPhysReturn, pReq->pDescChain->cbPhysSend));
     995                  pReq->cbDataIn, pReq->cbDataOut, pReq->pVirtqBuf->cbPhysReturn, pReq->pVirtqBuf->cbPhysSend));
    996996        LogFunc(("xfer = %lu, residual = %u\n", cbXfer, cbResidual));
    997997        LogFunc(("xfer direction: %s, sense written = %d, sense size = %d\n",
     
    10161016        respHdr.uResidual  = pReq->cbDataIn & UINT32_MAX;
    10171017
    1018         virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, pReq->idxVirtq, pReq->pDescChain, &respHdr, abSense,
     1018        virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, pReq->uVirtqNbr, pReq->pVirtqBuf, &respHdr, abSense,
    10191019                           RT_MIN(pThis->virtioScsiConfig.uSenseSize, VIRTIOSCSI_SENSE_SIZE_MAX));
    10201020    }
     
    10371037        size_t cbReqSgBuf = RTSgBufCalcTotalLength(&ReqSgBuf);
    10381038        /** @todo r=bird: Returning here looks a little bogus... */
    1039         AssertMsgReturn(cbReqSgBuf <= pReq->pDescChain->cbPhysReturn,
     1039        AssertMsgReturn(cbReqSgBuf <= pReq->pVirtqBuf->cbPhysReturn,
    10401040                       ("Guest expected less req data (space needed: %zu, avail: %u)\n",
    1041                         cbReqSgBuf, pReq->pDescChain->cbPhysReturn),
     1041                        cbReqSgBuf, pReq->pVirtqBuf->cbPhysReturn),
    10421042                        VERR_BUFFER_OVERFLOW);
    10431043
    1044         virtioCoreR3VirtqPut(pDevIns, &pThis->Virtio, pReq->idxVirtq, &ReqSgBuf, pReq->pDescChain, true /* fFence TBD */);
    1045         virtioCoreVirtqSync(pDevIns, &pThis->Virtio, pReq->idxVirtq);
     1044        virtioCoreR3VirtqBufPut(pDevIns, &pThis->Virtio, pReq->uVirtqNbr, &ReqSgBuf, pReq->pVirtqBuf, true /* fFence TBD */);
     1045        virtioCoreVirtqSync(pDevIns, &pThis->Virtio, pReq->uVirtqNbr);
    10461046
    10471047        Log2(("-----------------------------------------------------------------------------------------\n"));
     
    10721072        return VINF_SUCCESS;
    10731073
    1074     AssertReturn(pReq->pDescChain, VERR_INVALID_PARAMETER);
    1075 
    1076     PVIRTIOSGBUF pSgPhysReturn = pReq->pDescChain->pSgPhysReturn;
     1074    AssertReturn(pReq->pVirtqBuf, VERR_INVALID_PARAMETER);
     1075
     1076    PVIRTIOSGBUF pSgPhysReturn = pReq->pVirtqBuf->pSgPhysReturn;
    10771077    virtioCoreSgBufAdvance(pSgPhysReturn, offDst);
    10781078
     
    10961096
    10971097    Log3Func((".... Copied %lu bytes from %lu byte guest buffer, residual=%lu\n",
    1098               cbCopy, pReq->pDescChain->cbPhysReturn, pReq->pDescChain->cbPhysReturn - cbCopy));
     1098              cbCopy, pReq->pVirtqBuf->cbPhysReturn, pReq->pVirtqBuf->cbPhysReturn - cbCopy));
    10991099
    11001100    return VINF_SUCCESS;
     
    11171117        return VINF_SUCCESS;
    11181118
    1119     PVIRTIOSGBUF pSgPhysSend = pReq->pDescChain->pSgPhysSend;
     1119    PVIRTIOSGBUF pSgPhysSend = pReq->pVirtqBuf->pSgPhysSend;
    11201120    virtioCoreSgBufAdvance(pSgPhysSend, offSrc);
    11211121
     
    11331133
    11341134    Log2Func((".... Copied %lu bytes to %lu byte guest buffer, residual=%lu\n",
    1135               cbCopy, pReq->pDescChain->cbPhysReturn, pReq->pDescChain->cbPhysReturn - cbCopy));
     1135              cbCopy, pReq->pVirtqBuf->cbPhysReturn, pReq->pVirtqBuf->cbPhysReturn - cbCopy));
    11361136
    11371137    return VINF_SUCCESS;
     
    11441144 */
    11451145static int virtioScsiR3ReqSubmit(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC,
    1146                                  uint16_t idxVirtq, PVIRTIO_DESC_CHAIN_T pDescChain)
     1146                                 uint16_t uVirtqNbr, PVIRTQBUF pVirtqBuf)
    11471147{
    11481148
     
    11641164     */
    11651165    size_t const cbReqHdr = sizeof(REQ_CMD_HDR_T) + cbCdb;
    1166     AssertReturn(pDescChain->cbPhysSend >= cbReqHdr, VERR_INVALID_PARAMETER);
     1166    AssertReturn(pVirtqBuf->cbPhysSend >= cbReqHdr, VERR_INVALID_PARAMETER);
    11671167
    11681168    AssertCompile(VIRTIOSCSI_CDB_SIZE_MAX < 4096);
     
    11821182    {
    11831183        size_t cbSeg = cbReqHdr - offReq;
    1184         RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg);
     1184        RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pVirtqBuf->pSgPhysSend, &cbSeg);
    11851185        PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhys, &VirtqReq.ab[offReq], cbSeg);
    11861186        offReq += cbSeg;
     
    12181218    uint32_t const offDataOut = sizeof(REQ_CMD_HDR_T)  + cbCdb;
    12191219    uint32_t const offDataIn  = sizeof(REQ_RESP_HDR_T) + cbSenseCfg;
    1220     size_t   const cbDataOut  = pDescChain->cbPhysSend - offDataOut;
     1220    size_t   const cbDataOut  = pVirtqBuf->cbPhysSend - offDataOut;
    12211221    /** @todo r=bird: Validate cbPhysReturn properly? I've just RT_MAX'ed it for now. */
    1222     size_t   const cbDataIn   = RT_MAX(pDescChain->cbPhysReturn, offDataIn) - offDataIn;
     1222    size_t   const cbDataIn   = RT_MAX(pVirtqBuf->cbPhysReturn, offDataIn) - offDataIn;
    12231223    Assert(offDataOut <= UINT16_MAX);
    12241224    Assert(offDataIn  <= UINT16_MAX);
     
    12321232    {
    12331233        Log2Func(("Error submitting request, bad LUN format\n"));
    1234         return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, cbDataIn + cbDataOut, 0 /*bStatus*/,
     1234        return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, cbDataIn + cbDataOut, 0 /*bStatus*/,
    12351235                                   VIRTIOSCSI_S_FAILURE, NULL /*pbSense*/, 0 /*cbSense*/, cbSenseCfg);
    12361236    }
     
    12471247                              0, SCSI_SENSE_ILLEGAL_REQUEST,
    12481248                              0, 0, 0, 0, 10, SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED, 0, 0 };
    1249         return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,
     1249        return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,
    12501250                                   VIRTIOSCSI_S_BAD_TARGET, abSense, sizeof(abSense), cbSenseCfg);
    12511251    }
     
    12581258                              0, SCSI_SENSE_ILLEGAL_REQUEST,
    12591259                              0, 0, 0, 0, 10, SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED, 0, 0 };
    1260         return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,
     1260        return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,
    12611261                                   VIRTIOSCSI_S_OK, abSense, sizeof(abSense), cbSenseCfg);
    12621262    }
     
    12661266    {
    12671267        Log2Func(("Aborting req submission because reset is in progress\n"));
    1268         return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_OK,
     1268        return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, cbDataIn + cbDataOut, SCSI_STATUS_OK,
    12691269                                   VIRTIOSCSI_S_RESET, NULL /*pbSense*/, 0 /*cbSense*/, cbSenseCfg);
    12701270    }
     
    12771277        uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED,
    12781278                              0, SCSI_SENSE_ILLEGAL_REQUEST, 0, 0, 0, 0, 10, 0, 0, 0 };
    1279         return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,
     1279        return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,
    12801280                                   VIRTIOSCSI_S_FAILURE, abSense, sizeof(abSense), cbSenseCfg);
    12811281    }
     
    12951295    pReq->hIoReq      = hIoReq;
    12961296    pReq->pTarget     = pTarget;
    1297     pReq->idxVirtq    = idxVirtq;
     1297    pReq->uVirtqNbr    = uVirtqNbr;
    12981298    pReq->cbDataIn    = cbDataIn;
    12991299    pReq->cbDataOut   = cbDataOut;
    1300     pReq->pDescChain  = pDescChain;
    1301     virtioCoreR3DescChainRetain(pDescChain); /* (For pReq->pDescChain. Released by virtioScsiR3FreeReq.) */
     1300    pReq->pVirtqBuf  = pVirtqBuf;
     1301    virtioCoreR3VirtqBufRetain(pVirtqBuf); /* (For pReq->pVirtqBuf. Released by virtioScsiR3FreeReq.) */
    13021302    pReq->uDataInOff  = offDataIn;
    13031303    pReq->uDataOutOff = offDataOut;
     
    13421342        respHdr.uResponse  = VIRTIOSCSI_S_FAILURE;
    13431343        respHdr.uResidual  = (cbDataIn + cbDataOut) & UINT32_MAX;
    1344         virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, &respHdr, abSense, cbSenseCfg);
     1344        virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, &respHdr, abSense, cbSenseCfg);
    13451345        virtioScsiR3FreeReq(pTarget, pReq);
    13461346    }
     
    13561356 * @param   pThis       VirtIO SCSI shared instance data.
    13571357 * @param   pThisCC     VirtIO SCSI ring-3 instance data.
    1358  * @param   idxVirtq    CONTROLQ_IDX
    1359  * @param   pDescChain  Descriptor chain to process.
     1358 * @param   uVirtqNbr   CONTROLQ_IDX
     1359 * @param   pVirtqBuf   Descriptor chain to process.
    13601360 */
    13611361static int virtioScsiR3Ctrl(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC,
    1362                             uint16_t idxVirtq, PVIRTIO_DESC_CHAIN_T pDescChain)
    1363 {
    1364     AssertReturn(pDescChain->cbPhysSend >= RT_MIN(sizeof(VIRTIOSCSI_CTRL_AN_T),
     1362                            uint16_t uVirtqNbr, PVIRTQBUF pVirtqBuf)
     1363{
     1364    AssertReturn(pVirtqBuf->cbPhysSend >= RT_MIN(sizeof(VIRTIOSCSI_CTRL_AN_T),
    13651365                                                  sizeof(VIRTIOSCSI_CTRL_TMF_T)), 0);
    13661366
     
    13711371    RT_ZERO(ScsiCtrlUnion);
    13721372
    1373     size_t const cbCtrl = RT_MIN(pDescChain->cbPhysSend, sizeof(VIRTIO_SCSI_CTRL_UNION_T));
     1373    size_t const cbCtrl = RT_MIN(pVirtqBuf->cbPhysSend, sizeof(VIRTIO_SCSI_CTRL_UNION_T));
    13741374    for (size_t offCtrl = 0; offCtrl < cbCtrl; )
    13751375    {
    13761376        size_t cbSeg = cbCtrl - offCtrl;
    1377         RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg);
     1377        RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pVirtqBuf->pSgPhysSend, &cbSeg);
    13781378        PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhys, &ScsiCtrlUnion.ab[offCtrl], cbSeg);
    13791379        offCtrl += cbSeg;
     
    13811381
    13821382    AssertReturn(   (ScsiCtrlUnion.Type.uType == VIRTIOSCSI_T_TMF
    1383                      && pDescChain->cbPhysSend >= sizeof(VIRTIOSCSI_CTRL_TMF_T))
     1383                     && pVirtqBuf->cbPhysSend >= sizeof(VIRTIOSCSI_CTRL_TMF_T))
    13841384                 || ( (   ScsiCtrlUnion.Type.uType == VIRTIOSCSI_T_AN_QUERY
    13851385                       || ScsiCtrlUnion.Type.uType == VIRTIOSCSI_T_AN_SUBSCRIBE)
    1386                      && pDescChain->cbPhysSend >= sizeof(VIRTIOSCSI_CTRL_AN_T)),
     1386                     && pVirtqBuf->cbPhysSend >= sizeof(VIRTIOSCSI_CTRL_AN_T)),
    13871387                    0 /** @todo r=bird: what kind of status is '0' here? */);
    13881388
     
    14011401            uint32_t uScsiLun = RT_MAKE_U16(ScsiCtrlUnion.Tmf.abScsiLun[3], ScsiCtrlUnion.Tmf.abScsiLun[2]) & 0x3fff;
    14021402            Log2Func(("[%s] (Target: %d LUN: %d)  Task Mgt Function: %s\n",
    1403                       VIRTQNAME(idxVirtq), uTarget, uScsiLun, virtioGetTMFTypeText(ScsiCtrlUnion.Tmf.uSubtype)));
     1403                      VIRTQNAME(uVirtqNbr), uTarget, uScsiLun, virtioGetTMFTypeText(ScsiCtrlUnion.Tmf.uSubtype)));
    14041404
    14051405            if (uTarget >= pThis->cTargets || !pThisCC->paTargetInstances[uTarget].fPresent)
     
    14621462                virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), ScsiCtrlUnion.AsyncNotify.fEventsRequested);
    14631463                Log2Func(("[%s] (Target: %d LUN: %d)  Async. Notification Query: %s\n",
    1464                           VIRTQNAME(idxVirtq), uTarget, uScsiLun, szTypeText));
     1464                          VIRTQNAME(uVirtqNbr), uTarget, uScsiLun, szTypeText));
    14651465            }
    14661466#endif
     
    14871487                virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), ScsiCtrlUnion.AsyncNotify.fEventsRequested);
    14881488                Log2Func(("[%s] (Target: %d LUN: %d)  Async. Notification Subscribe: %s\n",
    1489                           VIRTQNAME(idxVirtq), uTarget, uScsiLun, szTypeText));
     1489                          VIRTQNAME(uVirtqNbr), uTarget, uScsiLun, szTypeText));
    14901490            }
    14911491#endif
     
    15081508        default:
    15091509        {
    1510             LogFunc(("Unknown control type extracted from %s: %u\n", VIRTQNAME(idxVirtq), ScsiCtrlUnion.Type.uType));
     1510            LogFunc(("Unknown control type extracted from %s: %u\n", VIRTQNAME(uVirtqNbr), ScsiCtrlUnion.Type.uType));
    15111511
    15121512            bResponse = VIRTIOSCSI_S_FAILURE;
     
    15271527    RTSgBufInit(&ReqSgBuf, aReqSegs, cSegs);
    15281528
    1529     virtioCoreR3VirtqPut(pDevIns, &pThis->Virtio, idxVirtq, &ReqSgBuf, pDescChain, true /*fFence*/);
    1530     virtioCoreVirtqSync(pDevIns, &pThis->Virtio, idxVirtq);
     1529    virtioCoreR3VirtqBufPut(pDevIns, &pThis->Virtio, uVirtqNbr, &ReqSgBuf, pVirtqBuf, true /*fFence*/);
     1530    virtioCoreVirtqSync(pDevIns, &pThis->Virtio, uVirtqNbr);
    15311531
    15321532    return VINF_SUCCESS;
     
    15471547static DECLCALLBACK(int) virtioScsiR3WorkerThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    15481548{
    1549     uint16_t const      idxVirtq  = (uint16_t)(uintptr_t)pThread->pvUser;
     1549    uint16_t const      uVirtqNbr  = (uint16_t)(uintptr_t)pThread->pvUser;
    15501550    PVIRTIOSCSI         pThis     = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    15511551    PVIRTIOSCSICC       pThisCC   = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);
    1552     PVIRTIOSCSIWORKER   pWorker   = &pThis->aWorkers[idxVirtq];
    1553     PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[idxVirtq];
     1552    PVIRTIOSCSIWORKER   pWorker   = &pThis->aWorkers[uVirtqNbr];
     1553    PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[uVirtqNbr];
    15541554
    15551555    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     
    15581558    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    15591559    {
    1560         if (!pWorkerR3->cRedoDescs && IS_VIRTQ_EMPTY(pDevIns, &pThis->Virtio, idxVirtq))
     1560        if (!pWorkerR3->cRedoDescs && IS_VIRTQ_EMPTY(pDevIns, &pThis->Virtio, uVirtqNbr))
    15611561        {
    15621562            /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */
     
    15651565            if (!fNotificationSent)
    15661566            {
    1567                 Log6Func(("%s worker sleeping...\n", VIRTQNAME(idxVirtq)));
     1567                Log6Func(("%s worker sleeping...\n", VIRTQNAME(uVirtqNbr)));
    15681568                Assert(ASMAtomicReadBool(&pWorker->fSleeping));
    15691569                int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pWorker->hEvtProcess, RT_INDEFINITE_WAIT);
     
    15731573                if (rc == VERR_INTERRUPTED)
    15741574                    continue;
    1575                 Log6Func(("%s worker woken\n", VIRTQNAME(idxVirtq)));
     1575                Log6Func(("%s worker woken\n", VIRTQNAME(uVirtqNbr)));
    15761576                ASMAtomicWriteBool(&pWorker->fNotified, false);
    15771577            }
     
    15791579        }
    15801580
    1581         if (!pThis->afVirtqAttached[idxVirtq])
     1581        if (!pThis->afVirtqAttached[uVirtqNbr])
    15821582        {
    1583             LogFunc(("%s queue not attached, worker aborting...\n", VIRTQNAME(idxVirtq)));
     1583            LogFunc(("%s queue not attached, worker aborting...\n", VIRTQNAME(uVirtqNbr)));
    15841584            break;
    15851585        }
     
    15891589             for (int i = 0; i < pWorkerR3->cRedoDescs; i++)
    15901590             {
    1591                   PVIRTIO_DESC_CHAIN_T pDescChain;
    1592                   int rc = virtioCoreR3DescChainGet(pDevIns, &pThis->Virtio, idxVirtq,
    1593                                                     pWorkerR3->auRedoDescs[i], &pDescChain);
     1591                  PVIRTQBUF pVirtqBuf;
     1592                  int rc = virtioCoreR3VirtqBufGet(pDevIns, &pThis->Virtio, uVirtqNbr,
     1593                                                    pWorkerR3->auRedoDescs[i], &pVirtqBuf);
    15941594                  if (RT_FAILURE(rc))
    15951595                      LogRel(("Error fetching desc chain to redo, %Rrc", rc));
    15961596
    1597                   rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, idxVirtq, pDescChain);
     1597                  rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf);
    15981598                  if (RT_FAILURE(rc))
    15991599                      LogRel(("Error submitting req packet, resetting %Rrc", rc));
    16001600
    1601                   virtioCoreR3DescChainRelease(&pThis->Virtio, pDescChain);
     1601                  virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf);
    16021602             }
    16031603             pWorkerR3->cRedoDescs = 0;
    16041604
    1605              Log6Func(("fetching next descriptor chain from %s\n", VIRTQNAME(idxVirtq)));
    1606              PVIRTIO_DESC_CHAIN_T pDescChain = NULL;
    1607              int rc = virtioCoreR3VirtqGet(pDevIns, &pThis->Virtio, idxVirtq, &pDescChain, true);
     1605             Log6Func(("fetching next descriptor chain from %s\n", VIRTQNAME(uVirtqNbr)));
     1606             PVIRTQBUF pVirtqBuf = NULL;
     1607             int rc = virtioCoreR3VirtqBufGet(pDevIns, &pThis->Virtio, uVirtqNbr, &pVirtqBuf, true);
    16081608             if (rc == VERR_NOT_AVAILABLE)
    16091609             {
    1610                  Log6Func(("Nothing found in %s\n", VIRTQNAME(idxVirtq)));
     1610                 Log6Func(("Nothing found in %s\n", VIRTQNAME(uVirtqNbr)));
    16111611                 continue;
    16121612             }
    16131613
    16141614             AssertRC(rc);
    1615              if (idxVirtq == CONTROLQ_IDX)
    1616                  virtioScsiR3Ctrl(pDevIns, pThis, pThisCC, idxVirtq, pDescChain);
     1615             if (uVirtqNbr == CONTROLQ_IDX)
     1616                 virtioScsiR3Ctrl(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf);
    16171617             else /* request queue index */
    16181618             {
    1619                  rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, idxVirtq, pDescChain);
     1619                 rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf);
    16201620                 if (RT_FAILURE(rc))
    16211621                     LogRel(("Error submitting req packet, resetting %Rrc", rc));
    16221622             }
    16231623
    1624              virtioCoreR3DescChainRelease(&pThis->Virtio, pDescChain);
     1624             virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf);
    16251625        }
    16261626    }
     
    19671967
    19681968    virtioScsiSetVirtqNames(pThis);
    1969     for (int idxVirtq = 0; idxVirtq < VIRTIOSCSI_VIRTQ_CNT; idxVirtq++)
    1970         pHlp->pfnSSMGetBool(pSSM, &pThis->afVirtqAttached[idxVirtq]);
     1969    for (int uVirtqNbr = 0; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++)
     1970        pHlp->pfnSSMGetBool(pSSM, &pThis->afVirtqAttached[uVirtqNbr]);
    19711971
    19721972    pHlp->pfnSSMGetU32(pSSM,  &pThis->virtioScsiConfig.uNumVirtqs);
     
    20072007                                              cReqsRedo, VIRTQ_MAX_ENTRIES));
    20082008
    2009         for (uint16_t idxVirtq = VIRTQ_REQ_BASE; idxVirtq < VIRTIOSCSI_VIRTQ_CNT; idxVirtq++)
     2009        for (uint16_t uVirtqNbr = VIRTQ_REQ_BASE; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++)
    20102010        {
    2011             PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[idxVirtq];
     2011            PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[uVirtqNbr];
    20122012            pWorkerR3->cRedoDescs = 0;
    20132013        }
     
    20152015        for (int i = 0; i < cReqsRedo; i++)
    20162016        {
    2017             uint16_t idxVirtq;
    2018             rc = pHlp->pfnSSMGetU16(pSSM, &idxVirtq);
     2017            uint16_t uVirtqNbr;
     2018            rc = pHlp->pfnSSMGetU16(pSSM, &uVirtqNbr);
    20192019            AssertRCReturn(rc, rc);
    2020             AssertReturn(idxVirtq < VIRTIOSCSI_VIRTQ_CNT,
     2020            AssertReturn(uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT,
    20212021                         pHlp->pfnSSMSetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
    20222022                                                  N_("Bad queue index for re-do in saved state (%#x, max %#x)"),
    2023                                                   idxVirtq, VIRTIOSCSI_VIRTQ_CNT - 1));
     2023                                                  uVirtqNbr, VIRTIOSCSI_VIRTQ_CNT - 1));
    20242024
    20252025            uint16_t idxHead;
     
    20312031                                                  idxHead, VIRTQ_MAX_ENTRIES - 1));
    20322032
    2033             PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[idxVirtq];
     2033            PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[uVirtqNbr];
    20342034            pWorkerR3->auRedoDescs[pWorkerR3->cRedoDescs++] = idxHead;
    20352035            pWorkerR3->cRedoDescs %= VIRTQ_MAX_ENTRIES;
     
    20452045     * Nudge request queue workers
    20462046     */
    2047     for (int idxVirtq = VIRTQ_REQ_BASE; idxVirtq < VIRTIOSCSI_VIRTQ_CNT; idxVirtq++)
    2048     {
    2049         if (pThis->afVirtqAttached[idxVirtq])
     2047    for (int uVirtqNbr = VIRTQ_REQ_BASE; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++)
     2048    {
     2049        if (pThis->afVirtqAttached[uVirtqNbr])
    20502050        {
    2051             LogFunc(("Waking %s worker.\n", VIRTQNAME(idxVirtq)));
    2052             int rc2 = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[idxVirtq].hEvtProcess);
     2051            LogFunc(("Waking %s worker.\n", VIRTQNAME(uVirtqNbr)));
     2052            int rc2 = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[uVirtqNbr].hEvtProcess);
    20532053            AssertRCReturn(rc, rc2);
    20542054        }
     
    20692069    LogFunc(("SAVE EXEC!!\n"));
    20702070
    2071     for (int idxVirtq = 0; idxVirtq < VIRTIOSCSI_VIRTQ_CNT; idxVirtq++)
    2072         pHlp->pfnSSMPutBool(pSSM, pThis->afVirtqAttached[idxVirtq]);
     2071    for (int uVirtqNbr = 0; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++)
     2072        pHlp->pfnSSMPutBool(pSSM, pThis->afVirtqAttached[uVirtqNbr]);
    20732073
    20742074    pHlp->pfnSSMPutU32(pSSM,  pThis->virtioScsiConfig.uNumVirtqs);
     
    21172117                 while(--cReqsRedo)
    21182118                 {
    2119                     pHlp->pfnSSMPutU16(pSSM, pReq->idxVirtq);
    2120                     pHlp->pfnSSMPutU16(pSSM, pReq->pDescChain->uHeadIdx);
     2119                    pHlp->pfnSSMPutU16(pSSM, pReq->uVirtqNbr);
     2120                    pHlp->pfnSSMPutU16(pSSM, pReq->pVirtqBuf->uHeadIdx);
    21212121
    21222122                    rc = pTarget->pDrvMediaEx->pfnIoReqQuerySuspendedNext(pTarget->pDrvMediaEx, hIoReq,
     
    23352335     * be awake due to new reqs coming in.
    23362336     */
    2337     for (uint16_t idxVirtq = 0; idxVirtq < VIRTIOSCSI_REQ_VIRTQ_CNT; idxVirtq++)
    2338     {
    2339         if (ASMAtomicReadBool(&pThis->aWorkers[idxVirtq].fSleeping))
     2337    for (uint16_t uVirtqNbr = 0; uVirtqNbr < VIRTIOSCSI_REQ_VIRTQ_CNT; uVirtqNbr++)
     2338    {
     2339        if (ASMAtomicReadBool(&pThis->aWorkers[uVirtqNbr].fSleeping))
    23402340        {
    2341             Log6Func(("waking %s worker.\n", VIRTQNAME(idxVirtq)));
    2342             int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[idxVirtq].hEvtProcess);
     2341            Log6Func(("waking %s worker.\n", VIRTQNAME(uVirtqNbr)));
     2342            int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[uVirtqNbr].hEvtProcess);
    23432343            AssertRC(rc);
    23442344        }
     
    24142414    pThisCC->pMediaNotify = NULL;
    24152415
    2416     for (unsigned idxVirtq = 0; idxVirtq < VIRTIOSCSI_VIRTQ_CNT; idxVirtq++)
    2417     {
    2418         PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[idxVirtq];
     2416    for (unsigned uVirtqNbr = 0; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++)
     2417    {
     2418        PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[uVirtqNbr];
    24192419        if (pWorker->hEvtProcess != NIL_SUPSEMEVENT)
    24202420        {
     
    24232423        }
    24242424
    2425         if (pThisCC->aWorkers[idxVirtq].pThread)
     2425        if (pThisCC->aWorkers[uVirtqNbr].pThread)
    24262426        {
    24272427            /* Destroy the thread. */
    24282428            int rcThread;
    2429             int rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->aWorkers[idxVirtq].pThread, &rcThread);
     2429            int rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->aWorkers[uVirtqNbr].pThread, &rcThread);
    24302430            if (RT_FAILURE(rc) || RT_FAILURE(rcThread))
    24312431                AssertMsgFailed(("%s Failed to destroythread rc=%Rrc rcThread=%Rrc\n",
    24322432                                 __FUNCTION__, rc, rcThread));
    2433            pThisCC->aWorkers[idxVirtq].pThread = NULL;
     2433           pThisCC->aWorkers[uVirtqNbr].pThread = NULL;
    24342434        }
    24352435    }
     
    25262526
    25272527    /* Attach the queues and create worker threads for them: */
    2528     for (uint16_t idxVirtq = 0; idxVirtq < VIRTIOSCSI_VIRTQ_CNT; idxVirtq++)
    2529     {
    2530         rc = virtioCoreR3VirtqAttach(&pThis->Virtio, idxVirtq, VIRTQNAME(idxVirtq));
     2528    for (uint16_t uVirtqNbr = 0; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++)
     2529    {
     2530        rc = virtioCoreR3VirtqAttach(&pThis->Virtio, uVirtqNbr, VIRTQNAME(uVirtqNbr));
    25312531        if (RT_FAILURE(rc))
    25322532            continue;
    2533         if (idxVirtq == CONTROLQ_IDX || IS_REQ_VIRTQ(idxVirtq))
     2533        if (uVirtqNbr == CONTROLQ_IDX || IS_REQ_VIRTQ(uVirtqNbr))
    25342534        {
    2535             rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->aWorkers[idxVirtq].pThread,
    2536                                        (void *)(uintptr_t)idxVirtq, virtioScsiR3WorkerThread,
    2537                                        virtioScsiR3WorkerWakeUp, 0, RTTHREADTYPE_IO, VIRTQNAME(idxVirtq));
     2535            rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->aWorkers[uVirtqNbr].pThread,
     2536                                       (void *)(uintptr_t)uVirtqNbr, virtioScsiR3WorkerThread,
     2537                                       virtioScsiR3WorkerWakeUp, 0, RTTHREADTYPE_IO, VIRTQNAME(uVirtqNbr));
    25382538            if (rc != VINF_SUCCESS)
    25392539            {
    2540                 LogRel(("Error creating thread for Virtual Virtq %s: %Rrc\n", VIRTQNAME(idxVirtq), rc));
     2540                LogRel(("Error creating thread for Virtual Virtq %s: %Rrc\n", VIRTQNAME(uVirtqNbr), rc));
    25412541                return rc;
    25422542            }
    25432543
    2544             rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->aWorkers[idxVirtq].hEvtProcess);
     2544            rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->aWorkers[uVirtqNbr].hEvtProcess);
    25452545            if (RT_FAILURE(rc))
    25462546                return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
    25472547                                           N_("DevVirtioSCSI: Failed to create SUP event semaphore"));
    25482548        }
    2549         pThis->afVirtqAttached[idxVirtq] = true;
     2549        pThis->afVirtqAttached[uVirtqNbr] = true;
    25502550    }
    25512551
  • trunk/src/VBox/Devices/VirtIO/VirtioCore.cpp

    r84818 r84819  
    11/* $Id$ */
     2
    23/** @file
    3  * Virtio_1_0 - Virtio Common (PCI, feature & config mgt, queue mgt & proxy, notification mgt)
     4 * VirtioCore - Virtio Core (PCI, feature & config mgt, queue mgt & proxy, notification mgt)
    45 */
    56
     
    3536#include <VBox/AssertGuest.h>
    3637#include <VBox/vmm/pdmdev.h>
    37 #include "Virtio_1_0.h"
     38#include "VirtioCore.h"
    3839
    3940
     
    4243*********************************************************************************************************************************/
    4344#define INSTANCE(a_pVirtio)                 ((a_pVirtio)->szInstance)
    44 #define VIRTQNAME(a_pVirtio, a_idxVirtq)    ((a_pVirtio)->aVirtqState[(a_idxVirtq)].szVirtqName)
     45#define VIRTQNAME(a_pVirtio, a_uVirtqNbr)    ((a_pVirtio)->aVirtqState[(a_uVirtqNbr)].szVirtqName)
    4546#define IS_DRIVER_OK(a_pVirtio)             ((a_pVirtio)->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
    4647#define IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtqState) \
     
    135136/* Internal Functions */
    136137
    137 static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq);
     138static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr);
    138139static int  virtioKick(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint8_t uCause, uint16_t uVec);
    139140
     
    145146 */
    146147#ifdef IN_RING3
    147 DECLINLINE(void) virtioReadDesc(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq,
     148DECLINLINE(void) virtioReadDesc(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
    148149                                uint32_t idxDesc, PVIRTQ_DESC_T pDesc)
    149150{
    150151    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    151     uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[idxVirtq], 1); /* Make sure to avoid div-by-zero. */
     152    uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */
    152153    PDMDevHlpPCIPhysRead(pDevIns,
    153                       pVirtio->aGCPhysVirtqDesc[idxVirtq] + sizeof(VIRTQ_DESC_T) * (idxDesc % cVirtqItems),
     154                      pVirtio->aGCPhysVirtqDesc[uVirtqNbr] + sizeof(VIRTQ_DESC_T) * (idxDesc % cVirtqItems),
    154155                      pDesc, sizeof(VIRTQ_DESC_T));
    155156}
     
    160161 */
    161162#ifdef IN_RING3
    162 DECLINLINE(uint16_t) virtioReadAvailDescIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, uint32_t availIdx)
     163DECLINLINE(uint16_t) virtioReadAvailDescIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint32_t availIdx)
    163164{
    164165    uint16_t uDescIdx;
    165166    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    166     uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[idxVirtq], 1); /* Make sure to avoid div-by-zero. */
     167    uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */
    167168    PDMDevHlpPCIPhysRead(pDevIns,
    168                         pVirtio->aGCPhysVirtqAvail[idxVirtq]
     169                        pVirtio->aGCPhysVirtqAvail[uVirtqNbr]
    169170                      + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[availIdx % cVirtqItems]),
    170171                      &uDescIdx, sizeof(uDescIdx));
     
    172173}
    173174
    174 DECLINLINE(uint16_t) virtioReadAvailUsedEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)
     175DECLINLINE(uint16_t) virtioReadAvailUsedEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
    175176{
    176177    uint16_t uUsedEventIdx;
     
    178179    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    179180    PDMDevHlpPCIPhysRead(pDevIns,
    180                       pVirtio->aGCPhysVirtqAvail[idxVirtq] + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[pVirtio->uVirtqSize[idxVirtq]]),
     181                      pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[pVirtio->uVirtqSize[uVirtqNbr]]),
    181182                      &uUsedEventIdx, sizeof(uUsedEventIdx));
    182183    return uUsedEventIdx;
     
    184185#endif
    185186
    186 DECLINLINE(uint16_t) virtioReadAvailRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)
     187DECLINLINE(uint16_t) virtioReadAvailRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
    187188{
    188189    uint16_t uIdx = 0;
    189190    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    190191    PDMDevHlpPCIPhysRead(pDevIns,
    191                       pVirtio->aGCPhysVirtqAvail[idxVirtq] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx),
     192                      pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx),
    192193                      &uIdx, sizeof(uIdx));
    193194    return uIdx;
    194195}
    195196
    196 DECLINLINE(uint16_t) virtioReadAvailRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)
     197DECLINLINE(uint16_t) virtioReadAvailRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
    197198{
    198199    uint16_t fFlags = 0;
    199200    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    200201    PDMDevHlpPCIPhysRead(pDevIns,
    201                       pVirtio->aGCPhysVirtqAvail[idxVirtq] + RT_UOFFSETOF(VIRTQ_AVAIL_T, fFlags),
     202                      pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_AVAIL_T, fFlags),
    202203                      &fFlags, sizeof(fFlags));
    203204    return fFlags;
     
    211212
    212213#ifdef IN_RING3
    213 DECLINLINE(void) virtioWriteUsedElem(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq,
     214DECLINLINE(void) virtioWriteUsedElem(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
    214215                                     uint32_t usedIdx, uint32_t uDescIdx, uint32_t uLen)
    215216{
    216217    VIRTQ_USED_ELEM_T elem = { uDescIdx,  uLen };
    217218    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    218     uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[idxVirtq], 1); /* Make sure to avoid div-by-zero. */
     219    uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */
    219220    PDMDevHlpPCIPhysWrite(pDevIns,
    220                           pVirtio->aGCPhysVirtqUsed[idxVirtq] + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[usedIdx % cVirtqItems]),
     221                          pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[usedIdx % cVirtqItems]),
    221222                          &elem, sizeof(elem));
    222223}
    223224
    224 DECLINLINE(void) virtioWriteUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, uint16_t fFlags)
     225DECLINLINE(void) virtioWriteUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint16_t fFlags)
    225226{
    226227    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    227228    RT_UNTRUSTED_VALIDATED_FENCE(); /* VirtIO 1.0, Section 3.2.1.4.1 */
    228229    PDMDevHlpPCIPhysWrite(pDevIns,
    229                           pVirtio->aGCPhysVirtqUsed[idxVirtq] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags),
     230                          pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags),
    230231                          &fFlags, sizeof(fFlags));
    231232}
    232233#endif
    233234
    234 DECLINLINE(void) virtioWriteUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, uint16_t uIdx)
     235DECLINLINE(void) virtioWriteUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint16_t uIdx)
    235236{
    236237    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    237238    PDMDevHlpPCIPhysWrite(pDevIns,
    238                           pVirtio->aGCPhysVirtqUsed[idxVirtq] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx),
     239                          pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx),
    239240                          &uIdx, sizeof(uIdx));
    240241}
     
    243244#ifdef IN_RING3
    244245
    245 DECLINLINE(uint16_t) virtioReadUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)
     246DECLINLINE(uint16_t) virtioReadUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
    246247{
    247248    uint16_t uIdx = 0;
    248249    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    249250    PDMDevHlpPCIPhysRead(pDevIns,
    250                       pVirtio->aGCPhysVirtqUsed[idxVirtq] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx),
     251                      pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx),
    251252                      &uIdx, sizeof(uIdx));
    252253    return uIdx;
    253254}
    254255
    255 DECLINLINE(uint16_t) virtioReadUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)
     256DECLINLINE(uint16_t) virtioReadUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
    256257{
    257258    uint16_t fFlags = 0;
    258259    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    259260    PDMDevHlpPCIPhysRead(pDevIns,
    260                       pVirtio->aGCPhysVirtqUsed[idxVirtq] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags),
     261                      pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags),
    261262                      &fFlags, sizeof(fFlags));
    262263    return fFlags;
    263264}
    264265
    265 DECLINLINE(void) virtioWriteUsedAvailEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, uint32_t uAvailEventIdx)
     266DECLINLINE(void) virtioWriteUsedAvailEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint32_t uAvailEventIdx)
    266267{
    267268    /** VirtIO 1.0 uAvailEventIdx (avail_event) immediately follows ring */
    268269    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    269270    PDMDevHlpPCIPhysWrite(pDevIns,
    270                           pVirtio->aGCPhysVirtqUsed[idxVirtq] + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[pVirtio->uVirtqSize[idxVirtq]]),
     271                          pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[pVirtio->uVirtqSize[uVirtqNbr]]),
    271272                          &uAvailEventIdx, sizeof(uAvailEventIdx));
    272273}
     
    277278DECLINLINE(uint16_t) virtioCoreVirtqAvailCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQSTATE pVirtqState)
    278279{
    279     uint16_t uIdx    = virtioReadAvailRingIdx(pDevIns, pVirtio, pVirtqState->idxVirtq);
     280    uint16_t uIdx    = virtioReadAvailRingIdx(pDevIns, pVirtio, pVirtqState->uVirtqNbr);
    280281    uint16_t uShadow = pVirtqState->uAvailIdxShadow;
    281282
     
    287288
    288289    LogFunc(("%s has %u %s (idx=%u shadow=%u)\n",
    289         VIRTQNAME(pVirtio, pVirtqState->idxVirtq), uDelta, uDelta == 1 ? "entry" : "entries",
     290        VIRTQNAME(pVirtio, pVirtqState->uVirtqNbr), uDelta, uDelta == 1 ? "entry" : "entries",
    290291        uIdx, uShadow));
    291292
     
    297298 * @param   pDevIns     The device instance.
    298299 * @param   pVirtio     Pointer to the shared virtio state.
    299  * @param   idxVirtq    Virtq number
     300 * @param   uVirtqNbr    Virtq number
    300301 *
    301302 * @returns how many entries have been added to ring as a delta of the consumer's
    302303 *          avail index and the queue's guest-side current avail index.
    303304 */
    304 uint16_t virtioCoreVirtqAvailCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)
    305 {
    306     if (!IS_DRIVER_OK(pVirtio) || !pVirtio->uVirtqEnable[idxVirtq])
     305uint16_t virtioCoreVirtqAvailCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
     306{
     307    if (!IS_DRIVER_OK(pVirtio) || !pVirtio->uVirtqEnable[uVirtqNbr])
    307308    {
    308309        LogRelFunc(("Driver not ready or queue not enabled\n"));
    309310        return 0;
    310311    }
    311     return virtioCoreVirtqAvailCount(pDevIns, pVirtio, &pVirtio->aVirtqState[idxVirtq]);
     312    return virtioCoreVirtqAvailCount(pDevIns, pVirtio, &pVirtio->aVirtqState[uVirtqNbr]);
    312313}
    313314
     
    435436
    436437#ifdef IN_RING3
     438
     439/** API Function: See header file*/
    437440void virtioCorePrintFeatures(VIRTIOCORE *pVirtio, PCDBGFINFOHLP pHlp)
    438441{
     
    478481
    479482#ifdef LOG_ENABLED
    480 /**
    481  * Debug assist for consumer device code.
    482  * Does a formatted hex dump using Log(()), recommend using VIRTIO_HEX_DUMP() macro to
    483  * control enabling of logging efficiently.
    484  *
    485  * @param   pv          pointer to buffer to dump contents of
    486  * @param   cb          count of characters to dump from buffer
    487  * @param   uBase       base address of per-row address prefixing of hex output
    488  * @param   pszTitle    Optional title. If present displays title that lists
    489  *                      provided text with value of cb to indicate size next to it.
    490  */
     483
     484/** API Function: See header file */
    491485void virtioCoreHexDump(uint8_t *pv, uint32_t cb, uint32_t uBase, const char *pszTitle)
    492486{
     
    527521}
    528522
    529 /**
    530  * Debug assist for consumer device code.
    531  * Do a hex dump of memory in guest physical context
    532  *
    533  * @param   GCPhys      pointer to buffer to dump contents of
    534  * @param   cb          count of characters to dump from buffer
    535  * @param   uBase       base address of per-row address prefixing of hex output
    536  * @param   pszTitle    Optional title. If present displays title that lists
    537  *                      provided text with value of cb to indicate size next to it.
    538  */
     523/* API FUnction: See header file */
    539524void virtioCoreGCPhysHexDump(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint16_t cb, uint32_t uBase, const char *pszTitle)
    540525{
     
    579564#endif /* LOG_ENABLED */
    580565
    581 /**
    582  * Log memory-mapped I/O input or output value.
    583  *
    584  * This is designed to be invoked by macros that can make contextual assumptions
    585  * (e.g. implicitly derive MACRO parameters from the invoking function). It is exposed
    586  * for the VirtIO client doing the device-specific implementation in order to log in a
    587  * similar fashion accesses to the device-specific MMIO configuration structure. Macros
    588  * that leverage this function are found in virtioCommonCfgAccessed() and can be
    589  * used as an example of how to use this effectively for the device-specific
    590  * code.
    591  *
    592  * @param   pszFunc     To avoid displaying this function's name via __FUNCTION__ or LogFunc()
    593  * @param   pszMember   Name of struct member
    594  * @param   pv          pointer to value
    595  * @param   cb          size of value
    596  * @param   uOffset     offset into member where value starts
    597  * @param   fWrite      True if write I/O
    598  * @param   fHasIndex   True if the member is indexed
    599  * @param   idx         The index if fHasIndex
    600  */
     566/** API function: See header file */
    601567void virtioCoreLogMappedIoValue(const char *pszFunc, const char *pszMember, uint32_t uMemberSize,
    602568                                const void *pv, uint32_t cb, uint32_t uOffset, int fWrite,
     
    673639#ifdef IN_RING3
    674640
    675 void virtioCoreR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    676 {
    677     RT_NOREF(pDevIns);
    678     bool fNone     = pszArgs && *pszArgs == '\0';
    679     bool fAll      = pszArgs && (*pszArgs == 'a' || *pszArgs == 'A'); /* "all"      */
    680     bool fBasic    = pszArgs && (*pszArgs == 'b' || *pszArgs == 'B'); /* "basic"    */
    681     bool fState    = pszArgs && (*pszArgs == 's' || *pszArgs == 'S'); /* "state"    */
    682     bool fPointers = pszArgs && (*pszArgs == 'p' || *pszArgs == 'P'); /* "pointers" */
    683     bool fVirtqs   = pszArgs && (*pszArgs == 'q' || *pszArgs == 'Q'); /* "queues    */
    684     RT_NOREF6(fNone, fAll, fBasic, fState, fPointers, fVirtqs);
    685     pHlp->pfnPrintf(pHlp, "");
    686 
    687 }
    688 
    689 void virtioCoreR3VirtqInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs, int idxVirtq)
     641/** API Fuunction: See header file */
     642void virtioCoreR3VirtqInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs, int uVirtqNbr)
    690643{
    691644    RT_NOREF(pszArgs);
    692645    PVIRTIOCORE pVirtio = PDMDEVINS_2_DATA(pDevIns, PVIRTIOCORE);
    693     PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq];
    694 
    695 //    bool fDump      = pszArgs && (*pszArgs == 'd' || *pszArgs == 'D'); /* "dump" (avail phys descriptor)"       */
    696 
    697     uint16_t uAvailIdx       = virtioReadAvailRingIdx(pDevIns, pVirtio, idxVirtq);
     646    PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];
     647
     648    /** @todo add ability to dump physical contents of any descriptor (using existing VirtIO core API function) */
     649//    bool fDump      = pszArgs && (*pszArgs == 'd' || *pszArgs == 'D'); /* "dump" (avail phys descriptor)"
     650
     651    uint16_t uAvailIdx       = virtioReadAvailRingIdx(pDevIns, pVirtio, uVirtqNbr);
    698652    uint16_t uAvailIdxShadow = pVirtqState->uAvailIdxShadow;
    699653
    700     uint16_t uUsedIdx        = virtioReadUsedRingIdx(pDevIns, pVirtio, idxVirtq);
     654    uint16_t uUsedIdx        = virtioReadUsedRingIdx(pDevIns, pVirtio, uVirtqNbr);
    701655    uint16_t uUsedIdxShadow  = pVirtqState->uUsedIdxShadow;
    702656
    703     PVIRTIO_DESC_CHAIN_T pDescChain = NULL;
     657    PVIRTQBUF pVirtqBuf = NULL;
    704658
    705659    bool fEmpty = IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtqState);
    706660
    707     LogFunc(("%s, empty = %s\n", VIRTQNAME(pVirtio, idxVirtq), fEmpty ? "true" : "false"));
     661    LogFunc(("%s, empty = %s\n", VIRTQNAME(pVirtio, uVirtqNbr), fEmpty ? "true" : "false"));
    708662
    709663    int cSendSegs = 0, cReturnSegs = 0;
    710664    if (!fEmpty)
    711665    {
    712         virtioCoreR3VirtqPeek(pDevIns,  pVirtio, idxVirtq, &pDescChain);
    713         cSendSegs   = pDescChain->pSgPhysSend ? pDescChain->pSgPhysSend->cSegs : 0;
    714         cReturnSegs = pDescChain->pSgPhysReturn ? pDescChain->pSgPhysReturn->cSegs : 0;
    715     }
    716 
    717     bool fAvailNoInterrupt   = virtioReadAvailRingFlags(pDevIns, pVirtio, idxVirtq) & VIRTQ_AVAIL_F_NO_INTERRUPT;
    718     bool fUsedNoNotify       = virtioReadUsedRingFlags(pDevIns, pVirtio, idxVirtq) & VIRTQ_USED_F_NO_NOTIFY;
    719 
    720 
    721     pHlp->pfnPrintf(pHlp, "       queue enabled: ........... %s\n", pVirtio->uVirtqEnable[idxVirtq] ? "true" : "false");
    722     pHlp->pfnPrintf(pHlp, "       size: .................... %d\n", pVirtio->uVirtqSize[idxVirtq]);
    723     pHlp->pfnPrintf(pHlp, "       notify offset: ........... %d\n", pVirtio->uVirtqNotifyOff[idxVirtq]);
     666        virtioCoreR3VirtqBufPeek(pDevIns,  pVirtio, uVirtqNbr, &pVirtqBuf);
     667        cSendSegs   = pVirtqBuf->pSgPhysSend ? pVirtqBuf->pSgPhysSend->cSegs : 0;
     668        cReturnSegs = pVirtqBuf->pSgPhysReturn ? pVirtqBuf->pSgPhysReturn->cSegs : 0;
     669    }
     670
     671    bool fAvailNoInterrupt   = virtioReadAvailRingFlags(pDevIns, pVirtio, uVirtqNbr) & VIRTQ_AVAIL_F_NO_INTERRUPT;
     672    bool fUsedNoNotify       = virtioReadUsedRingFlags(pDevIns, pVirtio, uVirtqNbr) & VIRTQ_USED_F_NO_NOTIFY;
     673
     674
     675    pHlp->pfnPrintf(pHlp, "       queue enabled: ........... %s\n", pVirtio->uVirtqEnable[uVirtqNbr] ? "true" : "false");
     676    pHlp->pfnPrintf(pHlp, "       size: .................... %d\n", pVirtio->uVirtqSize[uVirtqNbr]);
     677    pHlp->pfnPrintf(pHlp, "       notify offset: ........... %d\n", pVirtio->uVirtqNotifyOff[uVirtqNbr]);
    724678    if (pVirtio->fMsiSupport)
    725         pHlp->pfnPrintf(pHlp, "       MSIX vector: ....... %4.4x\n", pVirtio->uVirtqMsixVector[idxVirtq]);
     679        pHlp->pfnPrintf(pHlp, "       MSIX vector: ....... %4.4x\n", pVirtio->uVirtqMsixVector[uVirtqNbr]);
    726680    pHlp->pfnPrintf(pHlp, "\n");
    727681    pHlp->pfnPrintf(pHlp, "       avail ring (%d entries):\n", uAvailIdx - uAvailIdxShadow);
     
    740694        pHlp->pfnPrintf(pHlp, "          head idx: ............. %d\n", uUsedIdx);
    741695        pHlp->pfnPrintf(pHlp, "          segs: ................. %d\n", cSendSegs + cReturnSegs);
    742         pHlp->pfnPrintf(pHlp, "          refCnt ................ %d\n", pDescChain->cRefs);
     696        pHlp->pfnPrintf(pHlp, "          refCnt ................ %d\n", pVirtqBuf->cRefs);
    743697        pHlp->pfnPrintf(pHlp, "\n");
    744         pHlp->pfnPrintf(pHlp, "          host-to-guest (%d bytes):\n",      pDescChain->cbPhysSend);
     698        pHlp->pfnPrintf(pHlp, "          host-to-guest (%d bytes):\n",      pVirtqBuf->cbPhysSend);
    745699        pHlp->pfnPrintf(pHlp,     "             segs: .............. %d\n", cSendSegs);
    746700        if (cSendSegs)
    747701        {
    748             pHlp->pfnPrintf(pHlp, "             index: ............. %d\n", pDescChain->pSgPhysSend->idxSeg);
    749             pHlp->pfnPrintf(pHlp, "             unsent ............. %d\n", pDescChain->pSgPhysSend->cbSegLeft);
     702            pHlp->pfnPrintf(pHlp, "             index: ............. %d\n", pVirtqBuf->pSgPhysSend->idxSeg);
     703            pHlp->pfnPrintf(pHlp, "             unsent ............. %d\n", pVirtqBuf->pSgPhysSend->cbSegLeft);
    750704        }
    751705        pHlp->pfnPrintf(pHlp, "\n");
    752         pHlp->pfnPrintf(pHlp,     "          guest-to-host (%d bytes)\n",   pDescChain->cbPhysReturn);
     706        pHlp->pfnPrintf(pHlp,     "          guest-to-host (%d bytes)\n",   pVirtqBuf->cbPhysReturn);
    753707        pHlp->pfnPrintf(pHlp,     "             segs: .............. %d\n", cReturnSegs);
    754708        if (cReturnSegs)
    755709        {
    756             pHlp->pfnPrintf(pHlp, "             index: ............. %d\n", pDescChain->pSgPhysReturn->idxSeg);
    757             pHlp->pfnPrintf(pHlp, "             unsent ............. %d\n", pDescChain->pSgPhysReturn->cbSegLeft);
     710            pHlp->pfnPrintf(pHlp, "             index: ............. %d\n", pVirtqBuf->pSgPhysReturn->idxSeg);
     711            pHlp->pfnPrintf(pHlp, "             unsent ............. %d\n", pVirtqBuf->pSgPhysReturn->cbSegLeft);
    758712        }
    759713    } else
     
    763717}
    764718
    765 /**
    766  * Allocate client context for client to work with VirtIO-#provided with queue
    767  *
    768  * @param   pVirtio     Pointer to the shared virtio state.
    769  * @param   idxVirtq    Virtq number
    770  * @param   pcszName    Name to give queue
    771  *
    772  * @returns VBox status code.
    773  */
    774 int virtioCoreR3VirtqAttach(PVIRTIOCORE pVirtio, uint16_t idxVirtq, const char *pcszName)
     719int virtioCoreR3VirtqAttach(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, const char *pcszName)
    775720{
    776721    LogFunc(("%s\n", pcszName));
    777     PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq];
    778     pVirtqState->idxVirtq = idxVirtq;
     722    PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];
     723    pVirtqState->uVirtqNbr = uVirtqNbr;
    779724    pVirtqState->uAvailIdxShadow = 0;
    780725    pVirtqState->uUsedIdxShadow  = 0;
     
    788733#ifdef IN_RING3
    789734
    790 int virtioCoreR3DescChainGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq,
    791                              uint16_t uHeadIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain)
    792 {
    793     AssertReturn(ppDescChain, VERR_INVALID_POINTER);
    794     *ppDescChain = NULL;
    795 
    796     Assert(idxVirtq < RT_ELEMENTS(pVirtio->aVirtqState));
    797 
    798     PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq];
    799 
    800     AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtio->uVirtqEnable[idxVirtq],
     735/** API Function: See header file */
     736int virtioCoreR3VirtqBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
     737                             uint16_t uHeadIdx, PPVIRTQBUF ppVirtqBuf)
     738{
     739    AssertReturn(ppVirtqBuf, VERR_INVALID_POINTER);
     740    *ppVirtqBuf = NULL;
     741
     742    Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState));
     743
     744    PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];
     745
     746    AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtio->uVirtqEnable[uVirtqNbr],
    801747                    ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
    802748
     
    809755     * Allocate and initialize the descriptor chain structure.
    810756     */
    811     PVIRTIO_DESC_CHAIN_T pDescChain = (PVIRTIO_DESC_CHAIN_T)RTMemAllocZ(sizeof(VIRTIO_DESC_CHAIN_T));
    812     AssertReturn(pDescChain, VERR_NO_MEMORY);
    813     pDescChain->u32Magic = VIRTIO_DESC_CHAIN_MAGIC;
    814     pDescChain->cRefs    = 1;
    815     pDescChain->uHeadIdx = uHeadIdx;
    816     *ppDescChain = pDescChain;
     757    PVIRTQBUF pVirtqBuf = (PVIRTQBUF)RTMemAllocZ(sizeof(VIRTQBUF_T));
     758    AssertReturn(pVirtqBuf, VERR_NO_MEMORY);
     759    pVirtqBuf->u32Magic = VIRTQBUF_MAGIC;
     760    pVirtqBuf->cRefs    = 1;
     761    pVirtqBuf->uHeadIdx = uHeadIdx;
     762    *ppVirtqBuf = pVirtqBuf;
    817763
    818764    /*
     
    825771    uint32_t cSegsIn = 0;
    826772    uint32_t cSegsOut = 0;
    827     PVIRTIOSGSEG paSegsIn  = pDescChain->aSegsIn;
    828     PVIRTIOSGSEG paSegsOut = pDescChain->aSegsOut;
     773    PVIRTIOSGSEG paSegsIn  = pVirtqBuf->aSegsIn;
     774    PVIRTIOSGSEG paSegsOut = pVirtqBuf->aSegsOut;
    829775
    830776    do
     
    853799        RT_UNTRUSTED_VALIDATED_FENCE();
    854800
    855         virtioReadDesc(pDevIns, pVirtio, idxVirtq, uDescIdx, &desc);
     801        virtioReadDesc(pDevIns, pVirtio, uVirtqNbr, uDescIdx, &desc);
    856802
    857803        if (desc.fFlags & VIRTQ_DESC_F_WRITE)
    858804        {
    859             Log6Func(("%s IN  desc_idx=%u seg=%u addr=%RGp cb=%u\n", VIRTQNAME(pVirtio, idxVirtq), uDescIdx, cSegsIn, desc.GCPhysBuf, desc.cb));
     805            Log6Func(("%s IN  desc_idx=%u seg=%u addr=%RGp cb=%u\n", VIRTQNAME(pVirtio, uVirtqNbr), uDescIdx, cSegsIn, desc.GCPhysBuf, desc.cb));
    860806            cbIn += desc.cb;
    861807            pSeg = &paSegsIn[cSegsIn++];
     
    863809        else
    864810        {
    865             Log6Func(("%s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n", VIRTQNAME(pVirtio, idxVirtq), uDescIdx, cSegsOut, desc.GCPhysBuf, desc.cb));
     811            Log6Func(("%s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n", VIRTQNAME(pVirtio, uVirtqNbr), uDescIdx, cSegsOut, desc.GCPhysBuf, desc.cb));
    866812            cbOut += desc.cb;
    867813            pSeg = &paSegsOut[cSegsOut++];
     
    884830    if (cSegsIn)
    885831    {
    886         virtioCoreSgBufInit(&pDescChain->SgBufIn, paSegsIn, cSegsIn);
    887         pDescChain->pSgPhysReturn = &pDescChain->SgBufIn;
    888         pDescChain->cbPhysReturn  = cbIn;
     832        virtioCoreSgBufInit(&pVirtqBuf->SgBufIn, paSegsIn, cSegsIn);
     833        pVirtqBuf->pSgPhysReturn = &pVirtqBuf->SgBufIn;
     834        pVirtqBuf->cbPhysReturn  = cbIn;
    889835        STAM_REL_COUNTER_ADD(&pVirtio->StatDescChainsSegsIn, cSegsIn);
    890836    }
     
    892838    if (cSegsOut)
    893839    {
    894         virtioCoreSgBufInit(&pDescChain->SgBufOut, paSegsOut, cSegsOut);
    895         pDescChain->pSgPhysSend   = &pDescChain->SgBufOut;
    896         pDescChain->cbPhysSend    = cbOut;
     840        virtioCoreSgBufInit(&pVirtqBuf->SgBufOut, paSegsOut, cSegsOut);
     841        pVirtqBuf->pSgPhysSend   = &pVirtqBuf->SgBufOut;
     842        pVirtqBuf->cbPhysSend    = cbOut;
    897843        STAM_REL_COUNTER_ADD(&pVirtio->StatDescChainsSegsOut, cSegsOut);
    898844    }
     
    904850}
    905851
    906 
    907 /**
    908  * Retains a reference to the given descriptor chain.
    909  *
    910  * @returns New reference count.
    911  * @retval  UINT32_MAX on invalid parameter.
    912  * @param   pDescChain      The descriptor chain to reference.
    913  */
    914 uint32_t virtioCoreR3DescChainRetain(PVIRTIO_DESC_CHAIN_T pDescChain)
    915 {
    916     AssertReturn(pDescChain, UINT32_MAX);
    917     AssertReturn(pDescChain->u32Magic == VIRTIO_DESC_CHAIN_MAGIC, UINT32_MAX);
    918     uint32_t cRefs = ASMAtomicIncU32(&pDescChain->cRefs);
     852/** API Function: See header file */
     853uint32_t virtioCoreR3VirtqBufRetain(PVIRTQBUF pVirtqBuf)
     854{
     855    AssertReturn(pVirtqBuf, UINT32_MAX);
     856    AssertReturn(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC, UINT32_MAX);
     857    uint32_t cRefs = ASMAtomicIncU32(&pVirtqBuf->cRefs);
    919858    Assert(cRefs > 1);
    920859    Assert(cRefs < 16);
     
    923862
    924863
    925 /**
    926  * Releases a reference to the given descriptor chain.
    927  *
    928  * @returns New reference count.
    929  * @retval  0 if freed or invalid parameter.
    930  * @param   pVirtio         Pointer to the shared virtio state.
    931  * @param   pDescChain      The descriptor chain to reference.  NULL is quietly
    932  *                          ignored (returns 0).
    933  */
    934 uint32_t virtioCoreR3DescChainRelease(PVIRTIOCORE pVirtio, PVIRTIO_DESC_CHAIN_T pDescChain)
    935 {
    936     if (!pDescChain)
     864/** API Function: See header file */
     865uint32_t virtioCoreR3VirtqBufRelease(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf)
     866{
     867    if (!pVirtqBuf)
    937868        return 0;
    938     AssertReturn(pDescChain, 0);
    939     AssertReturn(pDescChain->u32Magic == VIRTIO_DESC_CHAIN_MAGIC, 0);
    940     uint32_t cRefs = ASMAtomicDecU32(&pDescChain->cRefs);
     869    AssertReturn(pVirtqBuf, 0);
     870    AssertReturn(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC, 0);
     871    uint32_t cRefs = ASMAtomicDecU32(&pVirtqBuf->cRefs);
    941872    Assert(cRefs < 16);
    942873    if (cRefs == 0)
    943874    {
    944         pDescChain->u32Magic = ~VIRTIO_DESC_CHAIN_MAGIC;
    945         RTMemFree(pDescChain);
     875        pVirtqBuf->u32Magic = ~VIRTQBUF_MAGIC;
     876        RTMemFree(pVirtqBuf);
    946877        STAM_REL_COUNTER_INC(&pVirtio->StatDescChainsFreed);
    947878    }
     
    949880}
    950881
    951 
    952 /*
    953  * Notifies guest (via ISR or MSI-X) of device configuration change
    954  *
    955  * @param   pVirtio     Pointer to the shared virtio state.
    956  */
     882/** API Function: See header file */
    957883void virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio)
    958884{
     
    960886}
    961887
    962 /**
    963  * Enable or Disable notification for the specified queue
    964  *
    965  * @param   pVirtio     Pointer to the shared virtio state.
    966  * @param   idxVirtq    Virtq number
    967  * @param   fEnable    Selects notification mode (enabled or disabled)
    968  */
    969 void virtioCoreVirtqNotifyEnable(PVIRTIOCORE pVirtio, uint16_t idxVirtq, bool fEnable)
     888void virtioCoreVirtqEnableNotify(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, bool fEnable)
    970889{
    971890    if (pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
    972891    {
    973         uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, idxVirtq);
     892        uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, uVirtqNbr);
    974893
    975894        if (fEnable)
     
    978897            fFlags |= VIRTQ_USED_F_NO_NOTIFY;
    979898
    980         virtioWriteUsedRingFlags(pVirtio->pDevInsR3, pVirtio, idxVirtq, fFlags);
    981     }
    982 }
    983 
    984 /**
    985  * Initiate orderly reset procedure. This is an exposed API for clients that might need it.
    986  * Invoked by client to reset the device and driver (see VirtIO 1.0 section 2.1.1/2.1.2)
    987  *
    988  * @param   pVirtio     Pointer to the virtio state.
    989  */
     899        virtioWriteUsedRingFlags(pVirtio->pDevInsR3, pVirtio, uVirtqNbr, fFlags);
     900    }
     901}
     902
     903/** API function: See Header file  */
    990904void virtioCoreResetAll(PVIRTIOCORE pVirtio)
    991905{
     
    999913}
    1000914
    1001 /**
    1002  * Fetches descriptor chain using avail ring of indicated queue and converts the descriptor
    1003  * chain into its OUT (to device) and IN to guest components, but does NOT remove it from
    1004  * the 'avail' queue. I.e. doesn't advance the index.  This can be used with virtioVirtqSkip(),
    1005  * which *does* advance the avail index. Together they facilitate a mechanism that allows
    1006  * work with a queue element (descriptor chain) to be aborted if necessary, by not advancing
    1007  * the pointer, or, upon success calling the skip function (above) to move to the next element.
    1008  *
    1009  * Additionally it converts the OUT desc chain data to a contiguous virtual
    1010  * memory buffer for easy consumption by the caller. The caller must return the
    1011  * descriptor chain pointer via virtioCoreR3VirtqPut() and then call virtioCoreVirtqSync()
    1012  * at some point to return the data to the guest and complete the transaction.
    1013  *
    1014  * @param   pDevIns     The device instance.
    1015  * @param   pVirtio     Pointer to the shared virtio state.
    1016  * @param   idxVirtq    Virtq number
    1017  * @param   ppDescChain Address to store pointer to descriptor chain that contains the
    1018  *                      pre-processed transaction information pulled from the virtq.
    1019  *
    1020  * @returns VBox status code:
    1021  * @retval  VINF_SUCCESS         Success
    1022  * @retval  VERR_INVALID_STATE   VirtIO not in ready state (asserted).
    1023  * @retval  VERR_NOT_AVAILABLE   If the queue is empty.
    1024  */
    1025 
    1026 int virtioCoreR3VirtqPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq,
    1027                          PPVIRTIO_DESC_CHAIN_T ppDescChain)
    1028 {
    1029     return virtioCoreR3VirtqGet(pDevIns, pVirtio,  idxVirtq, ppDescChain, false);
    1030 }
    1031 
    1032 /**
    1033  * Skip the next entry in the specified queue (typically used with virtioCoreR3VirtqPeek())
    1034  *
    1035  * @param   pVirtio     Pointer to the virtio state.
    1036  * @param   idxVirtq    Index of queue
    1037  */
    1038 int virtioCoreR3VirtqSkip(PVIRTIOCORE pVirtio, uint16_t idxVirtq)
    1039 {
    1040     Assert(idxVirtq < RT_ELEMENTS(pVirtio->aVirtqState));
    1041     PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq];
    1042 
    1043     AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtio->uVirtqEnable[idxVirtq],
     915/** API function: See Header file  */
     916int virtioCoreR3VirtqBufPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
     917                         PPVIRTQBUF ppVirtqBuf)
     918{
     919    return virtioCoreR3VirtqBufGet(pDevIns, pVirtio,  uVirtqNbr, ppVirtqBuf, false);
     920}
     921
     922/** API function: See Header file  */
     923int virtioCoreR3VirtqBufSkip(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
     924{
     925    Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState));
     926    PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];
     927
     928    AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtio->uVirtqEnable[uVirtqNbr],
    1044929                    ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
    1045930
     
    1053938}
    1054939
    1055 /**
    1056  * Fetches descriptor chain using avail ring of indicated queue and converts the descriptor
    1057  * chain into its OUT (to device) and IN to guest components.
    1058  *
    1059  * Additionally it converts the OUT desc chain data to a contiguous virtual
    1060  * memory buffer for easy consumption by the caller. The caller must return the
    1061  * descriptor chain pointer via virtioCoreR3VirtqPut() and then call virtioCoreVirtqSync()
    1062  * at some point to return the data to the guest and complete the transaction.
    1063  *
    1064  * @param   pDevIns     The device instance.
    1065  * @param   pVirtio     Pointer to the shared virtio state.
    1066  * @param   idxVirtq    Virtq number
    1067  * @param   ppDescChain Address to store pointer to descriptor chain that contains the
    1068  *                      pre-processed transaction information pulled from the virtq.
    1069  *                      Returned reference must be released by calling
    1070  *                      virtioCoreR3DescChainRelease().
    1071  * @param   fRemove     flags whether to remove desc chain from queue (false = peek)
    1072  *
    1073  * @returns VBox status code:
    1074  * @retval  VINF_SUCCESS         Success
    1075  * @retval  VERR_INVALID_STATE   VirtIO not in ready state (asserted).
    1076  * @retval  VERR_NOT_AVAILABLE   If the queue is empty.
    1077  */
    1078 int virtioCoreR3VirtqGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq,
    1079                          PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove)
    1080 {
    1081     PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq];
     940/** API function: See Header file  */
     941int virtioCoreR3VirtqBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
     942                         PPVIRTQBUF ppVirtqBuf, bool fRemove)
     943{
     944    PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];
    1082945
    1083946    if (IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtqState))
    1084947        return VERR_NOT_AVAILABLE;
    1085948
    1086     uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, idxVirtq, pVirtqState->uAvailIdxShadow);
     949    uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, uVirtqNbr, pVirtqState->uAvailIdxShadow);
    1087950
    1088951    if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX)
    1089         virtioWriteUsedAvailEvent(pDevIns,pVirtio, idxVirtq, pVirtqState->uAvailIdxShadow + 1);
     952        virtioWriteUsedAvailEvent(pDevIns,pVirtio, uVirtqNbr, pVirtqState->uAvailIdxShadow + 1);
    1090953
    1091954    if (fRemove)
    1092955        pVirtqState->uAvailIdxShadow++;
    1093956
    1094     int rc = virtioCoreR3DescChainGet(pDevIns, pVirtio, idxVirtq, uHeadIdx, ppDescChain);
     957    int rc = virtioCoreR3VirtqBufGet(pDevIns, pVirtio, uVirtqNbr, uHeadIdx, ppVirtqBuf);
    1095958    return rc;
    1096959}
    1097960
    1098 /**
    1099  * Returns data to the guest to complete a transaction initiated by virtVirtqGet().
    1100  *
    1101  * The caller passes in a pointer to a scatter-gather buffer of virtual memory segments
    1102  * and a pointer to the descriptor chain context originally derived from the pulled
    1103  * queue entry, and this function will write the virtual memory s/g buffer into the
    1104  * guest's physical memory free the descriptor chain. The caller handles the freeing
    1105  * (as needed) of the virtual memory buffer.
    1106  *
    1107  * @note This does a write-ahead to the used ring of the guest's queue. The data
    1108  *       written won't be seen by the guest until the next call to virtioCoreVirtqSync()
    1109  *
    1110  *
    1111  * @param   pDevIns         The device instance (for reading).
    1112  * @param   pVirtio         Pointer to the shared virtio state.
    1113  * @param   idxVirtq        Virtq number
    1114  *
    1115  * @param   pSgVirtReturn   Points to scatter-gather buffer of virtual memory
    1116  *                          segments the caller is returning to the guest.
    1117  *
    1118  * @param   pDescChain      This contains the context of the scatter-gather
    1119  *                          buffer originally pulled from the queue.
    1120  *
    1121  * @param   fFence          If true, put up copy fence (memory barrier) after
    1122  *                          copying to guest phys. mem.
    1123  *
    1124  * @returns VBox status code.
    1125  * @retval  VINF_SUCCESS       Success
    1126  * @retval  VERR_INVALID_STATE VirtIO not in ready state
    1127  * @retval  VERR_NOT_AVAILABLE Virtq is empty
    1128  *
    1129  * @note    This function will not release any reference to pDescChain.  The
    1130  *          caller must take care of that.
    1131  */
    1132 int virtioCoreR3VirtqPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, PRTSGBUF pSgVirtReturn,
    1133                          PVIRTIO_DESC_CHAIN_T pDescChain, bool fFence)
    1134 {
    1135     Assert(idxVirtq < RT_ELEMENTS(pVirtio->aVirtqState));
    1136     PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq];
    1137     PVIRTIOSGBUF pSgPhysReturn = pDescChain->pSgPhysReturn;
    1138 
    1139     Assert(pDescChain->u32Magic == VIRTIO_DESC_CHAIN_MAGIC);
    1140     Assert(pDescChain->cRefs > 0);
     961/** API function: See Header file  */
     962int virtioCoreR3VirtqBufPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, PRTSGBUF pSgVirtReturn,
     963                            PVIRTQBUF pVirtqBuf, bool fFence)
     964{
     965    Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState));
     966    PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];
     967    PVIRTIOSGBUF pSgPhysReturn = pVirtqBuf->pSgPhysReturn;
     968
     969    Assert(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC);
     970    Assert(pVirtqBuf->cRefs > 0);
    1141971
    1142972    AssertMsgReturn(IS_DRIVER_OK(pVirtio), ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
    1143973
    1144974    Log6Func(("Copying client data to %s, desc chain (head desc_idx %d)\n",
    1145               VIRTQNAME(pVirtio, idxVirtq), virtioReadUsedRingIdx(pDevIns, pVirtio, idxVirtq)));
     975              VIRTQNAME(pVirtio, uVirtqNbr), virtioReadUsedRingIdx(pDevIns, pVirtio, uVirtqNbr)));
    1146976
    1147977    /* Copy s/g buf (virtual memory) to guest phys mem (IN direction). */
     
    11731003    /* If this write-ahead crosses threshold where the driver wants to get an event flag it */
    11741004    if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX)
    1175         if (pVirtqState->uUsedIdxShadow == virtioReadAvailUsedEvent(pDevIns, pVirtio, idxVirtq))
     1005        if (pVirtqState->uUsedIdxShadow == virtioReadAvailUsedEvent(pDevIns, pVirtio, uVirtqNbr))
    11761006            pVirtqState->fVirtqRingEventThreshold = true;
    11771007
     
    11791009     * Place used buffer's descriptor in used ring but don't update used ring's slot index.
    11801010     * That will be done with a subsequent client call to virtioCoreVirtqSync() */
    1181     virtioWriteUsedElem(pDevIns, pVirtio, idxVirtq, pVirtqState->uUsedIdxShadow++, pDescChain->uHeadIdx, (uint32_t)cbTotal);
     1011    virtioWriteUsedElem(pDevIns, pVirtio, uVirtqNbr, pVirtqState->uUsedIdxShadow++, pVirtqBuf->uHeadIdx, (uint32_t)cbTotal);
    11821012
    11831013    if (pSgVirtReturn)
    11841014        Log6Func((".... Copied %zu bytes in %d segs to %u byte buffer, residual=%zu\n",
    1185                   cbTotal - cbRemain, pSgVirtReturn->cSegs, pDescChain->cbPhysReturn, pDescChain->cbPhysReturn - cbTotal));
     1015                  cbTotal - cbRemain, pSgVirtReturn->cSegs, pVirtqBuf->cbPhysReturn, pVirtqBuf->cbPhysReturn - cbTotal));
    11861016
    11871017    Log6Func(("Write ahead used_idx=%u, %s used_idx=%u\n",
    1188               pVirtqState->uUsedIdxShadow, VIRTQNAME(pVirtio, idxVirtq), virtioReadUsedRingIdx(pDevIns, pVirtio, idxVirtq)));
     1018              pVirtqState->uUsedIdxShadow, VIRTQNAME(pVirtio, uVirtqNbr), virtioReadUsedRingIdx(pDevIns, pVirtio, uVirtqNbr)));
    11891019
    11901020    return VINF_SUCCESS;
     
    11931023#endif /* IN_RING3 */
    11941024
     1025/** API function: See Header file  */
     1026int virtioCoreVirtqSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
     1027{
     1028    Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState));
     1029    PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];
     1030
     1031    AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtio->uVirtqEnable[uVirtqNbr],
     1032                    ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
     1033
     1034    Log6Func(("Updating %s used_idx to %u\n",
     1035              VIRTQNAME(pVirtio, uVirtqNbr), pVirtqState->uUsedIdxShadow));
     1036
     1037    virtioWriteUsedRingIdx(pDevIns, pVirtio, uVirtqNbr, pVirtqState->uUsedIdxShadow);
     1038    virtioCoreNotifyGuestDriver(pDevIns, pVirtio, uVirtqNbr);
     1039
     1040    return VINF_SUCCESS;
     1041}
     1042
     1043
    11951044/**
    1196  * Updates the indicated virtq's "used ring" descriptor index to match the
    1197  * current write-head index, thus exposing the data added to the used ring by all
    1198  * virtioCoreR3VirtqPut() calls since the last sync. This should be called after one or
    1199  * more virtioCoreR3VirtqPut() calls to inform the guest driver there is data in the queue.
    1200  * Explicit notifications (e.g. interrupt or MSI-X) will be sent to the guest,
    1201  * depending on VirtIO features negotiated and conditions, otherwise the guest
    1202  * will detect the update by polling. (see VirtIO 1.0 specification, Section 2.4 "Virtqueues").
    1203  *
    1204  * @param   pDevIns     The device instance.
    1205  * @param   pVirtio     Pointer to the shared virtio state.
    1206  * @param   idxVirtq    Virtq number
    1207  *
    1208  * @returns VBox status code.
    1209  * @retval  VINF_SUCCESS       Success
    1210  * @retval  VERR_INVALID_STATE VirtIO not in ready state
    1211  */
    1212 int virtioCoreVirtqSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)
    1213 {
    1214     Assert(idxVirtq < RT_ELEMENTS(pVirtio->aVirtqState));
    1215     PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq];
    1216 
    1217     AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtio->uVirtqEnable[idxVirtq],
    1218                     ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
    1219 
    1220     Log6Func(("Updating %s used_idx to %u\n",
    1221               VIRTQNAME(pVirtio, idxVirtq), pVirtqState->uUsedIdxShadow));
    1222 
    1223     virtioWriteUsedRingIdx(pDevIns, pVirtio, idxVirtq, pVirtqState->uUsedIdxShadow);
    1224     virtioCoreNotifyGuestDriver(pDevIns, pVirtio, idxVirtq);
    1225 
    1226     return VINF_SUCCESS;
    1227 }
    1228 
    1229 
    1230 /**
    1231  */
    1232 static void virtioCoreVirtqNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, uint16_t uNotifyIdx)
     1045 */
     1046static void virtioCoreVirtqNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint16_t uNotifyIdx)
    12331047{
    12341048
    12351049    PVIRTIOCORECC pVirtioCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOCORECC);
    12361050
    1237     /* See VirtIO 1.0, section 4.1.5.2 It implies that idxVirtq and uNotifyIdx should match.
     1051    /* See VirtIO 1.0, section 4.1.5.2 It implies that uVirtqNbr and uNotifyIdx should match.
    12381052     * Disregarding this notification may cause throughput to stop, however there's no way to know
    12391053     * which was queue was intended for wake-up if the two parameters disagree. */
    12401054
    1241     AssertMsg(uNotifyIdx == idxVirtq,
     1055    AssertMsg(uNotifyIdx == uVirtqNbr,
    12421056                    ("Guest kicked virtq %d's notify addr w/non-corresponding virtq idx %d\n",
    1243                      idxVirtq, uNotifyIdx));
     1057                     uVirtqNbr, uNotifyIdx));
    12441058    RT_NOREF(uNotifyIdx);
    12451059
    1246     AssertReturnVoid(idxVirtq < RT_ELEMENTS(pVirtio->aVirtqState));
     1060    AssertReturnVoid(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState));
    12471061    Log6Func(("%s (desc chains: %u)\n",
    1248         pVirtio->aVirtqState[idxVirtq].szVirtqName,
    1249         virtioCoreVirtqAvailCount(pDevIns, pVirtio, idxVirtq)));
     1062        pVirtio->aVirtqState[uVirtqNbr].szVirtqName,
     1063        virtioCoreVirtqAvailCount(pDevIns, pVirtio, uVirtqNbr)));
    12501064
    12511065    /* Inform client */
    1252     pVirtioCC->pfnVirtqNotified(pDevIns, pVirtio, idxVirtq);
     1066    pVirtioCC->pfnVirtqNotified(pDevIns, pVirtio, uVirtqNbr);
    12531067}
    12541068
     
    12621076 * @param   pDevIns     The device instance.
    12631077 * @param   pVirtio     Pointer to the shared virtio state.
    1264  * @param   idxVirtq    Virtq to check for guest interrupt handling preference
    1265  */
    1266 static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)
    1267 {
    1268 
    1269     Assert(idxVirtq < RT_ELEMENTS(pVirtio->aVirtqState));
    1270     PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq];
     1078 * @param   uVirtqNbr    Virtq to check for guest interrupt handling preference
     1079 */
     1080static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
     1081{
     1082
     1083    Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState));
     1084    PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];
    12711085
    12721086    if (!IS_DRIVER_OK(pVirtio))
     
    12821096#ifdef IN_RING3
    12831097            Log6Func(("...kicking guest %s, VIRTIO_F_EVENT_IDX set and threshold (%d) reached\n",
    1284                    VIRTQNAME(pVirtio, idxVirtq), (uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxVirtq)));
     1098                   VIRTQNAME(pVirtio, uVirtqNbr), (uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, uVirtqNbr)));
    12851099#endif
    1286             virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uVirtqMsixVector[idxVirtq]);
     1100            virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uVirtqMsixVector[uVirtqNbr]);
    12871101            pVirtqState->fVirtqRingEventThreshold = false;
    12881102            return;
     
    12901104#ifdef IN_RING3
    12911105        Log6Func(("...skip interrupt %s, VIRTIO_F_EVENT_IDX set but threshold (%d) not reached (%d)\n",
    1292                    VIRTQNAME(pVirtio, idxVirtq),(uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxVirtq), pVirtqState->uUsedIdxShadow));
     1106                   VIRTQNAME(pVirtio, uVirtqNbr),(uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, uVirtqNbr), pVirtqState->uUsedIdxShadow));
    12931107#endif
    12941108    }
     
    12961110    {
    12971111        /** If guest driver hasn't suppressed interrupts, interrupt  */
    1298         if (!(virtioReadAvailRingFlags(pDevIns, pVirtio, idxVirtq) & VIRTQ_AVAIL_F_NO_INTERRUPT))
    1299         {
    1300             virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uVirtqMsixVector[idxVirtq]);
     1112        if (!(virtioReadAvailRingFlags(pDevIns, pVirtio, uVirtqNbr) & VIRTQ_AVAIL_F_NO_INTERRUPT))
     1113        {
     1114            virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uVirtqMsixVector[uVirtqNbr]);
    13011115            return;
    13021116        }
    13031117        Log6Func(("...skipping interrupt for %s (guest set VIRTQ_AVAIL_F_NO_INTERRUPT)\n",
    1304                      VIRTQNAME(pVirtio, idxVirtq)));
     1118                     VIRTQNAME(pVirtio, uVirtqNbr)));
    13051119    }
    13061120}
     
    13471161
    13481162#ifdef IN_RING3
    1349 static void virtioResetVirtq(PVIRTIOCORE pVirtio, uint16_t idxVirtq)
    1350 {
    1351     Assert(idxVirtq < RT_ELEMENTS(pVirtio->aVirtqState));
    1352     PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq];
     1163static void virtioResetVirtq(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
     1164{
     1165    Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState));
     1166    PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];
    13531167    pVirtqState->uAvailIdxShadow = 0;
    13541168    pVirtqState->uUsedIdxShadow  = 0;
    13551169    pVirtqState->fVirtqRingEventThreshold = false;
    1356     pVirtio->uVirtqEnable[idxVirtq] = false;
    1357     pVirtio->uVirtqSize[idxVirtq] = VIRTQ_MAX_ENTRIES;
    1358     pVirtio->uVirtqNotifyOff[idxVirtq] = idxVirtq;
    1359     pVirtio->uVirtqMsixVector[idxVirtq] = idxVirtq + 2;
     1170    pVirtio->uVirtqEnable[uVirtqNbr] = false;
     1171    pVirtio->uVirtqSize[uVirtqNbr] = VIRTQ_MAX_ENTRIES;
     1172    pVirtio->uVirtqNotifyOff[uVirtqNbr] = uVirtqNbr;
     1173    pVirtio->uVirtqMsixVector[uVirtqNbr] = uVirtqNbr + 2;
    13601174    if (!pVirtio->fMsiSupport) /* VirtIO 1.0, 4.1.4.3 and 4.1.5.1.2 */
    1361         pVirtio->uVirtqMsixVector[idxVirtq] = VIRTIO_MSI_NO_VECTOR;
    1362 
    1363     virtioLowerInterrupt(pVirtio->pDevInsR3, pVirtio->uVirtqMsixVector[idxVirtq]);
     1175        pVirtio->uVirtqMsixVector[uVirtqNbr] = VIRTIO_MSI_NO_VECTOR;
     1176
     1177    virtioLowerInterrupt(pVirtio->pDevInsR3, pVirtio->uVirtqMsixVector[uVirtqNbr]);
    13641178}
    13651179
     
    13881202        pVirtio->uMsixConfig = VIRTIO_MSI_NO_VECTOR;
    13891203
    1390     for (uint16_t idxVirtq = 0; idxVirtq < VIRTQ_MAX_CNT; idxVirtq++)
    1391         virtioResetVirtq(pVirtio, idxVirtq);
     1204    for (uint16_t uVirtqNbr = 0; uVirtqNbr < VIRTQ_MAX_CNT; uVirtqNbr++)
     1205        virtioResetVirtq(pVirtio, uVirtqNbr);
    13921206}
    13931207
     
    20261840            break;
    20271841        case kvirtIoVmStateChangedResume:
    2028             virtioCoreNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, 0 /* idxVirtq */);
     1842            virtioCoreNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, 0 /* uVirtqNbr */);
    20291843            break;
    20301844        default:
  • trunk/src/VBox/Devices/VirtIO/VirtioCore.h

    r84818 r84819  
    11/* $Id$ */
     2
    23/** @file
    3  * Virtio_1_0.h - Virtio Declarations
     4 * VirtioCore.h - Virtio Declarations
    45 */
    56
     
    9394
    9495/**
    95  * Virtio descriptor chain representation.
    96  */
    97 typedef struct VIRTIO_DESC_CHAIN
    98 {
    99     uint32_t            u32Magic;                                   /**< Magic value, VIRTIO_DESC_CHAIN_MAGIC.    */
     96 * VirtIO buffers are actually descriptor chains. VirtIO's scatter-gather architecture
     97 * defines a head descriptor (index into ring of descriptors), which is chained to 0 or more
     98 * other descriptors that can optionally continue the chain.  This structure is VirtualBox's
     99 * Virtq buffer representation, which contains a reference to the head desc chain idx and
     100 * context for working with virtq buffers.
     101 */
     102typedef struct VIRTQBUF
     103{
     104    uint32_t            u32Magic;                                   /**< Magic value, VIRTQBUF_MAGIC.    */
    100105    uint32_t volatile   cRefs;                                      /**< Reference counter. */
    101106    uint32_t            uHeadIdx;                                   /**< Head idx of associated desc chain        */
     
    112117    VIRTIOSGSEG         aSegsOut[VIRTQ_MAX_ENTRIES];
    113118    /** @} */
    114 } VIRTIO_DESC_CHAIN_T;
    115 /** Pointer to a Virtio descriptor chain. */
    116 typedef VIRTIO_DESC_CHAIN_T *PVIRTIO_DESC_CHAIN_T;
    117 /** Pointer to a Virtio descriptor chain pointer. */
    118 typedef VIRTIO_DESC_CHAIN_T **PPVIRTIO_DESC_CHAIN_T;
    119 /** Magic value for VIRTIO_DESC_CHAIN_T::u32Magic. */
    120 #define VIRTIO_DESC_CHAIN_MAGIC             UINT32_C(0x19600219)
     119} VIRTQBUF_T;
     120
     121/** Pointers to a Virtio descriptor chain. */
     122typedef VIRTQBUF_T *PVIRTQBUF, **PPVIRTQBUF;
     123/** Magic value for VIRTQBUF_T::u32Magic. */
     124#define VIRTQBUF_MAGIC             UINT32_C(0x19600219)
    121125
    122126typedef struct VIRTIOPCIPARAMS
     
    187191typedef struct VIRTQSTATE
    188192{
    189     uint16_t  idxVirtq;                                          /**< Index of this queue                       */
     193    uint16_t  uVirtqNbr;                                          /**< Index of this queue                       */
    190194    char      szVirtqName[32];                                   /**< Dev-specific name of queue                */
    191195    uint16_t  uAvailIdxShadow;                                   /**< Consumer's position in avail ring         */
     
    348352     * @param   pVirtio    Pointer to the shared virtio state.
    349353     * @param   pVirtioCC  Pointer to the ring-3 virtio state.
    350      * @param   idxVirtq   Index of the notified queue
     354     * @param   uVirtqNbr   Index of the notified queue
    351355     */
    352     DECLCALLBACKMEMBER(void, pfnVirtqNotified)(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq);
     356    DECLCALLBACKMEMBER(void, pfnVirtqNotified)(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr);
    353357
    354358    /** @} */
     
    381385     * @param   pVirtio    Pointer to the shared virtio state.
    382386     * @param   pVirtioCC  Pointer to the ring-3 virtio state.
    383      * @param   idxVirtq   Index of the notified queue
     387     * @param   uVirtqNbr   Index of the notified queue
    384388     */
    385     DECLCALLBACKMEMBER(void, pfnVirtqNotified)(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq);
     389    DECLCALLBACKMEMBER(void, pfnVirtqNotified)(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr);
    386390
    387391} VIRTIOCORER0;
     
    405409 * @{ */
    406410
    407 int      virtioCoreVirtqSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq);
    408 uint16_t virtioCoreVirtqAvailCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq);
    409 void     virtioCoreVirtqEnable(PVIRTIOCORE pVirtio, uint16_t idxVirtq, bool fEnable);
    410 void     virtioCoreVirtqNotifyEnable(PVIRTIOCORE pVirtio, uint16_t idxVirtq, bool fEnable);
     411
     412/**
     413 * Initiate orderly reset procedure. This is an exposed API for clients that might need it.
     414 * Invoked by client to reset the device and driver (see VirtIO 1.0 section 2.1.1/2.1.2)
     415 *
     416 * @param   pVirtio     Pointer to the virtio state.
     417 */
     418void     virtioCoreResetAll(PVIRTIOCORE pVirtio);
     419
     420/**
     421 * 'Attaches' the inheriting device-specific code's queue state to the VirtIO core
     422 * queue management, informing the core of the name of the queue and number. The VirtIO core
     423 * allocates the queue state information so it can handle all the core VirtiIO queue operations
     424 * and dispatch callbacks, etc...
     425 *
     426 * @param   pVirtio     Pointer to the shared virtio state.
     427 * @param   uVirtqNbr    Virtq number
     428 * @param   pcszName    Name to give queue
     429 *
     430 * @returns VBox status code.
     431 */
     432int      virtioCoreR3VirtqAttach(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, const char *pcszName);
     433
     434/**
     435 * Enables or disables a virtq
     436 *
     437 * @param   pVirtio     Pointer to the shared virtio state.
     438 * @param   uVirtqNbr   Virtq number
     439 * @param   fEnable     Flags whether to enable or disable the virtq
     440 *
     441 */
     442
     443void     virtioCoreVirtqEnable(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, bool fEnable);
     444
     445/**
     446 * Enable or Disable notification for the specified queue
     447 *
     448 * @param   pVirtio     Pointer to the shared virtio state.
     449 * @param   uVirtqNbr    Virtq number
     450 * @param   fEnable    Selects notification mode (enabled or disabled)
     451 */
     452void     virtioCoreVirtqEnableNotify(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, bool fEnable);
     453
     454/*
     455 * Notifies guest (via ISR or MSI-X) of device configuration change
     456 *
     457 * @param   pVirtio     Pointer to the shared virtio state.
     458 */
    411459void     virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio);
    412 void     virtioCoreResetAll(PVIRTIOCORE pVirtio);
     460
     461/*
     462 * Displays the VirtIO spec-related features offered by the core component,
     463 * as well as which features have been negotiated and accepted or declined by the guest driver,
     464 * providing a summary view of the configuration the device is operating with.
     465 *
     466 * @param   pVirtio     Pointer to the shared virtio state.
     467 * @param   pHlp        Pointer to the debug info hlp struct
     468 */
    413469void     virtioCorePrintFeatures(VIRTIOCORE *pVirtio, PCDBGFINFOHLP pHlp);
    414470
    415 uint32_t virtioCoreR3DescChainRetain(PVIRTIO_DESC_CHAIN_T pDescChain);
    416 uint32_t virtioCoreR3DescChainRelease(PVIRTIOCORE pVirtio, PVIRTIO_DESC_CHAIN_T pDescChain);
    417 void     virtioCoreR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs);
    418 void     virtioCoreR3VirtqInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs, int idxVirtq);
    419 int      virtioCoreR3VirtqAttach(PVIRTIOCORE pVirtio, uint16_t idxVirtq, const char *pcszName);
    420 
    421 int      virtioCoreR3DescChainGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq,
    422                                   uint16_t uHeadIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain);
    423 
    424 int      virtioCoreR3VirtqPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq,
    425                                PPVIRTIO_DESC_CHAIN_T ppDescChain);
    426 
    427 int      virtioCoreR3VirtqSkip(PVIRTIOCORE pVirtio, uint16_t idxVirtq);
    428 
    429 int      virtioCoreR3VirtqGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq,
    430                               PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove);
    431 
    432 int      virtioCoreR3VirtqPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, PRTSGBUF pSgVirtReturn,
    433                               PVIRTIO_DESC_CHAIN_T pDescChain, bool fFence);
    434 
     471/*
     472 * Debuging assist feature displays the state of the VirtIO core code, which includes
     473 * an overview of the state of all of the queues.
     474 *
     475 * This can be invoked when running the VirtualBox debugger, or from the command line
     476 * using the command: "VboxManage debugvm <VM name or id> info <device name> [args]"
     477 *
     478 * Example:  VBoxManage debugvm myVnetVm info "virtio-net" all
     479 *
     480 * This is implemented currently to be invoked by the inheriting device-specific code
     481 * (see DevVirtioNet for an example, which receives the debugvm command directly).
     482 * That devices lists the available sub-options if no arguments are provided. In that
     483 * example this virtq info related function is invoked hierarchically when virtio-net
     484 * displays its device-specific queue info.
     485 *
     486 * @param   pDevIns     The device instance.
     487 * @param   pHlp        Pointer to the debug info hlp struct
     488 * @param   pszArgs     Arguments to function
     489 */
     490void     virtioCoreR3VirtqInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs, int uVirtqNbr);
     491
     492/*
     493 * Returns the number of avail bufs in the virtq.
     494 *
     495 * @param   pDevIns     The device instance.
     496 * @param   pVirtio     Pointer to the shared virtio state.
     497 * @param   uVirtqNbr   Virtqueue to return the count of buffers available for.
     498 */
     499uint16_t virtioCoreVirtqAvailCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr);
     500
     501/**
     502 * Fetches descriptor chain using avail ring of indicated queue and converts the descriptor
     503 * chain into its OUT (to device) and IN to guest components, but does NOT remove it from
     504 * the 'avail' queue. I.e. doesn't advance the index.  This can be used with virtioVirtqSkip(),
     505 * which *does* advance the avail index. Together they facilitate a mechanism that allows
     506 * work with a queue element (descriptor chain) to be aborted if necessary, by not advancing
     507 * the pointer, or, upon success calling the skip function (above) to move to the next element.
     508 *
     509 * Additionally it converts the OUT desc chain data to a contiguous virtual
     510 * memory buffer for easy consumption by the caller. The caller must return the
     511 * descriptor chain pointer via virtioCoreR3VirtqBufPut() and then call virtioCoreVirtqSync()
     512 * at some point to return the data to the guest and complete the transaction.
     513 *
     514 * @param   pDevIns     The device instance.
     515 * @param   pVirtio     Pointer to the shared virtio state.
     516 * @param   uVirtqNbr   Virtq number
     517 * @param   ppVirtqBuf Address to store pointer to descriptor chain that contains the
     518 *                      pre-processed transaction information pulled from the virtq.
     519 *
     520 * @returns VBox status code:
     521 * @retval  VINF_SUCCESS         Success
     522 * @retval  VERR_INVALID_STATE   VirtIO not in ready state (asserted).
     523 * @retval  VERR_NOT_AVAILABLE   If the queue is empty.
     524 */
     525int      virtioCoreR3VirtqBufPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
     526                                  PPVIRTQBUF ppVirtqBuf);
     527
     528/**
     529 * Fetches the next descriptor chain using avail ring of indicated queue and converts the descriptor
     530 * chain into its OUT (to device) and IN to guest components.
     531 *
     532 * Additionally it converts the OUT desc chain data to a contiguous virtual
     533 * memory buffer for easy consumption by the caller. The caller must return the
     534 * descriptor chain pointer via virtioCoreR3VirtqBufPut() and then call virtioCoreVirtqSync()
     535 * at some point to return the data to the guest and complete the transaction.
     536 *
     537 * @param   pDevIns     The device instance.
     538 * @param   pVirtio     Pointer to the shared virtio state.
     539 * @param   uVirtqNbr    Virtq number
     540 * @param   ppVirtqBuf Address to store pointer to descriptor chain that contains the
     541 *                      pre-processed transaction information pulled from the virtq.
     542 *                      Returned reference must be released by calling
     543 *                      virtioCoreR3VirtqBufRelease().
     544 * @param   fRemove     flags whether to remove desc chain from queue (false = peek)
     545 *
     546 * @returns VBox status code:
     547 * @retval  VINF_SUCCESS         Success
     548 * @retval  VERR_INVALID_STATE   VirtIO not in ready state (asserted).
     549 * @retval  VERR_NOT_AVAILABLE   If the queue is empty.
     550 */
     551int      virtioCoreR3VirtqBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
     552                                 PPVIRTQBUF ppVirtqBuf, bool fRemove);
     553
     554
     555/**
     556 * Fetches a specific descriptor chain using avail ring of indicated queue and converts the descriptor
     557 * chain into its OUT (to device) and IN to guest components.
     558 *
     559 * Additionally it converts the OUT desc chain data to a contiguous virtual
     560 * memory buffer for easy consumption by the caller. The caller must return the
     561 * descriptor chain pointer via virtioCoreR3VirtqBufPut() and then call virtioCoreVirtqSync()
     562 * at some point to return the data to the guest and complete the transaction.
     563 *
     564 * @param   pDevIns     The device instance.
     565 * @param   pVirtio     Pointer to the shared virtio state.
     566 * @param   uVirtqNbr    Virtq number
     567 * @param   ppVirtqBuf Address to store pointer to descriptor chain that contains the
     568 *                      pre-processed transaction information pulled from the virtq.
     569 *                      Returned reference must be released by calling
     570 *                      virtioCoreR3VirtqBufRelease().
     571 * @param   fRemove     flags whether to remove desc chain from queue (false = peek)
     572 *
     573 * @returns VBox status code:
     574 * @retval  VINF_SUCCESS         Success
     575 * @retval  VERR_INVALID_STATE   VirtIO not in ready state (asserted).
     576 * @retval  VERR_NOT_AVAILABLE   If the queue is empty.
     577 */
     578
     579int      virtioCoreR3VirtqBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
     580                                  uint16_t uHeadIdx, PPVIRTQBUF ppVirtqBuf);
     581
     582/**
     583 * Returns data to the guest to complete a transaction initiated by virtVirtqGet().
     584 *
     585 * The caller passes in a pointer to a scatter-gather buffer of virtual memory segments
     586 * and a pointer to the descriptor chain context originally derived from the pulled
     587 * queue entry, and this function will write the virtual memory s/g buffer into the
     588 * guest's physical memory free the descriptor chain. The caller handles the freeing
     589 * (as needed) of the virtual memory buffer.
     590 *
     591 * @note This does a write-ahead to the used ring of the guest's queue. The data
     592 *       written won't be seen by the guest until the next call to virtioCoreVirtqSync()
     593 *
     594 *
     595 * @param   pDevIns         The device instance (for reading).
     596 * @param   pVirtio         Pointer to the shared virtio state.
     597 * @param   uVirtqNbr        Virtq number
     598 *
     599 * @param   pSgVirtReturn   Points to scatter-gather buffer of virtual memory
     600 *                          segments the caller is returning to the guest.
     601 *
     602 * @param   pVirtqBuf      This contains the context of the scatter-gather
     603 *                          buffer originally pulled from the queue.
     604 *
     605 * @param   fFence          If true, put up copy fence (memory barrier) after
     606 *                          copying to guest phys. mem.
     607 *
     608 * @returns VBox status code.
     609 * @retval  VINF_SUCCESS       Success
     610 * @retval  VERR_INVALID_STATE VirtIO not in ready state
     611 * @retval  VERR_NOT_AVAILABLE Virtq is empty
     612 *
     613 * @note    This function will not release any reference to pVirtqBuf.  The
     614 *          caller must take care of that.
     615 */
     616
     617int      virtioCoreR3VirtqBufPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, PRTSGBUF pSgVirtReturn,
     618                                 PVIRTQBUF pVirtqBuf, bool fFence);
     619
     620/**
     621 * Skip the next entry in the specified queue (typically used with virtioCoreR3VirtqBufPeek())
     622 *
     623 * @param   pVirtio     Pointer to the virtio state.
     624 * @param   uVirtqNbr    Index of queue
     625 */
     626int      virtioCoreR3VirtqBufSkip(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr);
     627
     628/**
     629 * Updates the indicated virtq's "used ring" descriptor index to match the
     630 * current write-head index, thus exposing the data added to the used ring by all
     631 * virtioCoreR3VirtqBufPut() calls since the last sync. This should be called after one or
     632 * more virtioCoreR3VirtqBufPut() calls to inform the guest driver there is data in the queue.
     633 * Explicit notifications (e.g. interrupt or MSI-X) will be sent to the guest,
     634 * depending on VirtIO features negotiated and conditions, otherwise the guest
     635 * will detect the update by polling. (see VirtIO 1.0 specification, Section 2.4 "Virtqueues").
     636 *
     637 * @param   pDevIns     The device instance.
     638 * @param   pVirtio     Pointer to the shared virtio state.
     639 * @param   uVirtqNbr   Virtq number
     640 *
     641 * @returns VBox status code.
     642 * @retval  VINF_SUCCESS       Success
     643 * @retval  VERR_INVALID_STATE VirtIO not in ready state
     644 */
     645int      virtioCoreVirtqSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr);
     646
     647/**
     648 * Retains a reference to the given descriptor chain.
     649 *
     650 * @returns New reference count.
     651 * @retval  UINT32_MAX on invalid parameter.
     652 * @param   pVirtqBuf      The descriptor chain to reference.
     653 */
     654uint32_t virtioCoreR3VirtqBufRetain(PVIRTQBUF pVirtqBuf);
     655
     656/**
     657 * Releases a reference to the given descriptor chain.
     658 *
     659 * @returns New reference count.
     660 * @retval  0 if freed or invalid parameter.
     661 * @param   pVirtio         Pointer to the shared virtio state.
     662 * @param   pVirtqBuf       The descriptor chain to reference.  NULL is quietly
     663 *                          ignored (returns 0).
     664 */
     665uint32_t virtioCoreR3VirtqBufRelease(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf);
    435666
    436667/**
     
    438669 *
    439670 * @param   pVirtio     Pointer to the virtio state.
    440  * @param   idxVirtq    Virtq number.
    441  * @returns   true or false indicating whether to enable queue or not
    442  */
    443 DECLINLINE(bool) virtioCoreIsVirtqEnabled(PVIRTIOCORE pVirtio, uint16_t idxVirtq)
    444 {
    445     Assert(idxVirtq < RT_ELEMENTS(pVirtio->aVirtqState));
    446     return pVirtio->uVirtqEnable[idxVirtq] != 0;
     671 * @param   uVirtqNbr    Virtq number.
     672 * @returns true or false indicating whether to enable queue or not
     673 */
     674DECLINLINE(bool) virtioCoreIsVirtqEnabled(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
     675{
     676    Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState));
     677    return pVirtio->uVirtqEnable[uVirtqNbr] != 0;
    447678}
    448679
    449680/**
    450  * Get name of queue, by idxVirtq, assigned at virtioCoreR3VirtqAttach()
     681 * Get name of queue, by uVirtqNbr, assigned at virtioCoreR3VirtqAttach()
    451682 *
    452683 * @param   pVirtio     Pointer to the virtio state.
    453  * @param   idxVirtq    Virtq number.
     684 * @param   uVirtqNbr    Virtq number.
    454685 *
    455686 * @returns Pointer to read-only queue name.
    456687 */
    457 DECLINLINE(const char *) virtioCoreVirtqGetName(PVIRTIOCORE pVirtio, uint16_t idxVirtq)
    458 {
    459     Assert((size_t)idxVirtq < RT_ELEMENTS(pVirtio->aVirtqState));
    460     return pVirtio->aVirtqState[idxVirtq].szVirtqName;
     688DECLINLINE(const char *) virtioCoreVirtqGetName(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)
     689{
     690    Assert((size_t)uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState));
     691    return pVirtio->aVirtqState[uVirtqNbr].szVirtqName;
    461692}
    462693
     
    470701    return pVirtio->uDriverFeatures;
    471702}
    472 
    473703
    474704/**
     
    486716}
    487717
    488 void virtioCoreLogMappedIoValue(const char *pszFunc, const char *pszMember, uint32_t uMemberSize,
     718/**
     719 * Log memory-mapped I/O input or output value.
     720 *
     721 * This is to be invoked by macros that assume they are invoked in functions with
     722 * the relevant arguments. (See Virtio_1_0.cpp).
     723 *
     724 * It is exposed via the API so inheriting device-specific clients can provide similar
     725 * logging capabilities for a consistent look-and-feel.
     726 *
     727 * @param   pszFunc     To avoid displaying this function's name via __FUNCTION__ or LogFunc()
     728 * @param   pszMember   Name of struct member
     729 * @param   pv          pointer to value
     730 * @param   cb          size of value
     731 * @param   uOffset     offset into member where value starts
     732 * @param   fWrite      True if write I/O
     733 * @param   fHasIndex   True if the member is indexed
     734 * @param   idx         The index if fHasIndex
     735 */
     736const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState);void virtioCoreLogMappedIoValue(const char *pszFunc, const char *pszMember, uint32_t uMemberSize,
    489737                                const void *pv, uint32_t cb, uint32_t uOffset,
    490738                                int fWrite, int fHasIndex, uint32_t idx);
    491739
    492 /* Debug assist functions for consumer device code */
     740/**
     741 * Debug assist for any consumer device code that inherits VIRTIOCORE
     742 *
     743 * Does a formatted hex dump using Log(()), recommend using VIRTIO_HEX_DUMP() macro to
     744 * control enabling of logging efficiently.
     745 *
     746 * @param   pv          pointer to buffer to dump contents of
     747 * @param   cb          count of characters to dump from buffer
     748 * @param   uBase       base address of per-row address prefixing of hex output
     749 * @param   pszTitle    Optional title. If present displays title that lists
     750 *                      provided text with value of cb to indicate size next to it.
     751 */
    493752void virtioCoreHexDump(uint8_t *pv, uint32_t cb, uint32_t uBase, const char *pszTitle);
     753
     754/**
     755 * Debug assist for any consumer device code that inherits VIRTIOCORE
     756&
     757 * Do a hex dump of memory in guest physical context
     758 *
     759 * @param   GCPhys      pointer to buffer to dump contents of
     760 * @param   cb          count of characters to dump from buffer
     761 * @param   uBase       base address of per-row address prefixing of hex output
     762 * @param   pszTitle    Optional title. If present displays title that lists
     763 *                      provided text with value of cb to indicate size next to it.
     764 */
    494765void virtioCoreGCPhysHexDump(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint16_t cb, uint32_t uBase, const char *pszTitle);
    495766
    496 
     767/** The following virtioCoreSgBuf*() functions mimic the functionality of the related RT s/g functions,
     768 *  except they work with the data type GCPhys rather than void *
     769 */
    497770void     virtioCoreSgBufInit(PVIRTIOSGBUF pGcSgBuf, PVIRTIOSGSEG paSegs, size_t cSegs);
    498771void     virtioCoreSgBufReset(PVIRTIOSGBUF pGcSgBuf);
     
    504777size_t   virtioCoreSgBufCalcTotalLength(PVIRTIOSGBUF pGcSgBuf);
    505778
     779/** Misc VM and PDM boilerplate */
    506780int      virtioCoreR3SaveExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM);
    507781int      virtioCoreR3LoadExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM);
     
    511785                      const char *pcszInstance, uint64_t fDevSpecificFeatures, void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg);
    512786int      virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio);
     787
     788
    513789const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState);
    514790
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