VirtualBox

Changeset 81973 in vbox for trunk/src


Ignore:
Timestamp:
Nov 19, 2019 5:43:11 AM (5 years ago)
Author:
vboxsync
Message:

Storage/DevVirtioSCSI.cpp: Took care of more to do items from bird's review. Worked on suspend logic and state change logic. Restoring after save state is still buggy

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp

    r81935 r81973  
    1 /* $Id$ $Revision$ $Date$ $Author$ */
     1    /* $Id$ $Revision$ $Date$ $Author$ */
    22/** @file
    33 * VBox storage devices - Virtio SCSI Driver
     
    127127 * VirtIO SCSI Host Device device-specific configuration (see VirtIO 1.0, section 5.6.4)
    128128 * VBox VirtIO framework issues callback to this client (device) to handle MMIO accesses
    129  * to the device-specific configuration parameters.
     129 * to the device-specific configuration parameters. uNumQueues is constant, readonly,
     130 * but maintained in this struct due to the design of local MMIO and logging handling.
     131 * The named constant will be used instead to wherever feasible.
    130132 */
    131133typedef struct virtio_scsi_config
     
    332334     | VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY )
    333335
     336typedef struct VIRTIOSCSI_REQ_REDO
     337{
     338    struct VIRTIOSCSI_REQ_REDO *next;                           /**< link to next in chain                             */
     339    uint16_t  uHeadIdx;                                         /**< desc chain head idx                               */
     340} VIRTIOSCSI_REQ_REDO, *PVIRTIOSCSI_REQ_REDO;
     341
    334342/**
    335343 * Worker thread context, shared state.
     
    350358    bool volatile                   fSleeping;                  /**< Flags whether worker thread is sleeping or not    */
    351359    bool volatile                   fNotified;                  /**< Flags whether worker thread notified              */
     360    PVIRTIOSCSI_REQ_REDO            pReqRedoQueue;              /**< Singly-linked listhead for suspended reqs to redo */
    352361} VIRTIOSCSIWORKERR3;
    353362/** Pointer to a VirtIO SCSI worker. */
    354363typedef VIRTIOSCSIWORKERR3 *PVIRTIOSCSIWORKERR3;
    355 
    356364
    357365/**
     
    379387    /** Flag whether device is present. */
    380388    bool                            fPresent;
    381 
    382389    /** Media port interface. */
    383390    PDMIMEDIAPORT                   IMediaPort;
     
    401408
    402409} VIRTIOSCSITARGET, *PVIRTIOSCSITARGET;
    403 
    404 
    405 /** Why we're quiescing. */
    406 typedef enum VIRTIOSCSIQUIESCINGFOR
    407 {
    408     kvirtIoScsiQuiescingForInvalid = 0,
    409     kvirtIoScsiQuiescingForReset,
    410     kvirtIoScsiQuiescingForSuspend,
    411     kvirtIoScsiQuiescingForPowerOff,
    412     kvirtIoScsiQuiescingFor32BitHack = 0x7fffffff
    413 } VIRTIOSCSIQUIESCINGFOR;
    414 
    415410
    416411/**
     
    520515    /** True if in the process of quiescing I/O */
    521516    uint32_t                        fQuiescing;
     517
    522518    /** For which purpose we're quiescing. */
    523     VIRTIOSCSIQUIESCINGFOR          enmQuiescingFor;
     519    VIRTIOVMSTATECHANGED            enmQuiescingFor;
    524520
    525521} VIRTIOSCSIR3;
     
    566562typedef struct VIRTIOSCSIREQ
    567563{
     564    struct VIRTIOSCSIREQ           *next;                       /**< When linked into redo queue                       */
    568565    PDMMEDIAEXIOREQ                hIoReq;                      /**< Handle of I/O request                             */
    569566    PVIRTIOSCSITARGET              pTarget;                     /**< Target                                            */
     
    666663static int virtioScsiR3SendEvent(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uEventType, uint32_t uReason)
    667664{
    668 
    669 
    670665    VIRTIOSCSI_EVENT_T event;
    671666    event.uEvent = uEventType;
     
    727722    virtioCoreR3QueueGet(pDevIns, &pThis->Virtio, EVENTQ_IDX, &pDescChain, true);
    728723
    729     RTSGBUF reqSegBuf;
    730     RTSGSEG aReqSegs[] = { { &event, sizeof(event) } };
    731     RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
    732 
    733     virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, EVENTQ_IDX, &reqSegBuf, pDescChain, true);
     724    PRTSGBUF pReqSegBuf = (PRTSGBUF)RTMemAllocZ(sizeof(RTSGBUF));
     725    AssertReturn(pReqSegBuf, VERR_NO_MEMORY);
     726
     727    PRTSGSEG paReqSegs  = (PRTSGSEG)RTMemAllocZ(sizeof(RTSGSEG) * 2);
     728    AssertReturn(paReqSegs, VERR_NO_MEMORY);
     729
     730    paReqSegs[0].pvSeg = &event;
     731    paReqSegs[0].cbSeg = sizeof(sizeof(event));
     732
     733    RTSgBufInit(pReqSegBuf, paReqSegs, 1);
     734
     735    virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, EVENTQ_IDX, pReqSegBuf, pDescChain, true);
    734736    virtioCoreQueueSync(pDevIns, &pThis->Virtio, EVENTQ_IDX);
     737
     738    RTMemFree(paReqSegs);
     739    RTMemFree(pReqSegBuf);
    735740
    736741    return VINF_SUCCESS;
     
    10411046        uint64_t srcSgCur   = (uint64_t)pSgPhysSend->pGcSegCur;
    10421047        cbCopied = RT_MIN((uint64_t)pSgBuf->cbSegLeft, srcSgLen - (srcSgCur - srcSgStart));
    1043         PDMDevHlpPhysRead(pDevIns,
     1048        PDMDevHlpPCIPhysRead(pDevIns,
    10441049                          (RTGCPHYS)pSgPhysSend->pGcSegCur, pSgBuf->pvSegCur, cbCopied);
    10451050        RTSgBufAdvance(pSgBuf, cbCopied);
     
    10541059}
    10551060
    1056 /**
    1057  * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
    1058  */
    1059 static DECLCALLBACK(void) virtioScsiR3MediumEjected(PPDMIMEDIAEXPORT pInterface)
    1060 {
    1061     PVIRTIOSCSITARGET   pTarget   = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
    1062     PPDMDEVINS          pDevIns   = pTarget->pDevIns;
    1063     PVIRTIOSCSICC       pThisCC   = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);
    1064 
    1065     LogFunc(("LUN %d Ejected!\n", pTarget->iTarget));
    1066     if (pThisCC->pMediaNotify)
    1067     {
    1068         int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
    1069                                    (PFNRT)pThisCC->pMediaNotify->pfnEjected, 2,
    1070                                    pThisCC->pMediaNotify, pTarget->iTarget);
    1071         AssertRC(rc);
    1072     }
    1073 }
    1074 
    1075 /**
    1076  * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
    1077  */
    1078 static DECLCALLBACK(void) virtioScsiR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
    1079                                                         void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
    1080 {
    1081     PVIRTIOSCSITARGET   pTarget   = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
    1082     PPDMDEVINS          pDevIns   = pTarget->pDevIns;
    1083     PVIRTIOSCSI         pThis     = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1084     PVIRTIOSCSICC       pThisCC   = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);
    1085     RT_NOREF(hIoReq, pvIoReqAlloc);
    1086 
    1087     switch (enmState)
    1088     {
    1089         case PDMMEDIAEXIOREQSTATE_SUSPENDED:
    1090         {
    1091             /* Stop considering this request active */
    1092             if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThisCC->fQuiescing)
    1093                 PDMDevHlpAsyncNotificationCompleted(pDevIns);
    1094             break;
    1095         }
    1096         case PDMMEDIAEXIOREQSTATE_ACTIVE:
    1097             ASMAtomicIncU32(&pThis->cActiveReqs);
    1098             break;
    1099         default:
    1100             AssertMsgFailed(("Invalid request state given %u\n", enmState));
    1101     }
    1102 }
    1103 
    1104 
    11051061/*********************************************************************************************************************************
    11061062*   Worker Thread                                                                                                                *
     
    11321088        size_t cbSeg = cb;
    11331089        RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg);
    1134         PDMDevHlpPhysRead(pDevIns, GCPhys, pb, cbSeg);
     1090        PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pb, cbSeg);
    11351091        pb += cbSeg;
    11361092        cb -= cbSeg;
     
    13441300        size_t cbSeg = cb;
    13451301        RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg);
    1346         PDMDevHlpPhysRead(pDevIns, GCPhys, pb, cbSeg);
     1302        PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pb, cbSeg);
    13471303        pb += cbSeg;
    13481304        cb -= cbSeg;
     
    15511507    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    15521508    {
    1553         if (virtioCoreQueueIsEmpty(pDevIns, &pThis->Virtio, qIdx))
     1509        if (!pWorkerR3->pReqRedoQueue && virtioCoreQueueIsEmpty(pDevIns, &pThis->Virtio, qIdx))
    15541510        {
    15551511            /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */
     
    15771533        if (!pThisCC->fQuiescing)
    15781534        {
     1535             /* Process any reqs that were suspended saved to the redo queue in save exec. */
     1536             PVIRTIOSCSI_REQ_REDO pReqRedo = pWorkerR3->pReqRedoQueue;
     1537             for (; pReqRedo; pReqRedo = pReqRedo->next)
     1538             {
     1539                  PVIRTIO_DESC_CHAIN_T pDescChain;
     1540                  int rc = virtioCoreR3DescChainGet(pDevIns, &pThis->Virtio, qIdx,
     1541                                                pReqRedo->uHeadIdx, &pDescChain);
     1542                  if (RT_FAILURE(rc))
     1543                     LogRel(("Error fetching desc chain to redo, %Rrc", rc));
     1544
     1545                  rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, qIdx, pDescChain);
     1546                  if (RT_FAILURE(rc))
     1547                     LogRel(("Error submitting req packet, resetting %Rrc", rc));
     1548             }
     1549             pWorkerR3->pReqRedoQueue = NULL;
     1550
    15791551             Log6Func(("fetching next descriptor chain from %s\n", QUEUENAME(qIdx)));
    15801552             PVIRTIO_DESC_CHAIN_T pDescChain;
     
    15931565                  rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, qIdx, pDescChain);
    15941566                  if (RT_FAILURE(rc))
    1595                   {
    1596                      LogRel(("Error submitting req packet, resetting %Rrc", rc));
    1597                   }
     1567                      LogRel(("Error submitting req packet, resetting %Rrc", rc));
    15981568             }
    15991569        }
     
    20091979    pHlp->pfnSSMGetU32(pSSM, &pThis->virtioScsiConfig.uMaxLun);
    20101980    pHlp->pfnSSMGetU32(pSSM, &pThis->fAsyncEvtsEnabled);
    2011     pHlp->pfnSSMGetU32V(pSSM, &pThis->cActiveReqs);
    2012     pHlp->pfnSSMGetBool(pSSM, &pThis->fEventsMissed);
     1981    pHlp->pfnSSMGetU32(pSSM, (uint32_t *)&pThis->cActiveReqs);
    20131982    pHlp->pfnSSMGetU32(pSSM, &pThis->fVirtioReady);
    20141983    pHlp->pfnSSMGetU32(pSSM, &pThis->fHasT10pi);
     
    20171986    pHlp->pfnSSMGetU32(pSSM, &pThis->fHasLunChange);
    20181987    pHlp->pfnSSMGetU32(pSSM, &pThis->fResetting);
     1988    pHlp->pfnSSMGetBool(pSSM, &pThis->fEventsMissed);
     1989
     1990//    int rc = vboxscsiR3LoadExec(pHlp, &pThisCC->VBoxSCSI, pSSM);
    20191991
    20201992    /*
    20211993     * Call the virtio core to let it load its state.
    20221994     */
    2023     return virtioCoreR3LoadExec(&pThis->Virtio, pDevIns->pHlpR3, pSSM);
     1995    int rc = virtioCoreR3LoadExec(&pThis->Virtio, pDevIns->pHlpR3, pSSM);
     1996
     1997    /*
     1998     * Nudge request queue workers
     1999     */
     2000    for (int qIdx = VIRTQ_REQ_BASE; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
     2001    {
     2002        if (pThis->afQueueAttached[qIdx])
     2003        {
     2004            LogFunc(("Waking %s worker.\n", QUEUENAME(qIdx)));
     2005            rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[qIdx].hEvtProcess);
     2006            AssertRCReturn(rc, rc);
     2007        }
     2008    }
     2009    return rc;
    20242010}
    20252011
     
    20302016{
    20312017    PVIRTIOSCSI     pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    2032 //    PVIRTIOSCSICC   pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);
     2018    PVIRTIOSCSICC   pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);
    20332019    PCPDMDEVHLPR3   pHlp    = pDevIns->pHlpR3;
    20342020    LogFunc(("SAVE EXEC!!\n"));
    20352021
     2022     /* Every device first. */
     2023//     lsilogicR3LiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
     2024     for (unsigned i = 0; i < pThis->cTargets; i++)
     2025     {
     2026         PVIRTIOSCSITARGET pTarget = &pThisCC->paTargetInstances[i];
     2027
     2028         AssertMsg(!pThis->cActiveReqs, ("There are still outstanding requests on this device\n"));
     2029         pHlp->pfnSSMPutU32(pSSM, pThis->cTargets);
     2030
     2031         /* Query all suspended requests and store them in the request queue. */
     2032         if (pTarget->pDrvMediaEx)
     2033         {
     2034             uint32_t cReqsRedo = pTarget->pDrvMediaEx->pfnIoReqGetSuspendedCount(pTarget->pDrvMediaEx);
     2035             if (cReqsRedo)
     2036             {
     2037                 PDMMEDIAEXIOREQ hIoReq;
     2038                 PVIRTIOSCSIREQ pReq;
     2039                 int rc = pTarget->pDrvMediaEx->pfnIoReqQuerySuspendedStart(pTarget->pDrvMediaEx, &hIoReq,
     2040                                                                            (void **)&pReq);
     2041                 AssertRCBreak(rc);
     2042
     2043                 /* todo: BIOS? */
     2044                 for (; cReqsRedo; --cReqsRedo)
     2045                 {
     2046
     2047                    /* Add the head virtio desc idx of this request to the redo queue */
     2048                    PVIRTIOSCSI_REQ_REDO pReqRedo = (PVIRTIOSCSI_REQ_REDO)RTMemAllocZ(sizeof(VIRTIOSCSI_REQ_REDO));
     2049                    AssertReturn(pReqRedo, VERR_NO_MEMORY);
     2050                    pReqRedo->uHeadIdx = pReq->pDescChain->uHeadIdx;
     2051                    PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[pReq->qIdx];
     2052                    PVIRTIOSCSI_REQ_REDO *pReqRedoSlot = &pWorkerR3->pReqRedoQueue;
     2053
     2054                    while(*pReqRedoSlot)
     2055                        pReqRedoSlot = &((*pReqRedoSlot)->next);
     2056
     2057                    *pReqRedoSlot = pReqRedo;
     2058                     rc = pTarget->pDrvMediaEx->pfnIoReqQuerySuspendedNext(pTarget->pDrvMediaEx, hIoReq,
     2059                                                                           &hIoReq, (void **)&pReq);
     2060                     AssertRCBreak(rc);
     2061                 }
     2062             }
     2063         }
     2064//         int rc = vboxscsiR3SaveExec(pHlp, &pThisCC->VBoxSCSI, pSSM);
     2065     }
    20362066    pHlp->pfnSSMPutU32(pSSM, pThis->virtioScsiConfig.uNumQueues);
    20372067    pHlp->pfnSSMPutU32(pSSM, pThis->virtioScsiConfig.uSegMax);
     
    21632193    PVIRTIOSCSI     pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    21642194    PVIRTIOSCSICC   pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);
    2165     LogFunc(("Device I/O activity quiesced: enmQuiescingFor=%d\n", pThisCC->enmQuiescingFor));
    2166 
    2167     if (pThisCC->enmQuiescingFor == kvirtIoScsiQuiescingForReset)
    2168         virtioCoreR3PropagateResetNotification(pDevIns, &pThis->Virtio);
    2169     /** @todo r=bird: Do we need other notifications here for suspend and/or poweroff? */
    2170 
    2171 //    pThisCC->enmQuiescingFor  = kvirtIoScsiQuiescingForInvalid;
     2195
     2196    if (ASMAtomicReadU32(&pThis->cActiveReqs))
     2197        return false;
     2198
     2199    LogFunc(("Device I/O activity quiesced: enmQuiescingFor=%s\n",
     2200        virtioCoreGetStateChangeText(pThisCC->enmQuiescingFor)));
     2201
     2202    virtioCoreR3VmStateChanged(pDevIns, &pThis->Virtio, pThisCC->enmQuiescingFor);
     2203
     2204    pThis->fResetting = false;
    21722205    pThisCC->fQuiescing = false;
     2206
    21732207    return true;
    21742208}
     
    21772211 * Worker for virtioScsiR3Reset() and virtioScsiR3SuspendOrPowerOff().
    21782212 */
    2179 static void virtioScsiR3QuiesceDevice(PPDMDEVINS pDevIns, VIRTIOSCSIQUIESCINGFOR enmQuiscingFor)
     2213static void virtioScsiR3QuiesceDevice(PPDMDEVINS pDevIns, VIRTIOVMSTATECHANGED enmQuiscingFor)
    21802214{
    21812215    PVIRTIOSCSI     pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
     
    21942228
    21952229/**
    2196  * Common worker for suspend and power off.
    2197  */
    2198 static void virtioScsiR3SuspendOrPowerOff(PPDMDEVINS pDevIns, VIRTIOSCSIQUIESCINGFOR enmQuiscingFor)
    2199 {
     2230 * @interface_method_impl{PDMDEVREGR3,pfnReset}
     2231 */
     2232static DECLCALLBACK(void) virtioScsiR3Reset(PPDMDEVINS pDevIns)
     2233{
     2234    LogFunc(("\n"));
     2235    PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
     2236    pThis->fResetting = true;
     2237    virtioScsiR3QuiesceDevice(pDevIns, kvirtIoVmStateChangedReset);
     2238}
     2239
     2240/**
     2241 * @interface_method_impl{PDMDEVREGR3,pfnPowerOff}
     2242 */
     2243static DECLCALLBACK(void) virtioScsiR3SuspendOrPowerOff(PPDMDEVINS pDevIns, VIRTIOVMSTATECHANGED enmType)
     2244{
     2245    LogFunc(("\n"));
     2246
    22002247    PVIRTIOSCSI     pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    22012248    PVIRTIOSCSICC   pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);
    22022249
    2203     virtioScsiR3QuiesceDevice(pDevIns, enmQuiscingFor);
    2204 
     2250    virtioScsiR3QuiesceDevice(pDevIns, enmType);
    22052251
    22062252    /* VM is halted, thus no new I/O being dumped into queues by the guest.
     
    22192265
    22202266/**
    2221  * @interface_method_impl{PDMDEVREGR3,pfnPowerOff}
     2267 * @interface_method_impl{PDMDEVREGR3,pfnSuspend}
    22222268 */
    22232269static DECLCALLBACK(void) virtioScsiR3PowerOff(PPDMDEVINS pDevIns)
    22242270{
    22252271    LogFunc(("\n"));
    2226     virtioScsiR3SuspendOrPowerOff(pDevIns, kvirtIoScsiQuiescingForPowerOff);
     2272    virtioScsiR3SuspendOrPowerOff(pDevIns, kvirtIoVmStateChangedPowerOff);
    22272273}
    22282274
     
    22332279{
    22342280    LogFunc(("\n"));
    2235     virtioScsiR3SuspendOrPowerOff(pDevIns, kvirtIoScsiQuiescingForSuspend);
     2281    virtioScsiR3SuspendOrPowerOff(pDevIns, kvirtIoVmStateChangedSuspend);
    22362282}
    22372283
     
    22622308
    22632309    /* Ensure guest is working the queues too. */
    2264     virtioCoreR3PropagateResumeNotification(pDevIns, &pThis->Virtio);
    2265 }
    2266 
    2267 /**
    2268  * @interface_method_impl{PDMDEVREGR3,pfnReset}
    2269  */
    2270 static DECLCALLBACK(void) virtioScsiR3Reset(PPDMDEVINS pDevIns)
    2271 {
    2272     LogFunc(("\n"));
    2273     PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    2274     pThis->fResetting = true;
    2275     virtioScsiR3QuiesceDevice(pDevIns, kvirtIoScsiQuiescingForReset);
    2276     PDMDevHlpVMReset(pDevIns, 0);
     2310    virtioCoreR3VmStateChanged(pDevIns, &pThis->Virtio, kvirtIoVmStateChangedResume);
     2311}
     2312
     2313/**
     2314 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
     2315 */
     2316static DECLCALLBACK(void) virtioScsiR3MediumEjected(PPDMIMEDIAEXPORT pInterface)
     2317{
     2318    PVIRTIOSCSITARGET   pTarget   = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
     2319    PPDMDEVINS          pDevIns   = pTarget->pDevIns;
     2320    PVIRTIOSCSICC       pThisCC   = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);
     2321
     2322    LogFunc(("LUN %d Ejected!\n", pTarget->iTarget));
     2323    if (pThisCC->pMediaNotify)
     2324    {
     2325        int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
     2326                                   (PFNRT)pThisCC->pMediaNotify->pfnEjected, 2,
     2327                                   pThisCC->pMediaNotify, pTarget->iTarget);
     2328        AssertRC(rc);
     2329    }
     2330}
     2331
     2332/**
     2333 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
     2334 */
     2335static DECLCALLBACK(void) virtioScsiR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     2336                                                        void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
     2337{
     2338    PVIRTIOSCSITARGET   pTarget   = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
     2339    PPDMDEVINS          pDevIns   = pTarget->pDevIns;
     2340    PVIRTIOSCSI         pThis     = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
     2341    PVIRTIOSCSICC       pThisCC   = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);
     2342    RT_NOREF(hIoReq, pvIoReqAlloc);
     2343
     2344    switch (enmState)
     2345    {
     2346        case PDMMEDIAEXIOREQSTATE_SUSPENDED:
     2347        {
     2348            /* Stop considering this request active */
     2349            if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThisCC->fQuiescing)
     2350                PDMDevHlpAsyncNotificationCompleted(pDevIns);
     2351            break;
     2352        }
     2353        case PDMMEDIAEXIOREQSTATE_ACTIVE:
     2354            ASMAtomicIncU32(&pThis->cActiveReqs);
     2355            break;
     2356        default:
     2357            AssertMsgFailed(("Invalid request state given %u\n", enmState));
     2358    }
    22772359}
    22782360
     
    23542436    pThis->virtioScsiConfig.uMaxSectors     = VIRTIOSCSI_MAX_SECTORS_HINT;
    23552437    pThis->virtioScsiConfig.uCmdPerLun      = VIRTIOSCSI_MAX_COMMANDS_PER_LUN;
    2356     pThis->virtioScsiConfig.uEventInfoSize  = sizeof(VIRTIOSCSI_EVENT_T); /* Spec says at least this size! */
     2438    pThis->virtioScsiConfig.uEventInfoSize  = sizeof(VIRTIOSCSI_EVENT_T); /*VirtIO 1.0 Spec says at least this size! */
    23572439    pThis->virtioScsiConfig.uSenseSize      = VIRTIOSCSI_SENSE_SIZE_DEFAULT;
    23582440    pThis->virtioScsiConfig.uCdbSize        = VIRTIOSCSI_CDB_SIZE_DEFAULT;
     
    23682450
    23692451    VIRTIOPCIPARAMS VirtioPciParams;
    2370     VirtioPciParams.uDeviceId           = PCI_DEVICE_ID_VIRTIOSCSI_HOST;
    2371     VirtioPciParams.uClassBase          = PCI_CLASS_BASE_MASS_STORAGE;
    2372     VirtioPciParams.uClassSub           = PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER;
    2373     VirtioPciParams.uClassProg          = PCI_CLASS_PROG_UNSPECIFIED;
    2374     VirtioPciParams.uSubsystemId        = PCI_DEVICE_ID_VIRTIOSCSI_HOST;  /* Virtio 1.0 spec allows PCI Device ID here */
    2375     VirtioPciParams.uInterruptLine      = 0x00;
    2376     VirtioPciParams.uInterruptPin       = 0x01;
     2452    VirtioPciParams.uDeviceId               = PCI_DEVICE_ID_VIRTIOSCSI_HOST;
     2453    VirtioPciParams.uClassBase              = PCI_CLASS_BASE_MASS_STORAGE;
     2454    VirtioPciParams.uClassSub               = PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER;
     2455    VirtioPciParams.uClassProg              = PCI_CLASS_PROG_UNSPECIFIED;
     2456    VirtioPciParams.uSubsystemId            = PCI_DEVICE_ID_VIRTIOSCSI_HOST;  /* VirtIO 1.0 spec allows PCI Device ID here */
     2457    VirtioPciParams.uInterruptLine          = 0x00;
     2458    VirtioPciParams.uInterruptPin           = 0x01;
    23772459
    23782460    rc = virtioCoreR3Init(pDevIns, &pThis->Virtio, &pThisCC->Virtio, &VirtioPciParams, pThis->szInstance,
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r81838 r81973  
    103103
    104104
     105const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState)
     106{
     107    switch (enmState)
     108    {
     109        case kvirtIoVmStateChangedReset:                return "<VM RESET>";
     110        case kvirtIoVmStateChangedSuspend:              return "<VM SUSPEND>";
     111        case kvirtIoVmStateChangedPowerOff:             return "<VM POWEROFF>";
     112        case kvirtIoVmStateChangedResume:               return "<VM RESUME>";
     113        default:                                        return "<BAD ENUM>";
     114    }
     115}
     116
    105117/*********************************************************************************************************************************
    106118*   Internal Functions                                                                                                           *
     
    128140    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    129141    uint16_t const cQueueItems = RT_MAX(pVirtio->uQueueSize[idxQueue], 1); /* Make sure to avoid div-by-zero. */
    130     PDMDevHlpPhysRead(pDevIns, /** @todo r=bird: PDMDevHlpPhysRead or PDMDevHlpPCIPhysRead ?!? (ditto rest of file + writes) */
     142    PDMDevHlpPCIPhysRead(pDevIns,
    131143                      pVirtio->aGCPhysQueueDesc[idxQueue] + sizeof(VIRTQ_DESC_T) * (idxDesc % cQueueItems),
    132144                      pDesc, sizeof(VIRTQ_DESC_T));
     
    141153    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    142154    uint16_t const cQueueItems = RT_MAX(pVirtio->uQueueSize[idxQueue], 1); /* Make sure to avoid div-by-zero. */
    143     PDMDevHlpPhysRead(pDevIns,
     155    PDMDevHlpPCIPhysRead(pDevIns,
    144156                        pVirtio->aGCPhysQueueAvail[idxQueue]
    145157                      + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[availIdx % cQueueItems]),
     
    152164    uint16_t uIdx = 0;
    153165    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    154     PDMDevHlpPhysRead(pDevIns,
     166    PDMDevHlpPCIPhysRead(pDevIns,
    155167                      pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx),
    156168                      &uIdx, sizeof(uIdx));
     
    168180    uint16_t fFlags;
    169181    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    170     PDMDevHlpPhysRead(pDevIns,
     182    PDMDevHlpPCIPhysRead(pDevIns,
    171183                      pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF(VIRTQ_AVAIL_T, fFlags),
    172184                      &fFlags, sizeof(fFlags));
     
    180192    /* VirtIO 1.0 uUsedEventIdx (used_event) immediately follows ring */
    181193    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    182     PDMDevHlpPhysRead(pDevIns,
     194    PDMDevHlpPCIPhysRead(pDevIns,
    183195                      pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[pVirtio->uQueueSize[idxQueue]]),
    184196                      &uUsedEventIdx, sizeof(uUsedEventIdx));
     
    214226    uint16_t uIdx = 0;
    215227    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    216     PDMDevHlpPhysRead(pDevIns,
     228    PDMDevHlpPCIPhysRead(pDevIns,
    217229                      pVirtio->aGCPhysQueueUsed[idxQueue] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx),
    218230                      &uIdx, sizeof(uIdx));
     
    225237    uint16_t fFlags = 0;
    226238    AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    227     PDMDevHlpPhysRead(pDevIns,
     239    PDMDevHlpPCIPhysRead(pDevIns,
    228240                      pVirtio->aGCPhysQueueUsed[idxQueue] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags),
    229241                      &fFlags, sizeof(fFlags));
     
    516528#endif /* IN_RING3 */
    517529
    518 #if 0 /** @todo r=bird: no prototype or docs for this one  */
    519530/**
    520531 * See API comments in header file for description
     
    528539                    ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
    529540
    530     if (virtioCoreQueueIsEmpty(pVirtio, idxQueue))
     541    if (virtioCoreQueueIsEmpty(pVirtio->pDevIns, pVirtio, idxQueue))
    531542        return VERR_NOT_AVAILABLE;
    532543
     
    536547    return VINF_SUCCESS;
    537548}
    538 #endif
    539549
    540550/**
     
    557567#ifdef IN_RING3
    558568
    559 /**
    560  * Removes descriptor chain from avail ring of indicated queue and converts the descriptor
    561  * chain into its OUT (to device) and IN to guest components.
    562  *
    563  * Additionally it converts the OUT desc chain data to a contiguous virtual
    564  * memory buffer for easy consumption by the caller. The caller must return the
    565  * descriptor chain pointer via virtioCoreR3QueuePut() and then call virtioCoreQueueSync()
    566  * at some point to return the data to the guest and complete the transaction.
    567  *
    568  * @param   pDevIns     The device instance.
    569  * @param   pVirtio     Pointer to the shared virtio state.
    570  * @param   idxQueue    Queue number
    571  * @param   fRemove     flags whether to remove desc chain from queue (false = peek)
    572  * @param   ppDescChain Address to store pointer to descriptor chain that contains the
    573  *                      pre-processed transaction information pulled from the virtq.
    574  *
    575  * @returns VBox status code:
    576  * @retval  VINF_SUCCESS         Success
    577  * @retval  VERR_INVALID_STATE   VirtIO not in ready state (asserted).
    578  * @retval  VERR_NOT_AVAILABLE   If the queue is empty.
    579  */
    580 int virtioCoreR3QueueGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue,
    581                          PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove)
     569
     570int virtioCoreR3DescChainGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue,
     571                             uint16_t uHeadIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain)
    582572{
    583573    AssertReturn(ppDescChain, VERR_INVALID_PARAMETER);
     
    595585                    ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
    596586
    597     if (virtqIsEmpty(pDevIns, pVirtio, idxQueue))
    598         return VERR_NOT_AVAILABLE;
    599 
    600     uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, idxQueue, pVirtq->uAvailIdx);
    601587    uint16_t uDescIdx = uHeadIdx;
    602588
    603     Log3Func(("%s DESC CHAIN: (head) desc_idx=%u [avail_idx=%u]\n", pVirtq->szVirtqName, uHeadIdx, pVirtq->uAvailIdx));
    604 
    605     if (fRemove)
    606         pVirtq->uAvailIdx++;
     589    Log3Func(("%s DESC CHAIN: (head) desc_idx=%u\n", pVirtq->szVirtqName, uHeadIdx));
    607590
    608591    VIRTQ_DESC_T desc;
     
    682665
    683666/**
     667 * Fetches descriptor chain using avail ring of indicated queue and converts the descriptor
     668 * chain into its OUT (to device) and IN to guest components.
     669 *
     670 * Additionally it converts the OUT desc chain data to a contiguous virtual
     671 * memory buffer for easy consumption by the caller. The caller must return the
     672 * descriptor chain pointer via virtioCoreR3QueuePut() and then call virtioCoreQueueSync()
     673 * at some point to return the data to the guest and complete the transaction.
     674 *
     675 * @param   pDevIns     The device instance.
     676 * @param   pVirtio     Pointer to the shared virtio state.
     677 * @param   idxQueue    Queue number
     678 * @param   fRemove     flags whether to remove desc chain from queue (false = peek)
     679 * @param   ppDescChain Address to store pointer to descriptor chain that contains the
     680 *                      pre-processed transaction information pulled from the virtq.
     681 *
     682 * @returns VBox status code:
     683 * @retval  VINF_SUCCESS         Success
     684 * @retval  VERR_INVALID_STATE   VirtIO not in ready state (asserted).
     685 * @retval  VERR_NOT_AVAILABLE   If the queue is empty.
     686 */
     687int virtioCoreR3QueueGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue,
     688                         PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove)
     689{
     690    PVIRTQSTATE pVirtq = &pVirtio->virtqState[idxQueue];
     691
     692    if (virtqIsEmpty(pDevIns, pVirtio, idxQueue))
     693        return VERR_NOT_AVAILABLE;
     694
     695    uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, idxQueue, pVirtq->uAvailIdx);
     696
     697    if (fRemove)
     698        pVirtq->uAvailIdx++;
     699
     700    int rc = virtioCoreR3DescChainGet(pDevIns, pVirtio, idxQueue, uHeadIdx, ppDescChain);
     701    return rc;
     702}
     703
     704/**
    684705 * Returns data to the guest to complete a transaction initiated by virtQueueGet().
    685706 *
     
    895916static int virtioKick(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint8_t uCause, uint16_t uMsixVector, bool fForce)
    896917{
    897    if (fForce)
    898        Log6Func(("reason: resumed after suspend\n"));
    899    else
    900    if (uCause == VIRTIO_ISR_VIRTQ_INTERRUPT)
    901        Log6Func(("reason: buffer added to 'used' ring.\n"));
    902    else
    903    if (uCause == VIRTIO_ISR_DEVICE_CONFIG)
     918    if (fForce)
     919        Log6Func(("reason: resumed after suspend\n"));
     920    else
     921    if (uCause == VIRTIO_ISR_VIRTQ_INTERRUPT)
     922        Log6Func(("reason: buffer added to 'used' ring.\n"));
     923    else
     924    if (uCause == VIRTIO_ISR_DEVICE_CONFIG)
    904925       Log6Func(("reason: device config change\n"));
    905926
     
    910931    }
    911932    else if (uMsixVector != VIRTIO_MSI_NO_VECTOR)
    912     {
    913         Log6Func(("MSI-X enabled, calling PDMDevHlpPCISetIrq with vector: 0x%x\n", uMsixVector));
    914933        PDMDevHlpPCISetIrq(pDevIns, uMsixVector, 1);
    915     }
    916934    return VINF_SUCCESS;
    917935}
     
    922940 * @param   pDevIns     The device instance.
    923941 */
    924 static void virtioLowerInterrupt(PPDMDEVINS pDevIns)
    925 {
    926     /** @todo r=bird: MSI?   */
    927     PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_LOW);
     942static void virtioLowerInterrupt(PPDMDEVINS pDevIns, uint16_t uMsixVector)
     943{
     944    PVIRTIOCORE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOCORE);
     945    if (!pVirtio->fMsiSupport)
     946        PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_LOW);
     947    else if (uMsixVector != VIRTIO_MSI_NO_VECTOR)
     948        PDMDevHlpPCISetIrq(pDevIns, pVirtio->uMsixConfig, PDM_IRQ_LEVEL_LOW);
    928949}
    929950
     
    952973    pVirtio->uISR                   = 0;
    953974
    954     virtioLowerInterrupt(pDevIns);
     975    if (!pVirtio->fMsiSupport)
     976        virtioLowerInterrupt(pDevIns, 0);
     977    else
     978    {
     979        virtioLowerInterrupt(pDevIns, pVirtio->uMsixConfig);
     980        for (int i = 0; i < VIRTQ_MAX_CNT; i++)
     981        {
     982            virtioLowerInterrupt(pDevIns, pVirtio->uQueueMsixVector[i]);
     983            pVirtio->uQueueMsixVector[i];
     984        }
     985    }
    955986
    956987    if (!pVirtio->fMsiSupport)  /* VirtIO 1.0, 4.1.4.3 and 4.1.5.1.2 */
    957988        pVirtio->uMsixConfig = VIRTIO_MSI_NO_VECTOR;
    958989
    959     pVirtio->uNumQueues = VIRTQ_MAX_CNT;
    960     for (uint16_t idxQueue = 0; idxQueue < pVirtio->uNumQueues; idxQueue++)
     990    for (uint16_t idxQueue = 0; idxQueue < VIRTQ_MAX_CNT; idxQueue++)
    961991        virtioResetQueue(pVirtio, idxQueue);
    962992}
    963993
    964 #if 0 /** @todo r=bird: Probably not needed. */
    965 /**
    966  * Enable or disable queue
    967  *
    968  * @param   pVirtio     Pointer to the shared virtio state.
    969  * @param   idxQueue    Queue number
    970  * @param   fEnabled    Flag indicating whether to enable queue or not
    971  */
    972 void virtioCoreQueueEnable(PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fEnabled)
    973 {
    974     if (fEnabled)
    975         pVirtio->uQueueSize[idxQueue] = VIRTQ_MAX_SIZE;
    976     else
    977         pVirtio->uQueueSize[idxQueue] = 0;
    978 }
    979 #endif
    980 
    981 #if 0 /** @todo r=bird: This isn't invoked by anyone. Why?
    982           For this and the previous I was just trying to provide flexibility
    983           for other devices that might use this code r=paul */
    984 /**
    985  * Initiate orderly reset procedure.
     994/**
     995 * Initiate orderly reset procedure. This is an exposed API for clients that might need it.
    986996 * Invoked by client to reset the device and driver (see VirtIO 1.0 section 2.1.1/2.1.2)
    987997 */
    988998void virtioCoreResetAll(PVIRTIOCORE pVirtio)
    989999{
    990     LogFunc(("VIRTIO RESET REQUESTED!!!\n"));
     1000    LogFunc(("\n"));
    9911001    pVirtio->uDeviceStatus |= VIRTIO_STATUS_DEVICE_NEEDS_RESET;
    9921002    if (pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
    9931003    {
    9941004        pVirtio->fGenUpdatePending = true;
    995         virtioKick(pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false /* fForce */);
    996     }
    997 }
    998 #endif
     1005        virtioKick(pVirtio->pDevIns, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false /* fForce */);
     1006    }
     1007}
    9991008
    10001009#ifdef IN_RING3
     
    12331242        {
    12341243            Log6Func(("Guest read  uDeviceStatus ................ ("));
    1235             *(uint32_t *)pv = pVirtio->uDeviceStatus;   /** @todo r=bird: Why 32-bit write here, the field is 8-bit? */
     1244            *(uint8_t *)pv = pVirtio->uDeviceStatus;
    12361245            virtioLogDeviceStatus(pVirtio->uDeviceStatus);
    12371246            Log6((")\n"));
     
    13411350            pVirtio->fGenUpdatePending = false;
    13421351        }
     1352
     1353        if (pVirtio->fMsiSupport)
     1354            PDMDevHlpPCISetIrq(pDevIns, pVirtio->uMsixConfig, PDM_IRQ_LEVEL_LOW);
     1355
    13431356        return rcStrict;
    13441357#else
     
    13551368        Log6Func(("Read and clear ISR\n"));
    13561369        pVirtio->uISR = 0; /* VirtIO specification requires reads of ISR to clear it */
    1357         virtioLowerInterrupt(pDevIns);
     1370        virtioLowerInterrupt(pDevIns, 0);
    13581371        return VINF_SUCCESS;
    13591372    }
     
    15161529int virtioCoreR3SaveExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM)
    15171530{
     1531    LogFunc(("\n"));
    15181532    pHlp->pfnSSMPutU64(pSSM, VIRTIO_SAVEDSTATE_MARKER);
    15191533    pHlp->pfnSSMPutU32(pSSM, VIRTIO_SAVEDSTATE_VERSION);
     
    15281542    pHlp->pfnSSMPutU32(pSSM,    pVirtio->uDriverFeaturesSelect);
    15291543    pHlp->pfnSSMPutU64(pSSM,    pVirtio->uDriverFeatures);
    1530     Assert(pVirtio->uNumQueues == VIRTQ_MAX_CNT); /** @todo r=bird: See todo in struct & virtioCoreR3LoadExec. */
    1531     pHlp->pfnSSMPutU32(pSSM,    pVirtio->uNumQueues);
    1532 
    1533     for (uint32_t i = 0; i < pVirtio->uNumQueues; i++)
     1544
     1545    for (uint32_t i = 0; i < VIRTQ_MAX_CNT; i++)
    15341546    {
    15351547        pHlp->pfnSSMPutGCPhys64(pSSM, pVirtio->aGCPhysQueueDesc[i]);
     
    15591571int virtioCoreR3LoadExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM)
    15601572{
     1573    LogFunc(("\n"));
    15611574    /*
    15621575     * Check the marker and (embedded) version number.
     
    15751588        return pHlp->pfnSSMSetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
    15761589                                        N_("Unsupported virtio version: %u"), uVersion);
    1577 
    15781590    /*
    15791591     * Load the state.
     
    15891601    pHlp->pfnSSMGetU64(pSSM,  &pVirtio->uDriverFeatures);
    15901602
    1591     /* Make sure the queue count is within expectations. */
    1592     /** @todo r=bird: Turns out the expectations are exactly VIRTQ_MAX_CNT, bug? */
    1593     rc = pHlp->pfnSSMGetU32(pSSM, &pVirtio->uNumQueues);
    1594     AssertRCReturn(rc, rc);
    1595     AssertReturn(pVirtio->uNumQueues == VIRTQ_MAX_CNT,
    1596                  pHlp->pfnSSMSetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
    1597                                           N_("Saved queue count %u, expected %u"), uVersion, VIRTQ_MAX_CNT));
    1598     AssertCompile(RT_ELEMENTS(pVirtio->virtqState) == VIRTQ_MAX_CNT);
    1599     AssertCompile(RT_ELEMENTS(pVirtio->aGCPhysQueueDesc) == VIRTQ_MAX_CNT);
    1600 
    1601     for (uint32_t idxQueue = 0; idxQueue < pVirtio->uNumQueues; idxQueue++)
     1603    for (uint32_t idxQueue = 0; idxQueue < VIRTQ_MAX_CNT; idxQueue++)
    16021604    {
    16031605        pHlp->pfnSSMGetGCPhys64(pSSM, &pVirtio->aGCPhysQueueDesc[idxQueue]);
     
    16291631 * @param   pVirtio     Pointer to the shared virtio state.
    16301632 */
    1631 void virtioCoreR3PropagateResetNotification(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio)
    1632 {
    1633     /** @todo r=bird: You probably need to do something here.  See
    1634      *        virtioScsiR3Reset. */
     1633void virtioCoreR3VmStateChanged(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, VIRTIOVMSTATECHANGED enmState)
     1634{
     1635
     1636    LogFunc(("State changing to %s: ***FUNCTIONALITY TBD***\n",
     1637        virtioCoreGetStateChangeText(enmState)));
     1638
     1639    switch(enmState)
     1640    {
     1641        case kvirtIoVmStateChangedReset:
     1642            virtioCoreResetAll(pVirtio);
     1643            break;
     1644        case kvirtIoVmStateChangedSuspend:
     1645            break;
     1646        case kvirtIoVmStateChangedPowerOff:
     1647            break;
     1648        case kvirtIoVmStateChangedResume:
     1649            break;
     1650        default:
     1651            LogRelFunc(("Bad enum value"));
     1652            return;
     1653    }
    16351654    RT_NOREF(pDevIns, pVirtio);
    16361655}
     
    16981717    AssertLogRelReturn(pVirtio == PDMINS_2_DATA(pDevIns, PVIRTIOCORE), VERR_STATE_CHANGED);
    16991718    AssertLogRelReturn(pVirtioCC == PDMINS_2_DATA_CC(pDevIns, PVIRTIOCORECC), VERR_STATE_CHANGED);
     1719
     1720    pVirtio->pDevIns = pDevIns;
    17001721
    17011722    /*
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h

    r81818 r81973  
    3636typedef CTX_SUFF(PVIRTIOCORE) PVIRTIOCORECC;
    3737
     38typedef enum VIRTIOVMSTATECHANGED
     39{
     40    kvirtIoVmStateChangedInvalid = 0,
     41    kvirtIoVmStateChangedReset,
     42    kvirtIoVmStateChangedSuspend,
     43    kvirtIoVmStateChangedPowerOff,
     44    kvirtIoVmStateChangedResume,
     45    kvirtIoVmStateChangedFor32BitHack = 0x7fffffff
     46} VIRTIOVMSTATECHANGED;
    3847
    3948/**
     
    159168typedef struct VIRTQSTATE
    160169{
    161     char        szVirtqName[32];                                 /**< Dev-specific name of queue                */
    162     uint16_t    uAvailIdx;                                       /**< Consumer's position in avail ring         */
    163     uint16_t    uUsedIdx;                                        /**< Consumer's position in used ring          */
    164     bool        fEventThresholdReached;                          /**< Don't lose track while queueing ahead     */
     170    char      szVirtqName[32];                                 /**< Dev-specific name of queue                */
     171    uint16_t  uAvailIdx;                                       /**< Consumer's position in avail ring         */
     172    uint16_t  uUsedIdx;                                        /**< Consumer's position in used ring          */
     173    bool      fEventThresholdReached;                          /**< Don't lose track while queueing ahead     */
    165174} VIRTQSTATE, *PVIRTQSTATE;
    166175
     
    222231{
    223232    char                        szInstance[16];                     /**< Instance name, e.g. "VIRTIOSCSI0"         */
    224 
     233    PPDMDEVINS                  pDevIns;                            /**< Client device instance                    */
    225234    RTGCPHYS                    aGCPhysQueueDesc[VIRTQ_MAX_CNT];    /**< (MMIO) PhysAdr per-Q desc structs   GUEST */
    226235    RTGCPHYS                    aGCPhysQueueAvail[VIRTQ_MAX_CNT];   /**< (MMIO) PhysAdr per-Q avail structs  GUEST */
     
    237246    uint32_t                    uDriverFeaturesSelect;              /**< (MMIO) hi/lo select uDriverFeatures GUEST */
    238247    uint32_t                    uMsixConfig;                        /**< (MMIO) MSI-X vector                 GUEST */
    239     uint32_t                    uNumQueues;                         /**< (MMIO) Actual number of queues      GUEST
    240                                                                      * @todo r=bird: This value is always VIRTQ_MAX_CNT
    241                                                                      * and only used in for loops.  Guest always see
    242                                                                      * VIRTQ_MAX_CNT regardless of this value, so
    243                                                                      * what's the point of having this? */
    244248    uint8_t                     uDeviceStatus;                      /**< (MMIO) Device Status                GUEST */
    245249    uint8_t                     uPrevDeviceStatus;                  /**< (MMIO) Prev Device Status           GUEST */
     
    261265    uint8_t                     uISR;                               /**< Interrupt Status Register.                */
    262266    uint8_t                     fMsiSupport;
    263 
    264267
    265268    /** The MMIO handle for the PCI capability region (\#2). */
     
    369372 * @{ */
    370373
    371 int virtioCoreR3QueueAttach(PVIRTIOCORE pVirtio, uint16_t idxQueue, const char *pcszName);
    372 #if 0 /* no such function */
    373 /**
    374  * Detaches from queue and release resources
    375  *
    376  * @param hVirtio   Handle for VirtIO framework
    377  * @param idxQueue      Queue number
    378  */
    379 int virtioCoreR3QueueDetach(PVIRTIOCORE pVirtio, uint16_t idxQueue);
    380 #endif
     374int  virtioCoreR3QueueAttach(PVIRTIOCORE pVirtio, uint16_t idxQueue, const char *pcszName);
     375
     376int  virtioCoreR3DescChainGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue,
     377                             uint16_t uHeadIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain);
     378
    381379int  virtioCoreR3QueueGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue,
    382380                          PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove);
     
    388386
    389387/**
     388 * Skip the next entry in the specified queue
     389 *
     390 * @param   pVirtio     Pointer to the virtio state.
     391 * @param   idxQueue    Index of queue
     392 *
     393 */
     394int virtioQueueSkip(PVIRTIOCORE pVirtio, uint16_t idxQueue);
     395
     396/**
    390397 * Reset the device and driver (see VirtIO 1.0 section 2.1.1/2.1.2)
    391398 *
     
    469476int      virtioCoreR3SaveExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM);
    470477int      virtioCoreR3LoadExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM);
    471 void     virtioCoreR3PropagateResetNotification(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio);
    472 void     virtioCoreR3PropagateResumeNotification(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio);
     478void     virtioCoreR3VmStateChanged(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, VIRTIOVMSTATECHANGED enmState);
    473479void     virtioCoreR3Term(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC);
    474480int      virtioCoreR3Init(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, PVIRTIOPCIPARAMS pPciParams,
    475481                      const char *pcszInstance, uint64_t fDevSpecificFeatures, void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg);
    476482int      virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC);
     483const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState);
     484
    477485/** @} */
    478486
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