VirtualBox

Changeset 84774 in vbox for trunk


Ignore:
Timestamp:
Jun 11, 2020 6:01:00 AM (4 years ago)
Author:
vboxsync
Message:

Network/DevVirtioNet_1_0.cpp: Fixed controlq hang, reduced use of indexes to refer to queues in DevVirtioNet_1_0.cpp for a cleaner implemention. Streamlined and improved debug logging. Added DbgHelp functions, removed the virtq empty check API and implemented it as a macro based on counting queue entries instead..

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

Legend:

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

    r84468 r84774  
    5959#include "VBoxDD.h"
    6060
    61 /* After debugging single instance case, restore instance name logging */
    62 #define INSTANCE(pState) (char *)(pState->szInstanceName ? pState->szInstanceName : "") // Avoid requiring RT_NOREF in some funcs
    63 
    6461#define VIRTIONET_SAVED_STATE_VERSION          UINT32_C(1)
    6562#define VIRTIONET_MAX_QPAIRS                   1
     
    7067#define VIRTIONET_PREALLOCATE_RX_SEG_COUNT     32
    7168
    72 #define VIRTQNAME(idxQueue)       (pThis->aszVirtqNames[idxQueue])
     69#define VIRTQNAME(idxQueue)       (pThis->aQueues[idxQueue]->szName)
    7370#define CBVIRTQNAME(idxQueue)     RTStrNLen(VIRTQNAME(idxQueue), sizeof(VIRTQNAME(idxQueue)))
    7471#define FEATURE_ENABLED(feature)  RT_BOOL(pThis->fNegotiatedFeatures & VIRTIONET_F_##feature)
    7572#define FEATURE_DISABLED(feature) (!FEATURE_ENABLED(feature))
    7673#define FEATURE_OFFERED(feature)  VIRTIONET_HOST_FEATURES_OFFERED & VIRTIONET_F_##feature
     74
     75#define IS_VIRTQ_EMPTY(pDevIns, pVirtio, idxQueue) \
     76            (virtioCoreQueueAvailCount(pDevIns, pVirtio, idxQueue) == 0)
    7777
    7878#define SET_LINK_UP(pState) \
     
    301301
    302302/**
     303 * device-specific queue info
     304 */
     305struct VIRTIONETWORKER;
     306struct VIRTIONETWORKERR3;
     307
     308typedef struct VIRTIONETQUEUE
     309{
     310    struct VIRTIONETWORKER         *pWorker;                    /**< Pointer to R0 worker struct                      */
     311    struct VIRTIONETWORKERR3       *pWorkerR3;                  /**< Pointer to R3 worker struct                      */
     312    uint16_t                       idx;                         /**< Index of this queue                              */
     313    uint16_t                       align;
     314    char                           szName[VIRTIO_MAX_QUEUE_NAME_SIZE]; /**< Queue name                                */
     315    bool                           fCtlQueue;                   /**< If set this queue is the control queue           */
     316    bool                           fHasWorker;                  /**< If set this queue has an associated worker       */
     317    bool                           fAttachedToVirtioCore;       /**< Set if queue attached to virtio core             */
     318    uint8_t                        pad;
     319} VIRTIONETQUEUE, *PVIRTIONETQUEUE;
     320
     321/**
    303322 * Worker thread context, shared state.
    304323 */
     
    306325{
    307326    SUPSEMEVENT                     hEvtProcess;                /**< handle of associated sleep/wake-up semaphore      */
     327    PVIRTIONETQUEUE                 pQueue;                     /**< pointer to queue                                  */
     328    uint16_t                        idx;                        /**< Index of this worker                              */
    308329    bool volatile                   fSleeping;                  /**< Flags whether worker thread is sleeping or not    */
    309330    bool volatile                   fNotified;                  /**< Flags whether worker thread notified              */
     331    bool                            fAssigned;                  /**< Flags whether worker thread has been set up       */
     332    uint8_t                         pad;
    310333} VIRTIONETWORKER;
    311 /** Pointer to a VirtIO SCSI worker. */
     334/** Pointer to a virtio net worker. */
    312335typedef VIRTIONETWORKER *PVIRTIONETWORKER;
    313336
     
    318341{
    319342    R3PTRTYPE(PPDMTHREAD)           pThread;                    /**< pointer to worker thread's handle                 */
    320     uint16_t                        idxQueue;                   /**< Index of associated queue                         */
     343    PVIRTIONETQUEUE                 pQueue;                     /**< pointer to queue                                  */
     344    uint16_t                        idx;                        /**< Index of this worker                              */
     345    uint16_t                        pad;
    321346} VIRTIONETWORKERR3;
    322 /** Pointer to a VirtIO SCSI worker. */
     347/** Pointer to a virtio net worker. */
    323348typedef VIRTIONETWORKERR3 *PVIRTIONETWORKERR3;
    324349
     
    340365
    341366    /** Track which VirtIO queues we've attached to */
    342     bool                    afQueueAttached[VIRTIONET_MAX_QUEUES];
    343 
    344     /** Device-specific spec-based VirtIO VIRTQNAMEs */
    345     char                    aszVirtqNames[VIRTIONET_MAX_QUEUES][VIRTIO_MAX_QUEUE_NAME_SIZE];
    346 
    347     /** Instance name */
    348     char                    szInstanceName[16];
    349 
     367    VIRTIONETQUEUE          aQueues[VIRTIONET_MAX_QUEUES];
     368
     369    /** PDM device Instance name */
     370    char                    szInst[16];
     371
     372    /** VirtIO features negotiated with the guest, including generic core and device specific */
     373    uint64_t                fNegotiatedFeatures;
     374
     375    /** Number of Rx/Tx queue pairs (only one if MQ feature not negotiated */
    350376    uint16_t                cVirtqPairs;
    351377
     378    /** Number of virtqueues total (which includes each queue of each pair plus one control queue */
    352379    uint16_t                cVirtQueues;
    353380
     381    /** Number of worker threads (one for the control queue and one for each Tx queue) */
    354382    uint16_t                cWorkers;
    355383
    356     uint64_t                fNegotiatedFeatures;
    357 
    358     SUPSEMEVENT             hTxEvent;
     384    /** Alighnment */
     385    uint16_t                alignment;
    359386
    360387    /** Indicates transmission in progress -- only one thread is allowed. */
    361388    uint32_t                uIsTransmitting;
    362389
     390    /** virtio-net-1-dot-0 (in milliseconds). */
     391    uint32_t                cMsLinkUpDelay;
     392
     393    /** The number of actually used slots in aMacMulticastFilter. */
     394    uint32_t                cMulticastFilterMacs;
     395
     396    /** The number of actually used slots in aMacUniicastFilter. */
     397    uint32_t                cUnicastFilterMacs;
     398
     399    /** Semaphore leaf device's thread waits on until guest driver sends empty Rx bufs */
     400    SUPSEMEVENT             hEventRxDescAvail;
     401
     402    /** Array of MAC multicast addresses accepted by RX filter. */
     403    RTMAC                   aMacMulticastFilter[VIRTIONET_MAC_FILTER_LEN];
     404
     405    /** Array of MAC unicast addresses accepted by RX filter. */
     406    RTMAC                   aMacUnicastFilter[VIRTIONET_MAC_FILTER_LEN];
     407
     408    /** Default MAC address which rx filtering accepts */
     409    RTMAC                   rxFilterMacDefault;
     410
    363411    /** MAC address obtained from the configuration. */
    364412    RTMAC                   macConfigured;
    365413
    366     /** Default MAC address which rx filtering accepts */
    367     RTMAC                   rxFilterMacDefault;
     414    /** Bit array of VLAN filter, one bit per VLAN ID. */
     415    uint8_t                 aVlanFilter[VIRTIONET_MAX_VLAN_ID / sizeof(uint8_t)];
     416
     417    /** Set if PDM leaf device at the network interface is starved for Rx buffers */
     418    bool volatile           fLeafWantsEmptyRxBufs;
     419
     420    /** Number of packet being sent/received to show in debug log. */
     421    uint32_t                uPktNo;
     422
     423    /** Flags whether VirtIO core is in ready state */
     424    uint8_t                 fVirtioReady;
     425
     426    /** Resetting flag */
     427    uint8_t                 fResetting;
     428
     429    /** Quiescing I/O activity flag */
     430    uint8_t                 fQuiescing;
     431
     432    /** Promiscuous mode -- RX filter accepts all packets. */
     433    uint8_t                 fPromiscuous;
     434
     435    /** All multicast mode -- RX filter accepts all multicast packets. */
     436    uint8_t                 fAllMulticast;
     437
     438    /** All unicast mode -- RX filter accepts all unicast packets. */
     439    uint8_t                 fAllUnicast;
     440
     441    /** No multicast mode - Supresses multicast receive */
     442    uint8_t                 fNoMulticast;
     443
     444    /** No unicast mode - Suppresses unicast receive */
     445    uint8_t                 fNoUnicast;
     446
     447    /** No broadcast mode - Supresses broadcast receive */
     448    uint8_t                 fNoBroadcast;
    368449
    369450    /** True if physical cable is attached in configuration. */
    370451    bool                    fCableConnected;
    371 
    372     /** virtio-net-1-dot-0 (in milliseconds). */
    373     uint32_t                cMsLinkUpDelay;
    374 
    375     uint32_t                alignment;
    376 
    377     /** Number of packet being sent/received to show in debug log. */
    378     uint32_t                uPktNo;
    379 
    380     /** N/A: */
    381     bool volatile           fLeafWantsRxBuffers;
    382 
    383     SUPSEMEVENT             hEventRxDescAvail;
    384 
    385     /** Flags whether VirtIO core is in ready state */
    386     uint8_t                 fVirtioReady;
    387 
    388     /** Resetting flag */
    389     uint8_t                 fResetting;
    390 
    391     /** Quiescing I/O activity flag */
    392     uint8_t                 fQuiescing;
    393 
    394     /** Promiscuous mode -- RX filter accepts all packets. */
    395     uint8_t                 fPromiscuous;
    396 
    397     /** All multicast mode -- RX filter accepts all multicast packets. */
    398     uint8_t                 fAllMulticast;
    399 
    400     /** All unicast mode -- RX filter accepts all unicast packets. */
    401     uint8_t                 fAllUnicast;
    402 
    403     /** No multicast mode - Supresses multicast receive */
    404     uint8_t                 fNoMulticast;
    405 
    406     /** No unicast mode - Suppresses unicast receive */
    407     uint8_t                 fNoUnicast;
    408 
    409     /** No broadcast mode - Supresses broadcast receive */
    410     uint8_t                 fNoBroadcast;
    411 
    412     /** The number of actually used slots in aMacMulticastFilter. */
    413     uint32_t                cMulticastFilterMacs;
    414 
    415     /** Array of MAC multicast addresses accepted by RX filter. */
    416     RTMAC                   aMacMulticastFilter[VIRTIONET_MAC_FILTER_LEN];
    417 
    418     /** The number of actually used slots in aMacUniicastFilter. */
    419     uint32_t                cUnicastFilterMacs;
    420 
    421     /** Array of MAC unicast addresses accepted by RX filter. */
    422     RTMAC                   aMacUnicastFilter[VIRTIONET_MAC_FILTER_LEN];
    423 
    424     /** Bit array of VLAN filter, one bit per VLAN ID. */
    425     uint8_t                 aVlanFilter[VIRTIONET_MAX_VLAN_ID / sizeof(uint8_t)];
    426452
    427453    /** @name Statistic
     
    489515    R3PTRTYPE(PPDMINETWORKUP)       pDrv;
    490516
    491     R3PTRTYPE(PPDMTHREAD)           pTxThread;
    492 
    493517    /** Link Up(/Restore) Timer. */
    494518    TMTIMERHANDLE                   hLinkUpTimer;
    495 
    496     /** Queue to send tasks to R3. - HC ptr */
    497     R3PTRTYPE(PPDMQUEUE)            pNotifierQueueR3;
    498519
    499520    /** True if in the process of quiescing I/O */
     
    541562typedef CTX_SUFF(PVIRTIONET) PVIRTIONETCC;
    542563
     564#ifdef IN_RING3
     565static DECLCALLBACK(int) virtioNetR3WorkerThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread);
     566
     567DECLINLINE(const char *) virtioNetThreadStateName(PPDMTHREAD pThread)
     568{
     569    if (!pThread)
     570        return "<null>";
     571
     572    switch(pThread->enmState)
     573    {
     574        case PDMTHREADSTATE_INVALID:
     575            return "invalid state";
     576        case PDMTHREADSTATE_INITIALIZING:
     577            return "initializing";
     578        case PDMTHREADSTATE_SUSPENDING:
     579            return "suspending";
     580        case PDMTHREADSTATE_SUSPENDED:
     581            return "suspended";
     582        case PDMTHREADSTATE_RESUMING:
     583            return "resuming";
     584        case PDMTHREADSTATE_RUNNING:
     585            return "running";
     586        case PDMTHREADSTATE_TERMINATING:
     587            return "terminating";
     588        case PDMTHREADSTATE_TERMINATED:
     589            return "terminated";
     590        default:
     591            return "unknown state";
     592    }
     593}
     594#endif
     595
    543596/**
    544597 * Wakeup the RX thread.
     
    551604
    552605    STAM_COUNTER_INC(&pThis->StatRxOverflowWakeup);
    553 
    554     Log10Func(("%s Waking downstream driver's Rx buf waiter thread\n", INSTANCE(pThis)));
    555     int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEventRxDescAvail);
    556     AssertRC(rc);
     606    if (pThis->hEventRxDescAvail != NIL_SUPSEMEVENT)
     607    {
     608        Log10Func(("%s Waking downstream device's Rx buf waiter thread\n", pThis->szInst));
     609        int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEventRxDescAvail);
     610        AssertRC(rc);
     611    }
    557612}
    558613
     
    565620    PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    566621
    567     uint16_t idxWorker;
    568     if (idxQueue == CTRLQIDX)
    569         idxWorker = pThis->cWorkers - 1;
    570     else
    571         idxWorker = idxQueue / 2;
    572 
    573     PVIRTIONETWORKER pWorker = &pThis->aWorkers[idxWorker];
    574     AssertReturnVoid(idxQueue < pThis->cVirtQueues);
     622    PVIRTIONETQUEUE  pQueue = &pThis->aQueues[idxQueue];
     623    PVIRTIONETWORKER pWorker = pQueue->pWorker;
    575624
    576625#if defined (IN_RING3) && defined (LOG_ENABLED)
     
    578627#endif
    579628
    580     Log10Func(("%s %s has available buffers\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
    581 
    582629    if (IS_RX_QUEUE(idxQueue))
    583630    {
    584         Log10Func(("%s Receive buffers have been added, waking Rx thread.\n",
    585             INSTANCE(pThis)));
    586         virtioNetWakeupRxBufWaiter(pDevIns);
    587     }
    588     else
     631        uint16_t cBufsAvailable = virtioCoreQueueAvailCount(pDevIns, pVirtio, idxQueue);
     632
     633        if (cBufsAvailable)
     634        {
     635            Log10Func(("%s %u empty bufs added to %s by guest (notifying leaf device)\n",
     636                        pThis->szInst, cBufsAvailable, pQueue->szName));
     637            virtioNetWakeupRxBufWaiter(pDevIns);
     638        }
     639        else
     640            LogRel(("%s \n\n***WARNING: %s notified but no empty bufs added by guest! (skip notifying of leaf device)\n\n",
     641                    pThis->szInst, pQueue->szName));
     642    }
     643    else if (IS_TX_QUEUE(idxQueue) || IS_CTRL_QUEUE(idxQueue))
    589644    {
    590645        /* Wake queue's worker thread up if sleeping (e.g. a Tx queue, or the control queue */
     
    593648            if (ASMAtomicReadBool(&pWorker->fSleeping))
    594649            {
    595                 Log10Func(("%s waking %s worker.\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
     650                Log10Func(("%s %s has available buffers - waking worker.\n", pThis->szInst, pQueue->szName));
    596651                int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess);
    597652                AssertRC(rc);
    598653            }
     654            else
     655            {
     656                Log10Func(("%s %s has available buffers - worker already awake\n", pThis->szInst, pQueue->szName));
     657            }
    599658        }
    600     }
     659        else
     660        {
     661            Log10Func(("%s %s has available buffers - waking worker.\n", pThis->szInst, pQueue->szName));
     662        }
     663    }
     664    else
     665        LogRelFunc(("%s unrecognized queue %s (idx=%d) notified\n", pQueue->szName, idxQueue));
    601666}
    602667
     
    608673static DECLCALLBACK(int) virtioNetR3WakeupWorker(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    609674{
    610     PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    611     Log10Func(("%s\n", INSTANCE(pThis)));
    612     return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[(uintptr_t)pThread->pvUser].hEvtProcess);
     675    PVIRTIONET       pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
     676    PVIRTIONETWORKER pWorker = (PVIRTIONETWORKER)pThread->pvUser;
     677
     678    Log10Func(("%s\n", pThis->szInst));
     679
     680    return PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess);
    613681}
    614682
     
    616684DECLINLINE(void) virtioNetR3SetVirtqNames(PVIRTIONET pThis)
    617685{
     686    RTStrCopy(pThis->aQueues[CTRLQIDX].szName, VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq");
    618687    for (uint16_t qPairIdx = 0; qPairIdx < pThis->cVirtqPairs; qPairIdx++)
    619688    {
    620         RTStrPrintf(pThis->aszVirtqNames[RXQIDX(qPairIdx)], VIRTIO_MAX_QUEUE_NAME_SIZE, "receiveq<%d>",  qPairIdx);
    621         RTStrPrintf(pThis->aszVirtqNames[TXQIDX(qPairIdx)], VIRTIO_MAX_QUEUE_NAME_SIZE, "transmitq<%d>", qPairIdx);
    622     }
    623     RTStrCopy(pThis->aszVirtqNames[CTRLQIDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq");
     689        RTStrPrintf(pThis->aQueues[RXQIDX(qPairIdx)].szName, VIRTIO_MAX_QUEUE_NAME_SIZE, "receiveq<%d>",  qPairIdx);
     690        RTStrPrintf(pThis->aQueues[TXQIDX(qPairIdx)].szName, VIRTIO_MAX_QUEUE_NAME_SIZE, "transmitq<%d>", qPairIdx);
     691    }
    624692}
    625693
     
    637705        return;
    638706
    639     vboxEthPacketDump(INSTANCE(pThis), pszText, pbPacket, (uint32_t)cb);
    640 }
    641 
    642 #ifdef LOG_ENABLED
    643 
    644 void virtioNetDumpGcPhysRxBuf(PPDMDEVINS pDevIns, PVIRTIONET_PKT_HDR_T pRxPktHdr,
    645                      uint16_t cDescs, uint8_t *pvBuf, uint16_t cb, RTGCPHYS gcPhysRxBuf, uint8_t cbRxBuf)
    646 {
    647     PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    648     pRxPktHdr->uNumBuffers = cDescs;
    649     if (pRxPktHdr)
    650     {
    651         LogFunc(("-------------------------------------------------------------------\n"));
    652         LogFunc(("rxPktHdr\n"
    653                  "    uFlags ......... %2.2x\n"
    654                  "    uGsoType ....... %2.2x\n"
    655                  "    uHdrLen ........ %4.4x\n"
    656                  "    uGsoSize ....... %4.4x\n"
    657                  "    uChksumStart ... %4.4x\n"
    658                  "    uChksumOffset .. %4.4x\n"
    659                  "    uNumBuffers .... %4.4x\n",
    660                         pRxPktHdr->uFlags,
    661                         pRxPktHdr->uGsoType, pRxPktHdr->uHdrLen, pRxPktHdr->uGsoSize,
    662                         pRxPktHdr->uChksumStart, pRxPktHdr->uChksumOffset, pRxPktHdr->uNumBuffers));
    663 
    664         virtioCoreHexDump((uint8_t *)pRxPktHdr, sizeof(VIRTIONET_PKT_HDR_T), 0, "Dump of virtual rPktHdr");
    665     }
    666     virtioNetR3PacketDump(pThis, (const uint8_t *)pvBuf, cb, "<-- Incoming");
    667     LogFunc((". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n"));
    668     virtioCoreGcPhysHexDump(pDevIns, gcPhysRxBuf, cbRxBuf, 0, "Phys Mem Dump of Rx pkt");
    669     LogFunc(("-------------------------------------------------------------------\n"));
    670 }
    671 
    672 DECLINLINE(void) virtioNetPrintFeatures(VIRTIONET *pThis)
     707    vboxEthPacketDump(pThis->szInst, pszText, pbPacket, (uint32_t)cb);
     708}
     709
     710DECLINLINE(void) virtioNetPrintFeatures(VIRTIONET *pThis, PCDBGFINFOHLP pHlp)
    673711{
    674712    static struct
     
    714752                          isOffered ? "+" : "-", isNegotiated ? "x" : " ", s_aFeatures[i].pcszDesc);
    715753    }
    716     Log3(("VirtIO Net Features Configuration\n\n"
    717           "    Offered  Accepted  Feature              Description\n"
    718           "    -------  --------  -------              -----------\n"
    719           "%s\n", pszBuf));
     754    if (pHlp)
     755        pHlp->pfnPrintf(pHlp, "VirtIO Net Features Configuration\n\n"
     756              "    Offered  Accepted  Feature              Description\n"
     757              "    -------  --------  -------              -----------\n"
     758              "%s\n", pszBuf);
     759#ifdef LOG_ENABLED
     760    else
     761        Log3(("VirtIO Net Features Configuration\n\n"
     762              "    Offered  Accepted  Feature              Description\n"
     763              "    -------  --------  -------              -----------\n"
     764              "%s\n", pszBuf));
     765#endif
    720766    RTMemFree(pszBuf);
    721767}
     768
     769#ifdef LOG_ENABLED
     770void virtioNetDumpGcPhysRxBuf(PPDMDEVINS pDevIns, PVIRTIONET_PKT_HDR_T pRxPktHdr,
     771                     uint16_t cDescs, uint8_t *pvBuf, uint16_t cb, RTGCPHYS GCPhysRxBuf, uint8_t cbRxBuf)
     772{
     773    PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
     774    pRxPktHdr->uNumBuffers = cDescs;
     775    if (pRxPktHdr)
     776    {
     777        LogFunc(("-------------------------------------------------------------------\n"));
     778        LogFunc(("rxPktHdr\n"
     779                 "    uFlags ......... %2.2x\n"
     780                 "    uGsoType ....... %2.2x\n"
     781                 "    uHdrLen ........ %4.4x\n"
     782                 "    uGsoSize ....... %4.4x\n"
     783                 "    uChksumStart ... %4.4x\n"
     784                 "    uChksumOffset .. %4.4x\n"
     785                 "    uNumBuffers .... %4.4x\n",
     786                        pRxPktHdr->uFlags,
     787                        pRxPktHdr->uGsoType, pRxPktHdr->uHdrLen, pRxPktHdr->uGsoSize,
     788                        pRxPktHdr->uChksumStart, pRxPktHdr->uChksumOffset, pRxPktHdr->uNumBuffers));
     789
     790        virtioCoreHexDump((uint8_t *)pRxPktHdr, sizeof(VIRTIONET_PKT_HDR_T), 0, "Dump of virtual rPktHdr");
     791    }
     792    virtioNetR3PacketDump(pThis, (const uint8_t *)pvBuf, cb, "<-- Incoming");
     793    LogFunc((". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n"));
     794
     795    virtioCoreGCPhysHexDump(pDevIns, GCPhysRxBuf, cbRxBuf, 0, "Phys Mem Dump of Rx pkt");
     796    LogFunc(("-------------------------------------------------------------------\n"));
     797}
     798
    722799#endif /* LOG_ENABLED */
     800
     801/**
     802 * @callback_method_impl{FNDBGFHANDLERDEV, virtio-net debugger info callback.}
     803 */
     804static DECLCALLBACK(void) virtioNetR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
     805{
     806    PVIRTIONET     pThis   = PDMDEVINS_2_DATA(pDevIns,  PVIRTIONET);
     807    PVIRTIONETCC   pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC);
     808
     809    bool fNone     = pszArgs && *pszArgs == '\0';
     810    bool fAll      = pszArgs && (*pszArgs == 'a' || *pszArgs == 'A'); /* "all"      */
     811    bool fNetwork  = pszArgs && (*pszArgs == 'n' || *pszArgs == 'N'); /* "network"  */
     812    bool fFeatures = pszArgs && (*pszArgs == 'f' || *pszArgs == 'F'); /* "features" */
     813    bool fState    = pszArgs && (*pszArgs == 's' || *pszArgs == 'S'); /* "state"    */
     814    bool fPointers = pszArgs && (*pszArgs == 'p' || *pszArgs == 'P'); /* "pointers" */
     815    bool fQueues   = pszArgs && (*pszArgs == 'q' || *pszArgs == 'Q'); /* "queues    */
     816
     817    /* Show basic information. */
     818    pHlp->pfnPrintf(pHlp,
     819        "\n"
     820        "---------------------------------------------------------------------------\n"
     821        "Debug Info: %s\n"
     822        "        (options: [a]ll, [n]et, [f]eatures, [s]tate, [p]ointers, [q]ueues)\n"
     823        "---------------------------------------------------------------------------\n\n",
     824        pThis->szInst, pDevIns->pReg->szName);
     825
     826    if (fNone)
     827        return;
     828
     829    /* Show offered/unoffered, accepted/rejected features */
     830    if (fAll || fFeatures)
     831    {
     832        virtioCorePrintFeatures(&pThis->Virtio, pHlp);
     833        virtioNetPrintFeatures(pThis, pHlp);
     834        pHlp->pfnPrintf(pHlp, "\n");
     835    }
     836
     837    /* Show queues (and associate worker info if applicable) */
     838    if (fAll || fQueues)
     839    {
     840        pHlp->pfnPrintf(pHlp, "Queue information:\n\n");
     841
     842        for (int idxQueue = 0; idxQueue < pThis->cVirtQueues; idxQueue++)
     843        {
     844            PVIRTIONETQUEUE pQueue = &pThis->aQueues[idxQueue];
     845
     846            if (pQueue->fHasWorker)
     847            {
     848                PVIRTIONETWORKER pWorker = pQueue->pWorker;
     849                PVIRTIONETWORKERR3 pWorkerR3 = pQueue->pWorkerR3;
     850
     851                if (pWorker->fAssigned)
     852                {
     853                    pHlp->pfnPrintf(pHlp, "    %-15s (pThread: %p %s) ",
     854                        pQueue->szName,
     855                        pWorkerR3->pThread,
     856                        virtioNetThreadStateName(pWorkerR3->pThread));
     857                    if (pQueue->fAttachedToVirtioCore)
     858                    {
     859                        pHlp->pfnPrintf(pHlp, "worker: ");
     860                        pHlp->pfnPrintf(pHlp, "%s", pWorker->fSleeping ? "blocking" : "unblocked");
     861                        pHlp->pfnPrintf(pHlp, "%s", pWorker->fNotified ? ", notified" : "");
     862                    }
     863                    else
     864                    if (pWorker->fNotified)
     865                        pHlp->pfnPrintf(pHlp, "not attached to virtio core");
     866                }
     867            }
     868            else
     869            {
     870                pHlp->pfnPrintf(pHlp, "    %-15s (INetworkDown's thread) %s", pQueue->szName,
     871                    pQueue->fAttachedToVirtioCore  ? "" : "not attached to virtio core");
     872            }
     873            pHlp->pfnPrintf(pHlp, "\n");
     874            virtioCoreR3QueueInfo(pDevIns, pHlp, pszArgs, idxQueue);
     875            pHlp->pfnPrintf(pHlp, "    ---------------------------------------------------------------------\n");
     876            pHlp->pfnPrintf(pHlp, "\n");
     877        }
     878        pHlp->pfnPrintf(pHlp, "\n");
     879    }
     880
     881    /* Show various pointers */
     882    if (fAll || fPointers)
     883    {
     884
     885        pHlp->pfnPrintf(pHlp, "Internal pointers:\n\n");
     886
     887        pHlp->pfnPrintf(pHlp, "    pDevIns ................... %p\n",  pDevIns);
     888        pHlp->pfnPrintf(pHlp, "    PVIRTIONET ................ %p\n",  pThis);
     889        pHlp->pfnPrintf(pHlp, "    PVIRTIONETCC .............. %p\n", pThisCC);
     890        pHlp->pfnPrintf(pHlp, "    pDrvBase .................. %p\n",  pThisCC->pDrvBase);
     891        pHlp->pfnPrintf(pHlp, "    pDrv ...................... %p\n",  pThisCC->pDrv);
     892        pHlp->pfnPrintf(pHlp, "    pDrv ...................... %p\n",  pThisCC->pDrv);
     893        pHlp->pfnPrintf(pHlp, "\n");
     894        pHlp->pfnPrintf(pHlp, "Misc state\n");
     895        pHlp->pfnPrintf(pHlp, "\n");
     896        pHlp->pfnPrintf(pHlp, "    fVirtioReady .............. %d\n",  pThis->fVirtioReady);
     897        pHlp->pfnPrintf(pHlp, "    fGenUpdatePending ......... %d\n",  pThis->Virtio.fGenUpdatePending);
     898        pHlp->pfnPrintf(pHlp, "    fMsiSupport ............... %d\n",  pThis->Virtio.fMsiSupport);
     899        pHlp->pfnPrintf(pHlp, "    uConfigGeneration ......... %d\n",  pThis->Virtio.uConfigGeneration);
     900        pHlp->pfnPrintf(pHlp, "    uDeviceStatus ............. 0x%x\n", pThis->Virtio.uDeviceStatus);
     901        pHlp->pfnPrintf(pHlp, "    cVirtqPairs .,............. %d\n",  pThis->cVirtqPairs);
     902        pHlp->pfnPrintf(pHlp, "    cVirtQueues .,............. %d\n",  pThis->cVirtQueues);
     903        pHlp->pfnPrintf(pHlp, "    cWorkers .................. %d\n",  pThis->cWorkers);
     904        pHlp->pfnPrintf(pHlp, "    MMIO mapping name ......... %d\n",  pThisCC->Virtio.pcszMmioName);
     905
     906    }
     907
     908    /* Show device state info */
     909    if (fAll || fState)
     910    {
     911        pHlp->pfnPrintf(pHlp, "Device state:\n\n");
     912        uint32_t fTransmitting = ASMAtomicReadU32(&pThis->uIsTransmitting);
     913
     914        pHlp->pfnPrintf(pHlp, "    Transmitting: ............. %s\n", fTransmitting ? "true" : "false");
     915        pHlp->pfnPrintf(pHlp, "    Quiescing: ................ %s %s\n",
     916                pThis->fQuiescing ? "true" : "false",
     917                pThis->fQuiescing ? "(" : "",
     918                pThis->fQuiescing ? virtioCoreGetStateChangeText(pThisCC->enmQuiescingFor) : "",
     919                pThis->fQuiescing ? ")" : "");
     920        pHlp->pfnPrintf(pHlp, "    Resetting: ................ %s\n", pThis->fResetting ? "true" : "false");
     921        pHlp->pfnPrintf(pHlp, "\n");
     922    }
     923
     924    /* Show network related information */
     925    if (fAll || fNetwork)
     926    {
     927        pHlp->pfnPrintf(pHlp, "Network configuration:\n\n");
     928
     929        pHlp->pfnPrintf(pHlp, "    MAC: ...................... %RTmac\n", &pThis->macConfigured);
     930        pHlp->pfnPrintf(pHlp, "\n");
     931        pHlp->pfnPrintf(pHlp, "    Cable: .................... %s\n",      pThis->fCableConnected ? "connected" : "disconnected");
     932        pHlp->pfnPrintf(pHlp, "    Link-up delay: ............ %d ms\n",   pThis->cMsLinkUpDelay);
     933        pHlp->pfnPrintf(pHlp, "\n");
     934        pHlp->pfnPrintf(pHlp, "    Accept all multicast: ..... %s\n",      pThis->fAllMulticast  ? "true" : "false");
     935        pHlp->pfnPrintf(pHlp, "    Suppress broadcast: ....... %s\n",      pThis->fNoBroadcast   ? "true" : "false");
     936        pHlp->pfnPrintf(pHlp, "    Suppress unicast: ......... %s\n",      pThis->fNoUnicast     ? "true" : "false");
     937        pHlp->pfnPrintf(pHlp, "    Suppress multicast: ....... %s\n",      pThis->fNoMulticast   ? "true" : "false");
     938        pHlp->pfnPrintf(pHlp, "    Promiscuous: .............. %s\n",      pThis->fPromiscuous   ? "true" : "false");
     939        pHlp->pfnPrintf(pHlp, "\n");
     940        pHlp->pfnPrintf(pHlp, "    Default Rx MAC filter: .... %RTmac\n", pThis->rxFilterMacDefault);
     941        pHlp->pfnPrintf(pHlp, "\n");
     942
     943        pHlp->pfnPrintf(pHlp, "    Unicast filter MACs:\n");
     944
     945        if (!pThis->cUnicastFilterMacs)
     946            pHlp->pfnPrintf(pHlp, "        <none>\n");
     947
     948        for (uint32_t i = 0; i < pThis->cUnicastFilterMacs; i++)
     949            pHlp->pfnPrintf(pHlp, "        %RTmac\n", &pThis->aMacUnicastFilter[i]);
     950
     951        pHlp->pfnPrintf(pHlp, "\n    Multicast filter MACs:\n");
     952
     953        if (!pThis->cMulticastFilterMacs)
     954            pHlp->pfnPrintf(pHlp, "        <none>\n");
     955
     956        for (uint32_t i = 0; i < pThis->cMulticastFilterMacs; i++)
     957            pHlp->pfnPrintf(pHlp, "        %RTmac\n", &pThis->aMacMulticastFilter[i]);
     958
     959        pHlp->pfnPrintf(pHlp, "\n\n");
     960        pHlp->pfnPrintf(pHlp, "    Leaf starved: ............. %s\n",      pThis->fLeafWantsEmptyRxBufs ? "true" : "false");
     961        pHlp->pfnPrintf(pHlp, "\n");
     962
     963    }
     964    pHlp->pfnPrintf(pHlp, "\n");
     965    virtioCoreR3Info(pDevIns, pHlp, pszArgs);
     966    pHlp->pfnPrintf(pHlp, "\n");
     967}
     968
    723969/*
    724970 * Checks whether negotiated features have required flag combinations.
     
    8021048        uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIONET_CONFIG_T, member); \
    8031049        if (fWrite) \
    804             LogFunc(("%s Guest attempted to write readonly virtio_pci_common_cfg.%s\n", INSTANCE(pThis), #member)); \
     1050            LogFunc(("%s Guest attempted to write readonly virtio_pci_common_cfg.%s\n", pThis->szInst, #member)); \
    8051051        else \
    8061052        { \
     
    8291075    else
    8301076    {
    831         LogFunc(("%s Bad access by guest to virtio_net_config: off=%u (%#x), cb=%u\n", INSTANCE(pThis), offConfig, offConfig, cb));
     1077        LogFunc(("%s Bad access by guest to virtio_net_config: off=%u (%#x), cb=%u\n", pThis->szInst, offConfig, offConfig, cb));
    8321078        return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00;
    8331079    }
     
    8471093    PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    8481094
    849     LogFunc(("%s uOffset: %d, cb: %d\n",  INSTANCE(pThis), uOffset, cb));
     1095    LogFunc(("%s uOffset: %d, cb: %d\n",  pThis->szInst, uOffset, cb));
    8501096    RT_NOREF(pThis);
    8511097    return virtioNetR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIONET), uOffset, pv, cb, false /*fRead*/);
     
    8591105    PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    8601106
    861     Log10Func(("%s uOffset: %d, cb: %d: %.*Rhxs\n", INSTANCE(pThis), uOffset, cb, RT_MAX(cb, 8) , pv));
     1107    Log10Func(("%s uOffset: %d, cb: %d: %.*Rhxs\n", pThis->szInst, uOffset, cb, RT_MAX(cb, 8) , pv));
    8621108    RT_NOREF(pThis);
    8631109    return virtioNetR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIONET), uOffset, (void *)pv, cb, true /*fWrite*/);
    864 }
    865 
    866 
    867 /*********************************************************************************************************************************
    868 *   Misc                                                                                                                         *
    869 *********************************************************************************************************************************/
    870 
    871 /**
    872  * @callback_method_impl{FNDBGFHANDLERDEV, virtio-net debugger info callback.}
    873  */
    874 static DECLCALLBACK(void) virtioNetR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    875 {
    876     PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    877 
    878     /* Parse arguments. */
    879     RT_NOREF2(pThis, pszArgs); //bool fVerbose = pszArgs && strstr(pszArgs, "verbose") != NULL;
    880 
    881     /* Show basic information. */
    882     pHlp->pfnPrintf(pHlp, "%s#%d: virtio-scsci ",
    883                     pDevIns->pReg->szName,
    884                     pDevIns->iInstance);
    8851110}
    8861111
     
    9001125
    9011126    RT_NOREF(pThisCC);
    902     Log7Func(("%s LOAD EXEC!!\n", INSTANCE(pThis)));
     1127    Log7Func(("%s LOAD EXEC!!\n", pThis->szInst));
    9031128
    9041129    AssertReturn(uPass == SSM_PASS_FINAL, VERR_SSM_UNEXPECTED_PASS);
     
    9141139
    9151140    for (int idxQueue = 0; idxQueue < pThis->cVirtQueues; idxQueue++)
    916         pHlp->pfnSSMGetBool(pSSM, &pThis->afQueueAttached[idxQueue]);
     1141        pHlp->pfnSSMGetBool(pSSM, &pThis->aQueues[idxQueue].fAttachedToVirtioCore);
    9171142
    9181143    int rc;
     
    9301155        && (uPass == 0 || !PDMDevHlpVMTeleportedAndNotFullyResumedYet(pDevIns)))
    9311156        LogRel(("%s: The mac address differs: config=%RTmac saved=%RTmac\n",
    932             INSTANCE(pThis), &pThis->macConfigured, &macConfigured));
     1157            pThis->szInst, &pThis->macConfigured, &macConfigured));
    9331158#endif
    9341159
     
    9731198    for (int idxWorker = 0; idxWorker < pThis->cWorkers; idxWorker++)
    9741199    {
    975         uint16_t idxQueue = pThisCC->aWorkers[idxWorker].idxQueue;
    976         if (pThis->afQueueAttached[idxQueue])
     1200        PVIRTIONETWORKER pWorker = &pThis->aWorkers[idxWorker];
     1201        PVIRTIONETQUEUE  pQueue  = pWorker->pQueue;
     1202        if (pQueue->fAttachedToVirtioCore)
    9771203        {
    978             Log7Func(("%s Waking %s worker.\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
    979             rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[idxWorker].hEvtProcess);
     1204            Log7Func(("%s Waking %s worker.\n", pThis->szInst, pQueue->szName));
     1205            rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess);
    9801206            AssertRCReturn(rc, rc);
    9811207        }
     
    9941220
    9951221    RT_NOREF(pThisCC);
    996     Log7Func(("%s SAVE EXEC!!\n", INSTANCE(pThis)));
     1222    Log7Func(("%s SAVE EXEC!!\n", pThis->szInst));
    9971223
    9981224    pHlp->pfnSSMPutU64(     pSSM, pThis->fNegotiatedFeatures);
     
    10021228
    10031229    for (int idxQueue = 0; idxQueue < pThis->cVirtQueues; idxQueue++)
    1004         pHlp->pfnSSMPutBool(pSSM, pThis->afQueueAttached[idxQueue]);
     1230        pHlp->pfnSSMPutBool(pSSM, pThis->aQueues[idxQueue].fAttachedToVirtioCore);
    10051231
    10061232    /* Save config area */
     
    10531279
    10541280    Log7Func(("%s Device I/O activity quiesced: %s\n",
    1055         INSTANCE(pThis), virtioCoreGetStateChangeText(pThisCC->enmQuiescingFor)));
     1281        pThis->szInst, virtioCoreGetStateChangeText(pThisCC->enmQuiescingFor)));
    10561282
    10571283    virtioCoreR3VmStateChanged(&pThis->Virtio, pThisCC->enmQuiescingFor);
     
    10861312
    10871313    /* If already quiesced invoke async callback.  */
    1088     if (!ASMAtomicReadBool(&pThis->fLeafWantsRxBuffers))
     1314    if (!ASMAtomicReadBool(&pThis->fLeafWantsEmptyRxBufs))
    10891315        PDMDevHlpAsyncNotificationCompleted(pDevIns);
    10901316
     
    10981324{
    10991325    PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    1100     Log7Func(("%s\n", INSTANCE(pThis)));
     1326    Log7Func(("%s\n", pThis->szInst));
    11011327    pThis->fResetting = true;
    11021328    virtioNetR3QuiesceDevice(pDevIns, kvirtIoVmStateChangedReset);
     
    11111337    PVIRTIONET   pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    11121338    PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC);
    1113     Log7Func(("%s\n", INSTANCE(pThis)));
     1339    Log7Func(("%s\n", pThis->szInst));
    11141340
    11151341    RT_NOREF2(pThis, pThisCC);
     
    11251351{
    11261352    PVIRTIONET   pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    1127     Log7Func(("%s\n", INSTANCE(pThis)));
     1353    Log7Func(("%s\n", pThis->szInst));
    11281354    RT_NOREF(pThis);
    11291355    virtioNetR3SuspendOrPowerOff(pDevIns, kvirtIoVmStateChangedPowerOff);
     
    11361362{
    11371363    PVIRTIONET   pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    1138     Log7Func(("%s \n", INSTANCE(pThis)));
     1364    Log7Func(("%s \n", pThis->szInst));
    11391365    RT_NOREF(pThis);
    11401366    virtioNetR3SuspendOrPowerOff(pDevIns, kvirtIoVmStateChangedSuspend);
     
    12131439void virtioNetR3SetWriteLed(PVIRTIONETR3 pThisR3, bool fOn)
    12141440{
    1215     Log10Func(("%s\n", fOn ? "on" : "off"));
    12161441    if (fOn)
    12171442        pThisR3->led.Asserted.s.fWriting = pThisR3->led.Actual.s.fWriting = 1;
    12181443    else
    12191444        pThisR3->led.Actual.s.fWriting = fOn;
     1445}
     1446
     1447/*
     1448 * Returns true if VirtIO core and device are in a running and operational state
     1449 */
     1450DECLINLINE(bool) virtioNetIsOperational(PVIRTIONET pThis, PPDMDEVINS pDevIns)
     1451{
     1452    if (RT_LIKELY(pThis->fVirtioReady) && RT_LIKELY(!pThis->fQuiescing))
     1453    {
     1454        VMSTATE enmVMState = PDMDevHlpVMState(pDevIns);
     1455        if (RT_LIKELY(enmVMState == VMSTATE_RUNNING || enmVMState == VMSTATE_RUNNING_LS))
     1456            return true;
     1457    }
     1458    return false;
    12201459}
    12211460
     
    12311470 * @thread  RX
    12321471 */
    1233 static int virtioNetR3IsRxQueuePrimed(PPDMDEVINS pDevIns, PVIRTIONET pThis, uint16_t idxRxQueue)
    1234 {
    1235 #define LOGPARAMS INSTANCE(pThis), VIRTQNAME(idxRxQueue)
    1236 
    1237     if (!pThis->fVirtioReady)
    1238     {
    1239         Log8Func(("%s %s VirtIO not ready (rc = VERR_NET_NO_BUFFER_SPACE)\n", LOGPARAMS));
    1240     }
    1241     else if (!virtioCoreIsQueueEnabled(&pThis->Virtio, idxRxQueue))
    1242     {
    1243         Log8Func(("%s %s queue not enabled (rc = VERR_NET_NO_BUFFER_SPACE)\n", LOGPARAMS));
    1244     }
    1245     else if (virtioCoreQueueIsEmpty(pDevIns, &pThis->Virtio, idxRxQueue))
    1246     {
    1247         Log8Func(("%s %s queue is empty (rc = VERR_NET_NO_BUFFER_SPACE)\n", LOGPARAMS));
    1248         virtioCoreQueueSetNotify(&pThis->Virtio, idxRxQueue, true);
    1249     }
     1472static int virtioNetR3CheckRxBufsAvail(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETQUEUE pRxQueue)
     1473{
     1474    int rc = VERR_INVALID_STATE;
     1475
     1476    if (!virtioNetIsOperational(pThis, pDevIns))
     1477        Log8Func(("%s No Rx bufs available. (VirtIO core not ready)\n", pThis->szInst));
     1478
     1479    else if (!virtioCoreIsQueueEnabled(&pThis->Virtio, pRxQueue->idx))
     1480        Log8Func(("%s No Rx bufs available. (%s not enabled)\n",  pThis->szInst, pRxQueue->szName));
     1481
     1482    else if (IS_VIRTQ_EMPTY(pDevIns, &pThis->Virtio, pRxQueue->idx))
     1483        Log8Func(("%s No Rx bufs available. (%s empty)\n",  pThis->szInst, pRxQueue->szName));
     1484
    12501485    else
    12511486    {
    1252         Log8Func(("%s %s ready with available buffers\n", LOGPARAMS));
    1253         virtioCoreQueueSetNotify(&pThis->Virtio, idxRxQueue, false);
    1254         return VINF_SUCCESS;
    1255     }
    1256     return VERR_NET_NO_BUFFER_SPACE;
    1257 }
    1258 
    1259 
    1260 static bool virtioNetR3AreRxBufsAvail(PPDMDEVINS pDevIns, PVIRTIONET pThis)
    1261 {
    1262     /** @todo If we ever start using more than one Rx/Tx queue pair, is a random queue
    1263               selection algorithm feasible or even necessary to prevent starvation? */
     1487        Log8Func(("%s Empty guest buffers available in %s\n",  pThis->szInst,pRxQueue->szName));
     1488        rc = VINF_SUCCESS;
     1489    }
     1490    virtioCoreQueueNotifyEnable(&pThis->Virtio, pRxQueue->idx, rc == VERR_INVALID_STATE /* fEnable */);
     1491    return rc;
     1492}
     1493
     1494static bool virtioNetR3RxBufsAvail(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETQUEUE *pRxQueue)
     1495{
    12641496    for (int idxQueuePair = 0; idxQueuePair < pThis->cVirtqPairs; idxQueuePair++)
    1265         if (RT_SUCCESS(virtioNetR3IsRxQueuePrimed(pDevIns, pThis, RXQIDX(idxQueuePair))))
     1497    {
     1498        PVIRTIONETQUEUE pThisRxQueue = &pThis->aQueues[RXQIDX(idxQueuePair)];
     1499        if (RT_SUCCESS(virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pThisRxQueue)))
     1500        {
     1501            if (pRxQueue)
     1502                *pRxQueue = pThisRxQueue;
    12661503            return true;
     1504        }
     1505    }
    12671506    return false;
    1268 }
    1269 /*
    1270  * Returns true if VirtIO core and device are in a running and operational state
    1271  */
    1272 DECLINLINE(bool) virtioNetIsOperational(PVIRTIONET pThis, PPDMDEVINS pDevIns)
    1273 {
    1274     if (!pThis->fVirtioReady)
    1275         return false;
    1276 
    1277     if (pThis->fQuiescing)
    1278         return false;
    1279 
    1280     VMSTATE enmVMState = PDMDevHlpVMState(pDevIns);
    1281     if (!RT_LIKELY(enmVMState == VMSTATE_RUNNING || enmVMState == VMSTATE_RUNNING_LS))
    1282         return false;
    1283 
    1284     return true;
    12851507}
    12861508
     
    12941516    PVIRTIONET   pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    12951517
    1296     if (virtioNetR3AreRxBufsAvail(pDevIns, pThis))
    1297     {
    1298             Log10Func(("%s Rx bufs now available, releasing waiter...\n", INSTANCE(pThis)));
    1299             return VINF_SUCCESS;
     1518    if (virtioNetR3RxBufsAvail(pDevIns, pThis, NULL /* pRxQueue */))
     1519    {
     1520        Log10Func(("%s Rx bufs now available, releasing waiter...\n", pThis->szInst));
     1521        return VINF_SUCCESS;
    13001522    }
    13011523    if (!timeoutMs)
    13021524        return VERR_NET_NO_BUFFER_SPACE;
    13031525
    1304     LogFlowFunc(("%s timeoutMs=%u\n", INSTANCE(pThis), timeoutMs));
    1305 
    1306     ASMAtomicXchgBool(&pThis->fLeafWantsRxBuffers, true);
     1526    LogFunc(("%s %s\n", pThis->szInst, timeoutMs == RT_INDEFINITE_WAIT ? "<indefinite wait>" : ""));
     1527
     1528    ASMAtomicXchgBool(&pThis->fLeafWantsEmptyRxBufs, true);
    13071529    STAM_PROFILE_START(&pThis->StatRxOverflow, a);
    13081530
    13091531    do {
    1310         if (virtioNetR3AreRxBufsAvail(pDevIns, pThis))
     1532        if (virtioNetR3RxBufsAvail(pDevIns, pThis, NULL /* pRxQueue */))
    13111533        {
    1312                 Log10Func(("%s Rx bufs now available, releasing waiter...\n", INSTANCE(pThis)));
    1313                 return VINF_SUCCESS;
     1534            Log10Func(("%s Rx bufs now available, releasing waiter...\n", pThis->szInst));
     1535            return VINF_SUCCESS;
    13141536        }
    1315         Log9Func(("%s Starved for guest Rx bufs, waiting %u ms ...\n",
    1316                  INSTANCE(pThis), timeoutMs));
     1537        Log9Func(("%s Starved for empty guest Rx bufs. Waiting...\n", pThis->szInst));
    13171538
    13181539        int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->hEventRxDescAvail, timeoutMs);
    13191540
    13201541        if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
     1542        {
     1543            LogFunc(("Waken due to %s\n", rc == VERR_TIMEOUT ? "timeout" : "interrupted"));
    13211544            continue;
    1322 
    1323         if (RT_FAILURE(rc))
     1545        }
     1546        if (RT_FAILURE(rc)) {
     1547            LogFunc(("Waken due to failure %Rrc\n", rc));
    13241548            RTThreadSleep(1);
    1325 
     1549        }
     1550LogFunc(("\n\n\n********** WAKEN!!!!! ********\n\n\n"));
    13261551    } while (virtioNetIsOperational(pThis, pDevIns));
    13271552
    13281553    STAM_PROFILE_STOP(&pThis->StatRxOverflow, a);
    1329     ASMAtomicXchgBool(&pThis->fLeafWantsRxBuffers, false);
    1330 
    1331     Log7Func(("%s Wait for Rx buffers available was interrupted\n", INSTANCE(pThis)));
     1554    ASMAtomicXchgBool(&pThis->fLeafWantsEmptyRxBufs, false);
     1555
     1556    Log7Func(("%s Wait for Rx buffers available was interrupted\n", pThis->szInst));
    13321557    return VERR_INTERRUPTED;
    13331558}
     
    14351660
    14361661        LogFunc(("%s node(%RTmac %s%s), pkt(%RTmac %s)",
    1437                  INSTANCE(pThis), pThis->virtioNetConfig.uMacAddress.au8,
     1662                 pThis->szInst, pThis->virtioNetConfig.uMacAddress.au8,
    14381663                 pThis->fPromiscuous ? "promiscuous" : "",
    14391664                 pThis->fAllMulticast ? " all-multicast" : "",
     
    14511676        && !ASMBitTest(pThis->aVlanFilter, RT_BE2H_U16(uPtr[7]) & 0xFFF))
    14521677    {
    1453         Log11Func(("\n%s not our VLAN, returning false\n", INSTANCE(pThis)));
     1678        Log11Func(("\n%s not our VLAN, returning false\n", pThis->szInst));
    14541679        return false;
    14551680    }
     
    15051730                                       VIRTIONET_PKT_HDR_T *rxPktHdr, uint16_t cSegsAllocated,
    15061731                                       PRTSGBUF pVirtSegBufToGuest, PRTSGSEG paVirtSegsToGuest,
    1507                                        uint16_t idxRxQueue)
     1732                                       PVIRTIONETQUEUE pRxQueue)
    15081733{
    15091734    uint8_t fAddPktHdr = true;
    1510     RTGCPHYS gcPhysPktHdrNumBuffers = 0;
     1735    RTGCPHYS GCPhysPktHdrNumBuffers = 0;
    15111736    uint16_t cDescs;
    15121737    uint64_t uOffset;
     
    15151740        PVIRTIO_DESC_CHAIN_T pDescChain = NULL;
    15161741
    1517         int rc = virtioCoreR3QueueGet(pDevIns, &pThis->Virtio, RXQIDX(idxRxQueue), &pDescChain, true);
     1742        int rc = virtioCoreR3QueueGet(pDevIns, &pThis->Virtio, pRxQueue->idx, &pDescChain, true);
    15181743        AssertMsgReturn(rc == VINF_SUCCESS || rc == VERR_NOT_AVAILABLE, ("%Rrc\n", rc), rc);
    15191744
     
    15261751        /* Length of first seg of guest Rx buf should never be less than sizeof(virtio_net_pkt_hdr).
    15271752         * Otherwise code has to become more complicated, e.g. locate & cache seg idx & offset of
    1528          * virtio_net_header.num_buffers, to defer updating (in gcPhys). Re-visit if needed */
     1753         * virtio_net_header.num_buffers, to defer updating (in GCPhys). Re-visit if needed */
    15291754
    15301755        AssertMsgReturnStmt(pDescChain->pSgPhysReturn->paSegs[0].cbSeg >= sizeof(VIRTIONET_PKT_HDR_T),
     
    15491774                memcpy(paVirtSegsToGuest[0].pvSeg, rxPktHdr, cbHdr);
    15501775
    1551                 /* Calculate & cache addr of field to update after final value is known, in gcPhys mem */
    1552                 gcPhysPktHdrNumBuffers = pDescChain->pSgPhysReturn->paSegs[0].gcPhys
     1776                /* Calculate & cache addr of field to update after final value is known, in GCPhys mem */
     1777                GCPhysPktHdrNumBuffers = pDescChain->pSgPhysReturn->paSegs[0].GCPhys
    15531778                                         + RT_UOFFSETOF(VIRTIONET_PKT_HDR_T, uNumBuffers);
    15541779                fAddPktHdr = false;
     
    15761801            Log7Func(("Send Rx pkt to guest...\n"));
    15771802            STAM_PROFILE_START(&pThis->StatReceiveStore, a);
    1578             virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, idxRxQueue,
    1579                                  pVirtSegBufToGuest, pDescChain, true);
     1803            virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, pRxQueue->idx,
     1804                                 pVirtSegBufToGuest, pDescChain, true /* fFence */);
    15801805            STAM_PROFILE_STOP(&pThis->StatReceiveStore, a);
    15811806
     
    15891814    if (uOffset < cb)
    15901815    {
    1591         LogFunc(("%s Packet did not fit into RX queue (packet size=%u)!\n", INSTANCE(pThis), cb));
     1816        LogFunc(("%s Packet did not fit into RX queue (packet size=%u)!\n", pThis->szInst, cb));
    15921817        return VERR_TOO_MUCH_DATA;
    15931818    }
     
    15951820    /* Fix-up pkthdr (in guest phys. memory) with number buffers (descriptors) processed */
    15961821
    1597     int rc = PDMDevHlpPCIPhysWrite(pDevIns, gcPhysPktHdrNumBuffers, &cDescs, sizeof(cDescs));
     1822    int rc = PDMDevHlpPCIPhysWrite(pDevIns, GCPhysPktHdrNumBuffers, &cDescs, sizeof(cDescs));
    15981823    AssertMsgRCReturn(rc,
    15991824                  ("Failure updating descriptor count in pkt hdr in guest physical memory\n"),
    16001825                  rc);
    16011826
    1602     virtioCoreQueueSync(pDevIns, &pThis->Virtio, RXQIDX(idxRxQueue));
     1827    virtioCoreQueueSync(pDevIns, &pThis->Virtio, pRxQueue->idx);
    16031828
    16041829    return VINF_SUCCESS;
     
    16221847 */
    16231848static int virtioNetR3HandleRxPacket(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC,
    1624                                 const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso, uint16_t idxRxQueue)
     1849                                const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso, PVIRTIONETQUEUE pRxQueue)
    16251850{
    16261851    RT_NOREF(pThisCC);
    16271852
    1628     LogFunc(("%s (%RTmac) pGso %s\n", INSTANCE(pThis), pvBuf, pGso ? "present" : "not present"));
     1853    LogFunc(("%s (%RTmac) pGso %s\n", pThis->szInst, pvBuf, pGso ? "present" : "not present"));
    16291854    VIRTIONET_PKT_HDR_T rxPktHdr = { 0 };
    16301855
     
    16321857    {
    16331858        Log2Func(("%s gso type=%x cbPktHdrsTotal=%u cbPktHdrsSeg=%u mss=%u off1=0x%x off2=0x%x\n",
    1634               INSTANCE(pThis), pGso->u8Type, pGso->cbHdrsTotal,
     1859              pThis->szInst, pGso->u8Type, pGso->cbHdrsTotal,
    16351860              pGso->cbHdrsSeg, pGso->cbMaxSeg, pGso->offHdr1, pGso->offHdr2));
    16361861
     
    16731898
    16741899    int rc = virtioNetR3CopyRxPktToGuest(pDevIns, pThis, pvBuf, cb, &rxPktHdr, cSegsAllocated,
    1675                                         pVirtSegBufToGuest, paVirtSegsToGuest, idxRxQueue);
     1900                                        pVirtSegBufToGuest, paVirtSegsToGuest, pRxQueue);
    16761901
    16771902    RTMemFree(paVirtSegsToGuest);
     
    16911916    PPDMDEVINS      pDevIns = pThisCC->pDevIns;
    16921917    PVIRTIONET      pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    1693 
     1918LogFunc(("\n"));
    16941919    if (!pThis->fVirtioReady)
    16951920    {
     
    17251950        if (!uFeatures)
    17261951        {
    1727             Log2Func(("%s GSO type (0x%x) not supported\n", INSTANCE(pThis), pGso->u8Type));
     1952            LogFunc(("%s GSO type (0x%x) not supported\n", pThis->szInst, pGso->u8Type));
    17281953            return VERR_NOT_SUPPORTED;
    17291954        }
    17301955    }
    17311956
    1732     Log10Func(("%s pvBuf=%p cb=%3u pGso=%p ...", INSTANCE(pThis), pvBuf, cb, pGso));
     1957    Log10Func(("%s pvBuf=%p cb=%3u pGso=%p ...\n", pThis->szInst, pvBuf, cb, pGso));
    17331958
    17341959    /** @todo If we ever start using more than one Rx/Tx queue pair, is a random queue
     
    17371962    for (int idxQueuePair = 0; idxQueuePair < pThis->cVirtqPairs; idxQueuePair++)
    17381963    {
    1739         if (RT_SUCCESS(!virtioNetR3IsRxQueuePrimed(pDevIns, pThis, RXQIDX(idxQueuePair))))
     1964
     1965        PVIRTIONETQUEUE pRxQueue = &pThis->aQueues[RXQIDX(idxQueuePair)];
     1966        if (RT_SUCCESS(!virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pRxQueue)))
    17401967        {
    17411968            /* Drop packets if VM is not running or cable is disconnected. */
     
    17491976            if (virtioNetR3AddressFilter(pThis, pvBuf, cb))
    17501977            {
    1751                 rc = virtioNetR3HandleRxPacket(pDevIns, pThis, pThisCC, pvBuf, cb, pGso, RXQIDX(idxQueuePair));
     1978                rc = virtioNetR3HandleRxPacket(pDevIns, pThis, pThisCC, pvBuf, cb, pGso, pRxQueue);
    17521979                STAM_REL_COUNTER_ADD(&pThis->StatReceiveBytes, cb);
    17531980            }
     
    17842011    }
    17852012    LogFunc(("%s Pulled %d/%d bytes from desc chain (%d bytes left)\n",
    1786              INSTANCE(pThis), cb - cbLim, cb, pDescChain->cbPhysSend));
     2013             pThis->szInst, cb - cbLim, cb, pDescChain->cbPhysSend));
    17872014    RT_NOREF(pThis);
    17882015}
     
    17922019{
    17932020
    1794 #define LOG_VIRTIONET_FLAG(fld) LogFunc(("%s Setting %s=%d\n", INSTANCE(pThis), #fld, pThis->fld))
    1795 
    1796     LogFunc(("%s Processing CTRL Rx command\n", INSTANCE(pThis)));
     2021#define LOG_VIRTIONET_FLAG(fld) LogFunc(("%s Setting %s=%d\n", pThis->szInst, #fld, pThis->fld))
     2022
     2023    LogFunc(("%s Processing CTRL Rx command\n", pThis->szInst));
    17972024    RT_NOREF(pThis);
    17982025    switch(pCtrlPktHdr->uCmd)
     
    18662093                                  PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTIO_DESC_CHAIN_T pDescChain)
    18672094{
    1868     LogFunc(("%s Processing CTRL MAC command\n", INSTANCE(pThis)));
     2095    LogFunc(("%s Processing CTRL MAC command\n", pThis->szInst));
    18692096
    18702097    RT_NOREF(pThisCC);
     
    18982125            virtioNetR3PullChain(pDevIns, pThis, pDescChain, &cMacs, sizeof(cMacs));
    18992126            cbRemaining -= sizeof(cMacs);
    1900             Log7Func(("%s Guest provided %d unicast MAC Table entries\n", INSTANCE(pThis), cMacs));
     2127            Log7Func(("%s Guest provided %d unicast MAC Table entries\n", pThis->szInst, cMacs));
    19012128            if (cMacs)
    19022129            {
     
    19122139            virtioNetR3PullChain(pDevIns, pThis, pDescChain, &cMacs, sizeof(cMacs));
    19132140            cbRemaining -= sizeof(cMacs);
    1914             Log10Func(("%s Guest provided %d multicast MAC Table entries\n", INSTANCE(pThis), cMacs));
     2141            Log10Func(("%s Guest provided %d multicast MAC Table entries\n", pThis->szInst, cMacs));
    19152142            if (cMacs)
    19162143            {
     
    19232150
    19242151#ifdef LOG_ENABLED
    1925             LogFunc(("%s unicast MACs:\n", INSTANCE(pThis)));
     2152            LogFunc(("%s unicast MACs:\n", pThis->szInst));
    19262153            for(unsigned i = 0; i < cMacs; i++)
    19272154                LogFunc(("         %RTmac\n", &pThis->aMacUnicastFilter[i]));
    19282155
    1929             LogFunc(("%s multicast MACs:\n", INSTANCE(pThis)));
     2156            LogFunc(("%s multicast MACs:\n", pThis->szInst));
    19302157            for(unsigned i = 0; i < cMacs; i++)
    19312158                LogFunc(("         %RTmac\n", &pThis->aMacMulticastFilter[i]));
     
    19392166                                   PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTIO_DESC_CHAIN_T pDescChain)
    19402167{
    1941     LogFunc(("%s Processing CTRL VLAN command\n", INSTANCE(pThis)));
     2168    LogFunc(("%s Processing CTRL VLAN command\n", pThis->szInst));
    19422169
    19432170    RT_NOREF(pThisCC);
     
    19492176    virtioNetR3PullChain(pDevIns, pThis, pDescChain, &uVlanId, sizeof(uVlanId));
    19502177    AssertMsgReturn(uVlanId > VIRTIONET_MAX_VLAN_ID,
    1951         ("%s VLAN ID out of range (VLAN ID=%u)\n", INSTANCE(pThis), uVlanId), VIRTIONET_ERROR);
    1952     LogFunc(("%s uCommand=%u VLAN ID=%u\n", INSTANCE(pThis), pCtrlPktHdr->uCmd, uVlanId));
     2178        ("%s VLAN ID out of range (VLAN ID=%u)\n", pThis->szInst, uVlanId), VIRTIONET_ERROR);
     2179    LogFunc(("%s uCommand=%u VLAN ID=%u\n", pThis->szInst, pCtrlPktHdr->uCmd, uVlanId));
    19532180    switch (pCtrlPktHdr->uCmd)
    19542181    {
     
    19682195                            PVIRTIO_DESC_CHAIN_T pDescChain)
    19692196{
    1970     LogFunc(("%s Received CTRL packet from guest\n", INSTANCE(pThis)));
     2197    LogFunc(("%s Received CTRL packet from guest\n", pThis->szInst));
    19712198
    19722199    if (pDescChain->cbPhysSend < 2)
    19732200    {
    1974         LogFunc(("%s CTRL packet from guest driver incomplete. Skipping ctrl cmd\n", INSTANCE(pThis)));
     2201        LogFunc(("%s CTRL packet from guest driver incomplete. Skipping ctrl cmd\n", pThis->szInst));
    19752202        return;
    19762203    }
    19772204    else if (pDescChain->cbPhysReturn < sizeof(VIRTIONET_CTRL_HDR_T_ACK))
    19782205    {
    1979         LogFunc(("%s Guest driver didn't allocate memory to receive ctrl pkt ACK. Skipping ctrl cmd\n", INSTANCE(pThis)));
     2206        LogFunc(("%s Guest driver didn't allocate memory to receive ctrl pkt ACK. Skipping ctrl cmd\n", pThis->szInst));
    19802207        return;
    19812208    }
     
    19942221                         RT_MIN(pDescChain->cbPhysSend, sizeof(VIRTIONET_CTRL_HDR_T)));
    19952222
    1996     Log7Func(("%s CTRL COMMAND: class=%d command=%d\n", INSTANCE(pThis), pCtrlPktHdr->uClass, pCtrlPktHdr->uCmd));
     2223    Log7Func(("%s CTRL COMMAND: class=%d command=%d\n", pThis->szInst, pCtrlPktHdr->uClass, pCtrlPktHdr->uCmd));
    19972224
    19982225    uint8_t uAck;
     
    20132240            {
    20142241                LogFunc(("%s Ignoring CTRL class VIRTIONET_CTRL_ANNOUNCE.\n"
    2015                          "VIRTIO_F_STATUS or VIRTIO_F_GUEST_ANNOUNCE feature not enabled\n", INSTANCE(pThis)));
     2242                         "VIRTIO_F_STATUS or VIRTIO_F_GUEST_ANNOUNCE feature not enabled\n", pThis->szInst));
    20162243                break;
    20172244            }
    20182245            if (pCtrlPktHdr->uCmd != VIRTIONET_CTRL_ANNOUNCE_ACK)
    20192246            {
    2020                 LogFunc(("%s Ignoring CTRL class VIRTIONET_CTRL_ANNOUNCE. Unrecognized uCmd\n", INSTANCE(pThis)));
     2247                LogFunc(("%s Ignoring CTRL class VIRTIONET_CTRL_ANNOUNCE. Unrecognized uCmd\n", pThis->szInst));
    20212248                break;
    20222249            }
    20232250            pThis->virtioNetConfig.uStatus &= ~VIRTIONET_F_ANNOUNCE;
    2024             Log7Func(("%s Clearing VIRTIONET_F_ANNOUNCE in config status\n", INSTANCE(pThis)));
     2251            Log7Func(("%s Clearing VIRTIONET_F_ANNOUNCE in config status\n", pThis->szInst));
    20252252            break;
    20262253
     
    20552282    RTSgBufInit(pReturnSegBuf, paReturnSegs, cSegs);
    20562283
    2057     virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, CTRLQIDX, pReturnSegBuf, pDescChain, true);
     2284    virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, CTRLQIDX, pReturnSegBuf, pDescChain, true /* fFence */);
    20582285    virtioCoreQueueSync(pDevIns, &pThis->Virtio, CTRLQIDX);
    20592286
     
    20652292
    20662293    LogFunc(("%s Finished processing CTRL command with status %s\n",
    2067              INSTANCE(pThis), uAck == VIRTIONET_OK ? "VIRTIONET_OK" : "VIRTIONET_ERROR"));
     2294             pThis->szInst, uAck == VIRTIONET_OK ? "VIRTIONET_OK" : "VIRTIONET_ERROR"));
    20682295}
    20692296
     
    20742301        return rc;
    20752302
    2076     Log(("virtio-net: header (flags=%x gso-type=%x len=%x gso-size=%x Chksum-start=%x Chksum-offset=%x) cbFrame=%d\n",
     2303    LogFunc(("pktHdr (flags=%x gso-type=%x len=%x gso-size=%x Chksum-start=%x Chksum-offset=%x) cbFrame=%d\n",
    20772304          pPktHdr->uFlags, pPktHdr->uGsoType, pPktHdr->uHdrLen,
    20782305          pPktHdr->uGsoSize, pPktHdr->uChksumStart, pPktHdr->uChksumOffset, cbFrame));
     
    21282355        {
    21292356            Log4Func(("%s HdrLen before adjustment %d.\n",
    2130                   INSTANCE(pThis), pGso->cbHdrsTotal));
     2357                  pThis->szInst, pGso->cbHdrsTotal));
    21312358            switch (pGso->u8Type)
    21322359            {
     
    21462373            ((PPDMNETWORKGSO)pSgBuf->pvUser)->cbHdrsSeg   = pGso->cbHdrsSeg;
    21472374            Log4Func(("%s adjusted HdrLen to %d.\n",
    2148                   INSTANCE(pThis), pGso->cbHdrsTotal));
     2375                  pThis->szInst, pGso->cbHdrsTotal));
    21492376        }
    21502377        Log2Func(("%s gso type=%x cbHdrsTotal=%u cbHdrsSeg=%u mss=%u off1=0x%x off2=0x%x\n",
    2151                   INSTANCE(pThis), pGso->u8Type, pGso->cbHdrsTotal, pGso->cbHdrsSeg,
     2378                  pThis->szInst, pGso->u8Type, pGso->cbHdrsTotal, pGso->cbHdrsSeg,
    21522379                  pGso->cbMaxSeg, pGso->offHdr1, pGso->offHdr2));
    21532380        STAM_REL_COUNTER_INC(&pThis->StatTransmitGSO);
     
    21632390    }
    21642391
    2165     return pThisCC->pDrv->pfnSendBuf(pThisCC->pDrv, pSgBuf, false);
     2392    return pThisCC->pDrv->pfnSendBuf(pThisCC->pDrv, pSgBuf, true /* fOnWorkerThread */);
    21662393}
    21672394
    21682395static void virtioNetR3TransmitPendingPackets(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC,
    2169                                          uint16_t idxTxQueue, bool fOnWorkerThread)
     2396                                         PVIRTIONETQUEUE pTxQueue, bool fOnWorkerThread)
    21702397{
    21712398
     
    21832410    {
    21842411        LogFunc(("%s Ignoring Tx requests. VirtIO not ready (status=0x%x).\n",
    2185                 INSTANCE(pThis), pThis->virtioNetConfig.uStatus));
     2412                pThis->szInst, pThis->virtioNetConfig.uStatus));
    21862413        return;
    21872414    }
     
    21892416    if (!pThis->fCableConnected)
    21902417    {
    2191         Log(("%s Ignoring transmit requests while cable is disconnected.\n", INSTANCE(pThis)));
     2418        Log(("%s Ignoring transmit requests while cable is disconnected.\n", pThis->szInst));
    21922419        return;
    21932420    }
     
    22052432    }
    22062433
    2207     int cPkts = virtioCoreR3QueuePendingCount(pVirtio->pDevInsR3, pVirtio, idxTxQueue);
     2434    int cPkts = virtioCoreQueueAvailCount(pVirtio->pDevInsR3, pVirtio, pTxQueue->idx);
    22082435    if (!cPkts)
    22092436    {
    2210         LogFunc(("%s No packets to send found on %s\n", INSTANCE(pThis), VIRTQNAME(idxTxQueue)));
     2437        LogFunc(("%s No packets to send found on %s\n", pThis->szInst, pTxQueue->szName));
    22112438
    22122439        if (pDrv)
     
    22162443        return;
    22172444    }
    2218     LogFunc(("%s About to transmit %d pending packets\n", INSTANCE(pThis), cPkts));
     2445    LogFunc(("%s About to transmit %d pending packet%c\n", pThis->szInst, cPkts, cPkts == 1 ? ' ' : 's'));
    22192446
    22202447    virtioNetR3SetWriteLed(pThisCC, true);
     
    22222449    int rc;
    22232450    PVIRTIO_DESC_CHAIN_T pDescChain = NULL;
    2224     while ((rc = virtioCoreR3QueuePeek(pVirtio->pDevInsR3, pVirtio, idxTxQueue, &pDescChain)) == VINF_SUCCESS)
    2225     {
    2226         Log10Func(("%s fetched descriptor chain from %s\n", INSTANCE(pThis), VIRTQNAME(idxTxQueue)));
     2451    while ((rc = virtioCoreR3QueuePeek(pVirtio->pDevInsR3, pVirtio, pTxQueue->idx, &pDescChain)) == VINF_SUCCESS)
     2452    {
     2453        Log10Func(("%s fetched descriptor chain from %s\n", pThis->szInst, pTxQueue->szName));
    22272454
    22282455        PVIRTIOSGBUF pSgPhysSend = pDescChain->pSgPhysSend;
     
    22392466            uSize +=  paSegsFromGuest[i].cbSeg;
    22402467
    2241         Log5Func(("%s complete frame is %u bytes.\n", INSTANCE(pThis), uSize));
     2468        Log5Func(("%s complete frame is %u bytes.\n", pThis->szInst, uSize));
    22422469        Assert(uSize <= VIRTIONET_MAX_FRAME_SIZE);
    22432470
     
    22482475        if (pThisCC->pDrv)
    22492476        {
    2250             PDMNETWORKGSO  Gso;
    2251             PPDMNETWORKGSO pGso = virtioNetR3SetupGsoCtx(&Gso, &PktHdr);
    22522477            uint64_t uOffset;
     2478
     2479            uSize -= sizeof(PktHdr);
     2480            rc = virtioNetR3ReadHeader(pDevIns, paSegsFromGuest[0].GCPhys, &PktHdr, uSize);
     2481            if (RT_FAILURE(rc))
     2482                return;
     2483            virtioCoreSgBufAdvance(pSgPhysSend, sizeof(PktHdr));
     2484
     2485            PDMNETWORKGSO  Gso, *pGso = virtioNetR3SetupGsoCtx(&Gso, &PktHdr);
    22532486
    22542487            PPDMSCATTERGATHER pSgBufToPdmLeafDevice;
     
    22582491                STAM_REL_COUNTER_INC(&pThis->StatTransmitPackets);
    22592492                STAM_PROFILE_START(&pThis->StatTransmitSend, a);
    2260 
    2261                 uSize -= sizeof(PktHdr);
    2262                 rc = virtioNetR3ReadHeader(pDevIns, paSegsFromGuest[0].gcPhys, &PktHdr, uSize);
    2263                 if (RT_FAILURE(rc))
    2264                     return;
    2265                 virtioCoreSgBufAdvance(pSgPhysSend, sizeof(PktHdr));
    22662493
    22672494                size_t cbCopied = 0;
     
    22722499                {
    22732500                    PVIRTIOSGSEG paSeg  = &pSgPhysSend->paSegs[pSgPhysSend->idxSeg];
    2274                     uint64_t srcSgStart = (uint64_t)paSeg->gcPhys;
     2501                    uint64_t srcSgStart = (uint64_t)paSeg->GCPhys;
    22752502                    uint64_t srcSgLen   = (uint64_t)paSeg->cbSeg;
    2276                     uint64_t srcSgCur   = (uint64_t)pSgPhysSend->gcPhysCur;
     2503                    uint64_t srcSgCur   = (uint64_t)pSgPhysSend->GCPhysCur;
    22772504                    cbCopied = RT_MIN((uint64_t)cbRemain, srcSgLen - (srcSgCur - srcSgStart));
    22782505                    PDMDevHlpPCIPhysRead(pDevIns,
    2279                                          (RTGCPHYS)pSgPhysSend->gcPhysCur,
     2506                                         (RTGCPHYS)pSgPhysSend->GCPhysCur,
    22802507                                         ((uint8_t *)pSgBufToPdmLeafDevice->aSegs[0].pvSeg) + uOffset, cbCopied);
    22812508                    virtioCoreSgBufAdvance(pSgPhysSend, cbCopied);
     
    22912518                if (RT_FAILURE(rc))
    22922519                {
    2293                     LogFunc(("%s Failed to transmit frame, rc = %Rrc\n", INSTANCE(pThis), rc));
     2520                    LogFunc(("%s Failed to transmit frame, rc = %Rrc\n", pThis->szInst, rc));
    22942521                    STAM_PROFILE_STOP(&pThis->StatTransmitSend, a);
    22952522                    STAM_PROFILE_ADV_STOP(&pThis->StatTransmit, a);
     
    23082535
    23092536            /* Remove this descriptor chain from the available ring */
    2310             virtioCoreR3QueueSkip(pVirtio, idxTxQueue);
     2537            virtioCoreR3QueueSkip(pVirtio, pTxQueue->idx);
    23112538
    23122539            /* No data to return to guest, but call is needed put elem (e.g. desc chain) on used ring */
    2313             virtioCoreR3QueuePut(pVirtio->pDevInsR3, pVirtio, idxTxQueue, NULL, pDescChain, false);
     2540            virtioCoreR3QueuePut(pVirtio->pDevInsR3, pVirtio, pTxQueue->idx, NULL, pDescChain, true /* fFence */);
    23142541
    23152542            /* Update used ring idx and notify guest that we've transmitted the data it sent */
    2316             virtioCoreQueueSync(pVirtio->pDevInsR3, pVirtio, idxTxQueue);
     2543            virtioCoreQueueSync(pVirtio->pDevInsR3, pVirtio, pTxQueue->idx);
    23172544        }
    23182545
     
    23372564    PPDMDEVINS      pDevIns = pThisCC->pDevIns;
    23382565    PVIRTIONET      pThis   = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVIRTIONET);
    2339 
     2566    PVIRTIONETQUEUE pTxQueue  = &pThis->aQueues[TXQIDX(0)];
    23402567    STAM_COUNTER_INC(&pThis->StatTransmitByNetwork);
    23412568
    23422569    /** @todo If we ever start using more than one Rx/Tx queue pair, is a random queue
    23432570          selection algorithm feasible or even necessary */
    2344     virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, TXQIDX(0), false /*fOnWorkerThread*/);
    2345 }
    2346 
    2347 /**
    2348  * @callback_method_impl{FNPDMTHREADDEV}
    2349  */
    2350 static DECLCALLBACK(int) virtioNetR3WorkerThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    2351 {
    2352     PVIRTIONET         pThis     = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    2353     PVIRTIONETCC       pThisCC   = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC);
    2354     uint16_t const     idxWorker = (uint16_t)(uintptr_t)pThread->pvUser;
    2355     PVIRTIONETWORKER   pWorker   = &pThis->aWorkers[idxWorker];
    2356     PVIRTIONETWORKERR3 pWorkerR3 = &pThisCC->aWorkers[idxWorker];
    2357     uint16_t const     idxQueue  = pWorkerR3->idxQueue;
    2358 
    2359     if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
    2360     {
    2361         return VINF_SUCCESS;
    2362     }
    2363     LogFunc(("%s worker thread started for %s\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
    2364     virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, false);
    2365     while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    2366     {
    2367         if (virtioCoreQueueIsEmpty(pDevIns, &pThis->Virtio, idxQueue))
    2368         {
    2369             /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */
    2370             virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, true);
    2371             ASMAtomicWriteBool(&pWorker->fSleeping, true);
    2372             bool fNotificationSent = ASMAtomicXchgBool(&pWorker->fNotified, false);
    2373             if (!fNotificationSent)
    2374             {
    2375                 Log10Func(("%s %s worker sleeping...\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
    2376                 Assert(ASMAtomicReadBool(&pWorker->fSleeping));
    2377                 int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pWorker->hEvtProcess, RT_INDEFINITE_WAIT);
    2378                 STAM_COUNTER_INC(&pThis->StatTransmitByThread);
    2379                 AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc);
    2380                 if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
    2381                     return VINF_SUCCESS;
    2382                 if (rc == VERR_INTERRUPTED)
    2383                 {
    2384                     virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, false);
    2385                     continue;
    2386                 }
    2387                 Log10Func(("%s %s worker woken\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
    2388                 ASMAtomicWriteBool(&pWorker->fNotified, false);
    2389             }
    2390             ASMAtomicWriteBool(&pWorker->fSleeping, false);
    2391             virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, false);
    2392         }
    2393 
    2394         /* Dispatch to the handler for the queue this worker is set up to drive */
    2395 
    2396         if (!pThisCC->fQuiescing)
    2397         {
    2398              if (IS_CTRL_QUEUE(idxQueue))
    2399              {
    2400                  Log10Func(("%s fetching next descriptor chain from %s\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
    2401                  PVIRTIO_DESC_CHAIN_T pDescChain = NULL;
    2402                  int rc = virtioCoreR3QueueGet(pDevIns, &pThis->Virtio, idxQueue, &pDescChain, true);
    2403                  if (rc == VERR_NOT_AVAILABLE)
    2404                  {
    2405                     Log10Func(("%s Nothing found in %s\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
    2406                     continue;
    2407                  }
    2408                  virtioNetR3Ctrl(pDevIns, pThis, pThisCC, pDescChain);
    2409                  virtioCoreR3DescChainRelease(&pThis->Virtio, pDescChain);
    2410              }
    2411              else if (IS_TX_QUEUE(idxQueue))
    2412              {
    2413                  Log10Func(("%s Notified of data to transmit\n", INSTANCE(pThis)));
    2414                  virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC,
    2415                                                    idxQueue, false /* fOnWorkerThread */);
    2416              }
    2417 
    2418              /* Rx queues aren't handled by our worker threads. Instead, the PDM network
    2419               * leaf driver invokes PDMINETWORKDOWN.pfnWaitReceiveAvail() callback,
    2420               * which waits until notified directly by virtioNetQueueNotified()
    2421               * that guest IN buffers have been added to receive virt queue.
    2422               */
    2423         }
    2424     }
    2425     return VINF_SUCCESS;
    2426 }
     2571    virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pTxQueue, true /*fOnWorkerThread*/);
     2572}
     2573
    24272574
    24282575#ifdef USING_CRITICAL_SECTION
     
    24312578    RT_NOREF(pDevIns, pThis, rcBusy);
    24322579    /* Original DevVirtioNet uses CS in attach/detach/link-up timer/tx timer/transmit */
    2433     LogFunc(("%s CS unimplemented. What does the critical section protect in orig driver??", INSTANCE(pThis)));
     2580    LogFunc(("%s CS unimplemented. What does the critical section protect in orig driver??", pThis->szInst));
    24342581    return VINF_SUCCESS;
    24352582}
     
    24382585{
    24392586    RT_NOREF(pDevIns, pThis);
    2440     LogFunc(("%s CS unimplemented. What does the critical section protect in orig driver??", INSTANCE(pThis)));
     2587    LogFunc(("%s CS unimplemented. What does the critical section protect in orig driver??", pThis->szInst));
    24412588}
    24422589#endif /* USING_CRITICAL_SECTION */
     
    24592606    LEAVE_CRITICAL_SECTION;
    24602607
    2461     LogFunc(("%s Link is up\n", INSTANCE(pThis)));
     2608    LogFunc(("%s Link is up\n", pThis->szInst));
    24622609
    24632610    if (pThisCC->pDrv)
     
    24882635        AssertRC(rc);
    24892636
    2490         LogFunc(("%s Link is down temporarily\n", INSTANCE(pThis)));
    2491     }
    2492 }
    2493 
    2494 /**
    2495  * @interface_method_impl{PDMINETWORKCONFIG,pfnGetLinkState}
    2496  */
    2497 static DECLCALLBACK(PDMNETWORKLINKSTATE) virtioNetR3NetworkConfig_GetLinkState(PPDMINETWORKCONFIG pInterface)
    2498 {
    2499     PVIRTIONETCC pThisCC = RT_FROM_MEMBER(pInterface, VIRTIONETCC, INetworkConfig);
    2500     PVIRTIONET pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVIRTIONET);
    2501 
    2502     return IS_LINK_UP(pThis) ? PDMNETWORKLINKSTATE_UP : PDMNETWORKLINKSTATE_DOWN;
     2637        LogFunc(("%s Link is down temporarily\n", pThis->szInst));
     2638    }
    25032639}
    25042640
     
    25172653    if (LogIs7Enabled())
    25182654    {
    2519         LogFunc(("%s", INSTANCE(pThis)));
     2655        LogFunc(("%s", pThis->szInst));
    25202656        switch(enmState)
    25212657        {
     
    25512687        if (fCachedLinkIsUp)
    25522688        {
    2553             Log(("%s Link is up\n", INSTANCE(pThis)));
     2689            Log(("%s Link is up\n", pThis->szInst));
    25542690            pThis->fCableConnected = true;
    25552691            SET_LINK_UP(pThis);
     
    25602696            /* The link was brought down explicitly, make sure it won't come up by timer.  */
    25612697            PDMDevHlpTimerStop(pDevIns, pThisCC->hLinkUpTimer);
    2562             Log(("%s Link is down\n", INSTANCE(pThis)));
     2698            Log(("%s Link is down\n", pThis->szInst));
    25632699            pThis->fCableConnected = false;
    25642700            SET_LINK_DOWN(pThis);
     
    25702706    return VINF_SUCCESS;
    25712707}
     2708/**
     2709 * @interface_method_impl{PDMINETWORKCONFIG,pfnGetLinkState}
     2710 */
     2711static DECLCALLBACK(PDMNETWORKLINKSTATE) virtioNetR3NetworkConfig_GetLinkState(PPDMINETWORKCONFIG pInterface)
     2712{
     2713    PVIRTIONETCC pThisCC = RT_FROM_MEMBER(pInterface, VIRTIONETCC, INetworkConfig);
     2714    PVIRTIONET pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVIRTIONET);
     2715
     2716    return IS_LINK_UP(pThis) ? PDMNETWORKLINKSTATE_UP : PDMNETWORKLINKSTATE_DOWN;
     2717}
    25722718
    25732719static int virtioNetR3DestroyWorkerThreads(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC)
    25742720{
    2575     Log10Func(("%s\n", INSTANCE(pThis)));
     2721    Log10Func(("%s\n", pThis->szInst));
    25762722    int rc = VINF_SUCCESS;
    25772723    for (unsigned idxWorker = 0; idxWorker < pThis->cWorkers; idxWorker++)
    25782724    {
    2579         PVIRTIONETWORKER pWorker = &pThis->aWorkers[idxWorker];
     2725        PVIRTIONETWORKER   pWorker   = &pThis->aWorkers[idxWorker];
     2726        PVIRTIONETWORKERR3 pWorkerR3 = &pThisCC->aWorkers[idxWorker];
     2727
    25802728        if (pWorker->hEvtProcess != NIL_SUPSEMEVENT)
    25812729        {
     
    25832731            pWorker->hEvtProcess = NIL_SUPSEMEVENT;
    25842732        }
    2585         if (pThisCC->aWorkers[idxWorker].pThread)
     2733        if (pWorkerR3->pThread)
    25862734        {
    25872735            int rcThread;
    2588             rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->aWorkers[idxWorker].pThread, &rcThread);
     2736            rc = PDMDevHlpThreadDestroy(pDevIns, pWorkerR3->pThread, &rcThread);
    25892737            if (RT_FAILURE(rc) || RT_FAILURE(rcThread))
    25902738                AssertMsgFailed(("%s Failed to destroythread rc=%Rrc rcThread=%Rrc\n", __FUNCTION__, rc, rcThread));
    2591            pThisCC->aWorkers[idxWorker].pThread = NULL;
     2739            pWorkerR3->pThread = NULL;
    25922740        }
    25932741    }
     
    25952743}
    25962744
    2597 static int virtioNetR3CreateOneWorkerThread(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC,
    2598                                             uint16_t idxWorker, uint16_t idxQueue)
    2599 {
    2600     Log10Func(("%s\n", INSTANCE(pThis)));
    2601     int rc = VINF_SUCCESS;
    2602     rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->aWorkers[idxWorker].hEvtProcess);
     2745static int virtioNetR3CreateOneWorkerThread(PPDMDEVINS pDevIns, PVIRTIONET pThis, uint16_t idxWorker,
     2746                                            PVIRTIONETWORKER pWorker, PVIRTIONETWORKERR3 pWorkerR3,
     2747                                            PVIRTIONETQUEUE pQueue)
     2748{
     2749    Log10Func(("%s\n", pThis->szInst));
     2750
     2751    int rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pWorker->hEvtProcess);
    26032752
    26042753    if (RT_FAILURE(rc))
     
    26062755                                   N_("DevVirtioNET: Failed to create SUP event semaphore"));
    26072756
    2608     LogFunc(("creating thread, idxWorker=%d, idxQueue=%d\n", idxWorker, idxQueue));
    2609     rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->aWorkers[idxWorker].pThread,
    2610                                (void *)(uintptr_t)idxWorker, virtioNetR3WorkerThread,
    2611                                virtioNetR3WakeupWorker, 0, RTTHREADTYPE_IO, VIRTQNAME(idxQueue));
    2612     if (rc != VINF_SUCCESS)
    2613     {
    2614         LogRel(("Error creating thread for Virtual Queue %s: %Rrc\n", VIRTQNAME(idxQueue), rc));
    2615         return rc;
    2616     }
    2617     pThisCC->aWorkers[idxWorker].idxQueue = idxQueue;
    2618     pThis->afQueueAttached[idxQueue] = true;
     2757    LogFunc(("creating thread for queue %s\n", pQueue->szName));
     2758
     2759    rc = PDMDevHlpThreadCreate(pDevIns, &pWorkerR3->pThread,
     2760                               (void *)pWorker, virtioNetR3WorkerThread,
     2761                               virtioNetR3WakeupWorker, 0, RTTHREADTYPE_IO, pQueue->szName);
     2762    if (RT_FAILURE(rc))
     2763        return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     2764                                   N_("Error creating thread for Virtual Queue %s\n"), pQueue->idx);
     2765
     2766    pWorker->pQueue    = pWorkerR3->pQueue = pQueue;
     2767    pWorker->idx       = pWorkerR3->idx    = idxWorker;
     2768    pQueue->pWorker    = pWorker;
     2769    pQueue->pWorkerR3  = pWorkerR3;
     2770    pWorker->fAssigned = true;
     2771
     2772    LogFunc(("%s pThread: %p\n", pQueue->szName, pWorkerR3->pThread));
     2773
    26192774    return rc;
    26202775}
     
    26222777static int virtioNetR3CreateWorkerThreads(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC)
    26232778{
    2624     Log10Func(("%s\n", INSTANCE(pThis)));
    2625 
    2626     int rc;
    2627     uint16_t idxWorker = 0;
    2628     for (uint16_t idxQueuePair = 0; idxQueuePair < pThis->cVirtqPairs; idxQueuePair++)
    2629     {
    2630         rc = virtioNetR3CreateOneWorkerThread(pDevIns, pThis, pThisCC, idxWorker, TXQIDX(idxQueuePair));
     2779
     2780#define CTRLWIDX 0 /* First worker is for the control queue */
     2781
     2782    Log10Func(("%s\n", pThis->szInst));
     2783
     2784    PVIRTIONETQUEUE pCtlQueue = &pThis->aQueues[CTRLQIDX];
     2785    int rc = virtioNetR3CreateOneWorkerThread(pDevIns, pThis, CTRLQIDX /* idxWorker */,
     2786                                              &pThis->aWorkers[CTRLWIDX], &pThisCC->aWorkers[CTRLWIDX], pCtlQueue);
     2787    AssertRCReturn(rc, rc);
     2788
     2789    pCtlQueue->fHasWorker = true;
     2790
     2791    uint16_t idxWorker = CTRLWIDX + 1;
     2792    for (uint16_t idxQueuePair = 0; idxQueuePair < pThis->cVirtqPairs; idxQueuePair++, idxWorker++)
     2793    {
     2794        PVIRTIONETQUEUE pTxQueue = &pThis->aQueues[TXQIDX(idxQueuePair)];
     2795        PVIRTIONETQUEUE pRxQueue = &pThis->aQueues[RXQIDX(idxQueuePair)];
     2796
     2797        rc = virtioNetR3CreateOneWorkerThread(pDevIns, pThis, idxWorker, &pThis->aWorkers[idxWorker],
     2798                                              &pThisCC->aWorkers[idxWorker], pTxQueue);
    26312799        AssertRCReturn(rc, rc);
    2632         idxWorker++;
    2633     }
    2634     rc = virtioNetR3CreateOneWorkerThread(pDevIns, pThis, pThisCC, idxWorker, CTRLQIDX);
    2635     pThis->cWorkers = idxWorker + 1;
     2800
     2801        pTxQueue->fHasWorker = true;
     2802        pRxQueue->fHasWorker = false;
     2803    }
     2804    pThis->cWorkers = pThis->cVirtqPairs + 1;
    26362805    return rc;
    26372806}
     2807
     2808/**
     2809 * @callback_method_impl{FNPDMTHREADDEV}
     2810 */
     2811static DECLCALLBACK(int) virtioNetR3WorkerThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     2812{
     2813    PVIRTIONET         pThis     = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
     2814    PVIRTIONETCC       pThisCC   = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC);
     2815    PVIRTIONETWORKER   pWorker   = (PVIRTIONETWORKER)pThread->pvUser;
     2816    PVIRTIONETQUEUE    pQueue    = pWorker->pQueue;
     2817
     2818    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     2819        return VINF_SUCCESS;
     2820
     2821    LogFunc(("%s worker thread started for %s\n", pThis->szInst, pQueue->szName));
     2822
     2823 /** @todo Race w/guest enabling/disabling guest notifications cyclically.
     2824           that causes the controlq activity to hang sporadically. See BugRef #8651, Comment #82 */
     2825
     2826    virtioCoreQueueNotifyEnable(&pThis->Virtio, pQueue->idx, true /* fEnable */);
     2827
     2828    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
     2829    {
     2830        if (IS_VIRTQ_EMPTY(pDevIns, &pThis->Virtio, pQueue->idx))
     2831        {
     2832            /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */
     2833            ASMAtomicWriteBool(&pWorker->fSleeping, true);
     2834            bool fNotificationSent = ASMAtomicXchgBool(&pWorker->fNotified, false);
     2835            if (!fNotificationSent)
     2836            {
     2837                Log10Func(("%s %s worker sleeping...\n\n", pThis->szInst, pQueue->szName));
     2838                Assert(ASMAtomicReadBool(&pWorker->fSleeping));
     2839                int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pWorker->hEvtProcess, RT_INDEFINITE_WAIT);
     2840                STAM_COUNTER_INC(&pThis->StatTransmitByThread);
     2841                AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc);
     2842                if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
     2843                    return VINF_SUCCESS;
     2844                if (rc == VERR_INTERRUPTED)
     2845                    continue;
     2846               ASMAtomicWriteBool(&pWorker->fNotified, false);
     2847            }
     2848            ASMAtomicWriteBool(&pWorker->fSleeping, false);
     2849        }
     2850
     2851        /* Dispatch to the handler for the queue this worker is set up to drive */
     2852
     2853        if (!pThisCC->fQuiescing)
     2854        {
     2855             if (pQueue->fCtlQueue)
     2856             {
     2857                 Log10Func(("%s %s worker woken. Fetching desc chain\n", pThis->szInst, pQueue->szName));
     2858                 PVIRTIO_DESC_CHAIN_T pDescChain = NULL;
     2859                 int rc = virtioCoreR3QueueGet(pDevIns, &pThis->Virtio, pQueue->idx, &pDescChain, true);
     2860                 if (rc == VERR_NOT_AVAILABLE)
     2861                 {
     2862                    Log10Func(("%s %s worker woken. Nothing found in queue/n", pThis->szInst, pQueue->szName));
     2863                    continue;
     2864                 }
     2865                 virtioNetR3Ctrl(pDevIns, pThis, pThisCC, pDescChain);
     2866                 virtioCoreR3DescChainRelease(&pThis->Virtio, pDescChain);
     2867             }
     2868             else /* Must be Tx queue */
     2869             {
     2870                 Log10Func(("%s %s worker woken. Queue has data to transmit\n",  pThis->szInst, pQueue->szName));
     2871                 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pQueue, false /* fOnWorkerThread */);
     2872             }
     2873
     2874             /* Rx queues aren't handled by our worker threads. Instead, the PDM network
     2875              * leaf driver invokes PDMINETWORKDOWN.pfnWaitReceiveAvail() callback,
     2876              * which waits until notified directly by virtioNetQueueNotified()
     2877              * that guest IN buffers have been added to receive virt queue.
     2878              */
     2879        }
     2880    }
     2881    Log10(("%s %s worker thread exiting\n", pThis->szInst, pQueue->szName));
     2882    return VINF_SUCCESS;
     2883}
     2884
    26382885/**
    26392886 * @callback_method_impl{VIRTIOCORER3,pfnStatusChanged}
     
    26492896    {
    26502897        LogFunc(("%s VirtIO ready\n-----------------------------------------------------------------------------------------\n",
    2651                  INSTANCE(pThis)));
     2898                 pThis->szInst));
     2899
     2900        pThis->fNegotiatedFeatures = virtioCoreGetAcceptedFeatures(pVirtio);
     2901
     2902#ifdef LOG_ENABLED
     2903        virtioCorePrintFeatures(pVirtio, NULL);
     2904        virtioNetPrintFeatures(pThis, NULL);
     2905#endif
     2906
    26522907        pThis->virtioNetConfig.uStatus = pThis->fCableConnected ? VIRTIONET_F_LINK_UP : 0;
    26532908
    2654         pThis->fResetting    = false;
    2655         pThisCC->fQuiescing  = false;
    2656         pThis->fNegotiatedFeatures = virtioCoreGetAcceptedFeatures(pVirtio);
    2657 #ifdef LOG_ENABLED
    2658         virtioPrintFeatures(pVirtio);
    2659         virtioNetPrintFeatures(pThis);
    2660 #endif
     2909        pThis->fResetting = false;
     2910        pThisCC->fQuiescing = false;
     2911
    26612912        for (unsigned idxQueue = 0; idxQueue < pThis->cVirtQueues; idxQueue++)
    26622913        {
    2663             (void) virtioCoreR3QueueAttach(&pThis->Virtio, idxQueue, VIRTQNAME(idxQueue));
    2664             pThis->afQueueAttached[idxQueue] = true;
    2665             if (virtioCoreQueueIsEmpty(pThisCC->pDevIns, &pThis->Virtio, idxQueue))
    2666                 virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, true);
     2914            PVIRTIONETQUEUE pQueue = &pThis->aQueues[idxQueue];
     2915            pQueue->idx = idxQueue;
     2916            (void) virtioCoreR3QueueAttach(&pThis->Virtio, pQueue->idx, pQueue->szName);
     2917            pQueue->fAttachedToVirtioCore = true;
     2918            if (IS_VIRTQ_EMPTY(pThisCC->pDevIns, &pThis->Virtio, pQueue->idx))
     2919                virtioCoreQueueNotifyEnable(&pThis->Virtio, pQueue->idx, true /* fEnable */);
    26672920        }
    26682921    }
    26692922    else
    26702923    {
    2671         LogFunc(("%s VirtIO is resetting\n", INSTANCE(pThis)));
     2924        LogFunc(("%s VirtIO is resetting\n", pThis->szInst));
    26722925
    26732926        pThis->virtioNetConfig.uStatus = pThis->fCableConnected ? VIRTIONET_F_LINK_UP : 0;
    2674         Log7Func(("%s Link is %s\n", INSTANCE(pThis), pThis->fCableConnected ? "up" : "down"));
     2927        Log7Func(("%s Link is %s\n", pThis->szInst, pThis->fCableConnected ? "up" : "down"));
    26752928
    26762929        pThis->fPromiscuous         = true;
     
    26902943        pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, true);
    26912944
    2692         for (unsigned idxQueue = 0; idxQueue < pThis->cVirtQueues; idxQueue++)
    2693             pThis->afQueueAttached[idxQueue] = false;
     2945        for (uint16_t idxQueue = 0; idxQueue < pThis->cVirtQueues; idxQueue++)
     2946            pThis->aQueues[idxQueue].fAttachedToVirtioCore = false;
    26942947    }
    26952948}
     
    27092962    PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC);
    27102963
    2711     Log7Func(("%s\n", INSTANCE(pThis)));
     2964    Log7Func(("%s\n", pThis->szInst));
    27122965    AssertLogRelReturnVoid(iLUN == 0);
    27132966
     
    27372990    RT_NOREF(fFlags);
    27382991
    2739     Log7Func(("%s", INSTANCE(pThis)));
     2992    Log7Func(("%s", pThis->szInst));
    27402993
    27412994    AssertLogRelReturn(iLUN == 0, VERR_PDM_NO_SUCH_LUN);
     
    27543007    else if (   rc == VERR_PDM_NO_ATTACHED_DRIVER
    27553008             || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
    2756                     Log(("%s No attached driver!\n", INSTANCE(pThis)));
     3009                    Log(("%s No attached driver!\n", pThis->szInst));
    27573010
    27583011    LEAVE_CRITICAL_SECTION;
     
    27793032{
    27803033    PVIRTIONETR3 pThisCC = RT_FROM_MEMBER(pInterface, VIRTIONETCC, IBase);
    2781 
     3034LogFunc(("pInterface=%p %s\n", pInterface, pszIID));
    27823035    PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKDOWN,   &pThisCC->INetworkDown);
    27833036    PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKCONFIG, &pThisCC->INetworkConfig);
     
    27973050    PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC);
    27983051
    2799     Log(("%s Destroying instance\n", INSTANCE(pThis)));
     3052    Log(("%s Destroying instance\n", pThis->szInst));
    28003053
    28013054    if (pThis->hEventRxDescAvail != NIL_SUPSEMEVENT)
     
    28283081    Log7Func(("PDM device instance: %d\n", iInstance));
    28293082
    2830     RTStrPrintf(pThis->szInstanceName, sizeof(pThis->szInstanceName), "VIRTIONET%d", iInstance);
     3083    RTStrPrintf(pThis->szInst, sizeof(pThis->szInst), "VNET%d", iInstance);
     3084
     3085// Temporary for less logging clutter for singled-instance debugging
     3086*pThis->szInst = '\0';
    28313087
    28323088    pThisCC->pDevIns     = pDevIns;
     
    28453101    pThisCC->INetworkConfig.pfnSetLinkState   = virtioNetR3NetworkConfig_SetLinkState;
    28463102
     3103    pThis->hEventRxDescAvail = NIL_SUPSEMEVENT;
     3104
    28473105    /*
    28483106     * Validate configuration.
     
    28723130    if (pThis->cMsLinkUpDelay > 5000 || pThis->cMsLinkUpDelay < 100)
    28733131        LogRel(("%s WARNING! Link up delay is set to %u seconds!\n",
    2874                 INSTANCE(pThis), pThis->cMsLinkUpDelay / 1000));
    2875 
    2876     Log(("%s Link up delay is set to %u seconds\n", INSTANCE(pThis), pThis->cMsLinkUpDelay / 1000));
     3132                pThis->szInst, pThis->cMsLinkUpDelay / 1000));
     3133
     3134    Log(("%s Link up delay is set to %u seconds\n", pThis->szInst, pThis->cMsLinkUpDelay / 1000));
    28773135
    28783136    /* Copy the MAC address configured for the VM to the MMIO accessible Virtio dev-specific config area */
     
    28863144     */
    28873145
    2888 #if FEATURE_OFFERED(STATUS)
    2889     pThis->virtioNetConfig.uStatus = 0;
    2890 #endif
    2891 
    2892 #if FEATURE_OFFERED(MQ)
    2893     pThis->virtioNetConfig.uMaxVirtqPairs = VIRTIONET_MAX_QPAIRS;
    2894 #endif
     3146#   if FEATURE_OFFERED(STATUS)
     3147        pThis->virtioNetConfig.uStatus = 0;
     3148#   endif
     3149
     3150#   if FEATURE_OFFERED(MQ)
     3151        pThis->virtioNetConfig.uMaxVirtqPairs = VIRTIONET_MAX_QPAIRS;
     3152#   endif
    28953153
    28963154    /* Initialize the generic Virtio core: */
     
    29103168
    29113169    /*
     3170     * Create the semaphore that will be used to synchronize/throttle
     3171     * the downstream LUN's Rx waiter thread.
     3172     */
     3173    rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEventRxDescAvail);
     3174    if (RT_FAILURE(rc))
     3175        return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to create event semaphore"));
     3176
     3177    /*
    29123178     * Initialize VirtIO core. This will result in a "status changed" callback
    29133179     * when VirtIO is ready, at which time the Rx queue and ctrl queue worker threads will be created.
    29143180     */
    2915     rc = virtioCoreR3Init(pDevIns, &pThis->Virtio, &pThisCC->Virtio, &VirtioPciParams, INSTANCE(pThis),
     3181    rc = virtioCoreR3Init(pDevIns, &pThis->Virtio, &pThisCC->Virtio, &VirtioPciParams, pThis->szInst,
    29163182                          VIRTIONET_HOST_FEATURES_OFFERED,
    29173183                          &pThis->virtioNetConfig /*pvDevSpecificCap*/, sizeof(pThis->virtioNetConfig));
     
    29233189        return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-net: Required features not successfully negotiated."));
    29243190
    2925     pThis->cVirtqPairs =   pThis->fNegotiatedFeatures & VIRTIONET_F_MQ
    2926                          ? pThis->virtioNetConfig.uMaxVirtqPairs : 1;
     3191    pThis->cVirtqPairs =  (pThis->fNegotiatedFeatures & VIRTIONET_F_MQ)
     3192                         ? pThis->virtioNetConfig.uMaxVirtqPairs  : 1;
    29273193
    29283194    pThis->cVirtQueues += pThis->cVirtqPairs * 2 + 1;
     
    29363202     */
    29373203    virtioNetR3SetVirtqNames(pThis);
     3204    pThis->aQueues[CTRLQIDX].fCtlQueue = true;
    29383205
    29393206    /*
     
    29453212
    29463213    /*
    2947      * Create the semaphore that will be used to synchronize/throttle
    2948      * the downstream LUN's Rx waiter thread.
    2949      */
    2950     rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEventRxDescAvail);
    2951     if (RT_FAILURE(rc))
    2952         return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to create event semaphore"));
    2953 
    2954     /*
    29553214     * Attach network driver instance
    29563215     */
     
    29643223    else if (   rc == VERR_PDM_NO_ATTACHED_DRIVER
    29653224             || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
    2966                     Log(("%s No attached driver!\n", INSTANCE(pThis)));
     3225                    Log(("%s No attached driver!\n", pThis->szInst));
    29673226
    29683227    /*
     
    29823241                              virtioNetR3SaveExec, virtioNetR3LoadExec);
    29833242    AssertRCReturn(rc, rc);
    2984 
    2985 
    29863243
    29873244   /*
     
    30173274     */
    30183275    char szTmp[128];
    3019     RTStrPrintf(szTmp, sizeof(szTmp), "%s%u", pDevIns->pReg->szName, pDevIns->iInstance);
    3020     PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-net info", virtioNetR3Info);
     3276    rc = PDMDevHlpDBGFInfoRegister(pDevIns, "virtio-net", "Display virtio-net info (help, net, features, state, pointers, queues, all)", virtioNetR3Info);
     3277    if (RT_FAILURE(rc))
     3278        LogRel(("Failed to register DBGF info for device %s\n", szTmp));
    30213279    return rc;
    30223280}
  • trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp

    r84504 r84774  
    112112#define VIRTQ_REQ_BASE                              2           /**< Spec-defined base index of request queues       */
    113113
    114 #define VIRTQNAME(qIdx) (pThis->aszVirtqNames[qIdx])            /**< Macro to get queue name from its index          */
    115 #define CBVIRTQNAME(qIdx) RTStrNLen(VIRTQNAME(qIdx), sizeof(VIRTQNAME(qIdx)))
    116 
    117 #define IS_REQ_QUEUE(qIdx) (qIdx >= VIRTQ_REQ_BASE && qIdx < VIRTIOSCSI_QUEUE_CNT)
     114#define VIRTQNAME(idxQueue) (pThis->aszVirtqNames[idxQueue])            /**< Macro to get queue name from its index          */
     115#define CBVIRTQNAME(idxQueue) RTStrNLen(VIRTQNAME(idxQueue), sizeof(VIRTQNAME(idxQueue)))
     116
     117#define IS_REQ_QUEUE(idxQueue) (idxQueue >= VIRTQ_REQ_BASE && idxQueue < VIRTIOSCSI_QUEUE_CNT)
    118118
    119119#define VIRTIO_IS_IN_DIRECTION(pMediaExTxDirEnumValue) \
     
    123123    ((pMediaExTxDirEnumValue) == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE)
    124124
     125#define IS_VIRTQ_EMPTY(pDevIns, pVirtio, idxQueue) \
     126            (virtioCoreQueueAvailCount(pDevIns, pVirtio, idxQueue) == 0)
    125127
    126128/*********************************************************************************************************************************
     
    355357{
    356358    R3PTRTYPE(PPDMTHREAD)           pThread;                    /**< pointer to worker thread's handle                 */
    357     uint16_t                        auRedoDescs[VIRTQ_MAX_SIZE];/**< List of previously suspended reqs to re-submit    */
     359    uint16_t                        auRedoDescs[VIRTQ_MAX_ENTRIES];/**< List of previously suspended reqs to re-submit    */
    358360    uint16_t                        cRedoDescs;                 /**< Number of redo desc chain head desc idxes in list */
    359361} VIRTIOSCSIWORKERR3;
     
    554556    PDMMEDIAEXIOREQ                hIoReq;                      /**< Handle of I/O request                             */
    555557    PVIRTIOSCSITARGET              pTarget;                     /**< Target                                            */
    556     uint16_t                       qIdx;                        /**< Index of queue this request arrived on            */
     558    uint16_t                       idxQueue;                        /**< Index of queue this request arrived on            */
    557559    PVIRTIO_DESC_CHAIN_T           pDescChain;                  /**< Prepared desc chain pulled from virtq avail ring  */
    558560    size_t                         cbDataIn;                    /**< size of dataout buffer                            */
     
    573575 * @todo this causes burn if I prefix with at-sign. This callback is in VIRTIOCORER0 and VIRTIOCORER3
    574576 */
    575 static DECLCALLBACK(void) virtioScsiNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t qIdx)
     577static DECLCALLBACK(void) virtioScsiNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
    576578{
    577579
     
    579581    PVIRTIOSCSI pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    580582
    581     AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT);
    582     PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx];
     583    AssertReturnVoid(idxQueue < VIRTIOSCSI_QUEUE_CNT);
     584    PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[idxQueue];
    583585
    584586#if defined (IN_RING3) && defined (LOG_ENABLED)
     
    586588#endif
    587589
    588     if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx))
    589     {
    590         Log6Func(("%s has available data\n", VIRTQNAME(qIdx)));
     590    if (idxQueue == CONTROLQ_IDX || IS_REQ_QUEUE(idxQueue))
     591    {
     592        Log6Func(("%s has available data\n", VIRTQNAME(idxQueue)));
    591593        /* Wake queue's worker thread up if sleeping */
    592594        if (!ASMAtomicXchgBool(&pWorker->fNotified, true))
     
    594596            if (ASMAtomicReadBool(&pWorker->fSleeping))
    595597            {
    596                 Log6Func(("waking %s worker.\n", VIRTQNAME(qIdx)));
     598                Log6Func(("waking %s worker.\n", VIRTQNAME(idxQueue)));
    597599                int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess);
    598600                AssertRC(rc);
     
    600602        }
    601603    }
    602     else if (qIdx == EVENTQ_IDX)
    603     {
    604         Log3Func(("Driver queued buffer(s) to %s\n", VIRTQNAME(qIdx)));
     604    else if (idxQueue == EVENTQ_IDX)
     605    {
     606        Log3Func(("Driver queued buffer(s) to %s\n", VIRTQNAME(idxQueue)));
    605607//        if (ASMAtomicXchgBool(&pThis->fEventsMissed, false))
    606608//            virtioScsiR3ReportEventsMissed(pDevIns, pThis, 0);
    607609    }
    608610    else
    609         LogFunc(("Unexpected queue idx (ignoring): %d\n", qIdx));
     611        LogFunc(("Unexpected queue idx (ignoring): %d\n", idxQueue));
    610612}
    611613
     
    618620    RTStrCopy(pThis->aszVirtqNames[CONTROLQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq");
    619621    RTStrCopy(pThis->aszVirtqNames[EVENTQ_IDX],   VIRTIO_MAX_QUEUE_NAME_SIZE, "eventq");
    620     for (uint16_t qIdx = VIRTQ_REQ_BASE; qIdx < VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++)
    621         RTStrPrintf(pThis->aszVirtqNames[qIdx], VIRTIO_MAX_QUEUE_NAME_SIZE,
    622                     "requestq<%d>", qIdx - VIRTQ_REQ_BASE);
     622    for (uint16_t idxQueue = VIRTQ_REQ_BASE; idxQueue < VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_QUEUE_CNT; idxQueue++)
     623        RTStrPrintf(pThis->aszVirtqNames[idxQueue], VIRTIO_MAX_QUEUE_NAME_SIZE,
     624                    "requestq<%d>", idxQueue - VIRTQ_REQ_BASE);
    623625}
    624626
     
    808810 * @param   pThis       VirtIO SCSI shared instance data.
    809811 * @param   pThisCC     VirtIO SCSI ring-3 instance data.
    810  * @param   qIdx        Queue index
     812 * @param   idxQueue        Queue index
    811813 * @param   pDescChain  Pointer to pre-processed descriptor chain pulled from virtq
    812814 * @param   pRespHdr    Response header
     
    816818 * @returns VINF_SUCCESS
    817819 */
    818 static int virtioScsiR3ReqErr(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, uint16_t qIdx,
     820static int virtioScsiR3ReqErr(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, uint16_t idxQueue,
    819821                              PVIRTIO_DESC_CHAIN_T pDescChain, REQ_RESP_HDR_T *pRespHdr, uint8_t *pbSense,
    820822                              size_t cbSenseCfg)
     
    850852        pRespHdr->uResponse = VIRTIOSCSI_S_RESET;
    851853
    852     virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, qIdx, &ReqSgBuf, pDescChain, true /* fFence */);
    853     virtioCoreQueueSync(pDevIns, &pThis->Virtio, qIdx);
     854    virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, idxQueue, &ReqSgBuf, pDescChain, true /* fFence */);
     855    virtioCoreQueueSync(pDevIns, &pThis->Virtio, idxQueue);
    854856
    855857    if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThisCC->fQuiescing)
     
    869871 * @param   pThis       VirtIO SCSI shared instance data.
    870872 * @param   pThisCC     VirtIO SCSI ring-3 instance data.
    871  * @param   qIdx        Queue index
     873 * @param   idxQueue        Queue index
    872874 * @param   pDescChain  Pointer to pre-processed descriptor chain pulled from virtq
    873875 * @param   cbResidual  The number of residual bytes or something like that.
     
    880882 * @returns VINF_SUCCESS
    881883 */
    882 static int virtioScsiR3ReqErr4(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, uint16_t qIdx,
     884static int virtioScsiR3ReqErr4(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, uint16_t idxQueue,
    883885                               PVIRTIO_DESC_CHAIN_T pDescChain, size_t cbResidual, uint8_t bStatus, uint8_t bResponse,
    884886                               uint8_t *pbSense, size_t cbSense, size_t cbSenseCfg)
     
    891893    RespHdr.uResponse        = bResponse;
    892894
    893     return virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, qIdx, pDescChain, &RespHdr, pbSense, cbSenseCfg);
     895    return virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, idxQueue, pDescChain, &RespHdr, pbSense, cbSenseCfg);
    894896}
    895897
     
    10131015        respHdr.uResidual  = pReq->cbDataIn & UINT32_MAX;
    10141016
    1015         virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, pReq->qIdx, pReq->pDescChain, &respHdr, abSense,
     1017        virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, pReq->idxQueue, pReq->pDescChain, &respHdr, abSense,
    10161018                           RT_MIN(pThis->virtioScsiConfig.uSenseSize, VIRTIOSCSI_SENSE_SIZE_MAX));
    10171019    }
     
    10391041                        VERR_BUFFER_OVERFLOW);
    10401042
    1041         virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, pReq->qIdx, &ReqSgBuf, pReq->pDescChain, true /* fFence TBD */);
    1042         virtioCoreQueueSync(pDevIns, &pThis->Virtio, pReq->qIdx);
     1043        virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, pReq->idxQueue, &ReqSgBuf, pReq->pDescChain, true /* fFence TBD */);
     1044        virtioCoreQueueSync(pDevIns, &pThis->Virtio, pReq->idxQueue);
    10431045
    10441046        Log2(("-----------------------------------------------------------------------------------------\n"));
     
    10851087        cbCopied = RT_MIN(pSgBuf->cbSegLeft,  pSgPhysReturn->cbSegLeft);
    10861088        Assert(cbCopied > 0);
    1087         PDMDevHlpPCIPhysWriteUser(pDevIns, pSgPhysReturn->gcPhysCur, pSgBuf->pvSegCur, cbCopied);
     1089        PDMDevHlpPCIPhysWriteUser(pDevIns, pSgPhysReturn->GCPhysCur, pSgBuf->pvSegCur, cbCopied);
    10881090        RTSgBufAdvance(pSgBuf, cbCopied);
    10891091        virtioCoreSgBufAdvance(pSgPhysReturn, cbCopied);
     
    11231125        cbCopied = RT_MIN(pSgBuf->cbSegLeft, pSgPhysSend->cbSegLeft);
    11241126        Assert(cbCopied > 0);
    1125         PDMDevHlpPCIPhysReadUser(pDevIns, pSgPhysSend->gcPhysCur, pSgBuf->pvSegCur, cbCopied);
     1127        PDMDevHlpPCIPhysReadUser(pDevIns, pSgPhysSend->GCPhysCur, pSgBuf->pvSegCur, cbCopied);
    11261128        RTSgBufAdvance(pSgBuf, cbCopied);
    11271129        virtioCoreSgBufAdvance(pSgPhysSend, cbCopied);
     
    11411143 */
    11421144static int virtioScsiR3ReqSubmit(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC,
    1143                                  uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain)
     1145                                 uint16_t idxQueue, PVIRTIO_DESC_CHAIN_T pDescChain)
    11441146{
    11451147
     
    12291231    {
    12301232        Log2Func(("Error submitting request, bad LUN format\n"));
    1231         return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, qIdx, pDescChain, cbDataIn + cbDataOut, 0 /*bStatus*/,
     1233        return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxQueue, pDescChain, cbDataIn + cbDataOut, 0 /*bStatus*/,
    12321234                                   VIRTIOSCSI_S_FAILURE, NULL /*pbSense*/, 0 /*cbSense*/, cbSenseCfg);
    12331235    }
     
    12441246                              0, SCSI_SENSE_ILLEGAL_REQUEST,
    12451247                              0, 0, 0, 0, 10, SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED, 0, 0 };
    1246         return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, qIdx, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,
     1248        return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxQueue, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,
    12471249                                   VIRTIOSCSI_S_BAD_TARGET, abSense, sizeof(abSense), cbSenseCfg);
    12481250    }
     
    12551257                              0, SCSI_SENSE_ILLEGAL_REQUEST,
    12561258                              0, 0, 0, 0, 10, SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED, 0, 0 };
    1257         return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, qIdx, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,
     1259        return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxQueue, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,
    12581260                                   VIRTIOSCSI_S_OK, abSense, sizeof(abSense), cbSenseCfg);
    12591261    }
     
    12631265    {
    12641266        Log2Func(("Aborting req submission because reset is in progress\n"));
    1265         return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, qIdx, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_OK,
     1267        return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxQueue, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_OK,
    12661268                                   VIRTIOSCSI_S_RESET, NULL /*pbSense*/, 0 /*cbSense*/, cbSenseCfg);
    12671269    }
     
    12741276        uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED,
    12751277                              0, SCSI_SENSE_ILLEGAL_REQUEST, 0, 0, 0, 0, 10, 0, 0, 0 };
    1276         return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, qIdx, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,
     1278        return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxQueue, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,
    12771279                                   VIRTIOSCSI_S_FAILURE, abSense, sizeof(abSense), cbSenseCfg);
    12781280    }
     
    12921294    pReq->hIoReq      = hIoReq;
    12931295    pReq->pTarget     = pTarget;
    1294     pReq->qIdx        = qIdx;
     1296    pReq->idxQueue        = idxQueue;
    12951297    pReq->cbDataIn    = cbDataIn;
    12961298    pReq->cbDataOut   = cbDataOut;
     
    13391341        respHdr.uResponse  = VIRTIOSCSI_S_FAILURE;
    13401342        respHdr.uResidual  = (cbDataIn + cbDataOut) & UINT32_MAX;
    1341         virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, qIdx, pDescChain, &respHdr, abSense, cbSenseCfg);
     1343        virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, idxQueue, pDescChain, &respHdr, abSense, cbSenseCfg);
    13421344        virtioScsiR3FreeReq(pTarget, pReq);
    13431345    }
     
    13531355 * @param   pThis       VirtIO SCSI shared instance data.
    13541356 * @param   pThisCC     VirtIO SCSI ring-3 instance data.
    1355  * @param   qIdx        CONTROLQ_IDX
     1357 * @param   idxQueue    CONTROLQ_IDX
    13561358 * @param   pDescChain  Descriptor chain to process.
    13571359 */
    13581360static int virtioScsiR3Ctrl(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC,
    1359                             uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain)
     1361                            uint16_t idxQueue, PVIRTIO_DESC_CHAIN_T pDescChain)
    13601362{
    13611363    AssertReturn(pDescChain->cbPhysSend >= RT_MIN(sizeof(VIRTIOSCSI_CTRL_AN_T),
     
    13981400            uint32_t uScsiLun = RT_MAKE_U16(ScsiCtrlUnion.Tmf.abScsiLun[3], ScsiCtrlUnion.Tmf.abScsiLun[2]) & 0x3fff;
    13991401            Log2Func(("[%s] (Target: %d LUN: %d)  Task Mgt Function: %s\n",
    1400                       VIRTQNAME(qIdx), uTarget, uScsiLun, virtioGetTMFTypeText(ScsiCtrlUnion.Tmf.uSubtype)));
     1402                      VIRTQNAME(idxQueue), uTarget, uScsiLun, virtioGetTMFTypeText(ScsiCtrlUnion.Tmf.uSubtype)));
    14011403
    14021404            if (uTarget >= pThis->cTargets || !pThisCC->paTargetInstances[uTarget].fPresent)
     
    14591461                virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), ScsiCtrlUnion.AsyncNotify.fEventsRequested);
    14601462                Log2Func(("[%s] (Target: %d LUN: %d)  Async. Notification Query: %s\n",
    1461                           VIRTQNAME(qIdx), uTarget, uScsiLun, szTypeText));
     1463                          VIRTQNAME(idxQueue), uTarget, uScsiLun, szTypeText));
    14621464            }
    14631465#endif
     
    14841486                virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), ScsiCtrlUnion.AsyncNotify.fEventsRequested);
    14851487                Log2Func(("[%s] (Target: %d LUN: %d)  Async. Notification Subscribe: %s\n",
    1486                           VIRTQNAME(qIdx), uTarget, uScsiLun, szTypeText));
     1488                          VIRTQNAME(idxQueue), uTarget, uScsiLun, szTypeText));
    14871489            }
    14881490#endif
     
    15051507        default:
    15061508        {
    1507             LogFunc(("Unknown control type extracted from %s: %u\n", VIRTQNAME(qIdx), ScsiCtrlUnion.Type.uType));
     1509            LogFunc(("Unknown control type extracted from %s: %u\n", VIRTQNAME(idxQueue), ScsiCtrlUnion.Type.uType));
    15081510
    15091511            bResponse = VIRTIOSCSI_S_FAILURE;
     
    15241526    RTSgBufInit(&ReqSgBuf, aReqSegs, cSegs);
    15251527
    1526     virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, qIdx, &ReqSgBuf, pDescChain, true /*fFence*/);
    1527     virtioCoreQueueSync(pDevIns, &pThis->Virtio, qIdx);
     1528    virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, idxQueue, &ReqSgBuf, pDescChain, true /*fFence*/);
     1529    virtioCoreQueueSync(pDevIns, &pThis->Virtio, idxQueue);
    15281530
    15291531    return VINF_SUCCESS;
     
    15441546static DECLCALLBACK(int) virtioScsiR3WorkerThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    15451547{
    1546     uint16_t const      qIdx      = (uint16_t)(uintptr_t)pThread->pvUser;
     1548    uint16_t const      idxQueue  = (uint16_t)(uintptr_t)pThread->pvUser;
    15471549    PVIRTIOSCSI         pThis     = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    15481550    PVIRTIOSCSICC       pThisCC   = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);
    1549     PVIRTIOSCSIWORKER   pWorker   = &pThis->aWorkers[qIdx];
    1550     PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[qIdx];
     1551    PVIRTIOSCSIWORKER   pWorker   = &pThis->aWorkers[idxQueue];
     1552    PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[idxQueue];
    15511553
    15521554    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     
    15551557    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    15561558    {
    1557         if (!pWorkerR3->cRedoDescs && virtioCoreQueueIsEmpty(pDevIns, &pThis->Virtio, qIdx))
     1559        if (!pWorkerR3->cRedoDescs && IS_VIRTQ_EMPTY(pDevIns, &pThis->Virtio, idxQueue))
    15581560        {
    15591561            /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */
     
    15621564            if (!fNotificationSent)
    15631565            {
    1564                 Log6Func(("%s worker sleeping...\n", VIRTQNAME(qIdx)));
     1566                Log6Func(("%s worker sleeping...\n", VIRTQNAME(idxQueue)));
    15651567                Assert(ASMAtomicReadBool(&pWorker->fSleeping));
    15661568                int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pWorker->hEvtProcess, RT_INDEFINITE_WAIT);
     
    15701572                if (rc == VERR_INTERRUPTED)
    15711573                    continue;
    1572                 Log6Func(("%s worker woken\n", VIRTQNAME(qIdx)));
     1574                Log6Func(("%s worker woken\n", VIRTQNAME(idxQueue)));
    15731575                ASMAtomicWriteBool(&pWorker->fNotified, false);
    15741576            }
     
    15761578        }
    15771579
    1578         if (!pThis->afQueueAttached[qIdx])
     1580        if (!pThis->afQueueAttached[idxQueue])
    15791581        {
    1580             LogFunc(("%s queue not attached, worker aborting...\n", VIRTQNAME(qIdx)));
     1582            LogFunc(("%s queue not attached, worker aborting...\n", VIRTQNAME(idxQueue)));
    15811583            break;
    15821584        }
     
    15871589             {
    15881590                  PVIRTIO_DESC_CHAIN_T pDescChain;
    1589                   int rc = virtioCoreR3DescChainGet(pDevIns, &pThis->Virtio, qIdx,
     1591                  int rc = virtioCoreR3DescChainGet(pDevIns, &pThis->Virtio, idxQueue,
    15901592                                                    pWorkerR3->auRedoDescs[i], &pDescChain);
    15911593                  if (RT_FAILURE(rc))
    15921594                      LogRel(("Error fetching desc chain to redo, %Rrc", rc));
    15931595
    1594                   rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, qIdx, pDescChain);
     1596                  rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, idxQueue, pDescChain);
    15951597                  if (RT_FAILURE(rc))
    15961598                      LogRel(("Error submitting req packet, resetting %Rrc", rc));
     
    16001602             pWorkerR3->cRedoDescs = 0;
    16011603
    1602              Log6Func(("fetching next descriptor chain from %s\n", VIRTQNAME(qIdx)));
     1604             Log6Func(("fetching next descriptor chain from %s\n", VIRTQNAME(idxQueue)));
    16031605             PVIRTIO_DESC_CHAIN_T pDescChain = NULL;
    1604              int rc = virtioCoreR3QueueGet(pDevIns, &pThis->Virtio, qIdx, &pDescChain, true);
     1606             int rc = virtioCoreR3QueueGet(pDevIns, &pThis->Virtio, idxQueue, &pDescChain, true);
    16051607             if (rc == VERR_NOT_AVAILABLE)
    16061608             {
    1607                  Log6Func(("Nothing found in %s\n", VIRTQNAME(qIdx)));
     1609                 Log6Func(("Nothing found in %s\n", VIRTQNAME(idxQueue)));
    16081610                 continue;
    16091611             }
    16101612
    16111613             AssertRC(rc);
    1612              if (qIdx == CONTROLQ_IDX)
    1613                  virtioScsiR3Ctrl(pDevIns, pThis, pThisCC, qIdx, pDescChain);
     1614             if (idxQueue == CONTROLQ_IDX)
     1615                 virtioScsiR3Ctrl(pDevIns, pThis, pThisCC, idxQueue, pDescChain);
    16141616             else /* request queue index */
    16151617             {
    1616                  rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, qIdx, pDescChain);
     1618                 rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, idxQueue, pDescChain);
    16171619                 if (RT_FAILURE(rc))
    16181620                     LogRel(("Error submitting req packet, resetting %Rrc", rc));
     
    19641966
    19651967    virtioScsiSetVirtqNames(pThis);
    1966     for (int qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
    1967         pHlp->pfnSSMGetBool(pSSM, &pThis->afQueueAttached[qIdx]);
     1968    for (int idxQueue = 0; idxQueue < VIRTIOSCSI_QUEUE_CNT; idxQueue++)
     1969        pHlp->pfnSSMGetBool(pSSM, &pThis->afQueueAttached[idxQueue]);
    19681970
    19691971    pHlp->pfnSSMGetU32(pSSM,  &pThis->virtioScsiConfig.uNumQueues);
     
    19992001        rc = pHlp->pfnSSMGetU16(pSSM, &cReqsRedo);
    20002002        AssertRCReturn(rc, rc);
    2001         AssertReturn(cReqsRedo < VIRTQ_MAX_SIZE,
     2003        AssertReturn(cReqsRedo < VIRTQ_MAX_ENTRIES,
    20022004                     pHlp->pfnSSMSetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
    20032005                                              N_("Bad count of I/O transactions to re-do in saved state (%#x, max %#x - 1)"),
    2004                                               cReqsRedo, VIRTQ_MAX_SIZE));
    2005 
    2006         for (uint16_t qIdx = VIRTQ_REQ_BASE; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
     2006                                              cReqsRedo, VIRTQ_MAX_ENTRIES));
     2007
     2008        for (uint16_t idxQueue = VIRTQ_REQ_BASE; idxQueue < VIRTIOSCSI_QUEUE_CNT; idxQueue++)
    20072009        {
    2008             PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[qIdx];
     2010            PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[idxQueue];
    20092011            pWorkerR3->cRedoDescs = 0;
    20102012        }
     
    20122014        for (int i = 0; i < cReqsRedo; i++)
    20132015        {
    2014             uint16_t qIdx;
    2015             rc = pHlp->pfnSSMGetU16(pSSM, &qIdx);
     2016            uint16_t idxQueue;
     2017            rc = pHlp->pfnSSMGetU16(pSSM, &idxQueue);
    20162018            AssertRCReturn(rc, rc);
    2017             AssertReturn(qIdx < VIRTIOSCSI_QUEUE_CNT,
     2019            AssertReturn(idxQueue < VIRTIOSCSI_QUEUE_CNT,
    20182020                         pHlp->pfnSSMSetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
    20192021                                                  N_("Bad queue index for re-do in saved state (%#x, max %#x)"),
    2020                                                   qIdx, VIRTIOSCSI_QUEUE_CNT - 1));
     2022                                                  idxQueue, VIRTIOSCSI_QUEUE_CNT - 1));
    20212023
    20222024            uint16_t idxHead;
    20232025            rc = pHlp->pfnSSMGetU16(pSSM, &idxHead);
    20242026            AssertRCReturn(rc, rc);
    2025             AssertReturn(idxHead < VIRTQ_MAX_SIZE,
     2027            AssertReturn(idxHead < VIRTQ_MAX_ENTRIES,
    20262028                         pHlp->pfnSSMSetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
    20272029                                                  N_("Bad queue element index for re-do in saved state (%#x, max %#x)"),
    2028                                                   idxHead, VIRTQ_MAX_SIZE - 1));
    2029 
    2030             PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[qIdx];
     2030                                                  idxHead, VIRTQ_MAX_ENTRIES - 1));
     2031
     2032            PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[idxQueue];
    20312033            pWorkerR3->auRedoDescs[pWorkerR3->cRedoDescs++] = idxHead;
    2032             pWorkerR3->cRedoDescs %= VIRTQ_MAX_SIZE;
     2034            pWorkerR3->cRedoDescs %= VIRTQ_MAX_ENTRIES;
    20332035        }
    20342036    }
     
    20422044     * Nudge request queue workers
    20432045     */
    2044     for (int qIdx = VIRTQ_REQ_BASE; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
    2045     {
    2046         if (pThis->afQueueAttached[qIdx])
     2046    for (int idxQueue = VIRTQ_REQ_BASE; idxQueue < VIRTIOSCSI_QUEUE_CNT; idxQueue++)
     2047    {
     2048        if (pThis->afQueueAttached[idxQueue])
    20472049        {
    2048             LogFunc(("Waking %s worker.\n", VIRTQNAME(qIdx)));
    2049             int rc2 = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[qIdx].hEvtProcess);
     2050            LogFunc(("Waking %s worker.\n", VIRTQNAME(idxQueue)));
     2051            int rc2 = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[idxQueue].hEvtProcess);
    20502052            AssertRCReturn(rc, rc2);
    20512053        }
     
    20662068    LogFunc(("SAVE EXEC!!\n"));
    20672069
    2068     for (int qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
    2069         pHlp->pfnSSMPutBool(pSSM, pThis->afQueueAttached[qIdx]);
     2070    for (int idxQueue = 0; idxQueue < VIRTIOSCSI_QUEUE_CNT; idxQueue++)
     2071        pHlp->pfnSSMPutBool(pSSM, pThis->afQueueAttached[idxQueue]);
    20702072
    20712073    pHlp->pfnSSMPutU32(pSSM,  pThis->virtioScsiConfig.uNumQueues);
     
    21142116                 while(--cReqsRedo)
    21152117                 {
    2116                     pHlp->pfnSSMPutU16(pSSM, pReq->qIdx);
     2118                    pHlp->pfnSSMPutU16(pSSM, pReq->idxQueue);
    21172119                    pHlp->pfnSSMPutU16(pSSM, pReq->pDescChain->uHeadIdx);
    21182120
     
    23322334     * be awake due to new reqs coming in.
    23332335     */
    2334     for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++)
    2335     {
    2336         if (ASMAtomicReadBool(&pThis->aWorkers[qIdx].fSleeping))
     2336    for (uint16_t idxQueue = 0; idxQueue < VIRTIOSCSI_REQ_QUEUE_CNT; idxQueue++)
     2337    {
     2338        if (ASMAtomicReadBool(&pThis->aWorkers[idxQueue].fSleeping))
    23372339        {
    2338             Log6Func(("waking %s worker.\n", VIRTQNAME(qIdx)));
    2339             int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[qIdx].hEvtProcess);
     2340            Log6Func(("waking %s worker.\n", VIRTQNAME(idxQueue)));
     2341            int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[idxQueue].hEvtProcess);
    23402342            AssertRC(rc);
    23412343        }
     
    24112413    pThisCC->pMediaNotify = NULL;
    24122414
    2413     for (unsigned qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
    2414     {
    2415         PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx];
     2415    for (unsigned idxQueue = 0; idxQueue < VIRTIOSCSI_QUEUE_CNT; idxQueue++)
     2416    {
     2417        PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[idxQueue];
    24162418        if (pWorker->hEvtProcess != NIL_SUPSEMEVENT)
    24172419        {
     
    24202422        }
    24212423
    2422         if (pThisCC->aWorkers[qIdx].pThread)
     2424        if (pThisCC->aWorkers[idxQueue].pThread)
    24232425        {
    24242426            /* Destroy the thread. */
    24252427            int rcThread;
    2426             int rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->aWorkers[qIdx].pThread, &rcThread);
     2428            int rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->aWorkers[idxQueue].pThread, &rcThread);
    24272429            if (RT_FAILURE(rc) || RT_FAILURE(rcThread))
    24282430                AssertMsgFailed(("%s Failed to destroythread rc=%Rrc rcThread=%Rrc\n",
    24292431                                 __FUNCTION__, rc, rcThread));
    2430            pThisCC->aWorkers[qIdx].pThread = NULL;
     2432           pThisCC->aWorkers[idxQueue].pThread = NULL;
    24312433        }
    24322434    }
     
    25232525
    25242526    /* Attach the queues and create worker threads for them: */
    2525     for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
    2526     {
    2527         rc = virtioCoreR3QueueAttach(&pThis->Virtio, qIdx, VIRTQNAME(qIdx));
     2527    for (uint16_t idxQueue = 0; idxQueue < VIRTIOSCSI_QUEUE_CNT; idxQueue++)
     2528    {
     2529        rc = virtioCoreR3QueueAttach(&pThis->Virtio, idxQueue, VIRTQNAME(idxQueue));
    25282530        if (RT_FAILURE(rc))
    25292531            continue;
    2530         if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx))
     2532        if (idxQueue == CONTROLQ_IDX || IS_REQ_QUEUE(idxQueue))
    25312533        {
    2532             rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->aWorkers[qIdx].pThread,
    2533                                        (void *)(uintptr_t)qIdx, virtioScsiR3WorkerThread,
    2534                                        virtioScsiR3WorkerWakeUp, 0, RTTHREADTYPE_IO, VIRTQNAME(qIdx));
     2534            rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->aWorkers[idxQueue].pThread,
     2535                                       (void *)(uintptr_t)idxQueue, virtioScsiR3WorkerThread,
     2536                                       virtioScsiR3WorkerWakeUp, 0, RTTHREADTYPE_IO, VIRTQNAME(idxQueue));
    25352537            if (rc != VINF_SUCCESS)
    25362538            {
    2537                 LogRel(("Error creating thread for Virtual Queue %s: %Rrc\n", VIRTQNAME(qIdx), rc));
     2539                LogRel(("Error creating thread for Virtual Queue %s: %Rrc\n", VIRTQNAME(idxQueue), rc));
    25382540                return rc;
    25392541            }
    25402542
    2541             rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->aWorkers[qIdx].hEvtProcess);
     2543            rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->aWorkers[idxQueue].hEvtProcess);
    25422544            if (RT_FAILURE(rc))
    25432545                return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
    25442546                                           N_("DevVirtioSCSI: Failed to create SUP event semaphore"));
    25452547        }
    2546         pThis->afQueueAttached[qIdx] = true;
     2548        pThis->afQueueAttached[idxQueue] = true;
    25472549    }
    25482550
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r84509 r84774  
    2222#define LOG_GROUP LOG_GROUP_DEV_VIRTIO
    2323
    24 #include <VBox/log.h>
    25 #include <VBox/msi.h>
    26 #include <VBox/AssertGuest.h>
    27 #include <iprt/param.h>
    2824#include <iprt/assert.h>
    2925#include <iprt/uuid.h>
    3026#include <iprt/mem.h>
     27#include <iprt/sg.h>
    3128#include <iprt/assert.h>
    32 #include <iprt/sg.h>
    3329#include <iprt/string.h>
     30#include <iprt/param.h>
     31#include <iprt/types.h>
     32#include <VBox/log.h>
     33#include <VBox/msi.h>
     34#include <iprt/types.h>
     35#include <VBox/AssertGuest.h>
    3436#include <VBox/vmm/pdmdev.h>
    3537#include "Virtio_1_0.h"
     
    4244#define VIRTQNAME(a_pVirtio, a_idxQueue)    ((a_pVirtio)->virtqState[(a_idxQueue)].szVirtqName)
    4345#define IS_DRIVER_OK(a_pVirtio)             ((a_pVirtio)->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
     46#define IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtq) \
     47            (virtioCoreQueueAvailCount(pDevIns, pVirtio, pVirtq) == 0)
    4448
    4549/**
     
    5054 * @param[in]  a_offAccess      The offset into the MMIO bar of the access.
    5155 * @param[in]  a_cbAccess       The access size.
    52  * @param[out] a_offIntraVar    The variable to return the intra-capability
     56 * @param[out] a_offsetInMbr    The variable to return the intra-capability
    5357 *                              offset into.  ASSUMES this is uint32_t.
    5458 * @param[in]  a_LocCapData     The capability location info.
    5559 */
    56 #define MATCHES_VIRTIO_CAP_STRUCT(a_offAccess, a_cbAccess, a_offIntraVar, a_LocCapData) \
    57     (   ((a_offIntraVar) = (uint32_t)((a_offAccess) - (a_LocCapData).offMmio)) < (uint32_t)(a_LocCapData).cbMmio \
    58      && (a_offIntraVar) + (uint32_t)(a_cbAccess) <= (uint32_t)(a_LocCapData).cbMmio )
     60#define MATCHES_VIRTIO_CAP_STRUCT(a_offAccess, a_cbAccess, a_offsetInMbr, a_LocCapData) \
     61    (   ((a_offsetInMbr) = (uint32_t)((a_offAccess) - (a_LocCapData).offMmio)) < (uint32_t)(a_LocCapData).cbMmio \
     62     && (a_offsetInMbr) + (uint32_t)(a_cbAccess) <= (uint32_t)(a_LocCapData).cbMmio )
    5963
    6064
     
    131135/* Internal Functions */
    132136
    133 static void virtioNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue);
     137static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue);
    134138static int  virtioKick(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint8_t uCause, uint16_t uVec);
    135139
     
    190194}
    191195
    192 DECLINLINE(bool) virtqIsEmpty(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
    193 {
    194     uint16_t uAvailGuestIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, idxQueue);
    195     bool fEmpty = uAvailGuestIdx == pVirtio->virtqState[idxQueue].uAvailIdx;
    196 
    197     Log6Func(("%s idx=%u, shadow idx=%u (%s)\n",
    198              VIRTQNAME(pVirtio, idxQueue), uAvailGuestIdx, pVirtio->virtqState[idxQueue].uAvailIdx,
    199              fEmpty ? "Queue empty" : "Queue has available descriptors"));
    200     return fEmpty;
    201 }
    202 
    203196DECLINLINE(uint16_t) virtioReadAvailRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
    204197{
     
    259252#endif
    260253
    261 
    262254#ifdef IN_RING3
    263255DECLINLINE(uint16_t) virtioReadUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
     
    279271                          &uAvailEventIdx, sizeof(uAvailEventIdx));
    280272}
     273
     274
    281275#endif
     276
     277DECLINLINE(uint16_t) virtioCoreQueueAvailCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQSTATE pVirtq)
     278{
     279    uint16_t uIdx    = virtioReadAvailRingIdx(pDevIns, pVirtio, pVirtq->idxQueue);
     280    uint16_t uShadow = pVirtq->uAvailIdxShadow;
     281
     282    uint16_t uDelta;
     283    if (uIdx < uShadow)
     284        uDelta = (uIdx + VIRTQ_MAX_ENTRIES) - uShadow;
     285    else
     286        uDelta = uIdx - uShadow;
     287
     288    LogFunc(("%s has %u %s (idx=%u shadow=%u)\n",
     289        VIRTQNAME(pVirtio, pVirtq->idxQueue), uDelta, uDelta == 1 ? "entry" : "entries",
     290        uIdx, uShadow));
     291
     292    return uDelta;
     293}
     294/**
     295 * Get count of new (e.g. pending) elements in available ring.
     296 *
     297 * @param   pDevIns     The device instance.
     298 * @param   pVirtio     Pointer to the shared virtio state.
     299 * @param   idxQueue    Queue number
     300 *
     301 * @returns how many entries have been added to ring as a delta of the consumer's
     302 *          avail index and the queue's guest-side current avail index.
     303 */
     304uint16_t virtioCoreQueueAvailCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
     305{
     306    if (!IS_DRIVER_OK(pVirtio) || !pVirtio->uQueueEnable[idxQueue])
     307    {
     308        LogRelFunc(("Driver not ready or queue not enabled\n"));
     309        return 0;
     310    }
     311    return virtioCoreQueueAvailCount(pDevIns, pVirtio, &pVirtio->virtqState[idxQueue]);
     312}
     313
    282314
    283315/** @} */
     
    294326    if (cSegs && paSegs)
    295327    {
    296         pGcSgBuf->gcPhysCur = paSegs[0].gcPhys;
     328        pGcSgBuf->GCPhysCur = paSegs[0].GCPhys;
    297329        pGcSgBuf->cbSegLeft = paSegs[0].cbSeg;
    298330    }
    299331    else
    300332    {
    301         pGcSgBuf->gcPhysCur = 0;
     333        pGcSgBuf->GCPhysCur = 0;
    302334        pGcSgBuf->cbSegLeft = 0;
    303335    }
     
    319351
    320352    AssertMsg(    pGcSgBuf->cbSegLeft <= 128 * _1M
    321               && (RTGCPHYS)pGcSgBuf->gcPhysCur >= (RTGCPHYS)pGcSgBuf->paSegs[pGcSgBuf->idxSeg].gcPhys
    322               && (RTGCPHYS)pGcSgBuf->gcPhysCur + pGcSgBuf->cbSegLeft <=
    323                    (RTGCPHYS)pGcSgBuf->paSegs[pGcSgBuf->idxSeg].gcPhys + pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg,
    324                  ("pGcSgBuf->idxSeg=%d pGcSgBuf->cSegs=%d pGcSgBuf->gcPhysCur=%p pGcSgBuf->cbSegLeft=%zd "
    325                   "pGcSgBuf->paSegs[%d].gcPhys=%p pGcSgBuf->paSegs[%d].cbSeg=%zd\n",
    326                   pGcSgBuf->idxSeg, pGcSgBuf->cSegs, pGcSgBuf->gcPhysCur, pGcSgBuf->cbSegLeft,
    327                   pGcSgBuf->idxSeg, pGcSgBuf->paSegs[pGcSgBuf->idxSeg].gcPhys, pGcSgBuf->idxSeg,
     353              && (RTGCPHYS)pGcSgBuf->GCPhysCur >= (RTGCPHYS)pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys
     354              && (RTGCPHYS)pGcSgBuf->GCPhysCur + pGcSgBuf->cbSegLeft <=
     355                   (RTGCPHYS)pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys + pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg,
     356                 ("pGcSgBuf->idxSeg=%d pGcSgBuf->cSegs=%d pGcSgBuf->GCPhysCur=%p pGcSgBuf->cbSegLeft=%zd "
     357                  "pGcSgBuf->paSegs[%d].GCPhys=%p pGcSgBuf->paSegs[%d].cbSeg=%zd\n",
     358                  pGcSgBuf->idxSeg, pGcSgBuf->cSegs, pGcSgBuf->GCPhysCur, pGcSgBuf->cbSegLeft,
     359                  pGcSgBuf->idxSeg, pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys, pGcSgBuf->idxSeg,
    328360                  pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg));
    329361
    330362    cbData = RT_MIN(*pcbData, pGcSgBuf->cbSegLeft);
    331     pGcBuf = pGcSgBuf->gcPhysCur;
     363    pGcBuf = pGcSgBuf->GCPhysCur;
    332364    pGcSgBuf->cbSegLeft -= cbData;
    333365    if (!pGcSgBuf->cbSegLeft)
     
    337369        if (pGcSgBuf->idxSeg < pGcSgBuf->cSegs)
    338370        {
    339             pGcSgBuf->gcPhysCur = pGcSgBuf->paSegs[pGcSgBuf->idxSeg].gcPhys;
     371            pGcSgBuf->GCPhysCur = pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys;
    340372            pGcSgBuf->cbSegLeft = pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg;
    341373        }
     
    343375    }
    344376    else
    345         pGcSgBuf->gcPhysCur = pGcSgBuf->gcPhysCur + cbData;
     377        pGcSgBuf->GCPhysCur = pGcSgBuf->GCPhysCur + cbData;
    346378
    347379    return pGcBuf;
     
    355387    if (pGcSgBuf->cSegs)
    356388    {
    357         pGcSgBuf->gcPhysCur = pGcSgBuf->paSegs[0].gcPhys;
     389        pGcSgBuf->GCPhysCur = pGcSgBuf->paSegs[0].GCPhys;
    358390        pGcSgBuf->cbSegLeft = pGcSgBuf->paSegs[0].cbSeg;
    359391    }
    360392    else
    361393    {
    362         pGcSgBuf->gcPhysCur = 0;
     394        pGcSgBuf->GCPhysCur = 0;
    363395        pGcSgBuf->cbSegLeft = 0;
    364396    }
     
    402434 }
    403435
    404 #ifdef LOG_ENABLED
    405 
    406 void virtioPrintFeatures(VIRTIOCORE *pVirtio)
    407 {
    408 #ifdef LOG_ENABLED
     436#ifdef IN_RING3
     437void virtioCorePrintFeatures(VIRTIOCORE *pVirtio, PCDBGFINFOHLP pHlp)
     438{
    409439    static struct
    410440    {
     
    431461                          isOffered ? "+" : "-", isNegotiated ? "x" : " ", s_aFeatures[i].pcszDesc);
    432462    }
    433     Log3(("VirtIO Features Configuration\n\n"
    434           "    Offered  Accepted  Feature              Description\n"
    435           "    -------  --------  -------              -----------\n"
    436           "%s\n", pszBuf));
     463    if (pHlp)
     464        pHlp->pfnPrintf(pHlp, "VirtIO Core Features Configuration\n\n"
     465              "    Offered  Accepted  Feature              Description\n"
     466              "    -------  --------  -------              -----------\n"
     467              "%s\n", pszBuf);
     468#ifdef LOG_ENABLED
     469    else
     470        Log3(("VirtIO Core Features Configuration\n\n"
     471              "    Offered  Accepted  Feature              Description\n"
     472              "    -------  --------  -------              -----------\n"
     473              "%s\n", pszBuf));
     474#endif
    437475    RTMemFree(pszBuf);
    438 
    439 #else  /* !LOG_ENABLED */
    440     RT_NOREF3(pThis, fFeatures, pcszText);
    441 #endif /* !LOG_ENABLED */
    442 }
    443 
    444 
    445 /**
     476}
     477#endif
     478
     479#ifdef LOG_ENABLED
     480/**
     481 * Debug assist for consumer device code.
    446482 * Does a formatted hex dump using Log(()), recommend using VIRTIO_HEX_DUMP() macro to
    447483 * control enabling of logging efficiently.
     
    455491void virtioCoreHexDump(uint8_t *pv, uint32_t cb, uint32_t uBase, const char *pszTitle)
    456492{
     493#define ADJCURSOR(cb) pszOut += cb; cbRemain -= cb;
     494    int cbPrint = 0, cbRemain = ((cb / 16) + 1) * 80;
     495    char *pszBuf = (char *)RTMemAllocZ(cbRemain), *pszOut = pszBuf;
     496    AssertMsgReturnVoid(pszBuf, ("Out of Memory"));
    457497    if (pszTitle)
    458         Log(("%s [%d bytes]:\n", pszTitle, cb));
     498    {
     499        cbPrint = RTStrPrintf(pszOut, cbRemain, "%s [%d bytes]:\n", pszTitle, cb);
     500        ADJCURSOR(cbPrint);
     501    }
    459502    for (uint32_t row = 0; row < RT_MAX(1, (cb / 16) + 1) && row * 16 < cb; row++)
    460503    {
    461         Log(("%04x: ", row * 16 + uBase)); /* line address */
     504        cbPrint = RTStrPrintf(pszOut, cbRemain, "%04x: ", row * 16 + uBase); /* line address */
     505        ADJCURSOR(cbPrint);
    462506        for (uint8_t col = 0; col < 16; col++)
    463507        {
    464508           uint32_t idx = row * 16 + col;
    465509           if (idx >= cb)
    466                Log(("-- %s", (col + 1) % 8 ? "" : "  "));
     510               cbPrint = RTStrPrintf(pszOut, cbRemain, "-- %s", (col + 1) % 8 ? "" : "  ");
    467511           else
    468                Log(("%02x %s", pv[idx], (col + 1) % 8 ? "" : "  "));
     512               cbPrint = RTStrPrintf(pszOut, cbRemain, ("%02x %s", pv[idx], (col + 1) % 8 ? "" : "  "));
     513            ADJCURSOR(cbPrint);
    469514        }
    470515        for (uint32_t idx = row * 16; idx < row * 16 + 16; idx++)
    471            Log(("%c", (idx >= cb) ? ' ' : (pv[idx] >= 0x20 && pv[idx] <= 0x7e ? pv[idx] : '.')));
    472         Log(("\n"));
    473     }
    474     Log(("\n"));
     516        {
     517           cbPrint = RTStrPrintf(pszOut, cbRemain, "%c", (idx >= cb) ? ' ' : (pv[idx] >= 0x20 && pv[idx] <= 0x7e ? pv[idx] : '.'));
     518           ADJCURSOR(cbPrint);
     519        }
     520        *pszOut++ = '\n';
     521        --cbRemain;
     522    }
     523    Log(("%s\n", pszBuf));
     524    RTMemFree(pszBuf);
    475525    RT_NOREF2(uBase, pv);
    476 }
    477 
    478 /**
     526#undef ADJCURSOR
     527}
     528
     529/**
     530 * Debug assist for consumer device code.
    479531 * Do a hex dump of memory in guest physical context
    480532 *
    481  * @param   gcPhys      pointer to buffer to dump contents of
     533 * @param   GCPhys      pointer to buffer to dump contents of
    482534 * @param   cb          count of characters to dump from buffer
    483535 * @param   uBase       base address of per-row address prefixing of hex output
     
    485537 *                      provided text with value of cb to indicate size next to it.
    486538 */
    487 void virtioCoreGcPhysHexDump(PPDMDEVINS pDevIns, RTGCPHYS gcPhys, uint32_t cb, uint32_t uBase, const char *pszTitle)
    488 {
     539void virtioCoreGCPhysHexDump(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint16_t cb, uint32_t uBase, const char *pszTitle)
     540{
     541#define ADJCURSOR(cb) pszOut += cb; cbRemain -= cb;
     542    int cbPrint = 0, cbRemain = ((cb / 16) + 1) * 80;
     543    char *pszBuf = (char *)RTMemAllocZ(cbRemain), *pszOut = pszBuf;
     544    AssertMsgReturnVoid(pszBuf, ("Out of Memory"));
    489545    if (pszTitle)
    490         Log(("%s [%d bytes]:\n", pszTitle, cb));
    491     for (uint32_t row = 0; row < RT_MAX(1, (cb / 16) + 1) && row * 16 < cb; row++)
     546    {
     547        cbPrint = RTStrPrintf(pszOut, cbRemain, "%s [%d bytes]:\n", pszTitle, cb);
     548        ADJCURSOR(cbPrint);
     549    }
     550    for (uint16_t row = 0; row < (uint16_t)RT_MAX(1, (cb / 16) + 1) && row * 16 < cb; row++)
    492551    {
    493552        uint8_t c;
    494         Log(("%04x: ", row * 16 + uBase)); /* line address */
     553        cbPrint = RTStrPrintf(pszOut, cbRemain, "%04x: ", row * 16 + uBase); /* line address */
     554        ADJCURSOR(cbPrint);
    495555        for (uint8_t col = 0; col < 16; col++)
    496556        {
    497557           uint32_t idx = row * 16 + col;
    498            PDMDevHlpPCIPhysRead(pDevIns, gcPhys + idx, &c, 1);
     558           PDMDevHlpPCIPhysRead(pDevIns, GCPhys + idx, &c, 1);
    499559           if (idx >= cb)
    500                Log(("-- %s", (col + 1) % 8 ? "" : "  "));
     560               cbPrint = RTStrPrintf(pszOut, cbRemain, "-- %s", (col + 1) % 8 ? "" : "  ");
    501561           else
    502                Log(("%02x %s", c, (col + 1) % 8 ? "" : "  "));
    503         }
    504         for (uint32_t idx = row * 16; idx < row * 16 + 16; idx++)
    505         {
    506            PDMDevHlpPCIPhysRead(pDevIns, gcPhys + idx, &c, 1);
    507            Log(("%c", (idx >= cb) ? ' ' : (c >= 0x20 && c <= 0x7e ? c : '.')));
    508         }
    509         Log(("\n"));
    510     }
    511     Log(("\n"));
     562               cbPrint = RTStrPrintf(pszOut, cbRemain, "%02x %s", c, (col + 1) % 8 ? "" : "  ");
     563            ADJCURSOR(cbPrint);
     564        }
     565        for (uint16_t idx = row * 16; idx < row * 16 + 16; idx++)
     566        {
     567           PDMDevHlpPCIPhysRead(pDevIns, GCPhys + idx, &c, 1);
     568           cbPrint = RTStrPrintf(pszOut, cbRemain, "%c", (idx >= cb) ? ' ' : (c >= 0x20 && c <= 0x7e ? c : '.'));
     569           ADJCURSOR(cbPrint);
     570        }
     571        *pszOut++ = '\n';
     572        --cbRemain;
     573     }
     574    Log(("%s\n", pszBuf));
     575    RTMemFree(pszBuf);
    512576    RT_NOREF(uBase);
     577#undef ADJCURSOR
    513578}
    514579#endif /* LOG_ENABLED */
     
    607672
    608673#ifdef IN_RING3
    609 /**
    610  * Allocate client context for client to work with VirtIO-provided with queue
     674
     675void 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 fQueues   = pszArgs && (*pszArgs == 'q' || *pszArgs == 'Q'); /* "queues    */
     684    RT_NOREF6(fNone, fAll, fBasic, fState, fPointers, fQueues);
     685    pHlp->pfnPrintf(pHlp, "");
     686
     687}
     688
     689void virtioCoreR3QueueInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs, int idxQueue)
     690{
     691    RT_NOREF(pszArgs);
     692    PVIRTIOCORE pVirtio = PDMDEVINS_2_DATA(pDevIns, PVIRTIOCORE);
     693    PVIRTQSTATE pVirtq = &pVirtio->virtqState[idxQueue];
     694
     695//    bool fDump      = pszArgs && (*pszArgs == 'd' || *pszArgs == 'D'); /* "dump" (avail phys descriptor)"       */
     696
     697    uint16_t uAvailIdx       = virtioReadAvailRingIdx(pDevIns, pVirtio, idxQueue);
     698    uint16_t uAvailIdxShadow = pVirtq->uAvailIdxShadow;
     699
     700    uint16_t uUsedIdx        = virtioReadUsedRingIdx(pDevIns, pVirtio, idxQueue);
     701    uint16_t uUsedIdxShadow  = pVirtq->uUsedIdxShadow;
     702
     703    PVIRTIO_DESC_CHAIN_T pDescChain;
     704
     705    bool fEmpty = IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtq);
     706
     707    LogFunc(("%s, empty = %s\n", VIRTQNAME(pVirtio, idxQueue), fEmpty ? "true" : "false"));
     708
     709    int cSendSegs = 0, cReturnSegs = 0;
     710    if (!fEmpty)
     711    {
     712        virtioCoreR3QueuePeek(pDevIns,  pVirtio, idxQueue, &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, idxQueue) & VIRTQ_AVAIL_F_NO_INTERRUPT;
     718    bool fUsedNoNotify       = virtioReadUsedRingFlags(pDevIns, pVirtio, idxQueue) & VIRTQ_USED_F_NO_NOTIFY;
     719
     720
     721    pHlp->pfnPrintf(pHlp, "       queue enabled: ........... %s\n", pVirtio->uQueueEnable[idxQueue] ? "true" : "false");
     722    pHlp->pfnPrintf(pHlp, "       size: .................... %d\n", pVirtio->uQueueSize[idxQueue]);
     723    pHlp->pfnPrintf(pHlp, "       notify offset: ........... %d\n", pVirtio->uQueueNotifyOff[idxQueue]);
     724    if (pVirtio->fMsiSupport)
     725        pHlp->pfnPrintf(pHlp, "       MSIX vector: ....... %4.4x\n", pVirtio->uQueueMsixVector[idxQueue]);
     726    pHlp->pfnPrintf(pHlp, "\n");
     727    pHlp->pfnPrintf(pHlp, "       avail ring (%d entries):\n", uAvailIdx - uAvailIdxShadow);
     728    pHlp->pfnPrintf(pHlp, "          index: ................ %d\n", uAvailIdx);
     729    pHlp->pfnPrintf(pHlp, "          shadow: ............... %d\n", uAvailIdxShadow);
     730    pHlp->pfnPrintf(pHlp, "          flags: ................ %s\n", fAvailNoInterrupt ? "NO_INTERRUPT" : "");
     731    pHlp->pfnPrintf(pHlp, "\n");
     732    pHlp->pfnPrintf(pHlp, "       used ring (%d entries):\n",  uUsedIdx - uUsedIdxShadow);
     733    pHlp->pfnPrintf(pHlp, "          index: ................ %d\n", uUsedIdx);
     734    pHlp->pfnPrintf(pHlp, "          shadow: ............... %d\n", uUsedIdxShadow);
     735    pHlp->pfnPrintf(pHlp, "          flags: ................ %s\n", fUsedNoNotify ? "NO_NOTIFY" : "");
     736    pHlp->pfnPrintf(pHlp, "\n");
     737    if (!fEmpty)
     738    {
     739        pHlp->pfnPrintf(pHlp, "       desc chain:\n");
     740        pHlp->pfnPrintf(pHlp, "          head idx: ............. %d\n", uUsedIdx);
     741        pHlp->pfnPrintf(pHlp, "          segs: ................. %d\n", cSendSegs + cReturnSegs);
     742        pHlp->pfnPrintf(pHlp, "          refCnt ................ %d\n", pDescChain->cRefs);
     743        pHlp->pfnPrintf(pHlp, "\n");
     744        pHlp->pfnPrintf(pHlp, "          host-to-guest (%d bytes):\n",      pDescChain->cbPhysSend);
     745        pHlp->pfnPrintf(pHlp,     "             segs: .............. %d\n", cSendSegs);
     746        if (cSendSegs)
     747        {
     748            pHlp->pfnPrintf(pHlp, "             index: ............. %d\n", pDescChain->pSgPhysSend->idxSeg);
     749            pHlp->pfnPrintf(pHlp, "             unsent ............. %d\n",  pDescChain->pSgPhysSend->cbSegLeft);
     750        }
     751        pHlp->pfnPrintf(pHlp, "\n");
     752        pHlp->pfnPrintf(pHlp,     "          guest-to-host (%d bytes)\n",   pDescChain->cbPhysReturn);
     753        pHlp->pfnPrintf(pHlp,     "             segs: .............. %d\n", cReturnSegs);
     754        if (cReturnSegs)
     755        {
     756            pHlp->pfnPrintf(pHlp, "             index: ............. %d\n", pDescChain->pSgPhysReturn->idxSeg);
     757            pHlp->pfnPrintf(pHlp, "             unsent ............. %d\n",  pDescChain->pSgPhysReturn->cbSegLeft);
     758        }
     759    } else
     760        pHlp->pfnPrintf(pHlp,     "      No desc chains available\n");
     761    pHlp->pfnPrintf(pHlp, "\n");
     762
     763}
     764
     765/**
     766 * Allocate client context for client to work with VirtIO-#provided with queue
    611767 *
    612768 * @param   pVirtio     Pointer to the shared virtio state.
     
    620776    LogFunc(("%s\n", pcszName));
    621777    PVIRTQSTATE pVirtq = &pVirtio->virtqState[idxQueue];
    622     pVirtq->uAvailIdx = 0;
    623     pVirtq->uUsedIdx  = 0;
    624     pVirtq->fEventThresholdReached = false;
     778    pVirtq->idxQueue = idxQueue;
     779    pVirtq->uAvailIdxShadow = 0;
     780    pVirtq->uUsedIdxShadow  = 0;
     781    pVirtq->fVirtqRingEventThreshold = false;
    625782    RTStrCopy(pVirtq->szVirtqName, sizeof(pVirtq->szVirtqName), pcszName);
    626783    return VINF_SUCCESS;
     
    629786
    630787
    631 /**
    632  * Check if the associated queue is empty
    633  *
    634  * @param   pDevIns     The device instance (for reading).
    635  * @param   pVirtio     Pointer to the shared virtio state.
    636  * @param   idxQueue    Queue number
    637  *
    638  * @retval true  Queue is empty or unavailable.
    639  * @retval false Queue is available and has entries
    640  */
    641 bool virtioCoreQueueIsEmpty(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
    642 {
    643     if (pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
    644         return virtqIsEmpty(pDevIns, pVirtio, idxQueue);
    645     LogFunc(("VirtIO not ready: Returning 'true' for queue empty\n"));
    646     return true;
    647 }
    648 
    649788#ifdef IN_RING3
    650 
    651789
    652790int virtioCoreR3DescChainGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue,
     
    700838         * the following aborts I/O if breach and employs a simple log throttling algorithm to notify.
    701839         */
    702         if (cSegsIn + cSegsOut >= VIRTQ_MAX_SIZE)
     840        if (cSegsIn + cSegsOut >= VIRTQ_MAX_ENTRIES)
    703841        {
    704842            static volatile uint32_t s_cMessages  = 0;
     
    728866            cbOut += desc.cb;
    729867            pSeg = &paSegsOut[cSegsOut++];
    730         }
    731 
    732         pSeg->gcPhys = desc.GCPhysBuf;
     868            if (LogIs11Enabled())
     869            {
     870                virtioCoreGCPhysHexDump(pDevIns, desc.GCPhysBuf, desc.cb, 0, NULL);
     871                Log(("\n"));
     872            }
     873        }
     874
     875        pSeg->GCPhys = desc.GCPhysBuf;
    733876        pSeg->cbSeg = desc.cb;
    734877
     
    822965 * @param   pVirtio     Pointer to the shared virtio state.
    823966 * @param   idxQueue    Queue number
    824  * @param   fEnabled    Selects notification mode (enabled or disabled)
    825  */
    826 void virtioCoreQueueSetNotify(PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fEnabled)
     967 * @param   fEnable    Selects notification mode (enabled or disabled)
     968 */
     969void virtioCoreQueueNotifyEnable(PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fEnable)
    827970{
    828971    if (pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
     
    830973        uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, idxQueue);
    831974
    832         if (fEnabled)
     975        if (fEnable)
    833976            fFlags &= ~ VIRTQ_USED_F_NO_NOTIFY;
    834977        else
     
    855998    }
    856999}
    857 /**
    858  * Get count of new (e.g. pending) elements in available ring.
    859  *
    860  * @param   pDevIns     The device instance.
    861  * @param   pVirtio     Pointer to the shared virtio state.
    862  * @param   idxQueue    Queue number
    863  *
    864  * @returns how many entries have been added to ring as a delta of the consumer's
    865  *          avail index and the queue's guest-side current avail index.
    866  */
    867 int  virtioCoreR3QueuePendingCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
    868 {
    869     uint16_t uAvailRingIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, idxQueue);
    870     uint16_t uNextAvailIdx = pVirtio->virtqState[idxQueue].uAvailIdx;
    871     uint16_t uDelta = uAvailRingIdx - uNextAvailIdx;
    872     if (uAvailRingIdx > uNextAvailIdx)
    873         return uDelta;
    874     return VIRTQ_MAX_CNT + uDelta;
    875 }
     1000
     1001
     1002
    8761003/**
    8771004 * Fetches descriptor chain using avail ring of indicated queue and converts the descriptor
     
    9191046                    ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
    9201047
    921     if (virtioCoreQueueIsEmpty(pVirtio->pDevInsR3, pVirtio, idxQueue))
     1048    if (IS_VIRTQ_EMPTY(pVirtio->pDevInsR3, pVirtio, pVirtq))
    9221049        return VERR_NOT_AVAILABLE;
    9231050
    924     Log2Func(("%s avail_idx=%u\n", pVirtq->szVirtqName, pVirtq->uAvailIdx));
    925     pVirtq->uAvailIdx++;
     1051    Log6Func(("%s avail shadow idx: %u\n", pVirtq->szVirtqName, pVirtq->uAvailIdxShadow));
     1052    pVirtq->uAvailIdxShadow++;
    9261053
    9271054    return VINF_SUCCESS;
     
    9561083    PVIRTQSTATE pVirtq = &pVirtio->virtqState[idxQueue];
    9571084
    958     if (virtqIsEmpty(pDevIns, pVirtio, idxQueue))
     1085    if (IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtq))
    9591086        return VERR_NOT_AVAILABLE;
    9601087
    961     uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, idxQueue, pVirtq->uAvailIdx);
     1088    uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, idxQueue, pVirtq->uAvailIdxShadow);
    9621089
    9631090    if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX)
    964         virtioWriteUsedAvailEvent(pDevIns,pVirtio, idxQueue, pVirtq->uAvailIdx + 1);
     1091        virtioWriteUsedAvailEvent(pDevIns,pVirtio, idxQueue, pVirtq->uAvailIdxShadow + 1);
    9651092
    9661093    if (fRemove)
    967         pVirtq->uAvailIdx++;
     1094        pVirtq->uAvailIdxShadow++;
    9681095
    9691096    int rc = virtioCoreR3DescChainGet(pDevIns, pVirtio, idxQueue, uHeadIdx, ppDescChain);
     
    10341161            cbCopy = RT_MIN(pSgVirtReturn->cbSegLeft,  pSgPhysReturn->cbSegLeft);
    10351162            Assert(cbCopy > 0);
    1036             PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)pSgPhysReturn->gcPhysCur, pSgVirtReturn->pvSegCur, cbCopy);
     1163            PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)pSgPhysReturn->GCPhysCur, pSgVirtReturn->pvSegCur, cbCopy);
    10371164            RTSgBufAdvance(pSgVirtReturn, cbCopy);
    10381165            virtioCoreSgBufAdvance(pSgPhysReturn, cbCopy);
     
    10481175    /* If this write-ahead crosses threshold where the driver wants to get an event flag it */
    10491176    if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX)
    1050         if (pVirtq->uUsedIdx == virtioReadAvailUsedEvent(pDevIns, pVirtio, idxQueue))
    1051             pVirtq->fEventThresholdReached = true;
     1177        if (pVirtq->uUsedIdxShadow == virtioReadAvailUsedEvent(pDevIns, pVirtio, idxQueue))
     1178            pVirtq->fVirtqRingEventThreshold = true;
    10521179
    10531180    /*
    10541181     * Place used buffer's descriptor in used ring but don't update used ring's slot index.
    10551182     * That will be done with a subsequent client call to virtioCoreQueueSync() */
    1056     virtioWriteUsedElem(pDevIns, pVirtio, idxQueue, pVirtq->uUsedIdx++, pDescChain->uHeadIdx, (uint32_t)cbTotal);
     1183    virtioWriteUsedElem(pDevIns, pVirtio, idxQueue, pVirtq->uUsedIdxShadow++, pDescChain->uHeadIdx, (uint32_t)cbTotal);
    10571184
    10581185    if (pSgVirtReturn)
     
    10611188
    10621189    Log6Func(("Write ahead used_idx=%u, %s used_idx=%u\n",
    1063               pVirtq->uUsedIdx, VIRTQNAME(pVirtio, idxQueue), virtioReadUsedRingIdx(pDevIns, pVirtio, idxQueue)));
     1190              pVirtq->uUsedIdxShadow, VIRTQNAME(pVirtio, idxQueue), virtioReadUsedRingIdx(pDevIns, pVirtio, idxQueue)));
    10641191
    10651192    return VINF_SUCCESS;
     
    10871214int virtioCoreQueueSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
    10881215{
    1089     Assert(idxQueue        < RT_ELEMENTS(pVirtio->virtqState));
     1216    Assert(idxQueue < RT_ELEMENTS(pVirtio->virtqState));
    10901217    PVIRTQSTATE pVirtq = &pVirtio->virtqState[idxQueue];
    10911218
     
    10941221
    10951222    Log6Func(("Updating %s used_idx from %u to %u\n",
    1096               VIRTQNAME(pVirtio, idxQueue), virtioReadUsedRingIdx(pDevIns, pVirtio, idxQueue), pVirtq->uUsedIdx));
    1097 
    1098     virtioWriteUsedRingIdx(pDevIns, pVirtio, idxQueue, pVirtq->uUsedIdx);
    1099     virtioNotifyGuestDriver(pDevIns, pVirtio, idxQueue);
     1223              VIRTQNAME(pVirtio, idxQueue), virtioReadUsedRingIdx(pDevIns, pVirtio, idxQueue), pVirtq->uUsedIdxShadow));
     1224
     1225    virtioWriteUsedRingIdx(pDevIns, pVirtio, idxQueue, pVirtq->uUsedIdxShadow);
     1226    virtioCoreNotifyGuestDriver(pDevIns, pVirtio, idxQueue);
    11001227
    11011228    return VINF_SUCCESS;
    11021229}
    11031230
    1104 /**
    1105  */
    1106 static void virtioQueueNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, uint16_t uNotifyIdx)
     1231
     1232/**
     1233 */
     1234static void virtioCoreQueueNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, uint16_t uNotifyIdx)
    11071235{
    11081236
     
    11191247
    11201248    AssertReturnVoid(idxQueue < RT_ELEMENTS(pVirtio->virtqState));
    1121     Log6Func(("%s\n", pVirtio->virtqState[idxQueue].szVirtqName));
     1249    Log6Func(("%s (desc chains: %u)\n",
     1250        pVirtio->virtqState[idxQueue].szVirtqName,
     1251        virtioCoreQueueAvailCount(pDevIns, pVirtio, idxQueue)));
    11221252
    11231253    /* Inform client */
     
    11361266 * @param   idxQueue    Queue to check for guest interrupt handling preference
    11371267 */
    1138 static void virtioNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
     1268static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
    11391269{
    11401270
     
    11501280    if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX)
    11511281    {
    1152         if (pVirtq->fEventThresholdReached)
     1282        if (pVirtq->fVirtqRingEventThreshold)
    11531283        {
    11541284#ifdef IN_RING3
     
    11571287#endif
    11581288            virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uQueueMsixVector[idxQueue]);
    1159             pVirtq->fEventThresholdReached = false;
     1289            pVirtq->fVirtqRingEventThreshold = false;
    11601290            return;
    11611291        }
    11621292#ifdef IN_RING3
    1163         Log6Func(("...skipping interrupt %s, VIRTIO_F_EVENT_IDX set but threshold (%d) not reached (%d)\n",
    1164                    VIRTQNAME(pVirtio, idxQueue),(uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxQueue), pVirtq->uUsedIdx));
     1293        Log6Func(("...skip interrupt %s, VIRTIO_F_EVENT_IDX set but threshold (%d) not reached (%d)\n",
     1294                   VIRTQNAME(pVirtio, idxQueue),(uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxQueue), pVirtq->uUsedIdxShadow));
    11651295#endif
    11661296    }
     
    11731303            return;
    11741304        }
    1175         Log6Func(("...skipping interrupt, queue %s, Guest flagged VIRTQ_AVAIL_F_NO_INTERRUPT for queue\n",
     1305        Log6Func(("...skipping interrupt for %s (guest set VIRTQ_AVAIL_F_NO_INTERRUPT)\n",
    11761306                     VIRTQNAME(pVirtio, idxQueue)));
    11771307    }
     
    12231353    Assert(idxQueue < RT_ELEMENTS(pVirtio->virtqState));
    12241354    PVIRTQSTATE pVirtq = &pVirtio->virtqState[idxQueue];
    1225     pVirtq->uAvailIdx = 0;
    1226     pVirtq->uUsedIdx  = 0;
    1227     pVirtq->fEventThresholdReached = false;
     1355    pVirtq->uAvailIdxShadow = 0;
     1356    pVirtq->uUsedIdxShadow  = 0;
     1357    pVirtq->fVirtqRingEventThreshold = false;
    12281358    pVirtio->uQueueEnable[idxQueue] = false;
    1229     pVirtio->uQueueSize[idxQueue] = VIRTQ_MAX_SIZE;
     1359    pVirtio->uQueueSize[idxQueue] = VIRTQ_MAX_ENTRIES;
    12301360    pVirtio->uQueueNotifyOff[idxQueue] = idxQueue;
    12311361    pVirtio->uQueueMsixVector[idxQueue] = idxQueue + 2;
     
    13141444
    13151445#ifdef LOG_ENABLED
    1316 # define LOG_COMMON_CFG_ACCESS(member, a_offIntra) \
     1446# define LOG_COMMON_CFG_ACCESS(member, uOffset) \
    13171447    if (LogIs7Enabled()) { \
    13181448        virtioCoreLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIO_PCI_COMMON_CFG_T, member), \
    1319                                    pv, cb, a_offIntra, fWrite, false, 0); \
    1320     }
    1321 # define LOG_COMMON_CFG_ACCESS_INDEXED(member, idx, a_offIntra) \
     1449                                   pv, cb, uOffset, fWrite, false, 0); \
     1450    }
     1451# define LOG_COMMON_CFG_ACCESS_INDEXED(member, idx, uOffset) \
    13221452    if (LogIs7Enabled()) { \
    13231453        virtioCoreLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIO_PCI_COMMON_CFG_T, member), \
    1324                                    pv, cb, a_offIntra, fWrite, true, idx); \
     1454                                   pv, cb, uOffset, fWrite, true, idx); \
    13251455    }
    13261456#else
    1327 # define LOG_COMMON_CFG_ACCESS(member, a_offIntra)              do { } while (0)
    1328 # define LOG_COMMON_CFG_ACCESS_INDEXED(member, idx, a_offIntra) do { } while (0)
     1457# define LOG_COMMON_CFG_ACCESS(member, uOffset)              do { } while (0)
     1458# define LOG_COMMON_CFG_ACCESS_INDEXED(member, idx, uOffset) do { } while (0)
    13291459#endif
    13301460
     
    13321462    do \
    13331463    { \
    1334         uint32_t offIntra = offCfg - RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member); \
     1464        uint32_t uOffset = offCfg - RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member); \
    13351465        if (fWrite) \
    1336             memcpy((char *)&pVirtio->member + offIntra, (const char *)pv, cb); \
     1466            memcpy((char *)&pVirtio->member + uOffset, (const char *)pv, cb); \
    13371467        else \
    1338             memcpy(pv, (const char *)&pVirtio->member + offIntra, cb); \
    1339         LOG_COMMON_CFG_ACCESS(member, offIntra); \
     1468            memcpy(pv, (const char *)&pVirtio->member + uOffset, cb); \
     1469        LOG_COMMON_CFG_ACCESS(member, uOffset); \
    13401470    } while(0)
    13411471
     
    13431473    do \
    13441474    { \
    1345         uint32_t offIntra = offCfg - RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member); \
     1475        uint32_t uOffset = offCfg - RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member); \
    13461476        if (fWrite) \
    1347             memcpy((char *)&pVirtio->member[idx] + offIntra, pv, cb); \
     1477            memcpy((char *)&pVirtio->member[idx] + uOffset, pv, cb); \
    13481478        else \
    1349             memcpy(pv, (const char *)&pVirtio->member[idx] + offIntra, cb); \
    1350         LOG_COMMON_CFG_ACCESS_INDEXED(member, idx, offIntra); \
     1479            memcpy(pv, (const char *)&pVirtio->member[idx] + uOffset, cb); \
     1480        LOG_COMMON_CFG_ACCESS_INDEXED(member, idx, uOffset); \
    13511481    } while(0)
    13521482
     
    13541484    do \
    13551485    { \
    1356         uint32_t offIntra = offCfg - RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member); \
     1486        uint32_t uOffset = offCfg - RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member); \
    13571487        if (fWrite) \
    13581488            LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \
    13591489        else \
    13601490        { \
    1361             memcpy(pv, (const char *)&pVirtio->member + offIntra, cb); \
    1362             LOG_COMMON_CFG_ACCESS(member, offIntra); \
     1491            memcpy(pv, (const char *)&pVirtio->member + uOffset, cb); \
     1492            LOG_COMMON_CFG_ACCESS(member, uOffset); \
    13631493        } \
    13641494    } while(0)
     
    13671497    do \
    13681498    { \
    1369         uint32_t offIntra = offCfg - RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member); \
     1499        uint32_t uOffset = offCfg - RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member); \
    13701500        if (fWrite) \
    13711501            LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s[%d]\n", #member, idx)); \
    13721502        else \
    13731503        { \
    1374             memcpy(pv, (char const *)&pVirtio->member[idx] + offIntra, cb); \
    1375             LOG_COMMON_CFG_ACCESS_INDEXED(member, idx, offIntra); \
     1504            memcpy(pv, (char const *)&pVirtio->member[idx] + uOffset, cb); \
     1505            LOG_COMMON_CFG_ACCESS_INDEXED(member, idx, uOffset); \
    13761506        } \
    13771507    } while(0)
     
    15811711
    15821712
    1583     uint32_t offIntra;
    1584     if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, offIntra, pVirtio->LocDeviceCap))
     1713    uint32_t uOffset;
     1714    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocDeviceCap))
    15851715    {
    15861716#ifdef IN_RING3
     
    15881718         * Callback to client to manage device-specific configuration.
    15891719         */
    1590         VBOXSTRICTRC rcStrict = pVirtioCC->pfnDevCapRead(pDevIns, offIntra, pv, cb);
     1720        VBOXSTRICTRC rcStrict = pVirtioCC->pfnDevCapRead(pDevIns, uOffset, pv, cb);
    15911721
    15921722        /*
     
    15951725         * order to maintain the config generation (see VirtIO 1.0 spec, section 4.1.4.3.1)
    15961726         */
    1597         bool fDevSpecificFieldChanged = RT_BOOL(memcmp(pVirtioCC->pbDevSpecificCfg + offIntra,
    1598                                                  pVirtioCC->pbPrevDevSpecificCfg + offIntra,
    1599                                                  RT_MIN(cb, pVirtioCC->cbDevSpecificCfg - offIntra)));
     1727        bool fDevSpecificFieldChanged = RT_BOOL(memcmp(pVirtioCC->pbDevSpecificCfg + uOffset,
     1728                                                 pVirtioCC->pbPrevDevSpecificCfg + uOffset,
     1729                                                 RT_MIN(cb, pVirtioCC->cbDevSpecificCfg - uOffset)));
    16001730
    16011731        memcpy(pVirtioCC->pbPrevDevSpecificCfg, pVirtioCC->pbDevSpecificCfg, pVirtioCC->cbDevSpecificCfg);
     
    16181748    }
    16191749
    1620     if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, offIntra, pVirtio->LocCommonCfgCap))
    1621         return virtioCommonCfgAccessed(pDevIns, pVirtio, pVirtioCC, false /* fWrite */, offIntra, cb, pv);
    1622 
    1623     if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, offIntra, pVirtio->LocIsrCap) && cb == sizeof(uint8_t))
     1750    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocCommonCfgCap))
     1751        return virtioCommonCfgAccessed(pDevIns, pVirtio, pVirtioCC, false /* fWrite */, uOffset, cb, pv);
     1752
     1753    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocIsrCap) && cb == sizeof(uint8_t))
    16241754    {
    16251755        *(uint8_t *)pv = pVirtio->uISR;
     
    16501780
    16511781    Assert(pVirtio == (PVIRTIOCORE)pvUser); RT_NOREF(pvUser);
    1652     uint32_t offIntra;
    1653     if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, offIntra, pVirtio->LocDeviceCap))
     1782    uint32_t uOffset;
     1783    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocDeviceCap))
    16541784    {
    16551785#ifdef IN_RING3
     
    16571787         * Pass this MMIO write access back to the client to handle
    16581788         */
    1659         return pVirtioCC->pfnDevCapWrite(pDevIns, offIntra, pv, cb);
     1789        return pVirtioCC->pfnDevCapWrite(pDevIns, uOffset, pv, cb);
    16601790#else
    16611791        return VINF_IOM_R3_MMIO_WRITE;
     
    16631793    }
    16641794
    1665     if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, offIntra, pVirtio->LocCommonCfgCap))
    1666         return virtioCommonCfgAccessed(pDevIns, pVirtio, pVirtioCC, true /* fWrite */, offIntra, cb, (void *)pv);
    1667 
    1668     if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, offIntra, pVirtio->LocIsrCap) && cb == sizeof(uint8_t))
     1795    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocCommonCfgCap))
     1796        return virtioCommonCfgAccessed(pDevIns, pVirtio, pVirtioCC, true /* fWrite */, uOffset, cb, (void *)pv);
     1797
     1798    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocIsrCap) && cb == sizeof(uint8_t))
    16691799    {
    16701800        pVirtio->uISR = *(uint8_t *)pv;
     
    16771807
    16781808    /* This *should* be guest driver dropping index of a new descriptor in avail ring */
    1679     if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, offIntra, pVirtio->LocNotifyCap) && cb == sizeof(uint16_t))
    1680     {
    1681         virtioQueueNotified(pDevIns, pVirtio, offIntra / VIRTIO_NOTIFY_OFFSET_MULTIPLIER, *(uint16_t *)pv);
     1809    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocNotifyCap) && cb == sizeof(uint16_t))
     1810    {
     1811        virtioCoreQueueNotified(pDevIns, pVirtio, uOffset / VIRTIO_NOTIFY_OFFSET_MULTIPLIER, *(uint16_t *)pv);
    16821812        return VINF_SUCCESS;
    16831813    }
     
    18021932        pHlp->pfnSSMPutU16(pSSM,      pVirtio->uQueueEnable[i]);
    18031933        pHlp->pfnSSMPutU16(pSSM,      pVirtio->uQueueSize[i]);
    1804         pHlp->pfnSSMPutU16(pSSM,      pVirtio->virtqState[i].uAvailIdx);
    1805         pHlp->pfnSSMPutU16(pSSM,      pVirtio->virtqState[i].uUsedIdx);
     1934        pHlp->pfnSSMPutU16(pSSM,      pVirtio->virtqState[i].uAvailIdxShadow);
     1935        pHlp->pfnSSMPutU16(pSSM,      pVirtio->virtqState[i].uUsedIdxShadow);
    18061936        int rc = pHlp->pfnSSMPutMem(pSSM, pVirtio->virtqState[i].szVirtqName, 32);
    18071937        AssertRCReturn(rc, rc);
     
    18601990        pHlp->pfnSSMGetU16(pSSM, &pVirtio->uQueueEnable[i]);
    18611991        pHlp->pfnSSMGetU16(pSSM, &pVirtio->uQueueSize[i]);
    1862         pHlp->pfnSSMGetU16(pSSM, &pVirtio->virtqState[i].uAvailIdx);
    1863         pHlp->pfnSSMGetU16(pSSM, &pVirtio->virtqState[i].uUsedIdx);
     1992        pHlp->pfnSSMGetU16(pSSM, &pVirtio->virtqState[i].uAvailIdxShadow);
     1993        pHlp->pfnSSMGetU16(pSSM, &pVirtio->virtqState[i].uUsedIdxShadow);
    18641994        rc = pHlp->pfnSSMGetMem(pSSM, pVirtio->virtqState[i].szVirtqName,
    18651995                                sizeof(pVirtio->virtqState[i].szVirtqName));
     
    18982028            break;
    18992029        case kvirtIoVmStateChangedResume:
    1900             virtioNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, 0 /* idxQueue */);
     2030            virtioCoreNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, 0 /* idxQueue */);
    19012031            break;
    19022032        default:
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h

    r84468 r84774  
    5353  */
    5454#define VIRTIO_MAX_QUEUE_NAME_SIZE          32                   /**< Maximum length of a queue name           */
    55 #define VIRTQ_MAX_SIZE                      1024                 /**< Max size (# desc elements) of a virtq    */
     55#define VIRTQ_MAX_ENTRIES                   1024                 /**< Max size (# desc elements) of a virtq    */
    5656#define VIRTQ_MAX_CNT                       24                   /**< Max queues we allow guest to create      */
    5757#define VIRTIO_NOTIFY_OFFSET_MULTIPLIER     2                    /**< VirtIO Notify Cap. MMIO config param     */
     
    7171typedef struct VIRTIOSGSEG                                      /**< An S/G entry                              */
    7272{
    73     RTGCPHYS gcPhys;                                            /**< Pointer to the segment buffer             */
     73    RTGCPHYS GCPhys;                                            /**< Pointer to the segment buffer             */
    7474    size_t  cbSeg;                                              /**< Size of the segment buffer                */
    7575} VIRTIOSGSEG;
     
    8484    unsigned  cSegs;                                            /**< Number of segments                        */
    8585    unsigned  idxSeg;                                           /**< Current segment we are in                 */
    86     /** @todo r=bird: s/gcPhys/GCPhys/g as this is how we write it everywhere. */
    87     RTGCPHYS  gcPhysCur;                                        /**< Ptr to byte within the current seg        */
     86    RTGCPHYS  GCPhysCur;                                        /**< Ptr to byte within the current seg        */
    8887    size_t    cbSegLeft;                                        /**< # of bytes left in the current segment    */
    8988} VIRTIOSGBUF;
     
    110109    VIRTIOSGBUF         SgBufIn;
    111110    VIRTIOSGBUF         SgBufOut;
    112     VIRTIOSGSEG         aSegsIn[VIRTQ_MAX_SIZE];
    113     VIRTIOSGSEG         aSegsOut[VIRTQ_MAX_SIZE];
     111    VIRTIOSGSEG         aSegsIn[VIRTQ_MAX_ENTRIES];
     112    VIRTIOSGSEG         aSegsOut[VIRTQ_MAX_ENTRIES];
    114113    /** @} */
    115114} VIRTIO_DESC_CHAIN_T;
     
    188187typedef struct VIRTQSTATE
    189188{
    190     char      szVirtqName[32];                                 /**< Dev-specific name of queue                */
    191     uint16_t  uAvailIdx;                                       /**< Consumer's position in avail ring         */
    192     uint16_t  uUsedIdx;                                        /**< Consumer's position in used ring          */
    193     bool      fEventThresholdReached;                          /**< Don't lose track while queueing ahead     */
     189    uint16_t  idxQueue;                                          /**< Index of this queue                       */
     190    char      szVirtqName[32];                                   /**< Dev-specific name of queue                */
     191    uint16_t  uAvailIdxShadow;                                   /**< Consumer's position in avail ring         */
     192    uint16_t  uUsedIdxShadow;                                    /**< Consumer's position in used ring          */
     193    bool      fVirtqRingEventThreshold;                          /**< Don't lose track while queueing ahead     */
    194194} VIRTQSTATE, *PVIRTQSTATE;
    195195
     
    274274    /** @name The locations of the capability structures in PCI config space and the BAR.
    275275     * @{ */
    276     VIRTIO_PCI_CAP_LOCATIONS_T  LocPciCfgCap;                      /**< VIRTIO_PCI_CFG_CAP_T  */
    277     VIRTIO_PCI_CAP_LOCATIONS_T  LocNotifyCap;                      /**< VIRTIO_PCI_NOTIFY_CAP_T */
    278     VIRTIO_PCI_CAP_LOCATIONS_T  LocCommonCfgCap;                   /**< VIRTIO_PCI_CAP_T */
    279     VIRTIO_PCI_CAP_LOCATIONS_T  LocIsrCap;                         /**< VIRTIO_PCI_CAP_T */
    280     VIRTIO_PCI_CAP_LOCATIONS_T  LocDeviceCap;                      /**< VIRTIO_PCI_CAP_T + custom data.  */
     276    VIRTIO_PCI_CAP_LOCATIONS_T  LocPciCfgCap;                      /**< VIRTIO_PCI_CFG_CAP_T                       */
     277    VIRTIO_PCI_CAP_LOCATIONS_T  LocNotifyCap;                      /**< VIRTIO_PCI_NOTIFY_CAP_T                    */
     278    VIRTIO_PCI_CAP_LOCATIONS_T  LocCommonCfgCap;                   /**< VIRTIO_PCI_CAP_T                           */
     279    VIRTIO_PCI_CAP_LOCATIONS_T  LocIsrCap;                         /**< VIRTIO_PCI_CAP_T                           */
     280    VIRTIO_PCI_CAP_LOCATIONS_T  LocDeviceCap;                      /**< VIRTIO_PCI_CAP_T + custom data.            */
    281281    /** @} */
    282282
    283     bool                        fGenUpdatePending;                 /**< If set, update cfg gen after driver reads */
    284     uint8_t                     uPciCfgDataOff;
    285     uint8_t                     uISR;                              /**< Interrupt Status Register.                */
    286     uint8_t                     fMsiSupport;
     283    bool                        fGenUpdatePending;                 /**< If set, update cfg gen after driver reads  */
     284    uint8_t                     uPciCfgDataOff;                    /**< Offset to PCI configuration data area      */
     285    uint8_t                     uISR;                              /**< Interrupt Status Register.                 */
     286    uint8_t                     fMsiSupport;                       /**< Flag set if using MSI instead of ISR       */
    287287
    288288    /** The MMIO handle for the PCI capability region (\#2). */
     
    405405 * @{ */
    406406
    407 int  virtioCoreR3QueueAttach(PVIRTIOCORE pVirtio, uint16_t idxQueue, const char *pcszName);
    408 
    409 int  virtioCoreR3DescChainGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue,
    410                              uint16_t uHeadIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain);
     407int      virtioCoreQueueSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue);
     408uint16_t virtioCoreQueueAvailCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue);
     409void     virtioCoreQueueEnable(PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fEnable);
     410void     virtioCoreQueueNotifyEnable(PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fEnable);
     411void     virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio);
     412void     virtioCoreResetAll(PVIRTIOCORE pVirtio);
     413void     virtioCorePrintFeatures(VIRTIOCORE *pVirtio, PCDBGFINFOHLP pHlp);
     414
    411415uint32_t virtioCoreR3DescChainRetain(PVIRTIO_DESC_CHAIN_T pDescChain);
    412416uint32_t virtioCoreR3DescChainRelease(PVIRTIOCORE pVirtio, PVIRTIO_DESC_CHAIN_T pDescChain);
    413 
    414 int  virtioCoreR3QueuePeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue,
    415                            PPVIRTIO_DESC_CHAIN_T ppDescChain);
    416 
    417 int  virtioCoreR3QueueSkip(PVIRTIOCORE pVirtio, uint16_t idxQueue);
    418 
    419 int  virtioCoreR3QueueGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue,
    420                           PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove);
    421 
    422 int  virtioCoreR3QueuePut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, PRTSGBUF pSgVirtReturn,
    423                           PVIRTIO_DESC_CHAIN_T pDescChain, bool fFence);
    424 
    425 int  virtioCoreR3QueuePendingCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue);
    426 int  virtioCoreQueueSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue);
    427 bool virtioCoreQueueIsEmpty(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue);
    428 void virtioCoreQueueEnable(PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fEnabled);
    429 void virtioCoreQueueSetNotify(PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fEnabled);
    430 void virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio);
    431 void virtioCoreResetAll(PVIRTIOCORE pVirtio);
    432 void virtioPrintFeatures(VIRTIOCORE *pVirtio);
     417void     virtioCoreR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs);
     418void     virtioCoreR3QueueInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs, int idxQueue);
     419int      virtioCoreR3QueueAttach(PVIRTIOCORE pVirtio, uint16_t idxQueue, const char *pcszName);
     420
     421int      virtioCoreR3DescChainGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue,
     422                                  uint16_t uHeadIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain);
     423
     424int      virtioCoreR3QueuePeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue,
     425                               PPVIRTIO_DESC_CHAIN_T ppDescChain);
     426
     427int      virtioCoreR3QueueSkip(PVIRTIOCORE pVirtio, uint16_t idxQueue);
     428
     429int      virtioCoreR3QueueGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue,
     430                              PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove);
     431
     432int      virtioCoreR3QueuePut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, PRTSGBUF pSgVirtReturn,
     433                              PVIRTIO_DESC_CHAIN_T pDescChain, bool fFence);
     434
    433435
    434436/**
     
    437439 * @param   pVirtio     Pointer to the virtio state.
    438440 * @param   idxQueue    Queue number.
    439  * @param   fEnabled    Flag indicating whether to enable queue or not
     441 * @returns   true or false indicating whether to enable queue or not
    440442 */
    441443DECLINLINE(bool) virtioCoreIsQueueEnabled(PVIRTIOCORE pVirtio, uint16_t idxQueue)
     
    500502                                int fWrite, int fHasIndex, uint32_t idx);
    501503
     504/* Debug assist functions for consumer device code */
    502505void virtioCoreHexDump(uint8_t *pv, uint32_t cb, uint32_t uBase, const char *pszTitle);
    503 void virtioCoreGcPhysHexDump(PPDMDEVINS pDevIns, RTGCPHYS gcPhys, uint32_t cb, uint32_t uBase, const char *pszTitle);
     506void virtioCoreGCPhysHexDump(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint16_t cb, uint32_t uBase, const char *pszTitle);
     507
    504508
    505509void     virtioCoreSgBufInit(PVIRTIOSGBUF pGcSgBuf, PVIRTIOSGSEG paSegs, size_t cSegs);
     
    511515void     virtioCoreSgBufReset(PVIRTIOSGBUF pGcSgBuf);
    512516size_t   virtioCoreSgBufCalcTotalLength(PVIRTIOSGBUF pGcSgBuf);
     517
    513518int      virtioCoreR3SaveExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM);
    514519int      virtioCoreR3LoadExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM);
Note: See TracChangeset for help on using the changeset viewer.

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