Changeset 80571 in vbox
- Timestamp:
- Sep 4, 2019 12:06:41 AM (5 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r80539 r80571 179 179 struct REQ_RESP_HDR 180 180 { 181 uint32_t cbSense;/**< sense_len */181 uint32_t uSenseLen; /**< sense_len */ 182 182 uint32_t uResidual; /**< residual */ 183 183 uint16_t uStatusQualifier; /**< status_qualifier */ … … 488 488 out[0] = 0x01; out[1] = target; out[2] = (lun >> 8) & 0x40; out[3] = lun & 0xff; *((uint16_t *)out + 4) = 0; 489 489 490 /**491 * Do a hex dump of a buffer492 * @param pv Pointer to array to dump493 * @param cb Number of characters to dump494 * @param uBase Base address of offset addresses displayed495 * @param pszTitle Header line/title for the dump496 *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 }512 490 513 491 DECLINLINE(const char *) virtioGetTMFTypeText(uint32_t uSubType) … … 699 677 700 678 /** 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));703 679 memcpy(pReq->pbDataIn + offDst, pSgBuf->paSegs[0].pvSeg, cbCopy); 704 680 return VINF_SUCCESS; … … 805 781 AssertRC(rc); 806 782 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; 815 786 respHdr.uResidual = cbResidual; 816 787 respHdr.uStatus = pReq->uStatus; 817 788 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()) 827 799 { 828 800 Log2Func(("Sense: %s\n", SCSISenseText(pReq->pbSense[2]))); 829 801 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 } 833 822 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; 861 826 } 862 827 RTSGBUF reqSegBuf; … … 880 845 virtioQueueSync(pThis->hVirtio, pReq->qIdx); 881 846 882 RTMemFree(pReq->pVirtqReq); 847 Log(("-----------------------------------------------------------------------------------------\n")); 848 883 849 RTMemFree(pReq->pbSense); 884 850 RTMemFree(pReq->pbDataIn); 885 851 RTMemFree(pReq->pbPiIn); 852 RTMemFree(pReq->pVirtqReq); 886 853 887 854 pIMediaEx->pfnIoReqFree(pIMediaEx, pReq->hIoReq); … … 905 872 static int virtioScsiReqFinish(PVIRTIOSCSI pThis, uint16_t qIdx, struct REQ_RESP_HDR *respHdr, uint8_t *pbSense) 906 873 { 907 int cSegs = 0; 874 uint8_t *abSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize); 875 AssertReturn(abSenseBuf, VERR_NO_MEMORY); 876 908 877 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 916 888 RTSGBUF reqSegBuf; 917 RTSgBufInit(&reqSegBuf, aReqSegs, cSegs); 889 RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs)); 890 918 891 virtioQueuePut(pThis->hVirtio, qIdx, &reqSegBuf, true /* fFence */); 919 892 virtioQueueSync(pThis->hVirtio, qIdx); 893 894 RTMemFree(abSenseBuf); 895 920 896 LogFunc(("Response code: %s\n", virtioGetReqRespText(respHdr->uResponse))); 897 921 898 Log(("---------------------------------------------------------------------------------\n")); 899 922 900 return VINF_SUCCESS; 923 901 } … … 925 903 static int virtioScsiReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PRTSGBUF pInSgBuf, PRTSGBUF pOutSgBuf) 926 904 { 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 916 Log(("cbOut = %d\n", cbOut)); 917 uint32_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); 924 Log(("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; 954 928 cbOff += cbSeg; 955 929 } 956 930 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; 961 933 962 934 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)); 965 937 966 938 Log3Func((" id: %RX64, attr: %x, prio: %d, crn: %x\n", 967 939 pVirtqReq->cmdHdr.uId, pVirtqReq->cmdHdr.uTaskAttr, pVirtqReq->cmdHdr.uPrio, pVirtqReq->cmdHdr.uCrn)); 968 940 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; 974 946 975 947 if (pThis->fHasT10pi) 976 948 { 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; 989 957 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 } 997 991 998 992 PDMMEDIAEXIOREQ hIoReq = NULL; 999 993 PVIRTIOSCSIREQ pReq; 1000 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[uTarget];1001 994 PPDMIMEDIAEX pIMediaEx = pTarget->pDrvMediaEx; 1002 995 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) 1019 1036 { 1020 1037 /** 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; 1031 1062 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); 1036 1067 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); 1130 1069 return VINF_SUCCESS; 1131 1070 } … … 1603 1542 if (fVirtioReady) 1604 1543 { 1605 LogFunc(("VirtIO ready\n--------------------------------------------------------------------------------- \n"));1544 LogFunc(("VirtIO ready\n-----------------------------------------------------------------------------------------\n")); 1606 1545 uint64_t features = virtioGetNegotiatedFeatures(hVirtio); 1607 1546 pThis->fHasT10pi = features & VIRTIO_SCSI_F_T10_PI; -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r80528 r80571 196 196 pDescChain->cSegsIn = pDescChain->cSegsOut = 0; 197 197 198 199 198 pDescChain->uHeadIdx = virtioReadAvailDescIdx(pVirtio, qIdx, pVirtqProxy->uAvailIdx); 200 199 uint16_t uDescIdx = pDescChain->uHeadIdx; … … 206 205 pVirtqProxy->uAvailIdx++; 207 206 207 uint32_t cbIn = 0, cbOut = 0; 208 208 VIRTQ_DESC_T desc; 209 209 do … … 212 212 213 213 /** 214 * Malicious or ineptguests may go beyond aSegsIn or aSegsOut boundaries by linking214 * Malicious guests may go beyond aSegsIn or aSegsOut boundaries by linking 215 215 * several descriptors into a loop. Since there is no legitimate way to get a sequences of 216 216 * linked descriptors exceeding the total number of descriptors in the ring (see @bugref{8620}), … … 240 240 Log3Func(("%s IN desc_idx=%u seg=%u addr=%RGp cb=%u\n", 241 241 QUEUENAME(qIdx), uDescIdx, pDescChain->cSegsIn, desc.pGcPhysBuf, desc.cb)); 242 242 cbIn += desc.cb; 243 243 pSeg = &(pDescChain->aSegsIn[pDescChain->cSegsIn++]); 244 244 } … … 247 247 Log3Func(("%s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n", 248 248 QUEUENAME(qIdx), uDescIdx, pDescChain->cSegsOut, desc.pGcPhysBuf, desc.cb)); 249 cbOut += desc.cb; 249 250 pSeg = &(pDescChain->aSegsOut[pDescChain->cSegsOut++]); 250 251 } … … 256 257 } while (desc.fFlags & VIRTQ_DESC_F_NEXT); 257 258 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); 260 261 261 262 if (ppInSegs) 262 263 *ppInSegs = &pVirtqProxy->inSgBuf; 264 263 265 if (ppOutSegs) 264 266 *ppOutSegs = &pVirtqProxy->outSgBuf; 265 267 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)); 268 270 269 271 return VINF_SUCCESS; … … 289 291 290 292 size_t cbRemain = RTSgBufCalcTotalLength(pBufSrc); 291 uint16_t uUsedIdx 293 uint16_t uUsedIdx = virtioReadUsedRingIdx(pVirtio, qIdx); 292 294 Log3Func(("Copying client data to %s, desc chain (head desc_idx %d)\n", 293 295 QUEUENAME(qIdx), uUsedIdx)); … … 309 311 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); 310 312 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 316 313 /** If this write-ahead crosses threshold where the driver wants to get an event flag it */ 317 314 if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX) … … 326 323 pDescChain->uHeadIdx, 327 324 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 330 336 return VINF_SUCCESS; 331 337 }
Note:
See TracChangeset
for help on using the changeset viewer.