Changeset 80596 in vbox
- Timestamp:
- Sep 5, 2019 7:12:46 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
-
include/VBox/scsi.h (modified) (1 diff)
-
src/VBox/Devices/Storage/DevVirtioSCSI.cpp (modified) (27 diffs)
-
src/VBox/Devices/VirtIO/Virtio_1_0.cpp (modified) (19 diffs)
-
src/VBox/Devices/VirtIO/Virtio_1_0.h (modified) (2 diffs)
-
src/VBox/Devices/VirtIO/Virtio_1_0_impl.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/scsi.h
r80539 r80596 238 238 #define SCSI_ASCQ_UNKNOWN_FORMAT 0x01 239 239 #define SCSI_ASCQ_INCOMPATIBLE_FORMAT 0x02 240 #define SCSI_ASCQ_COPY_TARGET_DEVICE_DATA_OVERRUN 0x0d 240 241 241 242 /** @name SCSI_INQUIRY -
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r80589 r80596 106 106 #define CBQUEUENAME(qIdx) RTStrNLen(QUEUENAME(qIdx), sizeof(QUEUENAME(qIdx))) 107 107 108 108 109 #define IS_REQ_QUEUE(qIdx) (qIdx >= VIRTQ_REQ_BASE && qIdx < VIRTIOSCSI_QUEUE_CNT) 109 110 /** … … 463 464 /** 464 465 * Request structure for IMediaEx (Associated Interfaces implemented by DrvSCSI) 466 * (NOTE: cbIn, cbOUt, cbDataOut mostly for debugging) 465 467 */ 466 468 typedef struct VIRTIOSCSIREQ … … 469 471 PVIRTIOSCSITARGET pTarget; /**< Target */ 470 472 uint16_t qIdx; /**< Index of queue this request arrived on */ 473 size_t cbIn; /**< Size of input descriptor chain */ 474 size_t cbOut; /**< Size of output descriptor chain */ 471 475 size_t cbPiOut; /**< Size of T10 pi in buffer */ 472 476 uint8_t *pbPiOut; /**< Address of pi out buffer */ 473 477 uint8_t *pbDataOut; /**< dataout */ 478 size_t cbDataOut; /**< size of dataout buffer */ 474 479 size_t cbPiIn; /**< Size of T10 pi buffer */ 475 480 uint8_t *pbPiIn; /**< Address of pi in buffer */ … … 477 482 uint8_t *pbDataIn; /**< datain */ 478 483 size_t cbSense; /**< Size of sense buffer */ 484 size_t uSenseLen; /**< Receives # bytes written into sense buffer */ 479 485 uint8_t *pbSense; /**< Pointer to R3 sense buffer */ 486 PDMMEDIAEXIOREQSCSITXDIR enmTxDir; /**< Receives transfer direction of I/O req */ 480 487 uint8_t uStatus; /**< SCSI status code */ 481 488 PRTSGBUF pInSgBuf; /**< Buf vector to return PDM result to VirtIO Guest */ … … 487 494 #define SET_LUN_BUF(target, lun, out) \ 488 495 out[0] = 0x01; out[1] = target; out[2] = (lun >> 8) & 0x40; out[3] = lun & 0xff; *((uint16_t *)out + 4) = 0; 496 497 498 DECLINLINE(bool) isBufZero(uint8_t *pv, size_t cb) 499 { 500 for (uint32_t i = 0; i < cb; i++) 501 if (pv[i]) 502 return false; 503 return true; 504 } 505 506 DECLINLINE(const char *) virtioGetTxDirText(uint32_t enmTxDir) 507 { 508 switch (enmTxDir) 509 { 510 case PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN: return "<UNKNOWN>"; 511 case PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE: return "<DEV-TO-GUEST>"; 512 case PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE: return "<GUEST-TO-DEV>"; 513 case PDMMEDIAEXIOREQSCSITXDIR_NONE: return "<NONE>"; 514 default: return "<BAD ENUM>"; 515 } 516 } 489 517 490 518 … … 610 638 } 611 639 612 640 #define VIRTIO_IN_DIRECTION(pMediaExTxDirEnumValue) \ 641 pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE 642 643 #define VIRTIO_OUT_DIRECTION(pMediaExTxDirEnumValue) \ 644 pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE 613 645 614 646 typedef struct VIRTIOSCSIREQ *PVIRTIOSCSIREQ; … … 765 797 766 798 return VINF_SUCCESS; 767 768 } 799 } 800 801 /** 802 * This is called to complete a request immediately 803 * 804 * @param pThis - PDM driver instance state 805 * @param qIdx - Queue index 806 * @param pRespHdr - Response header 807 * @param pbSense - Pointer to sense buffer or NULL if none. 808 * 809 * @returns virtual box status code 810 */ 811 static int virtioScsiReqErr(PVIRTIOSCSI pThis, uint16_t qIdx, struct REQ_RESP_HDR *pRespHdr, uint8_t *pbSense) 812 { 813 uint8_t *abSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize); 814 AssertReturn(abSenseBuf, VERR_NO_MEMORY); 815 816 Log2Func((" status: %s response: %s\n", 817 SCSIStatusText(pRespHdr->uStatus), virtioGetReqRespText(pRespHdr->uResponse))); 818 819 RTSGSEG aReqSegs[2]; 820 aReqSegs[0].cbSeg = sizeof(pRespHdr); 821 aReqSegs[0].pvSeg = pRespHdr; 822 aReqSegs[1].cbSeg = pThis->virtioScsiConfig.uSenseSize; 823 aReqSegs[1].pvSeg = abSenseBuf; 824 825 if (pbSense && pRespHdr->uSenseLen) 826 memcpy(abSenseBuf, pbSense, pRespHdr->uSenseLen); 827 else 828 pRespHdr->uSenseLen = 0; 829 830 RTSGBUF reqSegBuf; 831 RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs)); 832 833 virtioQueuePut(pThis->hVirtio, qIdx, &reqSegBuf, true /* fFence */); 834 virtioQueueSync(pThis->hVirtio, qIdx); 835 836 RTMemFree(abSenseBuf); 837 838 Log(("---------------------------------------------------------------------------------\n")); 839 840 return VINF_SUCCESS; 841 } 842 769 843 /** TBD: VirtIO 1.0 spec 5.6.6.1.1 requires some request actions on reset that are 770 844 * not implemented. Specifically either canceling outstanding I/O or … … 795 869 #define SHOULD_FIX_VSCSI_TO_RETURN_SENSE_LEN 32 796 870 struct REQ_RESP_HDR respHdr = { 0 }; 797 respHdr.uSenseLen = pReq-> uStatus == SCSI_STATUS_CHECK_CONDITION ? SHOULD_FIX_VSCSI_TO_RETURN_SENSE_LEN : 0;871 respHdr.uSenseLen = pReq->pbSense[2] == SCSI_SENSE_NONE ? 0 : pReq->uSenseLen; 798 872 respHdr.uResidual = cbResidual; 799 873 respHdr.uStatus = pReq->uStatus; … … 810 884 break; 811 885 } 812 /* fallthrough */813 case SCSI_STATUS_BUSY:814 respHdr.uResponse = VIRTIOSCSI_S_BUSY;815 break;816 case SCSI_STATUS_DATA_UNDEROVER_RUN:817 respHdr.uResponse = VIRTIOSCSI_S_OVERRUN;818 break;819 case SCSI_STATUS_TASK_ABORTED:820 respHdr.uResponse = VIRTIOSCSI_S_ABORTED;821 break;822 886 case SCSI_STATUS_CHECK_CONDITION: 823 887 { … … 838 902 break; 839 903 case SCSI_SENSE_NOT_READY: 840 respHdr.uResponse = VIRTIOSCSI_S_BUSY; /* e.g. try again*/904 respHdr.uResponse = VIRTIOSCSI_S_BUSY; /* e.g. re-tryable */ 841 905 break; 842 906 default: … … 852 916 } 853 917 854 Log2Func(("status: %s, response: (%x) %s\n",855 SCSIStatusText(pReq->uStatus), respHdr.uResponse, virtioGetReqRespText(respHdr.uResponse)));918 Log2Func(("status: (%d) %s, response: (%d) %s\n", 919 pReq->uStatus, SCSIStatusText(pReq->uStatus), respHdr.uResponse, virtioGetReqRespText(respHdr.uResponse))); 856 920 857 921 if (RT_FAILURE(rcReq)) 858 922 Log2Func(("rcReq: %s\n", RTErrGetDefine(rcReq))); 859 923 860 Log3Func(("status:%02x/resp:%02x, xfer=%d, residual: %u, sense (len=%d, alloc=%d)\n", 861 pReq->uStatus, respHdr.uResponse, cbXfer, cbResidual, 862 respHdr.uSenseLen, pThis->virtioScsiConfig.uSenseSize)); 924 if (LogIs3Enabled()) 925 { 926 LogFunc(("cbDataIn = %u, cbDataOut = %u (cbIn = %u, cbOut = %u)\n", 927 pReq->cbDataIn, pReq->cbDataOut, pReq->cbIn, pReq->cbOut)); 928 LogFunc(("xfer = %d, residual = %u\n", cbXfer, cbResidual)); 929 LogFunc(("xfer direction: %s, sense written = %d, sense size = %d\n", 930 virtioGetTxDirText(pReq->enmTxDir), respHdr.uSenseLen, pThis->virtioScsiConfig.uSenseSize)); 931 } 863 932 864 933 if (respHdr.uSenseLen && LogIs2Enabled()) 865 934 { 866 Log2Func(("Sense: %s\n", SCSISenseText(pReq->pbSense[2]))); 867 Log2Func(("Sense Ext3: %s\n", SCSISenseExtText(pReq->pbSense[12], pReq->pbSense[13]))); 935 LogFunc(("Sense: %s\n", SCSISenseText(pReq->pbSense[2]))); 936 LogFunc(("Sense Ext3: %s\n", SCSISenseExtText(pReq->pbSense[12], pReq->pbSense[13]))); 937 } 938 939 if (LogIsItEnabled(RTLOGGRPFLAGS_LEVEL_12, LOG_GROUP)) 940 { 941 size_t cb = RT_MIN(cbXfer, 256); 942 if (VIRTIO_IN_DIRECTION(pReq->enmTxDir)) 943 { 944 Log(("datain[256 of %d total bytes xferred]:\n", cbXfer)); 945 if (!isBufZero(pReq->pbDataIn, cb)) 946 VIRTIO_HEX_DUMP(RTLOGGRPFLAGS_LEVEL_12, pReq->pbDataIn, cb, 0, 0); 947 else 948 Log12(("-- %d zeroes --\n", cb)); 949 } 950 else 951 if (VIRTIO_OUT_DIRECTION(pReq->enmTxDir)) 952 { 953 Log(("dataout[256 of %d total bytes xferred]:\n", cbXfer)); 954 if (!isBufZero(pReq->pbDataOut, cb)) 955 VIRTIO_HEX_DUMP(RTLOGGRPFLAGS_LEVEL_12, pReq->pbDataOut, cb, 0, 0); 956 else 957 Log12(("-- %d zeroes --\n", cb)); 958 } 868 959 } 869 960 870 961 int cSegs = 0; 871 962 872 873 // Assert(pReq->cbDataIn >= cbXfer); 874 Assert(pReq->pbSense != NULL); 875 876 RTSGSEG aReqSegs[4]; 877 aReqSegs[cSegs].pvSeg = &respHdr; 878 aReqSegs[cSegs++].cbSeg = sizeof(respHdr); 879 880 aReqSegs[cSegs].pvSeg = pReq->pbSense; 881 aReqSegs[cSegs++].cbSeg = pReq->cbSense; /* VirtIO 1.0 spec 5.6.4/5.6.6.1 */ 882 883 if (pReq->cbPiIn) 884 { 885 aReqSegs[cSegs].pvSeg = pReq->pbPiIn; 886 aReqSegs[cSegs++].cbSeg = pReq->cbPiIn; 887 } 888 if (pReq->cbDataIn) 889 { 890 aReqSegs[cSegs].pvSeg = pReq->pbDataIn; 891 aReqSegs[cSegs++].cbSeg = cbXfer; 892 } 893 RTSGBUF reqSegBuf; 894 RTSgBufInit(&reqSegBuf, aReqSegs, cSegs); 895 896 /** 897 * Fill in the request queue current descriptor chain's IN queue entry/entries 898 * (phys. memory) with the Req response data in virtual memory. 899 */ 900 size_t cbReqSgBuf = RTSgBufCalcTotalLength(&reqSegBuf); 901 size_t cbInSgBuf = RTSgBufCalcTotalLength(pReq->pInSgBuf); 902 AssertMsgReturn(cbReqSgBuf <= cbInSgBuf, 903 ("Guest expected less req data (space needed: %d, avail: %d)\n", cbReqSgBuf, cbInSgBuf), 904 VERR_BUFFER_OVERFLOW); 905 906 /** 907 * Following doesn't put up memory barrier (fence). 908 * VirtIO 1.0 Spec requires mem. barrier for ctrl cmds 909 * but doesn't mention fences in regard to requests. */ 910 virtioQueuePut(pThis->hVirtio, pReq->qIdx, &reqSegBuf, true /* fFence TBD */); 911 virtioQueueSync(pThis->hVirtio, pReq->qIdx); 912 913 Log(("-----------------------------------------------------------------------------------------\n")); 914 963 if ( (VIRTIO_IN_DIRECTION(pReq->enmTxDir) && cbXfer > pReq->cbDataIn) 964 || (VIRTIO_OUT_DIRECTION(pReq->enmTxDir) && cbXfer > pReq->cbDataOut)) 965 { 966 /** TBD try to figure out optimal sense info to send back besides response of VIRTIOSCSI_S_OVERRUN */ 967 Log2Func((" * * * * Data overrun, returning sense\n")); 968 uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED, 969 0, SCSI_SENSE_ILLEGAL_REQUEST, 0, 0, 0, 0, 10, 0, 0, 0 }; 970 respHdr.uSenseLen = sizeof(abSense); 971 respHdr.uStatus = SCSI_STATUS_CHECK_CONDITION; 972 respHdr.uResponse = VIRTIOSCSI_S_OVERRUN; 973 respHdr.uResidual = pReq->cbDataIn; 974 virtioScsiReqErr(pThis, pReq->qIdx, &respHdr, abSense); 975 } 976 else 977 { 978 Assert(pReq->pbSense != NULL); 979 980 RTSGSEG aReqSegs[4]; 981 aReqSegs[cSegs].pvSeg = &respHdr; 982 aReqSegs[cSegs++].cbSeg = sizeof(respHdr); 983 984 aReqSegs[cSegs].pvSeg = pReq->pbSense; 985 aReqSegs[cSegs++].cbSeg = pReq->cbSense; /* VirtIO 1.0 spec 5.6.4/5.6.6.1 */ 986 987 if (pReq->cbPiIn) 988 { 989 aReqSegs[cSegs].pvSeg = pReq->pbPiIn; 990 aReqSegs[cSegs++].cbSeg = pReq->cbPiIn; 991 } 992 if (pReq->cbDataIn) 993 { 994 aReqSegs[cSegs].pvSeg = pReq->pbDataIn; 995 aReqSegs[cSegs++].cbSeg = cbXfer; 996 } 997 RTSGBUF reqSegBuf; 998 RTSgBufInit(&reqSegBuf, aReqSegs, cSegs); 999 1000 /** 1001 * Fill in the request queue current descriptor chain's IN queue entry/entries 1002 * (phys. memory) with the Req response data in virtual memory. 1003 */ 1004 size_t cbReqSgBuf = RTSgBufCalcTotalLength(&reqSegBuf); 1005 size_t cbInSgBuf = RTSgBufCalcTotalLength(pReq->pInSgBuf); 1006 AssertMsgReturn(cbReqSgBuf <= cbInSgBuf, 1007 ("Guest expected less req data (space needed: %d, avail: %d)\n", cbReqSgBuf, cbInSgBuf), 1008 VERR_BUFFER_OVERFLOW); 1009 1010 virtioQueuePut(pThis->hVirtio, pReq->qIdx, &reqSegBuf, true /* fFence TBD */); 1011 virtioQueueSync(pThis->hVirtio, pReq->qIdx); 1012 1013 Log(("-----------------------------------------------------------------------------------------\n")); 1014 1015 } 915 1016 RTMemFree(pReq->pbSense); 916 1017 RTMemFree(pReq->pbDataIn); … … 926 1027 } 927 1028 928 /**929 * This is called to complete a request immediately930 *931 * @param pThis - PDM driver instance state932 * @param qIdx - Queue index933 * @param pRespHdr - Response header934 * @param pbSense - Pointer to sense buffer or NULL if none.935 *936 * @returns virtual box status code937 */938 static int virtioScsiReqFinish(PVIRTIOSCSI pThis, uint16_t qIdx, struct REQ_RESP_HDR *pRespHdr, uint8_t *pbSense)939 {940 uint8_t *abSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize);941 AssertReturn(abSenseBuf, VERR_NO_MEMORY);942 943 Log2Func(("status: %s response: %s\n",944 SCSIStatusText(pRespHdr->uStatus), virtioGetReqRespText(pRespHdr->uResponse)));945 946 RTSGSEG aReqSegs[2];947 aReqSegs[0].cbSeg = sizeof(pRespHdr);948 aReqSegs[0].pvSeg = pRespHdr;949 aReqSegs[1].cbSeg = pThis->virtioScsiConfig.uSenseSize;950 aReqSegs[1].pvSeg = abSenseBuf;951 952 if (pbSense && pRespHdr->uSenseLen)953 memcpy(abSenseBuf, pbSense, pRespHdr->uSenseLen);954 else955 pRespHdr->uSenseLen = 0;956 957 RTSGBUF reqSegBuf;958 RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));959 960 virtioQueuePut(pThis->hVirtio, qIdx, &reqSegBuf, true /* fFence */);961 virtioQueueSync(pThis->hVirtio, qIdx);962 963 RTMemFree(abSenseBuf);964 965 Log(("---------------------------------------------------------------------------------\n"));966 967 return VINF_SUCCESS;968 }969 970 1029 static int virtioScsiReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PRTSGBUF pInSgBuf, PRTSGBUF pOutSgBuf) 971 1030 { … … 975 1034 size_t cbIn = RTSgBufCalcTotalLength(pInSgBuf); 976 1035 977 AssertMsgReturn(cbOut >= sizeof(REQ_CMD_HDR) + pThis->virtioScsiConfig.uCdbSize, 978 ("Req too short"), VERR_BUFFER_UNDERFLOW); 979 980 PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)RTMemAlloc(cbOut); 1036 /** MAKE THIS NON-ZERO MALLOCING AFTER DEBUG */ 1037 PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)RTMemAllocZ(cbOut); 981 1038 AssertReturn(pVirtqReq, VERR_NO_MEMORY); 982 1039 … … 992 1049 } 993 1050 1051 // VIRTIO_HEX_DUMP(RTLOGGRPFLAGS_LEVEL_12, (uint8_t *)pVirtqReq, cbOut, 0, "\npVirtqReq"); 1052 994 1053 uint8_t uTarget = pVirtqReq->cmdHdr.uLUN[1]; 995 1054 uint32_t uLUN = (pVirtqReq->cmdHdr.uLUN[2] << 8 | pVirtqReq->cmdHdr.uLUN[3]) & 0x3fff; … … 997 1056 LogFunc(("[%s] (Target: %d LUN: %d) CDB: %.*Rhxs\n", 998 1057 SCSICmdText(pVirtqReq->uCdb[0]), uTarget, uLUN, 999 virtioScsiEstimateCdbLen(pVirtqReq->uCdb[0], pThis->virtioScsiConfig.uCdbSize), pVirtqReq->uCdb)); 1000 1001 Log3Func((" id: %RX64, attr: %x, prio: %d, crn: %x\n", 1058 virtioScsiEstimateCdbLen(pVirtqReq->uCdb[0], 1059 pThis->virtioScsiConfig.uCdbSize), pVirtqReq->uCdb)); 1060 1061 Log3Func(("id: %RX64, attr: %x, prio: %d, crn: %x\n", 1002 1062 pVirtqReq->cmdHdr.uId, pVirtqReq->cmdHdr.uTaskAttr, pVirtqReq->cmdHdr.uPrio, pVirtqReq->cmdHdr.uCrn)); 1003 1063 … … 1016 1076 } 1017 1077 1018 off_t uDataOutOff = sizeof(REQ_CMD_HDR) + pThis->virtioScsiConfig.uCdbSize + cbPiHdr;1078 off_t uDataOutOff = sizeof(REQ_CMD_HDR) + pThis->virtioScsiConfig.uCdbSize + cbPiHdr; 1019 1079 off_t uDataInOff = sizeof(REQ_RESP_HDR) + pThis->virtioScsiConfig.uSenseSize + cbPiIn; 1020 1080 uint8_t *pbDataOut = (uint8_t *)((uint64_t)pVirtqReq + uDataOutOff); … … 1032 1092 respHdr.uResponse = (uTarget > pThis->cTargets) ? VIRTIOSCSI_S_BAD_TARGET : VIRTIOSCSI_S_OK; 1033 1093 respHdr.uResidual = cbDataOut + cbDataIn; 1034 virtioScsiReq Finish(pThis, qIdx, &respHdr, abSense);1094 virtioScsiReqErr(pThis, qIdx, &respHdr, abSense); 1035 1095 return VINF_SUCCESS; 1036 1096 } … … 1048 1108 respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE; 1049 1109 respHdr.uResidual = cbDataIn + cbDataOut; 1050 virtioScsiReq Finish(pThis, qIdx, &respHdr, abSense);1110 virtioScsiReqErr(pThis, qIdx, &respHdr, abSense); 1051 1111 RTMemFree(pVirtqReq); 1052 1112 return VINF_SUCCESS; … … 1074 1134 pReq->pTarget = pTarget; 1075 1135 pReq->qIdx = qIdx; 1136 pReq->cbIn = cbIn; 1137 pReq->cbOut = cbOut; 1076 1138 pReq->pbDataOut = pbDataOut; 1139 pReq->cbDataOut = cbDataOut; 1077 1140 pReq->pVirtqReq = pVirtqReq; 1078 1141 pReq->pInSgBuf = pInSgBuf; … … 1092 1155 rc = pIMediaEx->pfnIoReqSendScsiCmd(pIMediaEx, pReq->hIoReq, uLUN, 1093 1156 pVirtqReq->uCdb, pThis->virtioScsiConfig.uCdbSize, 1094 PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, NULL, cbDataIn,1095 pReq->pbSense, pReq->cbSense, NULL,1157 PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, &pReq->enmTxDir, cbDataIn, 1158 pReq->pbSense, pReq->cbSense, &pReq->uSenseLen, 1096 1159 &pReq->uStatus, 30 * RT_MS_1SEC); 1097 1160 … … 1124 1187 respHdr.uResponse = VIRTIOSCSI_S_FAILURE; 1125 1188 respHdr.uResidual = cbDataIn + cbDataOut; 1126 virtioScsiReq Finish(pThis, qIdx, &respHdr, abSense);1189 virtioScsiReqErr(pThis, qIdx, &respHdr, abSense); 1127 1190 RTMemFree(pReq->pbSense); 1128 1191 RTMemFree(pReq->pbDataIn); … … 1336 1399 if (!fNotificationSent) 1337 1400 { 1338 Log 3Func(("%s worker sleeping...\n", QUEUENAME(qIdx)));1401 Log6Func(("%s worker sleeping...\n", QUEUENAME(qIdx))); 1339 1402 Assert(ASMAtomicReadBool(&pWorker->fSleeping)); 1340 1403 rc = SUPSemEventWaitNoResume(pThis->pSupDrvSession, pWorker->hEvtProcess, RT_INDEFINITE_WAIT); … … 1342 1405 if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING)) 1343 1406 break; 1344 Log 3Func(("%s worker woken\n", QUEUENAME(qIdx)));1407 Log6Func(("%s worker woken\n", QUEUENAME(qIdx))); 1345 1408 ASMAtomicWriteBool(&pWorker->fNotified, false); 1346 1409 } 1347 1410 ASMAtomicWriteBool(&pWorker->fSleeping, false); 1348 1411 } 1349 Log 3Func(("fetching next descriptor chain from %s\n", QUEUENAME(qIdx)));1412 Log6Func(("fetching next descriptor chain from %s\n", QUEUENAME(qIdx))); 1350 1413 rc = virtioQueueGet(pThis->hVirtio, qIdx, true, &pInSgBuf, &pOutSgBuf); 1351 1414 if (rc == VERR_NOT_AVAILABLE) … … 1576 1639 if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx)) 1577 1640 { 1578 Log 3Func(("%s has available data\n", QUEUENAME(qIdx)));1641 Log6Func(("%s has available data\n", QUEUENAME(qIdx))); 1579 1642 /** Wake queue's worker thread up if sleeping */ 1580 1643 if (!ASMAtomicXchgBool(&pWorker->fNotified, true)) … … 1582 1645 if (ASMAtomicReadBool(&pWorker->fSleeping)) 1583 1646 { 1584 Log 3Func(("waking %s worker.\n", QUEUENAME(qIdx)));1647 Log6Func(("waking %s worker.\n", QUEUENAME(qIdx))); 1585 1648 int rc = SUPSemEventSignal(pThis->pSupDrvSession, pWorker->hEvtProcess); 1586 1649 AssertRC(rc); … … 2145 2208 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: failed to initialize VirtIO")); 2146 2209 2147 2148 2210 RTStrCopy((char *)pThis->szQueueNames[CONTROLQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq"); 2149 2211 RTStrCopy((char *)pThis->szQueueNames[EVENTQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "eventq"); … … 2152 2214 "requestq<%d>", qIdx - VIRTQ_REQ_BASE); 2153 2215 2154 /**2155 * Create one worker per incoming-work-related queue (eventq is outgoing status to guest,2156 * wherein guest is supposed to keep the queue loaded-up with buffer vectors the host2157 * can quickly fill-in send back). Should be light-duty and fast enough to be handled on2158 * requestq or controlq thread. The Linux virtio_scsi driver limits the number of request2159 * queues to MIN(<# Guest CPUs>, <Device's req queue max>), so queue count is ultimately2160 * constrained from host side at negotiation time and initialization and later through2161 * bounds-checking.2162 */2163 2216 for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++) 2164 2217 { -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r80575 r80596 81 81 if (pszDepiction[i] == ' ' && first++) 82 82 pszDepiction[i] = '.'; 83 Log 3Func(("%s: Guest %s %s 0x%s\n",83 Log6Func(("%s: Guest %s %s 0x%s\n", 84 84 pszFunc, fWrite ? "wrote" : "read ", pszDepiction, pszFormattedVal)); 85 85 } 86 86 else /* odd number or oversized access, ... log inline hex-dump style */ 87 87 { 88 Log 3Func(("%s: Guest %s %s%s[%d:%d]: %.*Rhxs\n",88 Log6Func(("%s: Guest %s %s%s[%d:%d]: %.*Rhxs\n", 89 89 pszFunc, fWrite ? "wrote" : "read ", pszMember, 90 90 pszIdx, uOffset, uOffset + cb, cb, pv)); … … 199 199 uint16_t uDescIdx = pDescChain->uHeadIdx; 200 200 201 Log 3Func(("%s DESC CHAIN: (head) desc_idx=%u [avail_idx=%u]\n",201 Log6Func(("%s DESC CHAIN: (head) desc_idx=%u [avail_idx=%u]\n", 202 202 pVirtqProxy->szVirtqName, pDescChain->uHeadIdx, pVirtqProxy->uAvailIdx)); 203 203 … … 238 238 if (desc.fFlags & VIRTQ_DESC_F_WRITE) 239 239 { 240 Log 3Func(("%s IN desc_idx=%u seg=%u addr=%RGp cb=%u\n",240 Log6Func(("%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; … … 245 245 else 246 246 { 247 Log 3Func(("%s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n",247 Log6Func(("%s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n", 248 248 QUEUENAME(qIdx), uDescIdx, pDescChain->cSegsOut, desc.pGcPhysBuf, desc.cb)); 249 249 cbOut += desc.cb; … … 261 261 262 262 if (ppInSegs) 263 *ppInSegs = &pVirtqProxy->inSgBuf;263 *ppInSegs = &pVirtqProxy->inSgBuf; 264 264 265 265 if (ppOutSegs) 266 266 *ppOutSegs = &pVirtqProxy->outSgBuf; 267 267 268 Log 3Func(("%s -- segs OUT: %u (%u bytes) IN: %u (%u bytes) --\n",268 Log6Func(("%s -- segs OUT: %u (%u bytes) IN: %u (%u bytes) --\n", 269 269 pVirtqProxy->szVirtqName, pDescChain->cSegsOut, cbOut, pDescChain->cSegsIn, cbIn)); 270 270 … … 292 292 size_t cbRemain = RTSgBufCalcTotalLength(pBufSrc); 293 293 uint16_t uUsedIdx = virtioReadUsedRingIdx(pVirtio, qIdx); 294 Log 3Func(("Copying client data to %s, desc chain (head desc_idx %d)\n",294 Log6Func(("Copying client data to %s, desc chain (head desc_idx %d)\n", 295 295 QUEUENAME(qIdx), uUsedIdx)); 296 296 … … 328 328 size_t cbInSgBuf = RTSgBufCalcTotalLength(pBufDst); 329 329 size_t cbWritten = cbInSgBuf - RTSgBufCalcLengthLeft(pBufDst); 330 Log2Func((" Copied %u bytes to %u byte buffer, residual=%d\n",330 Log2Func((".... Copied %u bytes to %u byte buffer, residual=%d\n", 331 331 cbWritten, cbInSgBuf, cbInSgBuf - cbWritten)); 332 332 } 333 Log 3Func(("Write ahead used_idx=%d, %s used_idx=%d\n",333 Log6Func(("Write ahead used_idx=%d, %s used_idx=%d\n", 334 334 pVirtqProxy->uUsedIdx, QUEUENAME(qIdx), uUsedIdx)); 335 335 … … 351 351 352 352 uint16_t uIdx = virtioReadUsedRingIdx(pVirtio, qIdx); 353 Log 3Func(("Updating %s used_idx from %u to %u\n",353 Log6Func(("Updating %s used_idx from %u to %u\n", 354 354 QUEUENAME(qIdx), uIdx, pVirtqProxy->uUsedIdx)); 355 355 … … 368 368 369 369 PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx]; 370 Log 3Func(("%s\n", pVirtqProxy->szVirtqName));370 Log6Func(("%s\n", pVirtqProxy->szVirtqName)); 371 371 372 372 … … 398 398 return; 399 399 } 400 Log 3Func(("...skipping interrupt: VIRTIO_F_EVENT_IDX set but threshold not reached\n"));400 Log6Func(("...skipping interrupt: VIRTIO_F_EVENT_IDX set but threshold not reached\n")); 401 401 } 402 402 else … … 408 408 return; 409 409 } 410 Log 3Func(("...skipping interrupt. Guest flagged VIRTQ_AVAIL_F_NO_INTERRUPT for queue\n"));410 Log6Func(("...skipping interrupt. Guest flagged VIRTQ_AVAIL_F_NO_INTERRUPT for queue\n")); 411 411 412 412 } … … 456 456 { 457 457 if (uCause == VIRTIO_ISR_VIRTQ_INTERRUPT) 458 Log 3Func(("reason: buffer added to 'used' ring.\n"));458 Log6Func(("reason: buffer added to 'used' ring.\n")); 459 459 else 460 460 if (uCause == VIRTIO_ISR_DEVICE_CONFIG) 461 Log 3Func(("reason: device config change\n"));461 Log6Func(("reason: device config change\n")); 462 462 463 463 pVirtio->uISR |= uCause; … … 642 642 { 643 643 pVirtio->uDeviceStatus = *(uint8_t *)pv; 644 Log 3Func(("Guest wrote uDeviceStatus ................ ("));644 Log6Func(("Guest wrote uDeviceStatus ................ (")); 645 645 virtioLogDeviceStatus(pVirtio->uDeviceStatus); 646 Log 3((")\n"));646 Log6((")\n")); 647 647 if (pVirtio->uDeviceStatus == 0) 648 648 virtioGuestResetted(pVirtio); … … 659 659 else /* Guest READ pCommonCfg->uDeviceStatus */ 660 660 { 661 Log 3Func(("Guest read uDeviceStatus ................ ("));661 Log6Func(("Guest read uDeviceStatus ................ (")); 662 662 *(uint32_t *)pv = pVirtio->uDeviceStatus; 663 663 virtioLogDeviceStatus(pVirtio->uDeviceStatus); 664 Log 3((")\n"));664 Log6((")\n")); 665 665 } 666 666 } … … 764 764 { 765 765 ++pVirtio->uConfigGeneration; 766 Log 3Func(("Bumped cfg. generation to %d because %s%s\n",766 Log6Func(("Bumped cfg. generation to %d because %s%s\n", 767 767 pVirtio->uConfigGeneration, 768 768 fDevSpecificFieldChanged ? "<dev cfg changed> " : "", … … 781 781 { 782 782 *(uint8_t *)pv = pVirtio->uISR; 783 Log 3Func(("Read and clear ISR\n"));783 Log6Func(("Read and clear ISR\n")); 784 784 pVirtio->uISR = 0; /** VirtIO specification requires reads of ISR to clear it */ 785 785 virtioLowerInterrupt(pVirtio); … … 832 832 { 833 833 pVirtio->uISR = *(uint8_t *)pv; 834 Log 3Func(("Setting uISR = 0x%02x (virtq interrupt: %d, dev confg interrupt: %d)\n",834 Log6Func(("Setting uISR = 0x%02x (virtq interrupt: %d, dev confg interrupt: %d)\n", 835 835 pVirtio->uISR & 0xff, 836 836 pVirtio->uISR & VIRTIO_ISR_VIRTQ_INTERRUPT, … … 1045 1045 1046 1046 int rc = VINF_SUCCESS; 1047 1048 1047 1049 1048 PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)RTMemAllocZ(sizeof(VIRTIOSTATE)); … … 1463 1462 } 1464 1463 1464 /** 1465 * Do a hex dump of a buffer. 1466 * 1467 * @param pv Pointer to array to dump 1468 * @param cb Number of characters to dump 1469 * @param uBase Base address of offset addresses displayed 1470 * @param pszTitle Header line/title for the dump 1471 * 1472 */ 1473 void virtioHexDump(uint8_t *pv, size_t cb, uint32_t uBase, const char *pszTitle) 1474 { 1475 if (pszTitle) 1476 Log(("%s [%d bytes]:\n", pszTitle, cb)); 1477 for (uint32_t row = 0; row < RT_MAX(1, (cb / 16) + 1); row++) 1478 { 1479 uint32_t uAddr = row * 16 + uBase; 1480 Log(("%x%x%x%x: ", (uAddr >> 12) & 0xf, (uAddr >> 8) & 0xf, (uAddr >> 4) & 0xf, uAddr & 0xf)); 1481 for (int col = 0; col < 16; col++) 1482 { 1483 uint32_t idx = row * 16 + col; 1484 uint8_t u8 = pv[idx]; 1485 if (idx >= cb) 1486 Log(("-- %s", (col + 1) % 8 ? "" : " ")); 1487 else 1488 Log(("%x%x %s", u8 >> 4 & 0xf, u8 & 0xf, (col + 1) % 8 ? "" : " ")); 1489 } 1490 for (int col = 0; col < 16; col++) 1491 { 1492 uint32_t idx = row * 16 + col; 1493 uint8_t u8 = pv[idx]; 1494 if (idx >= cb) 1495 Log((" ")); 1496 else 1497 Log(("%c", u8 >= 0x20 && u8 <= 0x7e ? u8 : '.')); 1498 } 1499 Log(("\n")); 1500 } 1501 Log(("\n")); 1502 } 1465 1503 1466 1504 #endif /* IN_RING3 */ -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h
r80522 r80596 41 41 #define VIRTIOSCSI_REGION_PORT_IO 1 /**< BAR for PORT I/O (impl specific) */ 42 42 #define VIRTIOSCSI_REGION_PCI_CAP 2 /**< BAR for VirtIO Cap. MMIO (impl specific) */ 43 44 #define VIRTIO_HEX_DUMP(logLevel, pv, cb, base, title) \ 45 do { \ 46 if (LogIsItEnabled(logLevel, LOG_GROUP)) \ 47 virtioHexDump((pv), (cb), (base), (title)); \ 48 } while (0) 43 49 44 50 /** … … 320 326 bool fWrite, bool fHasIndex, uint32_t idx); 321 327 328 /** 329 * Does a formatted hex dump using Log(()), recommend using VIRTIO_HEX_DUMP() macro to 330 * control enabling of logging efficiently. 331 * 332 * @param pv - pointer to buffer to dump contents of 333 * @param cb - count of characters to dump from buffer 334 * @param uBase - base address of per-row address prefixing of hex output 335 * @param pszTitle - Optional title. If present displays title that lists 336 * provided text with value of cb to indicate size next to it. 337 */ 338 void virtioHexDump(uint8_t *pv, size_t cb, uint32_t uBase, const char *pszTitle); 322 339 323 340 #endif /* !VBOX_INCLUDED_SRC_VirtIO_Virtio_1_0_h */ -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h
r80527 r80596 409 409 pVirtio->pGcPhysQueueAvail[qIdx] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx), 410 410 &uIdx, sizeof(uIdx)); 411 Log3Func(("%s actual avail_idx=%d\n", pVirtio->virtqProxy[qIdx].szVirtqName, uIdx));412 411 return uIdx; 413 412 } … … 512 511 { 513 512 if (status == 0) 514 Log 3(("RESET"));513 Log6(("RESET")); 515 514 else 516 515 { 517 516 int primed = 0; 518 517 if (status & VIRTIO_STATUS_ACKNOWLEDGE) 519 Log 3(("ACKNOWLEDGE", primed++));518 Log6(("ACKNOWLEDGE", primed++)); 520 519 if (status & VIRTIO_STATUS_DRIVER) 521 Log 3(("%sDRIVER", primed++ ? " | " : ""));520 Log6(("%sDRIVER", primed++ ? " | " : "")); 522 521 if (status & VIRTIO_STATUS_FEATURES_OK) 523 Log 3(("%sFEATURES_OK", primed++ ? " | " : ""));522 Log6(("%sFEATURES_OK", primed++ ? " | " : "")); 524 523 if (status & VIRTIO_STATUS_DRIVER_OK) 525 Log 3(("%sDRIVER_OK", primed++ ? " | " : ""));524 Log6(("%sDRIVER_OK", primed++ ? " | " : "")); 526 525 if (status & VIRTIO_STATUS_FAILED) 527 Log 3(("%sFAILED", primed++ ? " | " : ""));526 Log6(("%sFAILED", primed++ ? " | " : "")); 528 527 if (status & VIRTIO_STATUS_DEVICE_NEEDS_RESET) 529 Log 3(("%sNEEDS_RESET", primed++ ? " | " : ""));528 Log6(("%sNEEDS_RESET", primed++ ? " | " : "")); 530 529 } 531 530 }
Note:
See TracChangeset
for help on using the changeset viewer.

