VirtualBox

Changeset 80762 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Sep 13, 2019 2:33:47 AM (5 years ago)
Author:
vboxsync
Message:

Storage/DevVirtioSCSI.cpp: Added multi-target support. See bugref:9440, Comment #90

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

Legend:

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

    r80718 r80762  
    4747#include "VBoxDD.h"
    4848
    49 
     49#define LUN0    0
    5050/**
    5151 * @name VirtIO 1.0 SCSI Host feature bits (See VirtIO 1.0 specification, Section 5.6.3)
     
    7171#define VIRTIOSCSI_REQ_QUEUE_CNT                    1            /**< Number of req queues exposed by dev.            */
    7272#define VIRTIOSCSI_QUEUE_CNT                        VIRTIOSCSI_REQ_QUEUE_CNT + 2
    73 #define VIRTIOSCSI_MAX_TARGETS                      1            /**< Can probably determined from higher layers      */
    74 #define VIRTIOSCSI_MAX_LUN                                    /* < VirtIO specification, section 5.6.4             */
     73#define VIRTIOSCSI_MAX_TARGETS                      256          /**< Default value                                   */
     74#define VIRTIOSCSI_MAX_LUN                          256          /* < VirtIO specification, section 5.6.4             */
    7575#define VIRTIOSCSI_MAX_COMMANDS_PER_LUN             1            /* < T.B.D. What is a good value for this?           */
    7676#define VIRTIOSCSI_MAX_SEG_COUNT                    1024         /* < T.B.D. What is a good value for this?           */
     
    196196    // Device-writable part
    197197    uint32_t uEvent;                                            /**< event:                                          */
    198     uint8_t  uLUN[8];                                           /**< lun                                             */
     198    uint8_t  uVirtioLun[8];                                     /**< lun                                             */
    199199    uint32_t uReason;                                           /**< reason                                          */
    200200} VIRTIOSCSI_EVENT_T, *PVIRTIOSCSI_EVENT_T;
     
    216216struct REQ_CMD_HDR
    217217{
    218     uint8_t  uLUN[8];                                           /**< lun                                          */
     218    uint8_t  uVirtioLun[8];                                     /**< lun                                          */
    219219    uint64_t uId;                                               /**< id                                           */
    220220    uint8_t  uTaskAttr;                                         /**< task_attr                                    */
     
    290290{
    291291    uint32_t uType;
    292 } VIRTIOSCSI_CTRL, *PVIRTIOSCSI_CTRL_T;
     292} VIRTIOSCSI_CTRL_T, *PVIRTIOSCSI_CTRL_T;
    293293
    294294/**
     
    312312    uint32_t uType;                                            /** type                                              */
    313313    uint32_t uSubtype;                                         /** subtype                                           */
    314     uint8_t  uLUN[8];                                          /** lun                                               */
     314    uint8_t  uScsiLun[8];                                    /** lun                                               */
    315315    uint64_t uId;                                              /** id                                                */
    316316    // Device-writable part
     
    335335    // Device-readable part
    336336    uint32_t  uType;                                          /** type                                               */
    337     uint8_t   uLUN[8];                                        /** lun                                                */
     337    uint8_t   uScsiLun[8];                                  /** lun                                                */
    338338    uint32_t  uEventsRequested;                               /** event_requested                                    */
    339339    // Device-writable part
     
    384384    R3PTRTYPE(PPDMIBASE)            pDrvBase;
    385385
    386     /** Target LUN */
    387     RTUINT                          iLUN;
    388 
    389     /** Target LUN Description */
    390     char *                          pszLunName;
     386    /** Target number (PDM LUN) */
     387    RTUINT                          iTarget;
     388
     389    /** Target Description */
     390    char *                          pszTargetName;
    391391
    392392    /** Target base interface. */
     
    452452    /** Pointer to the device instance. - R3 ptr. */
    453453    PPDMDEVINSR3                    pDevInsR3;
     454
    454455    /** Pointer to the device instance. - R0 ptr. */
    455456    PPDMDEVINSR0                    pDevInsR0;
     457
    456458    /** Pointer to the device instance. - RC ptr. */
    457459    PPDMDEVINSRC                    pDevInsRC;
    458460
    459     /** Status LUN: LEDs port interface. */
     461    /** Status Target: LEDs port interface. */
    460462    PDMILEDPORTS                    ILeds;
    461463
    462     /** Status LUN: Partner of ILeds. */
     464    /** Status Target: Partner of ILeds. */
    463465    R3PTRTYPE(PPDMILEDCONNECTORS)   pLedsConnector;
    464466
     
    480482    /** The event semaphore the processing thread waits on. */
    481483
    482     /** Number of ports detected */
     484    /** Number of targets detected */
    483485    uint64_t                        cTargets;
    484486
     
    518520    /** True if in the process of quiescing I/O */
    519521    bool                            fQuiescing;
    520 
    521 
    522522
    523523} VIRTIOSCSI, *PVIRTIOSCSI;
     
    532532    PVIRTIOSCSITARGET              pTarget;                  /**< Target                                            */
    533533    uint16_t                       qIdx;                     /**< Index of queue this request arrived on            */
    534     size_t                         cbIn;                     /**< Size of input descriptor chain                    */
    535     size_t                         cbOut;                    /**< Size of output descriptor chain                   */
    536534    size_t                         cbPiOut;                  /**< Size of T10 pi in buffer                          */
    537535    uint8_t                       *pbPiOut;                  /**< Address of pi out buffer                          */
     
    547545    PDMMEDIAEXIOREQSCSITXDIR       enmTxDir;                 /**< Receives transfer direction of I/O req            */
    548546    uint8_t                        uStatus;                  /**< SCSI status code                                  */
    549     PRTSGBUF                       pInSgBuf;                 /**< Buf vector to return PDM result to VirtIO Guest   */
    550     PVIRTIOSCSI_REQ_CMD_T          pVirtqReq;                /**< Holds guest's queued req after phys → virt trans  */
     547    PVIRTIO_DESC_CHAIN_T           pDescChain;               /**< Prepared desc chain pulled from virtq avail ring  */
    551548} VIRTIOSCSIREQ;
    552 
    553 #define PTARGET_FROM_LUN_BUF(lunBuf) &pThis->aTargetInstances[lunBuf[1]];
    554549
    555550DECLINLINE(bool) isBufZero(uint8_t *pv, size_t cb)
     
    675670#endif
    676671
    677 DECLINLINE(void) virtioScsiVirtToSgPhys(PVIRTIOSCSI pThis, PRTSGBUF pSgDst, void *pvSrc, size_t cb)
    678 {
    679     while (cb)
    680     {
    681         size_t cbSeg = cb;
    682         RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pSgDst, &cbSeg);
    683         PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhys, pvSrc, cbSeg);
    684         pvSrc = ((uint8_t *)pvSrc) + cbSeg;
    685         cb -= cbSeg;
    686     }
    687 }
    688 
    689 DECLINLINE(void) virtioScsiSgPhysToVirt(PVIRTIOSCSI pThis, PRTSGBUF pSgSrc, void *pvDst, size_t cb)
    690 {
    691     while (cb)
    692     {
    693         size_t cbSeg = cb;
    694         RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pSgSrc, &cbSeg);
    695         PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pvDst, cbSeg);
    696         pvDst = ((uint8_t *)pvDst) + cbSeg;
    697         cb -= cbSeg;
    698     }
    699 }
    700 
    701672/**
    702673 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf}
     
    728699static int virtioScsiSendEvent(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uEventType, uint32_t uReason)
    729700{
    730     uint8_t uLUN = 0;
    731701
    732702    VIRTIOSCSI_EVENT_T event;
    733703    event.uEvent = uEventType;
    734704    event.uReason = uReason;
    735     event.uLUN[0] = 1;
    736     event.uLUN[1] = uTarget;
    737     event.uLUN[2] = (uLUN >> 8) & 0x40;
    738     event.uLUN[3] = uLUN & 0xff;
    739     event.uLUN[4] = event.uLUN[5] = event.uLUN[6] = event.uLUN[7] = 0;
     705    event.uVirtioLun[0] = 1;
     706    event.uVirtioLun[1] = uTarget;
     707    event.uVirtioLun[2] = (LUN0 >> 8) & 0x40;
     708    event.uVirtioLun[3] = LUN0 & 0xff;
     709    event.uVirtioLun[4] = event.uVirtioLun[5] = event.uVirtioLun[6] = event.uVirtioLun[7] = 0;
    740710
    741711    switch(uEventType)
     
    743713        case VIRTIOSCSI_T_NO_EVENT:
    744714            if (uEventType & VIRTIOSCSI_T_EVENTS_MISSED)
    745                 LogFunc(("Warning driver that events were missed\n", uTarget, uLUN));
     715                LogFunc(("(target=%d, LUN=%d) Warning driver that events were missed\n", uTarget, LUN0));
    746716            else
    747717                LogFunc(("(target=%d, LUN=%d): Warning event info guest queued is shorter than configured\n",
    748                           uTarget, uLUN));
     718                          uTarget, LUN0));
    749719            break;
    750720        case VIRTIOSCSI_T_TRANSPORT_RESET:
     
    752722            {
    753723                case VIRTIOSCSI_EVT_RESET_REMOVED:
    754                     LogFunc(("(target=%d, LUN=%d): Target or LUN removed\n", uTarget, uLUN));
     724                    LogFunc(("(target=%d, LUN=%d): Target or LUN removed\n", uTarget, LUN0));
    755725                    break;
    756726                case VIRTIOSCSI_EVT_RESET_RESCAN:
    757                     LogFunc(("(target=%d, LUN=%d): Target or LUN added\n", uTarget, uLUN));
     727                    LogFunc(("(target=%d, LUN=%d): Target or LUN added\n", uTarget, LUN0));
    758728                    break;
    759729                case VIRTIOSCSI_EVT_RESET_HARD:
    760                     LogFunc(("(target=%d, LUN=%d): Target was reset\n", uTarget, uLUN));
     730                    LogFunc(("(target=%d, LUN=%d): Target was reset\n", uTarget, LUN0));
    761731                    break;
    762732            }
     
    765735            char szTypeText[128];
    766736            virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), uReason);
    767             LogFunc(("(target=%d, LUN=%d): Delivering subscribed async notification %s\n", uTarget, uLUN));
     737            LogFunc(("(target=%d, LUN=%d): Delivering subscribed async notification %s\n", uTarget, LUN0));
    768738            break;
    769739        case VIRTIOSCSI_T_PARAM_CHANGE:
    770740            LogFunc(("(target=%d, LUN=%d): PARAM_CHANGE sense code: 0x%x sense qualifier: 0x%x\n",
    771                         uTarget, uLUN, uReason & 0xff, (uReason >> 8) & 0xff));
     741                        uTarget, LUN0, uReason & 0xff, (uReason >> 8) & 0xff));
    772742            break;
    773743        default:
    774             LogFunc(("(target=%d, LUN=%d): Unknown event type: %d, ignoring\n", uTarget, uLUN));
     744            LogFunc(("(target=%d, LUN=%d): Unknown event type: %d, ignoring\n", uTarget, LUN0));
    775745            return VINF_SUCCESS;
    776746    }
     
    783753    }
    784754
    785     virtioQueueGet(pThis->hVirtio, EVENTQ_IDX, true, NULL, NULL);
     755    PVIRTIO_DESC_CHAIN_T pDescChain;
     756    virtioQueueGet(pThis->hVirtio, EVENTQ_IDX, &pDescChain, true);
    786757
    787758    RTSGBUF reqSegBuf;
     
    789760    RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
    790761
    791     virtioQueuePut (pThis->hVirtio, EVENTQ_IDX, &reqSegBuf, true);
     762    virtioQueuePut (pThis->hVirtio, EVENTQ_IDX, &reqSegBuf, pDescChain, true);
    792763    virtioQueueSync(pThis->hVirtio, EVENTQ_IDX);
    793764
     
    800771    RTMemFree(pReq->pbPiIn);
    801772    RTMemFree(pReq->pbDataIn);
    802     RTMemFree(pReq->pVirtqReq);
    803773    pTarget->pDrvMediaEx->pfnIoReqFree(pTarget->pDrvMediaEx, pReq->hIoReq);
    804774}
     
    807777 * This is called to complete a request immediately
    808778 *
    809  * @param pThis     - PDM driver instance state
    810  * @param qIdx      - Queue index
    811  * @param pRespHdr  - Response header
    812  * @param pbSense   - Pointer to sense buffer or NULL if none.
     779 * @param pThis      - PDM driver instance state
     780 * @param qIdx       - Queue index
     781 * @param pDescChain - Pointer to pre-processed descriptor chain pulled from virtq
     782 * @param pRespHdr   - Response header
     783 * @param pbSense    - Pointer to sense buffer or NULL if none.
    813784 *
    814785 * @returns virtual box status code
    815786 */
    816 static int virtioScsiReqErr(PVIRTIOSCSI pThis, uint16_t qIdx, struct REQ_RESP_HDR *pRespHdr, uint8_t *pbSense)
    817 {
    818 
     787static int virtioScsiReqErr(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain,
     788                            struct REQ_RESP_HDR *pRespHdr, uint8_t *pbSense)
     789{
    819790    uint8_t *abSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize);
    820791    AssertReturn(abSenseBuf, VERR_NO_MEMORY);
     
    840811        pRespHdr->uResponse = VIRTIOSCSI_S_RESET;
    841812
    842     virtioQueuePut(pThis->hVirtio, qIdx, &reqSegBuf, true /* fFence */);
     813    virtioQueuePut(pThis->hVirtio, qIdx, &reqSegBuf, pDescChain, true /* fFence */);
    843814    virtioQueueSync(pThis->hVirtio, qIdx);
    844815
     
    861832    RT_NOREF(pInterface);
    862833
    863     PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
    864     PVIRTIOSCSITARGET pTarget = pReq->pTarget;
    865     PVIRTIOSCSI pThis = pTarget->pVirtioScsi;
    866     PPDMIMEDIAEX pIMediaEx = pTarget->pDrvMediaEx;
     834    PVIRTIOSCSIREQ    pReq      = (PVIRTIOSCSIREQ)pvIoReqAlloc;
     835    PVIRTIOSCSITARGET pTarget   = pReq->pTarget;
     836    PVIRTIOSCSI       pThis    = pTarget->pVirtioScsi;
     837    PPDMIMEDIAEX      pIMediaEx = pTarget->pDrvMediaEx;
    867838
    868839    size_t cbResidual = 0, cbXfer = 0;
     
    937908    {
    938909        LogFunc(("cbDataIn = %u, cbDataOut = %u (cbIn = %u, cbOut = %u)\n",
    939                   pReq->cbDataIn, pReq->cbDataOut, pReq->cbIn, pReq->cbOut));
     910                  pReq->cbDataIn, pReq->cbDataOut, pReq->pDescChain->cbPhysDst, pReq->pDescChain->cbVirtSrc));
    940911        LogFunc(("xfer = %d, residual = %u\n", cbXfer, cbResidual));
    941912        LogFunc(("xfer direction: %s, sense written = %d, sense size = %d\n",
     
    984955        respHdr.uResponse = VIRTIOSCSI_S_OVERRUN;
    985956        respHdr.uResidual = pReq->cbDataIn;
    986         virtioScsiReqErr(pThis, pReq->qIdx, &respHdr, abSense);
     957
     958        virtioScsiReqErr(pThis, pReq->qIdx, pReq->pDescChain, &respHdr, abSense);
    987959        return VINF_SUCCESS;
    988960    }
     
    1016988         */
    1017989        size_t cbReqSgBuf = RTSgBufCalcTotalLength(&reqSegBuf);
    1018         size_t cbInSgBuf  = RTSgBufCalcTotalLength(pReq->pInSgBuf);
    1019         AssertMsgReturn(cbReqSgBuf <= cbInSgBuf,
    1020                        ("Guest expected less req data (space needed: %d, avail: %d)\n", cbReqSgBuf, cbInSgBuf),
     990        AssertMsgReturn(cbReqSgBuf <= pReq->pDescChain->cbPhysDst,
     991                       ("Guest expected less req data (space needed: %d, avail: %d)\n",
     992                         cbReqSgBuf, pReq->pDescChain->cbPhysDst),
    1021993                       VERR_BUFFER_OVERFLOW);
    1022994
    1023         virtioQueuePut(pThis->hVirtio, pReq->qIdx, &reqSegBuf, true /* fFence TBD */);
     995        virtioQueuePut(pThis->hVirtio, pReq->qIdx, &reqSegBuf, pReq->pDescChain, true /* fFence TBD */);
    1024996        virtioQueueSync(pThis->hVirtio, pReq->qIdx);
    1025997
     
    10361008}
    10371009
    1038 
    1039 static int virtioScsiReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PRTSGBUF pInSgBuf, PRTSGBUF pOutSgBuf)
    1040 {
    1041     AssertMsgReturn(pOutSgBuf->cSegs, ("Req. has no OUT data, unexpected/TBD\n"), VERR_INVALID_PARAMETER);
    1042 
     1010static int virtioScsiReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain)
     1011{
    10431012    ASMAtomicIncU32(&pThis->cActiveReqs);
    10441013
    1045     size_t cbOut = RTSgBufCalcTotalLength(pOutSgBuf);
    1046     size_t cbIn  = RTSgBufCalcTotalLength(pInSgBuf);
    1047 
    1048     PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)RTMemAlloc(cbOut);
    1049     AssertReturn(pVirtqReq, VERR_NO_MEMORY);
    1050 
    1051     virtioScsiSgPhysToVirt(pThis, pOutSgBuf, pVirtqReq, cbOut);
    1052 
    1053     uint8_t  uTarget =  pVirtqReq->cmdHdr.uLUN[1];
    1054     uint32_t uLUN    = (pVirtqReq->cmdHdr.uLUN[2] << 8 | pVirtqReq->cmdHdr.uLUN[3]) & 0x3fff;
     1014    PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)pDescChain->pVirtSrc;
     1015
     1016    uint8_t  uTarget  = pVirtqReq->cmdHdr.uVirtioLun[1];
     1017    uint32_t uScsiLun = (pVirtqReq->cmdHdr.uVirtioLun[2] << 8 | pVirtqReq->cmdHdr.uVirtioLun[3]) & 0x3fff;
     1018    PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[uTarget];
    10551019
    10561020    LogFunc(("[%s] (Target: %d LUN: %d)  CDB: %.*Rhxs\n",
    1057         SCSICmdText(pVirtqReq->uCdb[0]), uTarget, uLUN,
     1021        SCSICmdText(pVirtqReq->uCdb[0]), uTarget, uScsiLun,
    10581022        virtioScsiEstimateCdbLen(pVirtqReq->uCdb[0],
    10591023        pThis->virtioScsiConfig.uCdbSize), pVirtqReq->uCdb));
     
    10611025    Log3Func(("id: %RX64, attr: %x, prio: %d, crn: %x\n",
    10621026        pVirtqReq->cmdHdr.uId, pVirtqReq->cmdHdr.uTaskAttr, pVirtqReq->cmdHdr.uPrio, pVirtqReq->cmdHdr.uCrn));
    1063 
    1064     PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[uTarget];
    10651027
    10661028    /*
     
    10781040    }
    10791041
    1080     off_t   uDataOutOff = sizeof(REQ_CMD_HDR)  + pThis->virtioScsiConfig.uCdbSize   + cbPiHdr;
     1042    off_t   uDataOutOff = sizeof(REQ_CMD_HDR)  + pThis->virtioScsiConfig.uCdbSize + cbPiHdr;
    10811043    off_t   uDataInOff  = sizeof(REQ_RESP_HDR) + pThis->virtioScsiConfig.uSenseSize + cbPiIn;
    10821044    uint8_t *pbDataOut = (uint8_t *)((uint64_t)pVirtqReq + uDataOutOff);
    1083     size_t  cbDataOut = cbOut - uDataOutOff;
    1084     size_t  cbDataIn  = cbIn - uDataInOff;
     1045    size_t  cbDataOut = pDescChain->cbVirtSrc - uDataOutOff;
     1046    size_t  cbDataIn  = pDescChain->cbPhysDst - uDataInOff;
    10851047
    10861048    /**
     
    10951057        respHdr.uResponse = VIRTIOSCSI_S_RESET;
    10961058        respHdr.uResidual = cbDataIn + cbDataOut;
    1097         virtioScsiReqErr(pThis, qIdx, &respHdr, NULL);
    1098         RTMemFree(pVirtqReq);
     1059        virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr, NULL);
    10991060        return VINF_SUCCESS;
    11001061    }
    11011062    else
    1102     if (uTarget >= pThis->cTargets || uLUN != 0)
    1103     {
    1104         Log2Func(("Error submitting request to bad target (%d) or bad LUN (%d)\n", uTarget, uLUN));
     1063    if (uTarget >= pThis->cTargets || uScsiLun != 0)
     1064    {
     1065        Log2Func(("Error submitting request to bad target (%d) or bad LUN (%d)\n", uTarget, uScsiLun));
    11051066        uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED,
    11061067                              0, SCSI_SENSE_ILLEGAL_REQUEST,
     
    11111072        respHdr.uResponse = (uTarget > pThis->cTargets) ? VIRTIOSCSI_S_BAD_TARGET : VIRTIOSCSI_S_OK;
    11121073        respHdr.uResidual = cbDataOut + cbDataIn;
    1113         virtioScsiReqErr(pThis, qIdx, &respHdr, abSense);
    1114         RTMemFree(pVirtqReq);
     1074        virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr, abSense);
    11151075        return VINF_SUCCESS;
    11161076    }
     
    11261086        respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE;
    11271087        respHdr.uResidual = cbDataIn + cbDataOut;
    1128         virtioScsiReqErr(pThis, qIdx, &respHdr, abSense);
    1129         RTMemFree(pVirtqReq);
     1088        virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr , abSense);
    11301089        return VINF_SUCCESS;
    11311090    }
     
    11511110        pReq->pbPiOut   = (uint8_t *)((uint64_t)pVirtqReq + piOutOff);
    11521111        pReq->cbPiIn    = cbPiIn;
    1153         pReq->pbPiIn    = (uint8_t *)RTMemAllocZ(cbPiIn);
     1112        pReq->pbPiIn    = (uint8_t *)RTMemAlloc(cbPiIn);
    11541113        AssertMsgReturn(pReq->pbPiIn, ("Out of memory allocating pi_in buffer"),  VERR_NO_MEMORY);
    11551114    }
    11561115
    1157     pReq->hIoReq    = hIoReq;
    1158     pReq->pTarget   = pTarget;
    1159     pReq->qIdx      = qIdx;
    1160     pReq->cbIn      = cbIn;
    1161     pReq->cbOut     = cbOut;
    1162     pReq->cbDataOut = cbDataOut;
    1163     pReq->pbDataOut = cbDataOut ? pbDataOut : 0;
    1164     pReq->pVirtqReq = pVirtqReq;
    1165     pReq->pInSgBuf  = pInSgBuf;
    1166     pReq->cbSense   = pThis->virtioScsiConfig.uSenseSize;
    1167     pReq->pbSense   = (uint8_t *)RTMemAllocZ(pReq->cbSense);
     1116    pReq->hIoReq     = hIoReq;
     1117    pReq->pTarget    = pTarget;
     1118    pReq->qIdx       = qIdx;
     1119    pReq->cbDataOut  = cbDataOut;
     1120    pReq->pbDataOut  = cbDataOut ? pbDataOut : 0;
     1121    pReq->pDescChain = pDescChain;
     1122    pReq->cbSense    = pThis->virtioScsiConfig.uSenseSize;
     1123    pReq->pbSense    = (uint8_t *)RTMemAlloc(pReq->cbSense);
    11681124    AssertMsgReturn(pReq->pbSense,  ("Out of memory allocating sense buffer"),  VERR_NO_MEMORY);
    11691125
     
    11711127    {
    11721128        pReq->cbDataIn  = cbDataIn;
    1173         pReq->pbDataIn  = (uint8_t *)RTMemAllocZ(cbDataIn);
     1129        pReq->pbDataIn  = (uint8_t *)RTMemAlloc(cbDataIn);
    11741130        AssertMsgReturn(pReq->pbDataIn, ("Out of memory allocating datain buffer"), VERR_NO_MEMORY);
    11751131    }
    11761132
    1177     rc = pIMediaEx->pfnIoReqSendScsiCmd(pIMediaEx, pReq->hIoReq, uLUN,
     1133    rc = pIMediaEx->pfnIoReqSendScsiCmd(pIMediaEx, pReq->hIoReq, uScsiLun,
    11781134                                        pVirtqReq->uCdb, pThis->virtioScsiConfig.uCdbSize,
    11791135                                        PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, &pReq->enmTxDir,
     
    12091165        respHdr.uResponse = VIRTIOSCSI_S_FAILURE;
    12101166        respHdr.uResidual = cbDataIn + cbDataOut;
    1211         virtioScsiReqErr(pThis, qIdx, &respHdr, abSense);
     1167        virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr, abSense);
    12121168        virtioScsiFreeReq(pTarget, pReq);
    12131169        return VINF_SUCCESS;
     
    12171173}
    12181174
    1219 static int virtioScsiCtrl(PVIRTIOSCSI pThis, uint16_t qIdx, PRTSGBUF pInSgBuf, PRTSGBUF pOutSgBuf)
    1220 {
    1221     RT_NOREF3(pThis, qIdx, pInSgBuf);
    1222 
    1223     /*
    1224      * According to the VirtIO 1.0 SCSI Host device, spec, section 5.6.6.2, control packets are
    1225      * extremely small, so more than one segment is highly unlikely but not a bug. Get the
    1226      * the controlq sg buffer into virtual memory. */
    1227 
    1228     size_t cbOut = RTSgBufCalcTotalLength(pOutSgBuf);
    1229 
    1230     PVIRTIOSCSI_CTRL_T pScsiCtrl = (PVIRTIOSCSI_CTRL_T)RTMemAllocZ(cbOut);
    1231     AssertMsgReturn(pScsiCtrl, ("Out of memory"), VERR_NO_MEMORY);
    1232 
    1233     virtioScsiSgPhysToVirt(pThis, pOutSgBuf, pScsiCtrl, cbOut);
     1175static int virtioScsiCtrl(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain)
     1176{
     1177    RT_NOREF2(pThis, qIdx);
    12341178
    12351179    uint8_t  uResponse = VIRTIOSCSI_S_OK;
     1180
     1181    PVIRTIOSCSI_CTRL_T pScsiCtrl = (PVIRTIOSCSI_CTRL_T)pDescChain->pVirtSrc;
    12361182
    12371183    /*
     
    12531199            PVIRTIOSCSI_CTRL_TMF_T pScsiCtrlTmf = (PVIRTIOSCSI_CTRL_TMF_T)pScsiCtrl;
    12541200            LogFunc(("%s, VirtIO LUN: %.8Rhxs\n%*sTask Mgt Function: %s (not yet implemented)\n",
    1255                 QUEUENAME(qIdx), pScsiCtrlTmf->uLUN,
     1201                QUEUENAME(qIdx), pScsiCtrlTmf->uScsiLun,
    12561202                CBQUEUENAME(qIdx) + 18, "", virtioGetTMFTypeText(pScsiCtrlTmf->uSubtype)));
    12571203
     
    13051251
    13061252                LogFunc(("%s, VirtIO LUN: %.8Rhxs\n%*sAsync Query, types: %s\n",
    1307                     QUEUENAME(qIdx), pScsiCtrlAnQuery->uLUN, CBQUEUENAME(qIdx) + 30, "", szTypeText));
     1253                    QUEUENAME(qIdx), pScsiCtrlAnQuery->uScsiLun, CBQUEUENAME(qIdx) + 30, "", szTypeText));
    13081254            }
    13091255
     
    13291275
    13301276                LogFunc(("%s, VirtIO LUN: %.8Rhxs\n%*sAsync Subscribe, types: %s\n",
    1331                     QUEUENAME(qIdx), pScsiCtrlAnSubscribe->uLUN, CBQUEUENAME(qIdx) + 30, "", szTypeText));
     1277                    QUEUENAME(qIdx), pScsiCtrlAnSubscribe->uScsiLun, CBQUEUENAME(qIdx) + 30, "", szTypeText));
    13321278            }
    13331279
     
    13561302
    13571303    LogFunc(("Response code: %s\n", virtioGetCtrlRespText(uResponse)));
    1358     virtioQueuePut (pThis->hVirtio, qIdx, &reqSegBuf, true);
     1304    virtioQueuePut (pThis->hVirtio, qIdx, &reqSegBuf, pDescChain, true);
    13591305    virtioQueueSync(pThis->hVirtio, qIdx);
    13601306
     
    13831329    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    13841330    PWORKER pWorker = &pThis->aWorker[qIdx];
    1385     PRTSGBUF pInSgBuf;
    1386     PRTSGBUF pOutSgBuf;
    13871331
    13881332    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     
    14161360        }
    14171361        Log6Func(("fetching next descriptor chain from %s\n", QUEUENAME(qIdx)));
    1418         rc = virtioQueueGet(pThis->hVirtio, qIdx, true, &pInSgBuf, &pOutSgBuf);
     1362        PVIRTIO_DESC_CHAIN_T pDescChain;
     1363        rc = virtioQueueGet(pThis->hVirtio, qIdx, &pDescChain, true);
    14191364        if (rc == VERR_NOT_AVAILABLE)
    14201365        {
     
    14251370        AssertRC(rc);
    14261371        if (qIdx == CONTROLQ_IDX)
    1427             virtioScsiCtrl(pThis, qIdx, pInSgBuf, pOutSgBuf);
     1372            virtioScsiCtrl(pThis, qIdx, pDescChain);
    14281373        else
    14291374        {
    1430             rc = virtioScsiReqSubmit(pThis, qIdx, pInSgBuf, pOutSgBuf);
     1375            rc = virtioScsiReqSubmit(pThis, qIdx, pDescChain);
    14311376            if (RT_FAILURE(rc))
    14321377            {
     
    16141559    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
    16151560    PVIRTIOSCSI pThis = pTarget->pVirtioScsi;
    1616     LogFunc(("LUN %d Ejected!\n", pTarget->iLUN));
     1561    LogFunc(("LUN %d Ejected!\n", pTarget->iTarget));
    16171562    if (pThis->pMediaNotify)
    16181563    {
    16191564         int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY,
    16201565                                   (PFNRT)pThis->pMediaNotify->pfnEjected, 2,
    1621                                     pThis->pMediaNotify, pTarget->iLUN);
     1566                                    pThis->pMediaNotify, pTarget->iTarget);
    16221567         AssertRC(rc);
    16231568    }
     
    16861631
    16871632    pThis->fQuiescing = false;
    1688 #if 0 /* This should be unnecessary */
    1689     if (pThis->fResetting)
    1690     {
    1691         Log2Func(("Resetting VirtIO\n"));
    1692 
    1693 
    1694         /* Reset virtio infrastructure */
    1695         virtioResetAll(pThis->hVirtio);
    1696 
    1697         /* Reset locally-owned negotiable device-specific config parameters
    1698          *  to VirtIO spec-mandated default values */
    1699     }
    1700 #endif
     1633
    17011634    return true;
    17021635}
     
    18181751void virtioScsiSetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn)
    18191752{
    1820     LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->pszLunName, fOn ? "on" : "off"));
     1753    LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off"));
    18211754    if (fOn)
    18221755        pTarget->led.Asserted.s.fWriting = pTarget->led.Actual.s.fWriting = 1;
     
    18331766void virtioScsiSetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn)
    18341767{
    1835     LogFlow(("%s virtioSetReadLed: %s\n", pTarget->pszLunName, fOn ? "on" : "off"));
     1768    LogFlow(("%s virtioSetReadLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off"));
    18361769    if (fOn)
    18371770        pTarget->led.Asserted.s.fReading = pTarget->led.Actual.s.fReading = 1;
     
    18451778 * @returns VBox status code.
    18461779 * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    1847  * @param   iLUN            The unit which status LED we desire.
     1780 * @param   iTarget            The unit which status LED we desire.
    18481781 * @param   ppLed           Where to store the LED pointer.
    18491782 */
    1850 static DECLCALLBACK(int) virtioScsiTargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
     1783static DECLCALLBACK(int) virtioScsiTargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed)
    18511784{
    18521785  PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed);
    1853     if (iLUN == 0)
     1786    if (iTarget == 0)
    18541787    {
    18551788        *ppLed = &pTarget->led;
     
    18651798 * @returns VBox status code.
    18661799 * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    1867  * @param   iLUN            The unit which status LED we desire.
     1800 * @param   iTarget            The unit which status LED we desire.
    18681801 * @param   ppLed           Where to store the LED pointer.
    18691802 */
    1870 static DECLCALLBACK(int) virtioScsiDeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
     1803static DECLCALLBACK(int) virtioScsiDeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed)
    18711804{
    18721805    PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, ILeds);
    1873     if (iLUN < pThis->cTargets)
    1874     {
    1875         *ppLed = &pThis->aTargetInstances[iLUN].led;
     1806    if (iTarget < pThis->cTargets)
     1807    {
     1808        *ppLed = &pThis->aTargetInstances[iTarget].led;
    18761809        Assert((*ppLed)->u32Magic == PDMLED_MAGIC);
    18771810        return VINF_SUCCESS;
     
    19971930
    19981931static DECLCALLBACK(int) virtioScsiQueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
    1999                                                        uint32_t *piInstance, uint32_t *piLUN)
     1932                                                       uint32_t *piInstance, uint32_t *piTarget)
    20001933{
    20011934    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaPort);
     
    20041937    AssertPtrReturn(ppcszController, VERR_INVALID_POINTER);
    20051938    AssertPtrReturn(piInstance, VERR_INVALID_POINTER);
    2006     AssertPtrReturn(piLUN, VERR_INVALID_POINTER);
     1939    AssertPtrReturn(piTarget, VERR_INVALID_POINTER);
    20071940
    20081941    *ppcszController = pDevIns->pReg->szName;
    20091942    *piInstance = pDevIns->iInstance;
    2010     *piLUN = pTarget->iLUN;
     1943    *piTarget = pTarget->iTarget;
    20111944
    20121945    return VINF_SUCCESS;
     
    20461979 *
    20471980 * @param   pDevIns     The device instance.
    2048  * @param   iLUN        The logical unit which is being detached.
     1981 * @param   iTarget        The logical unit which is being detached.
    20491982 * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
    20501983 */
    2051 static DECLCALLBACK(void) virtioScsiDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
     1984static DECLCALLBACK(void) virtioScsiDetach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags)
    20521985{
    20531986    RT_NOREF(fFlags);
    20541987    PVIRTIOSCSI       pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    2055     PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN];
     1988    PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iTarget];
    20561989
    20571990    LogFunc((""));
     
    20742007 * @returns VBox status code.
    20752008 * @param   pDevIns     The device instance.
    2076  * @param   iLUN        The logical unit which is being detached.
     2009 * @param   iTarget        The logical unit which is being detached.
    20772010 * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
    20782011 */
    2079 static DECLCALLBACK(int)  virtioScsiAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
     2012static DECLCALLBACK(int)  virtioScsiAttach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags)
    20802013{
    20812014    PVIRTIOSCSI       pThis   = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    2082     PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN];
     2015    PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iTarget];
    20832016    int rc;
    20842017
     
    20932026    /* the usual paranoia */
    20942027    AssertRelease(!pTarget->pDrvBase);
    2095     Assert(pTarget->iLUN == iLUN);
     2028    Assert(pTarget->iTarget == iTarget);
    20962029
    20972030    /*
     
    20992032     * required as well as optional.
    21002033     */
    2101     rc = PDMDevHlpDriverAttach(pDevIns, pTarget->iLUN, &pDevIns->IBase,
    2102                                &pTarget->pDrvBase, (const char *)&pTarget->pszLunName);
     2034    rc = PDMDevHlpDriverAttach(pDevIns, pTarget->iTarget, &pDevIns->IBase,
     2035                               &pTarget->pDrvBase, (const char *)&pTarget->pszTargetName);
    21032036    if (RT_SUCCESS(rc))
    21042037        pTarget->fPresent = true;
    21052038    else
    2106         AssertMsgFailed(("Failed to attach %s. rc=%Rrc\n", pTarget->pszLunName, rc));
     2039        AssertMsgFailed(("Failed to attach %s. rc=%Rrc\n", pTarget->pszTargetName, rc));
    21072040
    21082041    if (RT_FAILURE(rc))
     
    21502083    LogFunc(("PDM device instance: %d\n", iInstance));
    21512084    RTStrPrintf((char *)pThis->szInstance, sizeof(pThis->szInstance), "VIRTIOSCSI%d", iInstance);
     2085
     2086    /* Usable defaults */
     2087    pThis->cTargets = VIRTIOSCSI_MAX_TARGETS;
    21522088
    21532089    /*
     
    22672203
    22682204    /* Initialize per device instance. */
    2269     for (RTUINT iLUN = 0; iLUN < VIRTIOSCSI_MAX_TARGETS; iLUN++)
    2270     {
    2271         PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN];
    2272 
    2273         if (RTStrAPrintf(&pTarget->pszLunName, "VSCSILUN%u", iLUN) < 0)
     2205
     2206    Log2Func(("Found %d targets attached to controller\n", pThis->cTargets));
     2207
     2208    for (RTUINT iTarget = 0; iTarget < pThis->cTargets; iTarget++)
     2209    {
     2210        PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iTarget];
     2211
     2212        if (RTStrAPrintf(&pTarget->pszTargetName, "VSCSI%u", iTarget) < 0)
    22742213            AssertLogRelFailedReturn(VERR_NO_MEMORY);
    22752214
    22762215        /* Initialize static parts of the device. */
    2277         pTarget->iLUN = iLUN;
     2216        pTarget->iTarget = iTarget;
    22782217        pTarget->pVirtioScsi = pThis;
     2218        pTarget->led.u32Magic = PDMLED_MAGIC;
    22792219
    22802220        pTarget->IBase.pfnQueryInterface                 = virtioScsiTargetQueryInterface;
     
    22962236        pTarget->led.u32Magic                            = PDMLED_MAGIC;
    22972237
    2298         LogFunc(("Attaching LUN: %s\n", pTarget->pszLunName));
    2299 
    2300         AssertReturn(iLUN < RT_ELEMENTS(pThis->aTargetInstances), VERR_PDM_NO_SUCH_LUN);
    2301         rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pTarget->IBase, &pTarget->pDrvBase, (const char *)&pTarget->pszLunName);
     2238        LogFunc(("Attaching LUN: %s\n", pTarget->pszTargetName));
     2239
     2240        AssertReturn(iTarget < RT_ELEMENTS(pThis->aTargetInstances), VERR_PDM_NO_SUCH_LUN);
     2241        rc = PDMDevHlpDriverAttach(pDevIns, iTarget, &pTarget->IBase, &pTarget->pDrvBase, (const char *)&pTarget->pszTargetName);
    23022242        if (RT_SUCCESS(rc))
    23032243        {
    23042244            pTarget->fPresent = true;
    23052245
    2306             /* DrvSCSI.cpp currently implements the IMedia and IMediaEx interfaces, so those
    2307              * are the interfaces that will be used to pass SCSI requests down to the
    2308              * DrvSCSI driver to eventually make it down to the VD layer */
    23092246            pTarget->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIA);
    23102247            AssertMsgReturn(VALID_PTR(pTarget->pDrvMedia),
    2311                          ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", pTarget->iLUN),
     2248                         ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", pTarget->iTarget),
    23122249                         VERR_PDM_MISSING_INTERFACE);
    23132250
     
    23152252            pTarget->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIAEX);
    23162253            AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
    2317                          ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", pTarget->iLUN),
     2254                         ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", pTarget->iTarget),
    23182255                         VERR_PDM_MISSING_INTERFACE);
    23192256
    23202257            rc = pTarget->pDrvMediaEx->pfnIoReqAllocSizeSet(pTarget->pDrvMediaEx, sizeof(VIRTIOSCSIREQ));
    23212258            AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
    2322                          ("virtio-scsi configuration error: LUN#%u: Failed to set I/O request size!\n", pTarget->iLUN),
     2259                         ("virtio-scsi configuration error: LUN#%u: Failed to set I/O request size!\n", pTarget->iTarget),
    23232260                         rc);
    23242261
     
    23262263            AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
    23272264                         ("virtio-scsi configuration error: LUN#%u: Failed to get set Media notify obj!\n",
    2328                           pTarget->iLUN), rc);
     2265                          pTarget->iTarget), rc);
    23292266
    23302267        }
     
    23342271            pTarget->pDrvBase = NULL;
    23352272            rc = VINF_SUCCESS;
    2336             Log(("virtio-scsi: no driver attached to device %s\n", pTarget->pszLunName));
     2273            Log(("virtio-scsi: no driver attached to device %s\n", pTarget->pszTargetName));
    23372274        }
    23382275        else
    23392276        {
    2340             AssertLogRelMsgFailed(("virtio-scsi: Failed to attach %s\n", pTarget->pszLunName));
     2277            AssertLogRelMsgFailed(("virtio-scsi: Failed to attach %s: %Rrc\n", pTarget->pszTargetName));
    23412278            return rc;
    23422279        }
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r80718 r80762  
    3434
    3535#define INSTANCE(pVirtio) pVirtio->szInstance
    36 #define QUEUENAME(qIdx) (pVirtio->virtqProxy[qIdx].szVirtqName)
    37 
     36#define QUEUENAME(qIdx) (pVirtio->virtqState[qIdx].szVirtqName)
     37
     38/**
     39 * See API comments in header file for description
     40 */
     41void virtioVirtToSgPhys(VIRTIOHANDLE hVirtio, PRTSGBUF pSgDst, void *pvSrc, size_t cb)
     42{
     43    while (cb)
     44    {
     45        size_t cbSeg = cb;
     46        RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pSgDst, &cbSeg);
     47        PDMDevHlpPhysWrite(((PVIRTIOSTATE)hVirtio)->CTX_SUFF(pDevIns), GCPhys, pvSrc, cbSeg);
     48        pvSrc = ((uint8_t *)pvSrc) + cbSeg;
     49        cb -= cbSeg;
     50    }
     51}
     52
     53/**
     54 * See API comments in header file for description
     55 */
     56void virtioSgPhysToVirt(VIRTIOHANDLE hVirtio, PRTSGBUF pSgSrc, void *pvDst, size_t cb)
     57{
     58    while (cb)
     59    {
     60        size_t cbSeg = cb;
     61        RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pSgSrc, &cbSeg);
     62        PDMDevHlpPhysRead(((PVIRTIOSTATE)hVirtio)->CTX_SUFF(pDevIns), GCPhys, pvDst, cbSeg);
     63        pvDst = ((uint8_t *)pvDst) + cbSeg;
     64        cb -= cbSeg;
     65    }
     66}
    3867
    3968/**
     
    4473    LogFunc(("%s\n", pcszName));
    4574    PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio;
    46     PVIRTQ_PROXY_T pVirtqProxy = &(pVirtio->virtqProxy[qIdx]);
    47     pVirtqProxy->pDescChain = (PVIRTQ_DESC_CHAIN_T)RTMemAllocZ(sizeof(VIRTQ_DESC_CHAIN_T));
    48     if (!pVirtqProxy->pDescChain)
    49     {
    50         Log(("Out of memory!"));
    51         return VERR_NO_MEMORY;
    52     }
    53     pVirtqProxy->uAvailIdx = 0;
    54     pVirtqProxy->uUsedIdx  = 0;
    55     pVirtqProxy->fEventThresholdReached = false;
    56     RTStrCopy((char *)pVirtqProxy->szVirtqName, sizeof(pVirtqProxy->szVirtqName), pcszName);
     75    PVIRTQSTATE  pVirtq  = &(pVirtio->virtqState[qIdx]);
     76    pVirtq->uAvailIdx = 0;
     77    pVirtq->uUsedIdx  = 0;
     78    pVirtq->fEventThresholdReached = false;
     79    RTStrCopy((char *)pVirtq->szVirtqName, sizeof(pVirtq->szVirtqName), pcszName);
    5780    return VINF_SUCCESS;
    5881
     
    6487const char *virtioQueueGetName(VIRTIOHANDLE hVirtio, uint16_t qIdx)
    6588{
    66     return (const char *)((PVIRTIOSTATE)hVirtio)->virtqProxy[qIdx].szVirtqName;
     89    return (const char *)((PVIRTIOSTATE)hVirtio)->virtqState[qIdx].szVirtqName;
    6790}
    6891
     
    7295int virtioQueueSkip(VIRTIOHANDLE hVirtio, uint16_t qIdx)
    7396{
    74     Assert(qIdx < sizeof(VIRTQ_PROXY_T));
     97    Assert(qIdx < sizeof(VIRTQSTATE));
    7598
    7699    PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio;
    77     PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];
     100    PVIRTQSTATE  pVirtq  = &pVirtio->virtqState[qIdx];
    78101
    79102    AssertMsgReturn(DRIVER_OK(pVirtio) && pVirtio->uQueueEnable[qIdx],
     
    83106        return VERR_NOT_AVAILABLE;
    84107
    85     Log2Func(("%s avail_idx=%u\n", pVirtqProxy->szVirtqName, pVirtqProxy->uAvailIdx));
    86     pVirtqProxy->uAvailIdx++;
     108    Log2Func(("%s avail_idx=%u\n", pVirtq->szVirtqName, pVirtq->uAvailIdx));
     109    pVirtq->uAvailIdx++;
    87110
    88111    return VINF_SUCCESS;
     
    112135 * See API comments in header file for description
    113136 */
    114 int virtioQueuePeek(VIRTIOHANDLE hVirtio, uint16_t qIdx, PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs)
    115 {
    116     return virtioQueueGet(hVirtio, qIdx, false /* fRemove */, ppInSegs, ppOutSegs);
    117 }
    118 
    119  /*/**
    120  * See API comments in header file for description
    121  */
    122 int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, bool fRemove,
    123                 PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs)
    124 {
     137int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain,  bool fRemove)
     138{
     139    Assert(ppDescChain);
     140
    125141    PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio;
    126     PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];
    127     PVIRTQ_DESC_CHAIN_T pDescChain = pVirtqProxy->pDescChain;
     142    PVIRTQSTATE  pVirtq  = &pVirtio->virtqState[qIdx];
     143
     144    PRTSGSEG paSegsIn = (PRTSGSEG)RTMemAlloc(VIRTQ_MAX_SIZE * sizeof(RTSGSEG));
     145    AssertReturn(paSegsIn, VERR_NO_MEMORY);
     146
     147    PRTSGSEG paSegsOut = (PRTSGSEG)RTMemAlloc(VIRTQ_MAX_SIZE * sizeof(RTSGSEG));
     148    AssertReturn(paSegsOut, VERR_NO_MEMORY);
    128149
    129150    AssertMsgReturn(DRIVER_OK(pVirtio) && pVirtio->uQueueEnable[qIdx],
     
    133154        return VERR_NOT_AVAILABLE;
    134155
    135     pDescChain->cSegsIn = pDescChain->cSegsOut = 0;
    136 
    137     pDescChain->uHeadIdx = virtioReadAvailDescIdx(pVirtio, qIdx, pVirtqProxy->uAvailIdx);
    138     uint16_t uDescIdx = pDescChain->uHeadIdx;
     156    uint16_t uHeadIdx = virtioReadAvailDescIdx(pVirtio, qIdx, pVirtq->uAvailIdx);
     157    uint16_t uDescIdx = uHeadIdx;
    139158
    140159    Log6Func(("%s DESC CHAIN: (head) desc_idx=%u [avail_idx=%u]\n",
    141             pVirtqProxy->szVirtqName, pDescChain->uHeadIdx, pVirtqProxy->uAvailIdx));
     160            pVirtq->szVirtqName, uHeadIdx, pVirtq->uAvailIdx));
    142161
    143162    if (fRemove)
    144         pVirtqProxy->uAvailIdx++;
    145 
    146     uint32_t cbIn = 0, cbOut = 0;
     163        pVirtq->uAvailIdx++;
     164
    147165    VIRTQ_DESC_T desc;
     166
     167    uint32_t cbIn = 0, cbOut = 0, cSegsIn = 0, cSegsOut = 0;
     168
    148169    do
    149170    {
     
    151172
    152173        /**
    153         * Malicious guests may go beyond aSegsIn or aSegsOut boundaries by linking
     174        * Malicious guests may go beyond paSegsIn or paSegsOut boundaries by linking
    154175        * several descriptors into a loop. Since there is no legitimate way to get a sequences of
    155176        * linked descriptors exceeding the total number of descriptors in the ring (see @bugref{8620}),
    156177        * the following aborts I/O if breach and employs a simple log throttling algorithm to notify.
    157178        */
    158         if (pDescChain->cSegsIn + pDescChain->cSegsOut >= VIRTQ_MAX_SIZE)
     179        if (cSegsIn + cSegsOut >= VIRTQ_MAX_SIZE)
    159180        {
    160181            static volatile uint32_t s_cMessages  = 0;
     
    178199        {
    179200            Log6Func(("%s IN  desc_idx=%u seg=%u addr=%RGp cb=%u\n",
    180                 QUEUENAME(qIdx), uDescIdx, pDescChain->cSegsIn, desc.pGcPhysBuf, desc.cb));
     201                QUEUENAME(qIdx), uDescIdx, cSegsIn, desc.pGcPhysBuf, desc.cb));
    181202            cbIn += desc.cb;
    182             pSeg = &(pDescChain->aSegsIn[pDescChain->cSegsIn++]);
     203            pSeg = &(paSegsIn[cSegsIn++]);
    183204        }
    184205        else
    185206        {
    186207            Log6Func(("%s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n",
    187                 QUEUENAME(qIdx), uDescIdx, pDescChain->cSegsOut, desc.pGcPhysBuf, desc.cb));
     208                QUEUENAME(qIdx), uDescIdx, cSegsOut, desc.pGcPhysBuf, desc.cb));
    188209            cbOut += desc.cb;
    189             pSeg = &(pDescChain->aSegsOut[pDescChain->cSegsOut++]);
     210            pSeg = &(paSegsOut[cSegsOut++]);
    190211        }
    191212
     
    196217    } while (desc.fFlags & VIRTQ_DESC_F_NEXT);
    197218
    198     RTSgBufInit(&pVirtqProxy->inSgBuf,  (PCRTSGSEG)&pDescChain->aSegsIn,  pDescChain->cSegsIn);
    199     RTSgBufInit(&pVirtqProxy->outSgBuf, (PCRTSGSEG)&pDescChain->aSegsOut, pDescChain->cSegsOut);
    200 
    201     if (ppInSegs)
    202         *ppInSegs = &pVirtqProxy->inSgBuf;
    203 
    204     if (ppOutSegs)
    205         *ppOutSegs = &pVirtqProxy->outSgBuf;
     219
     220    PRTSGBUF pSgPhysIn = (PRTSGBUF)RTMemAllocZ(sizeof(RTSGBUF));
     221    AssertReturn(pSgPhysIn, VERR_NO_MEMORY);
     222
     223    RTSgBufInit(pSgPhysIn, (PCRTSGSEG)paSegsIn, cSegsIn);
     224
     225    void *pSgVirtOut = RTMemAlloc(cbOut);
     226    AssertReturn(pSgVirtOut, VERR_NO_MEMORY);
     227
     228    if (cSegsOut)
     229    {
     230        RTSGBUF outSgPhys;
     231        RTSgBufInit(&outSgPhys, (PCRTSGSEG)paSegsOut, cSegsOut);
     232        virtioSgPhysToVirt((PVIRTIOSTATE)hVirtio, &outSgPhys, pSgVirtOut, cbOut);
     233        RTMemFree(paSegsOut);
     234    }
     235
     236    PVIRTIO_DESC_CHAIN_T pDescChain = (PVIRTIO_DESC_CHAIN_T)RTMemAllocZ(sizeof(VIRTIO_DESC_CHAIN_T));
     237    AssertReturn(pDescChain, VERR_NO_MEMORY);
     238
     239    pDescChain->uHeadIdx   = uHeadIdx;
     240    pDescChain->cbVirtSrc  = cbOut;
     241    pDescChain->pVirtSrc   = pSgVirtOut;
     242    pDescChain->cbPhysDst  = cbIn;
     243    pDescChain->pSgPhysDst = pSgPhysIn;
     244    *ppDescChain = pDescChain;
    206245
    207246    Log6Func(("%s -- segs OUT: %u (%u bytes)   IN: %u (%u bytes) --\n",
    208               pVirtqProxy->szVirtqName, pDescChain->cSegsOut, cbOut, pDescChain->cSegsIn, cbIn));
     247              pVirtq->szVirtqName, cSegsOut, cbOut, cSegsIn, cbIn));
    209248
    210249    return VINF_SUCCESS;
     
    212251
    213252 /** See API comments in header file prototype for description */
    214 int virtioQueuePut(VIRTIOHANDLE hVirtio, uint16_t qIdx, PRTSGBUF pSgBuf, bool fFence)
    215 {
    216 
    217     Assert(qIdx < sizeof(VIRTQ_PROXY_T));
     253int virtioQueuePut(VIRTIOHANDLE hVirtio, uint16_t qIdx, PRTSGBUF pSgVirtReturn,
     254                   PVIRTIO_DESC_CHAIN_T pDescChain, bool fFence)
     255{
     256    Assert(qIdx < VIRTQ_MAX_CNT);
    218257
    219258    PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio;
    220     PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];
    221     PVIRTQ_DESC_CHAIN_T pDescChain = pVirtqProxy->pDescChain;
     259    PVIRTQSTATE  pVirtq = &pVirtio->virtqState[qIdx];
     260    PRTSGBUF pSgPhysReturn = pDescChain->pSgPhysDst;
    222261
    223262    AssertMsgReturn(DRIVER_OK(pVirtio) /*&& pVirtio->uQueueEnable[qIdx]*/,
    224263                    ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
    225     /**
    226      * Copy caller's virtual memory sg buffer to physical memory
    227      */
    228     PRTSGBUF pBufSrc = pSgBuf;
    229     PRTSGBUF pBufDst = &pVirtqProxy->inSgBuf;
    230 
    231     size_t cbRemain = RTSgBufCalcTotalLength(pBufSrc);
     264
    232265    uint16_t uUsedIdx = virtioReadUsedRingIdx(pVirtio, qIdx);
    233266    Log6Func(("Copying client data to %s, desc chain (head desc_idx %d)\n",
    234267               QUEUENAME(qIdx), uUsedIdx));
    235268
     269    /*
     270     * Copy virtual memory s/g buffer containing data to return to the guest
     271     * to phys. memory described by (IN direction ) s/g buffer of the descriptor chain
     272     * original pulled from the queue, to 'send back' to the guest driver.
     273     */
     274    size_t cbRemain = RTSgBufCalcTotalLength(pSgVirtReturn);
     275    size_t cbCopy = 0;
    236276    while (cbRemain)
    237277    {
    238         uint64_t dstSgStart = (uint64_t)pBufDst->paSegs[pBufDst->idxSeg].pvSeg;
    239         uint64_t dstSgLen   = (uint64_t)pBufDst->paSegs[pBufDst->idxSeg].cbSeg;
    240         uint64_t dstSgCur   = (uint64_t)pBufDst->pvSegCur;
    241         size_t cbCopy = RT_MIN(pBufSrc->cbSegLeft, dstSgLen - (dstSgCur - dstSgStart));
     278        PCRTSGSEG paSeg = &pSgPhysReturn->paSegs[pSgPhysReturn->idxSeg];
     279        uint64_t dstSgStart = (uint64_t)paSeg->pvSeg;
     280        uint64_t dstSgLen   = (uint64_t)paSeg->cbSeg;
     281        uint64_t dstSgCur   = (uint64_t)pSgPhysReturn->pvSegCur;
     282        cbCopy = RT_MIN(pSgVirtReturn->cbSegLeft, dstSgLen - (dstSgCur - dstSgStart));
    242283        PDMDevHlpPhysWrite(pVirtio->CTX_SUFF(pDevIns),
    243                           (RTGCPHYS)pBufDst->pvSegCur, pBufSrc->pvSegCur, cbCopy);
    244         RTSgBufAdvance(pBufSrc, cbCopy);
    245         RTSgBufAdvance(pBufDst, cbCopy);
     284                          (RTGCPHYS)pSgPhysReturn->pvSegCur, pSgVirtReturn->pvSegCur, cbCopy);
     285        RTSgBufAdvance(pSgVirtReturn, cbCopy);
     286        RTSgBufAdvance(pSgPhysReturn, cbCopy);
    246287        cbRemain -= cbCopy;
    247288    }
     289
    248290
    249291    if (fFence)
     
    252294    /** If this write-ahead crosses threshold where the driver wants to get an event flag it */
    253295    if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX)
    254         if (pVirtqProxy->uUsedIdx == virtioReadAvailUsedEvent(pVirtio, qIdx))
    255             pVirtqProxy->fEventThresholdReached = true;
     296        if (pVirtq->uUsedIdx == virtioReadAvailUsedEvent(pVirtio, qIdx))
     297            pVirtq->fEventThresholdReached = true;
    256298
    257299    /**
    258300     * Place used buffer's descriptor in used ring but don't update used ring's slot index.
    259301     * That will be done with a subsequent client call to virtioQueueSync() */
    260     virtioWriteUsedElem(pVirtio, qIdx,
    261                         pVirtqProxy->uUsedIdx++,
    262                         pDescChain->uHeadIdx,
    263                         pDescChain->cSegsIn);
     302    virtioWriteUsedElem(pVirtio, qIdx, pVirtq->uUsedIdx++, pDescChain->uHeadIdx, cbCopy);
     303
    264304
    265305    if (LogIs2Enabled())
    266306    {
    267         size_t cbInSgBuf = RTSgBufCalcTotalLength(pBufDst);
    268         size_t cbWritten = cbInSgBuf - RTSgBufCalcLengthLeft(pBufDst);
    269307        Log2Func((".... Copied %u bytes to %u byte buffer, residual=%d\n",
    270              cbWritten, cbInSgBuf, cbInSgBuf - cbWritten));
     308             cbCopy, pDescChain->cbPhysDst, pDescChain->cbPhysDst - cbCopy));
    271309    }
    272310    Log6Func(("Write ahead used_idx=%d, %s used_idx=%d\n",
    273          pVirtqProxy->uUsedIdx,  QUEUENAME(qIdx), uUsedIdx));
     311         pVirtq->uUsedIdx,  QUEUENAME(qIdx), uUsedIdx));
     312
     313    RTMemFree((void *)pSgPhysReturn->paSegs);
     314    RTMemFree(pSgPhysReturn);
     315    RTMemFree(pDescChain);
    274316
    275317    return VINF_SUCCESS;
     
    281323int virtioQueueSync(VIRTIOHANDLE hVirtio, uint16_t qIdx)
    282324{
    283     Assert(qIdx < sizeof(VIRTQ_PROXY_T));
     325    Assert(qIdx < sizeof(VIRTQSTATE));
    284326
    285327    PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio;
    286     PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];
     328    PVIRTQSTATE pVirtq = &pVirtio->virtqState[qIdx];
    287329
    288330    AssertMsgReturn(DRIVER_OK(pVirtio) && pVirtio->uQueueEnable[qIdx],
     
    291333    uint16_t uIdx = virtioReadUsedRingIdx(pVirtio, qIdx);
    292334    Log6Func(("Updating %s used_idx from %u to %u\n",
    293               QUEUENAME(qIdx), uIdx, pVirtqProxy->uUsedIdx));
    294 
    295     virtioWriteUsedRingIdx(pVirtio, qIdx, pVirtqProxy->uUsedIdx);
     335              QUEUENAME(qIdx), uIdx, pVirtq->uUsedIdx));
     336
     337    virtioWriteUsedRingIdx(pVirtio, qIdx, pVirtq->uUsedIdx);
    296338    virtioNotifyGuestDriver(pVirtio, qIdx, false);
    297339
     
    306348    Assert(uNotifyIdx == qIdx);
    307349
    308     PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];
    309     Log6Func(("%s\n", pVirtqProxy->szVirtqName));
     350    PVIRTQSTATE pVirtq = &pVirtio->virtqState[qIdx];
     351    Log6Func(("%s\n", pVirtq->szVirtqName));
    310352
    311353    /** Inform client */
     
    337379static void virtioNotifyGuestDriver(PVIRTIOSTATE pVirtio, uint16_t qIdx, bool fForce)
    338380{
    339     PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];
     381    PVIRTQSTATE pVirtq = &pVirtio->virtqState[qIdx];
    340382
    341383    AssertMsgReturnVoid(DRIVER_OK(pVirtio), ("Guest driver not in ready state.\n"));
     
    345387        if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX)
    346388        {
    347             if (pVirtqProxy->fEventThresholdReached)
     389            if (pVirtq->fEventThresholdReached)
    348390            {
    349391                virtioRaiseInterrupt(pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, fForce);
    350                 pVirtqProxy->fEventThresholdReached = false;
     392                pVirtq->fEventThresholdReached = false;
    351393                return;
    352394            }
     
    434476static void virtioResetQueue(PVIRTIOSTATE pVirtio, uint16_t qIdx)
    435477{
    436     PVIRTQ_PROXY_T pVirtQ = &pVirtio->virtqProxy[qIdx];
     478    PVIRTQSTATE pVirtQ = &pVirtio->virtqState[qIdx];
    437479    pVirtQ->uAvailIdx = 0;
    438480    pVirtQ->uUsedIdx  = 0;
     
    832874    Assert(cb >= 32);
    833875
    834     if (iRegion == VIRTIOSCSI_REGION_PCI_CAP)
     876    if (iRegion == VIRTIO_REGION_PCI_CAP)
    835877    {
    836878        /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
     
    885927        uint8_t  uBar    = pVirtio->pPciCfgCap->pciCap.uBar;
    886928        uint32_t pv = 0;
    887         if (uBar == VIRTIOSCSI_REGION_PCI_CAP)
     929        if (uBar == VIRTIO_REGION_PCI_CAP)
    888930            (void)virtioR3MmioRead(pDevIns, NULL, (RTGCPHYS)((uint32_t)pVirtio->pGcPhysPciCapBase + uOffset),
    889931                                    &pv, uLength);
     
    929971        uint32_t uOffset = pVirtio->pPciCfgCap->pciCap.uOffset;
    930972        uint8_t  uBar    = pVirtio->pPciCfgCap->pciCap.uBar;
    931         if (uBar == VIRTIOSCSI_REGION_PCI_CAP)
     973        if (uBar == VIRTIO_REGION_PCI_CAP)
    932974            (void)virtioR3MmioWrite(pDevIns, NULL, (RTGCPHYS)((uint32_t)pVirtio->pGcPhysPciCapBase + uOffset),
    933975                                    (void *)&u32Value, uLength);
     
    11171159    pCfg->uCapLen  = sizeof(VIRTIO_PCI_CAP_T);
    11181160    pCfg->uCapNext = CFGADDR2IDX(pCfg) + pCfg->uCapLen;
    1119     pCfg->uBar     = VIRTIOSCSI_REGION_PCI_CAP;
     1161    pCfg->uBar     = VIRTIO_REGION_PCI_CAP;
    11201162    pCfg->uOffset  = RT_ALIGN_32(0, 4); /* reminder, in case someone changes offset */
    11211163    pCfg->uLength  = sizeof(VIRTIO_PCI_COMMON_CFG_T);
     
    11321174    pCfg->uCapLen  = sizeof(VIRTIO_PCI_NOTIFY_CAP_T);
    11331175    pCfg->uCapNext = CFGADDR2IDX(pCfg) + pCfg->uCapLen;
    1134     pCfg->uBar     = VIRTIOSCSI_REGION_PCI_CAP;
     1176    pCfg->uBar     = VIRTIO_REGION_PCI_CAP;
    11351177    pCfg->uOffset  = pVirtio->pCommonCfgCap->uOffset + pVirtio->pCommonCfgCap->uLength;
    11361178    pCfg->uOffset  = RT_ALIGN_32(pCfg->uOffset, 2);
     
    11511193    pCfg->uCapLen  = sizeof(VIRTIO_PCI_CAP_T);
    11521194    pCfg->uCapNext = CFGADDR2IDX(pCfg) + pCfg->uCapLen;
    1153     pCfg->uBar     = VIRTIOSCSI_REGION_PCI_CAP;
     1195    pCfg->uBar     = VIRTIO_REGION_PCI_CAP;
    11541196    pCfg->uOffset  = pVirtio->pNotifyCap->pciCap.uOffset + pVirtio->pNotifyCap->pciCap.uLength;
    11551197    pCfg->uLength  = sizeof(uint8_t);
     
    11841226        pCfg->uCapLen  = sizeof(VIRTIO_PCI_CAP_T);
    11851227        pCfg->uCapNext = fMsiSupport ? CFGADDR2IDX(pCfg) + pCfg->uCapLen : 0;
    1186         pCfg->uBar     = VIRTIOSCSI_REGION_PCI_CAP;
     1228        pCfg->uBar     = VIRTIO_REGION_PCI_CAP;
    11871229        pCfg->uOffset  = pVirtio->pIsrCap->uOffset + pVirtio->pIsrCap->uLength;
    11881230        pCfg->uOffset  = RT_ALIGN_32(pCfg->uOffset, 4);
     
    12141256     *  out size, so pad with an extra page */
    12151257
    1216     rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIOSCSI_REGION_PCI_CAP,  RT_ALIGN_32(cbRegion + 0x1000, 0x1000),
     1258    rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIO_REGION_PCI_CAP,  RT_ALIGN_32(cbRegion + 0x1000, 0x1000),
    12171259                                      PCI_ADDRESS_SPACE_MEM, virtioR3Map);
    12181260    if (RT_FAILURE(rc))
     
    12661308    {
    12671309        Log2Func(("%s queue:\n",
    1268                   "  virtqProxy[%u].uAvailIdx    = %u\n  virtqProxy[%u].uUsedIdx    = %u\n"
     1310                  "  virtqState[%u].uAvailIdx    = %u\n  virtqState[%u].uUsedIdx    = %u\n"
    12691311                  "  uQueueSize[%u]              = %u\n  uQueueNotifyOff[%u]         = %04x\n"
    12701312                  "  uQueueMsixVector[%u]        = %04x\n  uQueueEnable[%u]            = %04x\n"
    12711313                  "  pGcPhysQueueDesc[%u]        = %RGp\n  pGcPhysQueueAvail[%u]       = %RGp\n"
    12721314                  "  pGcPhysQueueUsed[%u]        = %RGp\n",
    1273                         i, pVirtio->virtqProxy[i].szVirtqName, i, pVirtio->virtqProxy[i].uAvailIdx,
    1274                         i, pVirtio->virtqProxy[i].uUsedIdx, i, pVirtio->uQueueSize[i],
     1315                        i, pVirtio->virtqState[i].szVirtqName, i, pVirtio->virtqState[i].uAvailIdx,
     1316                        i, pVirtio->virtqState[i].uUsedIdx, i, pVirtio->uQueueSize[i],
    12751317                        i, pVirtio->uQueueNotifyOff[i],i, pVirtio->uQueueMsixVector[i],
    12761318                        i, pVirtio->uQueueEnable[i], i, pVirtio->pGcPhysQueueDesc[i],
     
    13301372        rc = SSMR3PutU16(pSSM,      pVirtio->uQueueEnable[i]);
    13311373        rc = SSMR3PutU16(pSSM,      pVirtio->uQueueSize[i]);
    1332         rc = SSMR3PutU16(pSSM,      pVirtio->virtqProxy[i].uAvailIdx);
    1333         rc = SSMR3PutU16(pSSM,      pVirtio->virtqProxy[i].uUsedIdx);
    1334         rc = SSMR3PutMem(pSSM,      pVirtio->virtqProxy[i].szVirtqName, 32);
     1374        rc = SSMR3PutU16(pSSM,      pVirtio->virtqState[i].uAvailIdx);
     1375        rc = SSMR3PutU16(pSSM,      pVirtio->virtqState[i].uUsedIdx);
     1376        rc = SSMR3PutMem(pSSM,      pVirtio->virtqState[i].szVirtqName, 32);
    13351377    }
    13361378
     
    13891431            rc = SSMR3GetU16(pSSM,      &pVirtio->uQueueEnable[i]);
    13901432            rc = SSMR3GetU16(pSSM,      &pVirtio->uQueueSize[i]);
    1391             rc = SSMR3GetU16(pSSM,      &pVirtio->virtqProxy[i].uAvailIdx);
    1392             rc = SSMR3GetU16(pSSM,      &pVirtio->virtqProxy[i].uUsedIdx);
    1393             rc = SSMR3GetMem(pSSM,      (void *)&pVirtio->virtqProxy[i].szVirtqName, 32);
     1433            rc = SSMR3GetU16(pSSM,      &pVirtio->virtqState[i].uAvailIdx);
     1434            rc = SSMR3GetU16(pSSM,      &pVirtio->virtqState[i].uUsedIdx);
     1435            rc = SSMR3GetMem(pSSM,      (void *)&pVirtio->virtqState[i].szVirtqName, 32);
    13941436        }
    13951437    }
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h

    r80683 r80762  
    3838#define VIRTQ_MAX_CNT                       24                   /**< Max queues we allow guest to create      */
    3939#define VIRTIO_NOTIFY_OFFSET_MULTIPLIER     2                    /**< VirtIO Notify Cap. MMIO config param     */
    40 #define VIRTIOSCSI_REGION_MEM_IO            0                    /**< BAR for MMIO (implementation specific)   */
    41 #define VIRTIOSCSI_REGION_PORT_IO           1                    /**< BAR for PORT I/O (impl specific)         */
    42 #define VIRTIOSCSI_REGION_PCI_CAP           2                    /**< BAR for VirtIO Cap. MMIO (impl specific) */
     40#define VIRTIO_REGION_PCI_CAP               2                    /**< BAR for VirtIO Cap. MMIO (impl specific) */
    4341
    4442#define VIRTIO_HEX_DUMP(logLevel, pv, cb, base, title) \
     
    4745            virtioHexDump((pv), (cb), (base), (title)); \
    4846    } while (0)
     47
     48
     49/**
     50 * The following structure holds the pre-processed context of descriptor chain pulled from a virtio queue
     51 * to conduct a transaction between the client of this virtio implementation and the guest VM's virtio driver.
     52 * It contains the head index of the descriptor chain, the output data from the client that has been
     53 * converted to a contiguous virtual memory and a physical memory scatter-gather buffer for use by by
     54 * the virtio framework to complete the transaction in the final phase of round-trip processing.
     55 *
     56 * The client should not modify the contents of this buffer. The primary field of interest to the
     57 * client is pVirtSrc, which contains the VirtIO "OUT" (to device) buffer from the guest.
     58 *
     59 * Typical use is, When the client (worker thread) detects available data on the queue, it pulls the
     60 * next one of these descriptor chain structs off the queue using virtioQueueGet(), processes the
     61 * virtual memory buffer pVirtSrc, produces result data to pass back to the guest driver and calls
     62 * virtioQueuePut() to return the result data to the client.
     63 */
     64typedef struct VIRTIO_DESC_CHAIN
     65{
     66    uint32_t  uHeadIdx;                                    /**< Head idx of associated desc chain        */
     67    size_t    cbVirtSrc;                                   /**< Size of virt source buffer               */
     68    void     *pVirtSrc;                                    /**< Virt mem buf holding out data from guest */
     69    size_t    cbPhysDst;                                   /**< Total size of dst buffer                 */
     70    PRTSGBUF  pSgPhysDst;                                  /**< Phys S/G buf to store result for guest   */
     71} VIRTIO_DESC_CHAIN_T, *PVIRTIO_DESC_CHAIN_T, **PPVIRTIO_DESC_CHAIN_T;
    4972
    5073/**
     
    155178int virtioQueueAttach(VIRTIOHANDLE hVirtio, uint16_t qIdx, const char *pcszName);
    156179
    157 
    158 /**
    159  * Get the features VirtIO is running withnow.
    160  *
    161  * @returns Features the guest driver has accepted, finalizing the operational features
    162  *
    163  */
    164 uint64_t virtioGetNegotiatedFeatures(VIRTIOHANDLE hVirtio);
    165 
    166180/**
    167181 * Detaches from queue and release resources
     
    174188
    175189/**
    176  * Get name of queue, by qIdx, assigned at virtioQueueAttach()
    177  *
    178  * @param hVirtio   - Handle for VirtIO framework
    179  * @param qIdx      - Queue number
    180  *
    181  * @returns          Success: Returns pointer to queue name
    182  *                   Failure: Returns "<null>" (never returns NULL pointer).
    183  */
    184 const char *virtioQueueGetName(VIRTIOHANDLE hVirtio, uint16_t qIdx);
    185 
    186 /**
    187  * Removes descriptor chain from avail ring of indicated queue and converts it to
    188  * scatter/gather buffer (whose segments contain guest phys. data pointers)
    189  *
    190  * @param hVirtio   - Handle for VirtIO framework
    191  * @param qIdx      - Queue number
    192  * @param ppInSegs  - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF
    193  * @param ppOutSegs - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF
    194  *
    195  * @returns status    VINF_SUCCESS         - Success
    196  *                    VERR_INVALID_STATE   - VirtIO not in ready state
    197  */
    198 int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, bool fRemove, PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs);
    199 
    200 /**
    201  * Same as virtioQueueGet() but leaves the item on the avail ring of the queue.
    202  *
    203  * @param hVirtio   - Handle for VirtIO framework
    204  * @param qIdx      - Queue number
    205  * @param ppInSegs  - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF
    206  * @param ppOutSegs - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF
    207  *
    208  * @returns           VINF_SUCCESS         - Success
    209  *                    VERR_INVALID_STATE   - VirtIO not in ready state
    210  *                    VERR_NOT_AVAILABLE   - Queue is empty
    211  */
    212 int virtioQueuePeek(VIRTIOHANDLE hVirtio, uint16_t qIdx, PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs);
    213 
    214 /**
    215  * Writes a scatter/gather buffer (whose segments point to virtual memory) to next
    216  * available descriptor chain (consisting of segments pointing to guest phys. memory),
    217  * for the indicated virtq. The data won't be seen by the guest until the next
    218  * client call to virtioQueueSync(), which puts aforementioned descriptor
    219  * chain's head index on the indicated virtq's used ring (see VirtIO 1.0
    220  * specification, Section 2.4 "Virtqueues").
    221  *
    222  * @param hVirtio   - Handle for VirtIO framework
    223  * @param qIdx      - Queue number
    224  * @param pSgBuf    - Caller's sgbuf of one or more virtual memory segments
    225  *                    to write to the queue. This is useful because some kinds
    226  *                    of transactions involve variable length subcomponents
    227  *                    whose size can only be known near the time of writing.
    228  * @parame fFence   - If set put up copy fence (memory barrier) after
    229  *                    copying to guest phys. mem.
    230  *
    231  * @returns           VINF_SUCCESS         - Success
    232  *                    VERR_INVALID_STATE   - VirtIO not in ready state
    233  *                    VERR_NOT_AVAILABLE   - Queue is empty
    234  */
    235 int virtioQueuePut(VIRTIOHANDLE hVirtio, uint16_t qIdx, PRTSGBUF pSgBuf, bool fFence);
     190 * Removes descriptor chain from avail ring of indicated queue and converts the descriptor
     191 * chain into its OUT (to device) and IN to guest components. Additionally it converts
     192 * the OUT desc chain data to a contiguous virtual memory buffer for easy consumption
     193 * by the caller. The caller must return the descriptor chain pointer via virtioQueuePut()
     194 * and then call virtioQueueSync() at some point to return the data to the guest and
     195 * complete the transaction.
     196 *
     197 * @param hVirtio      - Handle for VirtIO framework
     198 * @param qIdx         - Queue number
     199 * @param fRemove      - flags whether to remove desc chain from queue (false = peek)
     200 * @param ppDescChain  - Address to store pointer to descriptor chain that contains the
     201 *                       pre-processed transaction information pulled from the virtq.
     202 *
     203 * @returns status     VINF_SUCCESS         - Success
     204 *                     VERR_INVALID_STATE   - VirtIO not in ready state
     205 */
     206int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove);
     207
     208
     209/**
     210 * Returns data to the guest to complete a transaction initiated by virtQueueGet().
     211 * The caller passes in a pointer to a scatter-gather buffer of virtual memory segments
     212 * and a pointer to the descriptor chain context originally derived from the pulled
     213 * queue entry, and this function will put write the virtual memory s/g buffer into the
     214 * guest's physical memory free the descriptor chain. The caller handles the freeing
     215 * (as needed) of the virtual memory buffer.
     216 *
     217 * NOTE: This does a write-ahead to the used ring of the guest's queue.
     218 *       The data written won't be seen by the guest until the next call to virtioQueueSync()
     219 *
     220 *
     221 * @param hVirtio       - Handle for VirtIO framework
     222 * @param qIdx          - Queue number
     223 *
     224 * @param pSgVirtReturn - Points toscatter-gather buffer of virtual memory segments
     225                          the caller is returning to the guest.
     226 *
     227 * @param pDescChain    - This contains the context of the scatter-gather buffer
     228 *                        originally pulled from the queue.
     229 *
     230 * @parame fFence       - If true, put up copy fence (memory barrier) after
     231 *                        copying to guest phys. mem.
     232 *
     233 * @returns              VINF_SUCCESS         - Success
     234 *                       VERR_INVALID_STATE   - VirtIO not in ready state
     235 *                       VERR_NOT_AVAILABLE   - Queue is empty
     236 */
     237
     238 int virtioQueuePut(VIRTIOHANDLE hVirtio, uint16_t qIdx, PRTSGBUF pSgVirtReturn,
     239                    PVIRTIO_DESC_CHAIN_T pDescChain, bool fFence);
     240
    236241
    237242/**
     
    297302void virtioPropagateResumeNotification(VIRTIOHANDLE hVirtio);
    298303
     304/**
     305 * Get name of queue, by qIdx, assigned at virtioQueueAttach()
     306 *
     307 * @param hVirtio   - Handle for VirtIO framework
     308 * @param qIdx      - Queue number
     309 *
     310 * @returns          Success: Returns pointer to queue name
     311 *                   Failure: Returns "<null>" (never returns NULL pointer).
     312 */
     313const char *virtioQueueGetName(VIRTIOHANDLE hVirtio, uint16_t qIdx);
     314
     315/**
     316 * Get the features VirtIO is running withnow.
     317 *
     318 * @returns Features the guest driver has accepted, finalizing the operational features
     319 *
     320 */
     321uint64_t virtioGetNegotiatedFeatures(VIRTIOHANDLE hVirtio);
    299322
    300323
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h

    r80718 r80762  
    8585
    8686/**
    87  * IN/OUT Descriptor chains descriptor chain associated with one element of virtq avail ring represented
    88  * as respective arrays of SG segments.
    89  */
    90 typedef struct VIRTQ_DESC_CHAIN                                  /**< Describes a single queue element          */
    91 {
    92     RTSGSEG     aSegsIn[VIRTQ_MAX_SIZE];                         /**< List of segments to write to guest        */
    93     RTSGSEG     aSegsOut[VIRTQ_MAX_SIZE];                        /**< List of segments read from guest          */
    94     uint32_t    uHeadIdx;                                        /**< Index at head desc (source of seg arrays) */
    95     uint32_t    cSegsIn;                                         /**< Count of segments in aSegsIn[]            */
    96     uint32_t    cSegsOut;                                        /**< Count of segments in aSegsOut[]           */
    97 } VIRTQ_DESC_CHAIN_T, *PVIRTQ_DESC_CHAIN_T;
    98 
    99 /**
    10087 * Local implementation's usage context of a queue (e.g. not part of VirtIO specification)
    10188 */
    102 typedef struct VIRTQ_PROXY
    103 {
    104     RTSGBUF     inSgBuf;                                         /**< host-to-guest buffers                     */
    105     RTSGBUF     outSgBuf;                                        /**< guest-to-host buffers                     */
     89typedef struct VIRTQSTATE
     90{
    10691    const char  szVirtqName[32];                                 /**< Dev-specific name of queue                */
    10792    uint16_t    uAvailIdx;                                       /**< Consumer's position in avail ring         */
    10893    uint16_t    uUsedIdx;                                        /**< Consumer's position in used ring          */
    10994    bool        fEventThresholdReached;                          /**< Don't lose track while queueing ahead     */
    110     PVIRTQ_DESC_CHAIN_T pDescChain;                              /**< Per-queue s/g data.                       */
    111 } VIRTQ_PROXY_T, *PVIRTQ_PROXY_T;
     95} VIRTQSTATE, *PVIRTQSTATE;
    11296
    11397/**
     
    191175    uint8_t                   uConfigGeneration;                 /**< (MMIO) Device config sequencer       HOST */
    192176
    193     VIRTQ_PROXY_T             virtqProxy[VIRTQ_MAX_CNT];         /**< Local impl-specific queue context         */
     177    VIRTQSTATE                virtqState[VIRTQ_MAX_CNT];         /**< Local impl-specific queue context         */
    194178    VIRTIOCALLBACKS           virtioCallbacks;                   /**< Callback vectors to client                */
    195179
     
    378362DECLINLINE(bool) virtqIsEmpty(PVIRTIOSTATE pVirtio, uint16_t qIdx)
    379363{
    380     return virtioReadAvailRingIdx(pVirtio, qIdx) == pVirtio->virtqProxy[qIdx].uAvailIdx;
     364    return virtioReadAvailRingIdx(pVirtio, qIdx) == pVirtio->virtqState[qIdx].uAvailIdx;
    381365}
    382366
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