VirtualBox

Changeset 81300 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Oct 17, 2019 5:51:54 AM (5 years ago)
Author:
vboxsync
Message:

Storage/DevVirtioSCSI.cpp: Improved bounds checking for MMIO functions, and tried to address Guru meditation reported by aichner in comment #9440 Comment #103 and the issues in Comment #110. See Comment #112

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

Legend:

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

    r81231 r81300  
    263263    /* Device-readable section */
    264264
    265     struct REQ_CMD_HDR  cmdHdr;
     265    struct REQ_CMD_HDR  ReqHdr;
    266266    uint8_t  uCdb[1];                                           /**< cdb                                          */
    267267
     
    550550    PVIRTIOSCSITARGET              pTarget;                  /**< Target                                            */
    551551    uint16_t                       qIdx;                     /**< Index of queue this request arrived on            */
    552     uint32_t                       cbPiOut;                  /**< Size of T10 pi in buffer                          */
    553     uint8_t                       *pbPiOut;                  /**< Address of pi out buffer                          */
    554     uint8_t                       *pbDataOut;                /**< dataout                                           */
     552    PVIRTIO_DESC_CHAIN_T           pDescChain;               /**< Prepared desc chain pulled from virtq avail ring  */
     553    uint32_t                       cbDataIn;                 /**< size of dataout buffer                            */
    555554    uint32_t                       cbDataOut;                /**< size of dataout buffer                            */
    556     uint32_t                       cbPiIn;                   /**< Size of T10 pi buffer                             */
    557     uint8_t                       *pbPiIn;                   /**< Address of pi in buffer                           */
    558     uint32_t                       cbDataIn;                 /**< Size of datain buffer                             */
    559     uint8_t                       *pbDataIn;                 /**< datain                                            */
     555    uint16_t                       uDataInOff;               /**< Fixed size of respHdr + sense (precede datain)    */
     556    uint16_t                       uDataOutOff;              /**< Fixed size of respHdr + sense (precede datain)    */
    560557    uint32_t                       cbSense;                  /**< Size of sense buffer                              */
    561558    size_t                         uSenseLen;                /**< Receives # bytes written into sense buffer        */
     
    563560    PDMMEDIAEXIOREQSCSITXDIR       enmTxDir;                 /**< Receives transfer direction of I/O req            */
    564561    uint8_t                        uStatus;                  /**< SCSI status code                                  */
    565     PVIRTIO_DESC_CHAIN_T           pDescChain;               /**< Prepared desc chain pulled from virtq avail ring  */
    566562} VIRTIOSCSIREQ;
    567563
     
    687683}
    688684#endif
    689 
    690 /**
    691  * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf}
    692  */
    693 static DECLCALLBACK(int) virtioScsiIoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
    694                                                       void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, size_t cbCopy)
    695 {
    696     RT_NOREF2(hIoReq, pInterface);
    697     PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
    698 
    699     AssertReturn(pReq->pbDataIn
    700                  && offDst + cbCopy <= pReq->cbDataIn
    701                  && cbCopy <= pSgBuf->cbSegLeft,  VERR_INVALID_PARAMETER);
    702 
    703     RTSgBufCopyToBuf(pSgBuf, pReq->pbDataIn + offDst, cbCopy);
    704 
    705     return VINF_SUCCESS;
    706 }
    707 
    708 /**
    709  * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf}
    710  */
    711 static DECLCALLBACK(int) virtioScsiIoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
    712                                                     void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, size_t cbCopy)
    713 {
    714     RT_NOREF2(hIoReq, pInterface);
    715     PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
    716 
    717     AssertReturn(pReq->pbDataOut
    718                  && offSrc + cbCopy <= pReq->cbDataOut
    719                  && cbCopy <= pSgBuf->cbSegLeft,  VERR_INVALID_PARAMETER);
    720 
    721     RTSgBufCopyFromBuf(pSgBuf, pReq->pbDataOut + offSrc, cbCopy);
    722 
    723     return VINF_SUCCESS;
    724 }
    725685
    726686static int virtioScsiSendEvent(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uEventType, uint32_t uReason)
     
    798758{
    799759    RTMemFree(pReq->pbSense);
    800     RTMemFree(pReq->pbPiIn);
    801     RTMemFree(pReq->pbDataIn);
    802760    pTarget->pDrvMediaEx->pfnIoReqFree(pTarget->pDrvMediaEx, pReq->hIoReq);
    803761}
     
    876834    AssertRC(rc);
    877835
     836    /* Masking used to deal with datatype size differences between APIs */
    878837    Assert(!(cbXfer & 0xffffffff00000000));
    879838    uint32_t cbXfer32 = cbXfer & 0xffffffff;
    880 
    881839    struct REQ_RESP_HDR respHdr = { 0 };
    882840    respHdr.uSenseLen = pReq->pbSense[2] == SCSI_SENSE_NONE ? 0 : (uint32_t)pReq->uSenseLen;
     
    972930    {
    973931        LogFunc(("cbDataIn = %u, cbDataOut = %u (cbIn = %u, cbOut = %u)\n",
    974                   pReq->cbDataIn, pReq->cbDataOut, pReq->pDescChain->cbPhysDst, pReq->pDescChain->cbVirtSrc));
     932                  pReq->cbDataIn, pReq->cbDataOut, pReq->pDescChain->cbPhysReturn, pReq->pDescChain->cbPhysSend));
    975933        LogFunc(("xfer = %lu, residual = %u\n", cbXfer, cbResidual));
    976934        const char *pszTxDirText = virtioGetTxDirText(pReq->enmTxDir);
     
    984942        LogFunc(("Sense: %s\n", SCSISenseText(pReq->pbSense[2])));
    985943        LogFunc(("Sense Ext3: %s\n", SCSISenseExtText(pReq->pbSense[12], pReq->pbSense[13])));
    986     }
    987 
    988     if (LogIs12Enabled())
    989     {
    990         uint32_t cb = RT_MIN(cbXfer32, 256);
    991         if (VIRTIO_IN_DIRECTION(pReq->enmTxDir))
    992         {
    993             if (!isBufZero(pReq->pbDataIn, cb))
    994             {
    995                 Log(("datain[showing the first %d of %d total bytes xferred]:\n", cb, cbXfer32));
    996                 VIRTIO_HEX_DUMP(RTLOGGRPFLAGS_LEVEL_12, pReq->pbDataIn,  cb,  0, 0);
    997             }
    998             else
    999                 Log12Func(("First %d bytes transfered in this req are 0 --\n", cb));
    1000         }
    1001         else
    1002         if (VIRTIO_OUT_DIRECTION(pReq->enmTxDir))
    1003         {
    1004             if (!isBufZero(pReq->pbDataOut, cb))
    1005             {
    1006                 Log(("dataout[showing the first %d of %d total bytes xferred]:\n", cb, cbXfer32));
    1007                 VIRTIO_HEX_DUMP(RTLOGGRPFLAGS_LEVEL_12, pReq->pbDataOut, cb, 0, 0);
    1008             }
    1009             else
    1010                 Log12Func(("First %d bytes transfered in this req are 0 --\n", cb));
    1011         }
    1012944    }
    1013945
     
    1032964        Assert(pReq->pbSense != NULL);
    1033965
     966        /* req datain bytes already in guest phys mem. via virtioScsiIoReqCopyFromBuf() */
     967
    1034968        RTSGSEG aReqSegs[4];
    1035969        aReqSegs[cSegs].pvSeg = &respHdr;
     
    1039973        aReqSegs[cSegs++].cbSeg = pReq->cbSense; /* VirtIO 1.0 spec 5.6.4/5.6.6.1 */
    1040974
    1041         if (pReq->cbPiIn)
    1042         {
    1043             aReqSegs[cSegs].pvSeg = pReq->pbPiIn;
    1044             aReqSegs[cSegs++].cbSeg = pReq->cbPiIn;
    1045         }
    1046         if (pReq->cbDataIn)
    1047         {
    1048             aReqSegs[cSegs].pvSeg = pReq->pbDataIn;
    1049             aReqSegs[cSegs++].cbSeg = cbXfer;
    1050         }
    1051975        RTSGBUF reqSegBuf;
    1052976        RTSgBufInit(&reqSegBuf, aReqSegs, cSegs);
    1053977
    1054978        size_t cbReqSgBuf = RTSgBufCalcTotalLength(&reqSegBuf);
    1055         AssertMsgReturn(cbReqSgBuf <= pReq->pDescChain->cbPhysDst,
     979        AssertMsgReturn(cbReqSgBuf <= pReq->pDescChain->cbPhysReturn,
    1056980                       ("Guest expected less req data (space needed: %d, avail: %d)\n",
    1057                          cbReqSgBuf, pReq->pDescChain->cbPhysDst),
     981                         cbReqSgBuf, pReq->pDescChain->cbPhysReturn),
    1058982                       VERR_BUFFER_OVERFLOW);
     983
    1059984
    1060985        virtioQueuePut(pThis->hVirtio, pReq->qIdx, &reqSegBuf, pReq->pDescChain, true /* fFence TBD */);
     
    1073998}
    1074999
     1000/**
     1001 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf}
     1002 *
     1003 * Copy virtual memory from VSCSI layer to guest physical memory
     1004 */
     1005static DECLCALLBACK(int) virtioScsiIoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     1006                                                      void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, size_t cbCopy)
     1007{
     1008    RT_NOREF(hIoReq, cbCopy);
     1009    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
     1010    PVIRTIOSCSI pThis = pTarget->pVirtioScsi;
     1011    PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
     1012
     1013    AssertReturn(pReq->pDescChain, VERR_INVALID_PARAMETER);
     1014
     1015    if (!pReq->cbDataIn)
     1016        return VINF_SUCCESS;
     1017
     1018    PRTSGBUF pSgPhysReturn = pReq->pDescChain->pSgPhysReturn;
     1019    RTSgBufAdvance(pSgPhysReturn, offDst);
     1020
     1021    size_t cbCopied = 0;
     1022    size_t cbRemain = pReq->cbDataIn;
     1023
     1024    if (!pSgPhysReturn->idxSeg && pSgPhysReturn->cbSegLeft == pSgPhysReturn->paSegs[0].cbSeg)
     1025    {
     1026        Log(("Do advance\n"));
     1027        RTSgBufAdvance(pSgPhysReturn, pReq->uDataInOff);
     1028    }
     1029
     1030    while (cbRemain)
     1031    {
     1032        PCRTSGSEG paSeg = &pSgPhysReturn->paSegs[pSgPhysReturn->idxSeg];
     1033        uint64_t dstSgStart = (uint64_t)paSeg->pvSeg;
     1034        uint64_t dstSgLen   = (uint64_t)paSeg->cbSeg;
     1035        uint64_t dstSgCur   = (uint64_t)pSgPhysReturn->pvSegCur;
     1036        cbCopied = RT_MIN((uint64_t)pSgBuf->cbSegLeft, dstSgLen - (dstSgCur - dstSgStart));
     1037        PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns),
     1038                          (RTGCPHYS)pSgPhysReturn->pvSegCur, pSgBuf->pvSegCur, cbCopied);
     1039        RTSgBufAdvance(pSgBuf, cbCopied);
     1040        RTSgBufAdvance(pSgPhysReturn, cbCopied);
     1041        cbRemain -= cbCopied;
     1042    }
     1043    RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); /* needed? */
     1044
     1045    Log2Func((".... Copied %lu bytes from %lu byte guest buffer, residual=%lu\n",
     1046         cbCopy, pReq->pDescChain->cbPhysReturn, pReq->pDescChain->cbPhysReturn - cbCopy));
     1047
     1048    return VINF_SUCCESS;
     1049}
     1050
     1051/**
     1052 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf}
     1053 *
     1054 * Copy guest physical memory to VSCSI layer virtual memory
     1055 */
     1056static DECLCALLBACK(int) virtioScsiIoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     1057                                                    void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, size_t cbCopy)
     1058{
     1059
     1060    RT_NOREF(hIoReq, cbCopy);
     1061    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
     1062    PVIRTIOSCSI pThis = pTarget->pVirtioScsi;
     1063    PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
     1064
     1065    if (!pReq->cbDataOut)
     1066        return VINF_SUCCESS;
     1067
     1068    PRTSGBUF pSgPhysSend = pReq->pDescChain->pSgPhysSend;
     1069    RTSgBufAdvance(pSgPhysSend, offSrc);
     1070
     1071    size_t cbCopied = 0;
     1072    size_t cbRemain = pReq->cbDataOut;
     1073    while (cbRemain)
     1074    {
     1075        PCRTSGSEG paSeg     = &pSgPhysSend->paSegs[pSgPhysSend->idxSeg];
     1076        uint64_t srcSgStart = (uint64_t)paSeg->pvSeg;
     1077        uint64_t srcSgLen   = (uint64_t)paSeg->cbSeg;
     1078        uint64_t srcSgCur   = (uint64_t)pSgPhysSend->pvSegCur;
     1079        cbCopied = RT_MIN((uint64_t)pSgBuf->cbSegLeft, srcSgLen - (srcSgCur - srcSgStart));
     1080        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
     1081                          (RTGCPHYS)pSgPhysSend->pvSegCur, pSgBuf->pvSegCur, cbCopied);
     1082        RTSgBufAdvance(pSgBuf, cbCopied);
     1083        RTSgBufAdvance(pSgPhysSend, cbCopied);
     1084        cbRemain -= cbCopied;
     1085    }
     1086
     1087    Log2Func((".... Copied %lu bytes to %lu byte guest buffer, residual=%lu\n",
     1088         cbCopy, pReq->pDescChain->cbPhysReturn, pReq->pDescChain->cbPhysReturn - cbCopy));
     1089
     1090    return VINF_SUCCESS;
     1091}
     1092
    10751093static int virtioScsiReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain)
    10761094{
     1095    AssertReturn(pDescChain->cbPhysSend, VERR_INVALID_PARAMETER);
     1096
    10771097    ASMAtomicIncU32(&pThis->cActiveReqs);
    10781098
    1079     PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)pDescChain->pVirtSrc;
    1080 
    1081     uint8_t  uTarget  = pVirtqReq->cmdHdr.uVirtioLun[1];
    1082     uint32_t uScsiLun = (pVirtqReq->cmdHdr.uVirtioLun[2] << 8 | pVirtqReq->cmdHdr.uVirtioLun[3]) & 0x3fff;
     1099    /* Extract command header and CDB from guest physical memory */
     1100
     1101    uint16_t cbReqHdr = sizeof(struct REQ_CMD_HDR) + pThis->virtioScsiConfig.uCdbSize;
     1102    PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)RTMemAlloc(cbReqHdr);
     1103    AssertReturn(pVirtqReq, VERR_NO_MEMORY);
     1104    uint8_t *pb = (uint8_t *)pVirtqReq;
     1105    for (size_t cb = RT_MIN(pDescChain->cbPhysSend, cbReqHdr); cb; )
     1106    {
     1107        size_t cbSeg = cb;
     1108        RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg);
     1109        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pb, cbSeg);
     1110        pb += cbSeg;
     1111        cb -= cbSeg;
     1112    }
     1113
     1114    uint8_t  uTarget  = pVirtqReq->ReqHdr.uVirtioLun[1];
     1115    uint32_t uScsiLun = (pVirtqReq->ReqHdr.uVirtioLun[2] << 8 | pVirtqReq->ReqHdr.uVirtioLun[3]) & 0x3fff;
    10831116    PVIRTIOSCSITARGET pTarget = &pThis->paTargetInstances[uTarget];
    10841117
     
    10881121        pThis->virtioScsiConfig.uCdbSize), pVirtqReq->uCdb));
    10891122
    1090     Log3Func(("id: %RX64, attr: %x, prio: %d, crn: %x\n",
    1091         pVirtqReq->cmdHdr.uId, pVirtqReq->cmdHdr.uTaskAttr, pVirtqReq->cmdHdr.uPrio, pVirtqReq->cmdHdr.uCrn));
     1123    Log3Func(("cmd id: %RX64, attr: %x, prio: %d, crn: %x\n",
     1124        pVirtqReq->ReqHdr.uId, pVirtqReq->ReqHdr.uTaskAttr, pVirtqReq->ReqHdr.uPrio, pVirtqReq->ReqHdr.uCrn));
    10921125
    10931126    /*
    10941127     * Calculate request offsets
    10951128     */
    1096     uint32_t  cbPiIn = 0, cbPiOut = 0, cbPiHdr = 0;
    1097     off_t   piOutOff = 0;
    1098 
    1099     if (pThis->fHasT10pi)
    1100     {
    1101         cbPiIn   = pVirtqReq->piHdr.uPiBytesOut;
    1102         cbPiOut  = pVirtqReq->piHdr.uPiBytesIn;
    1103         cbPiHdr  = sizeof(REQ_CMD_PI) + cbPiOut;
    1104         piOutOff = sizeof(REQ_CMD_HDR) + pThis->virtioScsiConfig.uCdbSize + sizeof(REQ_CMD_PI);
    1105     }
    1106 
    1107     off_t   uDataOutOff = sizeof(REQ_CMD_HDR)  + pThis->virtioScsiConfig.uCdbSize + cbPiHdr;
    1108     off_t   uDataInOff  = sizeof(REQ_RESP_HDR) + pThis->virtioScsiConfig.uSenseSize + cbPiIn;
    1109     uint8_t *pbDataOut = (uint8_t *)((uint64_t)pVirtqReq + uDataOutOff);
    1110     uint32_t  cbDataOut = pDescChain->cbVirtSrc - uDataOutOff;
    1111     uint32_t  cbDataIn  = pDescChain->cbPhysDst - uDataInOff;
    1112 
     1129    off_t uDataOutOff = sizeof(REQ_CMD_HDR)  + pThis->virtioScsiConfig.uCdbSize;
     1130    off_t uDataInOff  = sizeof(REQ_RESP_HDR) + pThis->virtioScsiConfig.uSenseSize;
     1131    uint32_t cbDataOut = pDescChain->cbPhysSend - uDataOutOff;
     1132    uint32_t cbDataIn  = pDescChain->cbPhysReturn - uDataInOff;
    11131133    /**
    11141134     * Handle submission errors
     
    11721192     * Have underlying driver allocate a req of size set during initialization of this device.
    11731193     */
    1174     PDMMEDIAEXIOREQ   hIoReq = NULL;
    1175     PVIRTIOSCSIREQ    pReq;
    1176     PPDMIMEDIAEX      pIMediaEx = pTarget->pDrvMediaEx;
     1194    PDMMEDIAEXIOREQ hIoReq = NULL;
     1195    PVIRTIOSCSIREQ  pReq;
     1196    PPDMIMEDIAEX    pIMediaEx = pTarget->pDrvMediaEx;
    11771197
    11781198    int rc = pIMediaEx->pfnIoReqAlloc(pIMediaEx, &hIoReq, (void **)&pReq, 0 /* uIoReqId */,
     
    11811201    AssertMsgRCReturn(rc, ("Failed to allocate I/O request, rc=%Rrc\n", rc), rc);
    11821202
    1183     /*
    1184      * Prepare req's parameters for submission
    1185      */
    1186     if (pThis->fHasT10pi)
    1187     {
    1188         pReq->cbPiOut   = cbPiOut;
    1189         pReq->pbPiOut   = (uint8_t *)((uint64_t)pVirtqReq + piOutOff);
    1190         pReq->cbPiIn    = cbPiIn;
    1191         pReq->pbPiIn    = (uint8_t *)RTMemAlloc(cbPiIn);
    1192         AssertMsgReturn(pReq->pbPiIn, ("Out of memory allocating pi_in buffer"),  VERR_NO_MEMORY);
    1193     }
    1194 
    1195     pReq->hIoReq     = hIoReq;
    1196     pReq->pTarget    = pTarget;
    1197     pReq->qIdx       = qIdx;
    1198     pReq->cbDataOut  = cbDataOut;
    1199     pReq->pbDataOut  = cbDataOut ? pbDataOut : 0;
    1200     pReq->pDescChain = pDescChain;
    1201     pReq->cbSense    = pThis->virtioScsiConfig.uSenseSize;
    1202     pReq->pbSense    = (uint8_t *)RTMemAlloc(pReq->cbSense);
     1203    pReq->hIoReq      = hIoReq;
     1204    pReq->pTarget     = pTarget;
     1205    pReq->qIdx        = qIdx;
     1206    pReq->cbDataIn    = cbDataIn;
     1207    pReq->cbDataOut   = cbDataOut;
     1208    pReq->pDescChain  = pDescChain;
     1209    pReq->uDataInOff  = uDataInOff;
     1210    pReq->uDataOutOff = uDataOutOff;
     1211
     1212    pReq->cbSense = pThis->virtioScsiConfig.uSenseSize;
     1213    pReq->pbSense = (uint8_t *)RTMemAlloc(pReq->cbSense);
    12031214    AssertMsgReturn(pReq->pbSense,  ("Out of memory allocating sense buffer"),  VERR_NO_MEMORY);
    12041215
    1205     if (cbDataIn)
    1206     {
    1207         pReq->cbDataIn  = cbDataIn;
    1208         pReq->pbDataIn  = (uint8_t *)RTMemAlloc(cbDataIn);
    1209         AssertMsgReturn(pReq->pbDataIn, ("Out of memory allocating datain buffer"), VERR_NO_MEMORY);
    1210     }
    1211 
     1216    /* Note: DrvSCSI allocates one virtual memory buffer for input and output phases of the request */
    12121217    rc = pIMediaEx->pfnIoReqSendScsiCmd(pIMediaEx, pReq->hIoReq, uScsiLun,
    12131218                                        pVirtqReq->uCdb, (size_t)pThis->virtioScsiConfig.uCdbSize,
     
    12561261    uint8_t  uResponse = VIRTIOSCSI_S_OK;
    12571262
    1258     PVIRTIOSCSI_CTRL_T pScsiCtrl = (PVIRTIOSCSI_CTRL_T)pDescChain->pVirtSrc;
     1263    PVIRTIOSCSI_CTRL_T pScsiCtrl = (PVIRTIOSCSI_CTRL_T)RTMemAlloc(sizeof(PVIRTIOSCSI_CTRL_T));
     1264
     1265    uint8_t *pb = (uint8_t *)pScsiCtrl;
     1266    for (size_t cb = RT_MIN(pDescChain->cbPhysSend, sizeof(PVIRTIOSCSI_CTRL_T)); cb; )
     1267    {
     1268        size_t cbSeg = cb;
     1269        RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg);
     1270        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pb, cbSeg);
     1271        pb += cbSeg;
     1272        cb -= cbSeg;
     1273    }
    12591274
    12601275    /*
     
    19001915                                    const void *pv, uint32_t cb, bool fWrite)
    19011916{
    1902     int rc = VINF_SUCCESS;
     1917
     1918    AssertReturn(!pv || cb >= sizeof(uint32_t), fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00);
     1919
    19031920    if (MATCH_SCSI_CONFIG(uNumQueues))
    19041921        SCSI_CONFIG_ACCESSOR_READONLY(uNumQueues);
     
    19331950    {
    19341951        LogFunc(("Bad access by guest to virtio_scsi_config: uoff=%d, cb=%d\n", uOffset, cb));
    1935         rc = VERR_ACCESS_DENIED;
    1936     }
    1937     return rc;
     1952        return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00;
     1953    }
     1954    return VINF_SUCCESS;
    19381955}
    19391956
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r81231 r81300  
    188188    } while (desc.fFlags & VIRTQ_DESC_F_NEXT);
    189189
    190 
    191190    PRTSGBUF pSgPhysIn = (PRTSGBUF)RTMemAllocZ(sizeof(RTSGBUF));
    192191    AssertReturn(pSgPhysIn, VERR_NO_MEMORY);
     
    194193    RTSgBufInit(pSgPhysIn, (PCRTSGSEG)paSegsIn, cSegsIn);
    195194
    196     void *pVirtOut = RTMemAlloc(cbOut);
    197     AssertReturn(pVirtOut, VERR_NO_MEMORY);
    198 
    199     /* If there's any guest → device data in phys. memory pulled
    200      * from queue, copy it into virtual memory to return to caller */
    201 
    202     if (cSegsOut)
    203     {
    204         uint8_t *outSgVirt = (uint8_t *)pVirtOut;
    205         RTSGBUF outSgPhys;
    206         RTSgBufInit(&outSgPhys, (PCRTSGSEG)paSegsOut, cSegsOut);
    207         for (size_t cb = cbOut; cb;)
    208         {
    209             size_t cbSeg = cb;
    210             RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(&outSgPhys, &cbSeg);
    211             PDMDevHlpPhysRead(((PVIRTIOSTATE)hVirtio)->CTX_SUFF(pDevIns), GCPhys, outSgVirt, cbSeg);
    212             outSgVirt = ((uint8_t *)outSgVirt) + cbSeg;
    213             cb -= cbSeg;
    214         }
    215         RTMemFree(paSegsOut);
    216     }
     195    PRTSGBUF pSgPhysOut = (PRTSGBUF)RTMemAllocZ(sizeof(RTSGBUF));
     196    AssertReturn(pSgPhysOut, VERR_NO_MEMORY);
     197
     198    RTSgBufInit(pSgPhysOut, (PCRTSGSEG)paSegsOut, cSegsOut);
    217199
    218200    PVIRTIO_DESC_CHAIN_T pDescChain = (PVIRTIO_DESC_CHAIN_T)RTMemAllocZ(sizeof(VIRTIO_DESC_CHAIN_T));
     
    220202
    221203    pDescChain->uHeadIdx   = uHeadIdx;
    222     pDescChain->cbVirtSrc  = cbOut;
    223     pDescChain->pVirtSrc   = pVirtOut;
    224     pDescChain->cbPhysDst  = cbIn;
    225     pDescChain->pSgPhysDst = pSgPhysIn;
     204    pDescChain->cbPhysSend  = cbOut;
     205    pDescChain->pSgPhysSend = pSgPhysOut;
     206    pDescChain->cbPhysReturn  = cbIn;
     207    pDescChain->pSgPhysReturn = pSgPhysIn;
    226208    *ppDescChain = pDescChain;
    227209
     
    240222    PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio;
    241223    PVIRTQSTATE  pVirtq = &pVirtio->virtqState[qIdx];
    242     PRTSGBUF pSgPhysReturn = pDescChain->pSgPhysDst;
     224    PRTSGBUF pSgPhysReturn = pDescChain->pSgPhysReturn;
     225
    243226
    244227    AssertMsgReturn(DRIVER_OK(pVirtio) /*&& pVirtio->uQueueEnable[qIdx]*/,
     
    251234
    252235    /*
    253      * Copy virtual memory s/g buffer containing data to return to the guest
    254      * to phys. memory described by (IN direction ) s/g buffer of the descriptor chain
    255      * (pulled from avail ring of queue), essentially giving result back to the guest driver.
    256      */
     236     * Copy s/g buf (virtual memory) to guest phys mem (IN direction). This virtual memory
     237     * block will be small (fixed portion of response header + sense buffer area or
     238     * control commands or error return values)... The bulk of req data xfers to phys mem
     239     * is handled by client */
     240
    257241    size_t cbCopy = 0;
    258242    size_t cbRemain = RTSgBufCalcTotalLength(pSgVirtReturn);
     243    RTSgBufReset(pSgPhysReturn); /* Reset ptr because req data may have already been written */
    259244    while (cbRemain)
    260245    {
     
    272257
    273258    if (fFence)
    274         RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
     259        RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); /* needed? */
    275260
    276261    /** If this write-ahead crosses threshold where the driver wants to get an event flag it */
     
    287272            (uint32_t)(cbCopy & 0xffffffff));
    288273
    289     Log2Func((".... Copied %ul bytes to %ul byte buffer, residual=%ul\n",
    290          cbCopy, pDescChain->cbPhysDst, pDescChain->cbPhysDst - cbCopy));
     274    Log2Func((".... Copied %lu bytes to %lu byte buffer, residual=%lu\n",
     275         cbCopy, pDescChain->cbPhysReturn, pDescChain->cbPhysReturn - cbCopy));
    291276
    292277    Log6Func(("Write ahead used_idx=%d, %s used_idx=%d\n",
     
    561546    {
    562547        if (fWrite) /* Guest WRITE pCommonCfg>uDeviceFeatures */
     548        {
    563549            LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.device_feature\n"));
     550            return VINF_SUCCESS;
     551        }
    564552        else /* Guest READ pCommonCfg->uDeviceFeatures */
    565553        {
     
    581569                    LogFunc(("Guest read uDeviceFeatures with out of range selector (%d), returning 0\n",
    582570                          pVirtio->uDeviceFeaturesSelect));
    583                     return VERR_ACCESS_DENIED;
     571                    return VINF_IOM_MMIO_UNUSED_00;
    584572            }
    585573        }
     
    604592                    LogFunc(("Guest wrote uDriverFeatures with out of range selector (%d), returning 0\n",
    605593                         pVirtio->uDriverFeaturesSelect));
    606                     return VERR_ACCESS_DENIED;
     594                    return VINF_SUCCESS;
    607595            }
    608596        }
     
    626614                    LogFunc(("Guest read uDriverFeatures with out of range selector (%d), returning 0\n",
    627615                         pVirtio->uDriverFeaturesSelect));
    628                     return VERR_ACCESS_DENIED;
     616                    return VINF_IOM_MMIO_UNUSED_00;
    629617            }
    630618        }
     
    635623        {
    636624            Log2Func(("Guest attempted to write readonly virtio_pci_common_cfg.num_queues\n"));
    637             return VERR_ACCESS_DENIED;
     625            return VINF_SUCCESS;
    638626        }
    639627        else
     
    712700        Log2Func(("Bad guest %s access to virtio_pci_common_cfg: uOffset=%d, cb=%d\n",
    713701            fWrite ? "write" : "read ", uOffset, cb));
    714         rc = VERR_ACCESS_DENIED;
     702        return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00;
    715703    }
    716704    return rc;
     
    770758    {
    771759        uint32_t uOffset = GCPhysAddr - pVirtio->pGcPhysCommonCfg;
    772         virtioCommonCfgAccessed(pVirtio, false /* fWrite */, uOffset, cb, (void const *)pv);
     760        rc = virtioCommonCfgAccessed(pVirtio, false /* fWrite */, uOffset, cb, (void const *)pv);
    773761    }
    774762    else
     
    784772                "                  pVirtio=%#p GCPhysAddr=%RGp cb=%u\n",
    785773                pVirtio, GCPhysAddr, cb));
     774        return VINF_IOM_MMIO_UNUSED_00;
    786775    }
    787776    return rc;
     
    802791    RT_NOREF(pvUser);
    803792    PVIRTIOSTATE pVirtio = *PDMINS_2_DATA(pDevIns, PVIRTIOSTATE *);
    804     int rc = VINF_SUCCESS;
    805793
    806794    MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysDeviceCap, pVirtio->pDeviceCap,     fDevSpecific);
     
    815803         * Pass this MMIO write access back to the client to handle
    816804         */
    817         rc = pVirtio->virtioCallbacks.pfnVirtioDevCapWrite(pDevIns, uOffset, pv, cb);
     805        (void)pVirtio->virtioCallbacks.pfnVirtioDevCapWrite(pDevIns, uOffset, pv, cb);
    818806    }
    819807    else
     
    821809    {
    822810        uint32_t uOffset = GCPhysAddr - pVirtio->pGcPhysCommonCfg;
    823         virtioCommonCfgAccessed(pVirtio, true /* fWrite */, uOffset, cb, pv);
     811        (void)virtioCommonCfgAccessed(pVirtio, true /* fWrite */, uOffset, cb, pv);
    824812    }
    825813    else
     
    847835                pVirtio, GCPhysAddr, pv, cb, pv, cb));
    848836    }
    849     return rc;
     837    return VINF_SUCCESS;
    850838}
    851839
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h

    r81122 r81300  
    6565typedef struct VIRTIO_DESC_CHAIN
    6666{
    67     uint32_t  uHeadIdx;                                    /**< Head idx of associated desc chain        */
    68     uint32_t  cbVirtSrc;                                   /**< Size of virt source buffer               */
    69     void     *pVirtSrc;                                    /**< Virt mem buf holding out data from guest */
    70     uint32_t  cbPhysDst;                                   /**< Total size of dst buffer                 */
    71     PRTSGBUF  pSgPhysDst;                                  /**< Phys S/G buf to store result for guest   */
     67    uint32_t  uHeadIdx;                                          /**< Head idx of associated desc chain        */
     68    uint32_t  cbPhysSend;                                        /**< Total size of src buffer                 */
     69    PRTSGBUF  pSgPhysSend;                                       /**< Phys S/G/ buf for data from guest        */
     70    uint32_t  cbPhysReturn;                                      /**< Total size of dst buffer                 */
     71    PRTSGBUF  pSgPhysReturn;                                     /**< Phys S/G buf to store result for guest   */
    7272} VIRTIO_DESC_CHAIN_T, *PVIRTIO_DESC_CHAIN_T, **PPVIRTIO_DESC_CHAIN_T;
    7373
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