VirtualBox

Changeset 84351 in vbox


Ignore:
Timestamp:
May 19, 2020 5:26:12 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
138040
Message:

Network/DevVirtioNet_1_0.cpp: Fixed R0->R3 degradation in I/O path by implementing R0 MMIO, also allows worker thread synchronization via notification from guest to run in R0. Fixed bug where wasn't properly detecting when guest suppressed interrupts, and various minor fixes. See bugref:8651, Comment #70

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

Legend:

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

    r84048 r84351  
    3131#define LOG_GROUP LOG_GROUP_DEV_VIRTIO
    3232#define VIRTIONET_WITH_GSO
     33
    3334#include <iprt/types.h>
    34 
     35#include <iprt/errcore.h>
     36#include <iprt/assert.h>
     37#include <iprt/string.h>
     38
     39#include <VBox/sup.h>
    3540#include <VBox/vmm/pdmdev.h>
    3641#include <VBox/vmm/stam.h>
     
    3944#include <VBox/msi.h>
    4045#include <VBox/version.h>
    41 //#include <VBox/asm.h>
    4246#include <VBox/log.h>
    43 #include <iprt/errcore.h>
    44 #include <iprt/assert.h>
    45 #include <iprt/string.h>
    46 #include <VBox/sup.h>
     47
    4748#ifdef IN_RING3
    48 #include <VBox/VBoxPktDmp.h>
    49 #endif
    50 #ifdef IN_RING3
     49# include <VBox/VBoxPktDmp.h>
    5150# include <iprt/alloc.h>
    5251# include <iprt/memcache.h>
     
    6160
    6261/* After debugging single instance case, restore instance name logging */
    63 #define INSTANCE(pState) (char *)(pState->szInstanceName ? "" : "") // Avoid requiring RT_NOREF in some funcs
     62#define INSTANCE(pState) (char *)(pState->szInstanceName ? pState->szInstanceName : "") // Avoid requiring RT_NOREF in some funcs
    6463
    6564#define VIRTIONET_SAVED_STATE_VERSION          UINT32_C(1)
     
    9998
    10099#define LUN0    0
     100
     101#ifdef USING_CRITICAL_SECTION
     102#  define ENTER_CRITICAL_SECTION \
     103        do { \
     104            int rc = virtioNetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY); \
     105            AssertRCReturnVoid(rc); \
     106            RT_NOREF(rc);
     107        } while(0)
     108#  define LEAVE_CRITICAL_SECTION \
     109        do { \
     110            virtioNetR3CsLeave(pDevIns, pThis); \
     111        } while(0)
     112#else
     113#   define ENTER_CRITICAL_SECTION do { } while(0)
     114#   define LEAVE_CRITICAL_SECTION do { } while(0)
     115#endif
    101116
    102117/*
     
    294309{
    295310    SUPSEMEVENT                     hEvtProcess;                /**< handle of associated sleep/wake-up semaphore      */
     311    bool volatile                   fSleeping;                  /**< Flags whether worker thread is sleeping or not    */
     312    bool volatile                   fNotified;                  /**< Flags whether worker thread notified              */
    296313} VIRTIONETWORKER;
    297314/** Pointer to a VirtIO SCSI worker. */
     
    304321{
    305322    R3PTRTYPE(PPDMTHREAD)           pThread;                    /**< pointer to worker thread's handle                 */
    306     bool volatile                   fSleeping;                  /**< Flags whether worker thread is sleeping or not    */
    307     bool volatile                   fNotified;                  /**< Flags whether worker thread notified              */
    308323    uint16_t                        idxQueue;                   /**< Index of associated queue                         */
    309324} VIRTIONETWORKERR3;
     
    530545typedef CTX_SUFF(PVIRTIONET) PVIRTIONETCC;
    531546
     547/**
     548 * Wakeup the RX thread.
     549 */
     550static void virtioNetWakeupRxBufWaiter(PPDMDEVINS pDevIns)
     551{
     552    PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
     553
     554    AssertReturnVoid(pThis->hEventRxDescAvail != NIL_SUPSEMEVENT);
     555
     556    STAM_COUNTER_INC(&pThis->StatRxOverflowWakeup);
     557
     558    Log10Func(("%s Waking downstream driver's Rx buf waiter thread\n", INSTANCE(pThis)));
     559    int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEventRxDescAvail);
     560    AssertRC(rc);
     561}
     562
     563/**
     564 * @callback_method_impl{VIRTIOCORER0,pfnQueueNotified}
     565 */
     566static DECLCALLBACK(void) virtioNetQueueNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
     567{
     568    RT_NOREF(pVirtio);
     569    PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
     570
     571    uint16_t idxWorker;
     572    if (idxQueue == CTRLQIDX)
     573        idxWorker = pThis->cWorkers - 1;
     574    else
     575        idxWorker = idxQueue / 2;
     576
     577    PVIRTIONETWORKER pWorker = &pThis->aWorkers[idxWorker];
     578    AssertReturnVoid(idxQueue < pThis->cVirtQueues);
     579
     580#if defined (IN_RING3) && defined (LOG_ENABLED)
     581     RTLogFlush(NULL);
     582#endif
     583
     584    Log10Func(("%s %s has available buffers\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
     585
     586    if (IS_RX_QUEUE(idxQueue))
     587    {
     588        Log10Func(("%s Receive buffers have been added, waking Rx thread.\n",
     589            INSTANCE(pThis)));
     590        virtioNetWakeupRxBufWaiter(pDevIns);
     591    }
     592    else
     593    {
     594        /* Wake queue's worker thread up if sleeping (e.g. a Tx queue, or the control queue */
     595        if (!ASMAtomicXchgBool(&pWorker->fNotified, true))
     596        {
     597            if (ASMAtomicReadBool(&pWorker->fSleeping))
     598            {
     599                Log10Func(("%s waking %s worker.\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
     600                int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess);
     601                AssertRC(rc);
     602            }
     603        }
     604    }
     605}
     606
    532607#ifdef IN_RING3 /* spans most of the file, at the moment. */
    533608
     
    542617}
    543618
    544 /**
    545  * Wakeup the RX thread.
    546  */
    547 static void virtioNetR3WakeupRxBufWaiter(PPDMDEVINS pDevIns)
    548 {
    549     PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    550 
    551     AssertReturnVoid(pThis->hEventRxDescAvail != NIL_SUPSEMEVENT);
    552 
    553     STAM_COUNTER_INC(&pThis->StatRxOverflowWakeup);
    554 
    555     Log10Func(("%s Waking downstream driver's Rx buf waiter thread\n", INSTANCE(pThis)));
    556     int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEventRxDescAvail);
    557     AssertRC(rc);
    558 }
    559619
    560620DECLINLINE(void) virtioNetR3SetVirtqNames(PVIRTIONET pThis)
     
    10331093     * to tell it that's going to happen...
    10341094     */
    1035     virtioNetR3WakeupRxBufWaiter(pDevIns);
     1095    virtioNetWakeupRxBufWaiter(pDevIns);
    10361096
    10371097    PDMDevHlpSetAsyncNotification(pDevIns, virtioNetR3DeviceQuiesced);
     
    10681128
    10691129    virtioNetR3QuiesceDevice(pDevIns, enmType);
    1070     virtioNetR3WakeupRxBufWaiter(pDevIns);
     1130    virtioNetWakeupRxBufWaiter(pDevIns);
    10711131}
    10721132
     
    21582218    }
    21592219
    2160     int cPkts = virtioCoreR3QueuePendingCount(pVirtio->pDevIns, pVirtio, idxTxQueue);
     2220    int cPkts = virtioCoreR3QueuePendingCount(pVirtio->pDevInsR3, pVirtio, idxTxQueue);
    21612221    if (!cPkts)
    21622222    {
     
    21752235    int rc;
    21762236    PVIRTIO_DESC_CHAIN_T pDescChain = NULL;
    2177     while ((rc = virtioCoreR3QueuePeek(pVirtio->pDevIns, pVirtio, idxTxQueue, &pDescChain)) == VINF_SUCCESS)
     2237    while ((rc = virtioCoreR3QueuePeek(pVirtio->pDevInsR3, pVirtio, idxTxQueue, &pDescChain)) == VINF_SUCCESS)
    21782238    {
    21792239        Log10Func(("%s fetched descriptor chain from %s\n", INSTANCE(pThis), VIRTQNAME(idxTxQueue)));
     
    22052265            uint64_t uOffset;
    22062266
    2207             /** @todo Optimize away the extra copying! (lazy bird) */
    22082267            PPDMSCATTERGATHER pSgBufToPdmLeafDevice;
    22092268            rc = pThisCC->pDrv->pfnAllocBuf(pThisCC->pDrv, uSize, pGso, &pSgBufToPdmLeafDevice);
     
    22652324
    22662325            /* No data to return to guest, but call is needed put elem (e.g. desc chain) on used ring */
    2267             virtioCoreR3QueuePut(pVirtio->pDevIns, pVirtio, idxTxQueue, NULL, pDescChain, false);
     2326            virtioCoreR3QueuePut(pVirtio->pDevInsR3, pVirtio, idxTxQueue, NULL, pDescChain, false);
    22682327
    22692328            /* Update used ring idx and notify guest that we've transmitted the data it sent */
    2270             virtioCoreQueueSync(pVirtio->pDevIns, pVirtio, idxTxQueue, false);
     2329            virtioCoreQueueSync(pVirtio->pDevInsR3, pVirtio, idxTxQueue, false);
    22712330        }
    22722331
     
    22972356          selection algorithm feasible or even necessary */
    22982357    virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, TXQIDX(0), false /*fOnWorkerThread*/);
    2299 }
    2300 
    2301 /**
    2302  * @callback_method_impl{VIRTIOCORER3,pfnQueueNotified}
    2303  */
    2304 static DECLCALLBACK(void) virtioNetR3QueueNotified(PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, uint16_t idxQueue)
    2305 {
    2306     PVIRTIONET         pThis     = RT_FROM_MEMBER(pVirtio, VIRTIONET, Virtio);
    2307     PVIRTIONETCC       pThisCC   = RT_FROM_MEMBER(pVirtioCC, VIRTIONETCC, Virtio);
    2308     PPDMDEVINS         pDevIns   = pThisCC->pDevIns;
    2309 
    2310     uint16_t idxWorker;
    2311     if (idxQueue == CTRLQIDX)
    2312         idxWorker = pThis->cWorkers - 1;
    2313     else
    2314         idxWorker = idxQueue / 2;
    2315 
    2316     PVIRTIONETWORKER   pWorker   = &pThis->aWorkers[idxWorker];
    2317     PVIRTIONETWORKERR3 pWorkerR3 = &pThisCC->aWorkers[idxWorker];
    2318     AssertReturnVoid(idxQueue < pThis->cVirtQueues);
    2319 
    2320 #ifdef LOG_ENABLED
    2321     RTLogFlush(NULL);
    2322 #endif
    2323 
    2324     Log10Func(("%s %s has available buffers\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
    2325 
    2326     if (IS_RX_QUEUE(idxQueue))
    2327     {
    2328         Log10Func(("%s Receive buffers have been added, waking Rx thread.\n",
    2329             INSTANCE(pThis)));
    2330         virtioNetR3WakeupRxBufWaiter(pDevIns);
    2331     }
    2332     else
    2333     {
    2334         /* Wake queue's worker thread up if sleeping (e.g. a Tx queue, or the control queue */
    2335         if (!ASMAtomicXchgBool(&pWorkerR3->fNotified, true))
    2336         {
    2337             if (ASMAtomicReadBool(&pWorkerR3->fSleeping))
    2338             {
    2339                 Log10Func(("%s waking %s worker.\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
    2340                 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess);
    2341                 AssertRC(rc);
    2342             }
    2343         }
    2344     }
    23452358}
    23462359
     
    23672380        if (virtioCoreQueueIsEmpty(pDevIns, &pThis->Virtio, idxQueue))
    23682381        {
     2382            /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */
    23692383            virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, true);
    2370             /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */
    2371             ASMAtomicWriteBool(&pWorkerR3->fSleeping, true);
    2372             bool fNotificationSent = ASMAtomicXchgBool(&pWorkerR3->fNotified, false);
     2384            ASMAtomicWriteBool(&pWorker->fSleeping, true);
     2385            bool fNotificationSent = ASMAtomicXchgBool(&pWorker->fNotified, false);
    23732386            if (!fNotificationSent)
    23742387            {
    2375                 virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, true);
    23762388                Log10Func(("%s %s worker sleeping...\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
    2377                 Assert(ASMAtomicReadBool(&pWorkerR3->fSleeping));
     2389                Assert(ASMAtomicReadBool(&pWorker->fSleeping));
    23782390                int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pWorker->hEvtProcess, RT_INDEFINITE_WAIT);
    23792391                STAM_COUNTER_INC(&pThis->StatTransmitByThread);
     
    23872399                }
    23882400                Log10Func(("%s %s worker woken\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));
    2389                 ASMAtomicWriteBool(&pWorkerR3->fNotified, false);
     2401                ASMAtomicWriteBool(&pWorker->fNotified, false);
    23902402            }
    2391             ASMAtomicWriteBool(&pWorkerR3->fSleeping, false);
     2403            ASMAtomicWriteBool(&pWorker->fSleeping, false);
    23922404            virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, false);
    23932405        }
     
    24142426                 Log10Func(("%s Notified of data to transmit\n", INSTANCE(pThis)));
    24152427                 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC,
    2416                                                    idxQueue, true /* fOnWorkerThread */);
     2428                                                   idxQueue, false /* fOnWorkerThread */);
    24172429             }
    24182430
    24192431             /* Rx queues aren't handled by our worker threads. Instead, the PDM network
    24202432              * leaf driver invokes PDMINETWORKDOWN.pfnWaitReceiveAvail() callback,
    2421               * which waits until notified directly by virtioNetR3QueueNotified()
     2433              * which waits until notified directly by virtioNetQueueNotified()
    24222434              * that guest IN buffers have been added to receive virt queue.
    24232435              */
     
    24272439}
    24282440
     2441#ifdef USING_CRITICAL_SECTION
    24292442DECLINLINE(int) virtioNetR3CsEnter(PPDMDEVINS pDevIns, PVIRTIONET pThis, int rcBusy)
    24302443{
     
    24402453    LogFunc(("%s CS unimplemented. What does the critical section protect in orig driver??", INSTANCE(pThis)));
    24412454}
    2442 
     2455#endif /* USING_CRITICAL_SECTION */
    24432456
    24442457/**
     
    24512464    RT_NOREF(pTimer, pvUser);
    24522465
    2453     int rc = virtioNetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY);
    2454     AssertRCReturnVoid(rc);
     2466    ENTER_CRITICAL_SECTION;
    24552467
    24562468    SET_LINK_UP(pThis);
    24572469
    2458     virtioNetR3WakeupRxBufWaiter(pDevIns);
    2459 
    2460     virtioNetR3CsLeave(pDevIns, pThis);
     2470    virtioNetWakeupRxBufWaiter(pDevIns);
     2471
     2472    LEAVE_CRITICAL_SECTION;
    24612473
    24622474    LogFunc(("%s Link is up\n", INSTANCE(pThis)));
     
    26462658            (void) virtioCoreR3QueueAttach(&pThis->Virtio, idxQueue, VIRTQNAME(idxQueue));
    26472659            pThis->afQueueAttached[idxQueue] = true;
    2648             virtioCoreQueueIsEmpty(pThisCC->pDevIns, &pThis->Virtio, idxQueue);
    2649             virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, true);
     2660            if (virtioCoreQueueIsEmpty(pThisCC->pDevIns, &pThis->Virtio, idxQueue))
     2661                virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, true);
    26502662        }
    26512663    }
     
    26952707    AssertLogRelReturnVoid(iLUN == 0);
    26962708
    2697     int rc = virtioNetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY);
    2698     AssertMsgRCReturnVoid(rc, ("Failed to enter critical section"));
     2709    ENTER_CRITICAL_SECTION;
     2710
     2711    RT_NOREF(pThis);
    26992712
    27002713    /*
     
    27042717    pThisCC->pDrv     = NULL;
    27052718
    2706     virtioNetR3CsLeave(pDevIns, pThis);
     2719    LEAVE_CRITICAL_SECTION;
    27072720}
    27082721
     
    27232736    AssertLogRelReturn(iLUN == 0, VERR_PDM_NO_SUCH_LUN);
    27242737
    2725     int rc = virtioNetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY);
    2726     AssertMsgRCReturn(rc, ("Failed to enter critical section"), rc);
    2727 
    2728     rc = PDMDevHlpDriverAttach(pDevIns, 0, &pDevIns->IBase, &pThisCC->pDrvBase, "Network Port");
     2738    ENTER_CRITICAL_SECTION;
     2739
     2740    RT_NOREF(pThis);
     2741
     2742    int rc = PDMDevHlpDriverAttach(pDevIns, 0, &pDevIns->IBase, &pThisCC->pDrvBase, "Network Port");
    27292743    if (RT_SUCCESS(rc))
    27302744    {
     
    27372751                    Log(("%s No attached driver!\n", INSTANCE(pThis)));
    27382752
    2739     virtioNetR3CsLeave(pDevIns, pThis);
     2753    LEAVE_CRITICAL_SECTION;
    27402754    return rc;
    27412755
     
    28112825     */
    28122826    Log7Func(("PDM device instance: %d\n", iInstance));
    2813 
    28142827
    28152828    RTStrPrintf(pThis->szInstanceName, sizeof(pThis->szInstanceName), "VIRTIONET", iInstance);
     
    28642877    memcpy(pThis->virtioNetConfig.uMacAddress.au8, pThis->macConfigured.au8, sizeof(pThis->virtioNetConfig.uMacAddress)); /* TBD */
    28652878
     2879
     2880    LogFunc(("RC=%RTbool R0=%RTbool\n", pDevIns->fRCEnabled, pDevIns->fR0Enabled));
     2881
    28662882    /*
    28672883     * Do core virtio initialization.
     
    28772893
    28782894    /* Initialize the generic Virtio core: */
     2895    pThisCC->Virtio.pfnQueueNotified        = virtioNetQueueNotified;
    28792896    pThisCC->Virtio.pfnStatusChanged        = virtioNetR3StatusChanged;
    2880     pThisCC->Virtio.pfnQueueNotified        = virtioNetR3QueueNotified;
    28812897    pThisCC->Virtio.pfnDevCapRead           = virtioNetR3DevCapRead;
    28822898    pThisCC->Virtio.pfnDevCapWrite          = virtioNetR3DevCapWrite;
     
    30143030    PVIRTIONET   pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    30153031    PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC);
    3016 
    3017 LogRelFunc(("\n"));
    3018     return virtioCoreRZInit(pDevIns, &pThis->Virtio, &pThisCC->Virtio);
     3032    pThisCC->Virtio.pfnQueueNotified = virtioNetQueueNotified;
     3033    return virtioCoreRZInit(pDevIns, &pThis->Virtio);
    30193034}
    30203035
    30213036#endif /* !IN_RING3 */
    30223037
    3023 
    3024 
    30253038/**
    30263039 * The device registration structure.
     
    30283041const PDMDEVREG g_DeviceVirtioNet_1_0 =
    30293042{
    3030     /* .uVersion = */             PDM_DEVREG_VERSION,
     3043    /* .uVersion = */               PDM_DEVREG_VERSION,
    30313044    /* .uReserved0 = */             0,
    30323045    /* .szName = */                 "virtio-net-1-dot-0",
    3033     /* .fFlags = */                 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_NEW_STYLE | PDM_DEVREG_FLAGS_RZ
    3034                                     | PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION
    3035                                     | PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION,
     3046    /* .fFlags = */                 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_NEW_STYLE | PDM_DEVREG_FLAGS_RZ,
    30363047    /* .fClass = */                 PDM_DEVREG_CLASS_NETWORK,
    30373048    /* .cMaxInstances = */          ~0U,
  • trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp

    r84003 r84351  
    343343{
    344344    SUPSEMEVENT                     hEvtProcess;                /**< handle of associated sleep/wake-up semaphore      */
     345    bool volatile                   fSleeping;                  /**< Flags whether worker thread is sleeping or not    */
     346    bool volatile                   fNotified;                  /**< Flags whether worker thread notified              */
    345347} VIRTIOSCSIWORKER;
    346348/** Pointer to a VirtIO SCSI worker. */
     
    353355{
    354356    R3PTRTYPE(PPDMTHREAD)           pThread;                    /**< pointer to worker thread's handle                 */
    355     bool volatile                   fSleeping;                  /**< Flags whether worker thread is sleeping or not    */
    356     bool volatile                   fNotified;                  /**< Flags whether worker thread notified              */
    357357    uint16_t                        auRedoDescs[VIRTQ_MAX_SIZE];/**< List of previously suspended reqs to re-submit    */
    358358    uint16_t                        cRedoDescs;                 /**< Number of redo desc chain head desc idxes in list */
     
    567567} VIRTIOSCSIREQ;
    568568typedef VIRTIOSCSIREQ *PVIRTIOSCSIREQ;
     569
     570
     571/**
     572 * @callback_method_impl{VIRTIOCORER0,pfnQueueNotified}
     573 */
     574static DECLCALLBACK(void) virtioScsiNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t qIdx)
     575{
     576
     577    RT_NOREF(pVirtio);
     578    PVIRTIOSCSI pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
     579
     580    AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT);
     581    PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx];
     582
     583#if defined (IN_RING3) && defined (LOG_ENABLED)
     584   RTLogFlush(NULL);
     585#endif
     586
     587    if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx))
     588    {
     589        Log6Func(("%s has available data\n", VIRTQNAME(qIdx)));
     590        /* Wake queue's worker thread up if sleeping */
     591        if (!ASMAtomicXchgBool(&pWorker->fNotified, true))
     592        {
     593            if (ASMAtomicReadBool(&pWorker->fSleeping))
     594            {
     595                Log6Func(("waking %s worker.\n", VIRTQNAME(qIdx)));
     596                int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess);
     597                AssertRC(rc);
     598            }
     599        }
     600    }
     601    else if (qIdx == EVENTQ_IDX)
     602    {
     603        Log3Func(("Driver queued buffer(s) to %s\n", VIRTQNAME(qIdx)));
     604//        if (ASMAtomicXchgBool(&pThis->fEventsMissed, false))
     605//            virtioScsiR3ReportEventsMissed(pDevIns, pThis, 0);
     606    }
     607    else
     608        LogFunc(("Unexpected queue idx (ignoring): %d\n", qIdx));
     609}
    569610
    570611
     
    15091550        {
    15101551            /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */
    1511             ASMAtomicWriteBool(&pWorkerR3->fSleeping, true);
    1512             bool fNotificationSent = ASMAtomicXchgBool(&pWorkerR3->fNotified, false);
     1552            ASMAtomicWriteBool(&pWorker->fSleeping, true);
     1553            bool fNotificationSent = ASMAtomicXchgBool(&pWorker->fNotified, false);
    15131554            if (!fNotificationSent)
    15141555            {
    15151556                Log6Func(("%s worker sleeping...\n", VIRTQNAME(qIdx)));
    1516                 Assert(ASMAtomicReadBool(&pWorkerR3->fSleeping));
     1557                Assert(ASMAtomicReadBool(&pWorker->fSleeping));
    15171558                int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pWorker->hEvtProcess, RT_INDEFINITE_WAIT);
    15181559                AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc);
     
    15221563                    continue;
    15231564                Log6Func(("%s worker woken\n", VIRTQNAME(qIdx)));
    1524                 ASMAtomicWriteBool(&pWorkerR3->fNotified, false);
     1565                ASMAtomicWriteBool(&pWorker->fNotified, false);
    15251566            }
    1526             ASMAtomicWriteBool(&pWorkerR3->fSleeping, false);
     1567            ASMAtomicWriteBool(&pWorker->fSleeping, false);
    15271568        }
    15281569
     
    16241665
    16251666#endif
    1626 
    1627 /**
    1628  * @callback_method_impl{VIRTIOCORER3,pfnQueueNotified}
    1629  */
    1630 static DECLCALLBACK(void) virtioScsiR3Notified(PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, uint16_t qIdx)
    1631 {
    1632     PVIRTIOSCSI         pThis     = RT_FROM_MEMBER(pVirtio, VIRTIOSCSI, Virtio);
    1633     PVIRTIOSCSICC       pThisCC   = RT_FROM_MEMBER(pVirtioCC, VIRTIOSCSICC, Virtio);
    1634     PPDMDEVINS          pDevIns   = pThisCC->pDevIns;
    1635     AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT);
    1636     PVIRTIOSCSIWORKER   pWorker   = &pThis->aWorkers[qIdx];
    1637     PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[qIdx];
    1638 
    1639 #ifdef LOG_ENABLED
    1640     RTLogFlush(NULL);
    1641 #endif
    1642 
    1643     if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx))
    1644     {
    1645         Log6Func(("%s has available data\n", VIRTQNAME(qIdx)));
    1646         /* Wake queue's worker thread up if sleeping */
    1647         if (!ASMAtomicXchgBool(&pWorkerR3->fNotified, true))
    1648         {
    1649             if (ASMAtomicReadBool(&pWorkerR3->fSleeping))
    1650             {
    1651                 Log6Func(("waking %s worker.\n", VIRTQNAME(qIdx)));
    1652                 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess);
    1653                 AssertRC(rc);
    1654             }
    1655         }
    1656     }
    1657     else if (qIdx == EVENTQ_IDX)
    1658     {
    1659         Log3Func(("Driver queued buffer(s) to %s\n", VIRTQNAME(qIdx)));
    1660         if (ASMAtomicXchgBool(&pThis->fEventsMissed, false))
    1661             virtioScsiR3ReportEventsMissed(pDevIns, pThis, 0);
    1662     }
    1663     else
    1664         LogFunc(("Unexpected queue idx (ignoring): %d\n", qIdx));
    1665 }
    16661667
    16671668/**
     
    23202321    for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++)
    23212322    {
    2322         if (ASMAtomicReadBool(&pThisCC->aWorkers[qIdx].fSleeping))
     2323        if (ASMAtomicReadBool(&pThis->aWorkers[qIdx].fSleeping))
    23232324        {
    23242325            Log6Func(("waking %s worker.\n", VIRTQNAME(qIdx)));
     
    24362437     */
    24372438    pThisCC->pDevIns = pDevIns;
     2439//    pDevIns->pVirtio = &pThis->Virtio;
    24382440
    24392441    LogFunc(("PDM device instance: %d\n", iInstance));
     
    24812483
    24822484    /* Initialize the generic Virtio core: */
     2485    pThisCC->Virtio.pfnQueueNotified        = virtioScsiNotified;
    24832486    pThisCC->Virtio.pfnStatusChanged        = virtioScsiR3StatusChanged;
    2484     pThisCC->Virtio.pfnQueueNotified        = virtioScsiR3Notified;
    24852487    pThisCC->Virtio.pfnDevCapRead           = virtioScsiR3DevCapRead;
    24862488    pThisCC->Virtio.pfnDevCapWrite          = virtioScsiR3DevCapWrite;
     
    26422644{
    26432645    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
     2646
    26442647    PVIRTIOSCSI   pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    26452648    PVIRTIOSCSICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);
    26462649
    2647     return virtioCoreRZInit(pDevIns, &pThis->Virtio, &pThisCC->Virtio);
     2650
     2651    pThisCC->Virtio.pfnQueueNotified = virtioScsiNotified;
     2652    return virtioCoreRZInit(pDevIns, &pThis->Virtio);
    26482653}
    26492654
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r83915 r84351  
    123123 * @{ */
    124124
    125 #if 0 /* unused */
    126 DECLINLINE(int) virtqIsEventNeeded(uint16_t uEventIdx, uint16_t uDescIdxNew, uint16_t uDescIdxOld)
    127 {
    128     return (uint16_t)(uDescIdxNew - uEventIdx - 1) < (uint16_t)(uDescIdxNew - uDescIdxOld);
    129 }
    130 #endif
    131 
    132125/**
    133126 * Accessor for virtq descriptor
     
    160153    return uDescIdx;
    161154}
    162 #endif
    163 
    164 DECLINLINE(uint16_t) virtioReadAvailRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
    165 {
    166     uint16_t uIdx = 0;
    167     AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    168     PDMDevHlpPCIPhysRead(pDevIns,
    169                       pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx),
    170                       &uIdx, sizeof(uIdx));
    171     return uIdx;
    172 }
    173 
    174 DECLINLINE(bool) virtqIsEmpty(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
    175 {
    176     uint16_t uAvailGuestIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, idxQueue);
    177     bool fEmpty = uAvailGuestIdx == pVirtio->virtqState[idxQueue].uAvailIdx;
    178 
    179     Log6Func(("%s idx=%u, shadow idx=%u (%s)\n",
    180              VIRTQNAME(pVirtio, idxQueue), uAvailGuestIdx, pVirtio->virtqState[idxQueue].uAvailIdx,
    181              fEmpty ? "Queue empty" : "Queue has available descriptors"));
    182     return fEmpty;
    183 }
    184 
    185 #if 0 /* unused - Will be used when VIRTIO_F_EVENT_IDX optional feature is implemented, VirtIO 1.0, 2.4.7 */
    186 DECLINLINE(uint16_t) virtioReadAvailFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
    187 {
    188     uint16_t fFlags;
    189     AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    190     PDMDevHlpPCIPhysRead(pDevIns,
    191                       pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF(VIRTQ_AVAIL_T, fFlags),
    192                       &fFlags, sizeof(fFlags));
    193     return fFlags;
    194 }
    195 #endif
    196 
    197 #ifdef IN_RING3
     155
    198156DECLINLINE(uint16_t) virtioReadAvailUsedEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
    199157{
     
    207165}
    208166#endif
     167
     168DECLINLINE(uint16_t) virtioReadAvailRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
     169{
     170    uint16_t uIdx = 0;
     171    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
     172    PDMDevHlpPCIPhysRead(pDevIns,
     173                      pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx),
     174                      &uIdx, sizeof(uIdx));
     175    return uIdx;
     176}
     177
     178DECLINLINE(bool) virtqIsEmpty(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
     179{
     180    uint16_t uAvailGuestIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, idxQueue);
     181    bool fEmpty = uAvailGuestIdx == pVirtio->virtqState[idxQueue].uAvailIdx;
     182
     183    Log6Func(("%s idx=%u, shadow idx=%u (%s)\n",
     184             VIRTQNAME(pVirtio, idxQueue), uAvailGuestIdx, pVirtio->virtqState[idxQueue].uAvailIdx,
     185             fEmpty ? "Queue empty" : "Queue has available descriptors"));
     186    return fEmpty;
     187}
     188
     189DECLINLINE(uint16_t) virtioReadAvailRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)
     190{
     191    uint16_t fFlags;
     192    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
     193    PDMDevHlpPCIPhysRead(pDevIns,
     194                      pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF(VIRTQ_AVAIL_T, fFlags),
     195                      &fFlags, sizeof(fFlags));
     196    return fFlags;
     197}
    209198
    210199/** @} */
     
    422411    for (unsigned i = 0; i < RT_ELEMENTS(s_aFeatures); ++i)
    423412    {
    424         bool isOffered    = !!(pVirtio->uDeviceFeatures & s_aFeatures[i].fFeatureBit);
    425         bool isNegotiated = !!(pVirtio->uDriverFeatures & s_aFeatures[i].fFeatureBit);
     413        bool isOffered    = RT_BOOL(pVirtio->uDeviceFeatures & s_aFeatures[i].fFeatureBit);
     414        bool isNegotiated = RT_BOOL(pVirtio->uDriverFeatures & s_aFeatures[i].fFeatureBit);
    426415        cp += RTStrPrintf(cp, cbBuf - (cp - pszBuf), "        %s       %s   %s",
    427416                          isOffered ? "+" : "-", isNegotiated ? "x" : " ", s_aFeatures[i].pcszDesc);
     
    810799void virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio)
    811800{
    812     virtioKick(pVirtio->pDevIns, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false);
     801    virtioKick(pVirtio->pDevInsR3, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false);
    813802}
    814803
     
    824813    if (pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
    825814    {
    826         uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevIns, pVirtio, idxQueue);
     815        uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, idxQueue);
    827816
    828817        if (fEnabled)
     
    831820            fFlags |= VIRTQ_USED_F_NO_NOTIFY;
    832821
    833         virtioWriteUsedRingFlags(pVirtio->pDevIns, pVirtio, idxQueue, fFlags);
     822        virtioWriteUsedRingFlags(pVirtio->pDevInsR3, pVirtio, idxQueue, fFlags);
    834823    }
    835824}
     
    848837    {
    849838        pVirtio->fGenUpdatePending = true;
    850         virtioKick(pVirtio->pDevIns, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false /* fForce */);
     839        virtioKick(pVirtio->pDevInsR3, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false /* fForce */);
    851840    }
    852841}
     
    915904                    ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
    916905
    917     if (virtioCoreQueueIsEmpty(pVirtio->pDevIns, pVirtio, idxQueue))
     906    if (virtioCoreQueueIsEmpty(pVirtio->pDevInsR3, pVirtio, idxQueue))
    918907        return VERR_NOT_AVAILABLE;
    919908
     
    10241013        size_t cbTarget = virtioCoreSgBufCalcTotalLength(pSgPhysReturn);
    10251014        cbRemain = cbTotal = RTSgBufCalcTotalLength(pSgVirtReturn);
    1026         AssertMsgReturn(cbTarget >= cbRemain, ("Not space to write data to phys memory"), VERR_BUFFER_OVERFLOW);
     1015        AssertMsgReturn(cbTarget >= cbRemain, ("No space to write data to phys memory"), VERR_BUFFER_OVERFLOW);
    10271016        virtioCoreSgBufReset(pSgPhysReturn); /* Reset ptr because req data may have already been written */
    10281017        while (cbRemain)
     
    10851074int virtioCoreQueueSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fForce)
    10861075{
    1087     Assert(idxQueue < RT_ELEMENTS(pVirtio->virtqState));
     1076    Assert(idxQueue        < RT_ELEMENTS(pVirtio->virtqState));
    10881077    PVIRTQSTATE pVirtq = &pVirtio->virtqState[idxQueue];
    10891078
     
    11001089}
    11011090
    1102 #ifdef IN_RING3
    1103 /**
    1104  */
    1105 static void virtioR3QueueNotified(PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, uint16_t idxQueue, uint16_t uNotifyIdx)
    1106 {
     1091/**
     1092 */
     1093static void virtioQueueNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, uint16_t uNotifyIdx)
     1094{
     1095
     1096    PVIRTIOCORECC pVirtioCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOCORECC);
     1097
    11071098    /* See VirtIO 1.0, section 4.1.5.2 It implies that idxQueue and uNotifyIdx should match.
    11081099     * Disregarding this notification may cause throughput to stop, however there's no way to know
     
    11181109
    11191110    /* Inform client */
    1120     pVirtioCC->pfnQueueNotified(pVirtio, pVirtioCC, idxQueue);
    1121 }
    1122 #endif /* IN_RING3 */
     1111    pVirtioCC->pfnQueueNotified(pDevIns, pVirtio, idxQueue);
     1112}
    11231113
    11241114/**
     
    11521142        Log6Func(("...kicking guest %s, VIRTIO_F_EVENT_IDX set and threshold (%d) reached\n",
    11531143                   VIRTQNAME(pVirtio, idxQueue), (uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxQueue)));
    1154 #else
    1155         Log6Func(("... kicking guest %s, VIRTIO_F_EVENT_IDX set and threshold reached\n",
    1156                    VIRTQNAME(pVirtio, idxQueue)));
    11571144#endif
    11581145            virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uQueueMsixVector[idxQueue], fForce);
     
    11631150        Log6Func(("...skipping interrupt %s, VIRTIO_F_EVENT_IDX set but threshold (%d) not reached (%d)\n",
    11641151                   VIRTQNAME(pVirtio, idxQueue),(uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxQueue), pVirtq->uUsedIdx));
    1165 #else
    1166         Log6Func(("...skipping interrupt %s, VIRTIO_F_EVENT_IDX set but threshold not reached\n",
    1167                     VIRTQNAME(pVirtio, idxQueue)));
    11681152#endif
    11691153    }
     
    11711155    {
    11721156        /** If guest driver hasn't suppressed interrupts, interrupt  */
    1173         if (fForce || !(virtioReadUsedRingFlags(pDevIns, pVirtio, idxQueue) & VIRTQ_AVAIL_F_NO_INTERRUPT))
     1157        if (fForce || !(virtioReadAvailRingFlags(pDevIns, pVirtio, idxQueue) & VIRTQ_AVAIL_F_NO_INTERRUPT))
    11741158        {
    11751159            if (fForce)
     
    12421226        pVirtio->uQueueMsixVector[idxQueue] = VIRTIO_MSI_NO_VECTOR;
    12431227
    1244     virtioLowerInterrupt(pVirtio->pDevIns, pVirtio->uQueueMsixVector[idxQueue]);
     1228    virtioLowerInterrupt(pVirtio->pDevInsR3, pVirtio->uQueueMsixVector[idxQueue]);
    12451229}
    12461230
     
    14761460        {
    14771461            uint8_t const fNewStatus = *(uint8_t *)pv;
    1478             Log7Func(("Guest wrote uDeviceStatus (%#x, was %#x, change #%x) ................ (",
    1479                       fNewStatus, pVirtio->uDeviceStatus, fNewStatus ^ pVirtio->uDeviceStatus));
     1462            Log7Func(("Guest wrote uDeviceStatus ................ (", fNewStatus ^ pVirtio->uDeviceStatus));
    14801463            if (LogIs7Enabled())
    14811464                virtioLogDeviceStatus(fNewStatus);
     
    15791562 *
    15801563 * This MMIO handler specifically supports the VIRTIO_PCI_CAP_PCI_CFG capability defined
    1581  * in the VirtIO 1.0 specification, section 4.1.4.7, and as such is limited to cb == 1, cb == 2, or cb==4 type reads.
     1564 * in the VirtIO 1.0 specification, section 4.1.4.7, and as such is restricted to reads
     1565 * of 1, 2 or 4 bytes, only.
    15821566 *
    15831567 */
     
    15881572    AssertReturn(cb == 1 || cb == 2 || cb == 4, VERR_INVALID_PARAMETER);
    15891573    Assert(pVirtio == (PVIRTIOCORE)pvUser); RT_NOREF(pvUser);
     1574
    15901575
    15911576    uint32_t offIntra;
     
    16031588         * order to maintain the config generation (see VirtIO 1.0 spec, section 4.1.4.3.1)
    16041589         */
    1605         bool fDevSpecificFieldChanged = !!memcmp(pVirtioCC->pbDevSpecificCfg + offIntra,
     1590        bool fDevSpecificFieldChanged = RT_BOOL(memcmp(pVirtioCC->pbDevSpecificCfg + offIntra,
    16061591                                                 pVirtioCC->pbPrevDevSpecificCfg + offIntra,
    1607                                                  RT_MIN(cb, pVirtioCC->cbDevSpecificCfg - offIntra));
     1592                                                 RT_MIN(cb, pVirtioCC->cbDevSpecificCfg - offIntra)));
    16081593
    16091594        memcpy(pVirtioCC->pbPrevDevSpecificCfg, pVirtioCC->pbDevSpecificCfg, pVirtioCC->cbDevSpecificCfg);
     
    16471632 *
    16481633 * This MMIO handler specifically supports the VIRTIO_PCI_CAP_PCI_CFG capability defined
    1649  * in the VirtIO 1.0 specification, section 4.1.4.7, and as such is limited
    1650  * to cb == 1, cb == 2, or cb==4 type writes.
     1634 * in the VirtIO 1.0 specification, section 4.1.4.7, and as such is restricted to writes
     1635 * of 1, 2 or 4 bytes, only.
    16511636 */
    16521637static DECLCALLBACK(VBOXSTRICTRC) virtioMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb)
     
    16581643
    16591644    Assert(pVirtio == (PVIRTIOCORE)pvUser); RT_NOREF(pvUser);
    1660 
    16611645    uint32_t offIntra;
    16621646    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, offIntra, pVirtio->LocDeviceCap))
     
    16881672    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, offIntra, pVirtio->LocNotifyCap) && cb == sizeof(uint16_t))
    16891673    {
    1690 #ifdef IN_RING3
    1691         virtioR3QueueNotified(pVirtio, pVirtioCC, offIntra / VIRTIO_NOTIFY_OFFSET_MULTIPLIER, *(uint16_t *)pv);
     1674        virtioQueueNotified(pDevIns, pVirtio, offIntra / VIRTIO_NOTIFY_OFFSET_MULTIPLIER, *(uint16_t *)pv);
    16921675        return VINF_SUCCESS;
    1693 #else
    1694         return VINF_IOM_R3_MMIO_WRITE;
    1695 #endif
    16961676    }
    16971677
     
    17211701         * (the virtio_pci_cfg_cap capability), and access data items.
    17221702         */
    1723         uint32_t uLength = pVirtioCC->pPciCfgCap->pciCap.uLength;
    1724         uint32_t uOffset = pVirtioCC->pPciCfgCap->pciCap.uOffset;
    1725         uint8_t  uBar    = pVirtioCC->pPciCfgCap->pciCap.uBar;
     1703        struct virtio_pci_cap *pPciCap = &pVirtioCC->pPciCfgCap->pciCap;
     1704        uint32_t uLength = pPciCap->uLength;
    17261705
    17271706        if (   (uLength != 1 && uLength != 2 && uLength != 4)
    17281707            || cb != uLength
    1729             || uBar != VIRTIO_REGION_PCI_CAP)
     1708            ||  pPciCap->uBar != VIRTIO_REGION_PCI_CAP)
    17301709        {
    17311710            ASSERT_GUEST_MSG_FAILED(("Guest read virtio_pci_cfg_cap.pci_cfg_data using mismatching config. Ignoring\n"));
     
    17341713        }
    17351714
    1736         VBOXSTRICTRC rcStrict = virtioMmioRead(pDevIns, pVirtio, uOffset, pu32Value, cb);
     1715        VBOXSTRICTRC rcStrict = virtioMmioRead(pDevIns, pVirtio, pPciCap->uOffset, pu32Value, cb);
    17371716        Log2Func(("virtio: Guest read  virtio_pci_cfg_cap.pci_cfg_data, bar=%d, offset=%d, length=%d, result=%d -> %Rrc\n",
    1738                   uBar, uOffset, uLength, *pu32Value, VBOXSTRICTRC_VAL(rcStrict)));
     1717                   pPciCap->uBar, pPciCap->uOffset, uLength, *pu32Value, VBOXSTRICTRC_VAL(rcStrict)));
    17391718        return rcStrict;
    17401719    }
     
    17591738         * (the virtio_pci_cfg_cap capability), and access data items. */
    17601739
    1761         uint32_t uLength = pVirtioCC->pPciCfgCap->pciCap.uLength;
    1762         uint32_t uOffset = pVirtioCC->pPciCfgCap->pciCap.uOffset;
    1763         uint8_t  uBar    = pVirtioCC->pPciCfgCap->pciCap.uBar;
     1740        struct virtio_pci_cap *pPciCap = &pVirtioCC->pPciCfgCap->pciCap;
     1741        uint32_t uLength = pPciCap->uLength;
    17641742
    17651743        if (   (uLength != 1 && uLength != 2 && uLength != 4)
    17661744            || cb != uLength
    1767             || uBar != VIRTIO_REGION_PCI_CAP)
     1745            ||  pPciCap->uBar != VIRTIO_REGION_PCI_CAP)
    17681746        {
    17691747            ASSERT_GUEST_MSG_FAILED(("Guest write virtio_pci_cfg_cap.pci_cfg_data using mismatching config. Ignoring\n"));
     
    17711749        }
    17721750
    1773         VBOXSTRICTRC rcStrict = virtioMmioWrite(pDevIns, pVirtio, uOffset, &u32Value, cb);
     1751        VBOXSTRICTRC rcStrict = virtioMmioWrite(pDevIns, pVirtio, pPciCap->uOffset, &u32Value, cb);
    17741752        Log2Func(("Guest wrote  virtio_pci_cfg_cap.pci_cfg_data, bar=%d, offset=%x, length=%x, value=%d -> %Rrc\n",
    1775                   uBar, uOffset, uLength, u32Value, VBOXSTRICTRC_VAL(rcStrict)));
     1753                   pPciCap->uBar, pPciCap->uOffset, uLength, u32Value, VBOXSTRICTRC_VAL(rcStrict)));
    17761754        return rcStrict;
    17771755    }
     
    19131891            break;
    19141892        case kvirtIoVmStateChangedResume:
    1915             virtioNotifyGuestDriver(pVirtio->pDevIns, pVirtio, 0 /* idxQueue */, true /* fForce */);
     1893            virtioNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, 0 /* idxQueue */, true /* fForce */);
    19161894            break;
    19171895        default:
     
    19391917
    19401918
    1941 /**
     1919/**rr
    19421920 * Setup PCI device controller and Virtio state
    19431921 *
     
    19691947    AssertLogRelReturn(pVirtioCC == PDMINS_2_DATA_CC(pDevIns, PVIRTIOCORECC), VERR_STATE_CHANGED);
    19701948
    1971     pVirtio->pDevIns = pDevIns;
     1949    pVirtio->pDevInsR3 = pDevIns;
    19721950
    19731951    /*
     
    20572035
    20582036    /*
    2059      * Notify capability (VirtIO 1.0 spec, section 4.1.4.4). Note: uLength is based the choice
    2060      * of this implementation that each queue's uQueueNotifyOff is set equal to (QueueSelect) ordinal
    2061      * value of the queue
     2037     * Notify capability (VirtIO 1.0 spec, section 4.1.4.4). Note: uLength is based on the choice
     2038     * of this implementation to make each queue's uQueueNotifyOff equal to (QueueSelect) ordinal
     2039     * value of the queue (different strategies are possible according to spec).
    20622040     */
    20632041    pCfg = (PVIRTIO_PCI_CAP_T)&pPciDev->abConfig[pCfg->uCapNext];
     
    21652143     *  out size, so pad with an extra page
    21662144     */
     2145    int cbSize = RTStrPrintf(pVirtioCC->pcszMmioName, sizeof(pVirtioCC->pcszMmioName), "%s MMIO", pcszInstance);
     2146    if (cbSize <= 0)
     2147        return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio: out of memory allocating string")); /* can we put params in this error? */
     2148
    21672149    rc = PDMDevHlpPCIIORegionCreateMmio(pDevIns, VIRTIO_REGION_PCI_CAP, RT_ALIGN_32(cbRegion + PAGE_SIZE, PAGE_SIZE),
    21682150                                        PCI_ADDRESS_SPACE_MEM, virtioMmioWrite, virtioMmioRead, pVirtio,
    2169                                         IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU, "virtio-scsi MMIO",
     2151                                        IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
     2152                                        pVirtioCC->pcszMmioName,
    21702153                                        &pVirtio->hMmioPciCap);
    21712154    AssertLogRelRCReturn(rc, PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio: cannot register PCI Capabilities address space")));
    2172 
    21732155    /*
    21742156     * Statistics.
     
    21952177 * @param   pVirtio     Pointer to the shared virtio state.  This must be the first
    21962178 *                      member in the shared device instance data!
    2197  * @param   pVirtioCC   Pointer to the current context virtio state.  This must be the
    2198  *                      first member in the currenct context's device instance data!
    2199  */
    2200 int virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC)
     2179 */
     2180int virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio)
    22012181{
    22022182    AssertLogRelReturn(pVirtio == PDMINS_2_DATA(pDevIns, PVIRTIOCORE), VERR_STATE_CHANGED);
    2203     AssertLogRelReturn(pVirtioCC == PDMINS_2_DATA_CC(pDevIns, PVIRTIOCORECC), VERR_STATE_CHANGED);
    2204 
     2183
     2184#ifdef FUTURE_OPTIMIZATION
     2185    int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
     2186    AssertRCReturn(rc, rc);
     2187#endif
    22052188    int rc = PDMDevHlpMmioSetUpContext(pDevIns, pVirtio->hMmioPciCap, virtioMmioWrite, virtioMmioRead, pVirtio);
    22062189    AssertRCReturn(rc, rc);
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h

    r83913 r84351  
    8181typedef struct VIRTIOSGBUF
    8282{
    83     PVIRTIOSGSEG paSegs;                                       /**< Pointer to the scatter/gather array       */
     83    PVIRTIOSGSEG paSegs;                                        /**< Pointer to the scatter/gather array       */
    8484    unsigned  cSegs;                                            /**< Number of segments                        */
    8585    unsigned  idxSeg;                                           /**< Current segment we are in                 */
     
    251251{
    252252    char                        szInstance[16];                     /**< Instance name, e.g. "VIRTIOSCSI0"         */
    253     PPDMDEVINS                  pDevIns;                            /**< Client device instance                    */
     253    PPDMDEVINS                  pDevInsR0;                          /**< Client device instance                    */
     254    PPDMDEVINS                  pDevInsR3;                          /**< Client device instance                    */
    254255    RTGCPHYS                    aGCPhysQueueDesc[VIRTQ_MAX_CNT];    /**< (MMIO) PhysAdr per-Q desc structs   GUEST */
    255256    RTGCPHYS                    aGCPhysQueueAvail[VIRTQ_MAX_CNT];   /**< (MMIO) PhysAdr per-Q avail structs  GUEST */
     
    297298} VIRTIOCORE;
    298299
     300#define MAX_NAME 64
     301
    299302
    300303/**
     
    317320
    318321    /**
    319      * When guest-to-host queue notifications are enabled, the guest driver notifies the host
    320      * that the avail queue has buffers, and this callback informs the client.
    321      *
    322      * @param   pVirtio    Pointer to the shared virtio state.
    323      * @param   pVirtioCC  Pointer to the ring-3 virtio state.
    324      * @param   idxQueue   Index of the notified queue
    325      */
    326     DECLCALLBACKMEMBER(void, pfnQueueNotified)(PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, uint16_t idxQueue);
    327 
    328     /**
    329322     * Implementation-specific client callback to access VirtIO Device-specific capabilities
    330323     * (other VirtIO capabilities and features are handled in VirtIO implementation)
     
    347340     */
    348341    DECLCALLBACKMEMBER(int,  pfnDevCapWrite)(PPDMDEVINS pDevIns, uint32_t offCap, const void *pvBuf, uint32_t cbWrite);
     342
     343
     344    /**
     345     * When guest-to-host queue notifications are enabled, the guest driver notifies the host
     346     * that the avail queue has buffers, and this callback informs the client.
     347     *
     348     * @param   pVirtio    Pointer to the shared virtio state.
     349     * @param   pVirtioCC  Pointer to the ring-3 virtio state.
     350     * @param   idxQueue   Index of the notified queue
     351     */
     352    DECLCALLBACKMEMBER(void, pfnQueueNotified)(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue);
     353
    349354    /** @} */
     355
    350356
    351357    R3PTRTYPE(PVIRTIO_PCI_CFG_CAP_T)    pPciCfgCap;                 /**< Pointer to struct in the PCI configuration area. */
     
    359365    R3PTRTYPE(uint8_t *)        pbPrevDevSpecificCfg;               /**< Previous read dev-specific cfg of client  */
    360366    bool                        fGenUpdatePending;                  /**< If set, update cfg gen after driver reads */
     367    char                        pcszMmioName[MAX_NAME];             /**< MMIO mapping name                         */
    361368} VIRTIOCORER3;
    362369
     
    367374typedef struct VIRTIOCORER0
    368375{
    369     uint64_t                    uUnusedAtTheMoment;
     376
     377    /**
     378     * When guest-to-host queue notifications are enabled, the guest driver notifies the host
     379     * that the avail queue has buffers, and this callback informs the client.
     380     *
     381     * @param   pVirtio    Pointer to the shared virtio state.
     382     * @param   pVirtioCC  Pointer to the ring-3 virtio state.
     383     * @param   idxQueue   Index of the notified queue
     384     */
     385    DECLCALLBACKMEMBER(void, pfnQueueNotified)(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue);
     386
    370387} VIRTIOCORER0;
    371388
     
    511528int      virtioCoreR3Init(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, PVIRTIOPCIPARAMS pPciParams,
    512529                      const char *pcszInstance, uint64_t fDevSpecificFeatures, void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg);
    513 int      virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC);
     530int      virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio);
    514531const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState);
    515532
Note: See TracChangeset for help on using the changeset viewer.

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