VirtualBox

Changeset 80571 in vbox


Ignore:
Timestamp:
Sep 4, 2019 12:06:41 AM (5 years ago)
Author:
vboxsync
Message:

Storage/DevVirtioSCSI.cpp: Cleaned up the req submit code. Trying to chase down a problem that occurs when bringing in 1.3Mb or so worth of data from the guest into a new request allocated into virtual memory

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

Legend:

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

    r80539 r80571  
    179179struct REQ_RESP_HDR
    180180{
    181     uint32_t cbSense;                                           /**< sense_len                                    */
     181    uint32_t uSenseLen;                                         /**< sense_len                                    */
    182182    uint32_t uResidual;                                         /**< residual                                     */
    183183    uint16_t uStatusQualifier;                                  /**< status_qualifier                             */
     
    488488     out[0] = 0x01;  out[1] = target; out[2] = (lun >> 8) & 0x40;  out[3] = lun & 0xff;  *((uint16_t *)out + 4) = 0;
    489489
    490 /**
    491  * Do a hex dump of a buffer
    492  * @param   pv       Pointer to array to dump
    493  * @param   cb       Number of characters to dump
    494  * @param   uBase    Base address of offset addresses displayed
    495  * @param   pszTitle Header line/title for the dump
    496  *
    497  */
    498 void virtioScsiHexDump(uint8_t *pv, size_t cb, uint32_t uBase, const char *pszTitle)
    499 {
    500     if (pszTitle)
    501         Log2(("%s [%d bytes]:\n", pszTitle, cb));
    502     char pszAsciiRow[16 + 1] = { 0 };
    503     for (uint8_t *pbLine = pv; pbLine <= pv + cb; pbLine += 16)
    504     {
    505         for (uint8_t i = 0; i < 16; i++)
    506             pszAsciiRow[i] = pbLine[i] > 0x20 && pbLine[i] <= 0x7e ? pbLine[i] : '.';
    507         Log2(("%04x %.*Rhxs  %.*Rhxs %s\n",
    508             uBase + (pbLine - pv), 8, pbLine, 8, pbLine + 8, pszAsciiRow));
    509     }
    510     Log2(("\n"));
    511 }
    512490
    513491DECLINLINE(const char *) virtioGetTMFTypeText(uint32_t uSubType)
     
    699677
    700678    /** DrvSCSI.cpp, that issues this callback, just sticks one segment in the buffer */
    701 //    memset(pReq->pbDataIn + offDst, 0, cbCopy);
    702 LogFunc(("*** pSgBuf->cbSegLeft=%d\n", pSgBuf->cbSegLeft));
    703679    memcpy(pReq->pbDataIn + offDst, pSgBuf->paSegs[0].pvSeg, cbCopy);
    704680    return VINF_SUCCESS;
     
    805781    AssertRC(rc);
    806782
    807     /**
    808      * Linux does not want any sense code if there wasn't problem!
    809      */
    810     if (pReq->pbSense[2] == SCSI_SENSE_NONE)
    811         pReq->cbSense = 0;
    812 
    813     struct REQ_RESP_HDR respHdr;
    814     respHdr.cbSense   = pReq->cbSense;
     783    #define SHOULD_FIX_VSCSI_TO_RETURN_SENSE_LEN 32
     784    struct REQ_RESP_HDR respHdr = { 0 };
     785    respHdr.uSenseLen = pReq->uStatus == SCSI_STATUS_CHECK_CONDITION ? SHOULD_FIX_VSCSI_TO_RETURN_SENSE_LEN : 0;
    815786    respHdr.uResidual = cbResidual;
    816787    respHdr.uStatus   = pReq->uStatus;
    817788    respHdr.uResponse = rcReq;
    818     respHdr.uStatusQualifier = 0;
    819 
    820     LogFunc(("status: %s  response: %s  0x%x%x/0x%x%x  cbXfer=%d, cbResidual: %u\n",
    821                 SCSIStatusText(pReq->uStatus),  virtioGetReqRespText(respHdr.uResponse),
    822                 pReq->uStatus >> 4 & 0xf, pReq->uStatus & 0xf,
    823                 respHdr.uResponse >> 4 & 0xf, respHdr.uResponse & 0xf,
    824                 cbXfer, cbResidual));
    825 
    826     if (pReq->cbSense)
     789
     790    Log2Func(("status: %s    response: %s\n",
     791              SCSIStatusText(pReq->uStatus),  virtioGetReqRespText(respHdr.uResponse)));
     792
     793    Log3Func(("status:%02x/resp:%02x, xfer=%d, residual: %u, sense (len=%d, alloc=%d)\n",
     794              pReq->uStatus, respHdr.uResponse, cbXfer, cbResidual,
     795              respHdr.uSenseLen, pThis->virtioScsiConfig.uSenseSize));
     796
     797
     798    if (respHdr.uSenseLen && LogIs2Enabled())
    827799    {
    828800        Log2Func(("Sense: %s\n", SCSISenseText(pReq->pbSense[2])));
    829801        Log2Func(("Sense Ext3: %s\n", SCSISenseExtText(pReq->pbSense[12], pReq->pbSense[13])));
    830         virtioScsiHexDump(pReq->pbSense, pReq->cbSense, 0, "\nSense");
    831     }
    832 
     802
     803    }
     804
     805    int cSegs = 0;
     806
     807    Assert(pReq->cbDataIn >= cbXfer);
     808    Assert(pReq->pbSense != NULL);
     809
     810    RTSGSEG aReqSegs[4];
     811    aReqSegs[cSegs].pvSeg   = &respHdr;
     812    aReqSegs[cSegs++].cbSeg = sizeof(respHdr);
     813
     814    aReqSegs[cSegs].pvSeg   = pReq->pbSense;
     815    aReqSegs[cSegs++].cbSeg = pReq->cbSense; /* VirtIO 1.0 spec 5.6.4/5.6.6.1 */
     816
     817    if (pReq->cbPiIn)
     818    {
     819        aReqSegs[cSegs].pvSeg   = pReq->pbPiIn;
     820        aReqSegs[cSegs++].cbSeg = pReq->cbPiIn;
     821    }
    833822    if (pReq->cbDataIn)
    834         virtioScsiHexDump(pReq->pbDataIn, pReq->cbDataIn, 0, "\ndatain");
    835 
    836     if (pReq->cbPiIn)
    837         virtioScsiHexDump(pReq->pbPiIn, pReq->cbPiIn, 0, "\nPi in");
    838 
    839     if (cbResidual)
    840         Log(("Residual: %d\n", cbResidual));
    841 
    842     Log(("---------------------------------------------------------------------------------\n"));
    843     int cSegs = 0;
    844     RTSGSEG aReqSegs[4];
    845     aReqSegs[cSegs].pvSeg = &respHdr;
    846     aReqSegs[cSegs++].cbSeg = sizeof(respHdr);
    847     if (pReq->cbSense)
    848     {
    849         aReqSegs[cSegs].pvSeg = pReq->pbSense;
    850         aReqSegs[cSegs++].cbSeg = pReq->cbSense;
    851     }
    852     if (pReq->cbPiIn)
    853     {
    854         aReqSegs[cSegs].pvSeg = pReq->pbPiIn;
    855         aReqSegs[cSegs++].cbSeg = pReq->cbPiIn;
    856     }
    857     if (pReq->cbDataIn)
    858     {
    859         aReqSegs[cSegs].pvSeg = pReq->pbDataIn;
    860         aReqSegs[cSegs++].cbSeg = pReq->cbDataIn;
     823    {
     824        aReqSegs[cSegs].pvSeg   = pReq->pbDataIn;
     825        aReqSegs[cSegs++].cbSeg = cbXfer;
    861826    }
    862827    RTSGBUF reqSegBuf;
     
    880845    virtioQueueSync(pThis->hVirtio, pReq->qIdx);
    881846
    882     RTMemFree(pReq->pVirtqReq);
     847    Log(("-----------------------------------------------------------------------------------------\n"));
     848
    883849    RTMemFree(pReq->pbSense);
    884850    RTMemFree(pReq->pbDataIn);
    885851    RTMemFree(pReq->pbPiIn);
     852    RTMemFree(pReq->pVirtqReq);
    886853
    887854    pIMediaEx->pfnIoReqFree(pIMediaEx, pReq->hIoReq);
     
    905872static int virtioScsiReqFinish(PVIRTIOSCSI pThis, uint16_t qIdx, struct REQ_RESP_HDR *respHdr, uint8_t *pbSense)
    906873{
    907     int cSegs = 0;
     874    uint8_t *abSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize);
     875    AssertReturn(abSenseBuf, VERR_NO_MEMORY);
     876
    908877    RTSGSEG aReqSegs[2];
    909     aReqSegs[cSegs].pvSeg = &respHdr;
    910     aReqSegs[cSegs++].cbSeg = sizeof(respHdr);
    911     if (respHdr->cbSense)
    912     {
    913         aReqSegs[cSegs].pvSeg = pbSense;
    914         aReqSegs[cSegs++].cbSeg = respHdr->cbSense;
    915     }
     878    aReqSegs[0].cbSeg = sizeof(respHdr);
     879    aReqSegs[0].pvSeg = respHdr;
     880    aReqSegs[1].cbSeg = pThis->virtioScsiConfig.uSenseSize;
     881    aReqSegs[1].pvSeg = abSenseBuf;
     882
     883    if (pbSense && respHdr->uSenseLen)
     884        memcpy(abSenseBuf, pbSense, respHdr->uSenseLen);
     885    else
     886        respHdr->uSenseLen = 0;
     887
    916888    RTSGBUF reqSegBuf;
    917     RTSgBufInit(&reqSegBuf, aReqSegs, cSegs);
     889    RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
     890
    918891    virtioQueuePut(pThis->hVirtio, qIdx, &reqSegBuf, true /* fFence */);
    919892    virtioQueueSync(pThis->hVirtio, qIdx);
     893
     894    RTMemFree(abSenseBuf);
     895
    920896    LogFunc(("Response code: %s\n", virtioGetReqRespText(respHdr->uResponse)));
     897
    921898    Log(("---------------------------------------------------------------------------------\n"));
     899
    922900    return VINF_SUCCESS;
    923901}
     
    925903static int virtioScsiReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PRTSGBUF pInSgBuf, PRTSGBUF pOutSgBuf)
    926904{
    927     RT_NOREF(pInSgBuf);
    928     RT_NOREF(qIdx);
    929 
    930     AssertMsgReturn(pOutSgBuf->cSegs, ("Req. has no OUT data, unexpected/TBD\n"), VERR_NOT_IMPLEMENTED);
    931 
    932     size_t cbOut     = RTSgBufCalcTotalLength(pOutSgBuf);
    933     size_t cbIn      = RTSgBufCalcTotalLength(pInSgBuf);
    934     size_t cbCdb     = pThis->virtioScsiConfig.uCdbSize;
    935     size_t cbSense   = pThis->virtioScsiConfig.uSenseSize;
    936     size_t cbCmdHdr  = sizeof(REQ_CMD_HDR);
    937     size_t cbRespHdr = sizeof(REQ_RESP_HDR);
    938 
    939 
    940     AssertMsgReturn(cbOut >= RT_SIZEOFMEMB(VIRTIOSCSI_REQ_CMD_T, cmdHdr), ("Req to short"), VERR_BUFFER_UNDERFLOW);
    941 
    942     /** Actual CDB bytes didn't fill negotiated space allocated for it, adjust size */
    943     if (cbOut <= cbCmdHdr)
    944         cbCdb -= (cbCmdHdr - cbOut);
    945 
    946     PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)RTMemAllocZ(cbOut);
    947     off_t  cbOff = 0;
    948     size_t cbSeg = 0, cbLeft = cbOut;
    949     while (cbLeft)
    950     {
    951         RTGCPHYS pvSeg = (RTGCPHYS)RTSgBufGetNextSegment(pOutSgBuf, &cbSeg);
    952         PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), pvSeg, pVirtqReq + cbOff, cbSeg);
    953         cbLeft -= cbSeg;
     905    AssertMsgReturn(pOutSgBuf->cSegs, ("Req. has no OUT data, unexpected/TBD\n"), VERR_INVALID_PARAMETER);
     906
     907    size_t cbOut = RTSgBufCalcTotalLength(pOutSgBuf);
     908    size_t cbIn  = RTSgBufCalcTotalLength(pInSgBuf);
     909
     910    AssertMsgReturn(cbOut >= sizeof(REQ_CMD_HDR) + pThis->virtioScsiConfig.uCdbSize,
     911                        ("Req too short"), VERR_BUFFER_UNDERFLOW);
     912
     913    PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)RTMemAlloc(cbOut);
     914    AssertReturn(pVirtqReq, VERR_NO_MEMORY);
     915
     916Log(("cbOut = %d\n", cbOut));
     917uint32_t seg = 0;
     918    off_t cbOff = 0;
     919    size_t cbCopy = cbOut;
     920    while (cbCopy)
     921    {
     922        size_t cbSeg = cbCopy;
     923        RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pOutSgBuf, &cbSeg);
     924Log(("seg:%03d, GCPhys:%p, virtAddr:%p, cbSeg:%6d, cbOff:%6d, cbCopy:%d\n",
     925         seg++, GCPhys,     pVirtqReq + cbOff, cbSeg, cbOff, cbCopy));
     926        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pVirtqReq + cbOff, cbSeg);
     927        cbCopy -= cbSeg;
    954928        cbOff += cbSeg;
    955929    }
    956930
    957     uint8_t *pbCdb = pVirtqReq->uCdb;
    958 
    959     uint8_t  uTarget = pVirtqReq->cmdHdr.uLUN[1];
    960     uint32_t uLUN = (pVirtqReq->cmdHdr.uLUN[2] << 8 | pVirtqReq->cmdHdr.uLUN[3]) & 0x3fff;
     931    uint8_t  uTarget =  pVirtqReq->cmdHdr.uLUN[1];
     932    uint32_t uLUN    = (pVirtqReq->cmdHdr.uLUN[2] << 8 | pVirtqReq->cmdHdr.uLUN[3]) & 0x3fff;
    961933
    962934    LogFunc(("[%s] (Target: %d LUN: %d)  CDB: %.*Rhxs\n",
    963          SCSICmdText(pbCdb[0]), uTarget, uLUN,
    964             virtioScsiEstimateCdbLen(pbCdb[0], pThis->virtioScsiConfig.uCdbSize), pbCdb));
     935        SCSICmdText(pVirtqReq->uCdb[0]), uTarget, uLUN,
     936        virtioScsiEstimateCdbLen(pVirtqReq->uCdb[0], pThis->virtioScsiConfig.uCdbSize), pVirtqReq->uCdb));
    965937
    966938    Log3Func(("   id: %RX64, attr: %x, prio: %d, crn: %x\n",
    967939        pVirtqReq->cmdHdr.uId, pVirtqReq->cmdHdr.uTaskAttr, pVirtqReq->cmdHdr.uPrio, pVirtqReq->cmdHdr.uCrn));
    968940
    969     off_t    uPiOutOff = 0;
    970     size_t   cbPiHdr = 0;
    971     size_t   cbPiIn  = 0;
    972     size_t   cbPiOut = 0;
    973     uint8_t *pbPiOut = NULL;
     941    /**
     942     * Calculate request offsets
     943     */
     944    size_t  cbPiIn = 0, cbPiOut = 0, cbPiHdr = 0;
     945    off_t   piOutOff = 0;
    974946
    975947    if (pThis->fHasT10pi)
    976948    {
    977         cbPiOut   = pVirtqReq->piHdr.uPiBytesOut;
    978         cbPiIn    = pVirtqReq->piHdr.uPiBytesIn;
    979         uPiOutOff = cbCmdHdr + cbCdb + cbPiHdr;
    980         pbPiOut   = (uint8_t *)((uint64_t)pVirtqReq + uPiOutOff);
    981         cbPiHdr   = sizeof(REQ_CMD_PI);
    982     }
    983 
    984     off_t uDataOutOff = cbCmdHdr + cbCdb + cbPiHdr + cbPiOut;
    985 
    986     /** Next line works because the OUT s/g buffer doesn't hold writable (e.g. IN) part(s) of req */
    987     size_t cbDataOut = cbOut - uDataOutOff;
    988 
     949        cbPiIn   = pVirtqReq->piHdr.uPiBytesOut;
     950        cbPiOut  = pVirtqReq->piHdr.uPiBytesIn;
     951        cbPiHdr  = sizeof(REQ_CMD_PI) + cbPiOut;
     952        piOutOff = sizeof(REQ_CMD_HDR) + pThis->virtioScsiConfig.uCdbSize + sizeof(REQ_CMD_PI);
     953    }
     954
     955    off_t   uDataOutOff = sizeof(REQ_CMD_HDR)  + pThis->virtioScsiConfig.uCdbSize + cbPiHdr;
     956    off_t   uDataInOff  = sizeof(REQ_RESP_HDR) + pThis->virtioScsiConfig.uSenseSize + cbPiIn;
    989957    uint8_t *pbDataOut = (uint8_t *)((uint64_t)pVirtqReq + uDataOutOff);
    990 
    991     if (cbDataOut)
    992         virtioScsiHexDump(pVirtqReq->uDataOut, cbDataOut, 0, "\ndataout");
    993 
    994 
    995     if (cbPiOut)
    996         virtioScsiHexDump(pVirtqReq->uPiOut, cbPiOut, 0, "\nPi out");
     958    size_t  cbDataOut = cbOut - uDataOutOff;
     959    size_t  cbDataIn  = cbIn  - uDataInOff;
     960
     961    if (uTarget >= pThis->cTargets || uLUN != 0)
     962    {
     963        uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED,
     964                              0, SCSI_SENSE_ILLEGAL_REQUEST,
     965                              0, 0, 0, 0, 10, SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED, 0, 0 };
     966        struct REQ_RESP_HDR respHdr = { 0 };
     967        respHdr.uSenseLen = sizeof(abSense);
     968        respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
     969        respHdr.uResponse = (uTarget > pThis->cTargets) ? VIRTIOSCSI_S_BAD_TARGET : VIRTIOSCSI_S_OK;
     970        respHdr.uResidual = cbDataOut + cbDataIn;
     971        virtioScsiReqFinish(pThis, qIdx, &respHdr, abSense);
     972        return VINF_SUCCESS;
     973    }
     974
     975    PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[uTarget];
     976
     977    if (RT_UNLIKELY(!pTarget->fPresent))
     978    {
     979        Log2Func(("Error submitting request, target not present!!\n"));
     980        uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED,
     981                              0, SCSI_SENSE_NOT_READY, 0, 0, 0, 0, 10, 0, 0, 0 };
     982        struct REQ_RESP_HDR respHdr = { 0 };
     983        respHdr.uSenseLen = sizeof(abSense);
     984        respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
     985        respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE;
     986        respHdr.uResidual = cbDataIn + cbDataOut;
     987        virtioScsiReqFinish(pThis, qIdx, &respHdr, abSense);
     988        RTMemFree(pVirtqReq);
     989        return VINF_SUCCESS;
     990    }
    997991
    998992    PDMMEDIAEXIOREQ   hIoReq = NULL;
    999993    PVIRTIOSCSIREQ    pReq;
    1000     PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[uTarget];
    1001994    PPDMIMEDIAEX      pIMediaEx = pTarget->pDrvMediaEx;
    1002995
    1003     size_t cbDataIn  = cbIn - (cbRespHdr + cbSense + cbPiIn);
    1004 
    1005     if (uTarget >= pThis->cTargets)
    1006     {
    1007         struct REQ_RESP_HDR respHdr;
    1008         respHdr.cbSense = 0;
    1009         respHdr.uResidual = cbDataOut + cbDataIn;
    1010         respHdr.uStatus = SCSI_STATUS_OK;
    1011         respHdr.uResponse = VIRTIOSCSI_S_BAD_TARGET;
    1012         respHdr.uStatusQualifier = 0;
    1013         virtioScsiReqFinish(pThis, qIdx, &respHdr, NULL /* pbSense */);
    1014         return VINF_SUCCESS;
    1015     }
    1016 
    1017     struct REQ_RESP_HDR respHdr = { 0 };
    1018     if (uLUN != 0)
     996    int rc = pIMediaEx->pfnIoReqAlloc(pIMediaEx, &hIoReq, (void **)&pReq, 0 /* uIoReqId */,
     997                                  PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
     998
     999    AssertMsgRCReturn(rc, ("Failed to allocate I/O request, rc=%Rrc\n", rc), rc);
     1000
     1001    if (pThis->fHasT10pi)
     1002    {
     1003        pReq->cbPiOut   = cbPiOut;
     1004        pReq->pbPiOut   = (uint8_t *)((uint64_t)pVirtqReq + piOutOff);
     1005        pReq->cbPiIn    = cbPiIn;
     1006        pReq->pbPiIn    = (uint8_t *)RTMemAllocZ(cbPiIn);
     1007        AssertMsgReturn(pReq->pbPiIn, ("Out of memory allocating pi_in buffer"),  VERR_NO_MEMORY);
     1008    }
     1009
     1010    pReq->hIoReq    = hIoReq;
     1011    pReq->pTarget   = pTarget;
     1012    pReq->qIdx      = qIdx;
     1013    pReq->pbDataOut = pbDataOut;
     1014    pReq->pVirtqReq = pVirtqReq;
     1015    pReq->pInSgBuf  = pInSgBuf;
     1016    pReq->cbSense   = pThis->virtioScsiConfig.uSenseSize;
     1017    pReq->pbSense   = (uint8_t *)RTMemAllocZ(pReq->cbSense);
     1018    AssertMsgReturn(pReq->pbSense,  ("Out of memory allocating sense buffer"),  VERR_NO_MEMORY);
     1019
     1020    if (cbDataIn)
     1021    {
     1022        pReq->cbDataIn  = cbDataIn;
     1023        pReq->pbDataIn  = (uint8_t *)RTMemAllocZ(cbDataIn);
     1024        AssertMsgReturn(pReq->pbDataIn, ("Out of memory allocating datain buffer"), VERR_NO_MEMORY);
     1025    }
     1026
     1027    ASMAtomicIncU32(&pTarget->cReqsInProgress);
     1028
     1029    rc = pIMediaEx->pfnIoReqSendScsiCmd(pIMediaEx, pReq->hIoReq, uLUN,
     1030                                        pVirtqReq->uCdb, pThis->virtioScsiConfig.uCdbSize,
     1031                                        PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, cbDataIn,
     1032                                        pReq->pbSense, pReq->cbSense,
     1033                                        &pReq->uStatus, 30 * RT_MS_1SEC);
     1034
     1035    if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
    10191036    {
    10201037        /**
    1021          * This is needed for the time being to respond with the right error condition and sense data
    1022          * at the right time.  It doesn't work to send requests to bad luns down to DrvSCSI. It returs
    1023          * success for the INQUIRY commands and then starts failing future requests with BAD PARAM errors.
    1024          * Unfortunately that's too late for Linux. If it doesn't get the bad lun error at inquiry it
    1025          * seems to mishandle the error on future requests and will create 8 devices for the target and
    1026          * it gets ugly. */
    1027 
    1028         uint8_t pbSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED, 0, SCSI_SENSE_ILLEGAL_REQUEST,
    1029                               0, 0, 0, 0, 10, SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED, 0, 0 };
    1030         respHdr.cbSense = sizeof(pbSense);
     1038         * This rc value from DrvSCSI/send SCSI cmd means the request failed early
     1039         * (no mem, buf copy callback, request buffer creation, or req enqueue),
     1040         * and not submitted to lower layers, error it out.
     1041         */
     1042        Log2Func(("Error submitting request!\n"));
     1043        size_t cbResidual;
     1044        pIMediaEx->pfnIoReqQueryResidual(pIMediaEx, pReq->hIoReq, &cbResidual);
     1045        uint8_t uASC, uASCQ = 0;
     1046        switch (rc)
     1047        {
     1048            case VERR_NO_MEMORY:
     1049                uASC = SCSI_ASC_SYSTEM_RESOURCE_FAILURE;
     1050                break;
     1051            default:
     1052                uASC = SCSI_ASC_INTERNAL_TARGET_FAILURE;
     1053                break;
     1054        }
     1055        uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED,
     1056                              0, SCSI_SENSE_VENDOR_SPECIFIC,
     1057                              0, 0, 0, 0, 10, uASC, uASCQ, 0 };
     1058        struct REQ_RESP_HDR respHdr = { 0 };
     1059        respHdr.uSenseLen = sizeof(abSense);
     1060        respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
     1061        respHdr.uResponse = VIRTIOSCSI_S_FAILURE;
    10311062        respHdr.uResidual = cbDataIn + cbDataOut;
    1032         respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
    1033         respHdr.uResponse = VIRTIOSCSI_S_OK;
    1034         respHdr.uStatusQualifier = 0;
    1035         virtioScsiReqFinish(pThis, qIdx, &respHdr, pbSense);
     1063        virtioScsiReqFinish(pThis, qIdx, &respHdr, abSense);
     1064        RTMemFree(pReq->pbSense);
     1065        RTMemFree(pReq->pbDataIn);
     1066        RTMemFree(pReq->pbPiIn);
    10361067        RTMemFree(pVirtqReq);
    1037         return VINF_SUCCESS;
    1038     }
    1039 
    1040     if (RT_LIKELY(pTarget->fPresent))
    1041     {
    1042         int rc = pIMediaEx->pfnIoReqAlloc(pIMediaEx, &hIoReq, (void **)&pReq, 0 /* uIoReqId */,
    1043                                       PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
    1044 
    1045         AssertMsgRCReturn(rc, ("Failed to allocate I/O request, rc=%Rrc\n", rc), rc);
    1046 
    1047         ASMAtomicIncU32(&pTarget->cReqsInProgress);
    1048 
    1049         pReq->hIoReq    = hIoReq;
    1050         pReq->pTarget   = pTarget;
    1051         pReq->qIdx      = qIdx;
    1052         pReq->cbPiOut   = cbPiOut;
    1053         pReq->pbPiOut   = pbPiOut;
    1054         pReq->pbDataOut = pbDataOut;
    1055         pReq->cbPiIn    = cbPiIn;
    1056         pReq->pVirtqReq = pVirtqReq;
    1057 
    1058         if (cbPiIn)
    1059         {
    1060             pReq->pbPiIn = (uint8_t *)RTMemAllocZ(cbPiIn);
    1061             AssertMsgReturn(pReq->pbPiIn, ("Out of memory allocating pi_in buffer"),  VERR_NO_MEMORY);
    1062         }
    1063 
    1064         if (cbDataIn)
    1065         {
    1066             pReq->cbDataIn  = cbDataIn;
    1067             pReq->pbDataIn  = (uint8_t *)RTMemAllocZ(cbDataIn);
    1068             AssertMsgReturn(pReq->pbDataIn, ("Out of memory allocating datain buffer"), VERR_NO_MEMORY);
    1069         }
    1070 
    1071         if (cbSense)
    1072         {
    1073             pReq->cbSense   = cbSense;
    1074             pReq->pbSense   = (uint8_t *)RTMemAllocZ(cbSense);
    1075             pReq->pInSgBuf   = pInSgBuf;
    1076             AssertMsgReturn(pReq->pbSense,  ("Out of memory allocating sense buffer"),  VERR_NO_MEMORY);
    1077         }
    1078 
    1079         Log3Func(("Submitting req on %s\n", uTarget, uLUN, QUEUENAME(qIdx)));
    1080 
    1081         rc = pIMediaEx->pfnIoReqSendScsiCmd(pIMediaEx, pReq->hIoReq, uLUN, pbCdb, cbCdb,
    1082                                             PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, cbDataIn, pReq->pbSense, cbSense,
    1083                                             &pReq->uStatus, 30 * RT_MS_1SEC);
    1084 
    1085         if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
    1086         {
    1087             /**
    1088              * This rc value from DrvSCSI/send SCSI cmd means the request failed early
    1089              * (no mem, buf copy callback, request buffer creation, or req enqueue),
    1090              * and not submitted to lower layers, error it out.
    1091              */
    1092             LogRel(("Error submitting request!\n"));
    1093             size_t cbResidual;
    1094             pIMediaEx->pfnIoReqQueryResidual(pIMediaEx, pReq->hIoReq, &cbResidual);
    1095             uint8_t uASC, uASCQ = 0;
    1096             switch (rc)
    1097             {
    1098                 case VERR_NO_MEMORY:
    1099                     uASC = SCSI_ASC_SYSTEM_RESOURCE_FAILURE;
    1100                     break;
    1101                 default:
    1102                     uASC = SCSI_ASC_INTERNAL_TARGET_FAILURE;
    1103                     break;
    1104             }
    1105             uint8_t pbSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED, 0, SCSI_SENSE_VENDOR_SPECIFIC,
    1106                                   0, 0, 0, 0, 10, uASC, uASCQ, 0 };
    1107             respHdr.cbSense   = sizeof(pbSense);
    1108             respHdr.uResidual = cbDataIn + cbDataOut;
    1109             respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
    1110             respHdr.uResponse = VIRTIOSCSI_S_FAILURE;
    1111             respHdr.uStatusQualifier = 0;
    1112             virtioScsiReqFinish(pThis, qIdx, &respHdr,  NULL /* pbSense */);
    1113             RTMemFree(pVirtqReq);
    1114             RTMemFree(pReq->pbSense);
    1115             RTMemFree(pReq->pbDataIn);
    1116             RTMemFree(pReq->pbPiIn);
    1117             pIMediaEx->pfnIoReqFree(pIMediaEx, pReq->hIoReq);
    1118             return VINF_SUCCESS;
    1119         }
    1120     } else {
    1121         LogRel(("Error submitting request, target not present!!\n"));
    1122         uint8_t pbSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED, 0, SCSI_SENSE_NOT_READY,
    1123                               0, 0, 0, 0, 10, 0, 0, 0 };
    1124         respHdr.cbSense   = sizeof(pbSense);
    1125         respHdr.uResidual = cbDataIn + cbDataOut;
    1126         respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
    1127         respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE;
    1128         respHdr.uStatusQualifier = 0;
    1129         virtioScsiReqFinish(pThis, qIdx, &respHdr,  NULL /* pbSense */);
     1068        pIMediaEx->pfnIoReqFree(pIMediaEx, pReq->hIoReq);
    11301069        return VINF_SUCCESS;
    11311070    }
     
    16031542    if (fVirtioReady)
    16041543    {
    1605         LogFunc(("VirtIO ready\n---------------------------------------------------------------------------------\n"));
     1544        LogFunc(("VirtIO ready\n-----------------------------------------------------------------------------------------\n"));
    16061545        uint64_t features = virtioGetNegotiatedFeatures(hVirtio);
    16071546        pThis->fHasT10pi     = features & VIRTIO_SCSI_F_T10_PI;
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r80528 r80571  
    196196    pDescChain->cSegsIn = pDescChain->cSegsOut = 0;
    197197
    198 
    199198    pDescChain->uHeadIdx = virtioReadAvailDescIdx(pVirtio, qIdx, pVirtqProxy->uAvailIdx);
    200199    uint16_t uDescIdx = pDescChain->uHeadIdx;
     
    206205        pVirtqProxy->uAvailIdx++;
    207206
     207    uint32_t cbIn = 0, cbOut = 0;
    208208    VIRTQ_DESC_T desc;
    209209    do
     
    212212
    213213        /**
    214         * Malicious or inept guests may go beyond aSegsIn or aSegsOut boundaries by linking
     214        * Malicious guests may go beyond aSegsIn or aSegsOut boundaries by linking
    215215        * several descriptors into a loop. Since there is no legitimate way to get a sequences of
    216216        * linked descriptors exceeding the total number of descriptors in the ring (see @bugref{8620}),
     
    240240            Log3Func(("%s IN  desc_idx=%u seg=%u addr=%RGp cb=%u\n",
    241241                QUEUENAME(qIdx), uDescIdx, pDescChain->cSegsIn, desc.pGcPhysBuf, desc.cb));
    242 
     242            cbIn += desc.cb;
    243243            pSeg = &(pDescChain->aSegsIn[pDescChain->cSegsIn++]);
    244244        }
     
    247247            Log3Func(("%s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n",
    248248                QUEUENAME(qIdx), uDescIdx, pDescChain->cSegsOut, desc.pGcPhysBuf, desc.cb));
     249            cbOut += desc.cb;
    249250            pSeg = &(pDescChain->aSegsOut[pDescChain->cSegsOut++]);
    250251        }
     
    256257    } while (desc.fFlags & VIRTQ_DESC_F_NEXT);
    257258
    258     RTSgBufInit(&pVirtqProxy->inSgBuf, (PCRTSGSEG)&pDescChain->aSegsIn,  pDescChain->cSegsIn);
    259     RTSgBufInit(&pVirtqProxy->outSgBuf,(PCRTSGSEG)&pDescChain->aSegsOut, pDescChain->cSegsOut);
     259    RTSgBufInit(&pVirtqProxy->inSgBuf,  (PCRTSGSEG)&pDescChain->aSegsIn,  pDescChain->cSegsIn);
     260    RTSgBufInit(&pVirtqProxy->outSgBuf, (PCRTSGSEG)&pDescChain->aSegsOut, pDescChain->cSegsOut);
    260261
    261262    if (ppInSegs)
    262263        *ppInSegs  = &pVirtqProxy->inSgBuf;
     264
    263265    if (ppOutSegs)
    264266        *ppOutSegs = &pVirtqProxy->outSgBuf;
    265267
    266     Log3Func(("%s -- segs out: %u,  segs in: %u --\n",
    267               pVirtqProxy->szVirtqName, pDescChain->cSegsOut, pDescChain->cSegsIn));
     268    Log3Func(("%s -- segs OUT: %u (%u bytes)   IN: %u (%u bytes) --\n",
     269              pVirtqProxy->szVirtqName, pDescChain->cSegsOut, cbOut, pDescChain->cSegsIn, cbIn));
    268270
    269271    return VINF_SUCCESS;
     
    289291
    290292    size_t cbRemain = RTSgBufCalcTotalLength(pBufSrc);
    291     uint16_t uUsedIdx  = virtioReadUsedRingIdx(pVirtio, qIdx);
     293    uint16_t uUsedIdx = virtioReadUsedRingIdx(pVirtio, qIdx);
    292294    Log3Func(("Copying client data to %s, desc chain (head desc_idx %d)\n",
    293295               QUEUENAME(qIdx), uUsedIdx));
     
    309311        RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
    310312
    311     /** TBD to avoid wasting cycles how do we wrap this in test for Log2* enabled? */
    312     size_t   cbInSgBuf = RTSgBufCalcTotalLength(pBufDst);
    313     size_t   cbWritten = cbInSgBuf  - RTSgBufCalcLengthLeft(pBufDst);
    314 
    315 
    316313    /** If this write-ahead crosses threshold where the driver wants to get an event flag it */
    317314    if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX)
     
    326323                        pDescChain->uHeadIdx,
    327324                        pDescChain->cSegsIn);
    328     Log3Func(("Copied %u bytes to %u byte buffer\n                Write ahead used_idx=%d, %s used_idx=%d\n",
    329              cbWritten, cbInSgBuf, pVirtqProxy->uUsedIdx,  QUEUENAME(qIdx), uUsedIdx));
     325
     326    if (LogIs2Enabled())
     327    {
     328        size_t cbInSgBuf = RTSgBufCalcTotalLength(pBufDst);
     329        size_t cbWritten = cbInSgBuf - RTSgBufCalcLengthLeft(pBufDst);
     330        Log2Func(("Copied %u bytes to %u byte buffer, residual=%d\n",
     331             cbWritten, cbInSgBuf, cbInSgBuf - cbWritten));
     332    }
     333    Log3Func(("Write ahead used_idx=%d, %s used_idx=%d\n",
     334         pVirtqProxy->uUsedIdx,  QUEUENAME(qIdx), uUsedIdx));
     335
    330336    return VINF_SUCCESS;
    331337}
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